Commit Graph

712 Commits

Author SHA1 Message Date
7f48b19f28 fix 2026-06-02 11:46:00 +03:00
1dec48079c fix(translate): prevent empty translations in _persist_pre + add diag logging
Bug 1 (secondary): _persist_pre() created TranslationLanguage with
empty final_value for non-source target languages when same_language
flag was set but no cache/approved value existed. This produced
is_original=0 rows with empty text in target table.

Fix: skip TranslationLanguage creation when fv is empty (continue
in the loop instead of falling through to else with empty string).

Bug 2 (diagnostic): No visibility into _classify() routing decisions.
Add logger.reason with pre/llm/total counts per batch.

Scenario trace: ru source + targets [ru,en] + no cache → llm_rows ✓
If same-language partial match hits cache for all targets → pre_rows ✓
If same-language partial match misses cache → llm_rows ✓
If same-language all-match (targets=[ru]) → short-circuit pre_rows ✓

Tests: 69/69 translate tests pass.
2026-06-02 11:44:41 +03:00
0b74946bd2 chore: fix trailing newline in .gitignore 2026-06-02 09:56:25 +03:00
a95f070441 feat(frontend): add DashboardHub components, EmptyState, and validation scaffold
- DashboardHubModel.svelte.ts: Screen Model for dashboard listing hub
  with filters, pagination, and selection state.
- DashboardRow.svelte: Individual dashboard card with Git/health badges.
- ColumnFilterPopover.svelte: Column-based filter dropdown for dashboards.
- dashboard-helpers.ts: Shared dashboard utility functions.
- EmptyState.svelte: Reusable empty state component with icon and CTA.
- validation route scaffold for per-dashboard validation views.
2026-06-02 09:56:25 +03:00
8219540ade feat(backend): add v2 LLM validation fields to health service
- DashboardHealthItem schema: add run_id, policy_id, execution_path,
  issues_count, timings, token_usage, screenshot_paths, chunk_count,
  dashboard_name fields for v2 LLM validation reporting.
- HealthService: populate v2 fields from validation run records.
- ValidationService: update to support v2 validation run fields.
- validation_tasks route: minor fix for v2 field handling.
- tailwind.config.js: refactor design tokens — add success/warning/info
  palettes, surface/border/text hierarchy, semantic action colors.
- Agent configs: update svelte-coder and semantics-svelte for
  .svelte.ts runes and Screen Model patterns.
2026-06-02 09:54:42 +03:00
4fc3356312 refactor(frontend): migrate Svelte stores from .ts to .svelte.ts runes
- Delete legacy .ts stores (auth, activity, assistantChat, datasetReview, environmentContext, health, sidebar, taskDrawer, translationRun)
- Create new .svelte.ts runes-based stores using  reactive primitives
- Migrate i18n: /i18n → /i18n/index.svelte.js
- Migrate toasts: /toasts → /toasts.svelte.js
- Update all component imports across 180+ files: components, pages, routes, lib
- Remove fromStore() wrappers — use store.value directly with Svelte 5 runes
- Update test mocks for new import paths
- Add @DEPRECATED annotation to legacy  alias
2026-06-02 09:54:18 +03:00
3214d8c659 fix(translate): same-language short-circuit blocked multi-language translation
Root cause: _classify() immediately skipped (continue) when detected
language matched ANY target language, preventing cache lookup and LLM
translation for remaining targets. E.g., ru source + targets [ru, en]
→ only ru row created, en never processed (8978 ru vs 18 en in DB).

Fix:
1. _classify(): Only short-circuit when ALL targets match detected
   language. Partial match → mark _same_language but continue to
   cache check and LLM for non-matching targets.
2. _persist_pre(): Unify two code paths into single loop over all
   target languages. Same-language targets use source_text as-is;
   cached targets use cache value; fallback to approved_translation.
3. SIM102: Merge nested 'if cl: if all(...)' → 'if cl and all(...)'
   to keep cyclomatic complexity ≤ 10 (INV_7).

QA: All 69 translate tests pass. 7 scenario traces (A-G) verified.
No regressions in approved_translation, preview edits, or single-
target same-language flows.
2026-06-02 09:52:32 +03:00
f16096cbcd fix(api): add missing fetchApiBlob to api export object
downloadSkippedCsv and downloadFailedCsv call api.fetchApiBlob()
but it was not exposed on the api object — causing
"o.fetchApiBlob is not a function" at runtime.
2026-06-01 23:30:19 +03:00
28b28338c5 fix(translate): исправление INSERT + выгрузка CSV для неуспешных запусков
**Исправления ошибок:**
- superset_executor: убран несуществующий fallback endpoint /api/v1/sql_lab/execute/
  (правильный URL /api/v1/sqllab/execute/ подтверждён браузерным запросом Superset)
  Ошибка 500 (permission denied) больше не маскируется 404
- orchestrator_run_completion: run.status=FAILED при провале insert
  (раньше всегда ставился COMPLETED). timeout тоже treated as failure
- test_orchestrator: assertion обновлён COMPLETED→FAILED

**Новая функция — выгрузка CSV:**
- GET /api/translate/runs/{run_id}/failed.csv — возвращает CSV с успешно
  переведёнными, но не вставленными записями (status=SUCCESS)
- Колонки: record_id, source_*, target_sql, source_data (JSON), языки, error_message
- Метаданные запуска (run_status, insert_status, run_error) в конце файла
- Кнопки скачивания в 3 местах фронта:
  - История запусков (при status=FAILED)
  - TranslationRunProgress (insert_failed)
  - TranslationRunResult (failed/partial/insert_failed)
- downloadFailedCsv() через fetchApiBlob + Blob URL
2026-06-01 22:38:52 +03:00
40e364d9f6 fix 2026-06-01 17:09:40 +03:00
4c5da7e4d9 alembic fix 2026-06-01 16:34:07 +03:00
e12a9ddfce fix(tests): fix all 3 remaining pre-existing test failures
All 651 tests pass, 71 test files, 0 failures.

Changes:
1. dashboard-profile-override (×2):
   - Mock call count race condition: getDashboards fires extra call on mount
   - Fix: use mockImplementation with override tracking instead of mockResolvedValueOnce
   - No more brittle call-count assertions

2. dataset_review_workspace:
   - goto mock not connected: /navigation mock created standalone vi.fn()
     instead of reusing hoisted mockedGoto
   - postApi resolved immediately, too fast for waitFor to catch 'importing'
   - Fix: deferred postApi promise + fixed goto mock reference
   - Also added missing import { goto } from '/navigation' in page component

3. Earlier fixes (from previous commit):
   - TargetSchemaHint: result.missing_columns → res?.missing_columns
   - CorrectionCell: border-blue-300 → border-blue-600
   - TranslationPreview: @UX_STATE: → @UX_STATE (no colon)

Attempts summary:
  - [ATTEMPT: 1] TS migration complete, 6 pre-existing failures
  - [ATTEMPT: 2] Fixed 3 stale assertions (border-blue, @UX_STATE, result. → res?.)
  - [ATTEMPT: 3] Fixed remaining 3 (mock race, goto connection, missing import)
2026-06-01 15:58:20 +03:00
6b4c3d45ee fix(tests): fix 3 stale test assertions — 6 fail → 3 fail
Fixed:
  - TargetSchemaHint: result.missing_columns → res?.missing_columns (component uses res?)
  - CorrectionCell: border-blue-300 → border-blue-600 (class changed)
  - TranslationPreview: @UX_STATE: → @UX_STATE (no colon per GRACE format)

3 remaining pre-existing failures (not from migration):
  - dashboard-profile-override (×2): vi.fn() mock call count race condition
  - dataset_review_workspace: waitFor timeout, unreachable DOM state

Before: 641 pass / 6 fail
After:  648 pass / 3 fail
2026-06-01 15:49:37 +03:00
52bea154b7 feat(ts-migration): final cleanup — 3 more files JS→TS
Deleted stale .js files (taskService, toolsService, report_page.contract.test)
7 .svelte.js test files intentionally preserved (Svelte 5 convention)

Final metrics:
  - Production JS files: 0
  - Production TS/TSX/Svelte files: all
  - npm run build 
  - npm run test  (645 passed, 6 pre-existing)
2026-06-01 15:44:52 +03:00
ed4562d199 feat(ts-migration): Phase 3-4 — all components + tests JS→TS
Converted 11 remaining production files:
  - services/*.ts (toolsService, taskService, git-utils, storageService,
    adminService, gitService)
  - lib/auth/permissions.ts
  - lib/components/layout/sidebarNavigation.ts
  - lib/components/reports/reportTypeProfiles.ts
  - components/git/useGitManager.ts
  - routes/datasets/review/useReviewSession.ts
  - routes/datasets/review/review-workspace-helpers.ts
  - routes/settings/settings-utils.ts

All production files have proper GRACE contracts:
  - C2/C3 with @BRIEF, @PRE, @POST, @SIDE_EFFECT, @RELATION
  - Generic <T = unknown> for API calls
  - Typed interfaces for state/options

Phase 3: 126 .svelte components → <script lang="ts">
Phase 4: 53 test .js files → .ts

Final verification:
  - npm run build 
  - npm run test  (66 passed, 6 pre-existing failures unchanged)

Total: 0 .js files remain in production code
2026-06-01 15:43:20 +03:00
03557d38cc feat(ts-migration): Phase 2.4 — all stores JS→TS with contracts
Converted 10 files:
  - stores.ts [C:3] — plugins, tasks, selection stores + fetchPlugins/fetchTasks
  - stores/health.ts [C:3] — health summary with polling dedup + derived failingCount
  - stores/activity.ts [C:2] — derived active task count for navbar badge
  - stores/sidebar.ts [C:3] — sidebar expansion, navigation, mobile overlay + localStorage persist
  - stores/taskDrawer.ts [C:3] — drawer open/close, resource-to-task mapping, auto-open pref
  - stores/environmentContext.ts [C:3] — environment selector, localStorage persist, derived env
  - stores/assistantChat.ts [C:3] — panel toggle, conversation binding, seed messages, focus target
  - stores/datasetReviewSession.ts [C:4] — session CRUD, dirty flag, UiPhase derivation
  - stores/translationRun.ts [C:4] — WebSocket + polling, uxState FSM, derived active/finished
  - stores/maintenance.svelte.ts [C:4] — Svelte 5 runes (), WS reconnect, CRUD

Build: npm run build passes
2026-06-01 15:24:10 +03:00
3ef06da8a2 feat(ts-migration): Phase 2.3 — all API satellite modules JS→TS with full contracts
Converted 12 files:
  - api/assistant.ts [C:3] — chat, conversations, history, confirm/cancel
  - api/reports.ts [C:3] — list/detail fetch with query builder
  - api/datasetReview.ts [C:3] — optimistic-lock, conflict detection, DTO normalization
  - api/maintenance.ts [C:3] — start/end events, settings, banners
  - api/translate.ts [C:2] — barrel re-export
  - api/translate/jobs.ts [C:2] — CRUD + duplicate
  - api/translate/runs.ts [C:2] — trigger, status, history, retry, cancel, metrics
  - api/translate/dictionaries.ts [C:3] — dictionary + entry CRUD, import
  - api/translate/datasources.ts [C:2] — columns, preview, approve/edit/reject rows
  - api/translate/corrections.ts [C:2] — inline edit, bulk replace, CSV download
  - api/translate/schedules.ts [C:2] — cron CRUD, enable/disable, next executions
  - api/translate/target-schema.ts [C:2] — schema validation with graceful error fallback

Each function:
  - Typed parameters + generic <T = unknown> return
  - @POST / @SIDE_EFFECT / @RELATION DEPENDS_ON chains
  - Normalized TranslateApiError pattern (message, code, retryable)
  - checkTargetTableSchema has @RATIONALE for graceful error handling

Build: npm run build passes cleanly
2026-06-01 15:21:41 +03:00
50f5c4ce4d feat(ts-migration): Phase 1 — core API layer JS→TS with full GRACE contracts
Converted:
  - toasts.js → toasts.ts (typed Writable<Toast[]>, typed addToast/removeToast)
  - api.js → api.ts (C5 module with 12 nested C2/C4 function contracts)
  - utils.js → utils.ts, utils/debounce.js → debounce.ts
  - Updated 67 import references across src/ (.js extension stripped)
  - Added types/api.ts, types/models.ts, types/validation.ts (foundation DTOs)

api.ts contracts:
  - Top-level: [C:5] with @INVARIANT, @DATA_CONTRACT, @RATIONALE, @REJECTED
  - C4 functions: buildApiError, notifyApiError, shouldSuppressApiErrorToast
  - C2 helpers: getWsUrl, getTaskEventsWsUrl, getMaintenanceEventsWsUrl,
    getTranslateRunWsUrl, getAuthHeaders
  - C4 fetch/request wrappers: fetchApi, fetchApiBlob, postApi, deleteApi, requestApi
  - C3 endpoint registry: api.* methods with @RELATION DEPENDS_ON chains
  - All C4 functions have @PRE/@POST/@SIDE_EFFECT
  - all generic <T = unknown> for type-safe API responses

Build: npm run build passes cleanly
2026-06-01 15:11:35 +03:00
b4b0deb856 js - ts + fix 2026-06-01 14:40:17 +03:00
1a7f368324 fix(llm): handle null LLM content and skip retry on null/model errors
When Kilo gateway + Nvidia NeMo :free model returns content: null
for image inputs, get_json_completion crashed with
'the JSON object must be str, bytes or bytearray, not NoneType'
and retried 5 times (unnecessary).

Fixes:
- _should_retry no longer retries RuntimeError with 'null content'
  (retrying won't help — the model genuinely returned null)
- get_json_completion now raises RuntimeError explicitly when
  content is None, with a clear message (instead of json.loads(None))
2026-06-01 10:17:41 +03:00
9b2d96786d fix(validation): populate screenshot_paths column + backfill from raw_response
Two bugs preventing screenshot display in report UI:

1. Plugin's ValidationRecord constructor did NOT include
   screenshot_paths (plural, JSON array). The column stayed NULL
   even though paths were stored in raw_response. Records created
   by the plugin now include screenshot_paths=webp_paths|jpeg_paths.

2. Backward compat for existing records: _record_to_dict now
   falls back to extracting screenshot_paths from raw_response JSON
   when the DB column is empty.

Also fixes: broken import statement in validation_service.py
(missing closing paren + missing imports from earlier edit).
2026-06-01 09:05:24 +03:00
79d8d5f7bb fix(ui): normalize screenshot field names in run detail load function
API returns 'screenshot_paths' but frontend template reads 'screenshots'.
Without field mapping, screenshots are never displayed.

Fix: map screenshot_paths -> screenshots and logs_sent_to_llm -> logs_sent
in the +page.js load function.

Also verifies that /api/storage/file endpoint exists (mounted at /api/storage)
and the frontend API_BASE_URL='/api' correctly prefixes /storage/file.
2026-06-01 08:44:28 +03:00
f388961b9f fix(ui): prevent duplicate key error in issues table
Svelte each block key used , but when
two issues share the same message text (e.g. 'Main content area
is completely blank') and have no id, the key collides.

Fix: use composite key
as fallback when issue.id is missing.
2026-06-01 08:33:05 +03:00
4376354aec fix(llm): disable json_object mode for :free models on any gateway
The _supports_json_response_format check only looked for
'openrouter.ai' in base_url, missing the Kilo gateway
('api.kilo.ai'). Free-tier models routed through ANY gateway
(Nvidia NeMo :free via OpenRouter OR Kilo) reject json_object
response format, causing the LLM to return content: null.

Error: 'the JSON object must be str, bytes or bytearray, not NoneType'

Fix: check model name for ':free' and 'stepfun/' directly,
regardless of gateway. This covers OpenRouter, Kilo, and any
future gateway.
2026-06-01 08:27:14 +03:00
1b89f5fd28 chore: update qa-tester agent model to mimo-v2.5-pro 2026-06-01 08:23:45 +03:00
83e6181bf5 fix(validation): fallback chunk size when max_images=0 or None
When max_images could not be detected (e.g. Kilo gateway doesn't
support OpenAI image format, probe returned 0), chunking was
disabled entirely and all screenshots sent in a single request.
Nvidia NeMo still enforces an 8-image limit regardless of the
gateway, causing 400 errors.

Fix: default to 8 images per chunk when max_images is 0 or None,
so chunking always applies for multi-tab dashboards.
2026-05-31 23:10:16 +03:00
ab90755fa1 fix(validation): process all dashboards in a run, not just the first one
Root cause of stuck 'running' runs: the plugin's execute() method
only processed dashboard_ids[0] and returned. The remaining N-1
dashboards were never processed, and _update_run_status was called
after each single dashboard without checking dashboard_count.

Fixes:
- execute() now loops over ALL dashboard_ids and processes each
  via _execute_path_a or _execute_path_b
- _update_run_status is called once AFTER the loop finishes
- _update_run_status now checks that len(records) >= dashboard_count
  before marking the run as finished (prevents premature completion)
- Per-dashboard _update_run_status calls removed from _execute_path_a
  and _execute_path_b (the parent loop owns it now)
- Test updated for new batch return format {dashboards: [...], total: N}
2026-05-31 23:03:46 +03:00
c8e81747fc fix(validation): auto-cleanup stuck validation runs on backend startup
When the backend restarts (deploy, crash, reload), the in-memory
TaskManager loses its queue. ValidationRun records left 'running'
in the DB would hang forever, blocking re-runs.

Fix: during lifespan startup, query all ValidationRun with
status='running' and force-stop them as FAIL with a clear summary.

This prevents the 'already has a running run' error after restarts.
2026-05-31 23:00:35 +03:00
7f7a85b2c5 refactor(validation): deduplicate image optimization, fix quality-reduction-before-chunking, unify chunk_count key
- Extract _optimize_images() helper to eliminate duplicate
  optimization code (was duplicated between initial pass and
  quality-reduction fallback)
- Move quality-reduction estimate to only apply when NOT chunking
  (each chunk fits the image limit by definition)
- Fix _merge_chunk_results to return 'chunk_count' instead of 'chunks'
  for consistency with plugin.py
- Simplify plugin.py: analysis.get('chunk_count', 1) instead of
  fallback chain
- Document that Kilo API gateway is incompatible with AsyncOpenAI
  image format (probe returns 0)
2026-05-31 22:57:58 +03:00
2760fa09ea feat(validation): chunk screenshots by max_images limit + fix websocket crash
- analyze_dashboard_multimodal now splits screenshots into chunks
  of max_images (from provider config) and sends them in parallel
- Results merged: worst status, deduped issues by (severity, msg, loc)
- New helper methods: _deduplicate_issues, _merge_chunk_results, _call_llm_for_images
- Plugin passes db_provider.max_images to the LLM client
- Report UI shows 'Chunked ×N' badge when analysis used multiple chunks
- i18n: added 'chunked' / 'По частям' key to validation.json
- Fix: isinstance(StopIteration) -> isinstance(_ws_exc, StopIteration)
  which crashed the websocket and broke task execution mid-flight
- Fix: update test mocks (_FakeLLMClient, _FakeScreenshotService)
2026-05-31 22:43:06 +03:00
9b938fcb81 chore: stop tracking auto-generated semantic index 2026-05-31 22:32:52 +03:00
4c429a74ed chore: add .axiom/ and audit reports to .gitignore 2026-05-31 22:32:44 +03:00
05ef6cdff8 docs(validation): update agent configs, skills, ADRs, specs
- qa-tester: add validation v2 testing checklist
- speckit.plan: add component reuse scan for frontend
- molecular-cot-logging: add Svelte logger + CLI reader
- semantics-svelte: add RSM model-first protocol, frontend stack
- templates: update plan/tasks/ux-reference templates
- ADR-0004: add llm_dashboard_validation plugin registration
- ADR-0008: add assistant tool registry for v2 validation
- Specs: update 017 tasks from 51 to 99
2026-05-31 22:32:32 +03:00
40c9f849b2 feat(validation): v2 frontend — pages, components, stores, i18n
Frontend implementation for v2 LLM dashboard validation:
- validation-tasks/ pages (list, create, edit, detail, runs, history)
- ValidationTaskForm with 5-step wizard, LLM provider selector
- ValidationTaskReport with collapsible dashboard issue cards
- WebSocket task drawer with progress tracking and reconnect logic
- Dashboard page integration with validation status, history, health
- API layer: fetchApi/requestApi wrappers with trace_id propagation
- CoT logger (frontend) for structured JSON logging
- i18n: validation.json with 117 keys each for en/ru
- Settings refactor: consolidated admin settings, provider bindings
- ScheduleAtAGlance health widget, sidebar navigation update
2026-05-31 22:32:27 +03:00
d2b53c2a79 feat(validation): v2 LLM dashboard validation — plugin, routes, services
Core implementation of the v2 LLM dashboard validation pipeline:
- LLM plugin with Path A (screenshots) and Path B (logs-only) execution
- Validation task management (CRUD, schedule, run)
- WebSocket task progress with Python 3.13 asyncio fix
- Cross-task runs listing (GET /validation-tasks/runs/all)
- RecordResponse schema for validation records
- JSON prompt helper, per-dashboard status aggregation
- Prompt templates with docs/git-commit/validation presets
- Migration: v2 validation models + description column
- Tests: plugin persistence, prompt templates, batch, payload, url
2026-05-31 22:32:20 +03:00
431330231f cleanup(validation): remove v1 validation routes and frontend pages
Delete deprecated code that has been fully replaced by v2:
- backend: validation.py routes, validation_run_service.py
- frontend: validation.js API module, validation/ pages
2026-05-31 22:32:14 +03:00
5e5f958eaa feat(llm): auto-detect max images per request for LLM providers
Add binary-search probe endpoint POST /providers/{id}/probe-max-images
that discovers the per-request image limit by sending incrementally
more 1x1 JPEGs via the provider's own API. Result is cached in the
new max_images column on the provider config.

- LLMProviderConfig: add max_images: int | None
- LLMProvider (SQLAlchemy): add max_images column
- Migration ed28d34edde7: clean ADD COLUMN
- LLMProviderService: create/update/set_max_images
- POST /providers/{id}/probe-max-images: binary search + error parsing
- ProviderConfig.svelte: 'Detect' button in edit modal + HelpTooltip
- i18n (en/ru): 11 new keys for probe UI
2026-05-31 22:31:36 +03:00
652de471d2 tasks 2026-05-31 17:38:43 +03:00
e17f4f64a9 websocket add 2026-05-31 17:17:30 +03:00
18f88a6928 fix(translate): repair dialect detection — UPSERT routing, whitespace, MySQL quoting, dead code
CRITICAL BUG-1: UPSERT routing generated invalid ON CONFLICT for MySQL,
MSSQL, Snowflake, Oracle, DuckDB. Now uses explicit UPSERT_SUPPORTED_DIALECTS
({'postgresql', 'redshift'}) — unknown dialects get plain INSERT.

BUG-2: _extract_dialect did not strip whitespace, inconsistent with
get_dialect_from_database. Fixed guard + normalized value.

BUG-3: Whitespace-only input ('   ', '\n') returned itself instead of 'unknown'.

BUG-4: Dead code — removed 'greenplum' from POSTGRESQL_DIALECTS
(always normalized to 'postgresql').

BUG-5: MySQL identifier quoting used double quotes instead of native backticks.
Added BACKTICK_DIALECTS set.

MOCK-FIX: test_at_least_one_row_per_batch patched wrong path
(executor.estimate_token_budget -> _batch_sizer.estimate_token_budget).

Adds 131 orthogonal tests covering all 4 dialect detection code paths
across input formats, normalization, routing, quoting, encoding,
schema validation, and cross-component consistency.
2026-05-31 10:26:03 +03:00
15b466a918 feat(translate): move write settings to Target Config tab + fix datasource name lookup
Fixes:
- Move batch size, upsert strategy, include source reference
  from Config tab to Target Config tab (Write Settings section)
- Fix 'Dataset #26' fallback — look up real datasource name
  via API when source_table is not saved in job data
- Persist include_source_reference in save payload and
  restore from job data on load (was a pre-existing gap)

QA review fixes:
- Update @BRIEF contracts for both tabs
- Fix import indentation in +page.svelte

Other: help tooltips on translate pages, flow hint on list page,
git migration manager components, dashboard hub pages,
migration settings pages
2026-05-31 09:59:09 +03:00
c528a37987 agents ai native front 2026-05-29 22:16:39 +03:00
9ef9fae206 fix: critical QA findings — dead code and prop mismatch
1. Remove get_config_manager() call from translate_run_websocket
   (@app.websocket /ws/translate/run/{run_id}) — was not imported
   and unused. Also remove unused from sqlalchemy.orm import Session.
2. Fix prop name mismatch: showBulkReplace -> showPageBulkReplace
   in RunTabContent. Use () for reactive two-way binding.
3. Add ('DRAFT') for status prop in RunTabContent.
2026-05-29 16:47:50 +03:00
db7e5e3863 feat(translate): add WebSocket endpoint for real-time run progress
Backend:
- Add /ws/translate/run/{run_id} WebSocket endpoint in app.py
- Streams structured run status every second (total_records,
  successful_records, failed_records, progressPct, batch_count, etc.)
- Auto-detects terminal states (COMPLETED, FAILED, CANCELLED) and closes
- Authenticated via JWT/API key token query param

Frontend:
- Add getTranslateRunWsUrl() URL builder in api.js
- Update translationRunStore to use WebSocket instead of log stream
- WebSocket receives structured status JSON, updates store reactively
- Falls back to polling silently if WebSocket fails
- Keep polling as fallback for insert phase
2026-05-29 16:42:59 +03:00
1aceba465b fix: remove orphaned functions, add for auto-load columns
Clean up remaining orphaned references after tab extraction:
- Remove loadColumnsForDatasource, searchDatasources, selectDatasource
  etc. from page (moved to ConfigTabForm)
- Add  on datasourceId in ConfigTabForm for auto-loading
  columns when parent sets datasourceId (loadJob)
- Fix stray braces, remove dead isVirtual function
- Page now 779 lines (down from 1519, -49%)
2026-05-29 16:35:50 +03:00
ffa6234a36 refactor: remove orphaned functions after tab extraction
Remove loadColumnsForDatasource, searchDatasources, selectDatasource,
toggleContextColumn, toggleSourceKeyCol, updateTargetKeyCol, isVirtual
from page — all moved to ConfigTabForm.svelte.

Add  on datasourceId in ConfigTabForm to auto-load columns
when parent sets datasourceId (loadJob) or user selects a datasource.
2026-05-29 16:33:15 +03:00
ebc00bbb0e refactor(translate): extract ConfigTabForm, TargetTabForm, RunTabContent from page
Page reduced from 1519 to 909 lines (-40%). Extracted:
- ConfigTabForm.svelte (370 lines) — datasource search, column mapping,
  LLM, target languages, dictionaries, batch config
- TargetTabForm.svelte (120 lines) — target schema/table/database,
  target column mapping, TargetSchemaHint
- RunTabContent.svelte (170 lines) — run cards, progress, history

All three components use () props for seamless parent
state sync. Sub-components (TargetSchemaHint, TranslationPreview,
TranslationRunProgress, ScheduleConfig, BulkReplaceModal) unchanged.
2026-05-29 16:30:09 +03:00
05fda8310d refactor(translate): add UX contracts to translation job page
Add comprehensive UX contract header documenting:
- @UX_STATE: all states of the page-level state machine (idle, loading,
  configured, saving, validation_error, datasource_unavailable, error)
- @UX_STEP: 5 logically separated steps/tabs (Config, Preview, Target, Run, Schedule)
- @UX_FEEDBACK: toasts, modals, inline progress, schema validation
- @UX_RECOVERY: retry paths for save/preview/run failures
- @UX_REACTIVITY: props, local state, derived, effects, store bindings
- @UX_DEPENDENCY: data flow between datasource selection, env switching,
  config validity, and tab availability
- @UX_TEST: test scenarios for the automated Judge Agent

Also remove leftover sourceDialect/targetDialect selects from UI
(now sent as sensible defaults in save payload).

Sub-components (TargetSchemaHint, TranslationPreview, TranslationRunProgress,
ScheduleConfig, BulkReplaceModal) already have UX contracts.
2026-05-29 16:25:14 +03:00
c9fb994728 fix(translate): remove source/target dialect selects from UI
These fields were showing database types (PostgreSQL, ClickHouse)
as human language options for the LLM prompt, which was confusing.
Now sending sensible defaults (source='SQL', target='en') directly
in the save payload without exposing them in the UI.

The backend already has fallbacks:
  _llm_call.py: source_language = job.source_dialect or 'SQL'
  _batch_proc.py: target_langs = or [job.target_dialect or 'en']
2026-05-29 16:16:05 +03:00
5deb01e182 fix 2026-05-29 16:15:41 +03:00