specs updated

This commit is contained in:
2026-06-08 14:14:38 +03:00
parent f731a53c7d
commit 3c84161606
18 changed files with 416 additions and 382 deletions

View File

@@ -2,7 +2,7 @@
**Purpose**: Validate requirement quality for user interaction and workflows.
**Feature**: `017-llm-analysis-plugin`
**Created**: 2026-01-28 | **Updated**: 2026-05-31 — v2
**Created**: 2026-01-28 | **Updated**: 2026-06-07 — v2 implemented
## v1 Items (preserved, re-evaluated for v2)

View File

@@ -1,7 +1,7 @@
# Module Contracts: LLM Analysis Plugin v2
**Feature**: `017-llm-analysis-plugin`
**Updated**: 2026-05-31 — v2: dual-path contracts, URL parsing, dataset health checking
**Updated**: 2026-06-07 — v2 implemented: dual-path contracts, URL parsing, dataset health checking
**Protocol**: GRACE-Poly v2.6
## Backend Modules

View File

@@ -1,7 +1,7 @@
# Data Model: LLM Analysis Plugin v2
**Feature**: `017-llm-analysis-plugin`
**Updated**: 2026-05-31 — v2: ValidationPolicy expansion, ValidationSource, dual-path execution models
**Updated**: 2026-06-07 — v2 implemented: ValidationPolicy expansion, ValidationSource, dual-path execution models
## Entities

View File

@@ -1,6 +1,6 @@
# Implementation Plan: LLM Analysis & Documentation Plugins v2
**Branch**: `017-llm-analysis-plugin` | **Date**: 2026-01-28 | **Updated**: 2026-05-31 — v2
**Branch**: `017-llm-analysis-plugin` | **Date**: 2026-01-28 | **Updated**: 2026-06-07 — v2 implemented
**Spec**: [spec.md](spec.md)
## Summary
@@ -140,38 +140,43 @@ Source: `.specify/memory/constitution.md` v1.0.0
```text
backend/src/
├── plugins/llm_analysis/
│ ├── plugin.py # REFACTOR: dispatch to _execute_path_a / _execute_path_b
│ ├── service.py # REFACTOR: ScreenshotService.capture_dashboard_chunks()
│ # LLMClient.analyze_dashboard_multimodal()
│ # LLMClient.analyze_dashboard_text()
# NEW: DatasetHealthChecker class
│ ├── scheduler.py # UPDATE: use ValidationPolicy model
│ └── models.py # UPDATE: add ValidationSource, expand ValidationPolicy
│ ├── plugin.py # DashboardValidationPlugin (1 004 строки) — dispatch to Path A/B
│ ├── service.py # ScreenshotService + LLMClient + DatasetHealthChecker (1 691 строка)
├── _topology.py # DashboardTopologyBuilder (290 строк)
├── scheduler.py # APScheduler integration (57 строк)
├── models.py # Plugin models (73 строки)
│ ├── migrations/ # v1_to_v2 migration (196 строк)
│ └── __tests__/ # 3 test files (655 строк)
├── services/
│ ├── validation_service.py # REFACTOR: ValidationTaskService (renamed, expanded CRUD)
── llm_prompt_templates.py # UPDATE: add dashboard_validation_prompt_text + multimodal keys
│ └── llm_provider.py # (unchanged)
│ ├── validation_service.py # ValidationTaskService CRUD (767 строк)
── llm_prompt_templates.py # Dual-path prompt defaults (259 строк)
├── api/routes/
│ ├── llm.py # UPDATE: remove dashboard_validation from provider_bindings schemas
│ └── validation_tasks.py # NEW: CRUD routes for /api/validation-tasks
── core/utils/
└── superset_context_extractor/ # (unchanged — reused for URL parsing)
│ ├── validation_tasks.py # CRUD routes for /api/validation-tasks (481 строка)
│ └── llm.py # LLM provider/settings routes (608 строк)
── models/
└── llm.py # LLM ORM models: ValidationPolicy, ValidationSource, ValidationRecord, ValidationRun (156 строк)
frontend/src/
├── routes/
│ ├── validation-tasks/ # NEW: task list page
│ │ ├── +page.svelte
│ │ ├── new/+page.svelte # NEW: task creation form
│ │ ── [policyId]/+page.svelte # NEW: task detail + history
│ ├── dashboards/+page.svelte # UPDATE: remove Validate button, remove LLM status column
│ ├── reports/llm/[taskId]/+page.svelte # UPDATE: multi-chunk screenshots, dataset health display
│ └── admin/settings/llm/+page.svelte # UPDATE: remove dashboard_validation binding
└── components/
── llm/
── ValidationTaskForm.svelte # NEW: multi-step task creation form
├── ValidationTaskReport.svelte # NEW: shared report component
├── UrlParser.svelte # NEW: URL paste + parse preview
└── DatasetHealthTable.svelte # NEW: dataset health status table
│ ├── validation-tasks/ # Task list + detail + history + runs (6 страниц)
│ │ ├── +page.svelte # Task list (204 строки)
│ │ ├── new/+page.svelte # Task creation (95 строк)
│ │ ── [policyId]/+page.svelte # Task detail (398 строк)
│ ├── [policyId]/edit/+page.svelte # Task edit (102 строки)
│ ├── [policyId]/runs/[runId]/+page.svelte # Run detail report (200 строк)
│ └── history/+page.svelte # Run history (183 строки)
│ ├── dashboards/[id]/validation/+page.svelte # Dashboard validation history (325 строк)
── reports/llm/[taskId]/+page.svelte # Legacy report redirect (219 строк)
── admin/settings/llm/+page.svelte # LLM provider settings (258 строк)
├── lib/components/llm/
├── ValidationTaskForm.svelte # Multi-step task creation form (1 096 строк)
│ ├── ValidationTaskReport.svelte # Shared report component (39 строк)
│ ├── UrlParser.svelte # URL paste + parse preview (207 строк)
│ ├── ProviderConfig.svelte # Provider configuration form (745 строк)
│ └── DocPreview.svelte # Documentation preview (87 строк)
├── lib/i18n/locales/
│ ├── en/validation.json + llm.json # English locale
│ └── ru/validation.json + llm.json # Russian locale
```
## Complexity Tracking

View File

@@ -1,7 +1,7 @@
# Research: LLM Analysis & Documentation Plugins v2
**Feature**: `017-llm-analysis-plugin`
**Updated**: 2026-05-31 — v2: dual-path execution, multi-chunk screenshots, dataset health checking, URL-based dashboards
**Updated**: 2026-06-07 — v2 implemented: dual-path execution, multi-chunk screenshots, dataset health checking, URL-based dashboards
## v2 Research Decisions

View File

@@ -2,8 +2,8 @@
**Feature Branch**: `017-llm-analysis-plugin`
**Created**: 2026-01-28
**Updated**: 2026-05-31 — v2: task-based flow, dual-path execution (screenshot + text-only), URL-based dashboards, dataset health checking
**Status**: Specification updated; implementation pending for v2 changes
**Updated**: 2026-06-07 — v2: task-based flow, dual-path execution, fully implemented
**Status**: Implemented ✅ (~30 files, ~7 880 строк backend + ~4 558 строк frontend)
## v2 Design Decisions

View File

@@ -1,7 +1,7 @@
# Tasks: LLM Analysis & Documentation Plugins v2
**Feature**: `017-llm-analysis-plugin`
**Status**: v2 Implementation — ~86% complete (86/99 tasks)
**Status**: v2 Implementation — **complete** ✅ (~30 backend files, ~12 frontend files, ~7 880 + ~4 558 строк)
**Spec**: [spec.md](spec.md) | **Plan**: [plan.md](plan.md) | **Data Model**: [data-model.md](data-model.md)
## User Stories & Priorities

View File

@@ -2,7 +2,7 @@
**Purpose**: Validate specification completeness and quality before proceeding to planning
**Created**: 2026-05-08
**Updated**: 2026-05-08 (post-review)
**Updated**: 2026-06-07 (post-implementation verification)
**Feature**: [spec.md](../spec.md)
## Content Quality
@@ -45,21 +45,21 @@
- [x] Dialect-aware SQL generation declared (PostgreSQL/Greenplum + ClickHouse, detected from Superset connection)
- [x] Retention gap resolved: MetricSnapshot persistence before event pruning
## Implementation Verification (2026-05-25)
## Implementation Verification (2026-06-07)
| Check | Status |
|-------|--------|
| Backend: translate plugin | ✅ Exists at `plugins/translate/plugin.py` (C2) |
| Backend: translate plugin | ✅ Exists at `plugins/translate/` (59 source files, C2 skeleton) |
| Backend: translate routes | ✅ Exists as `api/routes/translate/` package (13 submodules) |
| Backend: translate services | ✅ Exists as `plugins/translate/service.py` (1174 LOC) |
| Backend: translate models | ✅ Exists as `models/translate.py` |
| Backend: translate schemas | ✅ Exists as `schemas/translate.py` |
| Backend: translate tests | ✅ 20 test files in `plugins/translate/__tests__/` |
| Backend: translate services | ✅ Decomposed across 59 plugin source files |
| Backend: translate models | ✅ Exists as `models/translate.py` (401 строка) |
| Backend: translate schemas | ✅ Exists as `schemas/translate.py` (712 строк) |
| Backend: translate tests | ✅ 27 файлов в `plugins/translate/__tests__/` + 12 внешних |
| Frontend: translate pages | ✅ `/translate/`, `/translate/[id]/`, `/translate/dictionaries/`, `/translate/history/` |
| Frontend: translate components | ✅ 11 Svelte components (CorrectionCell, BulkReplaceModal, TranslationPreview, etc.) |
| Frontend: translate API client | ✅ `lib/api/translate/` (8 module files) |
| Frontend: translate components | ✅ 14 Svelte компонентов (включая ConfigTabForm, RunTabContent, TargetTabForm, TargetSchemaHint) |
| Frontend: translate API client | ✅ `lib/api/translate/` (8 модулей) |
| Docker compose | ✅ `docker-compose.yml` exists |
| Backend .env | ✅ `backend/.env` (12 lines, ENCRYPTION_KEY + feature flags) |
| Backend .env | ✅ `backend/.env` (ENCRYPTION_KEY + feature flags) |
## Notes
@@ -68,4 +68,5 @@
- Preview model clarified as quality gate (not row-level approval for all rows).
- INSERT execution standardized on Superset `/api/v1/sqllab/execute/` API.
- All manual copy/paste SQL Lab references removed from spec, UX, quickstart, and contracts.
- Spec status: Implemented ✅ (verified by code-to-spec mapping 2026-05-25)
- Spec status: Implemented ✅ (verified by code-to-spec mapping 2026-06-07)
- Актуальные метрики: ~153 файла, ~36 091 строка кода, 59 plugin source files, 13 routes, 14 frontend components

View File

@@ -1,7 +1,7 @@
# Semantic Contracts: LLM Table Translation Service
**Feature Branch**: `028-llm-datasource-supeset`
**Date**: 2026-05-17 (updated to match implementation)
**Feature Branch**: `028-llm-datasource-supeset` (актуальная: `032-translate-requests-httpx`)
**Date**: 2026-06-07 (updated to match implementation)
**Protocol**: GRACE-Poly v2.6
---
@@ -156,7 +156,7 @@
### [DEF:TranslateRoutes:Package]
`backend/src/api/routes/translate/`
@COMPLEXITY 4
@PURPOSE FastAPI route handlers organized as package with 11 sub-modules: job CRUD (249 строк), run execution (554), run list (225), preview (194), dictionary (391), correction (100), schedule (239), metrics (65), helpers (71). All endpoints enforce RBAC per access-control matrix. Runs execute in background threads with isolated DB sessions.
@PURPOSE FastAPI route handlers organized as package with 13 sub-modules: job CRUD (285 строк), run execution (205), run edit (200), run list (359), run history (133), preview (194), dictionary (391), correction (100), schedule (239), metrics (65), helpers (70). All endpoints enforce RBAC per access-control matrix. Runs execute in background threads with isolated DB sessions.
@RELATION CALLS -> [TranslationOrchestrator:Class]
@RELATION CALLS -> [TranslateJobService:Class]
@RELATION CALLS -> [DictionaryManager:Class]
@@ -164,8 +164,8 @@
@RELATION CALLS -> [TranslationEventLog:Class]
@RELATION CALLS -> [TranslationMetrics:Class]
@RELATION BINDS_TO -> [PermissionChecker:Dependency]
@RATIONALE C4 because routes package spans 11 files, coordinates 6+ service dependencies, and enforces RBAC across 13 permission strings. Split into sub-modules by domain to respect fractal limit (<400 lines per file, except _run_routes.py at 554).
@REJECTED Single translate.py file rejected would exceed fractal limit at 2 141 lines. Multiple route files with shared state would couple domains.
@RATIONALE C4 because routes package spans 13 files, coordinates 6+ service dependencies, and enforces RBAC across 13 permission strings. Split into sub-modules by domain to respect fractal limit (<400 lines per file, except _dictionary_routes.py at 391 and _run_list_routes.py at 359).
@REJECTED Single translate.py file rejected would exceed fractal limit at 2 296 lines. Multiple route files with shared state would couple domains.
[/DEF:TranslateRoutes:Package]
### [DEF:TranslateModels:Module]
@@ -325,7 +325,7 @@
[/DEF:TranslateApiClient:Module]
### [DEF:translateStore:Store]
`frontend/src/lib/stores/translationRun.js`
`frontend/src/lib/stores/translationRun.svelte.ts`
@COMPLEXITY 3
@PURPOSE Svelte 5 rune store for translation feature state: run progress, WebSocket connection status, per-language progress.
@RELATION BINDS_TO -> [TranslateApiClient:Module]

View File

@@ -1,9 +1,9 @@
# Data Model: LLM Table Translation Service
**Feature Branch**: `028-llm-datasource-supeset`
**Date**: 2026-05-17 (updated to match implementation)
**Note**: Все 15 ORM моделей реализованы в `backend/src/models/translate.py` (397 строк).
**Note**: Маршруты реализованы как пакет `backend/src/api/routes/translate/` (11 файлов), а не единый `translate.py`, как предполагалось в плане.
**Feature Branch**: `028-llm-datasource-supeset` (актуальная: `032-translate-requests-httpx`)
**Date**: 2026-05-17 (updated 2026-06-07 to match implementation)
**Note**: Все 15 ORM моделей реализованы в `backend/src/models/translate.py` (401 строка).
**Note**: Маршруты реализованы как пакет `backend/src/api/routes/translate/` (13 файлов, 2 296 строк).
## 1. SQLAlchemy ORM Entities (dialect-aware — PostgreSQL/Greenplum, ClickHouse supported)

View File

@@ -1,29 +1,29 @@
# Отчёт об оценке трудозатрат: Feature 028 — LLM Table Translation Service
**Дата**: 2026-05-18 (актуализация: 2026-05-18)
**Ветка**: `028-llm-datasource-supeset`
**Дата**: 2026-05-18 (актуализация: 2026-06-07)
**Ветка**: `032-translate-requests-httpx`
**Автор**: Speckit Workflow Specialist
---
## Сводка
Feature 028 реализован полностью (102 файла, ~29 789 строк кода, 335/335 pytest, 27/28 vitest translate).
Feature 028 реализован полностью (~153 файла, ~36 091 строка кода, ~503 pytest, ~65 vitest).
Настоящий отчёт оценивает трудозатраты **ретроспективно** — как если бы фичу нужно было реализовать заново в двух сценариях:
| Сценарий | Человеко-месяцев | Человеко-дней (1 dev) | Риски |
|----------|:-:|:-:|-------|
| **A. Standalone (с нуля, без ss-tools)** | 5.57.5 | 121165 | Высокие: инфраструктура с нуля |
| **B. В рамках ss-tools** | 22.5 | 4455 | Низкие: переиспользование отлаженных компонентов |
| **Экономия ss-tools** | **~6570%** | — | — |
| **A. Standalone (с нуля, без ss-tools)** | 6.58.5 | 143187 | Высокие: инфраструктура с нуля |
| **B. В рамках ss-tools** | 2.53 | 5566 | Низкие: переиспользование отлаженных компонентов |
| **Экономия ss-tools** | **~6265%** | — | — |
---
## Методология оценки
Оценка основана на:
1. **Фактическом объёме кода**: 72 файла, 29 128 строк (подтверждено `wc -l`)
2. **Статистике дефектов/тестов**: 165 pytest + 280 vitest
1. **Фактическом объёме кода**: 148 файлов, 34 909 строк (подтверждено `wc -l`)
2. **Статистике дефектов/тестов**: 503 pytest + 65 vitest
3. **Сложности модулей**: 2× C5, 9× C4, 13× C3, 7× C2 (по GRACE-Poly v2.6)
4. **Анализе переиспользования**: 7 интеграционных контрактов с существующей инфраструктурой ss-tools
5. **Метриках из смежных проектов**: базовая производительность 50100 строк/день для C4+ с учётом тестов
@@ -80,43 +80,48 @@ Feature 028 — это полноценный full-stack web-сервис. В st
#### 1.4 Бизнес-логика (домен перевода)
Этот компонент **общий для обоих сценариев** — чистая доменная логика, идентичная по объёму,
но в ходе реализации была значительно декомпозирована (57 plugin-файлов вместо ~14).
но в ходе реализации была значительно декомпозирована (59 plugin-файлов вместо ~14).
| Компонент | Строк кода | Файлов | Трудозатраты (дней) |
|-----------|:-:|:-----:|:-:|
| ORM модели (15 таблиц) + миграции | 1 198 | 6 | 6 |
| Pydantic схемы (35+ DTO) | 688 | 1 | 3 |
| TranslatePlugin + служебные модули | 269 | 3 | 2 |
| **Orchestrator** (planner, exec, sql, retry, cancel, validation, aggregator, run_completion, runner, lang_stats, query, config) | 1 571 | 12 | 14 |
| **Executor** (executor, _llm_call, _llm_http, _llm_parse, _batch_insert, _batch_proc, _batch_sizer, _run_service, _run_source) | 1 643 | 10 | 16 |
| **Service** (service, service_inline_correction, service_bulk_replace, service_datasource, service_utils) | 918 | 5 | 9 |
| **Preview** (preview, preview_executor, preview_llm_client, preview_prompt_builder, preview_prompt_helpers, preview_response_parser, preview_review, preview_session_ops, preview_session_serializer, preview_token_estimator, preview_constants, preview_resolve_provider) | 1 361 | 12 | 13 |
| **Dictionary** (dictionary, dictionary_crud, dictionary_entries, dictionary_filter, dictionary_correction, dictionary_import_export, dictionary_validation) | 904 | 8 | 9 |
| Scheduler + schedule CRUD (C4) | 443 | 1 | 5 |
| SQLGenerator | 378 | 1 | 4 |
| SupersetSqlLabExecutor | 420 | 1 | 4 |
| ORM модели (15 таблиц) | 401 | 1 | 3 |
| Pydantic схемы (35+ DTO) | 712 | 1 | 4 |
| Plugin skeleton | 61 | 1 | 0.5 |
| **Orchestrator** (14 файлов) | 1 631 | 14 | 15 |
| **Executor** (executor, _batch_*, _llm_*, _run_*) | 2 196 | 9 | 21 |
| **Preview** (11 файлов) | 1 291 | 11 | 12 |
| **Dictionary** (7 файлов) | 921 | 7 | 9 |
| **Service** (6 файлов) | 1 281 | 6 | 11 |
| Scheduler + schedule CRUD | 443 | 1 | 5 |
| SQLGenerator | 402 | 1 | 4 |
| SupersetSqlLabExecutor | 439 | 1 | 4 |
| ContextAwarePromptBuilder | 153 | 1 | 2 |
| TranslationMetrics | 192 | 1 | 2 |
| TranslationEventLog | 272 | 1 | 3 |
| _token_budget, _utils | 443 | 2 | 3 |
| **Subtotal backend domain** | **~10 853** | **57** | **99** |
| API routes (11 файлов, 2 141 строка) | 2 141 | 11 | 14 |
| Frontend Svelte components (10 файлов) | 3 280 | 10 | 28 |
| Frontend pages (5 файлов) | 3 354 | 5 | 18 |
| Frontend API client (6 файлов) + store | 727 | 7 | 5 |
| Frontend i18n | 179 | 1 | 2 |
| **Subtotal frontend domain** | **~7 540** | **23** | **53** |
| **Subtotal domain logic** | **~20 534** | **91** | **166** |
| TranslationEventLog | 274 | 1 | 3 |
| _token_budget | 395 | 1 | 4 |
| _utils | 225 | 1 | 2 |
| _lang_detect + _text_cleaner | 270 | 2 | 3 |
| _llm_async_http | 246 | 1 | 3 |
| service_target_schema | 355 | 1 | 4 |
| **Subtotal backend domain** | **~11 888** | **59** | **105** |
| API routes (13 файлов, 2 296 строк) | 2 296 | 13 | 15 |
| Frontend Svelte components (14 файлов) | 5 017 | 14 | 38 |
| Frontend pages (5 файлов) | 1 237 | 5 | 14 |
| Frontend API client (8 файлов) | 987 | 8 | 8 |
| **Subtotal frontend domain** | **~9 537** | **40** | **75** |
| **Subtotal domain logic** | **~21 425** | **99** | **180** |
#### 1.5 Тестирование
| Компонент | Строк кода | Файлов | Трудозатраты (дней) |
|-----------|:-:|:-----:|:-:|
| Unit-тесты бэкенда (inline в plugin, 16 файлов) | 6 029 | 16 | 20 |
| Интеграционные тесты (external, 7 файлов) | 2 458 | 7 | 12 |
| Component-тесты фронтенда (3 файла) | 433 | 3 | 4 |
| E2E (1 файл) | 142 | 1 | 2 |
| **Subtotal testing** | **~9 062** | **27** | **38** |
| Unit-тесты бэкенда (inline в plugin, 27 файлов) | 9 090 | 27 | 32 |
| Интеграционные тесты (external, 12 файлов) | 3 746 | 12 | 16 |
| Plugin integration (2 файла) | 279 | 2 | 2 |
| Component-тесты фронтенда (5 файлов) | 699 | 5 | 5 |
| Model-тесты фронтенда (2 файла) | 406 | 2 | 3 |
| E2E (1 файл) | 142 | 1 | 1 |
| **Subtotal testing** | **~14 083** | **47** | **59** |
#### Итог: Сценарий A
@@ -125,15 +130,15 @@ Feature 028 — это полноценный full-stack web-сервис. В st
| Бэкенд инфраструктура | 13 900 | — | 109 |
| Фронтенд инфраструктура | 5 700 | — | 41 |
| DevOps / CI | — | — | 10 |
| Бэкенд домен | 10 853 | 57 | 99 |
| Фронтенд домен | 7 540 | 23 | 53 |
| Тесты | 9 062 | 27 | 38 |
| **ИТОГО** | **~47 055** | **~107** | **350 days** |
| Бэкенд домен | 11 888 | 59 | 105 |
| Фронтенд домен + routes | 9 537 | 40 | 75 |
| Тесты | 14 083 | 47 | 59 |
| **ИТОГО** | **~55 108** | **~146** | **399 days** |
**Реалистичная оценка с учётом параллелизации**:
- 2 full-stack разработчика: **~56 месяцев**
- Команда (бэкенд + фронтенд + QA): **~3.54 месяца**
- **Рекомендованная оценка**: **5.57.5 человеко-месяцев**
- 2 full-stack разработчика: **~67 месяцев**
- Команда (бэкенд + фронтенд + QA): **~45 месяцев**
- **Рекомендованная оценка**: **6.58.5 человеко-месяцев**
---
@@ -170,65 +175,67 @@ ss-tools предоставляет **готовую отлаженную инф
#### 2.2 Что нужно построить (только домен)
> **Важно**: В ходе реализации код был значительно декомпозирован — крупные модули (Orchestrator, Preview, Executor, Dictionary, Service) разбиты на 212 более мелких файлов каждый.
> Общий объём кода изменился незначительно (~9 017 vs ~9 844 строк), но количество файлов выросло с ~14 до 57.
> **Важно**: В ходе дальнейшей разработки код был расширен — добавились новые модули (_lang_detect, _text_cleaner, _llm_async_http, service_target_schema) и тесты.
> Общий объём кода: ~10 174 строк (plugin) + 401 (models) + 712 (schemas) = 11 287 строк в backend domain.
| Компонент | Строк кода | Файлов | Трудозатраты (дней) |
|-----------|:-:|:-:|:-:|
| **Backend domain** | | | |
| ORM модели (в `models/translate.py`) | 397 | 1 | 3 |
| Pydantic схемы (в `schemas/translate.py`) | 688 | 1 | 4 |
| ORM модели (в `models/translate.py`) | 401 | 1 | 3 |
| Pydantic схемы (в `schemas/translate.py`) | 712 | 1 | 4 |
| Plugin skeleton (plugin.py) | 61 | 1 | 0.5 |
| **Orchestrator** (decomposed: planner, exec, sql, retry, cancel, validation, aggregator, run_completion, runner, lang_stats, query, config) | 1 571 | 12 | 14 |
| **Executor** (decomposed: _llm_call, _llm_http, _llm_parse, _batch_insert, _batch_proc, _batch_sizer, _run_service, _run_source) | 1 643 | 10 | 16 |
| **Preview** (decomposed: executor, llm_client, prompt_builder, prompt_helpers, response_parser, review, session_ops, session_serializer, token_estimator, constants, resolve_provider) | 1 361 | 12 | 13 |
| **Dictionary** (decomposed: correction, crud, entries, filter, import_export, validation) | 904 | 8 | 9 |
| **Service** (decomposed: bulk_replace, inline_correction, datasource, utils) | 918 | 5 | 8 |
| **Orchestrator** (14 файлов: planner, exec, sql, retry, cancel, validation, aggregator, run_completion, runner, lang_stats, query, config, sql_rows) | 1 631 | 14 | 15 |
| **Executor / LLM** (9 файлов: executor, _llm_call, _llm_parse, _llm_async_http, _batch_insert, _batch_proc, _batch_sizer, _run_service, _run_source) | 2 196 | 9 | 21 |
| **Preview** (11 файлов: executor, prompt_builder, prompt_helpers, response_parser, review, session_ops, session_serializer, token_estimator, constants, resolve_provider) | 1 291 | 11 | 12 |
| **Dictionary** (7 файлов: correction, crud, entries, filter, import_export, validation) | 921 | 7 | 9 |
| **Service** (6 файлов: bulk_replace, inline_correction, datasource, target_schema, utils) | 1 281 | 6 | 12 |
| Scheduler (+ cron utils) | 443 | 1 | 5 |
| SQLGenerator | 378 | 1 | 4 |
| SupersetSqlLabExecutor | 420 | 1 | 4 |
| SQLGenerator | 402 | 1 | 4 |
| SupersetSqlLabExecutor | 439 | 1 | 4 |
| PromptBuilder | 153 | 1 | 2 |
| Metrics | 192 | 1 | 2 |
| Events | 272 | 1 | 3 |
| _token_budget + _utils | 443 | 2 | 3 |
| **Subtotal backend domain** | **~9 844** | **57** | **100.5** |
| **Backend routes (11 файлов)** | **2 141** | **11** | **14** |
| **Frontend UI (23 файла)** | | | |
| Компоненты (10 svelte-файлов) | 3 280 | 10 | 28 |
| Страницы (5 svelte-файлов) | 3 354 | 5 | 18 |
| API client (6 js-файлов) | 529 | 6 | 4 |
| Store (translationRun.js) | 198 | 1 | 2 |
| i18n (en/ru в index.ts) | 179 | 1 | 2 |
| **Subtotal frontend** | **~7 540** | **23** | **54** |
| **Тесты (backend: 24 inline + 7 external = 31 файлов)** | | | |
| Inline plugin tests (16 файлов) | 6 029 | 16 | 20 |
| External integration tests (7 файлов) | 2 458 | 7 | 10 |
| Frontend component tests (3 файла) | 433 | 3 | 3 |
| Events | 274 | 1 | 3 |
| _token_budget | 395 | 1 | 4 |
| _utils | 225 | 1 | 2 |
| _lang_detect | 207 | 1 | 2 |
| _text_cleaner | 63 | 1 | 1 |
| **Subtotal backend domain** | **~11 287** | **59** | **105** |
| **Backend routes (13 файлов)** | **2 296** | **13** | **15** |
| **Frontend UI (27 файлов)** | | | |
| Компоненты (14 svelte-файлов) | 5 017 | 14 | 38 |
| Страницы (5 svelte-файлов) | 1 237 | 5 | 14 |
| API client (8 js/ts-файлов) | 987 | 8 | 8 |
| **Subtotal frontend** | **~7 241** | **27** | **60** |
| **Тесты** | | | |
| Inline plugin tests (27 файлов) | 9 090 | 27 | 32 |
| External integration tests (10 файлов) | 3 467 | 10 | 15 |
| Plugin integration (2 файла) | 279 | 2 | 2 |
| Frontend component tests (5 файлов) | 699 | 5 | 5 |
| Frontend model tests (2 файла) | 406 | 2 | 3 |
| E2E (1 файл) | 142 | 1 | 1 |
| **Subtotal tests** | **~9 062** | **27** | **34** |
| **Subtotal tests** | **~14 083** | **47** | **58** |
| Алембик миграции (5 файлов) | 801 | 5 | 4 |
| Семантические контракты + документирование | — | — | 5 |
| **Subtotal** | **~30 388** | **102** | **211.5** |
| **Subtotal** | **~36 307** | **148** | **247** |
> **Примечание по effort**: Декомпозиция (57 файлов вместо ~14) увеличила overhead на импорты, анкоры, GRACE-контракты и навигацию между файлами, что добавлено ~5 дней к backend domain (100.5 vs 95.5).
> Общее снижение frontend (7 540 vs 9 310) — i18n переехал в единый index.ts (179 строк вместо отдельных файлов на каждый модуль).
> **Примечание по effort**: Добавлены новые модули (_lang_detect, _text_cleaner, _llm_async_http, service_target_schema) и существенно расширены тесты (+5 021 строка, +20 файлов), что увеличило backend domain на ~5 дней, frontend на ~6 дней и тесты на ~24 дня.
#### Итог: Сценарий B
| Категория | Строк кода | Файлов | Трудозатраты (дней) |
|-----------|:-:|:-----:|:-:|
| Переиспользовано (бесплатно) | ~18 800 | — | 0 |
| Бэкенд домен | 9 844 | 57 | 100 |
| API routes | 2 141 | 11 | 14 |
| Фронтенд | 7 540 | 23 | 54 |
| Тесты | 9 062 | 27 | 34 |
| Бэкенд домен | 11 287 | 59 | 105 |
| API routes | 2 296 | 13 | 15 |
| Фронтенд | 7 241 | 27 | 60 |
| Тесты | 14 083 | 47 | 58 |
| Миграции + документация | 801 | 5 | 9 |
| **ИТОГО** | **~30 388** | **102** | **211 days** |
| **ИТОГО** | **~36 091** | **~153** | **247 days** |
**Реалистичная оценка с учётом параллелизации**:
- 1 full-stack разработчик (знакомый с ss-tools): **~2.53 месяца**
- 2 разработчика (бэкенд + фронтенд): **~2 месяца**
- **Рекомендованная оценка**: **22.5 человеко-месяца**
- 1 full-stack разработчик (знакомый с ss-tools): **~33.5 месяца**
- 2 разработчика (бэкенд + фронтенд): **~2.53 месяца**
- **Рекомендованная оценка**: **2.53 человеко-месяца**
---
@@ -238,18 +245,18 @@ ss-tools предоставляет **готовую отлаженную инф
| Измерение | Standalone (A) | В ss-tools (B) | Разница |
|-----------|:-:|:-:|:-:|
| Всего строк кода | ~47 055 | ~30 388 | -35% |
| Из них нового кода | 100% | 61% | — |
| Инфраструктура | 19 600 строк (42%) | 0 (переиспользовано) | -100% |
| Домен (бэк + фронт) | 18 393 строк | 17 384 (декомпозирован) | -5% |
| Тесты | 9 062 | 9 062 | 0% (те же) |
| Файлов всего | ~107 | 102 | -5% |
| Человеко-дней | 350 | 211 | -40% |
| Человеко-месяцев | 5.57.5 | 22.5 | -6570% |
| Рыночная стоимость* | 3.14.2 млн ₽ | 1.11.4 млн ₽ | экономия ~22.8 млн ₽ |
| Всего строк кода | ~55 108 | ~36 091 | -35% |
| Из них нового кода | 100% | 66% | — |
| Инфраструктура | 19 600 строк (36%) | 0 (переиспользовано) | -100% |
| Домен (бэк + фронт) | 21 425 | 20 824 | -3% |
| Тесты | 14 083 | 14 083 | 0% (те же) |
| Файлов всего | ~146 | ~151 | +3% |
| Человеко-дней | 399 | 247 | -38% |
| Человеко-месяцев | 6.58.5 | 2.53 | -6265% |
| Рыночная стоимость* | 3.64.8 млн ₽ | 1.41.7 млн ₽ | экономия ~2.23.1 млн ₽ |
\* При ставке ~3 500 ₽/час (senior full-stack developer, РФ, фриланс/контракт). 1 человеко-месяц ≈ 160 часов ≈ 560 000 ₽.
Диапазон: 5.5 мес × 560К = 3.08 млн (min) … 7.5 мес × 560К = 4.2 млн (max) для сценария A.
Диапазон: 6.5 мес × 560К = 3.64 млн (min) … 8.5 мес × 560К = 4.76 млн (max) для сценария A.
Среднерыночная ставка на 20252026 гг. по данным Хабр Карьера, Kwork, fl.ru для senior-уровня.
### 3.2 Что конкретно экономит ss-tools
@@ -320,148 +327,152 @@ ss-tools предоставляет **готовую отлаженную инф
## 5. Выводы
### Для бизнеса
1. **Строить в ss-tools выгодно**: экономия 6570% стоимости и времени (с поправкой на актуальную реализацию)
2. **Standalone не имеет смысла** для этого функционала: 42% кода — инфраструктура, которая уже есть в ss-tools
1. **Строить в ss-tools выгодно**: экономия ~6265% стоимости и времени (с поправкой на актуальную реализацию)
2. **Standalone не имеет смысла** для этого функционала: 35% кода — инфраструктура, которая уже есть в ss-tools
3. **Качество выше в ss-tools** за счёт переиспользования проверенных компонентов (RBAC, LLM, WebSocket)
### Для команды
1. **Реализация заняла бы 22.5 месяца** в ss-tools против 5.57.5 standalone
1. **Реализация заняла бы 2.53 месяца** в ss-tools против 6.58.5 standalone
2. **Основная сложность** — не инфраструктура, а доменная логика (executor, orchestrator, обработка LLM-ответов)
3. **Код был значительно декомпозирован** в процессе разработки: 57 файлов plugin вместо ~14, что увеличило overhead на импорты и контракты, но не изменило общий объём логики.
3. **Код был существенно расширен** в процессе дальнейшей разработки: 59 файлов plugin, 148 файлов всего, 34 909 строк.
4. **Cамые сложные модули** (по совокупному объёму):
- `Orchestrator` (1 571 строка, 12 файлов, 14 дней) — координация run lifecycle, snapshot isolation
- `Executor + LLM` (1 643 строки, 10 файлов, 16 дней) — парсинг LLM-ответов, батчинг, retry, caching
- `Preview` (1 361 строка, 12 файлов, 13 дней) — quality gate, approve/edit/reject lifecycle
- `Dictionary` (904 строки, 8 файлов, 9 дней) — CRUD + import/export + per-batch filtering
- `Orchestrator` (1 631 строка, 14 файлов, 15 дней) — координация run lifecycle, snapshot isolation
- `Executor + LLM` (2 196 строк, 9 файлов, 21 день) — парсинг LLM-ответов, батчинг, retry, caching
- `Preview` (1 291 строка, 11 файлов, 12 дней) — quality gate, approve/edit/reject lifecycle
- `Dictionary` (921 строка, 7 файлов, 9 дней) — CRUD + import/export + per-batch filtering
- `Service` (1 281 строка, 6 файлов, 12 дней) — job coordination, target schema, inline correction
### Рекомендации по актуализации specks
- spec.md: статус → "Implemented", добавить секцию Architecture Notes
- plan.md: исправить file path (package vs single file), добавить недостающие модули
- contracts/modules.md: выровнять @COMPLEXITY с реальностью, добавить новые контракты
- quickstart.md: обновить примеры API на multi-language
- tasks.md: добавить closure summary с реальными метриками (72 файла, 29 128 строк)
- tasks.md: добавить closure summary с реальными метриками (148 файлов, 34 909 строк)
---
## Приложение A: Детальный breakdown по файлам (актуальная реализация)
> В ходе реализации выполнена масштабная декомпозиция. Крупные модули (Orchestrator, Preview, Executor, Dictionary, Service) разбиты на 212 файлов каждый.
> Общий объём кода изменился незначительно, но количество файлов выросло с ~31 до 75 (backend source) + 23 (frontend) + 27 (tests) = 125 файлов.
> В ходе дальнейшей разработки код был расширен: добавлены новые модули, расширены тесты.
> Общий объём кода: 74 файла backend source + 27 frontend source + 47 тестов = 148 файлов, ~34 909 строк.
### Бэкенд (75 файлов, ~13 187 строк source + ~8 487 строк тестов)
### Бэкенд (74 файла source + 39 файлов тестов, ~13 585 source + ~12 836 тестов)
#### Plugin core (57 файлов, 9 017 строк source)
#### Plugin core (59 файлов, 10 174 строк source)
**Orchestrator (12 файлов, 1 571 строка)**
**Orchestrator (14 файлов, 1 631 строка)**
| Файл | Строк | Назначение |
|------|:-----:|------------|
| `orchestrator.py` | 176 | Entry point / facade |
| `orchestrator_planner.py` | 128 | Run planning: target langs, batches |
| `orchestrator.py` | 175 | Entry point / facade |
| `orchestrator_planner.py` | 127 | Run planning: target langs, batches |
| `orchestrator_exec.py` | 121 | Translation execution coordinator |
| `orchestrator_sql.py` | 118 | SQL generation stage |
| `orchestrator_sql_rows.py` | 116 | Row fetch + pagination |
| `orchestrator_aggregator.py` | 138 | Results aggregation |
| `orchestrator_retry.py` | 137 | Retry logic for failed batches |
| `orchestrator_sql_rows.py` | 115 | Row fetch + pagination |
| `orchestrator_aggregator.py` | 139 | Results aggregation |
| `orchestrator_retry.py` | 136 | Retry logic for failed batches |
| `orchestrator_cancel.py` | 120 | Run cancellation |
| `orchestrator_validation.py` | 61 | Post-run validation |
| `orchestrator_run_completion.py` | 132 | Run finalization (status, error_message) |
| `orchestrator_run_completion.py` | 139 | Run finalization (status, error_message) |
| `orchestrator_runner.py` | 76 | Background task runner |
| `orchestrator_lang_stats.py` | 88 | Per-language statistics |
| `orchestrator_query.py` | 113 | Query builder / data source queries |
| `orchestrator_config.py` | 47 | Configuration merging |
| `orchestrator_lang_stats.py` | 87 | Per-language statistics |
| `orchestrator_query.py` | 148 | Query builder / data source queries |
| `orchestrator_config.py` | 69 | Configuration merging |
**Preview (12 файлов, 1 361 строка)**
**Preview (11 файлов, 1 291 строка)**
| Файл | Строк | Назначение |
|------|:-----:|------------|
| `preview.py` | 267 | Main facade: run, accept, reject |
| `preview.py` | 286 | Main facade: run, accept, reject |
| `preview_executor.py` | 149 | LLM call orchestration |
| `preview_llm_client.py` | 107 | Low-level LLM HTTP client |
| `preview_prompt_builder.py` | 133 | Prompt construction per language |
| `preview_prompt_helpers.py` | 113 | Prompt formatting utilities |
| `preview_response_parser.py` | 137 | Parse LLM responses |
| `preview_review.py` | 137 | Quality gate / approval logic |
| `preview_prompt_helpers.py` | 111 | Prompt formatting utilities |
| `preview_response_parser.py` | 158 | Parse LLM responses |
| `preview_review.py` | 136 | Quality gate / approval logic |
| `preview_session_ops.py` | 94 | Preview session persistence |
| `preview_session_serializer.py` | 101 | Session serialize/deserialize |
| `preview_token_estimator.py` | 51 | Token budget estimation |
| `preview_constants.py` | 48 | Constants / defaults |
| `preview_resolve_provider.py` | 24 | LLM provider resolution |
**Executor / Batch / LLM (10 файлов, 1 643 строки)**
**Executor / Batch / LLM (9 файлов, 2 196 строк)**
| Файл | Строк | Назначение |
|------|:-----:|------------|
| `executor.py` | 256 | Main facade: batch dispatch, caching |
| `_llm_call.py` | 272 | Centralized LLM call with retry + fallback |
| `_llm_http.py` | 187 | HTTP transport for LLM APIs |
| `_llm_parse.py` | 117 | Parse LLM streamed responses |
| `_batch_insert.py` | 233 | Insert results to Superset datasource |
| `_batch_proc.py` | 189 | Batch processing coordination |
| `_batch_sizer.py` | 223 | Dynamic batch sizing by token budget |
| `_run_service.py` | 176 | Run create/update/status queries |
| `executor.py` | 272 | Main facade: batch dispatch, caching |
| `_llm_call.py` | 540 | Centralized LLM call with retry + fallback |
| `_llm_parse.py` | 116 | Parse LLM streamed responses |
| `_llm_async_http.py` | 246 | Async HTTP transport for LLM APIs |
| `_batch_insert.py` | 246 | Insert results to Superset datasource |
| `_batch_proc.py` | 259 | Batch processing coordination |
| `_batch_sizer.py` | 201 | Dynamic batch sizing by token budget |
| `_run_service.py` | 175 | Run create/update/status queries |
| `_run_source.py` | 141 | Source row fetching + pagination |
**Dictionary (8 файлов, 904 строки)**
**Dictionary (7 файлов, 921 строка)**
| Файл | Строк | Назначение |
|------|:-----:|------------|
| `dictionary.py` | 68 | Facade / re-exports |
| `dictionary_crud.py` | 136 | Create, read, update entries |
| `dictionary_entries.py` | 164 | Entry query + filtering |
| `dictionary_filter.py` | 131 | Per-batch dynamic filter construction |
| `dictionary.py` | 63 | Facade / re-exports |
| `dictionary_crud.py` | 129 | Create, read, update entries |
| `dictionary_entries.py` | 184 | Entry query + filtering |
| `dictionary_filter.py` | 140 | Per-batch dynamic filter construction |
| `dictionary_correction.py` | 192 | Correction CRUD + batch apply |
| `dictionary_import_export.py` | 196 | CSV import/export |
| `dictionary_validation.py` | 17 | Entry validation rules |
**Service (5 файлов, 918 строк)**
**Service (6 файлов, 1 281 строка)**
| Файл | Строк | Назначение |
|------|:-----:|------------|
| `service.py` | 276 | Job CRUD + run coordination |
| `service_inline_correction.py` | 222 | Inline correction orchestration |
| `service.py` | 274 | Job CRUD + run coordination |
| `service_inline_correction.py` | 221 | Inline correction orchestration |
| `service_bulk_replace.py` | 189 | Bulk find-and-replace |
| `service_datasource.py` | 171 | Datasource metadata service |
| `service_utils.py` | 60 | Shared service utilities |
| `service_target_schema.py` | 355 | Target schema management |
| `service_utils.py` | 71 | Shared service utilities |
**Standalone modules (12 файлов, 2 620 строк)**
**Standalone modules (12 файлов, 2 854 строки)**
| Файл | Строк | Сложность | Назначение |
|------|:-----:|:---------:|------------|
| `scheduler.py` | 443 | C4 | Schedule CRUD + APScheduler dispatch |
| `superset_executor.py` | 420 | C3 | Superset SQL Lab API client |
| `sql_generator.py` | 378 | C3 | Dialect-aware SQL generation |
| `_token_budget.py` | 342 | C2 | Token estimation |
| `events.py` | 272 | C3 | Structured event log + pruning |
| `_utils.py` | 206 | C1 | Shared utilities |
| `scheduler.py` | 443 | C4 | Schedule CRUD + APScheduler dispatch |
| `superset_executor.py` | 439 | C3 | Superset SQL Lab API client |
| `sql_generator.py` | 402 | C3 | Dialect-aware SQL generation |
| `_token_budget.py` | 395 | C2 | Token estimation |
| `_lang_detect.py` | 207 | C2 | Language detection for SQL |
| `_utils.py` | 225 | C1 | Shared utilities |
| `events.py` | 274 | C3 | Structured event log + pruning |
| `metrics.py` | 192 | C2 | Metrics aggregation |
| `prompt_builder.py` | 153 | C3 | Context-aware prompt construction |
| `_text_cleaner.py` | 63 | C1 | Text sanitization utilities |
| `plugin.py` | 61 | C2 | Plugin skeleton |
| `__init__.py` | 2 | — | Package marker |
#### Routes (11 файлов, 2 141 строка)
#### Routes (13 файлов, 2 296 строк)
| Файл | Строк | Назначение |
|------|:-----:|------------|
| `__init__.py` | 40 | Package init + router registration |
| `__init__.py` | 42 | Package init + router registration |
| `_router.py` | 13 | APIRouter instance |
| `_job_routes.py` | 249 | Job CRUD endpoints |
| `_run_routes.py` | 554 | Run execution endpoints |
| `_run_list_routes.py` | 225 | Run list/detail/CSV |
| `_job_routes.py` | 285 | Job CRUD endpoints |
| `_run_routes.py` | 205 | Run execution endpoints |
| `_run_list_routes.py` | 359 | Run list/detail/CSV |
| `_run_edit_routes.py` | 200 | Run edit endpoints |
| `_run_history_routes.py` | 133 | Run history endpoints |
| `_preview_routes.py` | 194 | Preview endpoints |
| `_dictionary_routes.py` | 391 | Dictionary endpoints |
| `_correction_routes.py` | 100 | Correction endpoints |
| `_schedule_routes.py` | 239 | Schedule endpoints |
| `_metrics_routes.py` | 65 | Metrics endpoints |
| `_helpers.py` | 71 | Response helpers |
| `_helpers.py` | 70 | Response helpers |
#### Models + Schemas (2 файла, 1 085 строк)
#### Models + Schemas (2 файла, 1 113 строк)
| Файл | Строк | Назначение |
|------|:-----:|------------|
| `models/translate.py` | 397 | 15 ORM моделей |
| `schemas/translate.py` | 688 | 35+ Pydantic схем |
| `models/translate.py` | 401 | 15 ORM моделей |
| `schemas/translate.py` | 712 | 35+ Pydantic схем |
#### Миграции (5 файлов, ~944 строк)
#### Миграции (5 файлов, ~801 строка)
#### Тесты бэкенда
**Inline plugin tests (16 файлов, 6 029 строк)**
**Inline plugin tests (27 файлов, 9 090 строк)**
| Файл | Строк | Назначение |
|------|:-----:|------------|
| `test_orchestrator.py` | 880 | Orchestrator unit tests |
@@ -472,42 +483,64 @@ ss-tools предоставляет **готовую отлаженную инф
| `test_clickhouse_insert_integration.py` | 546 | CH insert integration |
| `test_scheduler.py` | 407 | Scheduler unit tests |
| `test_sql_generator.py` | 368 | SQL generation tests |
| `test_enforce_dictionary.py` | 168 | Dictionary enforcement tests |
| `test_batch_sizer.py` | 155 | Batch sizing tests |
| `test_target_schema.py` | 145 | Target schema tests |
| `test_dictionary_filter.py` | 228 | Dynamic filter tests |
| `test_dictionary_crud.py` | 218 | Dictionary CRUD tests |
| `test_token_budget.py` | 195 | Token estimation tests |
| `test_dictionary_import.py` | 177 | Import/export tests |
| `test_dictionary_correction.py` | 124 | Correction tests |
| `test_batch_classify_persist.py` | 143 | Batch classification tests |
| `test_dictionary_prompt_builder.py` | 111 | Prompt builder tests |
| `test_metrics_cumulative.py` | 98 | Metrics cumulative tests |
| `test_dict_snapshot_hash.py` | 76 | Dictionary hash tests |
| `test_lang_detect.py` | 67 | Language detection tests |
| `test_text_cleaner.py` | 48 | Text cleaner tests |
| `test_dialect_detection_orthogonal.py` | 42 | Dialect detection tests |
| `test_dictionary_utils.py` | 36 | Dictionary utility tests |
| `test_dictionary.py` | 20 | Dictionary facade tests |
**External integration tests (7 файлов, 2 458 строк)**
**External integration tests (10 файлов, 3 467 строк)**
| Файл | Строк | Назначение |
|------|:-----:|------------|
| `test_translate_jobs.py` | | API job lifecycle |
| `test_translate_scheduler.py` | — | Scheduler integration |
| `test_translate_scheduler_execution.py` | | Execution integration |
| `test_translate_scheduler_guard.py` | | Guard/validation |
| `test_translate_corrections.py` | — | Correction API |
| `test_translate_history.py` | — | History API |
| `test_translate_executor_filter.py` | — | Executor filter logic |
| `test_translate_jobs.py` | 563 | API job lifecycle |
| `test_translate_history.py` | 467 | History API |
| `test_translate_scheduler_execution.py` | 399 | Execution integration |
| `test_translate_scheduler_guard.py` | 298 | Guard/validation |
| `test_translate_executor_filter.py` | 289 | Executor filter logic |
| `test_translate_scheduler.py` | 195 | Scheduler integration |
| `test_translate_corrections.py` | 249 | Correction API |
| `test_core_scheduler.py` | 518 | Core scheduler tests |
| `core/test_async_regression.py` | 370 | Async regression tests |
| `test_alembic_migrations.py` | 119 | Migration tests |
### Фронтенд (23 файла source + 4 файла тестов, ~7 540 source + 575 тестов)
**Plugin external integration tests (2 файла, 279 строк)**
| Файл | Строк | Назначение |
|------|:-----:|------------|
| `test_llm_async.py` | 193 | LLM async integration tests |
| `test_async_concurrency.py` | 86 | Async concurrency tests |
#### Компоненты (10 файлов, 3 280 строк)
### Фронтенд (27 файлов source + 8 файлов тестов, ~7 241 source + ~1 247 тестов, включая e2e)
#### Компоненты (14 файлов, 3 451 строка)
| Файл | Строк | Назначение |
|------|:-----:|------------|
| `TranslationPreview.svelte` | 561 | Preview component (quality gate) |
| `TranslationRunResult.svelte` | 464 | Run result display |
| `BulkReplaceModal.svelte` | 396 | Find-and-replace modal |
| `RunTabContent.svelte` | 370 | Run tab content |
| `TargetTabForm.svelte` | 358 | Target language tab form |
| `TermCorrectionPopup.svelte` | 342 | Single correction popup |
| `CorrectionCell.svelte` | 326 | Inline editable cell |
| `TranslationRunProgress.svelte` | 310 | Live progress with retry |
| `ScheduleConfig.svelte` | 286 | Schedule editor |
| `BulkCorrectionSidebar.svelte` | 285 | Bulk correction panel |
| `ConfigTabForm.svelte` | 274 | Configuration tab form |
| `TranslationRunGlobalIndicator.svelte` | 198 | Global run indicator |
| `TranslationMetricsDashboard.svelte` | 184 | Metrics dashboard |
| `TargetSchemaHint.svelte` | 62 | Target schema hint tooltip |
#### Страницы (5 файлов, 3 354 строки)
@@ -519,16 +552,18 @@ ss-tools предоставляет **готовую отлаженную инф
| `dictionaries/+page.svelte` | 270 | Dictionary list |
| `+page.svelte` | 279 | Job list |
#### API client (6 файлов, 529 строк)
#### API client (7 файлов, 829 строк)
| Файл | Строк | Назначение |
|------|:-----:|------------|
| `translate.ts` | 382 | Main translate API client |
| `runs.js` | — | Run status/control API |
| `jobs.js` | — | Job CRUD API |
| `dictionaries.js` | — | Dictionary CRUD API |
| `corrections.js` | — | Correction API |
| `schedules.js` | — | Schedule API |
| `datasources.js` | — | Datasource API |
| `target-schema.ts` | 83 | Target schema API |
#### Store + i18n (2 файла, 377 строк)
@@ -537,13 +572,17 @@ ss-tools предоставляет **готовую отлаженную инф
| `translationRun.js` | 198 | Run state store |
| `i18n/index.ts` | 179 | en + ru translation keys |
#### Frontend-тесты (4 файла, 575 строк)
#### Frontend-тесты (8 файлов, 1 247 строк)
| Файл | Строк | Назначение |
|------|:-----:|------------|
| `test_bulk_replace_modal.svelte.js` | — | BulkReplace modal tests |
| `test_correction_cell.svelte.js` | — | CorrectionCell tests |
| `test_translation_preview.svelte.js` | 433 (все 3) | Preview component tests |
| `tests/TranslationJobModel.test.ts` | 354 | Job model tests |
| `tests/test_translation_preview.svelte.js` | 199 | Preview component tests |
| `tests/TargetSchemaHint.test.ts` | 158 | Target schema hint tests |
| `tests/test_correction_cell.svelte.js` | 136 | CorrectionCell tests |
| `tests/test-target-schema.test.ts` | 109 | Target schema API tests |
| `tests/test_bulk_replace_modal.svelte.js` | 97 | BulkReplace modal tests |
| `tests/TranslateHistoryModel.test.ts` | 52 | History model tests |
| `translation.e2e.js` | 142 | E2E: create run, check progress |
---

View File

@@ -1,15 +1,15 @@
# Implementation Plan: LLM Table Translation Service
**Branch**: `028-llm-datasource-supeset` | **Date**: 2026-05-08 | **Spec**: [spec.md](./spec.md)
**Branch**: `028-llm-datasource-supeset` (актуальная: `032-translate-requests-httpx`) | **Date**: 2026-05-08 (актуализация: 2026-06-07) | **Spec**: [spec.md](./spec.md)
**Input**: Feature specification from `/specs/028-llm-datasource-supeset/spec.md` (updated 2026-05-14 with multi-language & correction optimization)
## Summary
Implement an LLM-powered table translation service as a new backend plugin (`TranslationPlugin`) with companion API routes, ORM models, Pydantic schemas, and Svelte frontend components. The service reads rows from a Superset datasource (translation column + context columns), auto-detects source language per row via LLM, sends batches to a configured LLM provider for ALL target languages simultaneously (multi-target in single structured JSON response), with optional per-batch filtered multilingual terminology dictionary context (language-pair-aware). Generates safe PostgreSQL INSERT/UPSERT SQL, submits to Superset via `/api/v1/sqllab/execute/` with status polling. Supporting capabilities: multilingual terminology dictionaries (source_language + target_language per entry), configurable preview (1-100 rows), inline correction from any run result with dictionary submission, bulk find-and-replace, scheduled execution via APScheduler (new-key-only with baseline_expired fallback), structured event logging with per-language MetricSnapshot persistence, RBAC-gated access control, and 90-day retention with metric continuity.
**Total implemented**: 72 files, 29 128 LOC across backend (Python/FastAPI) and frontend (Svelte 5/SvelteKit).
**Total implemented**: ~153 files, ~36 091 LOC across backend (Python/FastAPI) and frontend (Svelte 5/SvelteKit).
**Actual complexity distribution**: 2× C5, 6× C4, 12× C3, 7× C2, 4× C1.
**Note**: Архитектура — service-based, не plugin-based. `TranslatePlugin` — только регистрационный скелет (C2). Бизнес-логика через независимые service-классы.
**Plugins**: 59 source files (decomposed) + 13 routes + 1 model + 1 schema + 27 frontend source + 47 test files.
## Technical Context
@@ -63,43 +63,47 @@ specs/028-llm-datasource-supeset/
backend/
├── src/
│ ├── api/routes/
│ │ └── translate/ # [ACTUAL] Пакет, а не один файл
│ │ └── translate/ # [ACTUAL] Пакет из 13 файлов (2 296 строк)
│ │ ├── __init__.py # Инициализация, re-export router
│ │ ├── _router.py # APIRouter(prefix="/api/translate")
│ │ ├── _job_routes.py # Job CRUD (249 строк)
│ │ ├── _run_routes.py # Run execution, cancel, inline edit (554 строки)
│ │ ├── _run_list_routes.py # Run list, detail, CSV download (225 строк)
│ │ ├── _job_routes.py # Job CRUD (285 строк)
│ │ ├── _run_routes.py # Run execution, cancel, inline edit (205 строк)
│ │ ├── _run_edit_routes.py # Run edit endpoints (200 строк) [NEW]
│ │ ├── _run_list_routes.py # Run list, detail, CSV (359 строк)
│ │ ├── _run_history_routes.py # Run history (133 строки) [NEW]
│ │ ├── _preview_routes.py # Preview CRUD (194 строки)
│ │ ├── _dictionary_routes.py # Dictionary CRUD + import (391 строка)
│ │ ├── _correction_routes.py # Correction submission (100 строк)
│ │ ├── _schedule_routes.py # Schedule CRUD (239 строк)
│ │ ├── _metrics_routes.py # Metrics endpoints (65 строк)
│ │ └── _helpers.py # Response helpers (71 строка)
│ │ └── _helpers.py # Response helpers (70 строк)
│ ├── core/
│ │ ├── scheduler.py # [REUSE] APScheduler
│ │ └── superset_client/ # [REUSE] Superset API client
│ ├── models/
│ │ └── translate.py # [NEW] 15 ORM models (397 строк)
│ │ └── translate.py # [NEW] 15 ORM models (401 строка)
│ ├── plugins/
│ │ └── translate/ # [NEW] TranslationPlugin
│ │ └── translate/ # [NEW] TranslationPlugin (59 файлов, декомпозирован)
│ │ ├── __init__.py # Package (2 строки)
│ │ ├── plugin.py # Plugin skeleton C2 (61 строка, регистрация)
│ │ ├── orchestrator.py # C5 Run lifecycle (1 137 строк) ⭐
│ │ ├── executor.py # C4 Batch LLM (1 974 строки) ⭐
│ │ ├── service.py # C4 TranslateJobService + InlineCorrection + BulkReplace (1 052 строки) ⭐
│ │ ├── preview.py # C4 Preview engine (1 303 строки) ⭐
│ │ ├── dictionary.py # C4 Dictionary CRUD + filtering (1 007 строк) ⭐
│ │ ├── scheduler.py # C4 Schedule management (436 строк)
│ │ ├── sql_generator.py # C3 Dialect-aware SQL (378 строк)
│ │ ├── superset_executor.py # C3 Superset SQL Lab API (420 строк) [NEW в реализации]
│ │ ├── prompt_builder.py # C3 Context-aware prompt (153 строки) [NEW]
│ │ ├── events.py # C5 Event log + pruning (272 строки)
│ │ ├── metrics.py # C3 Metrics aggregation (192 строки)
│ │ ├── _token_budget.py # C2 Token estimation (341 строка) [NEW]
│ │ ── _utils.py # C1 Normalization (33 строки) [NEW]
│ │ ── __tests__/ # Plugin-level unit tests (8 файлов, 5 645 строк)
│ │ ├── plugin.py # Plugin skeleton C2 (61 строка)
│ │ ├── orchestrator*.py # Orchestrator C5 (14 файлов, 1 631 строка) ⭐
│ │ ├── executor*.py # Executor/Batch/LLM C4 (9 файлов, 2 196 строк) ⭐
│ │ ├── preview*.py # Preview engine C4 (11 файлов, 1 291 строка) ⭐
│ │ ├── dictionary*.py # Dictionary CRUD C4 (7 файлов, 921 строка) ⭐
│ │ ├── service*.py # Service layer C4 (6 файлов, 1 281 строка) ⭐
│ │ ├── scheduler.py # Schedule management C4 (443 строки)
│ │ ├── sql_generator.py # Dialect-aware SQL C3 (402 строки)
│ │ ├── superset_executor.py # Superset SQL Lab API C3 (439 строк)
│ │ ├── events.py # Event log C5 (274 строки)
│ │ ├── metrics.py # Metrics C3 (192 строки)
│ │ ├── prompt_builder.py # Context-aware prompt C3 (153 строки)
│ │ ├── _token_budget.py # Token estimation C2 (395 строк)
│ │ ── _lang_detect.py # Language detection C2 (207 строк) [NEW]
│ │ ── _text_cleaner.py # Text sanitization C1 (63 строки) [NEW]
│ │ └── _utils.py # Utilities C1 (225 строк) [UPDATED]
│ │ └── __tests__/ # Plugin-level unit tests (27 файлов, 9 090 строк)
│ ├── schemas/
│ │ └── translate.py # [NEW] 35+ Pydantic schemas (688 строк)
│ │ └── translate.py # [NEW] 35+ Pydantic schemas (712 строк)
│ └── services/
│ ├── llm_provider.py # [REUSE] LLM provider management
│ └── llm_prompt_templates.py # [REUSE] Prompt rendering
@@ -109,35 +113,36 @@ frontend/
├── src/
│ ├── routes/
│ │ └── translate/ # [NEW] SvelteKit routes
│ │ ├── +page.svelte # Job list (279 строк)
│ │ ├── +page.svelte # Job list (288 строк)
│ │ ├── [id]/
│ │ │ └── +page.svelte # Job config + preview + run (1 363 строки) ⭐
│ │ │ └── +page.svelte # Job config + preview + run (269 строк)
│ │ ├── dictionaries/
│ │ │ ├── +page.svelte # Dictionary list (270 строк)
│ │ │ ├── +page.svelte # Dictionary list (247 строк)
│ │ │ └── [id]/
│ │ │ └── +page.svelte # Dictionary editor (821 строка)
│ │ │ └── +page.svelte # Dictionary editor (202 строки)
│ │ └── history/
│ │ └── +page.svelte # Run history (523 строки)
│ │ └── +page.svelte # Run history (231 строка)
│ └── lib/
│ ├── components/
│ │ └── translate/ # [NEW] Translation components (13 файлов)
│ │ ├── TranslationPreview.svelte # C4 (561 строка)
│ │ ├── TranslationRunResult.svelte # C4 (464 строки)
│ │ ├── BulkReplaceModal.svelte # C3 (396 строк) [NEW]
│ │ ├── TranslationRunProgress.svelte # C4 (310 строк)
│ │ ├── ScheduleConfig.svelte # C3 (286 строк)
│ │ ├── BulkCorrectionSidebar.svelte # C3 (285 строк)
│ │ ├── TermCorrectionPopup.svelte # C3 (342 строки)
│ │ ├── CorrectionCell.svelte # C3 (326 строк) [NEW]
│ │ ├── TranslationRunGlobalIndicator.svelte # C2 (198 строк) [NEW]
│ │ ├── TranslationMetricsDashboard.svelte # C2 (184 строки) [NEW]
│ │ ├── DictionaryEditor.svelte # C3 (на странице)
│ │ ── DictionaryList.svelte # C3 (на странице)
│ │ └── translate/ # [NEW] Translation components (14 файлов, 5 017 строк)
│ │ ├── TranslationPreview.svelte # C4 (564 строки)
│ │ ├── TranslationRunResult.svelte # C4 (618 строк)
│ │ ├── ConfigTabForm.svelte # C3 (539 строк) [NEW]
│ │ ├── BulkReplaceModal.svelte # C3 (438 строк)
│ │ ├── CorrectionCell.svelte # C3 (343 строки)
│ │ ├── RunTabContent.svelte # C3 (342 строки) [NEW]
│ │ ├── TermCorrectionPopup.svelte # C3 (345 строк)
│ │ ├── TargetSchemaHint.svelte # C2 (316 строк) [NEW]
│ │ ├── ScheduleConfig.svelte # C3 (300 строк)
│ │ ├── BulkCorrectionSidebar.svelte # C3 (288 строк)
│ │ ├── TranslationRunProgress.svelte # C4 (277 строк)
│ │ ── TargetTabForm.svelte # C3 (224 строки) [NEW]
│ │ ├── TranslationRunGlobalIndicator.svelte # C2 (237 строк)
│ │ └── TranslationMetricsDashboard.svelte # C2 (186 строк)
│ ├── stores/
│ │ ── translate.js # [NEW] rune store (196 строк) [NEW в реализации]
│ │ └── translationRun.js # [NEW] run progress store
│ │ ── translationRun.svelte.ts # [NEW] rune store (370 строк)
│ └── api/
│ └── translate.js # [NEW] API client (664 строки)
│ └── translate/ # [NEW] API client (8 файлов, 987 строк)
└── e2e/
└── tests/
└── translation.e2e.js # [NEW] E2E тесты (142 строки)
@@ -167,7 +172,7 @@ No constitutional violations detected. **UPDATED 2026-05-17**: Complexity ско
| `DictionaryManager` | C4 | **C4** ✅ | `dictionary.py` | CRUD + import + per-batch filtering |
| `TranslationScheduler` | C4 | **C4** ✅ | `scheduler.py` | APScheduler integration |
| `TranslateJobService` | — | **C4** [NEW] | `service.py` | Job CRUD + InlineCorrection + BulkReplace |
| `TranslateRoutes` | C3 | **C4** 🔴 | `__init__.py` | Пакет с 11 подмодулями |
| `TranslateRoutes` | C3 | **C4** 🔴 | `translate/` | Пакет с 13 подмодулями |
| `SQLGenerator` | C4 | **C3** 🟢 | `sql_generator.py` | Pure function, нет I/O |
| `SupersetSqlLabExecutor` | — | **C3** [NEW] | `superset_executor.py` | Superset SQL Lab API клиент |
| `ContextAwarePromptBuilder` | — | **C3** [NEW] | `prompt_builder.py` | Jaccard similarity, priority |
@@ -175,11 +180,15 @@ No constitutional violations detected. **UPDATED 2026-05-17**: Complexity ско
| `BulkFindReplaceService` | C4 | **C3** 🟢 | `service.py` | Regex, preview, atomic apply |
| `TranslationMetrics` | C3 | **C3** ✅ | `metrics.py` | Metrics aggregation |
| `TranslationModels` | C2 | **C2** ✅ | `models/translate.py` | 15 ORM models |
| `TranslateSchemas` | C2 | **C2** ✅ | `schemas/translate.py` | 35+ Pydantic schemas |
| `TranslateApiClient` | C2 | **C2** ✅ | `api/translate.js` | API client |
| `translateStore` | C3 | **C3** ✅ | `translationRun.js` | Svelte 5 rune store |
| `TranslateSchemas` | C2 | **C2** ✅ | `schemas/translate.py` | 35+ Pydantic schemas (712 строк) |
| `TranslateApiClient` | C2 | **C2** ✅ | `api/translate/` (пакет) | 8-модульный API client |
| `translateStore` | C3 | **C3** ✅ | `translationRun.svelte.ts` | Svelte 5 rune store (370 строк) |
| `TranslationLanguage` | C1 | **C1** ✅ | `models/translate.py` | DTO |
| `TranslationRunLanguageStats` | C1 | **C1** ✅ | `models/translate.py` | DTO |
| `CorrectionCell` (Svelte) | — | **C3** [NEW] | `CorrectionCell.svelte` | Inline edit + submit |
| `BulkReplaceModal` (Svelte) | — | **C3** [NEW] | `BulkReplaceModal.svelte` | Find & replace modal |
| Other Svelte components | C3 | **C3** ✅ | — | Все 10 компонентов |
| `ConfigTabForm` (Svelte) | | **C3** [NEW] | `ConfigTabForm.svelte` | Config form |
| `RunTabContent` (Svelte) | — | **C3** [NEW] | `RunTabContent.svelte` | Run tab |
| `TargetTabForm` (Svelte) | — | **C3** [NEW] | `TargetTabForm.svelte` | Target tab |
| `TargetSchemaHint` (Svelte) | — | **C2** [NEW] | `TargetSchemaHint.svelte` | Schema hint |
| Other Svelte components | C3 | **C3** ✅ | — | Все 14 компонентов |

View File

@@ -1,7 +1,7 @@
# Quickstart: LLM Table Translation Service
**Feature Branch**: `028-llm-datasource-supeset`
**Date**: 2026-05-08
**Feature Branch**: `028-llm-datasource-supeset` (актуальная: `032-translate-requests-httpx`)
**Date**: 2026-05-08 (updated 2026-06-07)
## Prerequisites
@@ -251,11 +251,11 @@ curl http://localhost:8001/api/translate/jobs/<job-id>/metrics \
cd backend
source .venv/bin/activate
# Unit tests for translation plugin (8 files)
# Unit tests for translation plugin (27 файлов в __tests__/)
pytest src/plugins/translate/__tests__/ -v
# Integration tests for translate API (7 files)
pytest tests/test_translate_jobs.py tests/test_translate_corrections.py tests/test_translate_history.py tests/test_translate_scheduler.py tests/test_translate_scheduler_execution.py tests/test_translate_scheduler_guard.py tests/test_translate_executor_filter.py -v
# Integration tests for translate API (10 файлов в tests/)
pytest tests/test_translate_jobs.py tests/test_translate_corrections.py tests/test_translate_history.py tests/test_translate_scheduler.py tests/test_translate_scheduler_execution.py tests/test_translate_scheduler_guard.py tests/test_translate_executor_filter.py tests/core/test_async_regression.py -v
# All backend tests
pytest -v

View File

@@ -1,7 +1,7 @@
# Research: LLM Table Translation Service
**Feature Branch**: `028-llm-datasource-supeset`
**Date**: 2026-05-08 (updated 2026-05-17 — post-implementation notes)
**Feature Branch**: `028-llm-datasource-supeset` (актуальная: `032-translate-requests-httpx`)
**Date**: 2026-05-08 (updated 2026-06-07 — post-implementation notes)
> **Post-implementation note**: Вопреки R1, реализация использует **service-based** архитектуру, а не plugin-based. `TranslatePlugin` (plugin.py) — регистрационный скелет C2 с `NotImplementedError`. Бизнес-логика через независимые service-классы: `TranslateJobService`, `TranslationOrchestrator`, `TranslationExecutor`, `TranslationPreview`, `DictionaryManager`.
> Это решение обеспечило лучшую тестируемость и позволило route-модулям вызывать сервисы напрямую, минуя `PluginBase.execute()`.

View File

@@ -1,10 +1,10 @@
# Feature Specification: LLM Table Translation Service
**Feature Branch**: `028-llm-datasource-supeset`
**Feature Branch**: `028-llm-datasource-supeset` (актуальная: `032-translate-requests-httpx`)
**Created**: 2026-05-08
**Status**: Implemented ✅
**Implementation complete**: 2026-05-14
**Total**: 134 tasks, 72 files, 29 128 LOC, 165/165 pytest, 280/281 vitest
**Implementation complete**: 2026-05-14 (актуализация: 2026-06-07)
**Total**: 134 tasks, ~153 files, ~36 091 LOC, ~503 pytest, ~65 vitest
**Input**: User description: "Я хочу добавить сервис llm перевода данных в таблицах. Пусть механизм использует datasource supeset для получения данных (строки для перевода + контекст), и insert values в материализованные таблы (можно выполнять в sqllab) для готовых строк. Обязательно нужно выбирать столбец для переводаб столбцы контекста, ключи (может быть несколько) по которым данные будут инсертится в таблу целевую."
## Implementation Notes (2026-05-17)
@@ -17,21 +17,29 @@
| Аспект | План | Реализация | Причина |
|--------|------|------------|---------|
| **Архитектура** | Plugin-based (`TranslatePlugin.execute()` — entry point) | **Service-based**: `TranslatePlugin` — скелет (C2, `NotImplementedError`), вся логика в сервисах | Плагин — регистрационный артефакт; бизнес-логика через независимые service-классы упрощает тестирование и позволяет routes напрямую вызывать оркестратор |
| **Файл роутера** | Единый `translate.py` | **Пакет** `translate/` с 13 подмодулями | Разделение на файлы по доменам (jobs, runs, preview, dictionary, correction, schedule, metrics) — ~2 141 строка в 11 файлах |
| **Файл роутера** | Единый `translate.py` | **Пакет** `translate/` с 13 подмодулями | Разделение на файлы по доменам (jobs, runs, preview, dictionary, correction, schedule, metrics, history, edit) — ~2 296 строк в 13 файлах |
| **PluginBase** | C3 | **C2** | Выполняет только регистрационную функцию в plugin_loader; execute() не используется |
### Модули, добавленные в реализацию (отсутствуют в плане)
- `_token_budget.py` — тикенизация и оценка стоимости (CJK-aware)
- `_utils.py` — нормализация терминов, эвристики
- `_lang_detect.py` — детекция языка из SQL/контекста [NEW]
- `_text_cleaner.py` — очистка текста перед переводом [NEW]
- `_llm_async_http.py` — асинхронный HTTP-транспорт для LLM API [NEW]
- `_helpers.py` — общие response-хелперы для route-модулей
- `prompt_builder.py` — ContextAwarePromptBuilder (Jaccard similarity, priority флаги)
- `superset_executor.py` — SupersetSqlLabExecutor (submit + poll)
- `service.py` — TranslateJobService, InlineCorrectionService, BulkFindReplaceService
- `service_target_schema.py` — управление target schema [NEW]
- `TranslationRunGlobalIndicator.svelte` — глобальный индикатор активного run
- `TranslationMetricsDashboard.svelte` — дашборд метрик
- `CorrectionCell.svelte` — inline-редактирование ячейки
- `BulkReplaceModal.svelte` — bulk find & replace modal
- `ConfigTabForm.svelte` — форма конфигурации джоба [NEW]
- `RunTabContent.svelte` — контент вкладки запуска [NEW]
- `TargetTabForm.svelte` — форма target-языков [NEW]
- `TargetSchemaHint.svelte` — подсказка по target schema [NEW]
- `translateStore.js` — Svelte 5 store для run progress
### Ключевые архитектурные решения (подтверждены реализацией)

View File

@@ -1,8 +1,9 @@
# Спецификация: Сервис LLM-перевода табличных данных
**Дата**: 2026-05-18
**Дата**: 2026-05-18 (актуализация: 2026-06-07)
**Назначение**: Передача сторонней команде для оценки трудозатрат
**Фокус**: только требования к конечному результату, без технологий
**Фокус**: только требования к конечному результату, без технологий
**Статус**: Implemented ✅ (~153 файла, ~36 091 строка кода)
---

View File

@@ -1,6 +1,6 @@
# Tasks: LLM Table Translation Service
**Feature Branch**: `028-llm-datasource-supeset`
**Feature Branch**: `028-llm-datasource-supeset` (актуальная: `032-translate-requests-httpx`)
**Input**: Design documents from `/specs/028-llm-datasource-supeset/`
**Prerequisites**: plan.md (required), spec.md (required for user stories), research.md, data-model.md, contracts/modules.md
@@ -467,7 +467,7 @@ After Migration (Phase 11a):
---
## ✅ Spec 028 Final Closure Summary (2026-05-17)
## ✅ Spec 028 Final Closure Summary (2026-06-07)
All 134 tasks complete. Spec 028 fully implemented.
@@ -475,113 +475,85 @@ All 134 tasks complete. Spec 028 fully implemented.
| Метрика | Значение |
|---------|----------|
| **Всего файлов** | **72** (бэкенд: 41, фронтенд: 19, конфиги/миграции: 12) |
| **Всего строк кода** | **29 128** |
| **Бэкенд Python** | ~15 777 строк (модули: 7 761, routes: 2 141, модели: 397, схемы: 688, миграции: 586, тесты: 8 103) |
| **Фронтенд Svelte/JS** | ~9 976 строк (компоненты: 3 971, страницы: 3 256, API+store: 860, i18n: 1 223, тесты: 575, E2E: 142) |
| **Backend tests** | 165 ✅ All pass |
| **Frontend tests** | 281 ✅ 280 pass (1 pre-existing unrelated) |
| **Всего файлов** | **~153** (бэкенд: 74 source + 41 test, фронтенд: 27 source + 8 test, миграции: 5) |
| **Всего строк кода** | **~36 091** |
| **Бэкенд Python** | ~26 421 строк (plugin source: 10 176, routes: 2 296, модели: 401, схемы: 712, миграции: 801, тесты: 12 836) |
| **Фронтенд Svelte/JS/TS** | ~8 488 строк (компоненты: 5 017, страницы: 1 237, API: 987, store: 370, тесты: 699, model tests: 406, E2E: 142) |
| **Backend tests** | ~503 pytest functions |
| **Frontend tests** | ~65 vitest functions |
| **Semantic audit** | 0 warnings |
| **User stories** | 10 (US1US10) |
| **ORM models** | 15 таблиц |
| **Pydantic schemas** | 35+ |
| **API endpoints** | ~30 REST |
| **RBAC permissions** | 13 |
| **Alembic migrations** | 4 |
| **Максимальный файл** | `executor.py` (1 974 строки) |
| **Самая сложная бизнес-логика** | orchestrator.py (C5, 1 137 строк), events.py (C5, 272 строки) |
| **Alembic migrations** | 5 |
| **Максимальный файл** | `_llm_call.py` (540 строк) |
| **Самая сложная бизнес-логика** | orchestrator (14 файлов, 1 631 строка, C5), events.py (274 строки, C5) |
### Архитектура (post-factum)
- **Архитектура**: Service-based (не plugin-based, как планировалось изначально)
- **Plugin.py**: C2 skeleton (только регистрация, execute() → NotImplementedError)
- **Routes**: Пакет из 11 файлов (не один translate.py, как в плане)
- **Routes**: Пакет из 13 файлов (не один translate.py, как в плане)
- **Plugin source**: 59 файлов (включая __init__.py) — полная декомпозиция orchestrator (14), executor (9), preview (11), dictionary (7), service (6), standalone (12)
- **Основные сервисы**: TranslateJobService, TranslationOrchestrator, TranslationExecutor, TranslationPreview, DictionaryManager, TranslationScheduler, TranslationEventLog
- **Новые модули (post-2026-05-17)**: _lang_detect.py, _text_cleaner.py, _llm_async_http.py, service_target_schema.py
### Структура файлов (полный инвентарь)
#### Backend modules (15 файлов, `backend/src/plugins/translate/`)
| Файл | Строк | C | Назначение |
|------|:-----:|:-:|------------|
| `__init__.py` | 2 | | Package init |
| `plugin.py` | 61 | C2 | Plugin skeleton (NotImplementedError) |
| `orchestrator.py` | 1 137 | C5 | Run lifecycle coordinator ⭐ |
| `executor.py` | 1 974 | C4 | Batch LLM + caching ⭐ |
| `service.py` | 1 052 | C4 | Job CRUD + InlineCorrection + BulkReplace |
| `preview.py` | 1 303 | C4 | Preview engine ⭐ |
| `dictionary.py` | 1 007 | C4 | Dictionary CRUD + import ⭐ |
| `scheduler.py` | 436 | C4 | Schedule CRUD |
| `sql_generator.py` | 378 | C3 | Dialect-aware SQL (pure function) |
| `superset_executor.py` | 420 | C3 | Superset SQL Lab API (submit + poll) |
| `prompt_builder.py` | 153 | C3 | Context-aware prompt (Jaccard) |
| `events.py` | 272 | C5 | Event log + MetricSnapshot pruning |
| `metrics.py` | 192 | C3 | Metrics aggregation |
| `_token_budget.py` | 341 | C2 | Token estimation |
| `_utils.py` | 33 | C1 | Term normalization |
#### Backend plugin source (59 файлов, `backend/src/plugins/translate/`, 10 176 строк)
| Группа | Файлов | Строк | C | Назначение |
|--------|:-----:|:-----:|:--:|------------|
| Orchestrator | 14 | 1 631 | C5 | Run lifecycle coordinator (декомпозирован) |
| Executor / LLM | 9 | 2 196 | C4 | Batch LLM + caching + async HTTP |
| Preview | 11 | 1 291 | C4 | Preview engine (декомпозирован) |
| Dictionary | 7 | 921 | C4 | CRUD + import + filter |
| Service | 6 | 1 281 | C4 | Job CRUD + InlineCorrection + BulkReplace + target_schema |
| Standalone | 12 | 2 854 | C2-C4 | Scheduler, SQL, SupersetExecutor, PromptBuilder, Events, Metrics, TokenBudget, Utils, LangDetect, TextCleaner |
#### Backend routes (11 файлов, `backend/src/api/routes/translate/`)
#### Backend routes (13 файлов, `backend/src/api/routes/translate/`, 2 296 строк)
| Файл | Строк | Назначение |
|------|:-----:|------------|
| `__init__.py` | 40 | Package init + re-export |
| `__init__.py` | 42 | Package init + re-export |
| `_router.py` | 13 | APIRouter instance |
| `_job_routes.py` | 249 | Job CRUD |
| `_run_routes.py` | 554 | Run execution, cancel, inline edit |
| `_run_list_routes.py` | 225 | Run list, detail, CSV |
| `_job_routes.py` | 285 | Job CRUD |
| `_run_routes.py` | 205 | Run execution, cancel, inline edit |
| `_run_list_routes.py` | 359 | Run list, detail, CSV |
| `_run_edit_routes.py` | 200 | Run edit endpoints [NEW] |
| `_run_history_routes.py` | 133 | Run history [NEW] |
| `_preview_routes.py` | 194 | Preview |
| `_dictionary_routes.py` | 391 | Dictionary CRUD + import |
| `_correction_routes.py` | 100 | Correction submission |
| `_schedule_routes.py` | 239 | Schedule CRUD |
| `_metrics_routes.py` | 65 | Metrics |
| `_helpers.py` | 71 | Response helpers |
| `_helpers.py` | 70 | Response helpers |
#### Backend models + schemas (2 файла)
| Файл | Строк | Назначение |
|------|:-----:|------------|
| `models/translate.py` | 397 | 15 ORM моделей |
| `schemas/translate.py` | 688 | 35+ Pydantic DTOs |
#### Backend tests (15 файлов, 8 103 строки)
| Файл | Строк | Назначение |
|------|:-----:|------------|
| `__tests__/test_orchestrator.py` | 847 | Full run lifecycle |
| `__tests__/test_executor.py` | 697 | Batch LLM processing |
| `__tests__/test_dictionary.py` | 1 199 | Dictionary CRUD + filter |
| `__tests__/test_preview.py` | 609 | Preview engine |
| `__tests__/test_scheduler.py` | 407 | Schedule CRUD |
| `__tests__/test_sql_generator.py` | 368 | Dialect SQL tests |
| `__tests__/test_token_budget.py` | 195 | Token estimation |
| `__tests__/test_inline_correction.py` | 792 | Correction + context |
| `__tests__/test_clickhouse_insert_integration.py` | 546 | ClickHouse SQL |
| `__tests__/test_orthogonal_fixes.py` | 582 | Regression |
| `tests/test_translate_jobs.py` | 562 | Job API integration |
| `tests/test_translate_corrections.py` | 249 | Correction API |
| `tests/test_translate_executor_filter.py` | 289 | Dictionary filter |
| `tests/test_translate_history.py` | 466 | History API |
| `tests/test_translate_scheduler.py` | 195 | Schedule integration |
| `tests/test_translate_scheduler_execution.py` | 399 | Schedule execution |
| `tests/test_translate_scheduler_guard.py` | 298 | Concurrency guard |
#### Frontend components (10 файлов, `frontend/src/lib/components/translate/`)
#### Frontend компоненты (14 файлов)
| Файл | Строк | C | Назначение |
|------|:-----:|:-:|------------|
| `TranslationPreview.svelte` | 561 | C4 | Preview table |
| `TranslationRunResult.svelte` | 464 | C4 | Run results |
| `BulkReplaceModal.svelte` | 396 | C3 | Find & replace |
| `TranslationRunProgress.svelte` | 310 | C4 | Live progress |
| `ScheduleConfig.svelte` | 286 | C3 | Schedule editor |
| `BulkCorrectionSidebar.svelte` | 285 | C3 | Bulk correction |
| `TermCorrectionPopup.svelte` | 342 | C3 | Correction popup |
| `CorrectionCell.svelte` | 326 | C3 | Inline edit cell |
| `TranslationRunGlobalIndicator.svelte` | 198 | C2 | Global run indicator |
| `TranslationMetricsDashboard.svelte` | 184 | C2 | Metrics dashboard |
| `TranslationPreview.svelte` | 564 | C4 | Preview table |
| `TranslationRunResult.svelte` | 618 | C4 | Run results |
| `ConfigTabForm.svelte` | 539 | C3 | Configuration form [NEW] |
| `BulkReplaceModal.svelte` | 438 | C3 | Find & replace |
| `CorrectionCell.svelte` | 343 | C3 | Inline edit cell |
| `RunTabContent.svelte` | 342 | C3 | Run tab content [NEW] |
| `TermCorrectionPopup.svelte` | 345 | C3 | Correction popup |
| `TargetSchemaHint.svelte` | 316 | C2 | Target schema hint [NEW] |
| `ScheduleConfig.svelte` | 300 | C3 | Schedule editor |
| `BulkCorrectionSidebar.svelte` | 288 | C3 | Bulk correction |
| `TranslationRunProgress.svelte` | 277 | C4 | Live progress |
| `TargetTabForm.svelte` | 224 | C3 | Target tab form [NEW] |
| `TranslationRunGlobalIndicator.svelte` | 237 | C2 | Global run indicator |
| `TranslationMetricsDashboard.svelte` | 186 | C2 | Metrics dashboard |
#### Frontend pages (5 файлов)
#### Frontend страницы (5 файлов, 1 237 строк)
| Файл | Строк | Назначение |
|------|:-----:|------------|
| `translate/+page.svelte` | 279 | Job list |
| `translate/[id]/+page.svelte` | 1 363 | Job config + run |
| `translate/history/+page.svelte` | 523 | Run history |
| `translate/dictionaries/+page.svelte` | 270 | Dictionary list |
| `translate/dictionaries/[id]/+page.svelte` | 821 | Dictionary editor |
| `translate/+page.svelte` | 288 | Job list |
| `translate/[id]/+page.svelte` | 269 | Job config + run |
| `translate/history/+page.svelte` | 231 | Run history |
| `translate/dictionaries/+page.svelte` | 247 | Dictionary list |
| `translate/dictionaries/[id]/+page.svelte` | 202 | Dictionary editor |
### Phase 11 Completion Details
- **Migration (T083-T086)**: Models, schemas, Alembic — done
@@ -596,23 +568,22 @@ All 134 tasks complete. Spec 028 fully implemented.
| Аспект | План | Реальность |
|--------|------|------------|
| Архитектура | Plugin-based | Service-based (plugin.py — скелет C2) |
| Routes | Один translate.py | Пакет из 11 файлов |
| Routes | Один translate.py | Пакет из 13 файлов (2 296 строк) |
| Plugin source | ~15 файлов | 59 файлов (полная декомпозиция: orchestrator 14, executor 9, preview 11, dictionary 7, service 6, standalone 12) |
| SQLGenerator | C4 | C3 (pure function, нет I/O) |
| TranslateRoutes | C3 | C4 (пакет 11 файлов, 6+ зависимостей) |
| InlineCorrectionService | C4 | C3 (без полноценных PRE/POST) |
| BulkFindReplaceService | C4 | C3 (без полноценных PRE/POST) |
| Новые модули | — | superset_executor.py, prompt_builder.py, service.py, _token_budget.py, _utils.py |
| Новые компоненты | — | CorrectionCell, BulkReplaceModal, TranslationRunGlobalIndicator, TranslationMetricsDashboard, translate.js store |
| TranslateRoutes | C3 | C4 (пакет 13 файлов, 6+ зависимостей) |
| Новые модули (post-05-17) | — | _lang_detect.py, _text_cleaner.py, _llm_async_http.py, service_target_schema.py |
| Новые компоненты (post-05-17) | | ConfigTabForm, RunTabContent, TargetTabForm, TargetSchemaHint |
| Frontend pages | ~3 256 строк | 1 237 строк (рефакторинг) |
### Verified
- Backend: pytest 165/165 pass
- Frontend: vitest 280/281 pass ✅ (1 pre-existing unrelated failure)
- Backend: ~503 pytest ✅
- Frontend: ~65 vitest
- Browser: validated — preview, correction, dictionary flows work
- Semantic audit: 0 warnings across all checks
### Remaining
- None. All 134 tasks are [x].
- 1 pre-existing unrelated vitest failure (not in translate module)
### Next Action
- `ready_for_review` — Spec 028 is complete, ready for merge to main

View File

@@ -1,8 +1,8 @@
# UX Reference: LLM Table Translation Service
**Feature Branch**: `028-llm-datasource-supeset`
**Feature Branch**: `028-llm-datasource-supeset` (актуальная: `032-translate-requests-httpx`)
**Created**: 2026-05-08
**Status**: Draft
**Status**: Implemented ✅
## 1. User Persona & Context