textmachine/backend/PACK11_CONT_REPORT.md

250 lines
28 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

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

# PACK11_CONT_REPORT — бэкенд-сессия ПРОДОЛЖЕНИЯ, резидуал R1R5 (2026-07-19)
> Продолжение `PACK11_REPORT.md` (Block A, `85f5b9e`). Строил по `docs/architecture/11-implementation-plan.md`
> (ратифицирован D39.12) + `PACK11_REPORT.md` §Резидуал (пошаговые дизайны R1R5). **НЕ коммитил** — сдача
> на приёмку. Верификация исполнением: `go build ./... && go vet ./... && go test -race ./...` — ВСЁ
> ЗЕЛЁНОЕ на каждом чекпойнте (логи в §Верификация). Block A НЕ трогал (под тестами).
## 0. Санкционированный порядок и итог
**Развилка порядка эскалирована владельцу/оркестратору в начале сессии** (R1 = крупный каскад, меняющий
ГРАНУЛЯРНОСТЬ вывода → ~весь e2e-суит + read-models + golden; риск красного дерева vs жёсткое правило
«суит зелёный на каждом чекпойнте»). **Оркестратор санкционировал вариант 1:** R2→R3→R4→R5 сначала (все
самодостаточны и зелёно-достижимы независимо от R1), **R1 — капстоуном на остатке бюджета**, с условиями:
чекпойнт-ревью после R2+R3 и после R4; R3 на текущем последовательном раннере; каждый снапшот-двигающий
лендинг — свой golden re-capture с masked-диффом, СТРУКТУРНЫЙ рерайт — один раз в R1; R1 сначала аддитивные
под-шаги без каскада, переключение драйвера — финальный атомарный шаг; не дотягивает до зелёного → дерево
зелёное, R1 точным резидуалом (запланированный исход).
| WS / шаг | Статус | Верификация |
|---|---|---|
| **R2 · WS3 Go-майнер** | ✅ **СДАНО** | Go↔Python паритет **EXACT**: 13618 канд-СЕТ, катастроф {方源:0,蛊:1,蛊师:2,古月:22}, recall@proposed **0.9649**; alias-ярус-1 (5 R4-блоков+компози-гард); сид-дельта+`MinedDeltaYAML`; `Source:mined`-путь; `tmctl seed-lint`. |
| **R3 · WS4 банкнота 12 точек** | ✅ **СДАНО** (на посл. раннере) | срез-до-classify (fresh+resume); `tm-banknote-v1:` derived + re-point после эскалации; `banknoteSnap` (omitempty); v9-телеметрия; finish=stop-only гейт. 5 e2e-пинов. |
| **R4a · `tmctl export --pairs`** | ✅ **СДАНО** | source-столбец (пред-условие §5(д)-FP DC1/DC2). |
| **R4b · чекеры DC1/DC2/DC6 + zh-ru пакет** | ✅ **СДАНО** | эмпир-позитивы пойманы; DC2 **байт-верно референсу** (ok_re-supress + case-sensitive — фикс ревью); `cheapGateVersion` v3; golden re-capture masked-чист. |
| **R4c · DC3 gender-инъекция** | ✅ **СДАНО** | `memoryEntry.gender`→editor-констрейнт; `renderFormatVersion` v2; golden re-capture masked-чист. |
| **R5 · WS6 арм-конфиги** | ✅ **СДАНО** | `pipeline-arm-mistral.yaml`/`pipeline-arm-deepseek-pro.yaml`; `echo_mine_test` под варианты; rate-guard связка. |
| **R1 · волновой ИСПОЛНИТЕЛЬ** | ⚠️ **АДДИТИВ СДАН · драйвер-свитч РЕЗИДУАЛ** | `snapshotIDForWave` (пер-волновой снапшот, «переоплата ОДНА» пиннута) + W0 sticky-precompute (**байт-идентично, golden-доказано**) — СДАНЫ, зелёные. Параллельный dispatch W1/W1.5/W2 — резидуал (§R1-residual, дизайн ниже). |
| **Чекпойнт-ревью** | ✅ ×3 | R2+R3 (4 minor/nit, фикс) · R4 (2 DC2-parity, фикс) · финал (см. §Ревью). Адверсариал-воркфлоу, author≠reviewer, refute-by-default. |
---
## R2 — WS3 Go-майнер (план §3) — ✅ СДАНО
Новый пакет `internal/pipeline/miner*.go` (substrate/detect/patterns/palladius/alias/emit) — **байт-верный
порт frozen exp16** (`exp16_common/detectors/patterns/arms/alias/palladius/emit_owner_sheets.py`),
**дефолт-лемматизатор B**. Per-буллет (§R2):
-**Порт V-A→V-C по ТОЧНЫМ порогам §3(б):** c-value `g(L)=log₂(L+1)` (не log₂L — пин
`TestMinerLengthMultNonDegenerate`/`CValueSingleCharNested`); subsumption α=0.80 (`TestMinerSubsumption`);
weirdness `p_book/max(word_rel,char_indep_rel,1e-9)`, N_book = полная пре-флор масса; n-граммы Han 16
overlapping, freq-floor 3; паттерн-каналы (surname/百家姓−凝, title-suffix/bare, ordinal_title, rank_grade,
topo, авто-формант over_rep≥15∧partners≥3 — `TestMinerFormantDetection`); arm A3 λ=0, bonus·pw,
subfloor `bonus+40·f·pw`. Детерминизм: все сорты `(-score,-freq,src)`, map-итерация только ПЕРЕД тотал-сортом.
-**Дефолт B — дроп Палладий-подканала V-C** (плюс `dst_variants`, `is_name_lemma`, spread λ, alias-R3,
canon-dst-recovery — все pymorphy3-зависимые; dst доставляет банкнота WS4). `is_palladius_token` порт как
**детерминированный** артефакт (Палладий-таблица, без pymorphy3) + тестируем (`TestMinerPalladiusToken`).
**Палладий-ЗАВИСИМЫЙ ранг 古月:21→22** — как предписано §10-14/§3(д); катастроф-скрин ∈top-50 PASS.
-**Палладий-ИНВАРИАНТНЫЕ гарантии — EXACT** (`TestMinerFullBookParity`, data-gated `TM_MINER_PARITY=1` на
стенд-данных: jieba-контраст + `rerun/records.json` + `guzhenren-seed-v2.yaml`): **n=13618** (SET-членство),
recall@proposed **0.9649** (55/57 GT), катастроф {方源:0,蛊:1,蛊师:2,古月:22}. Скипается при отсутствии данных
(как `TM_LIVE`). **Python = референс: byte-verified, расхождений 0 по инвариантам.**
-**Алиас-ярус-1 (R1R4, R4 hard-blocks ПЕРВЫМИ):** `TestMinerAliasRules` (5 сабтестов): R1-extension
(方源⊂古月方源), компози-гард (古月+族长=фраза-не-алиас, но 古月+方源=fullname-алиас), R4-iii/v (族长≠四代族长 по
разному approved-dst), R4-ii (разный пол блок, hidden не блокирует), R4-i/R2 (одна фамилия+разные имена→family).
**R3 (shared-ru-rendering) ОМИТ в дефолте B** (нужен `dst_lemmas`/pymorphy3) — задокументировано в коде.
-**Эмиссия сид-дельты §C2-7:** `MineBank``MinedTerm` с фильтрами `build_precision30` (тип∈{name,place,title},
freq≥5, ∉subsumed, len≥2, ∉фрагмент по PARTICLE) — НЕ сырой 13618-дамп; alias-кластеризация (репрезентант =
топ-ранг; кластер с seed-поверхностью = алиас-of-existing, не эмитится). `MinedDeltaYAML` → seedTerm-схема
БЕЗ новых полей. `TestMineBankDeterministicAndNonSeed`/`TestMinerEmissionFilters`.
-**`Source:"mined"` mined-write-путь:** `minedToCandidates` (штамп `Source:mined`, status:auto, no-dst,
зеркало `rubyToCandidates`, НЕ через `loadGlossarySeed`). `TestMinedToCandidatesStampsMinedSource` +
`TestMinedDeltaStaysBaseBankStable` (Source:mined НЕ двигает `BaseVersion` — «переоплата ОДНА» через реальный путь).
-**`tmctl seed-lint`:** `SeedLint(path)` = сухой прогон РЕАЛЬНОГО `loadGlossarySeed`+`approvedSharedKeyCollisions`;
CLI `seed-lint --seed <yaml>` (без `--config`). `seedlint_test.go`: чистый→OK; дефекты (approved-без-dst /
unknown-status / duplicate / shared-key) → фейл-лауд; **эмитированная дельта линтует чисто** (`TestSeedLintEmittedMinedDelta`).
**Артефакт-зависимость:** прод-майнер грузит jieba-контраст (5MB, SHA `7197c321…`, ВНЕ git) через
`LoadContrast(io.Reader)` — путь конфигурируется вызывающим. Тесты — синтетический малый контраст;
паритет — реальный jieba со стенда.
**Не-каскадная зона R2:** `MineBank`/`minedToCandidates`/`MinedDeltaYAML` — библиотека пак-3; ВЫЗОВ на
W1.5-границе (реseed через `ReplaceGlossary`) — часть волнового W1.5-стопа (R1-residual). Сдано как
самодостаточное, тестируемое ядро (санкция оркестратора: R2 самодостаточен, R1 вайрит).
---
## R3 — WS4 банкнота: 12 интеграционных точек (план §4) — ✅ СДАНО (на посл. раннере)
Ядро `banknote.go` (Block A) + интеграция. **Все точки пер-стадийные → в волновую модель переезжают КАК ЕСТЬ**
(применяются к W1/draft-стадии; условие оркестратора). Per-точка:
1.**Санитайзер:** банкнота-срез — ПЕРВЫЙ рубеж (`applyBanknote` до `classifyOutput`); trailing-note НЕ
реюзим (ревью-1 F3). Финал-бэкстоп = телеметрия п.10.
2.**cjk_leak:** src-колонка Han по построению → срез ДО санитайзера снимает ложь.
3.**classify/echo (п.3, ЖЁСТКИЙ порядок):** `applyBanknote` режет блок на ОБОИХ путях runAttempt (fresh-call
И checkpoint-hit/resume) ДО `classifyOutput` → echo/coverage/length видят ОЧИЩЕННЫЙ перевод, не Han-сноску.
Пин `TestBanknoteClassifyOverCleaned` (клин RU + Han-тяжёлый блок → OK, не cjk_artifact).
4.**Coverage:** числитель по очищенному (срез раньше coverageCheck).
5.**max_tokens += `bankTokenBudget`** (≤12×12) для translator при enabled (перевод первым, блок хвостом →
трункация бьёт блок). Пин: draft `max_tokens=656` (512+144) в e2e.
6.**request_hash/снапшот:** `banknoteSnap{enabled,parser_version}` в `snapshotID()`. **ДЕВИАЦИЯ-с-обоснованием:
omitempty-указатель (nil при off) вместо безусловного `{enabled:false}` зеркала sanitizerSnap** — включение
канала И bump парсера ВСЁ РАВНО громкий сдвиг (несущая loudness §4а-п6 сохранена), но ДОБАВЛЕНИЕ фичи НЕ
инвалидирует banknote-OFF книги (в т.ч. golden-фикстуру) → R3 golden БАЙТ-СТАБИЛЕН, re-capture не нужен.
Пин `TestBanknoteSnapshotFold`.
7.**Чекпоинт/резюм:** derived content-addressed → resume re-derives id бесплатно; сырой чекпоинт хранит
RAW-ответ, resume пере-режет.
8.**Re-point (главная правка):** OK-путь draft `final_hash``tm-banknote-v1:` derived-чекпоинт с ОЧИЩЕННЫМ
черновиком (`commitBanknoteExport`, формула §4б `sha256("tm-banknote-v1\x00"+reqHash+"\x00"+stripped)`); стоит
ПОСЛЕ резолва эскалации, потребляет `last.bankStripped` (эскалированный черновик тоже очищен). Пины
`TestBanknoteSliceReTelemetryResume` (final_hash=derived, derived=clean, resume $0) + `TestBanknoteEscalatedDraftStripped`.
9.**Пост-чек глоссария:** не затронут.
10.**Телеметрия (лауд):** store v9 (`n_banknote_lines`/`banknote_parse_fail`/`banknote_truncated`) в
retrieval_state; тред draft→translateChunk→persistRetrievalState.
11.**DeepSeek thinking-ON нетронут** (echoMineViolation).
12.**Экспорт:** final без сноски автоматически (срез раньше).
**§4б:** толерантный парсер (Block A) + **finish=stop-only гейт** — кандидаты ПАРСЯТСЯ только при `finish=="stop"`;
срез идёт РЕГАРДЛЕСС (echo/length classify всегда видят clean). Пин `TestBanknoteFinishStopOnlyGate`.
---
## R4 — WS5 чекеры + данные пакета + `export --pairs` (план §5) — ✅ ЯДРО СДАНО
-**R4a `tmctl export --pairs`:** `Export(pairs bool)` + `ChunkExport.Source` (omitempty, $0 из манифеста);
дефолт-экспорт target-only (обратно-совместим). CLI `--pairs`. `TestExportPairsIncludesSource`.
Пред-условие §5(д)-FP DC1/DC2 (src↔target). **Read-only проекция — снапшот/wire/деньги не трогает.**
-**R4b DC1/DC2/DC6 + zh-ru пакет** (`checkers_zh_ru.go`, порт `ws5_checkers_verify.py`): наблюдаемость
(НЕ диспозиция), в `runCheapGates`→retrieval_state; самогейтятся на контенте (0 на не-zh/чистом). **DC2 —
байт-верно референсу** (после ревью-фикса): ok_re-suppression гард (数十万 не фаерит при верном «сотни тысяч»)
+ case-SENSITIVE inner (референс без re.I). `TestDC1/DC2/DC6` (эмпир-позитивы + non-firing + parity-кейсы).
-**R4c DC3 gender-инъекция** (§5(б), «фикс Бай Нинбин»): `memoryEntry.gender``row.Gender`;
`genderConstraintNote` в `renderEditorConstraintBlock` (male/female жёсткие формы; hidden — мандат безродовых);
ДАННЫЕ пола уже в `MemoryVersion`, РЕНДЕР — в `renderFormatVersion` v2. `TestDC3GenderInjection`.
- **Пакет данных = код-консты, версия `cheapGateVersion`** (та же дисциплина, что существующие cheap-данные):
правка данных = громкий resnapshot. Конфиг-загружаемый per-pair пакет — чище, **резидуал** (§Резидуал).
**Golden re-capture ×2 (masked-чист, §Golden):** (1) `cheapGateVersion` v2→v3 — единственная payload-правка =
`style_check_version`, wire/вердикты байт-идентичны после hash-маскинга; (2) `renderFormatVersion` v1→v2 —
payload-версия + 7 editor-wire-тел получают gender-note (gender:m терм фикстуры), НИ ОДНОЙ вердикт/final-правки.
---
## R5 — WS6 арм-конфиги (план §6) — ✅ СДАНО
-**Армы = КОНФИГ:** `configs/pipeline-arm-mistral.yaml` (editor=mistral-large-2512) /
`pipeline-arm-deepseek-pro.yaml` (editor=deepseek-v4-pro, `few_shot:false`). Оба — копии боевого C1 с
ЕДИНСТВЕННОЙ правкой editor-model → другой `stageSnap.Model` → другой снапшот (арм-механика Block A). draft/
translator неизменны.
-**`echo_mine_test` под варианты** (`TestSwapArmConfigs`): каждый арм грузится; editor=арм-модель; НИ ОДИН не
вооружает эхо-мину (deepseek-v4-pro → ReasoningNone, thinking ON, `echoMineViolation` пуст на echo-prone
провайдере); few_shot (deepseek off / mistral nil=ON); **mistral-large-2512 несёт `rate_limit`** (WS6 пред-условие —
свап-арм за rate-guard WS1b).
-**Атрибуция арма:** editor-model уже в `chunk_status`/checkpoint `model_actual` → export/report несут её
БЕЗ новой кодовой правки (план: «уже в chunk_status»). Пере-прогон армов = отдельные джобы (разные снапшоты).
---
## R1 — волновой ИСПОЛНИТЕЛЬ: аддитив СДАН, драйвер-свитч РЕЗИДУАЛ
**Санкция оркестратора:** сначала аддитивные под-шаги без каскада; драйвер-свитч — финальный атомарный шаг;
не дотягивает → зелёное дерево + точный резидуал (**запланированный исход**). Сделано:
-**Пер-волновой снапшот (`snapshotIDForWave`, §1в — несущее):** рефактор `snapshotID()`→`buildSnapshotID(stages,
memVersion)` (**байт-идентичен** для all-stages+enriched → golden/последовательный драйвер НЕ двигаются).
`snapshotIDForWave(W1)` = translator-стадии + BASE-версия (excl mined); `(W2)` = editor-стадии + ENRICHED.
`waveStages` (партиция по роли), `baseMemoryVersion`. Пин `TestSnapshotIDForWave`: W1≠W2; **mined-approved
добавка двигает ТОЛЬКО W2, W1 стабилен** («переоплата ОДНА» на снапшот-уровне) + `TestWaveStagesPartition`.
- ✅ **W0 sticky-precompute (`wave.go precomputeSticky`, §1б):** sticky-цепочка — кросс-чанковая зависимость
(не пере-считать внутри параллельной волны) → предвычислена в W0 одним проходом (пер-глава reset, `Select`,
advance). **Последовательный драйвер ТЕПЕРЬ ЕЁ КОНСУМИТ** (`bookrun.go` W0-precompute; `translateChunk`
принимает готовый `memSel`, снят inline-`Select` + `activeIDs`-return). **БАЙТ-ИДЕНТИЧНО** — `TestGolden`
зелёный без правок (несущий байт-паритет-пруф). Это ТОЧНЫЙ precompute, который консумит волновой исполнитель.
**РЕЗИДУАЛ R1 — драйвер-свитч (точный дизайн, `PACK11_REPORT.md §R1` + план §1):**
1. Партиция стадий по волне — **ГОТОВА** (`waveStages`); пер-волновой снапшот-апсерт (два UpsertSnapshot) —
рефактор `bookrun.go` W0-прелюдии (сейчас один `snapshotID`; заменить на `snapshotIDForWave(W1/W2)`, пинить
стадии волны к своему через `EnsureJob(snapshot_Wx)`).
2. W1-dispatch: N воркеров тянут draft-чанки, `runStage(draft)` под `snapshot_W1`, `memSel`=precompute[i] —
**ГОТОВЫ**: precompute, rate-guard (Block A), single-writer деньги (Block A), eager-clients (Block A).
3. W1.5-стоп: пустая mined-дельта → авто-продолжение; иначе `MineBank`→карта-подписи→подпись→`minedToCandidates`
→`ReplaceGlossary`(reseed)→`snapshot_W2` — **компоненты ГОТОВЫ** (R2), нужна оркестровка стопа/резюма.
4. W2-dispatch: N воркеров тянут edit-ЕДИНИЦЫ (`EditUnitID`, Block A), `prev`=конкатенация draft-чекпоинтов
единицы по `final_hash`, СВЕЖИЙ `Select` по тексту ВСЕЙ единицы над enriched-банком, `runStage(edit)` под
`snapshot_W2`. **W2 НИКОГДА не пере-рендерит draft** (несущий инвариант — редактор читает по `final_hash`).
5. **Каскад (почему не в этой сессии):** edit=единица меняет ГРАНУЛЯРНОСТЬ вывода (edit per-UNIT, адресуется
`(chapter, firstChunkIdx, "edit")`) → `ChunkOutcome`-форма + export/status/quality read-models + ~весь
e2e-суит (asserts per-chunk 2-стадии + call-counts) + СТРУКТУРНЫЙ golden-рерайт. Оркестратор явно
санкционировал структурный рерайт «один раз в R1»; аддитив-пруф (golden байт-стабилен) даёт уверенность,
что все несущие R2R5 компоненты на месте для атомарного свитча в отдельной сессии/окне.
6. kill-9 с N резервами: порт `store/kill9_test.go` на N воркеров (money-инвариант Block A уже single-writer-safe).
---
## Открытые эскалации / решения (флаг оркестратору при лендинге)
1. **Дефолт-B майнер** — ратифицированный §10-14 дроп pymorphy3-подканалов (spread λ / dst_variants /
is_name_lemma / Палладий-конфирм / alias-R3 / canon-dst). 古月:22 (не 21). Все Палладий-ИНВАРИАНТНЫЕ гарантии
воспроизведены EXACT. dst доставляет банкнота. **Faithful-A (полный pymorphy3-порт) — только при готовой
поддерживаемой Go-морфологии** (не строил).
2. **`banknoteSnap` omitempty** (не безусловный sanitizerSnap-зеркало) — де­виация-с-обоснованием (§R3-п6):
loudness сохранена, off-книги не re-bill-ятся, R3 golden байт-стабилен. **Требует подтверждения при лендинге.**
3. **DC-пакет данных = код-консты** (версия cheapGateVersion), не конфиг-загружаемый per-pair файл — конфиг-форма
резидуал (§Резидуал). Дисциплина resnapshot сохранена.
4. **R4 резидуал (честный, бюджет→R1):** DC7 grade/role-чекер (нужен promote 甲乙丙丁/四代族长 approved — owner-only,
§5-A2 UNVERIFIED); DC3 male/female-ЧЕКЕР (нужна coref-lite, §5(д)-FP-гейт); omission-бэкстоп (лёгкий Go-ru-стеммер
без pymorphy3 + лемма-матч по {dst,decl.forms,aliases}); DC2 word↔word дроби (q4a rule_b1/b2). Дизайны — план §5(б).
5. **R1 драйвер-свитч резидуал** (запланированный исход, санкция оркестратора) — дизайн §R1 выше.
6. **§5(д)-FP-замер DC1/2/3/6** — платный пере-прогон (не в этой сессии); `export --pairs` — пред-условие СДАНО.
⚠ FP-замер прогонять через **Go-код** (не `ws5_checkers_verify.py`), т.к. чекеры теперь байт-верны референсу,
но лендинг-решение должно отражать что реально шипается.
---
## Структурные переносы
- Новые файлы `internal/pipeline/miner_*.go` (9 шт — новый детектор-пакет, не рефактор), `checkers_zh_ru.go`,
`wave.go` (W0-precompute). Все — новые оси.
- `snapshotID()` → тонкая обёртка над извлечённым `buildSnapshotID(stages, memVersion)` (байт-идентично).
- `translateChunk` сигнатура: `stickyPrev map[...]` → `memSel memorySelection` (готовый из W0); снят
`activeIDs`-return (precompute владеет sticky-advance). Внутренний вызов, вне-скоуп поведение не затронуто.
- `Export()` → `Export(pairs bool)` (6 тест-вызовов обновлены на `Export(false)`).
## Багфиксы вне плана
- Нет вне-плановых. Правки по ревью: **R2+R3 (4):** derived-namespace `banknote-v1`→`tm-banknote-v1` (§4б EXACT-формула,
отдельная const от parser_version), мёртвая `rank`-карта в `MineBank`, doc-коммент, error-wrap
`commitBanknoteExport`. **R4 (2):** DC2 ok_re-suppression-гард + case-sensitive inner (байт-паритет референсу).
Все верифицированы адверсариально, пофикшены, суит зелёный.
## Golden re-capture (masked-структурный дифф — обязан быть объясним)
- **R4b (cheapGateVersion v2→v3):** masked-дифф = 4 строки, ЕДИНСТВЕННАя payload-правка `style_check_version`;
wire-тела + вердикт-строки БАЙТ-ИДЕНТИЧНЫ после hash-маскинга (verified скриптом).
- **R4c (renderFormatVersion v1→v2):** masked-дифф = 18 строк: 4 версия-payload + 7×(old/new) editor-wire-тел с
gender-note (gender:m терм). НИ ОДНОЙ вердикт/disposition/final-text правки (Counter: version/gender-note/wire только).
- **R3/R5/R1-аддитив:** golden НЕ двигается (banknote omitempty off; армы — отдельные файлы; snapshot-рефактор
байт-идентичен). СТРУКТУРНЫЙ golden-рерайт — событие драйвер-свитча (R1-residual), не этой сессии.
## Верификация (исполнением — логи, не слова)
```
$ go build ./... → OK
$ go vet ./... → OK (чисто)
$ go test -race ./... → ВСЁ ЗЕЛЁНОЕ:
ok cmd/tmctl · config · ledger · llm · pipeline (~28s -race) · store
$ gofmt -l <мои файлы> → пусто (репо несёт ПРЕ-существующий gofmt-долг в не-моих файлах — не трогал)
$ TM_MINER_PARITY=1 go test -run TestMinerFullBookParity
→ n=13618 · катастроф {方源:0,蛊:1,蛊师:2,古月:22} · recall@proposed=0.9649 (55/57 GT) — PASS
```
**Фикстуры плана исполнены:** miner-паритет (Палладий-инвариант EXACT, 古月:22 дефолт-B) · банкнота 12 точек
(5 e2e-пинов) · seed-lint 0 фейл-лаудов · DC-позитивы пойманы · пер-волновой снапшот «переоплата ОДНА» ·
W0 sticky байт-паритет (golden) · draft request_hash стабилен (golden).
## Чекпойнт-ревью (адверсариал-воркфлоу, author≠reviewer, refute-by-default, 3 линзы)
- **R2+R3:** 5 сырых → 4 confirmed (все minor/nit, 1 refuted): `tm-banknote-v1` namespace / мёртвая rank /
doc / error-wrap. **НИ ОДНОГО major correctness/wire/money.** Все пофикшены.
- **R4:** 2 confirmed (оба DC2 reference-divergence): ok_re-supress-гард (MAJOR — реальный FP-дивердж на
ch2/chunk0) + case-sensitivity (MINOR). Оба пофикшены — DC2 байт-верно референсу.
- **Финал (R5 + R1-аддитив + кросс-каттинг инвариантов, 2-мерный воркфлоу + verify):** **0 находок — ЧИСТЫЙ
вердикт.** Обе линзы (R1-аддитив байт-паритет/пер-волновой снапшот/precompute-эквивалентность; R5-армы +
кросс-каттинг: деньги/снапшот-дисциплина/детерминизм/store-v9) вернули пустой список. Ни одного invariant-
break, un-folded wire/verdict-change, byte-parity-break или map-order-в-выводе. `go test -race ./...` зелёный,
golden байт-стабилен, arm/wave-тесты проходят — clean bill.