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

25 KiB
Raw Permalink Blame History

Целевая архитектура и дорожная карта (арх-ресет 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, не переделка кода).