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

30 KiB
Raw Blame History

Целевая архитектура и дорожная карта (арх-ресет 2026-07-13)

Статус: проектный документ оркестратора, ратифицирован D39 (05-decisions-log.md). Рождён из арх-ресета (../archive/prompts/ORCHESTRATOR_ARCH_RESET_PROMPT_2026-07-13.md, 5 концернов владельца) и синк-аудита «сломанного телефона» (../archive/architecture/08-sync-audit-ledger.md, 65 находок, адверсариально верифицированы; архивирован 25.07 как отработанный). Решения владельца по подходу: фазовый (build-now ∥ ресёрч, пере-прогон после) + слой пар языков = сеам сейчас, контент только zh→ru.

Это карта «куда и почему», а не пошаговая спека. Спеки — в хендофф-промтах сессий; контракт — в D-логе.

КАК ЧИТАТЬ ШАПКУ (освежена 02.09). Таблица «слой → статус → пак/D» ниже — единственный статус-борд этого файла: она БЬЁТ тело документа, а D-лог бьёт её. Хроники лендингов паков здесь больше нет — кто что построил и когда живёт в журнале решений: 05-decisions-log.md + реестр 05-decisions-index.md + слайсы ../archive/architecture/ (эры D39.100D39.185 покрывают всю стройку платформы, шва и писателя книги). ⚠ ПОСТРОЕНО, но в семь слоёв НЕ укладывается (движковые оси рядом со слоями — читать шапку как полную нельзя без них): объёмный потолок оплаченной работы --max-units/VolumeStop (backend/internal/pipeline/volume.go, D39.170; ратифицированная единица продажи — D39.165 §1) · гейт схемы движка (backend/internal/store/sqlgate_test.go, D39.173: каждый SQL-оператор компилируется против схемы, поднятой продовой цепью миграций) · дверь правок банка POST /books/{bookId}/bank/corrections смонтирована синхронно (D39.162) · ключи деплоя доезжают до движка аргументом --keys-file (строка 211 ЗАКРЫТА, блокером живого прогона больше не является) · полоса прогресса СКВОЗНАЯ, подпись стадии — второе исключение границы (D39.162/163) · пере-проход можно КУПИТЬ (D39.166) · инъекция банка не теряется на провайдере с одним системным слотом (D39.164). ⚠ Канон контракта — 0.9.0 (D39.180, лендинг пака P12 31.08), не 0.4.0 и не 0.7.0. Носители — docs/architecture/14-api-contract/openapi.yaml и platform/internal/httpapi/capabilities.go, они сходятся гейтом.

ВХОДНАЯ ДВЕРЬ ШВА ПОСТРОЕНА (D39.158): закон двери — 17-seam-inbound-law.md, онтология банка, который она обслуживает, — 18-bank-ontology.md. Шапка — не переписывание: тело ниже = замысел арх-ресета 13.07, и при расхождении тела с шапкой первична шапка.

Слой Статус Пак / D
1 Сегментация ПОСТРОЕН: бюджет в выходных токенах снапшот-folded (chunk.SegBudget), edit-единицы декаплены; когезия/carryover — НЕ строится (D39.7/8: эффекты под floor 0.126; кнобы STMDepth/OverlapTokens УДАЛЕНЫ, WS2 §2а), граница logical — не рычаг (exp15), greedy остался пак-11 (D39.13 WS2 · D39.17 волны · D39.18 c-lite)
2 Пары СЕАМ ПОСТРОЕН: internal/lang+langpacks (embedded · книго-overlay langpack_extend) · пар-агностичные чекеры · configs/pairs/ · промпт-конвенция prompts/<пара>/<роль>.md; открыто: извлечение дискурс-норм/few-shot из ТЕЛА промтов (форсинг = ja→ru) D39.16 · пак-14 · пак-15 (D39.23г)
3 Контракт t/e ПОСТРОЕН ЗА enabled:false: checks.RepairCandidates (позиционная детекция) · read-only скан остатка · машинерия ремонта §15.2; включение платного пути = решение владельца по замеру остатка; эмпирика контракта: диффы ОТЛОЖЕНЫ (D39.108, экспы 19/20; D21.4/D21.10 закрыты), full-regen ПОДТВЕРЖДЁН, точечная починка как ЗАМЕНА редактора отклонена и принята формой «механический пре-гейт ПЕРЕД редактором» (D39.117; строка 142, строка 106 понижена) пак-16 (D39.24), D39.108, D39.117
4 Память ПОСТРОЕН + ДОСТРОЕН паком-20 + ВХОДНАЯ ДВЕРЬ ПОСТРОЕНА (D39.158): $0-глагол tmctl bank-apply (проекция --dry-run, всё-или-ничего, байтовый no-op идемпотентен), писатель решений internal/membank/decisions.go, стоп банка — ФЛАЖОК, который движок чтит сам (память предъявления bank_stop_presented, схема store v16), класс отказа 15 write_incomplete. Роли носителей и поток «источники → вид → проекции» — 18-bank-ontology.md; состав пака-20 (ТЕРМИНОЛОГ · флаговый стоп --verify-bank · двухсекционная редакторская инъекция · точечная ре-редактура · банкнота отдельным шиппинг-файлом · языковой экран target_script) — D39.4145/5053; ⚠ D39.104: инъекция схлопывается в ЕДИНЫЙ закон-блок, маркер ⟨проверить⟩ снимается с провода — внесение = строка 134 ПОСЛЕ пробы 18; жанровый словарь ОТМЕНЁН (D39.47) пак-1 · пак-11 · пак-20 (D39.4145/47/5053)
5 Качество детерм. часть: QualityReport · число/omission-гард · DC/пак-13-чекеры · repair-остаток; семантический span-судья/полярность — НЕ строился (защита = editor-swap, D38.4) D39.2 · D38.3 · пак-13 (2f91b04) · пак-16
6 Export ПОСТРОЕН: checks.ExportNormalize на каждом финале; санитайзер-классы strip+export · писатель книги: internal/bookfile + tmctl build (EPUB 3 + txt, D39.175) D39.2 · D38.3 · D39.175
7 Гигиена ПОСТРОЕН: реестр role→инъекция · вынос foldModelWire · снос сирот/gatesEnabled · target-aware гейты ПО ДАННЫМ — П1 «цель-шов» (фаза 2, D39.64: isRuTarget удалён, TargetActive/TargetScriptNonLatin, токенизатор цели из word_script); остаток — ё-фолд/segmentation за подписью (бэклог-строка 14) D39.2 · паки 1116 · фаза 2 (D39.64)

Общность (фаза 2) ИСПОЛНЕНА И ПРИНЯТА — D39.64, отчёт ../archive/reports/GENERALITY_PHASE2_2026-08-01.md: П0 хеш эмбед-данных (embedded_version в снапшоте) · П1 цель-шов (слой 7) · П2 скрипт-шов источника (lang-script.txt) · П3 нарезка/оценка (один дом DenseScript) · П4 манифест-по-каналам (packAlgoVersion не бампался); голден вердикт-нейтрален (0/172); П5 майнер гейтится второй книгой; 9 флагов §5 — очередь владельца (бэклог-строка 14). Карта языковой привязки ВСЕГО движка — ../archive/reports/GENERALITY_RESEARCH_2026-07-31.md (D39.60); пак-19 «голос/состояние» — D39.5456. Снято из тела как прожитое, адреса — здесь. §1 «как есть 13.07» (const-чанкер · glm-редактор · мёртвые STMDepth/OverlapTokens — ничего этого в коде больше нет): пофакторный разбор каждой находки — ../archive/architecture/08-sync-audit-ledger.md. §4 «дорожная карта» отработана целиком: трек A = слои таблицы выше, трек B исполнен (exp15/exp16 — программа ЗАВЕРШЕНА, D39.7/D39.10), гейт пере-прогона пройден фактом rerun2 (D39.20; планка ≤2 НЕ пройдена, эксп ЗАКРЫТ D39.22, редактор = deepseek-v4-pro интерим). Канал B — пак-17 ЗАКРЫТ ЦЕЛИКОМ (дизайн D39.26 · стройка D39.27 · дельта D39.28: действия route|allow|terminal, permissive/Stage.Channel/D4.1-блок отставлены, failover.go удалён; вокабуляр = ПАРА violence/sexually-explicit; accepts_labels fail-closed); ⚠ испр. 28.08 (D39.168): факты ToS предъявлены, поля ЗАПОЛНЕНЫ у трёх эндпоинтов (backend/configs/models.yaml, греп accepts_labels) — механизм fail-closed жив, но «пусты у всех» больше не факт. Инженерная форма — D39.25: в движке НЕТ понятия «18+», есть generic content-labels × provider-capabilities, refusal причино-агностичен; «18+ линия» в §6 читать как продукт-линию, не механизм движка.


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. Снимок «как есть» на 13.07 — СНЯТ

Раздел описывал состояние ДО стройки (const-бюджет чанкера 1500 в символах источника · билингв-редактор glm-5 с 4 мандатами одной перегенерацией · мёртвые config-кнобы STMDepth/OverlapTokens · zh→ru-промпты фикс-путём) — ничего этого в коде больше нет, статусы построенного см. в таблице шапки. Пофакторный разбор того состояния, находка за находкой (L1-*/L2-*/L3-*/L4-*), — ../archive/architecture/08-sync-audit-ledger.md, карта находок → слои — §3 ниже. Столпы, которые аудит велел НЕ ломать (деньги/durability, snapshot-дисциплина, эталонные сеамы config→stage-list и baseRequestLog, дословный перенос техник Ван Цуй, структурные few-shot, разделение переводчик/редактор), — §6.


2. Целевая архитектура — 7 слоёв с чистыми сеамами

ЧИТАТЬ КАК ЗАМЫСЕЛ 13.07, А НЕ КАК ДЕЙСТВУЮЩЕЕ ПРЕДПИСАНИЕ (баннер дописан 22.08 аудитом доков: у §1 и §4 такие оговорки были, у §2 не было — и его читали как норму). Что этот раздел предписывает, а стройка с тех пор отменила, видно из ШАПКИ-ТАБЛИЦЫ ЭТОГО ЖЕ ФАЙЛА: например меж-единичная когезия («оживить STMDepth/OverlapTokens») — эти кнобы УДАЛЕНЫ, эффекты замерены под флором и когезия НЕ строится (D39.7/D39.8, слой 1). При расхождении раздела с шапкой первична шапка, при расхождении шапки с D-логом — D-лог.

Вместо 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-книга едет через «китайский паратаксис»-промпт) и разблокирует расширяемость дёшево.
  • ⟶ Что из этого ПОСТРОЕНО (статусы и номера паков — таблица шапки): данные-часть вынесена в internal/lang+configs/langpacks/ с компиль-enforced границей и резолвом по Book.LangPair() (D39.16), пар-калибровки configs/pairs/ и промпт-конвенция prompts/<пара>/<роль>.md — паки 14/15 (D39.23г). Открытым остаётся извлечение правил из ТЕЛА промтов (дискурс-нормы, few-shot); форсинг-функция — ja→ru-реплика. x/text/language.Tag для гейт-предикатов ОТВЕРГНУТ (CLDR-инстабильность в снапшот-вердиктах) — исполнено иначе D39.64: TargetActive/TargetScriptNonLatin из данных пары.

Слой 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).
  • ИСПОЛНЕНО (D39.13, пак-11 WS2): D1-моно-рационализация из редакторского блока убрана, и «давать ли билингв-редактору src→dst» больше не открытый вопрос — блок рендерится src→dst-мэппингом, CONFIRMED-only, форма зафолжена в снапшот (internal/membank/memory.go, греп RenderEditorConstraintBlock и RenderFormatVersion).

Слой 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. Карта находок → слои (полный ледджер — ../archive/architecture/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. Дорожная карта 13.07 — ОТРАБОТАНА (тело снято)

Трек A (build-now) исполнен целиком: слои 4·5·6·7·2 — статусы и номера паков в таблице шапки; док-долг оркестратора закрыт там же (фантом «D35.7» формализован — D39 п.4, разбор ../archive/architecture/08-sync-audit-ledger.md).

Трек B (ресёрч перед постройкой) ЗАВЕРШЁН: программа нарезки/когезии — exp15/exp16, D39.7/D39.10 (граница logical — не рычаг НА ЭТОМ МАТЕРИАЛЕ, когезия под флором; скоуп замера — книги класса zh-вебновелла, а не весь спектр §0.1); конфликт exp14 ↔ research/18 §A решён этими же нотами. Методика-guard замеров — D32.4 (fidelity-first · leave-one-out · катастроф-скрин: полигон трижды собирал ложную сходимость).

Гейт пере-прогона пройден фактом rerun2 — D39.20; планка «≤2 претензии владельца» НЕ пройдена, эксперимент ЗАКРЫТ D39.22 (редактор = deepseek-v4-pro, интерим).

⚠ Ограничение дизайна эксперимента, которое НИКОГДА не переносится в продукт (§0.1): плоский тест-срез не задействует рычаги границы/когезии, поэтому «не сработало на нём» ≠ «не нужно в движке».

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, не переделка кода).