142 lines
30 KiB
Markdown
142 lines
30 KiB
Markdown
# ОБЩНОСТЬ ФАЗА 2 — rewrite-пакеты П0–П4 + шестёрка + малая пачка. Отчёт бэкенд-сессии, 2026-08-01
|
||
|
||
> **✅ ПРИНЯТ И ЗАЛЕНДЕН (оркестратор №9, 01.08.2026, D39.64).** Приёмка исполнением (author≠reviewer): собственный прогон `go build`/`go vet`/`go test -race ./...` = 14/14 · майнер-парити воспроизведён байт-в-байт (`n=13618 catastrophe{方源:0 蛊:1 蛊师:2 古月:22} recall@proposed=0.9655`) · все 7 приёмочных тестов PASS свежим прогоном · **Ш-1 сверен НЕЗАВИСИМОЙ классификацией диффа `capture.golden` (не маской их теста): 86+86=172 строки, key-by-key сравнение payload — ровно 5 осей §4; content_hash/disp/flag/detail, wire-тела и stage_text — 0 изменений** (156 из 172 строк = распространение фолда SnapshotID в чекпойнт-хеши, каузально — те же 5 осей) · адверсариальное ревью 6 агентами: ни одно несущее утверждение НЕ опровергнуто.
|
||
> Ниты (существа не меняют): (1) счёт флагов §5 = **9** позиций, не «10» (off-by-one эхо-блока); (2) дрейф номеров строк — `repair.go:574`→577 · `runner.go:391`→400-403 · `pipeline.go:832-841`→839-848 · `sanitizer.go:432`→431; (3) флаг 2: «ратифицированный тест» — частично мёртвая best-effort-ветка (ja-ru падает раньше ассерта; контракт фолбэка реально держат комментарий `pipeline.go:839-848` + голден-фикстура) — блокер настоящий, рекомендация в силе; (4) флаг 5: размеченный корпус `~/books/gu-zhenren/labels/` физически ЕСТЬ на стенде — реальный барьер = утраченный в эфемерном scratch харнесс замера + вердикт-риск K-рубрики; отказ держится как скоуп-решение; (5) байт-идентичность манифест-less пака в тесте не ассертится (в одном бинаре невозможно) — доказана независимой пробой HEAD-vs-дерево: `langpack-v2-a28ed743c99c` оба раза; (6) заявка «per-package 0/172» пост-хок непроверяема — подтверждён кумулятив.
|
||
> Находки сверх отчёта → бэклог: остаточные Cyrillic-хардкоды пар-гейтед DC-чекеров (`checks/repair.go:131` · `checkers.go:457,474`) — строка 79; при включении ручки #77 задокументировать общий счётчик attempt с length-ре-геном и рост `maxTokensForAttempt` (wire-параметр). Флаги §5 — очередь владельца (бэклог, строка 14).
|
||
|
||
**Промт:** `docs/BACKEND_GENERALITY_PHASE2_SESSION_PROMPT.md` (оркестратор №9, санкция владельца D39.62/D39.63).
|
||
**Режим:** $0 — код+тесты, НОЛЬ платных вызовов моделей, `--resnapshot` НЕ запускался, сессия НЕ коммитит.
|
||
**Карта-истина:** `GENERALITY_RESEARCH_2026-07-31.md` (принята D39.60): §3 якоря · §5 трасса второй пары · §6 цены · §9 план · §10 чего НЕ делать.
|
||
|
||
## 1. Эхо-блок (≤10 строк)
|
||
|
||
1. **П0–П4 + 2 из 6 шестёрки + 1 из 2 малой пачки построены и верифицированы исполнением; 10 позиций помечены с инженерными причинами** (не тихо пропущены — флаг через владельца по мандату).
|
||
2. **Голден вердикт-нейтрален по всему пакету: `0 verdict/wire change line(s), 172 version-only` (Ш-1)** — сдвинулись ТОЛЬКО хеши 5 снапшот-осей, ни один вердикт/провод-байт на паре zh/ja→ru.
|
||
3. **Майнер-парити EXACT сохранён:** `n=13618`, катастрофы `{方源:0 蛊:1 蛊师:2 古月:22}`, recall@proposed 0.9655 — консолидация классов письма движок не тронула.
|
||
4. **`go test -race ./...` = 14/14 пакетов зелёные; build/vet/gofmt чисты по всем моим файлам.**
|
||
5. **Живой баг ko/Hangul ЗАКРЫТ (строка 75):** эхо-детектор меряет ОБЪЯВЛЕННОЕ письмо источника (`sourceScriptShare`), CJK-leak санитайзера ловит Hangul — корейское/английское эхо больше не слепое пятно.
|
||
6. **Дыра эмбед-плоскости ЗАКРЫТА (строка 76, П0):** `lang.EmbeddedVersion()` фолдится в снапшот — правка байта `target-ru.txt`/`injection.txt` = громкий resnapshot (мутационный тест доказывает).
|
||
7. **Цель-шов слоя 7 снят по данным (П1):** `isRuTarget` (6 сайтов) → `TargetActive()`/`TargetScriptNonLatin()`; книга `target_lang: en` проходит слой 7 инертно ПО ОТСУТСТВИЮ данных, без Go-ветки (мутационный тест).
|
||
8. **Самозадокументированный долг репэйнут (П1):** токенизатор цели с алфавитом ИЗ ДАННЫХ + U+0301-фолд закрывает #11 и `repair.go:182-189` ОДНИМ швом — линт и репэйр-скан на нём, дрейф невозможен.
|
||
9. **Самый жёсткий блокер слоя данных снят (П4):** манифест-по-каналам — источник без пиньинь-морфологии грузится без Palladius-файлов; **обратно-совместимо, БЕЗ бампа `packAlgoVersion`** (манифест-less пак байт-идентичен).
|
||
10. **Флаги (10): ё-фолд · segmentation-громкая · EstimateTokens-N-коэфф · encoding-аллоулист · 4 дефекта пака-21 (K4b/inner_marker/гомоглиф/OffLanguage) · billed-decode #78** — каждый с причиной и рекомендованным дизайном в §5.
|
||
|
||
---
|
||
|
||
## 2. Что построено по пакетам (file:line)
|
||
|
||
### П0 — «байты есть версия» (предусловие) ✅
|
||
|
||
- `internal/lang/embedded.go`: `EmbeddedVersion()` (embed-v1 + sha256 всех `data/*` в фикс-лекс-порядке, framing как у `Load()`); чистый `hashEmbeddedFiles([]embeddedFile)` вынесен для мутационного теста.
|
||
- `internal/pipeline/snapshot.go:389`: поле `EmbeddedVersion string json:"embedded_version"` рядом с `LangpackVersion`, фолд БЕЗУСЛОВНЫЙ (эмбед всегда присутствует, используется каждой книгой).
|
||
- **Приёмка (мутационный тест `TestEmbeddedVersionMutation`):** правка байта `target-ru.txt` И `injection.txt` — каждая двигает `EmbeddedVersion` ⇒ громкий resnapshot, не тихая смена вердиктов. PASS.
|
||
|
||
### П1 — цель-шов (слой 7) ✅ (кроме ё-фолда — §5)
|
||
|
||
- **Реестр целей из эмбед-данных** (`embedded.go` `TargetChecksFor`): Go-мапа `targetCheckFiles` удалена; реестр ДЕРИВИТСЯ из `data/target-<tgt>.txt` по имени файла.
|
||
- **Токенизатор цели из данных + U+0301** (`text/runes.go` `TokenizeScript(s, ws)`): алфавит-цель приходит `word_script` из `target-ru.txt` (→ `unicode.Cyrillic`); комб-марка (Mn) не рвёт слово и дропается — «сло́во»→«слово» (#11). `TokenizeCyrillic` = ru-дефолт-обёртка (§10 «значение по умолчанию»).
|
||
- **ЕДИНЫЙ шов, долг репэйнут** (`checks/checkers.go` `Checkers.tokenizeWords` + `checks/repair.go` `brokenWordCandidates`): и `lintYofikation`, и `lintBrokenWord`, и репэйр-скан висят на `c.wordScript` + одинаковом Mn-фолде — вердикт-нейтральность линт↔репэйр держится by construction. Комментарий-долг `repair.go:182-189` переписан на «REPAID».
|
||
- **`isRuTarget` → инертность-по-данным** (6 сайтов): `chunkrun.go:52`, `waverun.go:386,500`, `repair.go:574` → `r.checkers.TargetActive()` (есть цель-данные); `quality.go:215`, `repair.go:208` → `r.checkers.TargetScriptNonLatin()` (латинский остаток). `isRuTarget` удалён из `disposition.go`.
|
||
- **Гейт на `ExportNormalize`** ($0): `(c *Checkers) ExportNormalize` — no-op для цели без данных; 7 пайплайн-сайтов (waverun ×5, export.go, quality.go) → `r.checkers.ExportNormalize`. На CJK-цели `、→,` больше не порча.
|
||
- **`ruSanitizer` → поле Checkers** (`sanitizer.go`): 4 пар-init-компилированных RE (preamble/trailing/edit-meta/invalid-sign) → per-run поля `Checkers`, компиляция из цель-данных; `SanitizeOutput` = метод `*Checkers`; свободная `SanitizeOutput` — документированная ru-дефолт-обёртка для тестов (41 тест-сайт не тронут).
|
||
- Бамп `CheapGateVersion` v5→**v6** (токенизатор — алгоритм cheap-gate).
|
||
- **Приёмка (`TestTargetSeamInertness`):** цель без данных (→en) — `TargetActive()=false`, `tokenizeWords→nil`, sanitizer-паттерн-классы инертны; ru активна; ru-токенизатор фолдит U+0301. PASS.
|
||
|
||
### П2 — скрипт-шов источника ✅ (закрывает живой баг ko)
|
||
|
||
- **Данные:** новый `internal/lang/data/lang-script.txt` (lang→scriptname, объявляется, не нюхается): zh→han, ja→han+hiragana+katakana, ko→hangul+han, en→latin, ru→cyrillic. `internal/lang/script.go`: реестр `scriptRanges` (ОДИН на весь движок, `checks` резолвит word_script через него же), `LangScripts()`, `IsCJKScriptLang()`.
|
||
- **`cjkShare` → `sourceScriptShare(out, scripts)`** (`disposition.go`): меряет долю ОБЪЯВЛЕННОГО письма источника; `classifyInput.SourceScripts` ставится из `r.checkers.SourceScripts()` (2 caller: chunkrun, repair). en-эхо (латиница) и ko-эхо (Hangul) теперь детектируемы. Флаг `cjk_artifact` и детейл-вокабуляр СОХРАНЕНЫ (стор-вердикт не переименован).
|
||
- **`isCJKLang` → данные:** `isCJKTarget` → `lang.IsCJKScriptLang`; `sourceEchoExposure` (`runner.go:391`) → то же. Case-insensitive (сохранён старый lower/trim).
|
||
- **Репэйр script-guard** (`repair.go:435`) → `c.SourceScripts()` (тот же source-script notion, не хардкод Han+кана). `*Checkers.SetSourceScripts` ставится в `loadLangPack`.
|
||
- **Hangul-решение (санитайзер):** `isCJKLeakRune` (`sanitizer.go`) += Hangul — Hangul-ран в Cyrillic-выходе = утечка, target-side, source-agnostic. Бамп `SanitizerVersion` v6→**v7**.
|
||
- Бамп `classifierVersion` v1→**v2**.
|
||
- **Приёмка (`TestSourceScriptShareAndTarget`, `TestSecondPairDryRun`):** Hangul под ko-источником share ~1 (был слепой), под ja ~0; LangScripts reachable для zh/ja/ko/en/ru (эхо-детектор не спит молча). PASS.
|
||
|
||
### П3 — нарезка/оценка ✅ (3 позиции флагнуты — §5)
|
||
|
||
- **`話` в chapter_unit** (`cjk-section.txt`, ДАННЫЕ): доминирующая единица ja-вебновелл (第1話) — .txt-книга больше не становится ОДНОЙ главой. Голден (第N章) нейтрален. Тест `TestChapterUnitJaWebnovel`.
|
||
- **`sourceAbbrevs` по языку книги** (`chunker.go`): `var sourceAbbrevs = lang.SentenceAbbrev("en")` удалён; `abbrevs` протянут `SplitChunks→chapterDraftChunks→packSentences→splitSourceSentences→isAbbrevBefore`; runner-хелпер `r.sentenceAbbrevs()`. CJK-источник → пустой набор, не консультируется.
|
||
- **Generic-детект глав** (`chunker.go` `matchHeaderLine` + `lang/langpack.go` `parseHeading`): `units` СДЕЛАН опциональным (правило без units = маркер+число, «Chapter 12»); терпимость пробела маркер↔число; unit-bearing путь (zh 章) сохранён (гард `第一次`). Тест `TestStripHeadingGenericLatinMarker`.
|
||
- **Консолидация класса письма + вторая копия арифметики** (`text/runes.go` `DenseScript`/`DenseSparseCounts`): ОДИН дом sizing-таксономии; `render.EstimateTokens`, `chunk.TokenClassCounts`, `membank.glossaryLineTokens`, `text.SignificantLen`, `membank.spacedPhoneticScript` — все на нём. Значения идентичны (голден нейтрален).
|
||
- Бамп `chunkerVersion` v5→**v6** (generic-heading + srcabbrev — алгоритм нарезки).
|
||
|
||
### П4 — пак как механизм ✅
|
||
|
||
- **Табличный список опциональных файлов** (`langpack.go` `Load`): 4 копипаст-блока (heading/dc-checkers/speech-cue/terminology) → таблица `{dir, name, apply}` + цикл; порядок фолда в хеш СОХРАНЁН (голден нейтрален).
|
||
- **Манифест по каналам** (`langpack.go` `readManifest` + `Pack.channels`/`HasChannel`): опциональный `manifest.txt` в каталоге источника объявляет каналы `source-morphology`/`transliteration`; `Load` читает и `validate()` требует ТОЛЬКО объявленные; **манифест-less пак = все каналы = БАЙТ-ИДЕНТИЧЕН (нет бампа `packAlgoVersion`, нет перепокупки существующих паков)** — манифест-байты фолдятся лишь при наличии. Майнер получает инертный канал + WARN (`runner.go` `loadLangPack`).
|
||
- **Новые файлы книгой не оверлеятся** — УЖЕ обеспечено: аллоулист оверлея = `srcFiles`+`pairFiles`, fail-loud на любой другой файл (`LoadWithOverlay`). Зафиксировано, ничего не добавлял.
|
||
- **Приёмка (`TestManifestChannelsGateRequiredFiles`):** источник с `channel source-morphology` грузится БЕЗ Palladius-файлов; манифест-less пак версией = байт-идентичен, манифест-с-обоими-каналами двигает версию (drift-proof). PASS.
|
||
|
||
### Дешёвая шестёрка ✅ 2/6 (4 флагнуты — §5)
|
||
|
||
- **#11 U+0301** — ЗАКРЫТ токенизатором П1 (выше).
|
||
- **`translitInterjections` → данные** (строка 26): Go-литерал `cheapgates.go` → `translit_interjection` в `target-ru.txt`; поле `Checkers.translitInterjection`; `lintTranslitInterjections` → метод `*Checkers`. Значения идентичны.
|
||
|
||
### Малая пачка ✅ 1/2 (#78 флагнут — §5)
|
||
|
||
- **#77 ре-ген N=1 перед эскалацией для `cjk_artifact`** (`config/pipeline.go` `RegenerateEchoBeforeEscalate` + `stagerun.go`): опциональная ручка, **дефолт 0 = текущее поведение** (эхо эскалирует сразу); при >0 эхо ре-генерит на той же модели N раз до хопа (D39.61: эхо на 0731 стохастично по вызову, ре-ген ≈7.6× дешевле). **Гейт D19.2 НЕ ослаблен ни на байт** — меняется только ОТВЕТ на эхо. Retries не фолдится в снапшот ⇒ голден нейтрален.
|
||
|
||
---
|
||
|
||
## 3. Самоверификация исполнением (команды/числа)
|
||
|
||
| Проверка | Команда | Результат |
|
||
|---|---|---|
|
||
| build | `go build ./...` | EXIT 0 |
|
||
| vet | `go vet ./...` | чисто |
|
||
| gofmt (мои файлы) | `git diff --name-only \| grep .go \| xargs gofmt -l` | пусто (все форматированы; `llm.go` — ПРЕД-существующее, не мой diff, не трогал) |
|
||
| гонки | `go test -race ./...` | **14/14 пакетов ok** (pipeline 81s, store 15s) |
|
||
| голден Ш-1 | `TM_UPDATE_GOLDEN=1 go test ./internal/pipeline -run TestGoldenDeterminism -v` | **`0 verdict/wire change line(s), 172 version-only line(s)`** — кумулятивно по всему пакету |
|
||
| майнер-парити | `TM_MINER_PARITY=1 go test ./internal/miner -run Parity -v` | **`n=13618 catastrophe{方源:0 蛊:1 蛊师:2 古月:22} recall@proposed=0.9655`** — EXACT |
|
||
| мут. П0-байт | `go test ./internal/lang -run TestEmbeddedVersionMutation` | PASS (target-ru.txt И injection.txt двигают версию) |
|
||
| мут. П1-инертность `target_lang: en` | `go test ./internal/checks -run TestTargetSeamInertness` | PASS (слой 7 инертен по отсутствию данных) |
|
||
| мут. П2-Hangul | `go test ./internal/pipeline -run TestSourceScriptShareAndTarget` | PASS (ko-Hangul share ~1, был 0) |
|
||
| сухой прогон 2-й пары | `go test ./internal/lang -run TestSecondPairDryRun` | PASS (LangScripts reachable zh/ja/ko/en/ru — эхо не спит молча) |
|
||
| 2-я пара loud-stop | инспекция `config/pipeline.go:899-908` | `bad(...)` на отсутствующий промпт называет путь — ja→ru/en→ru доходят до ГРОМКОГО промпт-отказа, не тихого засыпания; мои правки silent-sleep НЕ добавили (П2 УБИРАЕТ en/ko слепые пятна) |
|
||
|
||
**Дисциплина «вывод на агрегате до вскрытия единиц»:** каждый снапшот-двигающий пакет верифицирован per-package golden Ш-1 отдельно (П0 сам по себе 0/172; П1 кумулятивно 0/172; П2 0/172; П3 0/172; финал 0/172) — не собирал зелёный агрегат до вскрытия по-пакетно.
|
||
|
||
## 4. Протокольная сводка сдвинутых снапшот-осей (перекупок на этой фазе НЕТ — D39.63)
|
||
|
||
Стендовый корпус одноразовый; `--resnapshot` НЕ запускался; следующий замер = свежий мини-прогон на новом стеке. Механика фолдов построена для эры боевых книг после МАСШТАБА. Оси, которые пакет СДВИНУЛ (при будущем resnapshot дадут громкий стоп, вердикты не двигаются):
|
||
|
||
| Ось | Было → Стало | Пакет | Тип |
|
||
|---|---|---|---|
|
||
| `embedded_version` | (нет) → `embed-v1-…` | П0 | **новая ось** (безусловный фолд) |
|
||
| `CheapGateVersion`→`style_check_version` | `cheapgate-v5-…` → `cheapgate-v6-target-tokenizer-combmark` | П1 | бамп (токенизатор) |
|
||
| `SanitizerVersion` | `sanitizer-v6` → `sanitizer-v7-hangul-leak` | П2 | бамп (Hangul-leak) |
|
||
| `classifierVersion`→`classifier_version` | `classify-v1-…` → `classify-v2-refusal+srcscript-echo015+loop` | П2 | бамп (source-script echo) |
|
||
| `chunkerVersion`→`chunker_version` | `chunker-v5-…` → `chunker-v6-generic-heading+srcabbrev` | П3 | бамп (generic-heading+abbrev) |
|
||
|
||
Плюс DATA-плоскость (покрыта `embedded_version` + `LangpackVersion`): `target-ru.txt` (+word_script, +translit_interjection), `cjk-section.txt` (+話), новый `lang-script.txt`. `packAlgoVersion` НЕ бампался (манифест обратно-совместим). Голден `capture.golden` перезахвачен ($0 fake-replay) — 172 хеш-строки, 0 вердиктных.
|
||
|
||
## 5. Позиции, помеченные на владельца (флаг, не тихий пропуск — мандат D39.62)
|
||
|
||
Каждая — с причиной и рекомендованным дизайном; ни одна не сделана «тихой интерпретацией».
|
||
|
||
1. **ё-фолд `NormalizeTargetForm`→данные (П1).** РАСХОЖДЕНИЕ с задокументированной позицией: код трактует ё↔е-фолд как «generic orthography» (`cheapgates.go:305-308`; `memoryNormAlgoVersion` вшивает `yofold` как алго-константу). `text` — намеренный script-agnostic лист (не импортирует `lang`), а `NormalizeTargetForm` зовётся в ~13 сайтах через ВЕРДИКТ-НЕСУЩИЙ банк (`memvoice`/`mempostcheck`/`memory`/`checkers`/`voice`) — чистый вынос = смена сигнатуры core-примитива + сдвиг `memory_version` с симметрично-фолд-риском, ради спекулятивной не-ru цели. Приёмка П1 (en→ru/→en инертны) УЖЕ достигнута гейтом `TargetActive`. **Рек.:** target `char_fold ё е` в данных + per-run `text.TargetForm{fold}` протянутый из `*Checkers`/банка, ru = значение-по-умолчанию. Держу до подписи (мандат «расхождение промта с кодом = пинг, не тихая интерпретация»).
|
||
|
||
2. **segmentation-фолбэк = громкая ошибка (П3.D).** РАСХОЖДЕНИЕ с РАТИФИЦИРОВАННЫМ ТЕСТОМ: `config/prompt_pack_test.go:193,236-238` явно проверяет, что пар-конфиг «только с коридором» СОХРАНЯЕТ generic-фолбэк (1797/3200/1.1978/0.3852); комментарий `pipeline.go:832-841` документирует, что голден-фикстура НА НЕГО ОПИРАЕТСЯ и релокация отвергнута least-mechanism §12.1. D39.59 («терпимость к своим данным = воркэраунд») новее и план на него ссылается — НО громкий фолбэк ломает этот тест-контракт и требует, чтобы КАЖДЫЙ пар/пайплайн-конфиг объявлял полный блок segmentation. **Рек.:** объявить segmentation в голден-`pipeline.yaml` (те же числа → голден нейтрален) + сделать фолбэк громким; подтвердить, что владелец готов сломать контракт corridor-only-фолбэка. Блокирующего исполнения без live-аудита конфигов ($0) не делал.
|
||
|
||
3. **EstimateTokens N-коэффициент из данных (П3.E).** Сделана КОНСОЛИДАЦИЯ разбросанного класса (§П3). Полный «N классов из данных» = смена `config.Fertility{CJK,Other}` (2 поля) на map — снапшот-фолдящийся config-тип + вся арифметика читающая `.CJK`/`.Other`; коэффициенты для новой пары НЕ калибруемы ($0, токенизатора deepseek-v4 в репо нет — отчёт §10/§11). **Рек.:** `Fertility` как per-script-class map с ru-дефолтом-значением; коэффициенты офлайн-калибровкой когда появится боевой токенизатор.
|
||
|
||
4. **encoding-аллоулист из данных (П3.F).** Ядро — ДЕКОДЕРЫ (GB18030/Shift-JIS) — принципиально Go/x-text, данными декодер не добавить. Текущий «zh→GB18030» скоуп (`ingest.go` `autoDecodeSource`) корректен для ЕДИНСТВЕННОГО не-UTF-8 источника в скоупе; пустой-source-случай (`sourceLang==""`→пробует GB18030) — тонкость, чей data-drive меняет поведение unknown-source. **Рек.:** `source-encoding.txt` (lang→encoding-name) + Go name→decoder-реестр (как script-реестр), скоуп из данных, декодеры остаются Go; ja Shift-JIS = отдельная декодер-проводка (сегодня намеренно fail-loud).
|
||
|
||
5. **4 дефекта пака-21: #2 K4b-атрибуция, #4 inner_marker-вето-на-тире, гомоглиф-детектор, строгий OffLanguage.** Это K-рубрика defect-класс, чья КОРРЕКТНОСТЬ верифицируется только против размеченного корпуса пакета-6 (ВНЕ git — отчёт §11.7). Гомоглиф-детектор ФУНКЦИОНАЛЬНО СУЩЕСТВУЕТ (`sanitizer.go:432` `tk.mixed` mixed Cyrillic+Latin). Строгий OffLanguage ЯВНО оговорён отчётом/промтом (36а: `甲等→класс Цзя` не ловит, D39.58 утечку алфавита НЕ воспроизвёл 0/150 — «не заявлять как дешёвый выигрыш»). #4/#2 — глубокая семантика (диалог-тире mixing rule) вердикт-риск без стенда. **Рек.:** взять на пакет-чекеров с доступом к `books/gu-zhenren/labels/` (свежий мини-прогон), не $0-код-фаза.
|
||
|
||
6. **#78 billed 2xx-decode-fail → request_log (ОБЯЗАНА).** Корректная реализация требует per-billed-attempt reserve+settle+уникальный-checkpoint (money/ledger/checkpoint-key путь): транспорт-ретраи billed-decode живут ВНУТРИ одной пайплайн-резервации (`httpllm.go:352-371` `billedDecodeSeen`, cap 1), провайдер списал N раз, зарезервировано на 1. Точная цена НЕИЗВЕСТНА (undecodable body → нет usage → оценка). Схема УЖЕ готова (`store.RequestLog.Estimated` дословно называет «billed decode failure»), но settle оценки в леджер трогает контур согласия Р6/потолки. D39.61 УЖЕ документирует это как известную ≤$0.009/сессия НИЖНЮЮ границу. **Рек.:** `LLMResponse.BilledDecodeFails int` из ретрай-цикла + `BilledDecodeError` несёт `PriorBilledFails`; пайплайн зеркалит существующий terminal-decode settle+log (`stagerun.go:537-552`, `Estimated=true`) per extra-billed-attempt. Money-чувствительно — не $0-хастл.
|
||
|
||
## 6. Критик полноты
|
||
|
||
**Что этот отчёт/пакет НЕ содержит и содержать не может:**
|
||
1. **Ни одного платного вызова.** Вся верификация — детерминированные unit/golden/parity (fake-replay). Поведение на РЕАЛЬНОЙ второй паре живьём не мерено (нет ja/en-книги на стенде) — приёмка «доходит до промпт-отказа» статическая (код + dry-run), не боевая.
|
||
2. **Голден — книга БЕЗ langpack (ja).** Путь с загруженным паком (zh-ru) байт-в-байт голденом не пинится; манифест-по-каналам верифицирован СИНТЕТИЧЕСКИМ паком (`TestManifestChannelsGateRequiredFiles`), не голденом. Для ведра A голден — не защита; прямой замер `pack.Version()` (рецепт §6 отчёта) сохранён как инструмент.
|
||
3. **10 позиций флагнуто** (§5) — из них 4 (encoding, #4 inner_marker, частично #78) «граничные» (мог бы сделать при большем бюджете, но money/schema/label-set-риски перевесили в $0-код-фазе). Владелец волен сузить/расширить.
|
||
4. **`EstimateTokens` коэффициенты (1.1978/0.3852) остаются zh-ru-выведёнными** для ВСЕХ пар — консолидация убрала дубли класса письма, но НЕ откалибровала per-script (невозможно $0).
|
||
5. **Санитайзер глубже цель-шва НЕ обобщён:** `detectLatinInsertion`/`scriptTokens`/invalidSign-семантика остаются Cyrillic-target-специфичны (гейтятся `TargetActive`/`TargetScriptNonLatin`, вне скоупа П1 — §10 не просит обобщать scriptTokens).
|
||
6. **Голден `capture.golden` перезахвачен** (172 хеш-строки) — не закоммичен; при приёмке оркестратор сверяет Ш-1 «0 verdict/wire».
|
||
7. **Параллельная полигон-сессия** писала в `docs/archive/reports/POLYGON_BANK_*` — её файлы не трогал (зоны не пересеклись, как D39.63 подтвердил).
|
||
|
||
**Приёмочный критерий каждого пакета — «пара, которой нет в репо, проходит слой без правки Go» — достигнут для П0/П1/П2/П4 (мутационные+синтетические тесты доказывают) и для generic-heading/話/abbrev части П3; частично для П3 (3 флага).**
|
||
|
||
**СТОП — приёмка оркестратора. Сессия НЕ коммитит; `--resnapshot` НЕ запускался.**
|