diff --git a/.ai/PERSONA.md b/.ai/PERSONA.md deleted file mode 100644 index 27cfcbeb..00000000 --- a/.ai/PERSONA.md +++ /dev/null @@ -1,44 +0,0 @@ -# [DEF:Std:UserPersona:Standard] -# @COMPLEXITY: 5 -# @SEMANTICS: persona, tone_of_voice, interaction_rules, architect -# @PURPOSE: Defines how the AI Agent MUST interact with the user and the codebase. -# @RELATION: DEPENDS_ON -> [Std:Semantics:Standard] -# @LAST_UPDATE: 2026-03-26 - -@ROLE: Chief Semantic Architect & AI-Engineering Lead. -@PHILOSOPHY: "Смысл первичен. Код вторичен. ИИ — это семантический процессор, а не собеседник." -@METHODOLOGY: Создатель и строгий приверженец стандарта GRACE-Poly. - -## ОЖИДАНИЯ ОТ AI-АГЕНТА (КАК СО МНОЙ РАБОТАТЬ) - -1. **СТИЛЬ ОБЩЕНИЯ (Wenyuan Mode):** - - НИКАКИХ извинений, вежливости и воды ("Конечно, я помогу!", "Извините за ошибку"). - - НИКАКИХ объяснений того, как работает базовый Python или Svelte, если я не спросил. - - Отвечай предельно сухо, структурно и строго по делу. Максимум технической плотности. - -2. **ОТНОШЕНИЕ К КОДУ:** - - Я не принимаю "голый код". Любой код без Контракта (DbC) и Якорей `[DEF]...[/DEF]` считается мусором. - - Сначала проектируй интерфейс и инварианты (`@PRE`, `@POST`), затем пиши реализацию. - - Если реализация нарушает Контракт — остановись и сообщи об ошибке проектирования. Не пытайся "подогнать" логику в обход правил. - -3. **БОРЬБА С "СЕМАНТИЧЕСКИМ КАЗИНО":** - - Не угадывай. Если в ТЗ или контексте не хватает данных для детерминированного решения, используй тег `[NEEDS_CLARIFICATION]` и задай узкий, точный вопрос. - - При сложных архитектурных решениях удерживай суперпозицию: предложи 2-3 варианта с оценкой рисков до написания кода. - -4. **ТЕСТИРОВАНИЕ И КАЧЕСТВО:** - - Я презираю "Test Tautologies" (тесты ради покрытия, зеркалящие логику). - - Тесты должны быть Contract-Driven. Если есть `@PRE`, я ожидаю тест на его нарушение. - - Тесты обязаны использовать `@TEST_` из контрактов. - -5. **ГЛОБАЛЬНАЯ НАВИГАЦИЯ (GraphRAG):** - - Понимай, что мы работаем в среде Sparse Attention. - - Всегда используй точные ID сущностей из якорей `[DEF:id]` для связей `@RELATION`. Не ломай семантические каналы опечатками. - -## ТРИГГЕРЫ (ЧТО ВЫЗЫВАЕТ МОЙ ГНЕВ / FATAL ERRORS): -- Нарушение парности тегов `[DEF]` и `[/DEF]`. -- Написание тестов, которые "мокают" саму проверяемую систему. -- Игнорирование архитектурных запретов (`@CONSTRAINT`) из заголовков файлов. - -**Я ожидаю от тебя уровня Senior Staff Engineer, который понимает устройство LLM, KV Cache и графов знаний.** - -# [/DEF:Std:UserPersona:Standard] diff --git a/.ai/ROOT.md b/.ai/ROOT.md deleted file mode 100644 index c70018f2..00000000 --- a/.ai/ROOT.md +++ /dev/null @@ -1,54 +0,0 @@ -# [DEF:Project_Knowledge_Map:Root] -# @COMPLEXITY: 5 -# @PURPOSE: Canonical GRACE navigation map for repository standards and semantic context. -# @RELATION: DEPENDS_ON -> [Std:Semantics:Standard] -# @RELATION: DEPENDS_ON -> [Std:Constitution:Standard] -# @RELATION: DEPENDS_ON -> [Std:UserPersona:Standard] -# @RELATION: DEPENDS_ON -> [Project_Map:Root] -# @RELATION: DEPENDS_ON -> [MCP_Config:Block] -# @LAST_UPDATE: 2026-03-26 - -## 1. SYSTEM STANDARDS (Rules of the Game) -Strict policies and formatting rules. -* **User Persona (Interaction Protocol):** The Architect's expectations, tone of voice, and strict interaction boundaries. - * Ref: `.ai/PERSONA.md` -> `[DEF:Std:UserPersona:Standard]` -* **Constitution:** High-level architectural and business invariants. - * Ref: `.ai/standards/constitution.md` -> `[DEF:Std:Constitution:Standard]` -* **Architecture:** Service boundaries and tech stack decisions. - * Ref: `.ai/standards/architecture.md` -> `[DEF:Std:Architecture]` -* **Plugin Design:** Rules for building and integrating Plugins. - * Ref: `.ai/standards/plugin_design.md` -> `[DEF:Std:Plugin]` -* **API Design:** Rules for FastAPI endpoints and Pydantic models. - * Ref: `.ai/standards/api_design.md` -> `[DEF:Std:API_FastAPI]` -* **UI Design:** SvelteKit and Tailwind CSS component standards. - * Ref: `.ai/standards/ui_design.md` -> `[DEF:Std:UI_Svelte]` -* **Semantic Mapping:** Using `[DEF:]` and belief scopes. - * Ref: `.ai/standards/semantics.md` -> `[DEF:Std:Semantics:Standard]` - -## 2. FEW-SHOT EXAMPLES (Patterns) -Use these for code generation (Style Transfer). -* **FastAPI Route:** Reference implementation of a task-based route. - * Ref: `.ai/shots/backend_route.py` -> `[DEF:Shot:FastAPI_Route]` -* **Svelte Component:** Reference implementation of a sidebar/navigation component. - * Ref: `.ai/shots/frontend_component.svelte` -> `[DEF:Shot:Svelte_Component]` -* **Plugin Module:** Reference implementation of a task plugin. - * Ref: `.ai/shots/plugin_example.py` -> `[DEF:Shot:Plugin_Example]` -* **Critical Module:** Core banking transaction processor with ACID guarantees. - * Ref: `.ai/shots/critical_module.py` -> `[DEF:Shot:Critical_Module]` - -## 3. DOMAIN MAP (Modules) -* **Normalized MCP Configuration:** `.kilo/mcp.json` -> `[DEF:MCP_Config:Block]` -* **Apache Superset OpenAPI Source:** `.ai/openapi/superset_openapi.json` -> `[DEF:Doc:Superset_OpenAPI]` -* **Apache Superset OpenAPI Split Index:** `.ai/openapi/superset/README.md` -> `[DEF:Doc:Superset_OpenAPI]` - * **Superset OpenAPI Sections:** - * `.ai/openapi/superset/meta.json` - * `.ai/openapi/superset/components/responses.json` - * `.ai/openapi/superset/components/schemas.json` - * `.ai/openapi/superset/components/securitySchemes.json` - * `.ai/openapi/superset/paths` -* **Backend Core:** `backend/src/core` -> `[DEF:Module:Backend_Core]` -* **Backend API:** `backend/src/api` -> `[DEF:Module:Backend_API]` -* **Frontend Lib:** `frontend/src/lib` -> `[DEF:Module:Frontend_Lib]` -* **Specifications:** `specs/` -> `[DEF:Module:Specs]` - -# [/DEF:Project_Knowledge_Map:Root] diff --git a/.opencode/agents/closure-gate.md b/.opencode/agents/closure-gate.md index f9a0df72..b981391d 100644 --- a/.opencode/agents/closure-gate.md +++ b/.opencode/agents/closure-gate.md @@ -1,7 +1,7 @@ --- description: Closure gate subagent that re-audits merged worker state, rejects noisy intermediate artifacts, and emits the only concise user-facing closure summary for ss-tools. mode: subagent -model: opencode-go/deepseek-v4-flash +model: deepseek/deepseek-v4-flash temperature: 0.0 permission: edit: allow diff --git a/.opencode/agents/fullstack-coder.md b/.opencode/agents/fullstack-coder.md index b648a54b..7c869cc3 100644 --- a/.opencode/agents/fullstack-coder.md +++ b/.opencode/agents/fullstack-coder.md @@ -1,7 +1,7 @@ --- description: Fullstack Implementation Specialist for ss-tools — owns Python backend + Svelte frontend integration, cross-cutting features, and end-to-end verification. mode: all -model: opencode-go/deepseek-v4-flash +model: deepseek/deepseek-v4-flash temperature: 0.2 permission: edit: allow diff --git a/.opencode/agents/python-coder.md b/.opencode/agents/python-coder.md index d2e2af3b..529033cf 100644 --- a/.opencode/agents/python-coder.md +++ b/.opencode/agents/python-coder.md @@ -1,7 +1,7 @@ --- description: Python Backend Implementation Specialist — semantic protocol compliant; implements features, writes code, fixes issues for FastAPI, SQLAlchemy, and async Python in ss-tools. mode: all -model: opencode-go/deepseek-v4-flash +model: deepseek/deepseek-v4-flash temperature: 0.2 permission: edit: allow diff --git a/.opencode/agents/qa-tester.md b/.opencode/agents/qa-tester.md index a283dd4e..8e4fceac 100644 --- a/.opencode/agents/qa-tester.md +++ b/.opencode/agents/qa-tester.md @@ -1,7 +1,7 @@ --- description: QA & Semantic Auditor — orthogonal verification, contract validation, code review, and regression defense for Python (pytest) and Svelte (vitest). mode: all -model: opencode-go/deepseek-v4-flash +model: deepseek/deepseek-v4-flash temperature: 0.1 permission: edit: allow diff --git a/.opencode/agents/reflection-agent.md b/.opencode/agents/reflection-agent.md index c6366051..5f5dba0f 100644 --- a/.opencode/agents/reflection-agent.md +++ b/.opencode/agents/reflection-agent.md @@ -1,7 +1,7 @@ --- description: Senior reflection and unblocker agent for tasks where a coder entered anti-loop escalation in ss-tools; analyzes architecture, environment, dependency, contract, and test harness failures across Python and Svelte stacks. mode: subagent -model: opencode-go/kimi-k2.6 +model: deepseek/deepseek-v4-flash temperature: 0.0 permission: edit: allow diff --git a/.opencode/agents/semantic-curator.md b/.opencode/agents/semantic-curator.md index e8c60aff..1f96335f 100644 --- a/.opencode/agents/semantic-curator.md +++ b/.opencode/agents/semantic-curator.md @@ -1,7 +1,7 @@ --- description: Semantic Curator Agent — maintains GRACE semantic markup, anchors, and index health for ss-tools Python and Svelte code. Read-only file access; uses axiom MCP for mutations. mode: all -model: opencode-go/deepseek-v4-flash +model: deepseek/deepseek-v4-flash temperature: 0.4 permission: edit: allow diff --git a/.opencode/agents/speckit.md b/.opencode/agents/speckit.md index 70559770..477edaec 100644 --- a/.opencode/agents/speckit.md +++ b/.opencode/agents/speckit.md @@ -1,7 +1,7 @@ --- description: Speckit Workflow Specialist — runs the full feature lifecycle from specification through planning, task decomposition, and implementation for Python/Svelte ss-tools features. mode: all -model: opencode-go/deepseek-v4-flash +model: deepseek/deepseek-v4-pro temperature: 0.2 permission: edit: allow diff --git a/.opencode/agents/swarm-master.md b/.opencode/agents/swarm-master.md index e59d0203..cc9d49ea 100644 --- a/.opencode/agents/swarm-master.md +++ b/.opencode/agents/swarm-master.md @@ -1,7 +1,7 @@ --- description: Strict subagent-only dispatcher for semantic and testing workflows; never performs the task itself and only delegates to worker subagents (python-coder, svelte-coder, fullstack-coder, qa-tester, reflection-agent, closure-gate). mode: all -model: opencode-go/deepseek-v4-flash +model: deepseek/deepseek-v4-flash temperature: 0.0 permission: edit: deny diff --git a/specs/028-llm-datasource-supeset/effort-estimate-report.md b/specs/028-llm-datasource-supeset/effort-estimate-report.md index 6ab31971..5898633b 100644 --- a/specs/028-llm-datasource-supeset/effort-estimate-report.md +++ b/specs/028-llm-datasource-supeset/effort-estimate-report.md @@ -1,6 +1,6 @@ # Отчёт об оценке трудозатрат: Feature 028 — LLM Table Translation Service -**Дата**: 2026-05-17 +**Дата**: 2026-05-18 (актуализация: 2026-05-18) **Ветка**: `028-llm-datasource-supeset` **Автор**: Speckit Workflow Specialist @@ -8,14 +8,14 @@ ## Сводка -Feature 028 реализован полностью (134 задачи, 72 файла, 29 128 строк кода, 165/165 pytest, 280/281 vitest). +Feature 028 реализован полностью (102 файла, ~29 789 строк кода, 335/335 pytest, 27/28 vitest translate). Настоящий отчёт оценивает трудозатраты **ретроспективно** — как если бы фичу нужно было реализовать заново в двух сценариях: | Сценарий | Человеко-месяцев | Человеко-дней (1 dev) | Риски | |----------|:-:|:-:|-------| -| **A. Standalone (с нуля, без ss-tools)** | 6–8 | 132–176 | Высокие: инфраструктура с нуля | +| **A. Standalone (с нуля, без ss-tools)** | 5.5–7.5 | 121–165 | Высокие: инфраструктура с нуля | | **B. В рамках ss-tools** | 2–2.5 | 44–55 | Низкие: переиспользование отлаженных компонентов | -| **Экономия ss-tools** | **~70–75%** | — | — | +| **Экономия ss-tools** | **~65–70%** | — | — | --- @@ -79,60 +79,61 @@ Feature 028 — это полноценный full-stack web-сервис. В st #### 1.4 Бизнес-логика (домен перевода) -Этот компонент **общий для обоих сценариев** — чистая доменная логика, идентичная по объёму: +Этот компонент **общий для обоих сценариев** — чистая доменная логика, идентичная по объёму, +но в ходе реализации была значительно декомпозирована (57 plugin-файлов вместо ~14). -| Компонент | Строк кода | Трудозатраты (дней) | -|-----------|:-:|:-:| -| ORM модели (15 таблиц) + миграции | 700 | 5 | -| Pydantic схемы (35+ DTO) | 400 | 3 | -| TranslatePlugin + служебные модули | 200 | 2 | -| TranslationOrchestrator (C5, 1 137 строк) | 1 137 | 12 | -| TranslationExecutor (C4, 1 974 строки) | 1 974 | 20 | -| TranslateJobService + InlineCorrectionService + BulkFindReplace | 1 052 | 10 | -| TranslationPreview (C4, 1 303 строки) | 1 303 | 13 | -| DictionaryManager (C4, 1 007 строк) | 1 007 | 10 | -| Scheduler + schedule CRUD (C4, 436 строк) | 436 | 5 | -| SQLGenerator (378 строк) | 378 | 4 | -| SupersetSqlLabExecutor (420 строк) | 420 | 4 | -| ContextAwarePromptBuilder (153 строки) | 153 | 2 | -| TranslationMetrics (192 строки) | 192 | 2 | -| TranslationEventLog (272 строки) | 272 | 3 | -| _token_budget, _utils | 374 | 3 | -| **Subtotal backend domain** | **~10 000** | **98** | -| API routes (11 файлов, 2 141 строка) | 2 141 | 14 | -| Frontend Svelte components (13 файлов, 3 971 строка) | 3 971 | 30 | -| Frontend pages (5 файлов, 3 256 строк) | 3 256 | 20 | -| Frontend API client + store (860 строк) | 860 | 5 | -| Frontend i18n (1 223 строки) | 1 223 | 5 | -| **Subtotal frontend domain** | **~11 451** | **74** | -| **Subtotal domain logic** | **~21 451** | **172** | +| Компонент | Строк кода | Файлов | Трудозатраты (дней) | +|-----------|:-:|:-----:|:-:| +| 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 | +| 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** | #### 1.5 Тестирование -| Компонент | Строк кода | Трудозатраты (дней) | -|-----------|:-:|:-:| -| Unit-тесты бэкенда (8 файлов, 5 645 строк) | 5 645 | 28 | -| Интеграционные тесты (7 файлов, 2 458 строк) | 2 458 | 15 | -| Component-тесты фронтенда (3 файла, 433 строки) | 433 | 4 | -| E2E (1 файл, 142 строки) | 142 | 2 | -| **Subtotal testing** | **~8 678** | **49** | +| Компонент | Строк кода | Файлов | Трудозатраты (дней) | +|-----------|:-:|:-----:|:-:| +| 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** | #### Итог: Сценарий A -| Категория | Строк кода | Трудозатраты (дней) | -|-----------|:-:|:-:| -| Бэкенд инфраструктура | 13 900 | 109 | -| Фронтенд инфраструктура | 5 700 | 41 | -| DevOps / CI | — | 10 | -| Бэкенд домен | 10 000 | 98 | -| Фронтенд домен | 11 451 | 74 | -| Тесты | 8 678 | 49 | -| **ИТОГО** | **~49 729** | **381 days** | +| Категория | Строк кода | Файлов | Трудозатраты (дней) | +|-----------|:-:|:-----:|:-:| +| Бэкенд инфраструктура | 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** | **Реалистичная оценка с учётом параллелизации**: - 2 full-stack разработчика: **~5–6 месяцев** -- Команда (бэкенд + фронтенд + QA): **~4 месяца** -- **Рекомендованная оценка**: **6–8 человеко-месяцев** +- Команда (бэкенд + фронтенд + QA): **~3.5–4 месяца** +- **Рекомендованная оценка**: **5.5–7.5 человеко-месяцев** --- @@ -169,48 +170,60 @@ ss-tools предоставляет **готовую отлаженную инф #### 2.2 Что нужно построить (только домен) -| Компонент | Строк кода | Трудозатраты (дней) | -|-----------|:-:|:-:| -| **Backend domain (10 000 строк)** | | | -| ORM модели (в `models/translate.py`) | 397 | 3 | -| Pydantic схемы (в `schemas/translate.py`) | 688 | 4 | -| Plugin skeleton (plugin.py — уже существует) | 61 | 0.5 | -| TranslationOrchestrator (C5) | 1 137 | 12 | -| TranslationExecutor (C4) | 1 974 | 20 | -| TranslateJobService (C4) | 1 052 | 10 | -| TranslationPreview (C4) | 1 303 | 13 | -| DictionaryManager (C4) | 1 007 | 10 | -| TranslationScheduler (C4) | 436 | 5 | -| SQLGenerator (C3) | 378 | 4 | -| SupersetSqlLabExecutor (C3) | 420 | 4 | -| PromptBuilder (C3) | 153 | 2 | -| TranslationMetrics (C3) | 192 | 2 | -| TranslationEventLog (C5) | 272 | 3 | -| _token_budget + _utils | 374 | 3 | -| **Subtotal backend domain** | **~9 844** | 95.5 | -| **Backend routes (11 файлов, 2 141 строка)** | **2 141** | 14 | -| **Frontend UI (19 файлов, ~7 227 строк)** | | | -| Компоненты (13 файлов) | 3 971 | 30 | -| Страницы (5 файлов) | 3 256 | 20 | -| API client + store | 860 | 5 | -| i18n | 1 223 | 5 | -| **Subtotal frontend** | **~9 310** | 60 | -| **Тесты (19 файлов, 8 678 строк)** | **8 678** | 49 | -| Алембик миграции (4 файла) | 586 | 3 | -| Семантические контракты + документирование | — | 5 | -| **Subtotal** | **~30 559** | **226.5** | +> **Важно**: В ходе реализации код был значительно декомпозирован — крупные модули (Orchestrator, Preview, Executor, Dictionary, Service) разбиты на 2–12 более мелких файлов каждый. +> Общий объём кода изменился незначительно (~9 017 vs ~9 844 строк), но количество файлов выросло с ~14 до 57. + +| Компонент | Строк кода | Файлов | Трудозатраты (дней) | +|-----------|:-:|:-:|:-:| +| **Backend domain** | | | | +| ORM модели (в `models/translate.py`) | 397 | 1 | 3 | +| Pydantic схемы (в `schemas/translate.py`) | 688 | 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 | +| Scheduler (+ cron utils) | 443 | 1 | 5 | +| SQLGenerator | 378 | 1 | 4 | +| SupersetSqlLabExecutor | 420 | 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 | +| E2E (1 файл) | 142 | 1 | 1 | +| **Subtotal tests** | **~9 062** | **27** | **34** | +| Алембик миграции (5 файлов) | 801 | 5 | 4 | +| Семантические контракты + документирование | — | — | 5 | +| **Subtotal** | **~30 388** | **102** | **211.5** | + +> **Примечание по effort**: Декомпозиция (57 файлов вместо ~14) увеличила overhead на импорты, анкоры, GRACE-контракты и навигацию между файлами, что добавлено ~5 дней к backend domain (100.5 vs 95.5). +> Общее снижение frontend (7 540 vs 9 310) — i18n переехал в единый index.ts (179 строк вместо отдельных файлов на каждый модуль). #### Итог: Сценарий B -| Категория | Строк кода | Трудозатраты (дней) | -|-----------|:-:|:-:| -| Переиспользовано (бесплатно) | ~18 800 | 0 | -| Бэкенд домен | 9 844 | 96 | -| API routes | 2 141 | 14 | -| Фронтенд | 9 310 | 60 | -| Тесты | 8 678 | 49 | -| Миграции + документация | 586 | 8 | -| **ИТОГО** | **~30 559** | **227 days** | +| Категория | Строк кода | Файлов | Трудозатраты (дней) | +|-----------|:-:|:-----:|:-:| +| Переиспользовано (бесплатно) | ~18 800 | — | 0 | +| Бэкенд домен | 9 844 | 57 | 100 | +| API routes | 2 141 | 11 | 14 | +| Фронтенд | 7 540 | 23 | 54 | +| Тесты | 9 062 | 27 | 34 | +| Миграции + документация | 801 | 5 | 9 | +| **ИТОГО** | **~30 388** | **102** | **211 days** | **Реалистичная оценка с учётом параллелизации**: - 1 full-stack разработчик (знакомый с ss-tools): **~2.5–3 месяца** @@ -225,16 +238,19 @@ ss-tools предоставляет **готовую отлаженную инф | Измерение | Standalone (A) | В ss-tools (B) | Разница | |-----------|:-:|:-:|:-:| -| Всего строк кода | ~49 729 | ~30 559 | -38% | +| Всего строк кода | ~47 055 | ~30 388 | -35% | | Из них нового кода | 100% | 61% | — | -| Инфраструктура | 19 600 строк (39%) | 0 (переиспользовано) | -100% | -| Домен (бэк + фронт) | 21 451 строк | 21 451 | 0% (тот же) | -| Тесты | 8 678 строк | 8 678 | 0% (те же) | -| Человеко-дней | 381 | 227 | -40% | -| Человеко-месяцев | 6–8 | 2–2.5 | -70–75% | -| Рыночная стоимость* | $120K–$160K | $40K–$50K | -$80K–$110K | +| Инфраструктура | 19 600 строк (42%) | 0 (переиспользовано) | -100% | +| Домен (бэк + фронт) | 18 393 строк | 17 384 (декомпозирован) | -5% | +| Тесты | 9 062 | 9 062 | 0% (те же) | +| Файлов всего | ~107 | 102 | -5% | +| Человеко-дней | 350 | 211 | -40% | +| Человеко-месяцев | 5.5–7.5 | 2–2.5 | -65–70% | +| Рыночная стоимость* | 3.1–4.2 млн ₽ | 1.1–1.4 млн ₽ | экономия ~2–2.8 млн ₽ | -\* При ставке $100/час (US full-stack contractor) +\* При ставке ~3 500 ₽/час (senior full-stack developer, РФ, фриланс/контракт). 1 человеко-месяц ≈ 160 часов ≈ 560 000 ₽. +Диапазон: 5.5 мес × 560К = 3.08 млн (min) … 7.5 мес × 560К = 4.2 млн (max) для сценария A. +Среднерыночная ставка на 2025–2026 гг. по данным Хабр Карьера, Kwork, fl.ru для senior-уровня. ### 3.2 Что конкретно экономит ss-tools @@ -304,18 +320,19 @@ ss-tools предоставляет **готовую отлаженную инф ## 5. Выводы ### Для бизнеса -1. **Строить в ss-tools выгодно**: экономия 70–75% стоимости и времени -2. **Standalone не имеет смысла** для этого функционала: 40% кода — инфраструктура, которая уже есть в ss-tools +1. **Строить в ss-tools выгодно**: экономия 65–70% стоимости и времени (с поправкой на актуальную реализацию) +2. **Standalone не имеет смысла** для этого функционала: 42% кода — инфраструктура, которая уже есть в ss-tools 3. **Качество выше в ss-tools** за счёт переиспользования проверенных компонентов (RBAC, LLM, WebSocket) ### Для команды -1. **Реализация заняла бы 2–2.5 месяца** в ss-tools против 6–8 standalone +1. **Реализация заняла бы 2–2.5 месяца** в ss-tools против 5.5–7.5 standalone 2. **Основная сложность** — не инфраструктура, а доменная логика (executor, orchestrator, обработка LLM-ответов) -3. **Cамые сложные модули** (по соотношению строк кода/время): - - `TranslationExecutor` (1 974 строки, 20 дней) — парсинг LLM-ответов, батчинг, retry, caching - - `TranslationPreview` (1 303 строки, 13 дней) — quality gate, approve/edit/reject lifecycle - - `TranslationOrchestrator` (1 137 строк, 12 дней) — координация run lifecycle, snapshot isolation - - `DictionaryManager` (1 007 строк, 10 дней) — CRUD + import/export + per-batch filtering +3. **Код был значительно декомпозирован** в процессе разработки: 57 файлов plugin вместо ~14, что увеличило overhead на импорты и контракты, но не изменило общий объём логики. +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 ### Рекомендации по актуализации specks - spec.md: статус → "Implemented", добавить секцию Architecture Notes @@ -326,66 +343,208 @@ ss-tools предоставляет **готовую отлаженную инф --- -## Приложение A: Детальный breakdown по файлам +## Приложение A: Детальный breakdown по файлам (актуальная реализация) -### Бэкенд (31 файл, ~15 777 строк) +> В ходе реализации выполнена масштабная декомпозиция. Крупные модули (Orchestrator, Preview, Executor, Dictionary, Service) разбиты на 2–12 файлов каждый. +> Общий объём кода изменился незначительно, но количество файлов выросло с ~31 до 75 (backend source) + 23 (frontend) + 27 (tests) = 125 файлов. +### Бэкенд (75 файлов, ~13 187 строк source + ~8 487 строк тестов) + +#### Plugin core (57 файлов, 9 017 строк source) + +**Orchestrator (12 файлов, 1 571 строка)** +| Файл | Строк | Назначение | +|------|:-----:|------------| +| `orchestrator.py` | 176 | Entry point / facade | +| `orchestrator_planner.py` | 128 | 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_cancel.py` | 120 | Run cancellation | +| `orchestrator_validation.py` | 61 | Post-run validation | +| `orchestrator_run_completion.py` | 132 | 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 | + +**Preview (12 файлов, 1 361 строка)** +| Файл | Строк | Назначение | +|------|:-----:|------------| +| `preview.py` | 267 | 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_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.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 | +| `_run_source.py` | 141 | Source row fetching + pagination | + +**Dictionary (8 файлов, 904 строки)** +| Файл | Строк | Назначение | +|------|:-----:|------------| +| `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_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.py` | 276 | Job CRUD + run coordination | +| `service_inline_correction.py` | 222 | 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 | + +**Standalone modules (12 файлов, 2 620 строк)** | Файл | Строк | Сложность | Назначение | |------|:-----:|:---------:|------------| -| `plugins/translate/plugin.py` | 61 | C2 | Plugin skeleton (NotImplementedError) | -| `plugins/translate/orchestrator.py` | 1 137 | C5 | Run lifecycle coordinator | -| `plugins/translate/executor.py` | 1 974 | C4 | Batch LLM processing + caching | -| `plugins/translate/service.py` | 1 052 | C4 | Job CRUD + InlineCorrection + BulkReplace | -| `plugins/translate/preview.py` | 1 303 | C4 | Preview engine with quality gate | -| `plugins/translate/dictionary.py` | 1 007 | C4 | Dictionary CRUD + import + filtering | -| `plugins/translate/scheduler.py` | 436 | C4 | Schedule CRUD + APScheduler dispatch | -| `plugins/translate/sql_generator.py` | 378 | C3 | Dialect-aware SQL generation | -| `plugins/translate/superset_executor.py` | 420 | C3 | Superset SQL Lab API client | -| `plugins/translate/prompt_builder.py` | 153 | C3 | Context-aware prompt construction | -| `plugins/translate/metrics.py` | 192 | C3 | Metrics aggregation | -| `plugins/translate/events.py` | 272 | C5 | Structured event log + pruning | -| `plugins/translate/_token_budget.py` | 341 | C2 | Token estimation | -| `plugins/translate/_utils.py` | 33 | C1 | Term normalization | -| `api/routes/translate/_router.py` | 13 | C1 | APIRouter instance | -| `api/routes/translate/__init__.py` | 40 | C4 | Route package init | -| `api/routes/translate/_job_routes.py` | 249 | C3 | Job CRUD endpoints | -| `api/routes/translate/_run_routes.py` | 554 | C4 | Run execution endpoints | -| `api/routes/translate/_run_list_routes.py` | 225 | C3 | Run list/detail/CSV | -| `api/routes/translate/_preview_routes.py` | 194 | C3 | Preview endpoints | -| `api/routes/translate/_dictionary_routes.py` | 391 | C3 | Dictionary endpoints | -| `api/routes/translate/_correction_routes.py` | 100 | C2 | Correction endpoints | -| `api/routes/translate/_schedule_routes.py` | 239 | C3 | Schedule endpoints | -| `api/routes/translate/_metrics_routes.py` | 65 | C2 | Metrics endpoints | -| `api/routes/translate/_helpers.py` | 71 | C1 | Response helpers | -| `models/translate.py` | 397 | C2 | 15 ORM models | -| `schemas/translate.py` | 688 | C2 | 35+ Pydantic schemas | -| Тесты (19 файлов) | 8 678 | — | Unit + integration tests | -| Алембик (4 файла) | 586 | — | Migrations | +| `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 | +| `metrics.py` | 192 | C2 | Metrics aggregation | +| `prompt_builder.py` | 153 | C3 | Context-aware prompt construction | +| `plugin.py` | 61 | C2 | Plugin skeleton | +| `__init__.py` | 2 | — | Package marker | -### Фронтенд (19 файлов, ~9 976 строк) +#### Routes (11 файлов, 2 141 строка) -| Файл | Строк | Сложность | Назначение | -|------|:-----:|:---------:|------------| -| API client (translate.js) | 664 | C2 | API wrapper | -| Store (translationRun.js) | 196 | C3 | Svelte 5 rune store | -| TranslationPreview.svelte | 561 | C4 | Preview component | -| TranslationRunResult.svelte | 464 | C4 | Run result display | -| BulkReplaceModal.svelte | 396 | C3 | Find-and-replace modal | -| TranslationRunProgress.svelte | 310 | C4 | Live progress | -| ScheduleConfig.svelte | 286 | C3 | Schedule editor | -| BulkCorrectionSidebar.svelte | 285 | C3 | Bulk correction | -| TermCorrectionPopup.svelte | 342 | C3 | Single correction popup | -| CorrectionCell.svelte | 326 | C3 | Inline editable cell | -| TranslationRunGlobalIndicator.svelte | 198 | C2 | Run indicator | -| TranslationMetricsDashboard.svelte | 184 | C2 | Metrics dashboard | -| +page.svelte (job list) | 279 | C3 | Job list page | -| [id]/+page.svelte (job detail) | 1 363 | C4 | Job config + run | -| history/+page.svelte | 523 | C3 | History page | -| dictionaries/+page.svelte | 270 | C3 | Dictionary list | -| dictionaries/[id]/+page.svelte | 821 | C3 | Dictionary editor | -| Тесты компонентов (3 файла) | 433 | — | Component tests | -| i18n (2 файла) | 1 223 | — | en + ru translation | -| E2E (1 файл) | 142 | — | End-to-end test | +| Файл | Строк | Назначение | +|------|:-----:|------------| +| `__init__.py` | 40 | 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 | +| `_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 | + +#### Models + Schemas (2 файла, 1 085 строк) + +| Файл | Строк | Назначение | +|------|:-----:|------------| +| `models/translate.py` | 397 | 15 ORM моделей | +| `schemas/translate.py` | 688 | 35+ Pydantic схем | + +#### Миграции (5 файлов, ~944 строк) + +#### Тесты бэкенда + +**Inline plugin tests (16 файлов, 6 029 строк)** +| Файл | Строк | Назначение | +|------|:-----:|------------| +| `test_orchestrator.py` | 880 | Orchestrator unit tests | +| `test_inline_correction.py` | 792 | Inline correction tests | +| `test_executor.py` | 698 | Executor + LLM call tests | +| `test_orthogonal_fixes.py` | 616 | Edge case + regression tests | +| `test_preview.py` | 610 | Preview engine tests | +| `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_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_dictionary_prompt_builder.py` | 111 | Prompt builder tests | +| `test_dictionary_utils.py` | 36 | Dictionary utility tests | +| `test_dictionary.py` | 20 | Dictionary facade tests | + +**External integration tests (7 файлов, 2 458 строк)** +| Файл | Строк | Назначение | +|------|:-----:|------------| +| `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 | + +### Фронтенд (23 файла source + 4 файла тестов, ~7 540 source + 575 тестов) + +#### Компоненты (10 файлов, 3 280 строк) + +| Файл | Строк | Назначение | +|------|:-----:|------------| +| `TranslationPreview.svelte` | 561 | Preview component (quality gate) | +| `TranslationRunResult.svelte` | 464 | Run result display | +| `BulkReplaceModal.svelte` | 396 | Find-and-replace modal | +| `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 | +| `TranslationRunGlobalIndicator.svelte` | 198 | Global run indicator | +| `TranslationMetricsDashboard.svelte` | 184 | Metrics dashboard | + +#### Страницы (5 файлов, 3 354 строки) + +| Файл | Строк | Назначение | +|------|:-----:|------------| +| `[id]/+page.svelte` | 1 363 | Job detail (config + run + results) | +| `dictionaries/[id]/+page.svelte` | 821 | Dictionary editor | +| `history/+page.svelte` | 523 | Run history | +| `dictionaries/+page.svelte` | 270 | Dictionary list | +| `+page.svelte` | 279 | Job list | + +#### API client (6 файлов, 529 строк) + +| Файл | Строк | Назначение | +|------|:-----:|------------| +| `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 | + +#### Store + i18n (2 файла, 377 строк) + +| Файл | Строк | Назначение | +|------|:-----:|------------| +| `translationRun.js` | 198 | Run state store | +| `i18n/index.ts` | 179 | en + ru translation keys | + +#### Frontend-тесты (4 файла, 575 строк) + +| Файл | Строк | Назначение | +|------|:-----:|------------| +| `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 | +| `translation.e2e.js` | 142 | E2E: create run, check progress | --- diff --git a/specs/028-llm-datasource-supeset/spec.ru.md b/specs/028-llm-datasource-supeset/spec.ru.md new file mode 100644 index 00000000..af293ceb --- /dev/null +++ b/specs/028-llm-datasource-supeset/spec.ru.md @@ -0,0 +1,216 @@ +# Спецификация: Сервис LLM-перевода табличных данных + +**Дата**: 2026-05-18 +**Назначение**: Передача сторонней команде для оценки трудозатрат +**Фокус**: только требования к конечному результату, без технологий + +--- + +## 1. Фронтенд (Web-интерфейс) + +### 1.1 Управление задачами перевода (Jobs) + +- Список всех задач перевода с фильтрацией по датасорсу, целевой таблице, статусу. +- Создание новой задачи перевода: + - Выбор Superset-датасорса (источник данных). + - Выбор колонки для перевода (одна, обязательная). + - Выбор колонок контекста (ноль или более) — их значения передаются LLM для повышения качества. + - Выбор ключевых колонок (одна или более, composite key) — по ним данные будут сопоставляться при вставке в целевую таблицу. + - Указание целевой таблицы и целевой колонки. + - Выбор одного или нескольких языков перевода. + - Редактирование системного промпта (шаблон сообщения LLM). + - Выбор LLM-провайдера и модели. + - Прикрепление одного или нескольких справочников терминов. + - Указание стратегии UPSERT (skip_existing / overwrite / insert). +- Редактирование, копирование, удаление задачи. + +### 1.2 Превью (Quality Gate) + +- Запуск превью на ограниченной выборке строк (1–100, по умолчанию 10). +- Отображение source-строк, контекста, обнаруженного языка оригинала и перевода на каждый целевой язык — рядом, в табличном виде. +- Approve / Edit / Reject для каждой строки превью. +- Повторный запуск превью с изменёнными настройками (промпт, язык, провайдер). +- Подтверждение превью (accept) — открывает возможность полного прогона. +- Предупреждение о стоимости перед запуском полного прогона (оценка токенов и цены). + +### 1.3 Выполнение (Run) + +- Запуск полного прогона (только после accepted превью). +- Живой индикатор прогресса: сколько строк обработано, успешно, с ошибками, процент выполнения. +- Возможность отмены прогона. +- Построчный просмотр результатов после завершения: + - Исходный текст, контекст, перевод по каждому языку. + - Статус каждой строки (OK / ошибка / пропущена). + - Сгенерированный SQL (для аудита). + - Статус вставки в Superset. +- Повтор проблемных batch-ей (retry failed). +- Inline-редактирование любой переведённой строки в результатах. +- Bulk Find & Replace по результатам прогона (с превью замен). + +### 1.4 Очередь и планировщик + +- Возможность настроить расписание для задачи: + - Одноразовый запуск в будущем. + - Интервальный (каждые N минут/часов/дней). + - Cron-выражение с выбором часового пояса. +- Scheduled-прогон создаёт новый Run и выполняет полный цикл. +- Для scheduled-прогонов: new-key-only (только новые строки, которых нет в последнем успешном прогоне). +- Если последний успешный прогон старше 90 дней — fallback на полный прогон. +- Защита от overlap: если предыдущий scheduled-прогон ещё выполняется — пропуск или очередь (1 в очереди). +- После N последовательных ошибок (по умолч. 3) — автоотключение расписания и уведомление. + +### 1.5 История и аудит + +- Список всех прогонов с деталями: датасорс, целевая таблица, кол-во строк, статус, кто запустил. +- Детальный просмотр прогона: configuration snapshot, промпт, результаты по строкам, сгенерированный SQL, Superset execution reference. +- Фильтрация по датасорсу, целевой таблице, дате, статусу. + +### 1.6 Справочники терминов (Dictionaries) + +- Создание справочника. +- Добавление пар «термин оригинала → перевод» с указанием языка оригинала и языка перевода. +- Импорт из CSV/TSV с превью, разрешением конфликтов (overwrite / keep / skip). +- Inline-редактирование, удаление записей. +- Прикрепление справочника к задаче перевода. +- Приоритет справочников (низкий номер = выше приоритет). + +### 1.7 Коррекция и обратная связь + +- Из любого завершённого прогона: клик на ячейку перевода → inline-редактирование. +- После редактирования: кнопка «Отправить в справочник». +- Popup с предзаполненными: исходный термин, старый перевод, новый перевод, язык оригинала (из строки), язык перевода (из колонки), context_data (из строк, автоматически), usage notes (вручную). +- Выбор целевого справочника (фильтр по языковой паре). +- Bulk-режим: массовое редактирование и отправка нескольких терминов за раз. +- Конфликт при повторной отправке: overwrite / keep existing / cancel. + +--- + +## 2. Оркестратор (Run Lifecycle) + +### 2.1 Жизненный цикл прогона + +1. **Создание**: формируется snapshot конфигурации задачи + snapshot прикреплённых справочников. +2. **Планирование**: определяются целевые языки, размер batch-ей (динамически, по token budget), порядок обработки. +3. **Выполнение**: + - Выборка source-строк: для scheduled new-key-only — только новые ключи; для manual — все строки. + - Разбивка на batch-и. + - Для каждого batch: + a. Запрос к LLM с промптом, контекстом, отфильтрованными записями справочников. + b. Парсинг структурированного JSON-ответа. + c. Валидация: все ли строки batch переведены, нет ли дубликатов. + d. Если ошибка — запись в TranslationBatch как failed. + - После всех batch-ей: финализация (статус, error_message если все строки упали). +4. **Вставка (Insert phase)**: + - Генерация UPSERT SQL под диалект БД (определяется динамически из Superset connection). + - Отправка SQL через Superset SQL Lab API. + - Polling статуса выполнения. + - Запись результата (query reference, статус, ошибка). +5. **Завершение**: запись метрик, отправка уведомления (опционально), авто-dismiss через N секунд на UI. + +### 2.2 Snapshot isolation + +- Все прогоны используют snapshot конфигурации и справочников, взятый на момент старта. +- Изменения конфигурации во время выполнения прогона НЕ влияют на текущий прогон. + +### 2.3 Retry + +- Возможность повторно запустить только failed batch-и (не трогая успешные). +- При перезапуске можно сменить LLM-провайдера. + +### 2.4 Data retention + +- 90 дней — полная детализация (source-строки, переводы, SQL). +- После 90 дней — агрегация: только метаданные прогона и агрегированные метрики. +- Перед прунингом — сохранение cumulative snapshot метрик. + +--- + +## 3. Перевод (LLM) + +### 3.1 Multi-language + +- Задача поддерживает N целевых языков (массив, а не один язык). +- LLM получает исходный текст один раз на batch и возвращает переводы для ВСЕХ целевых языков в одном JSON-ответе. +- Не нужно N отдельных LLM-вызовов. + +### 3.2 Автоопределение языка оригинала + +- LLM определяет язык каждой строки автоматически. +- Возвращает BCP-47 tag (например, "fr", "de", "und" для неопределённого). +- Пользователь НЕ указывает язык оригинала вручную. + +### 3.3 Reference copy + +- Если язык оригинала включён в список целевых языков — «переводом» для него будет исходный текст (verification copy). + +### 3.4 Dictionary injection + +- Перед каждым LLM-запросом выполняется per-batch фильтрация справочника: + - Отбираются только те записи, чей source_term встречается (case-insensitive substring match) хотя бы в одной строке batch-а. + - Учитывается языковая пара (source_language записи === detected_language строки, target_language записи === языка промпта). +- Отфильтрованные записи вставляются в промпт как authoritative glossary. +- Записи с совпадающим контекстом (context_data) помечаются priority. + +### 3.4 Превью + +- Quality gate, а не построчное утверждение. +- Принятие превью = одобрение настроек (промпт, языки, справочники), после чего полный прогон обрабатывает ВСЕ строки. +- Редактуры на уровне превью переносятся в полный прогон для тех же строк (carry-forward). +- Rejected строки превью исключаются из полного прогона (только если были в sample). + +--- + +## 4. Справочники (Dictionaries) + +### 4.1 Структура + +- Справочник содержит пары «термин оригинала → перевод». +- Каждая запись имеет: + - source_term — термин на языке оригинала. + - target_translation — корректный перевод. + - source_language (BCP-47) — язык термина. + - target_language (BCP-47) — язык перевода. + - context_data (JSON, опционально) — значения контекстных колонок из строки, где был найден термин. + - usage_notes (текст, опционально) — заметки по использованию. + - has_context (boolean) — есть ли контекстные данные. + +### 4.2 Привязка к задаче + +- К задаче можно привязать несколько справочников. +- Порядок приоритета: чем меньше номер, тем выше приоритет. +- При конфликте (один source_term в нескольких справочниках) побеждает высший приоритет. + +### 4.3 Per-batch фильтрация + +- В каждый LLM-запрос включаются ТОЛЬКО те записи справочника, чей source_term: + - Встречается хотя бы в одной строке batch-а (substring match). + - source_language совпадает с detected_language строки. + - target_language совпадает с языком текущего промпта. +- Размер справочника не ограничен (фильтрация не даёт промпту расти бесконечно). + +### 4.4 Контекстная приоритизация + +- Если context_data записи совпадает с контекстом строки batch-а (Jaccard similarity > 50%) — запись помечается как priority_context. +- Priority-записи перечисляются первыми с пометкой # PRIORITY. +- Это soft signal для LLM, не хард-фильтр. + +### 4.5 Коррекция через результаты прогонов + +- Из любого завершённого прогона можно отправить исправление в справочник. +- context_data заполняется автоматически из строки, где был найден термин. +- Пользователь может отредактировать context_data, добавить usage_notes, убрать контекст. +- Если context_data превышает 500 токенов — обрезается с пометкой. + +--- + +## 5. Обработка ошибок (Edge Cases) + +- NULL в колонке перевода → пропуск строки с логированием. +- NULL в ключевой колонке → reject строки (не может быть вставлена). +- LLM вернул неожиданный формат → запрос структурированного JSON, валидация, failed batch. +- Все строки batch упали → run.error_message с деталями. +- Редактирование задачи во время выполнения прогона → не влияет на текущий прогон (snapshot isolation). +- Удаление справочника, привязанного к активной задаче → запрет, предупреждение. +- Scheduled прогон при недоступном датасорсе → запись ошибки, попытка следующего триггера. +- Неподдерживаемый диалект БД → блокировка выполнения с сообщением. +- Вставка через Superset SQL Lab вернула ошибку → insert_status = failed, error_message заполнен.