textmachine/docs/architecture/09-target-architecture.md

208 lines
25 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Целевая архитектура и дорожная карта (арх-ресет 2026-07-13)
> **Статус:** проектный документ оркестратора, ратифицирован **D39** (`05-decisions-log.md`). Рождён из арх-ресета
> (`ORCHESTRATOR_ARCH_RESET_PROMPT.md`, 5 концернов владельца) и синк-аудита «сломанного телефона»
> (`08-sync-audit-ledger.md`, 65 находок, адверсариально верифицированы). Решения владельца по подходу:
> **фазовый** (build-now ∥ ресёрч, пере-прогон после) + **слой пар языков = сеам сейчас, контент только zh→ru**.
>
> Это карта «куда и почему», а не пошаговая спека. Спеки — в хендофф-промтах сессий; контракт — в D-логе.
---
## 0. Стратегический вывод аудита (почему ресет)
Потолок художественности сейчас — **в НАШЕЙ организации пайплайна, а не в моделях.** Эмпирика (exp1214b) и
код-аудит сошлись: дефекты, которые владелец назвал «крайне слабо художественно» (рубленые абзацы + «непонимание
связей»), рождаются из **нарезки, структуры редакторских проходов, контракта переводчик/редактор и отсутствия
меж-чанковой когезии** — всё это архитектура, не выбор модели. Это подтверждает трек «дешёвые модели сейчас»
(D30.7) и переопределяет источник следующего прироста качества: **он архитектурный.**
Ключевое свойство проблемы: **рычаги сцеплены.** Редактор репараграфизует ВНУТРИ ~1500-токенного чанка → он
физически не может чинить когезию через границу чанка → нарезка (концерн 2) жёстко ограничивает потолок
дискурс-переверстки, которую мы требуем от редактора (концерн 1). Поэтому чинить их порознь = снова получить
локальный оптимум на неверно нарезанном тексте (ровно «слабый тест» exp14). **Концерны 1, 2, 4 проектируются
вместе.**
## 0.1 Инвариант общности (поправка владельца, 2026-07-13) — НЕСУЩИЙ
**Цель — перевод ЛЮБОЙ книги, ЛЮБОЙ пары языков, написанной ПО-РАЗНОМУ.** Ни один компонент не смеет предполагать
структуру конкретной книги (蛊真人) или конкретную пару (zh→ru). Из этого:
- **Чанкер = ОБЩИЙ адаптивный модуль:** характеризует структуру КАЖДОГО входа в рантайме (плоский CJK line-per-
sentence · сцен-маркированный · длинно-абзацный европейский роман · ja-ранобэ · смешанный) → выбирает стратегию
границы → фоллбек-лестница. Он обязан работать корректно на всём спектре, а не на одной форме.
- **Разница «продукт» vs «эксперимент»** (моя ошибка, которую поправил владелец): чтобы ИЗМЕРИТЬ рычаг эмпирикой,
нужен тест-текст, который его задействует — это ограничение ДИЗАЙНА ЭКСПЕРИМЕНТА (валидируй на разнообразном
корпусе), и оно **никогда** не переносится в scope продукта («книга плоская → урежем нарезку» — ЗАПРЕЩЕНО).
- **Пер-язык (слой 2)** — та же логика: строим ОБЩИЙ сеам, контент наполняем инкрементально (zh→ru сейчас); новая
книга/пара = данные (пакет конвенций), не переделка кода. «Бэкенд только под русский/под одну книгу» = антицель.
- **Эмпирика валидирует ОБЩНОСТЬ** (корректность+near-оптимум на структуро- и языко-разнообразном корпусе), не
оптимизирует под книгу на стенде.
---
## 1. Текущая архитектура (как есть, grounded)
Пайплайн = линейный проход по плоскому списку чанков; на каждый чанк — стадии по порядку из `pipeline-*.yaml`:
```
книга → ingest (главы) → SplitChunks (чанкер) → [ по чанку: translator(draft) → editor(edit) ] → export
↑ память v2 (Select→inject) + детерм. гейты
```
- **Нарезка** (`chunker.go`): жадная упаковка целых абзацев в бюджет `targetChunkTokens=1500` (**const**, в единице
«оценка символов исходника», не выходные токены), спуск до предложений при оверсайзе. Граница — там, где накопление
пересекло бюджет; **логической/сценовой границы нет**. Единица одна и для черновика, и для редактуры.
- **Переводчик** (`translator.md`, deepseek-v4-flash): подстрочник + слабая однострочка про вёрстку; на верности
валидирован (exp13), на художественность/структуру — **не мерен никогда** (D30.6).
- **Редактор** (`editor.md`, glm-5, БИЛИНГВ): ОДНА полная перегенерация чанка с **4 мандатами сразу** — верность,
стиль, глоссарий, дискурс-reflow (техники Ван Цуй + few-shot).
- **Память v2** (`memory.go`): Aho-Corasick матч → disposition → инъекция per-role (переводчику src→dst, редактору
CONFIRMED-dst-констрейнты) → детерм. post-check. Единственная меж-чанковая память. Меж-чанковой когезии
(summary/carryover) НЕТ — есть мёртвые config-заглушки `STMDepth`/`OverlapTokens`, которые код не читает.
- **Гейты** (детерминированные): intrinsic-классификатор (echo/empty/refusal/length), coverage/excision (только
translator), output-санитайзер (только final), glossary post-check (флаггер), cheap style-флаггеры, regression-guard.
**Семантического/качественного сигнала в контуре нет.**
- **Промты**: единые zh→ru-файлы, выбор по фикс-пути из yaml; `{{source_lang}}` — поверхностный шаблон; правила
захардкожены; язык промпта всегда русский. `Book.LangPair()` — мёртвый код.
Хорошее, что подтвердил аудит (не ломать): деньги/durability (reserve→settle+checkpoint, committed==SUM, kill-9),
snapshot-дисциплина, эталонные сеамы `config→stage-list` и `baseRequestLog`, дословный перенос техник Ван Цуй,
структурные (не «правильно-переводные») few-shot, осознанность разделения переводчик/редактор.
---
## 2. Целевая архитектура — 7 слоёв с чистыми сеамами
Вместо 65 заплаток — слои, каждый первоклассный, независимо конфигурируемый и снапшот-folded. Ровно они закрывают
5 концернов.
### Слой 1 — Сегментация (чанкер-модуль) · концерны 1+2
- Размер бюджета — **снапшот-folded config-кноб в ВЫХОДНЫХ токенах** (не const, не в símволах исходника), чтобы
пре-регистрированная кривая полигона могла приземлиться как настройка. Механизм fold уже есть (`coverageSnap`).
- **Стратегия границы** — first-class ось: `greedy` (как сейчас) | `logical` (сцена/диалог/тема) — с фоллбек-лестницей
и инвариантом «никогда не резать предложение». Наполнение стратегии `logical` — по интернет-best-practices + ресёрч.
- **Декаплинг edit-единицы от draft-единицы** (бывший фантомный «D35.7»): черновик — мелкий чанк (COGS/coverage/
выравнивание); reflow/edit — крупная дискурс-единица (глава/сцена), где антецеденты со-встречаются.
- **Меж-единичная когезия**: оживить `STMDepth`/`OverlapTokens` — running bilingual summary + carryover соседних
единиц как read-only контекст. (⚠ exp14 «крупнее лучше» и research/18 §A «мелкий чанк + carryover» **конфликтуют**
решает ресёрч-матрица, см. §4.)
### Слой 2 — Конвенции пары языков (pair-keyed pack) · концерн 4
> Консолидированная заметка по всей промпт-теме (инвентарь, статусы, открытое) — `10-prompt-architecture.md`.
- Версионируемый пакет, ключ `src→tgt[×genre]`, снапшот-folded (правка = громкий `--resnapshot`, как `chunkerVersion`).
- Держит: дискурс-правила, few-shot (в языке пары), транскрипцию/хонорифики, **и язык самого промпта** (свойство
пакета — не хардкод русского).
- Стадия резолвит промпт/правила из слоя по паре книги, а не из фикс-пути. `Book.LangPair()` оживает как ось выбора.
- **Высота сейчас (решение владельца):** построить СЕАМ, наполнить только zh→ru; другие пары — когда придёт книга.
Убирает латентный баг (ja-книга едет через «китайский паратаксис»-промпт) и разблокирует расширяемость дёшево.
- **⟶ Реализация (D39.16, обновление):** данные-часть этого слоя РЕАЛИЗОВАНА для майнера — zh/Палладий-инвентари
вынесены из `pipeline/`-констант в `configs/langpacks/<lang|pair>/` через leaf-пакет `internal/lang` (граница
компиль-enforced; резолв по `Book.LangPair()`; байт-точно — парити EXACT, golden байт-идентичен). Извлечение
правил из ТЕЛА промтов (дискурс-нормы, few-shot) — ещё открыто (форсинг-функция = ja→ru-реплика). `x/text/
language.Tag` ОТВЕРГНУТ для гейт-предикатов (CLDR-инстабильность в снапшот-вердиктах — держим точные `isRuTarget`).
### Слой 3 — Контракт переводчик/редактор (роли = узкие проходы) · концерн 1
- research/07 предписывает **узкие мандаты + диффы, а не полную перегенерацию** — сейчас ровно наоборот (4 мандата,
full-regen), что и породило хвост инверсий.
- Целевой контракт: переводчик отдаёт **структурный ~верный черновик**; редактор — узкая правка смысла+стиля,
в идеале **diff-based** (search/replace-спаны + детерм. Go-apply → ограниченный blast-radius, дешевле, аудируемо,
структурно omission-safe). Между проходами — гейт.
- **⚠ Арм «переводчик отдаёт структуру» никогда не тестировался** — решает ресёрч-матрица (§4), а не догадка.
### Слой 4 — Память (код-корень) · концерн 3
- Починить **disposition-слепой** `suppressContained`: более длинный НИЗКО-доверенный ключ (draft/ambiguous) не должен
подавлять вложенный ВЫСОКО-доверенный (approved/confirmed). Это закрывает терм-дрейф в КОДЕ (сейчас — сид-воркэраунд).
- **Тихие дропы → в громкие**: подавленный approved-термин обязан попадать в retrieval-state (обещание research/13).
- Убрать устаревшую D1-моно-рационализацию из `renderEditorConstraintBlock` (редактор теперь БИЛИНГВ, D30.1); открытый
вопрос — давать ли билингв-редактору src→dst-мэппинг, а не голые dst-формы.
### Слой 5 — Измерение качества в контуре · главная цель + концерн 5
- Per-run/per-segment авто-сигнал: **детерминированный структурный KPI** (предл./абзац, диалог-тире, CJK-утечка,
глоссарий-консистентность) — дёшево, build-now — + **дешёвая span-проверка смысла** (полярность/число/ранг/пропуск →
тот самый inversion/omission-бэкстоп; семантический span-судья — ресёрч-зависим, позже).
- Даёт то, что владелец просил (телеметрия качества с 1-го дня, п.25/п.31) и делает КАЖДУЮ правку ниже измеримой;
предпосылка самоулучшения.
### Слой 6 — Export-contract (нормализация) · концерн 3
- Единая нормализация КАЖДОГО финального текста (NFKC-fold + пробелы/CJK-пунктуация/U+3000) — тот самый D29.1a-слой,
который D-лог откладывает. Санитайзер сводится к **чистому детектору** (флагует только по-настоящему невосстановимое).
- Убирает: дефект чинится на флагнутом чанке, но уезжает сырым на чистом; дубль NFKC; churn регексов v1→v4.
### Слой 7 — Гигиена расширяемости · концерн 3 п4
- **Реестр** `role→инъекция` (map/стратегия из конфига) вместо рукоправимого switch — чтобы Ф2-annotator/voice
добавлялся данными, не хирургией.
- **Target-aware гейты**: readability-набор за `TargetLang` (сейчас слеп — любой не-ru target даст ложные флаги).
- Де-размазать strip-and-export (5 файлов → один resolver `classification→(disposition, exportText)`).
- Снести сироты-промпты (`analyst.md`/`terminologist.md`/дубль `editor-mono.md`), мёртвый `gatesEnabled()`;
вынести `foldModelWire()` (tripwire на 3-ю модель-ось уже стоит).
- Эталоны для копирования: `config→stage-list`, `baseRequestLog`.
---
## 3. Карта находок → слои (полный ледджер — `08-sync-audit-ledger.md`)
| Слой | Несущие находки (HIGH, CONFIRMED) |
|---|---|
| 1 Сегментация | `L2-1500-untested-apriori`, `L2-budget-wrong-unit`, `L2-token-budget-not-semantic`, `L2-edit-unit-equals-chunk`, `L2-cross-chunk-only-glossary`, `L2-d357-phantom-decision`, `H1-smart-chunking-never-formalized`, `L2-no-boundary-algo-research` |
| 2 Слой пар | `L4-prompts-not-per-pair-zh-baked`, `L4-convention-pack-layer-never-built`, `L4-prompt-language-always-russian`, `H2`, `L4-adding-a-pair-is-a-rewrite-not-config` |
| 3 Контракт t/e | `L1-editor-four-mandates-one-fullregen-pass`, `L1-fidelity-has-no-owner-in-cheap-path`, `L1-diff-editing-never-built`, `H3/H4`, `L1-translator-structure-arm-never-tested` |
| 4 Память | `L3-seed-workaround-not-code-root`, `L3-recurrence-draft-longer-eats-approved-shorter`, `L3-suppressor-disposition-blind-right-fix`, `L3-editor-block-stale-monolingual-D1` |
| 5 Качество | `H5-no-in-loop-quality-signal`, `H14-inversion-guard` (D37 §2г), `H12-cross-boundary-coherence-untested` |
| 6 Export | `L5-normalization-fused-to-flag-path`, `L5-broken-word-class-*`, `L5-diacritics-class-lost`, `L5-legit-cjk-gloss-stripped`, `L6-technique-not-norm-overclaim` |
| 7 Гигиена | `L8-*` (target-blind gates, role-switch, strip-smear, prompt-orphans, dead gatesEnabled, foldModelWire) |
| Процесс (к.5) | `H18-no-standing-findings-ledger-process` + незакрытые владельческие: `H6` running-summary, `H7` input-size-limit, `H8` abuse-prescreen, `H9` parallelism/speed (V4-п1), `H15` glossary-auto-build (V4-п4), `H10` user-stop, `H16` self-improvement |
---
## 4. Дорожная карта — две параллельные фазы (решение владельца: фазово)
### Трек A — Build-now (бэкенд, ресёрч НЕ нужен, высокий ROI, низкий риск)
Порядок ≈ по ROI/риску; всё под мандат самопроверки исполнением (CLAUDE.md):
1. **Слой 4 память-корень** — disposition-gate на suppressor + громкий лог дропа. Мал, хирургичен, закрывает терм-дрейф
в коде (снимает вечную зависимость от сид-воркэраунда).
2. **Слой 5 (детерм. часть)** — per-run структурный quality-report + **inversion/omission-бэкстоп** (полярность/число/
ранг/пропуск, span). Измеряет всё остальное.
3. **Слой 6 export-contract** — нормализация каждого финала; санитайзер → детектор.
4. **Слой 7 гигиена** — реестр role→инъекция, target-aware гейты, де-размазка, снос сирот. (Разблокирует слой 2 сеам.)
5. **Слой 2 сеам** (после гигиены) — pair-keyed резолв промпта/правил; наполнить zh→ru; язык промпта = свойство пакета.
6. **Док-долг оркестратора:** формализовать/вычистить фантомный «D35.7»; ратифицировать диспозиции незакрытых
владельческих идей (input-limit / abuse-prescreen / parallelism / glossary-auto-build — явное решение, даже если «Ф2/Ф3»).
### Трек B — Ресёрч ПЕРЕД постройкой (концерны 1+2+4 — сцеплены)
- **Единая полигон-матрица:** `{граница: greedy|logical} × {edit-единица: чанк|глава} × {когезия: нет|summary/carryover}
× {где reflow: переводчик|редактор|отдельный-пасс}` на реальном вебновелл-срезе. ⚠ **exp14 vs research/18 §A прямо
конфликтуют** по размеру чанка — это ключевой вопрос, который матрица решает эмпирически, не догадкой.
- **Полигон-синк (13.07) — ТОЛЬКО про дизайн эксперимента, НЕ про продукт (инвариант общности §0.1):** exp14
«пробелы» по сцен-границе/кросс-границе/translate-стадии — не отрицательные результаты, а непротестированные
допущения, потому что **тест-срез (ранняя арка 蛊真人) плоский** (1 предл./строка, мало сцен-маркеров) и физически
не задействует эти рычаги. Это чисто **экспериментальное** ограничение: чтобы ИЗМЕРИТЬ рычаг границы/когезии, нужен
текст, который его задействует. → **эмпирика валидирует чанкер на РАЗНООБРАЗНОМ корпусе** (плоский CJK line-per-
sentence · сцен-маркированный · длинно-абзацный европейский · ja-ранобэ · …), а не на одной книге. Плоская книга —
ОДНА точка спектра, который общий чанкер обязан обрабатывать, **никогда не повод сузить продукт**. Реюз: кривая +
A-ref-prev/both как есть; дозаказать `A-ref-next` + translate-плечо + добрать структурно-разные срезы.
- **Интернет-best-practices** по логической/семантической нарезке крупных текстов (владелец просил явно) + фоллбеки.
- **Дизайн слоя 2** (форма pair-pack, язык промпта) — под данные матрицы (§D-3 research/18: форма не разрешена).
- Методика-guard D32.4 (fidelity-first, leave-one-out, катастроф-скрин — полигон трижды собирал ложную сходимость).
### Гейт пере-прогона
Пере-прогон 310 глав — **только после** трека B (иначе снова слабый тест на голом конфиге) и приёмки ключевых
build-now (память-корень + quality-сигнал + export-contract). Планка — 2 претензии владельца (интерим, не пилот Ф2.5).
---
## 5. Процесс против «сломанного телефона» (концерн 5)
Постоянный **findings-ledger** как повторяющийся шаг оркестратора (этот аудит — первый экземпляр, `08-*`):
- Каждая находка полигона/ресёрча/аудита получает явную диспозицию (FAITHFUL/DISTORTED/LOST/WORKAROUND_NOT_ROOT/
UNTESTED_ASSUMPTION/NEVER_CLOSED/CODE_SMELL) и трекается **до закрытия** (fixed / ratified-deferred / retracted).
- Вопросы «к бэкенду» из ресёрча (research/18 §D) обязаны получать ответ, маршрутизируемый обратно (сейчас висят).
- Периодический completeness-critic прогон (как этот) на границе фаз — не разовый.
---
## 6. Что НЕ демонтируется
Столпы (деньги/durability, snapshot-дисциплина, детерминированный банк памяти как ставка, echo-гейт, 18+ линия,
дешёвый трек, конфиг-первое ядро) — целы. Целевая архитектура — это **декомпозиция и до-стройка** существующей
машинерии по чистым сеамам, а не переписывание. Фронтир-тир остаётся «потом» (новый yaml, не переделка кода).