140 KiB
План реализации пере-прогонного стека (слои 1+4+5 + данные слоя 2) — дизайн-синтез, 2026-07-19
Статус: РАТИФИЦИРОВАН — D39.12 (19.07, оркестратор №7); дизайн-оф-рекорд бэкенд-стройки. Проектный документ дизайн-синтез-сессии (D39.11): синтез всей исследовательской программы арх-ресета (research/19–20, exp15/16, аудит 08, дефект-классы слепого чтения) в план стройки с верифицированными ($0) алгоритмами. Ревью-провенанс (три рубежа): ревью-2 оркестратора (F1–F11, все внесены — 36 маркеров) → пост-фикс 7-агентный адверсариал-воркфлоу сессии (5 находок впитаны, вкл. переписанный F8 и mined-write-путь) → 3-агентный подтверждающий пас (2 резидуала закрыты). Бэкенд строит СТРОГО по этому плану (
BACKEND_PLAN11_SESSION_PROMPT.md, единый пак — решение владельца); 4 гейтнутых арма — §11.Источник истины: при конфликте побеждает D-лог (
05-decisions-log.md, D1–D39.11). Всеfile:line— против HEAD766a60e. Все пороги/коэффициенты — число + источник. $0-верификации —eval/design11/, результаты вbooks/gu-zhenren/design11/(вне git); сводка —VERIFICATION_RESULTS.md.Дисциплина цитат: аудит 08 и D-лог местами несут устаревшие
memory.go-строки (~+11…+26 к HEAD:renderEditorConstraintBlock:515 не :489,suppressContained:684,dispositionFor:441; санитайзер = v6 не v4). Этот план цитирует HEAD-строки.
§0. Рамка: доказанная база и зоны
Строим (ратифицировано D39.x; в план внесено, НЕ пере-открывается): волновой раннер W0→W1(∥)→W1.5→W2(∥); бюджет чанкера в ВЫХОДНЫХ токенах (фертильность 1.20/0.39); банк W1.5 слоя 4 (детектор V-C WHICH + банкнота dst + Палладий + консолидация §C2 + алиас-ярус-1 + карта подписи); декаплинг draft=мелкий-чанк / edit=крупная-единица; свап редактора glm→mistral/deepseek-pro; дефект-класс чекеры + данные пакета пары.
НЕ строим (доказано/ратифицировано): сцен-детекция и carryover-машинерия (D39.7/8, метрики под полом 0.126 И читатель); DP/logical-граница чанкера (Q1: «граница не рычаг»; Q1a 0/7); ко-оккуренция для dst (canon-recovery 0.20–0.68 < 70%); LLM-сегментация/ML-сцены/эмбеддинг-границы/RAG-оверлап; фронтир в дефолт; жанр-паки; локальный 9B-споттер (код ≥ локаль). Парковки (не тестировано, консервативный дефолт — НЕ строим, НЕ хоронить): lookahead (Q3b), diff-редактор §C2 (Q4b), reflow-отдельным-пассом (Q4c), широкое-окно/узкая-эмиссия (Q2c), W2.5-швейный пасс (Q5). Каждая парковка помечена «не тестировано» — диспозиции в §9 (lookahead/diff-редактор через §1(е)/E.7; Q4c/Q2c/Q5 — явные строки в §9).
Столпы (инварианты 1–8 backend/README.md, ломать нельзя): деньги/durability (committed==SUM, kill-9);
снапшот-дисциплина (правка wire/вердиктов = громкий resnapshot; все правки этого плана → ЕДИНЫЙ resnapshot §8);
детерминированный банк (не вектора); эхо-мина DeepSeek (thinking НИКОГДА не off); 18+; конфиг-первое ядро;
экспорт-контракт (внешняя экстракция ТОЛЬКО tmctl export); golden-гард детерминизма; инвариант общности §0.1
(любая книга/пара/структура; пара = ось данных).
Сводка $0-верификаций (все PASS, детали в каждом WS (г)):
| WS | Верификация | Результат |
|---|---|---|
| WS2 | фертильность независимо пере-выведена | 1.1978/0.3852, R²=0.9633 (Δ<3e-5); классиф.-mismatch на zh = 0 |
| WS2 | нарезка на 25 главах | target_out=1797 → тот же СЧЁТ 56 чанков (4 ре-сегм / 2 абзац-сдвига, НЕ byte-identical); edit-единица: 8000-арм 25/25 в 2k–8k, ратиф. дефолт 3200 → 37 единиц (11 глав делятся; размер ГЕЙТИТСЯ Q2a) |
| WS3 | майнер-v1 golden | катастроф {方源:0,蛊:1,蛊师:2,古月:21} EXACT (вариант A / Python-референс; при ратиф. дефолте B → 古月:22, скрин PASS — §3(г)/(д) split-фикстура); 13618 канд.; recall 0.965/0.932 |
| WS3 | сид-дельта + линт | 61 терм, 0 фейл-лаудов; флагает D38-дефект как draft ⟨проверить⟩ |
| WS4 | банкнота пере-парс | 95 строк/65 src/0 fail/0 trunc EXACT; hash resume-стабилен |
| WS5 | чекеры | 6/6 позитивов; DC1/2/6 n=1 (реальные, FP-rate §5д); DC3 3.5% (1 паратекст + 1 narrative-coref на hidden); DC5 74%/42% → не гейт; DC7 не покрыт $0 |
| WS1 | деньги под ∥ + wall-clock | money-инвариант ALL PASS (границы ПАРАЛЛЕЛЬНЫ); within-wave compute ≈7.3× (end-to-end + W1.5-стоп) |
| WS6 | COGS per-арм | glm-5 $0.335 / mistral $0.205 / deepseek-pro $0.117 (25-гл, warm/valley) |
§1. WS1 — Волновой раннер (слой 1 / оркестровка)
Целевой раннер: W0 (чанкер + контекст-пакеты, $0) → W1 черновики параллельно → W1.5 (стоп-граница:
банк-синк, подпись владельца, resnapshot) → W2 редактуры параллельно. Сегодня перевод строго последователен:
bookrun.go итерирует плоский список чанков, translateChunk (chunkrun.go:90) гонит ВСЕ стадии одного чанка по
порядку под ОДНИМ snapID. Волны разносят: W1 = только draft-стадия по всем чанкам; W2 = только edit-стадия по всем
единицам; W1.5 между ними.
(а) Что меняем (модули, file:line)
runner.go— новый волновой драйвер (илиbookrun.goрасширяется режимом waves); закрыть гонку lazy-initRunner.client(runner.go:171-181):r.clients map[string]llm.LLMClientчитается+пишется без лока.bookrun.go— цикл книги переходит на волны; per-chapter sticky-reset (stickyWin=nil, HEAD ~bookrun.go:144) переезжает в W0-precompute.chunkrun.go—translateChunkрасщепляется на per-волна проходы; sticky-цепочка (chunkrun.go:107-115:memSel=r.memory.Select(...)→activeIDs→ следующий stickyPrev) precompute'ится в W0.snapshot.go—snapshotID()(:101-279) становится пер-волновым (см. (в)).stagerun.go— деньги/чекпоинт-путь (Reserve→SettleWithCheckpoint,:312-449) без изменений семантики, но вызывается из N горутин;client(model)предвычислен.config/pipeline.go— новый конфигwaves.workers(число воркеров волны — НЕfanout.workers:Fanoutзанят C2-кандидатами,CheckRunnableотвергаетcandidates>1pipeline.go:208-209; оси ортогональны) +pricing_windowsпровайдера + пер-модельный rate-guard (ревью-2 F4):models.yamlmax_concurrency/опц.min_intervalНА МОДЕЛЬ (конфиг, НЕ хардкод); rate-guard = транспорт-ось, НЕ снапшот (wire-байты не трогает).
(б) Алгоритм (детерминизм явно)
W0 (детерминированный, $0):
SplitChunks(draft-чанки, WS2) + сборка edit-единиц (WS2).- Predвычислить sticky-цепочку: один упорядоченный проход по чанкам КАЖДОЙ главы; для чанка
istickyPrev_i = union предыдущих stickyDepth=2 чанков той же главы(портbookrun.gounionSticky), затемmemSel_i = memory.Select(chunk_i, chapter, stickyPrev_i, budget),activeIDs_iкормитstickyPrev_{i+1}.Select— ПУРЕ детерминированная функция(chunk, chapter, stickyPrev, budget, frozen-bank)(memory.go:324), src-производна, БЕЗ модель-выхода → precompute воспроизводит БАЙТ-в-БАЙТ ту же инъекцию, что онлайн-цепочка последовательного раннера. Инвариант: precompute'нутые инъекц-байты ≡ байтам текущего раннера (golden-тест в (д)) → sticky-переезд НЕ двигает request_hash, НЕ строка манифеста resnapshot. ⚠ Byte-identity держит только над BASE-банком и над НОВОЙ нарезкой (WS2 сдвигает 4 чанка); golden-тест (д) сверяет против нового чанк-сета, не старого. (Параллелизм байты НЕ меняет —Selectsrc-производна, порядок фиксирован; ревью-1 CONFIRMED.) - Eager-build клиентов: множество моделей известно из
Pipeline.Stages[].Model∪EscalateToдо старта → построить ВСЕllm.LLMClientв W0 (BuildClient,clients.go:15), заполнитьr.clientsДО любой горутины. Закрывает гонкуrunner.go:171-181без лока (карта только читается в волнах;r.client()вызывается ровно в одном местеstagerun.go:343сmodel∈{st.Model, EscalateTo}— перечисление ПОЛНОЕ). Защита от будущей 3-й модель-оси (channel B / annotator,stagerun.go:476-478): в волновом режимеclient()делается READ-ONLY (panic/error на miss), чтобы не-перечисленная модель не пере-открыла гонку тихо. Прочие разделяемые хендлы:templates(построена раз вloadTemplates, read-only в волнах — safe),memory *MemoryBank(материализован раз, immutable — safe),Store(single-writer сериализует записи — safe),Log(slog thread-safe).
W1 (∥): N воркеров тянут draft-чанки из очереди; каждый — runStage(draft-стадия) под snapshot_W1. Деньги:
Reserve→Complete→SettleWithCheckpoint (stagerun.go) — сериализуются через single-writer store-пул
(store.go:71 MaxOpenConns=1, BEGIN IMMEDIATE). Ретрай чанка i изолирован: его вход — чистая функция
(source_i, frozen-bank, snapshot_W1), независим от чанка j (свойство волн — нет разделяемого мутабельного входа).
W1.5 (стоп-граница, $0 к провайдерам кроме опц. облачной Z1-адъюдикации): банк-майнинг из W1-черновиков
(WS3) → алиас-кластеризация ярус-1 → канон-предложения (draft) → карта подписи (сайдкар) → подпись владельца
(approve/правка/draft/расклеить) → эмиссия сид-дельты → reseed → snapshot_W2. Механика стопа (см. (в)).
W2 (∥): N воркеров тянут edit-единицы (главы, WS2); каждый — runStage(edit-стадия) под snapshot_W2, читая
draft из W1-чекпоинта (prev = draft-текст единицы). W1-чекпоинты под snapshot_W1 НИКОГДА не пере-гоняются →
W1 не пере-оплачивается. Инъекция редактора W2 (ревью-2 F3, специфицировано): edit-стадия единицы получает
СВЕЖИЙ memory.Select по тексту ВСЕЙ единицы (глава) над ОБОГАЩЁННЫМ банком (sticky-окно на уровне глав вырождено:
единица = глава); констрейнт-блок renderEditorConstraintBlock = CONFIRMED-only, формат src→dst (решение WS2 §2(б)).
Явный запрет: НЕ реюзить per-чанк memSel из W0 (chunkrun.go:107-114) — тот посчитан над BASE-банком, W2 поехала
бы БЕЗ майненого банк-энфорса. Это НЕ противоречит инварианту секвенирования (в): свежий Select кормит ТОЛЬКО
edit-стадию (CONFIRMED-only enriched-банк), draft-стадия по-прежнему НЕ пере-рендерится/не пере-хешируется. Пин — (д):
инъекция W2 содержит подписанные на W1.5 mined-термы.
Пер-модельный rate-guard (ревью-2 F4, НЕСУЩЕЕ для ∥): пер-ВЫЗОВНЫЙ 429/Retry-After УЖЕ есть в адаптере
(httpllm.go:27-29,138-140, читается+уважается, кап maxRetryAfterWait=5мин :76; тест
TestRetryOn429HonoursRetryAfter httpllm_test.go:168) — до WS1 раннер БЫЛ последователен, проблема
N-параллельности НЕ возникала. Гэп именно N-конкуренция. Волновой диспетчер добавляет пер-модельный семафор
конкуренции (+опц. пейсинг min_interval) из models.yaml + телеметрию 429-плотности. Rate-guard НЕ снапшот-ось
(транспорт, wire-байты не трогает). ⚠ Известный лимитер: mistral-large-latest ~48% retry-fails @1.3s интервала,
max lat 64.7s (судейский eval-риг exp15 §7.6 REV.2; grok 0%); расширение 1.3→2.6s эффекта НЕ дало (49.5→48.2%) →
похоже на токен-бакет/конкуренцию, тир-зависимо → mistral-арм НЕ идёт через прод-путь до rate-guard (WS6
пред-условие). Заготовка-блок для 00-provider-quirks.md — §12 (вносит оркестратор при лендинге, зона полигона).
Money под параллелизмом (доказано верификацией): потолок проверяется ВНУТРИ Reserve immediate-транзакции
(ledger.go:56-72: committed+reserved+estimate ≤ ceiling) → конкурентные резервы N воркеров сериализуются
single-writer'ом, overshoot ≤ одной макс-резервации. Урок D12 (гонка Runner.clients + commit-terms-on-boundary):
клиенты предвычислены (закрыто); commit-терминов на границе джобы в этой архитектуре не применяется (банк
консолидируется в W1.5, не на границе чанка).
(в) Конфиг + снапшот-механика — ПЕР-ВОЛНОВОЙ снапшот (несущее)
Сегодня snapshotID() — book-global, фолдится в КАЖДЫЙ request_hash (stagerun.go:268-269: snapID — прямой
вход). Правка snapID = all-or-nothing re-bill (snapshot.go:26-34); content-addressed reuse (msgsContentHash)
гейтится НЕ-изменённым снапшотом → через resnapshot не срабатывает (D15.2 — не построен). Проблема: банк входит
в snapshotID через MemoryVersion (snapshot.go:191,229); наивный resnapshot после W1.5 сдвинул бы snapID для
ВСЕХ стадий, включая W1 → пере-оплата W1 → «две переоплаты».
⚠ Коррекция после адверсариал-ревью-1 (несущее): «переоплата ОДНА» держит НЕ снапшот, а ВОЛНОВОЙ ИНВАРИАНТ
СЕКВЕНИРОВАНИЯ. request_hash фолдит рендер msgs НАПРЯМУЮ (stagerun.go:268-269), не только через snapID;
resume-fast-path отдельно сверяет cs.ContentHash == msgsContentHash(msgs) (stagerun.go:65,79). W1-инъекция
переводчика (renderGlossaryBlock, memory.go:480,484-487) эмитит ВСЕ строки с непустым dst, ВКЛЮЧАЯ AMBIGUOUS
(auto/draft, помечены ⟨проверить⟩) — а WS3-майнинг добавляет до 21 draft-строки с dst. ⇒ если W2-проход когда-либо
ПЕРЕ-рендерит/пере-хеширует draft-стадию над обогащённым банком, её msgs→contentHash→request_hash меняются → miss →
re-bill W1, даже при byte-identical snapshot_W1. Несущий инвариант: W2-проход НИКОГДА не трогает рендер/хеш
draft-стадии; редактор получает черновик из W1-ЧЕКПОИНТА (final_hash→response_text), не из свежего draft-рендера над
обогащённым банком. Это ПРЯМО противоречит текущему translateChunk, который считает memSel ОДИН раз и рендерит
инъекции ОБЕИХ стадий из него (chunkrun.go:107-114) — наивный волновой сплит, пере-считывающий memSel в W2 для
content-verification, пере-выведет draft-инъекцию над обогащённым банком и споткнётся ровно тут. Волновой раннер обязан
разнести: W2-проход рендерит ТОЛЬКО edit-стадию, черновик читает по final_hash.
Роль пер-волнового снапшота (уточнено): он НЕ предотвращает re-bill (это делает инвариант выше) — он избегает
громкого resnapshot-СТОПА (stagerun.go:45-49): на резюме-после-W1.5, если владелец промоутнул майненые строки в
approved (это ДВИГАЕТ MemoryVersion, memory.go:264-282), book-global снапшот сделал бы snapshot_id уже-готовых
draft-джоб ≠ пере-вычисленному глобальному → hard-стоп. Пер-волновой снапшот держит W1-джобы на snapshot_W1 (стабилен)
→ стопа нет. snapshotID вычисляется пер-волна, фолдя ТОЛЬКО стадии этой волны + состояние банка на момент волны.
Хранение уже пер-стадийное — jobs UNIQUE(book_id, chapter, stage) (migrate.go:37), каждая джоба несёт свой
snapshot_id. Под-специфицировано (реальная ре-архитектура, не кноб — бэкенду построить): сегодня snapshotID()
фолдит ВСЕ стадии + ОДИН book-global MemoryVersion в ОДИН хеш (snapshot.go:229), TranslateBook апсертит РОВНО один
снапшот (bookrun.go:117-123). План требует: раннер вычисляет ДВА MemoryVersion (base vs enriched, разбивка по
Source ниже), апсертит ДВА снапшота (W1/W2), пинит стадии волны к своему. Сейчас все стадии получают ОДИН snapID;
план делает MemoryVersion (и stage-plan) компонентом волны:
snapshot_W1 = f(brief, chunkerVersion, draft-stage-plan, base-bank-version, coverage/sanitizer/classifier/…).snapshot_W2 = f(brief, chunkerVersion, edit-stage-plan, enriched-bank-version, …). W1.5-обогащение банка двигает ТОЛЬКОenriched-bank-version→ ТОЛЬКОsnapshot_W2. W1 стабилен.
Механизм стабильности W1 на РЕЗЮМЕ (несущее, закрывает re-bill-дыру): после W1.5 сид ОБОГАЩЁН (дельта влита) →
наивный пересчёт snapshot_W1 из ТЕКУЩЕГО (обогащённого) банка дал бы enriched-memory-version → mismatch с замороженным
в W1-джобах snapshot_id → resnapshot-стоп → re-bill W1. Фикс использует поле Source (glossary.go:36,
seed|ruby|auto + новое mined WS3): base-bank-version = хеш approved-строк с Source∈{seed,ruby} (БЕЗ mined);
enriched-bank-version = хеш ВСЕХ approved-строк (вкл. Source:mined). Майненые строки исключены из W1-фолда →
computeMemoryVersion-вариант для W1 пере-вычисляется из НЕ-майненых строк, стабилен через W1.5-обогащение (майнинг
только ДОБАВЛЯЕТ mined-строки, не трогает seed/ruby) → snapshot_W1 воспроизводится идентично на резюме → W1-чекпоинты
ХИТ, не пере-оплачиваются. Детерминировано (фильтр по Source + сортировка GlossaryForBook). Пиновый тест — (д).
⚠ Скоуп подписи W1.5 = ТОЛЬКО Source:mined (ревью-2 F2, инвариант — прямое следствие фикса выше): mid-run
подпись владельца на W1.5-границе трогает ИСКЛЮЧИТЕЛЬНО Source:mined-строки (промоут draft→approved, правка dst
майненого терма). Правка/промоут APPROVED Source∈{seed,ruby}-строки ДВИГАЕТ base-bank-version → mismatch с
замороженным в W1-джобах snapshot_W1 → resnapshot-СТОП / re-bill W1 — поэтому разрешена ТОЛЬКО как ОТДЕЛЬНОЕ
resnapshot-событие ВНЕ прогона (пред-прогонный reseed §8), НЕ на W1.5-границе. (Уточнение precision: DRAFT-status
seed/ruby-строка НЕ фолдится в base-bank-version [gate off, memory.go:264-266], но W1-инъектится через
renderGlossaryBlock → её правка = ТИХИЙ per-чанк re-bill через contentHash-путь stagerun.go:72-79, не громкий стоп;
реалистично seed/ruby = approved, пин (д) это разделяет.)
- Write-path
Source:mined(ревью-2 пост-верифай, НЕСУЩЕЕ — закрывает грунт-гэп критика):loadGlossarySeedБЕЗУСЛОВНО штампуетSource:"seed"(memseed.go:131) — наивный reseed W1.5-дельты через него проштамповал бы майненые термыSource:seed→ они попали бы вbase-bank-version→ сдвинулиsnapshot_W1→ сломали «переоплата ОДНА». ⇒ персист майненой дельты после подписи идёт ОТДЕЛЬНЫМ mined-write-путём (штампSource:mined, зеркалоrubyToCandidates'sSource:"ruby"memseed.go:352) — НЕ через немодифицированныйloadGlossarySeed(хардкодитSource:"seed":131) и НЕ расширениемseedTerm-схемы (та остаётся БЕЗ новых полей — §3(б); Source-класс живёт в сайдкар-карте подписи). Пин — WS3 (д). - Промоут
甲乙丙丁/四代族长(DC-7): майнер СЮРФЕЙСИТ их какSource:mineddraft (флаг-для-видимости §3(б)); но их промоут в approved-канон = ЭЛЕВАЦИЯ вSource:seed(канон грейд/титул = base-seed-класс, не run-time mined) → поэтому строго в пред-прогонный reseed (§8,MemoryVersionдвигается), НЕ в W1.5-подпись. Пин-тест — (д): правка approved seed-строки после W1 → ГРОМКИЙ resnapshot-стоп, не тихий re-bill.
Механика W1.5 для ОБОИХ состояний гейта (доказуемо «переоплата ОДНА»):
PostcheckGate=false(текущий дефолт):computeMemoryVersion(rows, gateOn=false)фолдит ТОЛЬКО approved-строки (memory.go:264-266). Майненые auto/draft НЕ двигают снапшот; их вливание меняет лишь инъекцию стадий, которые их инъектят. На момент W1 банк = base (майнинг идёт ПОСЛЕ W1) → W1-инъекция = base. В W1.5 подпись владельца промоутит часть в approved →enriched-bank-versionменяется →snapshot_W2двигается ОДИН раз. Auto/draft (AMBIGUOUS) в редакторский блок (renderEditorConstraintBlock, CONFIRMED-only,memory.go:515) НЕ входят.PostcheckGate=true(hard-gate, висит за пере-замером D24.4/D28.1):computeMemoryVersion(rows, gateOn=true)фолдит ВСЕ строки вкл. auto/draft +gate:-флаг (memory.go:251-266,snapshot.go:86-93). Но на момент W1 майненых строк ещё НЕТ →base-bank-versionреально base. В W2 банк обогащён →enriched-bank-versionвключает все майненые строки. Пер-волновой снапшот держит «одну переоплату» и здесь: W1 под base, W2 под enriched.
UX-решение (стоп посреди книги) — владельцу (§10 вопрос W1.5-UX; §E-5 research/20). Дефолт плана: W1.5 — явная
стоп-граница (не mid-run-append): раннер завершает W1, пишет карту подписи, ОСТАНАВЛИВАЕТСЯ; владелец подписывает;
tmctl возобновляет с W2 под snapshot_W2 (--resnapshot принимает сдвиг). Sticky/scene-инерция precompute'ится в
W0 (src-производна) — не ломается параллелизмом.
Scheduler-aware диспетчер: ценовые окна = конфиг провайдера (providers.json/models.yaml), не хардкод.
Вендор-чеки ($0, разрешены):
- (а) DeepSeek пик/офф-пик — РАЗРЕШЁН (флаг D39.10-6): два механизма из разных эр, НЕ конфликт. Легаси off-peak
СКИДКА
16:30–00:30 UTC −50%/−75%— только V3/R1, НЕ переносить на v4. Актуально для v4: PEAK-надбавка ×2 в UTC 01:00–04:00 ∪ 06:00–10:00 (пики Пекин 09–12 & 14–18); офф-пик = baseline (доп. скидки НЕТ). ⚠ ×2 подтверждён ТОЛЬКО вторичкой (TechNode/explainx/KuCoin); офиц.api-docs.deepseek.com/quick_start/pricingна 2026-07-19 — ФЛЭТ, без peak/off-peak. Правило двух направлений: держать ×2 как РИСК-ПИН, ре-чек у катовера 24.07. Раннер: платные DeepSeek-джобы вне пик-окон; нельзя — закладывать ×2, не блокировать. (URL: docs §157–167.) - (б) ZAI/GLM префикс-кэш — РАЗРЕШЁН (§E.8-бис): implicit префикс-кэш подтверждён на
glm-5(docs.z.ai/guides/capabilities/cache); cache-hit = $0.20/1M (−80% от input $1.00), НЕ 50% из иллюстрации доки; хранение бесплатно (limited-time); TTL официально НЕ документирован (агрегаторные «5мин/512ток» НЕ подтверждены). Warm-then-fan оправдан: warming-вызов платит полный input, фан-аут-соседи — cache-hit. Инвариант байт-идентичного ПРЕФИКСА ([система+мандаты]+[глоссарий сорт-ключи]→[волатильный чанк в хвост], research/19:506): любой timestamp/ счётчик-ретрая/«почему упало» — только в ХВОСТ (:213). Бэкенд УЖЕ читаетcached_tokens(httpllm.go:232-255); реальную долю cache-hit верифицировать в ledger (эмпирика бьёт веру, TTL-риск). - (в) Слаги DeepSeek 24.07 — РАЗРЕШЁН:
deepseek-chat/deepseek-reasonerдепрекация 2026-07-24 15:59 UTC → оба на v4-flash (chat=non-thinking, reasoner=thinking). Наш продdeepseek-v4-flash/deepseek-v4-pro— НЕ задет. Действие бэкенду: grepconfigs/models.yaml+ eval-скриптов на legacy-слаги + liveGET /models. (research/19 §E.8: eval-скрипты несут legacy-слаги —exp15/preflight_models.py:32,local_bench.py,editor_bench.py:36— это eval-долг, не прод.)
(г) Верификация ДО стройки ($0) — ws1_wave_cogs.py, РЕЗУЛЬТАТ
- Money-инвариант (mock, моделирует single-writer admission-ось
ledger.go; НЕ полное зеркало — см. каветы): ALL PASS —committed==SUM($0.448),reserved=0, kill-9 без двойной оплаты (идемпотентный settleledger.go:143ON CONFLICT DO NOTHING). ⚠ Границы — ПАРАЛЛЕЛЬНЫЕ, не последовательные (адверсариал-ревью-1): (1) kill-9 теряет ≤N in-flight вызовов (recoverReservationsобнуляет ВСЕreserved_usd,store.go:219), каждый пере-оплачен ОДИН раз — не «≤1»; (2) overshoot: реальныйReserveОТКЛОНЯЕТ приbookTotal+estimate>ceiling(ledger.go:67-71) → reserved потолок не пробивает; единственный overshoot-источник = settle бронируетcostприcost>estimate(priciermodelActualPriceForResponsestagerun.go:420; reasoning-overflow) → под N резервами bound =Σ(cost_i−est_i). Mock это НЕ проверяет (cost=0.008<est=0.01захардкожен) → закрепляет Go-тест в (д). Каветы неверности mock: проверяет ОДИН потолок (реальный book И dayledger.go:67-71); settle НЕ идемпотентен (реальный да,ledger.go:151-160) — обе оси в Go-тест (д). Реальную durability пинит Go+SQLite-race+kill-9 с N живыми резервами в (д). - Wall-clock (mock-латентности, LPT bin-pack): ВНУТРИ-ВОЛНОВАЯ compute-параллелизация sequential-compute 1896s
→ волны 8-воркеров 258s ≈ 7.3× (W1 121s + W2 138s). ⚠ End-to-end доминирован W1.5 человек-стопом (подпись
владельца между волнами — неограниченное ожидание, в 7.3× НЕ входит); mock — единый
LAT_PER_KTOKдля thinking-ON черновика и редактора (разные профили). ⚠ 7.3× НЕ учитывает rate-limit-столлы (ревью-2 F4): пер-модельный семафор + 429-бэкофф сериализуют вызовы к лимитированной модели (mistral ~48% retry-fails) → реальный wall-clock волны ниже compute-идеала. Порядок-величины; точные латентности — прод-телеметрия. - Структура: 25 глав → 56 draft-чанков (target_out 1797) + 25 edit-единиц. COGS — WS6 (г).
(д) Тест-спека ПОСЛЕ стройки
go test -race ./...над волновым раннером: N-воркер прогон, детектор гонок чист (клиенты/store/templates/memory).- kill-9-тест с N живыми резервами: убить процесс между
ReserveиSettleWithCheckpointдля N чанков → рестарт:recoverReservationsобнуляет резервы, ретрай оплачивает ≤N вызовов ОДИН раз каждый;committed==SUM(checkpoints.cost)(портstore/kill9_test.goна волны). + overshoot-тестcost>estimate(pricier modelActual): overshoot ≤ Σ shortfall. - Golden: инъекц-байты W0-precompute sticky ≡ байтам текущего последовательного раннера над НОВЫМ чанк-сетом WS2 (fresh↔resume; sticky не двигает request_hash над base-банком).
- НЕСУЩИЙ пин (ревью-1 F1): draft
request_hash/contentHashБАЙТ-СТАБИЛЕН под ОБОГАЩЁННЫМ банком — W2-проход не пере-рендерит draft-стадию; редактор читает черновик поfinal_hash. (Не просто «snapshot_W2двигается».) - Пер-волновой снапшот: промоут майненых→approved двигает ТОЛЬКО
snapshot_W2(W1-джобы не ловят resnapshot-стоп);base-bank-version=хешSource∈{seed,ruby}-строк стабилен через W1.5. - Пин скоупа подписи W1.5 (ревью-2 F2): правка/промоут
Source∈{seed,ruby}-строки ПОСЛЕ W1 → ГРОМКИЙ resnapshot-стоп (не тихий re-bill W1); правка ТОЛЬКОSource:mined-строки → двигает лишьsnapshot_W2, W1 стабилен. - Race-тест
Runner.clients(D12-урок):client()read-only в волнах, panic на miss не-перечисленной модели.
(е) Открытое / маршрутизация
- Соседи-черновики как контекст W2 — НЕ ратифицированы (Q3a null + гипотеза CJK-протечки V2-брака §7.9: src- carryover → больше исходника → выше протечка). Дефолт: без них. Если бэкенд захочет — обоснуй + дешёвый гейт.
- Lookahead (Q3b) — парковка (не тестировано). Не в дефолт.
- W1.5-UX (стоп посреди книги vs автопродолжение) — вопрос владельцу (§10).
- Пик-надбавка DeepSeek ×2 — риск-пин, ре-чек 24.07 (§10).
§2. WS2 — Чанкер-бюджет + крупная edit-единица (слой 1)
(а) Что меняем (file:line)
chunker.go— бюджет изconst targetChunkTokens = 1500(:47, единицаestTokensFrom=cjk+other/3:173-181) → конфиг per-pair в ВЫХОДНЫХ токенах через фертильность;Chunk{Chapter,ChunkIdx,Text}(:32-36) расширяется аддитивно (EstOut float64,OversizedSentence bool,EditUnitID int). Мега-ПРЕДЛОЖЕНИЕ (packSentences:129-152: своё оверсайз-под-чанком БЕЗ клауза-сплита и БЕЗ флага) — решить (см. (б)).config/pipeline.go— снести мёртвыеSTMDepth/OverlapTokens(:47-48, carryover не строим); добавитьSegmentation{DraftBudgetOut int, EditCeilingOut int, Fertility{CJK,Other float64}}(per-pair, снапшот-folded).coverage.go— инвариант floor: draft-бюджет держит чанки надGates.Coverage.MinChunkChars(pipeline.go:159, дефолт 500); связь-инвариант, не жёсткий (хвосты глав легально < floor — документ. границаchunker.go:42-45).snapshot.go—contextSnap(:15-21) теряет STMDepth/OverlapTokens; добавляетсяsegmentationSnap(бюджет+фертильность+edit-ceiling, фолд какcoverageSnap).- новый
slojpjat-омиссия-бэкстоп в слое 5 (см. WS5/(б)) — компенсатор зоны деградации.
(б) Алгоритм
- Draft-чанк = мелкая единица (COGS/coverage/выравнивание): greedy-упаковка абзацев (как сейчас,
appendChapterChunks), но бюджет =est_out(chunk) = 1.1978·cjk + 0.3852·other(ВЫХОДНЫЕ токены) вместо input-est. Оверсайз-абзац →packSentences; НИКОГДА не резать предложение. (WS2 (г): на zh смена единицы near-нейтральна — тот же СЧЁТ 56 чанков при target_out=1797, НО 4 из 56 чанков ре-сегментируются (2 реальных абзац-сдвига на границе накопления, где est_out other-вес 0.3852 vs input-est integer other/3 расходятся) → НЕ byte-identical → законныйchunkerVersionbump §8. Ни один target_out не даёт 0 diff.)strategy-ось (greedy|logical) — заложить как СЕАМ (аддитивное поле), но наполнениеlogicalНЕ строить (Q1 «граница не рычаг», Q1a 0/7). DP §B1.5 (штрафы B0:0/B1:1/B2:3/B3:6/B4:10, веса w_size=3/w_bound=60/w_dialog=200) — справочно в research/19, НЕ реализуем. - Мега-предложение (решение плана):
packSentencesпропускает мега-ПРЕДЛОЖЕНИЕ оверсайз-под-чанком без флага. Решение: passthrough + флагOversizedSentence=true(не аварийный клауза-сплит ;:,、 из §B1.4). Обоснование: клауза-сплит = граничная машинерия (анти-скоуп); «деградация не молчит» удовлетворяется ФЛАГОМ (наблюдаемость). Мега-абзац уже покрыт (packSentences). Стихи/паратекст — как обычный текст (§0.1: не спец-кейсить структуру книги); стих-РЕНДЕР — пак-политика WS5-DC5. - Edit-единица = глава — ДЕКАПЛИНГ draft/edit ратифицирован (D39 п.4, exp14 претензия-1: редактору нужна КРУПНАЯ
единица для меж-чанковой когезии). Глава = естественная дискурс-граница; глава >
EditCeilingOut→ деление по АБЗАЦНЫМ границам greedy до потолка (never-split-paragraph). На 25-гл книге при дефолте 3200: 11 глав делятся → 37 edit-единиц (при гейтнутом 8000-арме — 25 цельных глав, 0 > 8000, max 6528, все в 2k–8k; ревью-2 F1 — детали (г)). ⚠ РАЗМЕР единицы ГЕЙТИТСЯ (ревью-1 F1, не «безопасно»): span-омиссия Q2a НЕ гонялась; omission-бэкстоп WS5 — сеть ENTITY-уровня (сущность есть где-угодно), СТРУКТУРНО СЛЕП к пропуску клауза/сцены внутри 6.5k-единицы, чьи сущности повторяются (самreflow_omission.py:205-212: «NOT evidence big chunks omission-safe… needs SPAN-JUDGES; Q2b cannot ratify edit=chapter, only Q2a»). Решение: глава-единица — ЦЕЛЬ; для пере-прогонаEditCeilingOut— консервативный дефолт ≤3200 out (край нижней зоны деградации, а не 6.5k), большая-глава-арм ГЕЙТИТСЯ платными Q2a span-судьями (прогон-протокол WS6/(д)) + чтением владельца (2-претензии ловят span-омиссию). Owner-развилка §10. Единица маппится на чекпоинты: деньги/resume per-СТАДИЯ-волна, НЕ per-микро-чанк — против инварианта №1: чекпоинт = единица оплаты стадии, волна = последовательность. - Сайзинг edit-единицы (ревью-2 F8, ИСПРАВЛЕНО пост-верифай): unit-awareness сайзинга УЖЕ автоматическая —
stagerun.go:87-90(D2.5) сайзитmax_tokensотsizingText=prev(для стадии >0 = ЧЕРНОВИК всей единицы, НЕ источник):EstimateTokens(prev)·MaxOutputRatio+ пер-модельный флор D24.3 (applyModelFloor);Reserveтоже text-proportional по msgs. ⚠ НЕ сайзить отest_outединицы (первичная формулировка F8 «от est_out» НЕВЕРНА):est_out=1.20·cjk+0.39·otherИСТОЧНИКО-производна и в glm-4.6 output-token-пространстве (≠ эвристикаEstimateTokenscjk+other/3), а D2.5 прямо сайзит редактора от ЧЕРНОВИКА (~1.9× источника) — сайзинг от источника недо-бюджетит и ложно-триггерит length-ретрай. ⇒ единственное требование: edit-единица передаёт СВОЙ ПОЛНЫЙ черновик какprev(волновой дизайн W2 это и делает, §1(б)); НОВОЙ формулы сайзинга НЕТ → строки манифеста §8 F8 не требует. Инъекция единицы (ревью-2 F3, детали §1(б)): свежийmemory.Selectпо тексту ВСЕЙ единицы над ОБОГАЩЁННЫМ банком (НЕ реюз per-чанк W0-memSelнад base); формат src→dst, CONFIRMED-only. - Формат банк-констрейнтов редактора (открытый вопрос D30.1,
memory.go:505-511— решается ЗДЕСЬ, парковка запрещена): сегодняrenderEditorConstraintBlock(:515) даёт ГОЛЫЕ dst-формы (- «dst», CONFIRMED-only, дедуп по dst). Решение: перейти на src→dst-мэппинг (- 源термин → «dst»), как у переводчика. Обоснование (единственное несущее — ревью-1 F4 снял два ложных): редактор БИЛИНГВ (D30.1,editor.md:1видит источник) — привязка канона к src-терму устраняет неоднозначность при ОМОНИМИЧНЫХ dst (одна ru-поверхность на две сущности). ⚠ Отвергнутые обоснования: «AMBIGUOUS-строк станет больше» — НЕ-секвитур (блок CONFIRMED-onlymemory.go:519, майненые AMBIGUOUS сюда НЕ входят); «инвариант кэш-префикса» — нет (блок из per-chunkmemSel.injected= волатильный ХВОСТ, не стабильный префикс). Мех-безопасность:RequestHashхешируетmsgsвкл. блок → формат-правка меняет request_hash, тихого false-hit нет; CONFIRMED-only СОХРАНЯЕТСЯ; дедуп по (src,dst) лишь РАСШИРЯЕТ список (безвредно). Снапшот-фолд ЯВНЫЙ: формат рендераrenderEditorConstraintBlockНЕ схватываетсяmemoryMatchVersion(тот = нормализатор/матчер) — добавить версию формата рендера как folded-компонент снапшота (иначе loudness держится дисциплиной, не механизмом).
(в) Конфиг + снапшот
- Фертильность
{cjk:1.1978, other:0.3852}— конфиг слоя 2 (per-pair), снапшот-folded; пересчёт = громкий resnapshot (D30.9). Go грузит ТОЛЬКО коэффициенты (не токенайзер). DraftBudgetOutдефолт 1797 (тот же СЧЁТ 56 чанков, что текущий input-est=1500 на zh; 4 чанка ре-сегментируются, 2 абзац-сдвига — НЕ byte-identical, WS2 (г)) — «tunable, ревизия по пере-прогону».EditCeilingOutдефолт 3200 out (ревью-2 F1: приведено к WS2(б)/§7/§10-13/§11 — прежнее «8000» ЗДЕСЬ противоречило консервативному дефолту; 3200 = край нижней зоны деградации) — tunable. 8000 out = потолок ГЕЙТНУТОГО крупно-главного арма (верх зоны деградации research/19 §A.1.1), открывается ТОЛЬКО по платным Q2a span-судьям (§10-13), НЕ дефолт.- Снос STMDepth/OverlapTokens меняет
contextSnap-структуру → строка манифеста resnapshot §8 (снапшот двигается). - ⚠ Классификатор CJK (WS2 (г) находка §1.6):
fertility_calib.is_cjk= ord-диапазоны БЕЗ Hangul;EstimateTokens(render.go) =\p{Han}\p{Hiragana}\p{Katakana}\p{Hangul}. На ЭТОМ zh-корпусе — 0 сдвиг коэффициентов (verified — но КОРПУС-СПЕЦИФИЧНО: корпус не содержит спорных символов々/〇/CJK-радикалов, kana-марок・ー). ⚠ ws2_fertility_verify классификатор B — НЕ верный Go-прокси (ревью-1 F3: исключает々/〇/радикалы, чтоunicode.Hanвключает; включает・ー, чтоunicode.Katakanaисключает) → скрипт НЕ доказывает ja/ko-общность. Решение: Go-порт использует РЕАЛЬНЫЕunicode.RangeTableEstimateTokens(для общности §0.1); инвариантность задокументирована для ДАННОГО zh-корпуса, не как свойство классификатора; ja/ko-паритет — верифицировать Go-таблицами (после стройки). Коэффициенты не менять (impact на текущий zh = 0 подтверждён).
(г) Верификация ДО стройки ($0) — ws2_fertility_verify.py + ws2_chunk_sim.py, РЕЗУЛЬТАТ
- Независимый пере-вывод фертильности (НЕ доверяя
fertility_calib.json):f_cjk=1.1978, f_other=0.3852, R²=0.9633, MAPE 4.25%, n=52— Δ vs артефакт< 3e-5. Классиф.-mismatch impact на zh = 0.0%. - Симуляция нарезки 25 глав: гистограммы est_out;
target_out=1797→ 56 чанков (mean 1408.8, max 1795) — тот же СЧЁТ, что текущий input-est=1500, но 4 из 56 чанков ре-сегментируются (2 реальных абзац-сдвига; проверено прямым diff чанк-сетов: чанк 1 = 1777 vs 1778 симв, чанки 11↔12 и 54↔55 — абзац переезжает; ни один target_out не даёт 0 diff). Смена единицы near-нейтральна на zh, НЕ no-op/byte-identical. Floor: 4 чанка < 500 симв (хвосты). Edit-единица — ДВА конфига симулированы (ревью-2 F1, пере-сим at 3200,ws2_chunk_sim.pyceiling∈{8000,3200}): (i) ГЕЙТНУТЫЙ 8000-арм — 25/25 глав-единиц в зоне 2k–8k out (0 глав > 8000, max 6528, hist: 14×[2k–3.2k]/10×[3.2k–5k]/ 1×[5k–8k]); (ii) РАТИФИЦИРОВАННЫЙ дефолт 3200 — 25 глав → 37 edit-единиц (11 глав > 3200 делятся абзацно на 23 под-единицы; hist out: 26×[2k–3.2k], 10×[0–1k] split-хвосты (< нижней зоны деградации — покрыты omission-бэкстопом), 1×[1k–2k]). ⟶ «25/25 в 2k–8k» описывал 8000-арм, НЕ дефолт; при 3200 единицы МЕНЬШЕ (безопаснее для span-омиссии — цель F1) ценой 10 мелких split-хвостов. omission-бэкстоп (слой 5) = СЕТЬ, НЕ доказательство безопасности (Q2a span-омиссия НЕ гонялась; бэкстоп entity-уровня слеп к span-пропуску → размер edit-единицы гейтится, см. (б)/(е)). - COGS-прогноз (no-cache upper bound): $0.403/25-гл; с кэшем — WS6.
(д) Тест-спека ПОСЛЕ стройки
- Пин:
est_out-бюджет на zh даёт СЧЁТ 56 чанков (не byte-identical к input-est) + fresh↔resume детерминизм. - Пин: мега-предложение →
OversizedSentence=trueфлаг (синтетика). - Пин: глава >
EditCeilingOut→ абзацный сплит (never-split-paragraph, tiling lossless). - Пин (ревью-2 F8, испр.):
max_tokens/Reserveedit-единицы сайзятся от ПОЛНОГО ЧЕРНОВИКА единицы (prev,EstimateTokens(prev)·MaxOutputRatio+ флор D24.3, D2.5) — НЕ от источника/est_out; синтетика: крупная глава, переданная целиком какprev, получает unit-масштабныйmax_tokensбез ложного length-ретрая. - Golden re-capture: снос STMDepth/OverlapTokens + фертильность-бюджет = маскированный дифф старого↔нового снапшота (только хеши/версии + новые поля).
(е) Открытое / маршрутизация
logical-стратегия — СЕАМ, наполнение парковано (Q1).DraftBudgetOut/EditCeilingOut— tunable, ревизия по пере-прогону. src→dst редакторский мэппинг — решён здесь (в план), не хвост.- Бюджет whole-chapter
Selectдля W2-инъекции редактора (ревью-2 пост-верифай, открытый): свежий Select по ВСЕЙ единице над enriched-банком (§1(б)/F3) не имеет пиннутого token-бюджета; per-чанкGlossaryTokenBudgetна всю главу (много больше матчей) может вытеснить approved-канон и разбавить enriched-энфорс. Бэкенду: per-глава бюджет ИЛИ unbounded для констрейнт-блока редактора (решить в пак-2).
§3. WS3 — Банк-машинерия W1.5 в Go (слой 4)
Go-порт детектора V-C (WHICH) + алиас-ярус-1 + консолидация §C2 + эмиссия сид-дельты. WHAT (dst) = НЕ ко-оккуренция (canon-recovery 0.20–0.68 < 70%) → dst через банкноту (WS4) + Палладий (имена) + облако (термы Z1/Z3).
(а) Что меняем (file:line)
- новый
backend/internal/pipeline/miner*.go— детектор V-A→V-B→V-C (авторитет = exp16arms.pyFROZEN, НЕ пересказ research/20 §B); алиас-ярус-1 (alias.pyR1–R4); консолидация (canon.py§C2); эмиссия сид-дельты. memseed.go—loadGlossarySeed(:64-186) читает BASE-сид + сухую валидацию дельты (штампуетSource:"seed":131); но ПЕРСИСТ майненой дельты после подписи — ОТДЕЛЬНЫМ mined-write-путём (штампSource:mined, зеркалоrubyToCandidates:314-360), НЕ черезloadGlossarySeed(F2, §1(в) — иначеSource:seedдвигаетsnapshot_W1); новыйtmctl seed-lint(сухой прогон фейл-лаудов по дельте::87src,:94-98dup,:104-108status,:113-115draft/approved-dst,:161-181спойлер-оверлап,:201-237shared-key).store/glossary.go—GlossaryEntry.Source(:36, сейчасseed|ruby|auto) +=mined; единая схема кандидата ruby↔mined (research/20 §E-бэкенд-5).store/ruby.go-паттерн — прецедентrubyToCandidates(memseed.go:314-360: Source:ruby, status:auto, no dst, Confidence=occ) зеркалится для mined-канала.- артефакты детектора — контраст-словарь (jieba SHA
7197c321…, вне git, воспроизводим из jieba 0.42.1dict.txt), паттерн-инвентари (PACK_VERSION="zh-universal-v1"), Палладий-таблица (~400 слогов, генерируемая).
(б) Алгоритм (frozen miner-v1 = exp16 §1.2 арм A3; ТОЧНЫЕ пороги)
Детерминизм-контракт: все ранкинги сорт key=(-score, -freq, src); occurrence-count перекрывающийся (pos=i+1),
suppress-free (D24.2 — subsume чистит ТОЛЬКО ранжирование); norm = normalizeSourceKey (memnorm.go, trad2simp→
NFKC→lowercase); Contrast-коллизия → MAX freq; Laplace (cf+1)/(total_char+|distinct|) идентичен в char_indep_rel и
detect_formants; Палладий-сегментация жадная longest-first, ъ отбрасывается.
- V-A: кандидаты = Han-n-граммы 1–6 (БЕЗ сегментации);
freq_floor=3; c-value nested-дисконт сg(L)=log₂(L+1)(НЕlog₂(L)— иначе 蛊/转 зануляются, катастроф-скрин FAIL, 蛊 rank 4753); weirdness =p_book/max(word_rel, char_indep_rel, 1e-9);score = max(cval,0)·termhood^1.0,termhood=log1p(weirdness); subsumptionα=0.80(дроп a если ∃ длиннее b, a⊂b, f(b)≥α·f(a)). - V-B: + spread (Dice ко-оккуренция ru-лемм, pymorphy3)
score·(1+λ·spread),λ=0.0на инъект-черновиках (spread ВРЕДИТ, конфаунд §D1), свип >0 только на cold-start;spread_freq_min=5; dst_variantstop=4, min_dice=0.05, co-salience need=max(2, round(0.30·|chunks|)). - V-C: + паттерн-каналы (
patterns.py): (1) 百家姓-якорь (SURNAMES_SINGLE после.discard(凝)+ SURNAMES_COMPOUND 16 вкл. 古月; окно 1–2 Han справа → name); (2) титул-суффиксы (TITLE_SUFFIX 26, ≤3 Han слева → title) + (2b) ordinal_title (ORDINAL 15 + suffix → 四代族长); (2c) rank/grade (GRADE_PREFIX 甲…癸 / NUMERAL / RANK_WORD 等转阶级重 品段层 → title, ловит 等/转 форманто-невидимые); (3) топо-суффиксы (TOPO_SUFFIX 26 → place); (4) авто-формант (detect_formants: символ c продуктивен если ≥min_partners=3различных морфем-партнёров Иover_rep=p_book/p_gen≥15.0— над-представленность, НЕ редкость; изолирует 蛊/窍/虫, отвергает 师/花/等); (5) Палладий ru-канал (is_palladius_token+ кап-лемма-гейтis_name_lemma→ блок «найти»=най+ти; бонус +56.0). Бонусы{name/place:140, title:120, term:80}×pattern_source_weight{surname:1.0, ordinal_title:1.0, rank_grade:1.0, title_suffix:0.9, topo_suffix:0.9, palladius:0.8, formant_suffix:0.6, formant_prefix:0.5, title_bare:0.4, default:0.3}(pw = МАКС по evidence); sub-floorscore=bonus+40.0·f·pw.top_k=90операционная точка. - Алиас-ярус-1 (R1–R4,
alias.py, precision-safe, R4 hard-blocks ПЕРВЫМИ): R4-ii (разный пол, кроме hidden) → R4-iii/v (разный approved dst → разные сущности ДАЖЕ при containment: блок族长⊂四代族长[D38 §3],古月⊂古月方源) → R1 containment (|X|≥2 → extension; компози-гард: long=short+Y, Y∈{title,place,term}∩gt → ФРАЗА не алиас, блок古月+族长, сохрани古月+方源) → R2 фамильный якорь → family (не identity; R4-i разные имена) → R3 общий ru-рендеринг → identity (кап-лемма-гейт: Палладий-токен И name-lemma min_syl=2). R4-ivcooccur_same_sentence. Кластеризация union-find по identity-рёбрам,sorted. Метрика — B³ (entity-level), НЕ MUC. - Консолидация §C2 (
canon.py): канон по ВСЕМ вхождениям (НЕ first-wins, анти-LTCR) × Палладий-конформность (name/place) × полнота падежной леммы.canon_recovery cover_frac=0.5. Майнер по построению НЕ пишет approved (канон-предложение = draft). Пол = 他/她-счётчики evidence, вердикт владельца (D19.3, hidden невыводим). since_ch = первая глава вхождения (авто); until_ch — только человек. - Эмиссия сид-дельты §C2-7: YAML в схеме
seedTerm(memseed.go:30-57, БЕЗ новых полей): non-seed кандидат с banknote/canon dst →status:draft(dst, ⟨проверить⟩); WHICH-only без dst →status:auto(инертен). Алиасы — поверхностями терма. Evidence/Source-класс/зоны Z1–Z5 — в сайдкар-карту подписи (прецедентdiag/glossary_v2_signoff.md), НЕ в схему сида. Пре-валидация против фейл-лаудов loadGlossarySeed = часть карты. Эмиттер обязан реюзить subsumption+fragment-фильтры (emit_owner_sheets.build_precision30: тип∈{name,place, title}, freq≥5, src∉subsumed, len≥2, не фрагмент по PARTICLE-сету), а НЕ сырой 13618-дамп (WS3 (г) находка: сырой дамп несёт §B2-фрагмент-шум). - Плагин-сеамы P1–P6 (§B5): данные/конфиг per язык/пара (идиом промпт-паков
PromptPathFor), НЕ ветки кода. Наполнение — zh(-ru) инстансы + существующий ruby-канал ja. Политика: degrade-with-flag (P2–P6, потеря recall видима в карте подписи), fail-loud ТОЛЬКО P1 (нет генератора кандидатов → майнинг для языка не заявляется). P5 = лемматизатор цели (см. ru-лемматизация ниже). P4 = таблица транслитерации по ПАРЕ (Палладий zh→ru). - ru-лемматизация (§B5 P5) — Go-прод-путь W1.5 (ИСПРАВЛЕНО ревью-1 F2, прежняя формулировка «λ=0 → лемматизатор не
нужен» ОПРОВЕРГНУТА):
λ=0глушит spread-МНОЖИТЕЛЬ, НОdst_variantsсчитается БЕЗУСЛОВНО λ (arms.py:103_dst_ofприfreq≥5), а Палладий-канал V-C потребляетdst_variants[:2]+is_name_lemma(arms.py:124-131) — обе pymorphy3-backed (spread.py:45-60,117-143). ⇒ Палладий-подканал V-C НУЖДАЕТСЯ в лемматизации даже при λ=0. Три варианта (owner/бэкенд-развилка §10): (A) faithful pymorphy3-порт (dst_variants + is_name_lemma) → Go воспроизводит golden ТОЧНО, вкл. Палладий-бонус +56.0 →古月:21; цена — нетривиальный порт лемматизатора; (B) дропнуть Палладий-подканал в Go-дефолте →古月теряет +56.0, ранг 21→22 (катастроф-СКРИН ∈top-50 ВСЁ ЕЩЁ PASS, но exact-ранг не воспроизводится); (C) surface-аппроксимация (cap-предоминантность по поверхности + стеммер для dst_variants) — грубее, паритет НЕ exact. Рекомендация (обновлено ревью-2 к ратифицированному §10-14 дефолту): дефолт (B) — дроп Палладий-подканала с явным пере-пином фикстур (古月:21→22, скрин PASS; dst доставляет банкнота, exact-ранг НЕ продуктовая ценность); (A) faithful pymorphy3-порт — ТОЛЬКО при готовой поддерживаемой Go-морфологии. omission-бэкстоп слоя 5 (WS2/WS5) — отдельно: substring- матч поdecl.forms+dst + лёгкий Snowball/Porter-ru-стеммер (Go-либа, детерминирован), pymorphy3 НЕ требуется там.
(в) Конфиг + снапшот
- Пороги miner-v1 = СТАРТОВЫЙ версионируемый конфиг
mining-v1(свип ±50% инвариантен — A3@f≥3=1.0 держится по floor/over_rep/subsume/partners).PACK_VERSION="zh-universal-v1". - Майненые auto/draft строки: при
PostcheckGate=falseНЕ двигаютMemoryVersion(memory.go:264-266); подписанные approved → двигаютsnapshot_W2(§1 (в)). Строка манифеста §8. Source:"mined"— новое значение enum (аддитивно, миграция store).
(г) Верификация ДО стройки ($0, несущая) — ws3_miner_verify.py + ws3_seeddelta.py, РЕЗУЛЬТАТ
- (г) до-стройки: Python miner-v1 на запинённых входах exp16 (§1.10 SHA: 8 код-файлов ✅, jieba
7197c321, сид175a67ad, records3de49eaf) воспроизводит golden: катастроф-ранги{方源:0,蛊:1,蛊师:2,古月:21}EXACT, 13618 кандидатов EXACT, recall@proposed full 0.9649≈0.965, test-half 0.9318≈0.932, top-1 方源 score 6640.9. ⚠ Паритет-фикстура РАСЩЕПЛЕНА (ревью-1 F1) — нельзя пинить古月:21exact И дропать pymorphy3: (i) Палладий- ИНВАРИАНТНЫЕ гарантии (Go-порт обязан воспроизвести при ЛЮБОМ ru-лемм-решении): recall@proposed 0.965/0.932, 13618-кандидат-СЕТ (членство), катастроф-СКРИН ∈top-50; (ii) Палладий-ЗАВИСИМЫЕ ранги/скоры (古月 rank/score, прочие +56.0-кандидаты): пинить exact ТОЛЬКО при варианте (A) faithful pymorphy3-порт; при (B)-дропе — пере-пин (古月→22, скрин PASS).方源/蛊/蛊师(ранги 0/1/2) Палладий НЕ трогает → инвариантны. - Юнит-фикстуры алиас-правил (exp16 §3.2): 族长≠四代族长 блок, кап-лемма-гейт «найти», компози-гард — в
alias.py(recall известных 2/2). Прогон против Python-реализации — часть фикстур порта. - Эмиссия сид-дельты §C2-7 (exp16 её НЕ эмитил — только сайдкары): 61 терм (21 draft+banknote-dst / 40
auto-без-dst); сухой линт против фейл-лаудов memseed = 0 проблем (loadable). Артефакт
books/gu-zhenren/design11/ws3_seed_delta.yaml. Находка: draft-кандидаты флагают ТОЧНЫЙ D38-дефект (古月族长→старейшина,甲/丙-грейд) какdraft ⟨проверить⟩для подписи — дисциплина «майнер не пишет approved» РАБОТАЕТ; auto-кандидаты несут §B2-фрагмент-шум → эмиттер обязан реюзить subsumption+fragment-фильтры. - (д) исполнение самого паритета Go↔Python закрепляет бэкенд после стройки (метод mem_select.py в обратную сторону: Python = референс; при расхождении чинить Go-порт).
(д) Тест-спека ПОСЛЕ стройки
- Байт/значение-паритет Go↔Python miner-v1: Go-порт воспроизводит Палладий-ИНВАРИАНТНЫЕ гарантии (13618-СЕТ, recall
0.965/0.932, катастроф-СКРИН ∈top-50) — фикстуры (г). Палладий-ЗАВИСИМЫЕ exact-ранги (古月:21) — только при варианте
(A) pymorphy3-порт; при (B) — пере-пин. Начать с
normalizeSourceKey(реюзmemnorm.go, уже байт-верифицирован черезmem_select.py). - Юнит-тесты алиас-правил (5 R4-блоков + компози-гард + кап-лемма-гейт).
tmctl seed-lint: прогон эмитированной дельты через РЕАЛЬНЫЙloadGlossarySeed(не Python-зеркало) → 0 фейл-лаудов.- Пин
Source:mined(ревью-2 F2): reseed W1.5-дельты штампуетSource:mined(НЕseed—loadGlossarySeedхардкодитSource:"seed"memseed.go:131); проверитьbase-bank-version= хешSource∈{seed,ruby}СТАБИЛЕН после вливания mined-дельты (иначеsnapshot_W1двигается → «переоплата ОДНА» сломана). - Детерминизм: повтор Go-майнера байт-в-байт (без time/rand).
(е) Открытое / маршрутизация
λ-режим (spread-коэф): дефолт 0 (инъект); свип на реальных не-инъект черновиках пере-прогона (§10).- ru-лемматизатор P5 — полный pymorphy3-паритет парковано; дефолт-майнер обходится (см. (б)).
- Мини-голд алиасов владельца (§E-1) — recall кластеризации; без него ярус-1 только по precision (§10).
- precision@30 non-seed A3 — адъюдикация владельца (§10).
- Z1-адъюдикация → ОБЛАКО (локальная 9B wrong-catch 0.333, принимает 族长→«старейшина»), НЕ локаль. Локальный 9B-споттер НЕ строим (код 0.965 ≥ локаль 0.895).
§4. WS4 — Банкнота: dst-канал (слой 4, wire-инвариант)
Спека banknote-v1 = research/20 §B3 / exp16 banknote.py: разделитель ⟦TM-BANK-v1⟧, ≤MAX_LINES=12 строк
src<TAB>dst<TAB>type (type∈{name,place,title,term}, парсер +nickname), «только НОВОЕ» (нет новых → нет разделителя).
Строить канал ТОЛЬКО если §D-правило «сноска оправдана» сработало. РАТИФИЦИРОВАНО D39.10 как dst-канал: parse_fail
0% (<5% ✓); ниша = ПРЯМАЯ доставка dst (переводчик эмитит 蛊→гу, non-seed 龙公→Лун Гун — ровно то, что ко-оккуренция
извлечь НЕ смогла), НЕ recall (маржин f<3 +1 терм ~10 п.п. — на пороге; код сильнее: f<3 8/10 vs банкнота 5/10);
Δкачества mean 0.935 под шум-полом 0.261 → уверенной деградации нет. Цена ~$0.01–0.1/ранобэ.
(а) Что меняем + 12 интеграционных точек (file:line, HEAD, каждая с тест-спекой в (д))
- Санитайзер (
sanitizer.gov6): на draft-стадии НЕ гоняется (isFinal-only,chunkrun.go:48). ⚠ СуществующийtrailingNoteRE(:240) НЕ ловит⟦TM-BANK-v1⟧/src<TAB>dst-строки (только «Примечание/Сноска»-заголовки), а CJK-leak (:76-84) фаерит только на голых Han-ранах — смешанная банкнот-строка «蛊 гу term» может НЕ сработать (ревью-1 F3: НЕ полагаться на trailing-note как бэкстоп). ПЕРВЫЙ и единственный надёжный рубеж — телеметрия п.10banknote_parse_failДО редактуры. Если нужен финал-бэкстоп — добавить ЯВНОЕ версионируемое⟦TM-BANK-v1⟧-правило санитайзера (не переиспользовать trailing-note). - Санитайзер cjk_leak (v6): src-колонка = Han по построению → срез ДО санитайзера снимает ложное срабатывание; gloss-whitelist v6 НЕ трогаем.
- classify/echo-детект (
disposition.go,const cjkEchoThreshold=0.15): считать по ОЧИЩЕННОМУ тексту (срез → classify(stripped)). Порядок ЖЁСТКИЙ. - Coverage-гейт (
coverage.go, translator-onlychunkrun.go:73):len_ratioчислитель по очищенному (сноска ≠ перевод). - max_tokens-сайзинг (
stagerun.go:87-100): += бюджет блока (≤12 строк × ~12 ток). Перевод ПЕРВЫМ, блок хвостом → трункация бьёт по блоку; парсер fail-tolerant на последней строке + флагbanknote_truncated. - request_hash/снапшот (
render.goRequestHash,snapshot.go): ⚠ (ревью-1 F2)PromptSHA256(:238) фолдит ТОЛЬКО файл промпта — если инструкция сноски = config-флаг, аппендящий её при рендере (какfew_shot), PromptSHA256 не двигается, wire тихо расходится (snapshot.go:110-116-класс). Решение (а): запечь инструкцию в ФАЙЛ промпта (тогда PromptSHA256 реально двигается) ИЛИ явный stage-флаг-фолд. (б) Версия ПАРСЕРА/среза банкноты — verdict-ось (управляет resolved-выходом черновика + derived-hash, какClassifierVersion:173/sanitizerSnap:66-77): добавитьbanknoteSnap{enabled, parser_version}вsnapshotID()(единое имя поля, ревью-2 F9-унификация; json-тег в Go — какsanitizerSnap.version, решает бэкенд) — иначе bump парсера без правки промпта оставляет снапшот тем же (свежие чанки режут новым парсером, резюмнутые отдают старый derived → тихая внутри-книжная дивергенция). Включение канала = громкий--resnapshot. - Чекпоинт/резюм (
stagerun.go:66-80): resume передоказывает derived-артефакт из сырого чекпоинта бесплатно (content-addressed hash → тот же id). - «Редактор её не видит» (НЕСУЩАЯ, главная правка кода): свежий прогон — редактор читает
prev=sr.Text(chunkrun.go:162), хук подменяет на очищенный. НО на резюме OK-путь берёт текст поfinal_hash, который сегодня = СЫРОЙ attempt (stagerun.go:168-169:if disposition==DispOK { finalHash=last.reqHash }); re-point на derived существует ТОЛЬКО для flagged (:170-185). ТРЕБОВАНИЕ: final_hash OK-стадии draft ПЕРЕНАПРАВИТЬ наtm-banknote-v1derived-чекпоинт (расширение прецедента flagged→ok). Без этого резюм отдаёт редактору сырой блок. ⚠ Эскалационный путь (ревью-1 F1): draft-стадия ЭСКАЛИРУЕТ (pipeline-c1.yaml:53escalate_to: deepseek-v4-pro— живое, не гипотеза;pipeline.go:374разрешает escalate_to только translator). На эскалированном OK-черновикеlast=esc.fb(stagerun.go:159),finalHash=last.reqHash= СЫРОЙ эскалированный чекпоинт,sr.Text=last.textкормит редактора СЫРЬЁМ. Срез+derived-commit+sr.Text=stripped+re-point ДОЛЖНЫ стоять ПОСЛЕ резолва эскалации (stagerun.go:163) и потреблятьlast.stripped— тогда эскалированный черновик тоже очищен. (resume.go:32-52читаетGetCheckpoint(final_hash)прозрачно → правка resume.go НЕ нужна.) - Пост-чек глоссария (
mempostcheck.go, по финалу редактора): не влияет; ноrenderGlossaryBlock(memory.go:477) идёт в промпте ДО инструкции сноски («новые = не из этого списка»). - Телеметрия (лауд): per-chunk
n_banknote_lines,banknote_parse_fail,banknote_truncated(в retrieval_state- стиле). - Провайдер-квирки: DeepSeek thinking-ON НЕ трогать (
models.goechoMineViolation,LoadModelsfail-fast). §D-арм меряет дельту качества черновика с/без инструкции (гейт канала; exp16: mean 0.935, под шум-полом 0.261 → уверенной деградации нет, но пере-замерить на пере-прогоне). - Экспорт/полигон:
tmctl exportотдаёт final без сноски автоматически (срез раньше); кандидаты — из артефакт-файла, не текста.
(б) Алгоритм
- Срез (
split_banknote):idx=output.find(SEP); <0 →(output.rstrip(), ""); иначеclean=output[:idx].rstrip(),block=output[idx+len(SEP):].strip("\n"). Срез ПЕРЕДclassifyOutput(chunkrun.go:32) на сыром draft-output. - Парс (
parse_banknote): строкиblock.split("\n")непустые; толерантный field-split\t| {2,}|\s*\|\s*; <2 полей → если последняя строка Иtruncated_generation→banknote_truncated, иначеbad+=1;typ=parts[2].lower()(≥3 полей) иначеterm, не-_TYPE_OK→term; src ДОЛЖЕН содержать Han[㐀-鿿]иначе bad;parse_fail=(bad>0). - finish=stop-only гейт (обязателен, errata exp16 §6): генерация банкноты принимается ТОЛЬКО при
finish=="stop"(не «≠length» — DeepSeek peak-overload даётinsufficient_system_resource). При stop-only truncation-толерантность парсера в проде НЕДОСТИЖИМА (гейт отклоняет не-stop) — но держать в парсере для устойчивости. - derived-checkpoint (ТОЧНАЯ формула прецедента
commitSanitizedExport,stagerun.go:230-232):sha256("tm-banknote-v1\x00" + reqHash + "\x00" + stripped), id-префикс"tm-banknote-v1:", черезPutDerivedCheckpoint(ledger.go:182, cost=0, escalation=0, idempotent),UsageJSON:"{}",FinishReason:"banknote_export". (НЕ упрощённая формула доки без NULL-байтов.) - Распарсенные кандидаты → отдельный артефакт-файл (evidence для W1.5 §C), НЕ в store до подписи.
(в) Конфиг + снапшот
- Включение канала: инструкция запечена в ФАЙЛ промпта (→
PromptSHA256двигается) ИЛИ stage-флаг-фолд; ПЛЮС новыйbanknoteSnap{enabled, parser_version}вsnapshotID()(verdict-ось, зеркалитsanitizerSnap) — не полагаться наPromptSHA256(ревью-1 F2). Смена парсера/среза = громкий--resnapshot. Строка манифеста §8. - derived-hash неймспейсит версию канала → смена версии = новый id (не коллизия).
(г) Верификация ДО стройки ($0) — ws4_banknote_verify.py, РЕЗУЛЬТАТ
- Пере-парс 95 строк (14 сохранённых сырых выходов exp16): 95 строк / 65 distinct_src / 0 parse_fail / 0 truncated — EXACT golden (parse_fail 0% воспроизведён).
- Синтетическая трункация: под
truncated_generation=True→ 2 годные строки +banknote_truncated(не bad); подFalse→banknote_parse_fail(корректно). - fresh↔resume эквивалент-тест (спека):
tm-banknote-v1:id = content-addressed (формула с NULL-байтами) → fresh и resume дают ИДЕНТИЧНЫЙ id; смена stripped → другой id. Re-point OK-пути final_hash resume-стабилен конструкцией. - Инварианты парсера: SEP не note-слово; non-Han src=bad; no-SEP→всё clean; толерантный сплит (таб/≥2проб/pipe) — все PASS.
(д) Тест-спека ПОСЛЕ стройки
- Каждая из 12 точек — пиновый тест (срез ДО classify; cjk_leak/coverage/echo по очищенному; max_tokens+блок; derived-hash формула; re-point OK-пути final_hash → derived [fresh↔resume эквивалент]; телеметрия 3 метрики; thinking-ON нетронут).
- Пин: parse_fail 0% на 95 строках; truncation-толерантность (синтетика); SEP не встречается в чистом тексте.
- Пин: включение канала = снапшот-сдвиг (промпт-SHA + константа).
(е) Открытое / маршрутизация
- Дельта качества перевода от форматного констрейнта — пере-замер на пере-прогоне (§11-провайдер §D-арм).
- Ниша канала = ДОСТАВКА dst, НЕ recall (код f<3: 8/10 vs банкнота 5/10). Z2-дрейф банкнотного dst (转→«оборот» vs approved «ранг») — ловится подписью владельца (draft, не approved).
§5. WS5 — Дефект-класс чекеры + данные пакета пары (слои 5 + 2-данные)
Дефект-класс-леджер D39.8 (все пак/банк/гейт-уровня, НЕ нарезка). Действие при срабатывании: флаг / констрейнт- инъекция — НЕ тихая правка текста (диспозиция D2 цела). Гейты — ДЕТЕРМИНИРОВАННЫЕ ($0): судьи слишком шумны (пол 0.126 когезия / 0.261 смысл — судьи только НОМИНИРУЮТ).
(а) Что меняем (file:line) — по классу: где живёт правило (данные пакета vs код гейта)
cheapgates.go— расширяется дефект-классами DC1/DC2/DC7 (детерм. флаггеры на финале,chunkrun.go:199-207реюзrunCheapGates, target-gatedisRuTarget, наблюдаемость не гейт по дефолту).- новый omission-бэкстоп (слой 5, компенсатор зоны деградации WS2) — reflow-инвариантный лемма-матч.
- данные пакета пары zh-ru (слой 2, версионируемый) — таблицы конверсии единиц (DC1), негатив-лист регистра (DC6), verse-локусы (DC5).
memory.go/renderEditorConstraintBlock— gender-инъекция (DC3) из поля сидаGender(glossary.go:26,memseed.go:35, folded в F1memory.go:273).
(б) Алгоритм + верифицированный статус ланд-абельности
- DC-1 时辰/меры (данные пакета + детерм. чекер): таблица конверсии
时辰=2ч,万/億-порядок,里/斤/суй-1; извлечь числовое время из src (N个时辰), сверить рендер (三个时辰≈6ч, НЕ «три часа»). Рефайн: флагать ТОЛЬКО явный mismatch (рендер счёта как часов), не «часы не найдены». ⚠ (ревью-1 A1) сработка на 25-гл — ОДНА (n=1, ch1/chunk4), РЕАЛЬНЫЙ дефект (3个时辰→3 часов) на КОРПУСЕ-ОТКРЫТИЯ этого дефекта → «true FP≈0» преждевременно (n=1 ≠ rate). Landing ГЕЙТИТСЯ §5(д)-FP на СВЕЖЕМ пере-прогоне (не текущий rerun). Конверсия детерминирована → низкий-FP ожидаем. - DC-2 масштабы
千万/数十万(b1-класс):千万=10⁷,数十万=неск.×10⁵; + word↔word alignment (四成四=44%,三成=30%,十二分之一=1/12— реюзq4a_traps.rule_b1/rule_b2+ LOCATOR). Это то, чтоregressionguard.goНЕ умеет (арабские цифры только,L5-regressionguardслеп к word↔word). ⚠ (ревью-1 A4)千万— стоковая ГИПЕРБОЛА («несметно/тьма»), «тысячи» — in-register литературный рендер, НЕ жёсткая ошибка как DC1/DC6. НЕ bundle с DC1/DC6 как «true FP≈0»; магнитуд-чекер — самый hyperbole-exposed → замерить FP ОТДЕЛЬНО в §5(д). Landing ГЕЙТИТСЯ §5(д). - DC-3 gender — РАЗВЕСТИ инъекцию и чекер (ревью-2 F6):
(1) Инъекция из поля сида
Genderв констрейнт-блок редактора — ЛЕНДИТСЯ для ВСЕХ ТРЁХ состояний, ВКЛЮЧАЯ hidden-мандат: male/female ⇒ жёсткие родовые формы; hidden ⇒ мандат БЕЗРОДОВЫХ конструкций / surface-他(→ «он») ДОuntil_ch(D19.3,白凝冰) — ЭТО и есть фикс класса Бай Нинбин: инъекция НАПРАВЛЯЕТ редактора, кореференция НЕ нужна. (2) Чекер (наблюдаемость на финале): male/female-чекер ЛЕНДИТСЯ с FP-гейтом §5(д), паратекст-чанки (foreword/синопсис) исключены. hidden-ЧЕКЕР НЕ лендится — ⚠ (ревью-1 A3, УТОЧНЕНО пост-верифай по records.json): FP 3.5% (2 сработки) НЕ обе паратекстные:ch1/chunk0= паратекст-книга-референс («её»→«эту книгу»), НОch1/chunk5(«Бай Нинбин… её дар просто пугает», сцена совета старейшин, НЕ паратекст) = РЕАЛЬНАЯ narrative-coref-неоднозначность женской формы на HIDDEN-персонаже — это СИЛЬНЕЕ довод к Ф2, не слабее. Паратекст-исключение снимает ТОЛЬКО chunk0; chunk5 остаётся → нужна РЕАЛЬНАЯ кореференция (→ Ф2). until_ch/sentence-scope НЕ фиксит. ⟶ Не лендится ТОЛЬКО hidden-ЧЕКЕР (инъекция всех трёх — лендится); прежняя формулировка «лендится только male/female энфорс» смешивала — бэкенд не построил бы hidden-инъекцию. - DC-4 род говорящего в диалоге: Ф2-annotator (дискурс-уровень, НЕ поле сида — говорящий может быть не в глоссарии). Трап «я мечтал»→«мечтала». Вне детерм.-скоупа слоя 5 → Ф2 (диспозиция §9).
- DC-5 стих/аллюзии — ⚠ НЕ ЛЕНДИТСЯ детерм. (верификация): loose line-profile детектор ловит трап но FP 73.7%; strict (регулярный метр + поэт-лексема) → FP 42.1% НО теряет позитив. ⚠ (ревью-1 A5) ДВЕ протестированные профили не лендятся (best = 42% FP + потеря позитива; 排比↔стих-неоднозначность трудна); универсального «детекция неспособна» из n=2 не утверждаем. Решение (консервативный дефолт): DC-5 = пак-локусы (владелец курирует известные verse/ allusion src-строки) + рендер-мандат «не сплющивать» + слот сноски + опц. LLM-НОМИНАЦИЯ (не гейт). Продукт-решения (рендер-политика, сноски) — владельцу (§10).
- DC-6 регистр-лексикон (негатив-лист данных пакета):
{терем-класс}— сказочно-русский/канцелярский слой, ломающий жанр. Чекер вхождений на финале + замены. Сработка на 25-гл — ОДНА (ch1/chunk4), РЕАЛЬНЫЙ дефект («терем» в сянься — жёсткая регистр-ошибка). ⚠ (ревью-1 A1) n=1 ≠ FP-rate; Landing ГЕЙТИТСЯ §5(д)-FP на свежем прогоне (негатив-лист по построению низкий-FP). Негатив-лист — данные пакета (расширяемо владельцем). - DC-7 editor-инверсии grade/role (сверка на ВЫХОДЕ редактора): канон-грейд
甲乙丙丁→«класс А/Б/В/Г»(не Б/2/A), титул族长→«глава клана»(не «старейшина»). Точный канон-матч против editor-output → низкий FP ожидаем. ⚠ (ревью-1 A2) DC-7 НЕ имеет $0-верификации (ws5-скрипт не тестирует его) → landing UNVERIFIED, FP только в §5(д) — не утверждать «ЛЕНДИТСЯ» до замера. Корень (D38 §3): promote甲乙丙丁+四代族长draft→approved + reseed (owner-only) — иначеrenderEditorConstraintBlock(CONFIRMED-only) не инъектит,suppressContainedсъедает верный族长. - Omission-бэкстоп (слой 5, WS2-компенсатор): reflow-инвариантный лемма-матч (
reflow_omission.py): per-source ENTITY присутствует ли ГДЕ-УГОДНО в target (position-independent → reflow-safe); verdict-каскад skip→present→partial →omitted;inflection_gapFLAG (лемма совпала, surface вне pinned decl.forms — НЕ omission, иначе ~7-8% ложных); content-floorratio=len(tgt)/(1.3·len(src))<0.5крайний backstop. Правило: entity-omission≈0 = «INSTRUMENT CEILING» НЕ «size safe» (D32.4). Go-путь БЕЗ pymorphy3: substring-матч по{dst, decl.forms, aliases}(детерм.), флаг при отсутствии; inflection-толерантность через лёгкий стеммер (см. WS3 (б) P5-решение).RegressionGuard/ coverage тут смещены (editor легально мержит — research/19 §B0-4).
(в) Конфиг + снапшот
- Данные пакета пары (таблицы единиц, негатив-лист, verse-локусы) — версионируемый пакет zh-ru, снапшот-folded
(правка = громкий resnapshot, как
chunkerVersion). Строка манифеста §8. - gender-инъекция (ревью-2 реконсиляция): ДАННЫЕ пола (
Genderseed-поле) фолдятся черезMemoryVersion(правка пола персонажа → снапшот); РЕНДЕР-ЛОГИКА (пол→констрейнт-текст вrenderEditorConstraintBlock) фолдится тем же выделеннымrender-format-version-компонентом, что и src→dst-блок (НЕmemoryMatchVersion— §2(в)/§8). - Дефект-чекеры (cheapgates) версионируются
StyleCheckVersion(snapshot.go:207, наблюдаемость → resnapshot при правке правила). - DC-7 promote
甲乙丙丁+四代族长draft→approved = reseed →MemoryVersionдвигается (снапшот).
(г) Верификация ДО стройки ($0) — ws5_checkers_verify.py, РЕЗУЛЬТАТ
- (а) Позитивы: 6/6 пойманы (синтетика exp15 §7.9/§2:
三个时辰→«три часа»,千万→«тысячи»,数十万→«десятки тысяч», «терем», стих[loose], gender-hidden). Точные zh-трап-строки (exp14b §2 таблица a1..d2 + 时辰/千万) — фикстуры. ⚠ DC-7 (grade/role) НЕ покрыт $0-скриптом (ревью-1 A2) → его landing verifies только §5(д). - (б) FP-fire на 25-гл финале (корпус records.json final; §5(д)-замер =
tmctl exportпосле стройки — rerun-store схема v7 < HEAD v8, read-only не мигрирует; exportNormalize косметичен, не меняет слова чекеров): DC1/DC2/DC6 = по 1 сработке (n=1, все на ch1/chunk4 — реальные дефекты, но n=1 ≠ FP-rate, ревью-1 A1) · DC3 3.5% (2 — 1 паратекст book-ref + 1 narrative-coref на hidden-персонаже, A3-уточ; male/female-чекер $0-неверифицирован как DC-7 → §5(д)) · DC5 loose 73.7% / strict 42.1% → НЕ детерм.-гейт. ⟶ Разделение: DC5 НЕ лендится (эскалация владельцу); DC1/DC2/DC6/DC7 landing ГЕЙТИТСЯ §5(д)-FP на СВЕЖЕМ прогоне (текущий n=1 — недостаточно); DC3 — только male/female seed-field.
(д) Тест-спека ПОСЛЕ стройки
- FP-замер через
tmctl export(инвариант №8) на СВЕЖЕМ пере-прогонном 25-гл финале (не records.json): каждый чекер (DC1/2/3/6/7) — измеренный FP-rate в отчёте; чекер с заметной долей ложных не лендится. ⚠ Пред-условие (ревью-1 A6): DC1/DC2 нужен SOURCE-столбец (для时辰/千万сверки src↔target);tmctl export --pairsна HEAD НЕ существует (research/20 §E-бэкенд-3) → построить--pairs(source-join в Export уже есть) ДО §5(д)-замера DC1/DC2. - Позитивы из эмпирики (exp15 §7.9 / exp14b / exp16) обязаны ловиться (регресс-фикстуры).
- Sentence-scoping обязателен (q4a_traps F4: скорить ОДНО предложение, эндеры
.!?…\n— иначе raw-draft и merged-glm- абзац несопоставимы). Три исхода fix/fail/«?»; «?» ИСКЛЮЧАЕТСЯ из rates, никогда тихий pass.
(е) Открытое / маршрутизация — ВЛАДЕЛЬЦУ (§10)
- DC-5 рендер-политика стиха + слот сноски (детерм. детекция не работает — эмпирика): продукт-решение владельца.
- DC-4 род говорящего = Ф2-annotator (диспозиция §9: Ф2-очередь).
- Промоут
甲乙丙丁/四代族长draft→approved — owner-only (approved-инвариант).
§6. WS6 — Свап-арм редактора + готовность пере-прогона
(а) Что меняем (file:line)
configs/pipeline-*.yaml/models.yaml— армы = КОНФИГ, не код: editor-стадияmodel: glm-5(базлайн) /mistral-large-latest/deepseek-v4-pro+few_shotтумблер (pipeline.go:103FewShot *bool); снапшот per-арм (разный editor-model → разныйstageSnap.Model→ разныйsnapshot_W2).export.go/quality.go— атрибуция арма в export/report (editor-model уже в chunk_status/checkpoint).- Инвариант: editor pinned (D12,
pipeline.go:373: escalate_to только на translator) — свап = смена editor-модели конфигом, НЕ эскалация. Пинитсяecho_mine_test.go(сейчас требует glm-5 обоих пайплайнов; тест обновляется под арм-варианты).
(б) Алгоритм (прогон-протокол — предпосылки для будущего полигон/монитор-промта)
- Армы идут ЧЕРЕЗ прод-путь со ВСЕМИ гейтами (урок V2-брака §7.9: eval-риг без прод-гейтов [санитайзер v6 поймал бы 待遇/一步登天] дискредитировал арм).
- Пред-условие mistral-арма (ревью-2 F4):
mistral-large-latestНЕ идёт через прод-путь до пер-модельного rate-guard (§1(б)) — ~48% retry-fails @1.3s без него исказят и латентность, и денежную телеметрию арма. glm-5/ deepseek-pro-армы (grok-семейство 0% retry-fails) rate-guard не блокирует, но семафор общий по конфигу. - Инструмент-фиксы слепых пакетов (D39.8 п.3): авто-QA до человека (CJK-в-ru / битые формы / род-консистентность); обрезка ВСЕХ версий по общему финальному предложению; 2-way для тонких контрастов; тир-структура претензий (критические/смысловые/редакторские) вместо плоского «≤2». Планка — 2 претензии (интерим, не пилот Ф2.5).
- Любое судимое сравнение наследует ратифицированный риг-стандарт (D39.7): per-vote персист, полно-evidence окна
(HEAD_CHARS-класс запрещён), оба порядка, floor-гейт маргиналов, DET-primary > судьи где возможен (валидирован
D39.9); генерации — только
finish=stop. - ⚠ Полы
0.126/0.261— ИСТОРИЧЕСКИЕ калибровки, НЕ переносимые константы (ревью-2 F5, замечание владельца): измерены в glm/flash-условиях на S2′/exp14-материале. Каждый СУДИМЫЙ арм-контраст пере-прогона меряет СВОЙ пол A0↔A0′-блоком (~$1/арм) на материале ЭТОГО прогона ДО интерпретации маргиналов — per-editor-model И per-материал. Смягчающее: главные оси floor-иммунны — DET-чекеры (WS5) + слепое чтение владельца (WS6/(д)); судьи только НОМИНИРУЮТ. Внести в предпосылки будущего полигон-промта.
(в) Конфиг + снапшот
- Каждый арм = отдельный
snapshot_W2(editor-model вstageSnap). Пере-прогон армов = отдельные джобы (не конфликтуют).few_shot:falseдля reasoning-редактора (deepseek-thinking) — фолдится (snapshot.go:110-116, только где есть---FEWSHOT---блок).
(г) Верификация ДО стройки ($0) — ws1_wave_cogs.py (реюз WS1-расчёта), РЕЗУЛЬТАТ
- COGS per-арм (фертильность × цены providers.json × реальная структура 25-гл, warm-cache/valley): glm-5 $0.335 · mistral $0.205 · deepseek-v4-pro $0.117. Свап-арм editor'ов ДЕШЕВЛЕ базлайна (out $1.5/$0.87 vs glm-5 $3.2) — COGS-win + D38 качество-фикс. Пик-надбавка ×2 (риск-пин) удваивает ТОЛЬКО deepseek-pro-editor до $0.234 → scheduler-aware критичен только для deepseek-арма. Кэш экономит ~17% на editor-input.
- Качественная сторона свап-арма — эскейп-хатч (эскалация): точная спека «верификация полигоном ПОСЛЕ стройки» в прогон-протоколе (это (д); платная — отдельной полигон-сессией по ратифицированному плану).
(д) Тест-спека ПОСЛЕ стройки
- Полигон-прогон армов {glm-5, mistral, deepseek-pro} через прод-путь + слепое чтение владельца (тир-структура) — ОТДЕЛЬНЫЙ полигон/монитор-промт по этому плану. Наследует риг-стандарт D39.7.
- Пин: editor-swap = конфиг (не код); снапшот per-арм; атрибуция в export/report.
(е) Открытое / маршрутизация
- Качественная ратификация свап-арма — платный полигон после стройки (деньги-развилка §10; кандидат — пере-прогон 3–10 глав, планка 2 претензии).
§7. Порядок стройки и нарезка на пакеты
Зависимости: WS3/WS4 (банк W1.5) требуют W1.5-стоп-границы из WS1. WS2 (единицы) требуется WS1 (что гонят волны). WS5-omission-бэкстоп компенсирует WS2-зону деградации. Рекомендуемая нарезка:
- Бэкенд-пак-2 (слой 1 оркестровка + чанкер): WS1 (волновой раннер: W0-precompute, eager-clients, пер-волновой
снапшот + wave-sequencing-инвариант, money-под-∥, scheduler-aware) + WS2 (чанкер-бюджет в output-токенах, edit-единица
с КОНСЕРВАТИВНЫМ
EditCeilingOut≤3200до Q2a, src→dst редактор, снос мёртвых кнобов). Разблокирует всё (волны — несущий каркас). ⚠ omission-бэкстоп в пак-4 → пока его нет, edit-ceiling держать консервативным (ревью-1 WS2-F1). - Бэкенд-пак-3 (слой 4 банк): WS3 (Go-майнер V-C + алиас + консолидация + сид-дельта +
tmctl seed-lint+Source:mined) + WS4 (банкнота 12 точек). Гейтится W1.5-стоп из пак-2. WS3-паритет Go↔Python — исполнение в (д). - Бэкенд-пак-4 (слой 5 + данные слоя 2): WS5 (DC1/2/3/6/7 чекеры + omission-бэкстоп + данные пакета zh-ru +
gender-инъекция) +
tmctl export --pairs(ревью-2 F7: пред-условие §5(д)-FP-замера DC1/DC2 — source-столбец). DC-5/DC-4 — эскалация владельцу/Ф2 (не в пак). - Конфиг-пак (WS6): армы редактора = yaml/models (не отдельный бэкенд-пак; часть пере-прогонного конфига).
Гейт: каждый пак — мандат самопроверки исполнением (свой код + запросы + результаты); адверсариальный бэкенд-ревью после кода. Затем единый resnapshot (§8) → пере-прогон 3–10 глав → чтение владельца.
§8. Манифест единого resnapshot (D30.9 — одна переоплата)
Все правки этого плана + уже висящие трек-A компоненты обязаны схлопнуться в ОДИН --resnapshot (одна переоплата
книги). Всё, что двигает snapshotID (snapshot.go:101-279):
Уже висящие (трек A залендён, но текущий снапшот книги их не несёт — resnapshot был отложен D38.5/D39.2/39.5):
memmatch-v4(trust-gated suppressor,memory.go:47) →MemoryVersion.sanitizer-v6(fold-first детекция) →Sanitizer(когда enabled).- reseed-сид
eb409f2(промоут 5 термов) →MemoryVersion/BriefHash. - editor-v3
0ac5f7a(дискурс+чэнъюй, few_shot-тумблер) →PromptSHA256/FewShot.
Новое из этого плана:
- WS2: снос
STMDepth/OverlapTokens(contextSnapменяется) +segmentationSnap(бюджет-output-токены + фертильность + edit-ceiling) +chunkerVersionbump → снапшот. - WS2: src→dst редакторский блок (
renderEditorConstraintBlockФОРМАТ меняется) → выделенныйrender-format-versionfolded-компонент (ревью-2 реконсиляция: НЕmemoryMatchVersion— тот const скоуп-матчер/алгоритмmemory.go:33-47, формат рендера НЕ ловит автоматически; механизм пинится в §2(в)) → снапшот. - WS3: майненые approved-строки (подпись W1.5) →
MemoryVersion(толькоsnapshot_W2, §1 (в));Source:minedenum (аддитивно, миграция store — НЕ снапшот, если не меняет folded content). - WS4: включение банкнота-канала = промпт-SHA (инструкция) + константа
banknote-v1→PromptSHA256(draft-стадия); +banknoteSnap{enabled, parser_version}(ревью-2 F9, verdict-ось из WS4(в) — управляет resolved-выходом черновика + derived-hash, зеркалитsanitizerSnap; §8 прежде нёс ТОЛЬКО промпт-SHA) →snapshotID(). - WS5: данные пакета пары (единицы/регистр/verse-локусы) — версионируемый пакет → снапшот; gender-инъекция: ДАННЫЕ
(
Genderseed-поле) →MemoryVersion, РЕНДЕР-ЛОГИКА →render-format-version(ревью-2 реконсиляция, НЕmemoryMatchVersion; §5(в)/§2(в)); DC-чекеры →StyleCheckVersion; promote 甲乙丙丁/四代族长 →MemoryVersion. - WS6: editor-model per-арм →
stageSnap.Model(разные армы = разные снапшоты, но это РАЗНЫЕ прогоны, не переоплата одного). - Структурное (ревью-2 F9): сама пер-волновая реструктуризация
snapshotID()(дваMemoryVersionbase/enriched- два снапшота W1/W2 вместо одного book-global, §1(в)) = снапшот-инвалидация — ОЖИДАЕМАЯ строка golden re-capture (структура хеша меняется даже при идентичном контенте).
Доказательство «переоплата ОДНА»: пере-прогон = ОДИН fresh-translate под финальным конфигом (W1 под snapshot_W1
- W2 под
snapshot_W2); ВСЕ вышеперечисленное фолдится в эти два пер-волновых снапшота ДО старта прогона. W1.5- обогащение банка двигает ТОЛЬКОsnapshot_W2(пер-волновой скоуп, §1 (в)) — W1 не пере-оплачивается. Итог: один draft- проход + один edit-проход = стоимость книги ×1 (не ×N от множественных resnapshot). Golden re-capture: маскированный структурный дифф старого↔нового снапшота = только хеши/версии + новые поля.
§9. Диспозиции хвостов
Свип дорожек L1–L8 аудита 08 (полнота; приоритет L1/L2/L3/L5):
- L1 (контракт t/e): editor-4-мандата-full-regen → WS6 свап-арм (near-term: слабое звено = редактор, D38/D39.9); translator-structure-arm (H3) → ЗАКРЫТ D39.9 (flash-черновик уже верен 25/0/27; pro не ратифицирован; «верность у переводчика» закрыта); diff-editing (H4/E.7) → парковка Q4b (не тестировано; EM 0.68–0.95 на КОДЕ); fidelity-no- owner → WS5 DC-2/DC-7 детерм. чекеры (полярность/число/грейд/ранг) + omission-бэкстоп.
- L2 (сегментация): ВЕСЬ трек → WS2 (бюджет-output-токены, edit-единица, снос STMDepth/OverlapTokens, мега-
предложение-флаг); фантомный «D35.7» формализован D39 как цель слоя 1 (
05-log:563), реализуется здесь. - L3 (память): код-корень терм-дрейфа ЗАКРЫТ треком A (
d3f6b34trust-gated suppressormemory.go:684, громкий trustGateEvent) — НЕ переоткрываем; src→dst редактор (D30.1) → WS2 (решён); майнинг ПОВЕРХ → WS3. - L5 (экспорт): нормализация ЗАКРЫТА треком A (
exportNormalize, fold-first санитайзер v6, CJK-gloss whitelist owner-решение) — НЕ переоткрываем; L5-legit-cjk-gloss-stripped (D38.3 §4б owner-q) → РАЗРЕШЁН (whitelist сохраняет глоссыsanitizer.go:662, WS4-банкнота = dst-канал); резидуалы L5-broken-word (retract) / L5-diacritics (NFC-pass в export) / L5-regressionguard-40% (калибровка) — мелкие долги ниже. - L4 (пер-язык промпты; L4-convention-pack-layer NEVER_CLOSED/HIGH): сеам ЗАЛЕНДЁН треком A (
prompts:{zh-ru}fail-loud); полный versioned convention-pack ЛАЙЕР + язык-промпта → промпт-тема10-prompt-architecture.md, гейт exp15+research/18 §D-3 (форма пакета). Субстанция пакета РЕАЛИЗУЕТСЯ здесь: данные пакета пары zh-ru (единицы DC1/ регистр DC6/verse DC5) = WS5-слой-2-данные; плагины P1–P6 = WS3. Форма versioned-layer — за промпт-темой. - H5 (no-in-loop-quality-signal, NEVER_CLOSED/HIGH): частично ЗАКРЫТ треком A (
quality.goQualityReport = claim-1 структурный KPI); span-citing судья claim-2 нет. Субстанция слоя-5 сигнала = WS5 (DET-чекеры DC1/2/3/6/7 + omission-бэкстоп = в-контуре измеримость); семантический span-судья — Ф2 (ресёрч-зависим). - L6 (дискурс-reflow): Ван Цуй 5 техник + чэнъюй-атом верны; резидуалы (L6-overclaim
editor.md:14, deliteralize↔ chengyu tension, chengyu-atom untested) → промпт-тема / измерить в пере-прогоне (мелкие долги ниже). confirm-only. - L7 (NEVER_CLOSED владельческие идеи): H6–H19 — каждой явная диспозиция ниже.
- L8 (чистота кода): role-registry / target-гейты / gatesEnabled-снос ЗАКРЫТЫ треком A; остаток (strip-smear 5-файлов, foldModelWire-extract, prompt-orphans) — закрыты пак-1/1.5 (аудит датирован ДО них); confirm-only.
Ledger-очередь D39.4/39.5 (LOW/NOTE — в пак по надобности, не блокеры): golden-глосс-ячейка, escalated+stripped
тест, Retries-снапшот pre-existing, пунктуационные огрызки, trustGateEvent первый-отказ, pair-fail-loud-до-store,
капы maxGlossCJKRunes=6/maxGlossLatinTokenRunes=24 (tunable, ревизия по пере-прогону), F6-rename (CJK-сплит).
§E research/19 (E.5–E.8-бис): E.5 аддитивный Chunk → WS2 (реализовано). E.6 кнобы когезии → СНЕСЕНЫ (carryover
не строим). E.7 дифф-apply после Q4b → парковка (Q4b не гонялся; diff-XYZ EM 0.68–0.95, aider 91–98% на КОДЕ,
ru-проза — гипотеза). E.8 DeepSeek-слаги → WS1 (в)-(в) (grep). E.8-бис ZAI-кэш → WS1 (в)-(б) (разрешён).
Парковки (НЕ тестировано — консервативный дефолт, НЕ строим, НЕ хоронить как «доказано»; ревизия по пере-прогону): lookahead (Q3b) → WS1 (е). diff-редактор §C2 (Q4b) → E.7 выше. Q4c reflow-отдельным-пассом · Q2c широкое-окно/ узкая-эмиссия · Q5 W2.5-швейный-пасс — все три НЕ гонялись, парк, не в дефолт (§0-скоуп: рычаги сцеплены, но эти конкретные армы вне ратифицированной матрицы; ревизия только если пере-прогон/чтение владельца укажут дефицит).
§E research/20 (E-бэкенд-1…6): E-1 Source:mined+tmctl seed-lint → WS3. E-2 канал сноски → WS4. E-3
tmctl export --pairs (НЕ существует на HEAD, main.go) → ОБЯЗАТЕЛЬСТВО пак-4 (ревью-2 F7: НЕ «слот по
надобности» — §5(д) требует source-столбец ДО FP-замера DC1/DC2): source-join в Export уже есть (export.go
bookChunks); флаг --pairs строится как ПРЕД-УСЛОВИЕ §5(д)-замера DC1/DC2. E-4 транспорт gender → WS5-DC3.
E-5 ruby↔mined схема → WS3. E-6 src→dst редактор (D30.1, memory.go:505-511) → WS2 (решён в план, не хвост).
Дефекты D39.9 (finish=length-гейты в eval-харнесах): exp14_common.call НЕ отклоняет finish=length — это
EVAL-риг-долг (полигон), НЕ прод (прод classify обрабатывает length, stagerun.go:455). Прод-инвариант WS4: генерации
только finish=stop. Диспозиция: eval-риги будущих полигон-сессий чинят (в промт-стандарт D39.7), прод чист.
NEVER_CLOSED владельческие идеи дорожки L7 аудита 08 (каждой — явная диспозиция, требование 09:165):
- H7 input-size-limit (лимит входных токенов книги, отдельно от money-ceiling): НЕТ кода/диспозиции.
Диспозиция: preflight-чек в W0 (est-токены книги vs конфиг-лимит
max_book_tokens, fail-loud ДО трат) — дешёвый, в пак-2 (W0 уже считает est_out). Владельцу: значение лимита (§10). - H8 abuse/misuse pre-screen (дешёвый high-precision скрин prompt-injection/non-translation): НЕТ кода/дисп.
Диспозиция: паркуется в Ф3 (trust-boundary + injection-probe → eval-очередь,
05-log:311«не срочно»); дешёвый non-translation pre-screen — записка владельцу (§10: строить сейчас дёшево или Ф3?). - H10 user-stop/cancel (+ non-resumable для abuse-джобов): НЕТ кода/дисп. Диспозиция: Ф2/Ф3 (resume.go +
ceiling/outage-пауза есть; user-facing stop в
tmctl— дешёвый follow-up, но не гейтит пере-прогон). Записка (§10). - H16 self-improvement harness (само-улучшение без дорогого human-review): НЕТ кода/дисп. Диспозиция: предпосылка = слой 5 quality-сигнал (WS5) + banknote/bank-auto-build (WS3); сам A/B-loop = Ф3 (frontier-meta- reviewer убит владельцем V4-п2, базовая идея — после того как слой 5 даёт измеримость каждой правки).
- H17 frontier-meta-reviewer (фронтир-модель ревьюит правки пайплайна): ЗАКРЫТ владельцем (V4-п2) — НЕ переоткрываем (ревью-2 F10: без этой строки клейм «H6–H19 каждой диспозиция» формально ложен). Базовая измеримость правки = слой 5 (WS5); сам meta-review-loop = Ф3 (см. H16).
- H6 running-summary (DelTA-class near-term рычаг): carryover НЕ строим (D39.7/8 — метрики под полом 0.126 И читатель). Диспозиция: ретайр для книг этого класса (не хоронить как «доказано» — ревизия на структуро-разнообразном корпусе; §0.1). Не в пак.
- H9 parallelism («главная V4-идея»): ПОДХВАЧЕНО WS1 (волновой раннер = safe-parallel дизайн; не наивный — клиенты предвычислены, деньги сериализованы, sticky precompute'нут). Диспозиция: строится (пак-2).
- H15 glossary-auto-build (V4-п4): ПОДХВАЧЕНО WS3 (банк-майнинг W1.5 = query-time context + детектор). Диспозиция: строится (пак-3); broad web-fetch auto-populate = Ф3.
- H11 backend-render-questions (§D-7 neighbor-reference): PROD-MINOR (
MessagesWithInjectionпринимает произвольную инъекцию); ±1-reference SHELVED (exp14 A-ref null). Диспозиция: закрыто SHELVED (соседи-черновики не в дефолт, §1 (е)). - H12 cross-boundary trap-set на вебновелл-домене: не построен; «cross-boundary не доминирует» предварительно (PD- classic). Диспозиция: чистовик на вне-претрейн новелле (после пере-прогона, §0.1).
- H13 broken-draft-joins (битые склейки без детектора): Диспозиция: omission-бэкстоп WS5 частично покрывает (content-floor); специфичный join-детектор — ledger-хвост LOW.
- H14 inversion-guard (полярность/ранг/эмоция, D37 §2г): editor-swap = near-term защита (WS6) + DC-7 grade/role чекер + DC-2 полярность-числа (WS5) частично реализуют. Диспозиция: WS5-DC частично + WS6 свап; полный полярность-guard — ревизия по пере-прогону.
- H18 findings-ledger process (концерн-5, стоящий процесс): Диспозиция: оркестратор-процесс (completeness-critic на границе фаз — этот план = экземпляр; не бэкенд-код).
- H19 merge↔completeness collision (
editor.md:8сливай vs:9полнота, без omission-guard): Диспозиция: omission-бэкстоп WS5 = измеримость коллизии (лемма-присутствие после мержа).
L5/L6 мелкие долги (аудит 08 §8 п.9): L5-broken-word-class (fix-or-retract — D-лог рекламирует несуществующую
способность; retract в контракте, класс отложен Ф2-морфология) · L5-diacritics-class (NFC-pass дёшев — в
export-слой, zero-FP) · L5-regressionguard-40% (калибровать по реальному draft→final распределению — ledger-хвост) ·
L6-overclaim (editor.md:14 «КОНВЕНЦИЯ русского» → техника-vs-норма split — промпт-тема) · L6-deliteralize↔chengyu
(эксплицитная граница — промпт-тема) · L6-chengyu-atom (измерить в пере-прогоне, не считать закрытым).
§10. Реестр вопросов владельцу (консолидированный, с дефолтами плана)
| # | Вопрос | Дефолт плана | Развилка |
|---|---|---|---|
| 1 | W1.5-UX: стоп посреди книги для подписи vs автопродолжение? | Явная стоп-граница (раннер стоп → подпись → resume W2) | UX-решение |
| 2 | DC-5 стих: рендер-политика (не сплющивать) + слот сноски? Детерм. детекция НЕ работает (FP 74%/42%) | Пак-локусы (владелец курирует src-строки) + рендер-мандат + сноска; LLM-номинация не гейт. Рекомендация оркестратора (ревью-2): дефолт плана поддержан | Продукт-решение |
| 3 | DC-3 gender: промоут 甲乙丙丁/四代族长 draft→approved + подпись пола 人祖=male, 古月=n-a, 白凝冰=hidden |
Промоут + reseed (owner-only, approved-инвариант) | Подпись |
| 4 | H7 input-limit: значение max_book_tokens? |
Preflight-чек в W0, лимит tunable | Настройка |
| 5 | H8 misuse-prescreen: строить дешёвый non-translation скрин сейчас или Ф3? | Ф3 (не срочно) | Скоуп |
| 6 | H10 user-stop: user-facing stop/cancel в tmctl сейчас или Ф2/Ф3? | Ф2/Ф3 (ceiling/outage-пауза есть) | Скоуп |
| 7 | Мини-голд алиасов (~20–30 мин): нужен для recall кластеризации ярус-1 | Без него — только precision | Тачпойнт |
| 8 | precision@30 non-seed A3: адъюдикация T/F/? | Сайдкар готов (precision_at30.md) |
Тачпойнт |
| 9 | DeepSeek пик ×2: риск-пин (вторичка, не офиц.); ре-чек 24.07 у катовера слагов. Провенанс (ревью-2 F11): клейм D39.7 «официально» имел провенанс «через владельца» (URL/цитата НЕ пинились); свежий чек 19.07 офиц. прайса = ФЛЭТ → label остаётся РИСК-ПИН до ре-чека 24.07 (там запинить URL+цитату); историч. запись D39.7 НЕ переписывать (D23.3) | scheduler-aware вне пик-окон + ×2-бюджет-фолбэк | Вендор-чек |
| 10 | Свап-арм качество: платный полигон-прогон армов после стройки (планка 2 претензии)? | Пере-прогон 3–10 глав через прод-путь | Деньги-развилка |
| 11 | ja→ru реплика (P1=ruby-канал) как тест общности §0.1 после zh→ru | Отдельный мини-фриз след-за-стройкой | Скоуп/деньги |
| 12 | PostcheckGate флип (hard-gate) — висит за пере-замером D24.4/D28.1 | Дефолт-флаггер (false); пер-волновой снапшот держит обе механики | Пере-замер |
| 13 | Edit-ceiling размер (ревью-1 WS2-F1): глава-единица до 6.5k out span-омиссия НЕ доказана безопасной (только Q2a) | Консервативный EditCeilingOut≤3200 до Q2a; большая-глава-арм — платный Q2a span-судья. Рекомендация оркестратора (ревью-2): дефолт 3200 + платный Q2a-гейт поддержан; Q2a ОБЪЕДИНИТЬ с полигон-прогоном свап-армов (Q10) |
Деньги/качество |
| 14 | WS3 ru-лемматизатор (ревью-1 WS3-F2): Палладий-подканал V-C нужен pymorphy3 (dst_variants+is_name_lemma) | (A) faithful pymorphy3-порт → golden exact; или (B) дроп Палладий → 古月:21→22, скрин PASS, пере-пин. Рекомендация оркестратора (ревью-2): дефолт (B) — дроп подканала с пере-пином (dst доставляет банкнота, exact-rank НЕ продуктовая ценность); (A) только при готовой поддерживаемой Go-морфологии |
Порт-цена/точность |
§11. Мандат самопроверки (исполнено) + приёмка
Ревью исполнением: каждый верификационный скрипт (eval/design11/ws{1,2,3,4,5}*.py) ПРОГНАН, результат
воспроизводим (детерминизм: без time/rand в money-инварианте; фикс-mock-латентности); каждое несущее file:line
сверено с ЖИВЫМ кодом HEAD 766a60e (не worktree-память отчётов). Находки верификации, изменившие план: (1) WS2
классиф.-mismatch = 0 на zh (не realign, документировать); (2) WS3 сид-дельта флагает D38-дефект как draft
(дисциплина работает) + фрагмент-шум (эмиттер реюзит фильтры); (3) WS5 DC-5 стих НЕ лендится детерм. (74%/42% FP) →
эскалация владельцу; (4) WS1 W1.5-re-bill-форк → пер-волновой снапшот.
Адверсариальный селф-ревью несущих алгоритмов — ИСПОЛНЕН (раунд-1, 5-агентный refute-by-default воркфлоу, author≠ reviewer; каждый агент пере-исполнил верификации + сверил file:line на HEAD). Все скрипты воспроизвелись байт-в-байт. Несущие расхождения ВПИТАНЫ в план (помечены «ревью-1» in-line):
- WS1-F1 (несущее): «переоплата ОДНА» держит НЕ снапшот, а волновой инвариант секвенирования (W2 не пере-рендерит
draft; редактор читает черновик из W1-чекпоинта) —
renderGlossaryBlockинъектит майненые draft-строки, так что наивный пере-рендер draft над обогащённым банком пере-оплатил бы W1. Снапшот избегает resnapshot-СТОПА. → §1(в) переписан. - WS1-F3/F4/F5: money-границы ПАРАЛЛЕЛЬНЫ (≤N in-flight, overshoot ≤ Σ(cost−est)); mock ≠ полное зеркало (day-ceiling/
идемпотентность в Go-тест); wall-clock = compute-only, end-to-end + W1.5-стоп. WS1-F6/F8: client() read-only в волнах;
waves.workers(не fanout). - WS2-F1 (риск): edit=глава при 6.5k out НЕ доказана span-безопасной (backstop entity-уровня слеп; только Q2a) →
EditCeilingOut≤3200консервативно + Q2a-гейт (§10-13). WS2-F2: 1797 не byte-identical (4 чанка, 2 абзац-сдвига). WS2-F3: классиф-инвариантность корпус-специфична (не ja/ko). WS2-F4: src→dst — одно несущее обоснование (омонимы), явный снапшот-фолд формата. - WS3-F1/F2: паритет-фикстура расщеплена (Палладий-инвариант vs -зависимый
古月:21); «λ=0 → лемматизатор не нужен» ОПРОВЕРГНУТ (dst_variants безусловен λ) → развилка A/B/C (§10-14). - WS4-F1/F2/F3: point 8 + эскалационный путь (draft эскалирует в prod); парсер-версия = verdict-ось снапшота (не PromptSHA256); trailing-note НЕ бэкстоп банкноты.
- WS5-A1..A6: DC1/2/6 сработки = n=1 на корпусе-открытия (НЕ FP-rate) → landing гейтится §5(д); DC2=гипербола-exposed;
DC3-fires = паратекст-кореф (не hidden; только male/female лендится); DC5 «две профили не лендятся» (не «неспособна»);
DC7 без $0-верификации; §5(д) нужен source-столбец (
tmctl export --pairs). - Completeness: Q4c/Q2c/Q5 явные §9-строки; H5/L4-pack/L5-gloss названы. CONFIRMED без правок: eager-build race-фикс, Select-детерминизм, derived-hash формула, strip-ordering, records.json-FP-суррогат легитимен.
**Ревью-2 оркестратора (19.07) — ВПИТАН (in-line маркер «ревью-2»; провенанс: соло-проход оркестратора [полное чтение
- спот-чеки file:line по HEAD исполнением; мульти-агентный рубеж НЕ запускался — лимиты владельца] + 2 замечания владельца F4/F5).** Вердикт: план РАТИФИЦИРУЕМ после фикс-листа. Ни одна находка НЕ пересматривает алгоритмы или шесть $0-верификаций — все правки ТЕКСТОВЫЕ (скрипты не пере-гонялись; ни одна (г)-цифра не изменилась). Фиксы:
- F1 (MAJOR):
EditCeilingOutдефолт приведён к 3200 (было противоречие «8000» в §2(в) vs ≤3200 везде); 8000 = потолок ГЕЙТНУТОГО крупно-главного арма за Q2a. → §2(в). - F2 (MAJOR): явный инвариант — mid-run подпись W1.5 трогает ТОЛЬКО
Source:mined; правка seed/ruby = ОТДЕЛЬНОЕ пред-прогонное resnapshot-событие (§8), НЕ W1.5; промоут 甲乙丙丁/四代族长 — в reseed. Пин в (д). → §1(в)/(д). - F3 (MAJOR): инъекция W2 специфицирована — СВЕЖИЙ
Selectпо ВСЕЙ единице над enriched-банком, запрет реюза per-чанк W0-memSel(base). → §1(б)/§2(б)/(д). - F4 (MAJOR, владелец): пер-модельный rate-guard в волновом диспетчере (пер-вызовный 429 УЖЕ есть
httpllm.go:27-29, гэп = N-∥);models.yaml-конфиг, НЕ снапшот-ось; mistral-арм — за rate-guard; заготовка quirks → §12; каветка wall-clock. → §1(а)/(б)/(г), §6(б). - F5 (MINOR, владелец): полы 0.126/0.261 — ИСТОРИЧЕСКИЕ, per-editor-model + per-материал; каждый арм меряет свой A0↔A0′ (~$1); главные оси floor-иммунны (DET + слепое чтение). → §6(б).
- F6 (MINOR): DC-3 развести инъекцию (ЛЕНДИТСЯ все три вкл. hidden-мандат) от hidden-ЧЕКЕРА (не лендится, Ф2-кореф). → §5(б).
- F7 (MINOR):
tmctl export --pairs= обязательство пак-4 (пред-условие §5(д)), не «слот». → §7/§9. - F8 (MINOR): сайзинг edit-единицы (
max_tokens+Reserve) unit-aware (МЕХАНИЗМ исправлен пост-верифай: «от ЧЕРНОВИКАprev, не est_out» — блок ниже). → §2(б)/(д). - F9 (MINOR): §8 +=
banknoteSnap{enabled,parser_version}verdict-ось + строка «пер-волновая реструктуризация = снапшот-инвалидация». → §8. - F10 (MINOR): H17-frontier-meta-reviewer добавлен в §9-свип (ЗАКРЫТ V4-п2 — иначе «H6–H19 каждой» ложен). → §9.
- F11 (микро): §10-9 нота провенанса Q9 (D39.7 «официально» = через владельца; риск-пин до 24.07, D39.7 не переписывать). → §10.
- §10 рекомендации оркестратора вписаны: Q13 (3200+Q2a, объединить с Q10), Q14 (дефолт B), Q2 (дефолт поддержан).
Пост-фикс адверсариал-воркфлоу (7-агентный, 19.07 — тот мульти-агентный рубеж, что ревью-2 не гонял; $0 к
провайдерам, все 6 $0-скриптов воспроизведены под eval/.venv [зависимости regex/jieba/pymorphy3 — НЕ system
python]). Вердикт критика: РАТИФИЦИРУЕМ, все 11 фиксов на месте, F1 MAJOR полностью снят, MAJOR-противоречий нет;
6/6 golden воспроизведены байт-в-байт. Несущие находки ВПИТАНЫ (маркеры «пост-верифай»/«испр.»):
- F8 ПЕРЕПИСАН (был неверен): «сайзить от
est_outединицы» — ошибка;stagerun.go:87-90(D2.5) уже сайзит редактора от ЧЕРНОВИКА (prev, ~1.9× источника), аest_outисточнико-производна + чужое токен-пространство → НОВОЙ формулы нет, §8-строки F8 не требует. → §2(б)/(д). - F1 ПЕРЕ-СИМУЛИРОВАН at 3200: ратиф. дефолт = 25 глав → 37 edit-единиц (11 делятся, 10 split-хвостов <1k out);
«25/25 в 2k–8k» был 8000-арм. → §2(б)/(г),
ws2_chunk_sim.pyceiling∈{8000,3200}. - F2 write-path (грунт-гэп критика):
loadGlossarySeedхардкодитSource:"seed"(memseed.go:131) → reseed mined-дельты ОБЯЗАН нестиSource-столбец, иначеsnapshot_W1двигается; 甲乙丙丁/四代族长 промоут = элевация вSource:seed(base) → pre-run. → §1(в), WS3 (д). - Реконсиляция снапшот-loudness: src→dst-блок + gender-рендер фолдятся ВЫДЕЛЕННЫМ
render-format-version, НЕmemoryMatchVersion(const скоуп-алгоритмmemory.go:33-47) — §8/§5(в) приведены к §2(в). - F6 уточнён по records.json: 2-я DC3-сработка (
ch1/chunk5, «её дар» на Бай Нинбин, сцена совета) = narrative-coref на HIDDEN-персонаже, НЕ паратекст — СИЛЬНЕЕ довод к Ф2. → §5(б)/(г). - Мелкое:
banknoteSnapимя поля унифицировано (parser_version); §3(б)/§0-сводка приведены к дефолту B; whole-chapter Select-бюджет — открытый пункт (§2(е)).
Подтверждающий пас (3-агентный, 19.07 — верификация 6 корректировок на НОВЫЕ противоречия) — ИСПОЛНЕН. Поймал ДВА
F1-класс-резидуала (моя реконсиляция сиблингов оставила одну строку устаревшей) — ОБА пофикшены: (1) MAJOR —
§8-WS5 gender-инъекция → memoryMatchVersion не был приведён (сиблинги §5(в)/§8-WS2/§2(в) были) → реконсилирован к
render-format-version; (2) MINOR — §1(в) предлагал «расширить seedTerm-схему», что противоречит §3(б) «без новых
полей» → пиннут ЕДИНЫЙ путь: отдельный mined-write-путь (штамп Source:mined), §3(а)/§3(б)/§1(в) согласованы.
Корректировки 1/2/5/6 подтверждены ЧИСТЫМИ (F8 grounded stagerun.go:87-90; 37-единиц воспроизведён байт-в-байт;
F6 по records.json; имена/дефолт-B). После фикса резидуалов — MAJOR-противоречий не осталось.
Приёмка (оркестратор): пере-исполнение симуляций; спот-чек file:line; refute-воркфлоу по несущим алгоритмам;
сверка полноты против скоуп-листа D39.11. Мин-планка ратификации: все WS с исполненной (г) — все шесть исполнены и
PASS ($0-верификации воспроизводимы, детерминированы); манифест resnapshot полон (§8); реестр владельцу
консолидирован (§10). Гейтнутые армы (ратифицируемы как ГЕЙТНУТЫЕ, стройка сердцевины не ждёт, но арм не стартует до
верификации): (1) WS2 КРУПНАЯ edit-единица (>~3200 out) — гейтится платными Q2a span-судьями (сердцевина строит с
консервативным EditCeilingOut≤3200); (2) WS6 качество свап-арма — гейтится платным полигон-прогоном после стройки
(COGS-сторона (г) исполнена; эскейп-хатч (а)/(б) D39.11); (3) WS5 DC-чекеры landing — гейтится $0-FP-замером §5(д)
на СВЕЖЕМ прогоне (текущий n=1 недостаточен — не платный гейт, build-time тест); (4) WS6 mistral-арм через прод-путь
— гейтится пер-модельным rate-guard (ревью-2 F4: ~48% retry-fails без него искажают латентность+биллинг). Эти четыре —
развилки в §10 (13/10/9/…), маршрутизированы явно, не тихо. Эмпирика exp15/16 — предварительна до вне-претрейн новеллы: несущие
пороги «tunable, ревизия по пере-прогону».
§12. Заготовка для 00-provider-quirks.md (ревью-2 F4 — вносит ОРКЕСТРАТОР при лендинге, зона полигона)
⚠ Этот блок — НЕ часть плана-контракта; это черновик записи для
docs/experiments/00-provider-quirks.md(зона полигона). Дизайн-синтез-сессия НЕ пишет вdocs/experiments/; оркестратор переносит текст ниже в quirks-файл при лендинге плана и там же пинит URL/цитату при пере-замере на прод-тире.
mistral-large-latest — агрессивный rate-limiter (тир-зависим, пере-замерить на прод-тире):
- Судейский eval-риг (exp15 §7.6 REV.2, N-параллельные вызовы): ~48% retry-fails @1.3s интервала, max latency
64.7s;
grok-*в том же риге — 0%. - Расширение интервала 1.3→2.6s эффекта НЕ дало (49.5→48.2%) → лимитер похож на токен-бакет / конкуренц-кап, НЕ per-request-пейсинг; тир-зависим.
- Действие бэкенда (WS1(б)): пер-модельный семафор конкуренции + 429/
Retry-After-бэкофф (пер-вызовный уже есть,httpllm.go:27-29,138-140, капmaxRetryAfterWait=5мин). Правило двух направлений: цифры из eval-рига, НЕ офиц. доки — при переносе в quirks запинить прод-тир-замер + вендор-страницу rate-limits. - Пред-условие: mistral-editor-арм не идёт через прод-путь до этого guard (§6(б)).