Record the English pair pack report and its plan note, both written by the backend session in its own journal section

This commit is contained in:
heaven 2026-09-18 03:51:17 +03:00
parent ddadb3e619
commit 63e3a0d01a

View file

@ -210,6 +210,672 @@
## Бэкенд
#### ОТЧЁТ пака «АНГЛИЙСКАЯ ПАРА en→ru» (18.09, сессия `textmachine-main-c5`). НЕ КОММИЧУ — дерево передаю оркестратору №23
**Деньги пака: $0.** Платных вызовов моделей — ноль. Дымовая покупка §4.10 НЕ делалась: прогон отложен
словом владельца («доведи до ума всё перед прогоном»), а без прогона она ничего не доказывает. Весь
инвентарь снят `tmctl manifest` / `tmctl translate` на $0-конфиге (все модели рендера — `local-qwen3-8b`,
провайдер `local`, все цены нулевые; ключей провайдеров в окружении нет ни одного, `.env` рядом с пробным
`book.yaml` нет, CWD проб — не `backend/`), пробами на КОПИЯХ дерева и чтением EPUB питоном.
##### 1. Исход по КАЖДОМУ пункту заказа — по списку ЗАКАЗЧИКА, а не по своему
| пункт промта | исход | чем предъявлено |
|---|---|---|
| §4.1 инвентарь исполнением | **сделано** | восемь стен с командами в записке-плане; ряд 315 пере-снят своим прибором |
| §4.1 фабл-советчик до кода | **сделано** | один агент, постоянный контекст, **шесть кругов**, восемь ОК с обеих сторон |
| §4.2 промт-пакет пары, состав решаю сама | **сделано** | 8 файлов `prompts/en-ru/`, довод по каждому — `backend/docs/EN_RU_PAIR_BASIS.md` |
| §4.2 сквозной прогон пути манифеста ПЕРВЫМ делом | **сделано, посылка ОПРОВЕРГНУТА** | пять написаний манифеста + живой `tmctl translate`: двери нет |
| §4.2 одиннадцать таблиц морфологии | **НЕ ДЕЛАЮ с замером** | единственный потребитель — Han-only майнер; отказ подписан оркестратором |
| §4.3 путь данными вокруг гейта терминолога | **сделано** | сквозной прогон до `calling model … estimate_usd=0.000000` |
| §4.3 правка Go под ряд 347 | **НЕ ДЕЛАЮ** | без слова оркестратора, как велено |
| §4.4 нарезка глав | **НЕ ЧИНЮ с доводом** | `EN_RU_PAIR_BASIS.md` §12: замер, три причины, граница ряда 303 |
| §4.5 порог эха — замер, потом решение | **замер сделан, порог НЕ двинут** | §11 дока: 0 из 75 выше порога, запас 11× на прозе |
| §4.6 детектор латиницы — замер | **сделано, найден его СВОЙ дефект** | §11: 10 из 75, хиты — французские вставки; `Château Impérial` → три осколка |
| §4.7 ключи банка — замер | **сделано, подозрение сужено** | §11: 3 из 25 ключей с омографом; лечение дисциплиной промта |
| §4.8 бюджет нарезки — оценка | **сделано, названо оценкой** | `configs/pairs/en-ru.yaml`: `other = r/3.64 = 0.4203` |
| §4.9 что НЕ входит | **соблюдено** | не-Han майнер, целевая латиница, пиньинь-канал, японская пара, `gates.repair` не тронуты |
| §4.10 дымовая покупка | **НЕ ДЕЛАЮ** | прогон отложен владельцем; пинг с ценой не потребовался |
| §5 мутации на каждую новую ветку | **сделано** | 12 записей, все `battery`, 12/12 RED; седьмая ветка добрана на разборе мелких |
| §5 адверсариальный проход по СВОЕЙ работе | **сделано, нашёл 9 дефектов МОЕЙ работы** | 3 в гейте (§4) + 6 на поимённом разборе 37 мелких (§4б) |
| **заказ владельца: консилиум с фаблом, «пока вы оба не окните»** | **сделано** | §10 дока зоны: шесть кругов, что дал каждый; и ГРАНИЦА метода — двух дефектов не увидели оба, их поймали третьи читатели (§4г) |
| **заказ владельца: комментариев в промты не писать «ни в каком виде»** | **сделано** | 0 комментариев в 8 файлах `prompts/en-ru/`; из `prompts/zh-ru/` сняты в 3 файлах из 11, провенанс переехал в док зоны §8, хеши не сдвинулись |
| **заказ владельца: ресёрч полигона и его замеров** | **сделано, и два вывода ОТОЗВАНЫ** | §3 и §9 дока зоны: редакция `_BRAK` доказана кодом; английские судейские числа помечены как снятые на искажённом тексте |
| **заказ владельца: дефекты РЕПОРТИТЬ оркестратору и ПРОКОНТРОЛИРОВАТЬ, что взяты в оборот** | **сделано** | §5: 13 находок, каждая с ценой; контроль — ряды 347/499/500 открыты, курсив забран в следующий пак, ряд 498 пере-формулируется |
| **заказ владельца: никаких хаков и воркэраундов** | **соблюдено** | ни один тест/гейт не правлен «чтобы прошло»; смена поведения подана ратифицируемо (§2), два отказа — с замером (§6) |
| **слово владельца 17.09: данные обязаны отрабатывать там, где явления НЕТ** | **сделано** | пакет пройден построчно: снят `stone` (мера ×0), обоснование «в мире книги нет метрики» заменено, французский слой поднят до КЛАССА |
| §6 три оси ревью | **сделано** | §4: одна ось поймала мою собственную ошибку |
| §7 записка-план до кода | **сделано** | выше в этом журнале |
##### 2. ⛔ СМЕНА ПОВЕДЕНИЯ — подаю ратифицируемо, отдельным пунктом
**Заведён ключ `prompt_variant`** (`internal/config/pipeline.go`): вариант РОЛИ резолвится конвенцией
`<prompts root>/<пара>/<роль>-<вариант>.md`, то есть внутри каталога пары КНИГИ. Четыре боевых конфига
переведены с `prompt_override` на него. `prompt_override` сохраняет ратифицированное пар-агностичное
значение — пин `TestPromptOverrideIsPairAgnostic` не тронут ни байтом и зелен (проверено и на мутанте).
**Почему это потребовалось.** До пака свойство «книга не едет чужими конвенциями» держалось ОТСУТСТВИЕМ
второго промт-пакета: боевые конфиги указывали на `../prompts/zh-ru/translator-banknote.md` литералом, а
другая пара отказывалась на ПРОЧИХ стадиях, чьих файлов не было. **Мой собственный пакет это отсутствие
убирал.** Замер после его появления: `pipeline-c1.yaml` для пары `en-ru` ЗАГРУЖАЛСЯ, draft резолвился в
`prompts/zh-ru/translator-banknote.md`, edit — в `prompts/en-ru/editor.md`: китайские правила мер и
паратаксиса на английской книге, молча.
**Цена перехода четырёх конфигов — ноль, и это замер.** Хеш промта берётся по СОДЕРЖИМОМУ после снятия
комментариев, путь в него не входит: тот же файл по другому пути и под другим именем дал
`602fb80236ab9834` против `602fb80236ab9834`; контроль — один добавленный байт содержимого дал
`42fedc886b5fdc5d`. Поведение zh-ru не сдвинулось: `TestBoevoyPipelineC1ResolvesZhRu`,
`TestPairLayerCarriesCalibration`, `TestEveryShippingConfigLoadsUnderThePairLayer` зелены; эффективные
числа пары те же (1797/3200, 1.1978/0.3852, коридор [2.2 4.2]).
**Обслуженный пин №1, и он сработал как задумано.** `TestInternalCallDecidesEveryStageField` покраснел на
новом поле `Stage.PromptVariant` («is not decided for engine-internal calls»). Я не подгоняла тест: довод
вписан в `internal_call.go` рядом с соседями (гейты, делающие внутренние вызовы, резолвят промты по
ПЛОСКОЙ ролевой конвенции, поэтому вариант на этом шве назвал бы файл, которого никто не читает), строка
решения — в `deliberatelyZero`.
**Обслуженный пин №2 — и он о том же классе, что и смена поведения.** `TestPromptLabelsPinTheirBytes`
ходил по ОДНОЙ паре (`const pair = "zh-ru" // the only pair with a prompt pack in the repo; a new pair
joins this map by existing`), и мой второй пакет сделал этот комментарий ЛОЖЬЮ: восемь новых промтов
оказались вне байтового гейта. Гейт пере-написан на цикл по парам с диска — делает то, что комментарий
уже обещал; реестр лейблов 6 → 12 ключей. То же у `TestEditorPromptIsBilingual` (читал только
`prompts/zh-ru/`): теперь цикл по парам, `editor-mono` опционален на пару.
##### 3. ЧИСЛА — все сняты ПОСЛЕ последней правки, каждое с командой
**Батарея зоны.** `cd backend && make battery`**`MAKE_EXIT=0`** (лог `battery-final9`, снят ПОСЛЕ
последней правки кода и данных). Цели в логе — восемь команд: `go build ./...` · `go vet ./...` ·
`go vet -tags live ./...` · сборка `bin/tmvet` · `go vet -vettool=bin/tmvet ./...`с `-tags live`) ·
`golangci-lint run --timeout=15m ./...` · `go test ./... -race -count=1 -timeout=20m`, плюс харвест-пасс.
Линтер **`0 issues.`**. Полнота СПИСКОМ, не хвостом: `go list ./...` = **24**, вердиктов в логе = **24**,
`comm -23` и `comm -13` пусты **ОБА**. Строк `FAIL`**0**. `internal/pipeline`**420.038s** (подпись
нагрузки: на свободной машине).
⛔ **И ПРЕДЫДУЩИЙ ПРОГОН БЫЛ КРАСНЫМ, НА ПАКЕТЕ, КОТОРОГО Я НЕ ТРОГАЛА — говорю это сама, потому что в
акт идёт `final9`, а `final8` существует.** `MAKE_EXIT=2`,
`TestARefusalIsNotAPurchaseEvenWhenTheReplyOutrunsTheWrite/the_body_was_still_writing_when_the_refusal_arrived`
(`internal/llm`). Текст падения — о ПОСЫЛКЕ, не о предмете: «premise: the provider was connected to 3
time(s) … write: connection reset by peer» и «the client came back with a STATUS, so this run never reached
the delivery question» ⇒ локальной HTTP-фикстуре сбросили соединение, и тест честно покраснел вместо
молчаливого зелёного.
Разбор прибором, а не мнением: моих файлов в `internal/llm`**0**; развёрнут чистый `HEAD`
(`git archive HEAD backend | tar -x`, ревизия `77f3791`) и `./internal/llm -race -count=1` прогнан
**вперемежку** по три раза в каждом дереве — **6 из 6 зелёных** (мой 14.3/13.8/13.9s, чистый
14.0/14.0/14.1s); по батареям смены частота **1 из 9**, в прогонах `final``final7` этот тест не падал ни
разу.
**Формулирую дизъюнкцией, а не удобной определённостью:** падение пришлось на окно, в котором рядом
работали моя батарея и агенты оркестратора с разрешением на сборку (его замер: в кеше сборки за 35 минут
тронуто 5474 файла из 125 280; его копия под кампанию сделана в 02:49, ВНЕ окна). Прибора, который разделит
чьё давление сбросило соединение, у нас нет, и я не пишу «флейк»: **«не воспроизвелось» ≠ «дефекта нет»**.
Уцелевает утверждение, которое прибор держит: с моим диффом падение не связано.
**Следствие для мутационной кампании, названное оркестратору до её запуска:** запись, чей текст падения
говорит `premise:` или `connection reset by peer`, поимкой НЕ является — тест не дошёл до предмета, запись
НЕ ИЗМЕРЕНА, и её число печатается отдельным третьим исходом, а не складывается с пойманными. Скипы (`--- SKIP` харвест-пасса)
**6**: `TestCorpusBankKeyConflicts` · `TestHelperEventsRun` · `TestHelperKillLoop` ·
`TestMinerFullBookParity` · `TestProbeBankBasisM1` · `TestProbeBankBatchOrdinalShift`.
**Число скипов зависит от ДЕРЕВА, а не от рецепта, и мои шесть — не полный список РАБОТЫ.** Рецепт
`battery` гонит харвест-пасс в `mktemp` и печатает из него ТОЛЬКО строки `--- SKIP`: строк `--- PASS` в
логе **0**, то есть по нему не видно, что отработало. Приёмка на ОТДЕЛЁННОЙ копии получила **11** скипов —
её знаменатель шире моего на пять корпусных (`TestCheckerLabels` ×2, `TestK6Labels` ×2, оракул холодного
прогона), потому что харнессы ищут книги, поднимаясь вверх от своего исходника: в ворктри `../books`
симлинк, и он резолвится, а над копией книг нет. Проверено исполнением у меня: все пять дают `PASS`. ⇒ два
честных прибора о разных условиях; в ворктри корпусный контур ОТРАБОТАЛ, в копии он недостижим.
**Мутации.** Каталог 526 → **538** записей, в гейте `battery` 315 → **327**; моих **12**, все с флагом.
Прогоны на КОПИЯХ (`tar` без `.env`; базовый прогон пакета зелёный ПЕРЕД каждой посадкой; восстановление
сверено `diff -rq`):
| запись | слой посадки | покрасневший пин |
|---|---|---|
| `EN-variant-resolves-in-the-books-pair` | Go | `TestPromptVariantResolvesInsideTheBooksPair` + пар-гейт |
| `EN-variant-and-override-both-accepted` | Go | `TestPromptVariantAndOverrideAreMutuallyExclusive` |
| `EN-variant-accepts-a-path` | Go | `TestPromptVariantMustBeABareName` |
| `EN-variant-missing-file-is-silent` | Go | `TestPromptVariantMissingFileFailsLoudNamingPairAndVariant` |
| `EN-shipping-config-pins-the-pair-in-a-path` | ДАННЫЕ | пар-гейт + арм-паритет |
| `EN-pair-fertility-falls-back-to-zh` | ДАННЫЕ | `TestEnRuPairLayerCarriesItsOwnFertilityEstimate` |
| `EN-override-traverses-out-of-the-pair-dir` | ДАННЫЕ | пар-гейт (закрывает `..`-обход) |
| `EN-shipping-config-stops-serving-a-pair` | ДАННЫЕ | пар-гейт (закрывает молчаливый недобор) |
| `EN-prompt-moves-under-a-stationary-label` | ДАННЫЕ | `TestPromptLabelsPinTheirBytes` **и** `TestBanknotePromptIsItsTranslatorPromptPlusOneBlock` (со-ловцы, названы оба) |
| `EN-banknote-body-drifts-from-the-translator-it-copies` | ДАННЫЕ (промт + значение реестра) | ТОЛЬКО `TestBanknotePromptIsItsTranslatorPromptPlusOneBlock`; байтовый гейт при этой посадке **PASS** — этим посадка и изолирующая |
| `EN-variant-branch-stops-naming-the-variant` | Go | `TestPromptVariantMissingFileFailsLoudNamingPairAndVariant` (после того как утверждение перестало удовлетворяться напечатанным путём) |
| `EN-production-pair-layer-drifts-unseen-by-the-english-pin` | ДАННЫЕ | `TestEnRuPairLayerCarriesItsOwnFertilityEstimate` **и** `TestPairLayerCarriesCalibration` **и** `TestEveryShippingConfigLoadsUnderThePairLayer`со-ловцы названы, потому что дыры в дереве не было |
Итог: **12 из 12 RED, 0 неожиданных исходов, 0 неизмеренных, 0 протухших якорей из 538.**
**Чем это снято и чем НЕ снято.** Мои 12 записей прогнаны `go run ./cmd/tmmutate -root <копия> -id …`
поодиночке и пачками, каждая на СВЕЖЕЙ копии под `/home/ubuntu/tm-c5-stand/mut-*` (проверка `pwd` + `test -f
go.mod` перед правкой, копия удалена после замера). **Полный каталог на 538 записей своим корнем я НЕ
гоняла** — это прибор приёмки, и два утверждения складывать нельзя: «мои 12 красные» и «каталог
целиком зелёный» суть разные замеры одного предмета.
⚠ И ротация якорей своя: правка сообщения загрузчика рассыпала `EN-variant-missing-file-is-silent`
(«anchor occurs 0 times»), правка промта — value-coupled якорь записи банкноты. Оба наведены на ЖИВОЙ
предмет (сама проверка `os.Stat`, действующее значение реестра), подметание после этого — `0 of 538 rotten`.
Слой посадок по `edits[].file`: Go — 5, ДАННЫЕ — 8, файлов затронуто 7.
**ИСПР. при приёмке: записей в ДАННЫХ — ПЯТЬ, а не шесть.** Счёт по ЦЕЛИ каждой правки (`edits[].file`):
Go — 4 (все в `internal/config/pipeline.go`), ДАННЫЕ — 5 (`configs/pipeline-c1.yaml` ×2,
`configs/pairs/en-ru.yaml`, `configs/pipeline-c2.yaml`, `prompts/en-ru/translator.md`), смешанных 0.
Прежнее «шесть» я назвала по памяти, а не прибором; поймал оркестратор своим счётом. Довод не меняется:
три пина стоят над ДАННЫМИ, и мутация Go под них измеряла бы пустоту.
**Пакет промтов.** 8 файлов грузятся движком (`LoadPromptTemplate`); контроль — шаблон с отставленным
`{{genre}}` отвергнут ПРИ ЗАГРУЗКЕ. Комментариев — **0 из 8**. Реальных имён живой книги в тексте,
уходящем модели, — **0** (контроль прибора: слово «перевод» найдено 77 раз, значит файлы читались). Системная
часть банкноты — это системная часть `translator.md` плюс ОДНА вставка (канал ⟦TM-BANK-v1⟧), пользовательская
часть байт-в-байт та же.
⚠ **ИСПР. моего же текста: «собирается программно, равенство по построению» было ОБЕЩАНИЕМ — генератора нет,
файл собран один раз руками.** Своё утверждение я закрыла пином `TestBanknotePromptIsItsTranslatorPromptPlusOneBlock`
(`internal/pipeline/banknotebody_test.go`, идёт по КАЖДОЙ паре, у которой есть банкнотный промт: сегодня 2).
Изолирующая посадка: правку увести в ОДИН из двух файлов и обновить реестр лейблов документированным путём —
**байтовый гейт при этом ЗЕЛЁН** (снято на копии), краснеет только новый пин; зеркальная посадка (тронута
только банкнота) краснеет тоже; законная правка ОБОИХ файлов — зелено. Запись каталога
`EN-banknote-body-drifts-from-the-translator-it-copies` (`battery: true`, две правки: промт + значение реестра).
**Китайский пакет.** Комментарии сняты из трёх файлов (`classifier`, `editor-mono`, `terminologist`) из
**11** (7 ролевых + 4 в `repair/`; в `repair/` их не было). Хеши НЕ сдвинулись: `885766fd1e37`,
`54d9ee6ab743`, `78c59f547941` — до и после. Контроль: `tpl.System` начинается с «Ты — классиф», то есть
оставленные в файлах ведущие пустые строки на провод не уходят.
##### 4. АДВЕРСАРИАЛЬНЫЙ ПРОХОД ПО СВОЕЙ ГОТОВОЙ РАБОТЕ — он нашёл ТРИ дефекта в ней
Восемь линз по дереву (содержание промтов · механизм Go · держат ли пины · цена перехода конфигов ·
уборка комментариев · числа · мутации · полнота против заказа), 57 находок, триаж мой.
⛔ **Три настоящих дефекта МОЕГО гейта, все проверены посадкой на копии с зелёной базой:**
1. **Пин судил ПОДСТРОКУ пути, а не каталог.** `strings.Contains(path, "/en-ru/")` проходит на
`…/prompts/en-ru/../zh-ru/translator.md`. ⇒ предикат заменён на «родительский каталог ОЧИЩЕННОГО пути
равен паре». Посадка `prompt_override: ../prompts/en-ru/../zh-ru/translator-banknote.md` теперь даёт
красное с текстом про пару.
2. **Пин считал загрузки ПО ПАРЕ, а не по (конфиг, пара).** Конфиг, перестав обслуживать пару, снимал
себя с гейта молча: 3 из 4 неотличимо от 4 из 4. ⇒ счёт по (конфиг, пара), недобор — ошибка с
названным числом. Посадка даёт `checked 7 of 8 … the shortfall is reported above`.
3. **Мой пакет вывел восемь промтов из байтового гейта** (§2). Посадка «правка en-ru промта при
неподвижном `prompt_version`» теперь краснеет: «⚠ THE PROMPT MOVED AND ITS LABEL DID NOT».
**Четыре противоречия внутри промтов — сняты:** (а) `translator.md` объявлял список исключений из правила
абзацев ЗАКРЫТЫМ и следующей строкой требовал второго — сборки разорванного стихотворного блока; теперь
исключений названо два и сказано, что других нет. (б) Банкнота и терминолог утверждали ОДНОВРЕМЕННО «с той
же заглавной, иначе не найдётся» и «регистр при поиске не учитывается»: первое ложно и стояло ОБОСНОВАНИЕМ
правила. (в) «Past Perfect — совершенный вид» стояло безоговорочно, тогда как носитель (`research/12` §3)
утверждает только «Progressive → всегда несовершенный, обратное неверно»; добавлена оговорка о длительности
и повторе. (г) «часть книги — исповедь героя слушателю» — факт ЭТОЙ книги в ОБЩЕМ пар-слое; правило сделано
условным.
**Чего проход НЕ подтвердил** (отрицательный результат тоже мой): «скипов 6» — верно для ворктри; 11 у
приёмки — верно для отделённой копии, разбор в §3.
**И ПЯТЬ ВЕЩЕЙ, КОТОРЫХ МОЙ ТРИАЖ НЕ УВИДЕЛ ВОВСЕ.** Я сняла подпись советчика с пакета сама — после его
«окей» я внесла семь правок по находкам прохода, и подпись под изменённым текстом не стоит. На финальном
круге он нашёл пять пропусков, и **два из них — тот же дефект, который я починила в переводчике и не довела
в редакторе**:
1. `editor.md` «единственное штатное исключение — реплики» соседствовало с пунктом, требующим второго
исключения (сборка разорванного блока). Ровно то, что я сняла в `translator.md`. ⇒ «Исключений два, и
других нет».
2. `editor.md` «число предложений И АБЗАЦЕВ совпадать с исходником НЕ обязано» — наследие zh-редактора,
прямо отменявшее правило «абзацы авторские». ⇒ «число абзацев отличается только на исключения п.1».
3. `translator.md` и `editor.md`: правило велело передавать ЛЮБУЮ многоабзацную речь обычным
повествованием. Для рамочного рассказа верно; для обычной английской книги та же типографика (re-open
«“» в каждом абзаце — общая англо-американская конвенция) означает длинный МОНОЛОГ собеседнику, и по
русской норме каждый его абзац начинается с тире. ⇒ правило различает два случая по содержанию чанка.
4. `translator-banknote.md`: список точности первого поля не называл ДИАКРИТИКУ, ДЕФИС и ПРОБЕЛ. Пере-снято
функцией движка: `NormalizeSourceKey` складывает регистр и вид апострофа, но `fabién``fabien` и
`jean-françois``jean françois`. Книга это провоцирует (`Fabién` ×180, `Jean-François` ×465) — без
правила терм молча выпадал бы из проверки покрытия.
5. Книжный факт «реплики сцен настоящего времени — парными двойными» ушёл вместе с переписыванием п.3.
**вывод о методе, который дороже самих правок:** починив противоречие в одном файле пакета, я не
проверила его БЛИЗНЕЦА, хотя редактор повторяет правила переводчика по построению. Собственный триаж этого
не увидел, потому что знаменателем ему служил мой же список находок.
##### 4б. ПОИМЁННЫЙ РАЗБОР 37 «МЕЛКИХ» — он дал ШЕСТЬ живых дефектов, и это был не косметический проход
Веер дал **57** находок: 20 крупных (закрыты выше) и 37 помеченных `minor`. Пачкой их закрывать было
нельзя: разобрав поимённо, я нашла шесть дефектов СВОЕЙ работы, каждый предъявлен посадкой, а не словом.
1. **ОБЕЩАНИЕ БЕЗ МЕХАНИЗМА.** Док зоны объявлял: «банкнота **собирается из `translator.md` программно**
правится ОДИН файл». Генератора в дереве нет, пина на равенство тел нет. Заведён
`TestBanknotePromptIsItsTranslatorPromptPlusOneBlock` (`internal/pipeline/banknotebody_test.go`): у
КАЖДОЙ пары с банкнотным промтом системная часть банкноты обязана быть системной частью переводчика
плюс ОДНА вставка, содержащая `⟦TM-BANK-v1⟧`, пользовательская — байт-в-байт. Сегодня таких пар 2.
**Изолирующий замер, он сильнее самого пина:** правку увести в ОДИН из двух файлов и обновить реестр
лейблов его же документированным путём (`TM_UPDATE_PROMPT_LABELS=1`) — **байтовый гейт при этом ЗЕЛЁН**,
краснеет ТОЛЬКО новый пин. Зеркальная посадка (тронута только банкнота) красная; законная правка ОБОИХ
файлов — зелёная. ⇒ без пина порча проезжала. Запись каталога
`EN-banknote-body-drifts-from-the-translator-it-copies` (две правки: промт + значение реестра; оба
якоря value-coupled, и подметание каталога об этом кричит).
2. **МОЙ ПИН УДОВЛЕТВОРЯЛСЯ ЧУЖОЙ УЛИКОЙ.** `TestPromptVariantMissingFileFailsLoudNamingPairAndVariant`
обещал именем, что сообщение назовёт ВАРИАНТ, а проверял токен `nosuch` — который есть и в напечатанном
ПУТИ `translator-nosuch.md`. ⇒ вариантная половина держалась не на том объекте. Теперь спрашивается
`variant "nosuch"` дословно; запись `EN-variant-branch-stops-naming-the-variant` даёт RED по имени пина.
Заодно найдено, что сообщение промаха ВАРИАНТА советовало `prompt_override` — то есть вело ровно к
зашиванию пары, от которого пак уходил: лечение разведено по случаю.
3. **ПРИБОР КАТАЛОГА ПОЙМАЛ МЕНЯ НА РОТАЦИИ ЯКОРЯ.** Правка того же сообщения рассыпала существующую
запись `EN-variant-missing-file-is-silent` («the anchor occurs 0 times»). Якорь наведён НЕ подгонкой под
то, что оказалось рядом, а на настоящий предмет мутации — саму проверку `os.Stat(cp)`. После этого
`anchors swept: 0 of 538 entr(ies) rotten`.
4. **ПОЛУПУСТАЯ ПОЛОВИНА В МОЁМ ЖЕ ПИНЕ.** zh-сторона `pairlayer_enru_test.go` утверждала «боевая пара не
тронута», опираясь на `1.1978/0.3852`а это ОДНОВРЕМЕННО литералы `configs/pairs/zh-ru.yaml` и фолбэк
`LoadPipeline` ⇒ отличить «пар-слой читается» от «пар-файла нет» она не могла. Добавлен коридор
`[2.2 4.2]` — единственная величина zh-слоя, которой в фолбэке нет.
**И честный итог посадки: коридор УЖЕ стерегли два других пина** (`TestPairLayerCarriesCalibration`,
`TestEveryShippingConfigLoadsUnderThePairLayer`) ⇒ дыры в дереве не было, пустая половина была в моём
утверждении. Это записано в `why` записи `EN-production-pair-layer-drifts-unseen-by-the-english-pin`, а
не выдано за починку дерева.
5. **ПРОЗА, СТАВШАЯ ЛОЖЬЮ ОТ МОЕГО ЖЕ ПАКА — четыре носителя, и один внутри теста, который стережёт
изменённую стадию.** Доккоммент `TestBoevoyPipelineC1ResolvesZhRu` утверждал, что стадия draft
объявлена через `prompt_override` (сегодня `prompt_variant: banknote`), и звал ja-ru отказом «only
prompts/zh-ru exists» (паков два); перечисление правила резолва в `internal/pipeline/runner.go`
осталось двучленным; `example/book.yaml` говорил «в репо есть только `prompts/zh-ru/`». Все четыре
приведены к дереву.
6. **ПРАВИЛО ПРОМТА ПРИ НУЛЕ ВХОЖДЕНИЙ ЯВЛЕНИЯ.** «Вес `stone` русской традиции не имеет… отличай
stone-меру от stone-камня» — замер по тексту книги: `stone`/`stones` **228**, МЕРОЙ ВЕСА **0**
(единственное вхождение с числительным — «five stone **bowls**», прилагательное). ⇒ правило требовало
различения там, где различать нечего, и ставило под сомнение 228 законных «камней». Снято из
переводчика, редактора и банкноты. Это частный случай ратифицированного слова владельца 17.09: данные
обязаны **так же хорошо отрабатывать там, где явления нет**.
**Вывод о методе, отдельно от находок:** «мелкая» в веере — это оценка ВЕСА, а не приговор о содержании.
Шесть из тридцати семи оказались тем, что чинится кодом и данными, и ни одна из шести не была бы найдена
чтением заголовков. Знаменатель разбора печатаю: 37 из 37 разобраны, классов 8, дубликатов между линзами
19 (один битый якорь нашли шесть линз из восьми).
##### 4в. ТАБЛИЦА СХОЖДЕНИЯ: находка → что сделано → чем предъявлено (все 57)
| класс находки (сколько) | что сделано | чем предъявлено |
|---|---|---|
| Пин судил ПОДСТРОКУ пути (1 кр.) | предикат → родительский каталог ОЧИЩЕННОГО пути | посадка `…/en-ru/../zh-ru/…` краснеет по имени пина |
| Пин считал загрузки ПО ПАРЕ (3 кр.) | счёт по (конфиг, пара) + недобор с названным числом | посадка даёт `checked 7 of 8 … the shortfall is reported above` |
| Восемь промтов ВНЕ байтового гейта (4 кр.) | цикл по парам с диска; реестр 6 → 12 ключей | `EN-prompt-moves-under-a-stationary-label` → RED двумя пинами |
| Противоречия внутри промтов (9: 4 кр. + 5 от советчика) | каждое снято текстом, близнец проверен | чтение обеих сторон + подпись советчика по файлам |
| Канон КНИГИ в общем пар-слое (3 кр. + 1 мел.) | правила сделаны условными; «в мире книги метрики нет» → «так принято в русской переводной прозе»; французский слой поднят до КЛАССА | греп «французск» — 3 файла из 8, каждый ВНУТРИ класса; вторая книга дерева больше не опровергает обоснование |
| Замеры §4.54.7 без результата в дереве (2 кр.) | §11 дока зоны: три замера с контролями | таблицы порога эха, детектора латиницы, ключей банка |
| Отчёта в дереве нет (1 кр.) | этот отчёт | он же |
| Ряд 498 не построен как предписано (2 кр.) | отказ ОБЪЯВЛЕН с доводом (§6 п.3) | `TestPromptOverrideIsPairAgnostic` — ратифицированный пин, который гард отменял бы |
| Битый якорь `terminologist.go` (6 мел.) | наведён на `internal/terminology/terminology.go:710-738` | греп `terminologist.go` по доку = **0** |
| «Собирается программно» (5 мел.) | пин + запись каталога + правка дока и отчёта | изолирующая посадка: байтовый гейт ЗЕЛЁН, краснеет только новый пин |
| Проза, ставшая ложью от пака (8 мел.) | 4 носителя правлены (доккоммент пина, `runner.go`, `example/book.yaml`, сообщение загрузчика) + README и `zh-ru.yaml` ранее | `TestBoevoyPipelineC1ResolvesZhRu` зелёный на исправленном тексте |
| Вывод без условия / односторонний §6 (2 мел.) | условие названо: `runner.go:432` `if r.Book.LangpackRoot == ""` | цитата кода в доке и в пар-файле |
| Обещанные файлы `langpacks/en/` (3 мел.) | диспозиция ПОФАЙЛЬНО (см. §6 п.4) | §12 дока: с файлом и без — манифест побайтно тот же; `langpack.go:305` + `runner.go:436` |
| Числа и контроли дока (7 мел.) | 7 правок, каждое число пере-снято своим прибором | 1345 JSON + 82 txt при контроле `uid` в 1235 файлах; `82759ef35326` против `f7bc660330a3`; 25 примеров ×0 при контроле `François` 517 |
| Пины без различающей силы (2 мел.) | коридор `[2.2 4.2]`; дословный `variant "nosuch"` | две записи каталога → RED |
| Содержание промтов: `stone`, FEWSHOT, рефрен/`said` (4 мел.) | `stone` снят; FEWSHOT назван как едущий только на армах; атрибуция названа исключением из рефрена | мера ×0 в книге; `few_shot: false` в c1/c2 против отсутствия ключа у армов |
| ⛔ НЕ подтверждено веером (1 мел.) | «скипов 6» — не дефект: два честных прибора о разных условиях | §3, разбор симлинка `../books` |
##### 4г. ПРО ЧТО ВЕЕР И КОНСИЛИУМ МОЛЧАЛИ ОБА — поймали ТРЕТЬИ читатели
**Механизм дефекта ингеста я назвала неверно ДВА РАЗА, и оба раза со словом «проверено».** Сперва
«перенос на каждый уровень вложенности `<blockquote>`», потом «`<p>` внутри `<blockquote>` — строка стиха».
Пере-снято МОИМ прибором по EPUB (126 документов): **`<p>` внутри `<blockquote>` — 0**. Такого механизма
нет. ⭐ Что есть: цепочек `blockquote` **88**, пустых 0, **87 из 88 несут ровно одну строку**, медиана
**32 знака**, и шесть подряд читаются как прозаический эпиграф, разбитый конвертером по строкам. ⇒ вывод
правила верен, объяснение было ложным; признак пере-формулирован без опоры на знаки конца предложения (они
у пар разные — такой признак ветвился бы по ЯЗЫКУ). Поймала полигонная сессия, подтвердил советчик,
пере-снято мной.
**Вторая форма стиха в этой книге моим правилом НЕ накрывается, и я это знаю:** оркестратор №23 замерил,
что курсив теряется в ингесте ПО ПОСТРОЕНИЮ, а среди потерянного — **154 строки гимнов, набранных
курсивными абзацами по строке** (ещё 32 блока). Носитель не доезжает до чанка ⇒ в промте это не лечится.
Забрано в следующий пак; от меня правок ноль, и молчать об этом было бы удобнее.
##### 5. НАХОДКИ О ДЕРЕВЕ — переданы оркестратору, каждая с ценой
| находка | замер | состояние |
|---|---|---|
| Манифест пары: двери для не-Han источника НЕТ | 5 написаний + живой `tmctl translate` | ряд 347, оркестратор |
| Реверс-секция банка РАБОТАЕТ на латинице | 4 поверхности → 4 строки дельты, четыре контроля | оговорка ряда 347 пере-решена |
| `mining.contrast_path` требует китайский корпус у ЛЮБОЙ пары | `EXIT=10`; с ПУСТЫМ контрастом майнер даёт те же нули | ряд, оркестратор |
| Ингест рвёт стихи: вложенные `<blockquote>` до 10 уровней | 726 абзацев из 11 203 не кончаются знаком конца предложения; прогонов из 8 `\n` — 101, из 16 — 66, до 24 | ряд 499 |
| Ингест теряет курсив целиком | 4842 разметки в 46 документах; следов в тексте движка 0 при сохранённых СЛОВАХ | ряд 500 |
| `lintLatinResidue` ASCII-only дробит акцентированное имя | `Château Impérial``Imp`, `rial`, `teau` | оркестратору |
| Ремонт не видит глоссарий | `repair.go:282` рендерит только `Book/Text/Draft` | оркестратору |
| Решения владельца 16.08/20.08 и слепое чтение 17.08 не ратифицированы и не в боевых промтах | `onepass-core.md:13-19`, `rol.py:187-190` | оркестратору |
| Правка ТЕКСТА банк-роли = пере-спрос решённых терминов | `bankbasis.go:183-187` | цена лечения zh `classifier.md` |
| Канон живой книги в пар-файле zh `classifier.md` | `:27` `方源 (Фан Юань)`, `:63` `元石 term none` | оркестратору |
| `$0` уборки комментариев держится ОДНИМ переносом строки | снятие с хвостовым пробелом двигает хеш, только тега — нет | в доке зоны §6 |
| ⛔ `prompt_version` НЕ МОЖЕТ метить две пары независимо | ключ реестра `<пара>/<роль>/<лейбл>`, а сам лейбл живёт в конфиге ОДНОЙ строкой на стадию ⇒ правка промта ОДНОЙ пары либо пере-использует лейбл над новыми байтами (то, ради чего гейт и стоит), либо бампает лейбл ВТОРОЙ пары ни за что | оркестратору; сегодня безвредно: en-ru-прогонов не существует, сравнивать под пере-использованным лейблом нечего |
| Ингест теряет курсив ПО ПОСТРОЕНИЮ, и среди потерянного 154 строки гимнов | замер оркестратора №23: в обходчике 0 упоминаний `span/i/em/italic/font-style/class=`, токен пишется безусловно | забрано в пак долга перед прогоном |
##### 6. ЧТО НЕ УДАЛОСЬ И ГДЕ ПРИБОР СЛЕП
**Не получилось.**
1. **Качество данных и промтов НЕ измерено и измерено быть не могло.** Размеченного корпуса для en→ru в
репозитории нет, человеческого эталона книги в дереве нет, покупка эталона — открытый вопрос владельцу.
Батарея зелена при ЛЮБОМ содержании восьми файлов. Единственный рубеж — консилиум. Самодельной метрики
не изобретала: она выглядела бы замером, не будучи им.
2. **Дымовая покупка не сделана**, значит путь «от интейка до файла, который читает человек» пройден до
`calling model` и НЕ дальше. Что движок доходит до модели — предъявлено; что он отдаёт читаемую книгу —
НЕТ.
3. **Гард ряда 498 в форме, которую ряд предписывает** («override обязан лежать внутри каталога пары ЭТОЙ
книги»), НЕ построен, и это не умолчание: он отменял бы ратифицированное свойство с живым пином. Вместо
него построен `prompt_variant`. ⚠ Ряд 498 писан ДО смены курса, и его первый критерий закрытия теперь
описывает не то, что сделано — пере-формулировка за оркестратором.
4. **ДВА ФАЙЛА, ОБЪЯВЛЕННЫЕ МОЕЙ ЖЕ ЗАПИСКОЙ-ПЛАНОМ, В ДЕРЕВЕ ОТСУТСТВУЮТ — и довод, стоявший в дереве,
покрывал только один из них.** Нашёл мой веер; диспозиция ПОФАЙЛЬНАЯ, потому что механизмы разные.
- `configs/langpacks/en/structure.txt`**НЕ заблокирован**: `LoadSourceStructure`
(`internal/lang/structure.go:141`) читает `<root>/<lang>/structure.txt` СВОЕЙ дверью, каталог пары ей
не нужен, а `parseSourceStructure` прямо рассчитан на латинский маркер («`Chapter`») и допускает
отсутствие `units`. ⇒ отказ не «нельзя», а **ИЗМЕРЕН инертным**: на контрольной английской книге
дерева (`books/fifty_shades_1_en.txt`, строк `^[[:space:]]*Chapter ` — 26) `tmctl manifest` даёт
`chapters=1 units=146 chunks=147` И БЕЗ файла, И С файлом `marker⇥Chapter` — числа побайтно те же,
потому что маркерная грамматика до не-CJK TXT-пути не доходит (тело ряда 303). Заводить данные,
которые ничего не меняют ни на одной книге дерева, я не стала; носитель замера — §12 дока зоны.
- `configs/langpacks/en/speech-cue.txt`**заблокирован, и цепочка из трёх звеньев названа**:
файл читается ВНУТРИ `lang.Load` (`internal/lang/langpack.go:305`, список `optional`), сам `Load`
вызывается только когда существует каталог ПАРЫ (`internal/pipeline/runner.go:436`), а каталог пары
нельзя создать, не подложив либо одиннадцать таблиц китайской морфологии, либо пиньинь (замер:
5 написаний манифеста, живой `tmctl translate`, `EXIT=1`). ⇒ ряд бэклога 347, и это ДРУГОЙ механизм,
чем «любой файл в `langpacks/en-ru/`»: там файл ломает, здесь отсутствие каталога делает недостижимым.
**Что я знаю и не сказала бы, если бы не спросили.**
1. **Рамочное правило промта взвешено по ДОМИНИРУЮЩЕМУ случаю, и редкий промах законен:** непарная «“» в
начале абзаца неотличима от многоабзацной реплики сцены настоящего, если чанк обрезан до закрывающей.
Правило берёт 2370 абзацев из 2532 и на остатке ошибётся.
2. **Правило о разорванных стихах — ОБХОД реального дефекта движка, и Я НАЗВАЛА ЭТОТ ДЕФЕКТ НЕВЕРНО ДВА
РАЗА, оба раза со словом «проверено».** Сперва: «движок отдаёт перенос на каждый уровень вложенности
`<blockquote>`» — неверно, `splitParagraphs` (`internal/chunk/chunker.go:470-478`) отбрасывает пустые
абзацы, а `blockTags` держит `blockquote` намеренно (без него глава схлопывается в один абзац). Затем:
«`<p>` внутри `<blockquote>` — разметка издателя для СТРОКИ СТИХА» — тоже неверно: пере-снято МОИМ
прибором прямо по EPUB (126 документов), **`<p>` внутри `<blockquote>` = 0**.
**Что в книге есть, тем же прибором:** цепочек `blockquote` **88**, пустых 0, **87 из 88 несут ровно
ОДНУ строку**, медиана длины **32 знака**, максимальная вложенность 10 (типографский отступ). Шесть
подряд: «And so ended the dark year of» · «Empire 676, wherein the Fivefold» · «Throne of Elidaen was
beset by» … ⇒ прозаический эпиграф, разбитый конвертером на строки, каждая своей цепочкой; движок отдаёт
каждую отдельным абзацем. **Вывод правила верен, ложным было объяснение.** Признак пере-формулирован без
опоры на знаки конца предложения — они у пар разные, и такой признак ветвился бы по ЯЗЫКУ; плюс оговорка
советчика: он ловил и цепочку оборванных реплик, которых в прозе полно.
⚠ Число «726 абзацев без знака конца предложения» о стихе не говорит: у него внутри заголовки, обрывки
оглавления и реплики, оборванные тире. Разложение советчика (общий счёт 573) — ДРУГАЯ популяция, и
вычитать одно из другого нельзя.
**Вторая форма стиха моим правилом НЕ накрыта:** оркестратор №23 замерил, что курсив теряется в
ингесте по построению, а среди потерянного **154 строки гимнов курсивными абзацами по строке**. В промте
это не лечится — забрано в следующий пак.
⚠ Совет «взять `restore_paragraphs` из полигона» ОТОЗВАН его автором: тот скрипт чинил дефект
ПОЛИГОННОГО экстрактора, а не движка.
**НО СЛЕДСТВИЕ ТОГО ПОЛИГОННОГО ДЕФЕКТА ОСТАЁТСЯ И БЬЁТ ПО ДВУМ МОИМ ЧИСЛАМ.** Их диспозиция «починка
экстрактора абзацев — до любого нового английского замера, весь материал искажён нами»
(`eval/dovodka/KONSILIUM-22-08.md:141`) не исполнена, арм `RA` не куплен ⇒ английские СУДЕЙСКИЕ числа
полигона сняты на тексте с потерянными границами абзацев. Затронуты ровно два, на которые я ссылаюсь:
вес ролевого промта (1.50/1.13) и «редактор на английском покупает» (1.22 против 2.78). Оба помечены в
доке зоны. Плюс их оговорка о приборе: разрешение на английской паре 2.15 места против 1.63 на китайской.
⭐ Уточнение от самого полигона, возвращающее основание: дефект подачи обойдён ОСОЗНАННО — вход у всех
273 английских клеток одинаково плоский (`eval/dovodka/rol.py:110-127`) ⇒ **контрасты промтов между собой
ЧИСТЫ**, порядок `RB > RC > RN` держится; не держится абсолютный уровень и всё про абзацный строй.
НЕ затронуты: подсчёты по тексту книги (счёт, а не судейство), абляция рамки (куплена на ZH),
постинструкция A1 (zh и grok), мои собственные замеры движком.
2б. ⛔ **РАМКА ДВУХ БРАКОВ МОЖЕТ РАБОТАТЬ НЕ ТЕМ, ЧТО Я ПЕРЕНЕСЛА.** `eval/dovodka/SESSION2-LOG.md:1392`:
«`RB` думает 23 301 токен и пишет 94100% текста в уме… Качество здесь пропорционально не удачности
формулировки, а количеству черновиков, которые модель успела написать про себя». Цена клетки вчетверо выше
боевой связки. ⇒ я переношу ФОРМУЛИРОВКУ, а работал, возможно, БЮДЖЕТ РАЗМЫШЛЕНИЯ. Названо в доке зоны,
чтобы первый замер на английском не приписал промту то, что сделал тариф.
3. **Капитель-открывашка секции не покрыта ни одним правилом:** 40 чанков книги начинаются словами, где
первые 34 слова набраны капителью, и ни один гейт движка результат не судит. Нашёл адверсариальный
проход; правила я не внесла — у него нет замера, а пакет и так на пределе плотности инструкций.
4. **`judge-selector.md` несёт контракт, которого в движке нет:** «выведи ТОЛЬКО номер» назначено раньше
парсера фазы 2. Названо в доке зоны как заглушка.
5. **Текст рамки двух браков — ВТОРАЯ редакция `_BRAK`, и это ДОКАЗАНО КОДОМ** (полигонная сессия, сверено
мной): два присваивания одному имени (`rol.py:192` и `:214`) при единственном использовании на `:226`
в Python побеждает последнее; коммит `3075566` добавил оба сразу, значит первая была мёртвым кодом с
рождения. Артефактами недоказуемо — провод в клетках не хранится.
6. **Вес промта (1.3 порога против 1.6 у дорогой стадии) измерен на жильце `gemini-3.1-flash-lite`** при
вендор-дефолте, не на боевом редакторе. Переносится НАПРАВЛЕНИЕ, не величина.
7. **Абляция редакций рамки: контроль шума КРАСНЫЙ**, порядок `RB > RC > RN` при n=3 не разрешим.
Уцелевает «RB не хуже продакшена»; RB выбрана потому, что это формулировка ВЛАДЕЛЬЦА, а не потому, что
доказана лучшей.
8. **Я ЧЕТЫРЕ РАЗА СДЕЛАЛА РОВНО ТО, ЧТО БАЙТОВЫЙ ГЕЙТ НАЗЫВАЕТ СВОИМ ДЕФЕКТОМ** — пере-записала значение
под СУЩЕСТВУЮЩИМ ключом реестра (`TM_UPDATE_PROMPT_LABELS=1`), тогда как его собственный доккоммент
гласит: «a NEW key is a deliberate bump, a CHANGED value under an existing key is the defect this gate
exists for». Почему это не хак и почему всё равно должно быть названо: бампнуть лейбл я НЕ МОГУ —
`prompt_version` живёт в конфиге ОДНОЙ строкой на стадию, а пар в реестре две, и бамп пере-именовал бы
ключ zh-ru, у которого байты не двигались (это и есть находка §5). Сегодня безвредно: en-ru-прогонов не
существует, сравнивать под пере-использованным лейблом нечего. **Условие, при котором вывод перестанет
держаться: первая же покупка на английской книге** — после неё пере-запись значения станет тем самым
дефектом, от которого гейт построен.
9. **Мой новый пин утверждает ОДНУ вставку, и это сужение, а не закон.** Банкнотный канал аддитивен в обеих
парах дерева, но пара, чей канал потребует ДВУХ вставок, покраснеет законно. Тогда пин расширяется
явно — а не глушится: `singleInsertion` сравнивает БАЙТЫ, и при расширении надо помнить, что печатаемая
вставка может начаться посреди руны (на предикат это не влияет, на текст сообщения — может).
10. **Два FEWSHOT-примера редактора на БОЕВОМ пути модель не видит:** `c1` и `c2` держат `few_shot: false`
(D38.5, reasoning-редактор), у армов ключа нет ⇒ примеры едут только на армах. В таблице §1 дока зоны
они названы частью пакета — теперь с этой оговоркой. Это ратифицированное поведение движка, не мой
дефект, но читать таблицу без оговорки означало считать, что пакет везёт на два примера больше.
11. **Замер «25 примеров ×0 в книге» считает ПОДСТРОКИ.** Токен, который встречается как часть длинного
слова, был бы посчитан; ноль поэтому — утверждение сильное, а не слабое. Контроль прибора на том же
тексте: `François` 517, прочитано 1 626 475 рун. ⚠ И семь примеров из двадцати пяти нашёл советчик, а не
я: мой список был на семь короче, то есть «посчитала примеры» и «посчитала ВСЕ примеры» — разные
утверждения, и первое я предъявляла как второе.
##### 7. ЗАВЕРШЁННОСТЬ
**Круги сошлись, и вот чем это предъявлено.** Консилиум: шесть кругов, последний не дал новых находок по
содержанию промтов — он дал ДВА исправления моих же правил (обоснование «в мире книги метрической системы
нет» и признак стихотворного блока, ловивший оборванные реплики) и досчитал примеры законодателей с 18 до
25; всё внесено, после чего советчик закрыл консилиум. Адверсариальный веер: 57 находок, **57 из 57
диспозиционированы** — 20 крупных в §4, 37 мелких поимённо в §4б, сводка «находка → что сделано → чем
предъявлено» в §4в. Прежние круги закрыты таблицами §4в и §5.
**Числа сняты ПОСЛЕ последней правки кода и данных** (`battery-final9`); всё, что снято раньше, в акт не
идёт и помечено как след замера. После этой батареи тронуты только два ДОКУМЕНТА (`docs/PROGRESS.md` и
`backend/docs/EN_RU_PAIR_BASIS.md`), и их батарее-нейтральность — замер, а не слово: `grep -rn
'PROGRESS.md\|EN_RU_PAIR_BASIS\|"docs"' --include='*.go' backend/` даёт ОДНУ строку, и та — текст
сообщения об ошибке, а не чтение файла.
**Гейт зоны зелёный** списком, а не хвостом (24 из 24, `comm` пуст в ОБЕ стороны, `0 issues.`, скипы
названы поимённо). ⚠ Предыдущий прогон был КРАСНЫМ на чужом пакете — назван в §3 сам, с разбором и без
слова «флейк». **Мутации:** каталог 538, в гейте 327, моих 12 — **12 из 12 RED, 0 неожиданных, 0
неизмеренных, 0 протухших якорей из 538**; полный каталог своим корнем я НЕ гоняла и не склеиваю эти два
утверждения (§3).
**Работа завершена, править не планирую.** Открытым остаётся названное в §6: дымовая покупка (прогон
отложен владельцем), пере-формулировка ряда 498, пофайльная диспозиция двух `langpacks/en/` (§6 п.4) и
тринадцать находок §5 — они в зоне оркестратора. Из них две новые: `prompt_version` не может метить две
пары независимо, и курсив, теряемый ингестом по построению, вместе с 154 строками гимнов.
#### ЗАПИСКА-ПЛАН пака «АНГЛИЙСКАЯ ПАРА en→ru» (17.09, сессия `textmachine-main-c5`). До первой строки кода, по §7 промта
**Деньги на момент записки: $0**, платных вызовов моделей ноль. Весь инвентарь снят путём `tmctl manifest` /
`tmctl translate` на $0-конфиге, юнит-пробами на КОПИИ дерева (`~/tm-c5-stand/backend-probe`) и чтением EPUB
питоном. Ключей провайдеров в окружении нет ни одного (проверено по именам семи переменных `*_API_KEY`,
значения не читались), `.env` рядом с пробным `book.yaml` нет, CWD проб — не `backend/`.
##### 0. ВХОДНАЯ СТРОКА БАТАРЕИ — ЧИСЛОМ, и она КРАСНАЯ
`cd backend && make battery` на полученном дереве (чистый `871e0af`, `git status --porcelain` = **0 путей**):
**`MAKE_EXIT=2`**. Цепочка `build vet fmt lint` дошла зелёной, упала цель `test`:
```
--- FAIL: TestEvidenceWindowsDoesNotGrowQUADRATICALLYWithTheBook (0.76s)
evidence_test.go:77: source ×4 (occurrences 2000 → 8000): 42.5ms → 700.2ms, ratio ×16.5
FAIL textmachine/backend/internal/terminology 0.850s
```
Полнота прогона проверена СПИСКОМ, а не хвостом: `go list ./...` = **24**, вердиктов в логе = **24**,
`comm -23` и `comm -13` пусты **ОБА**. **Скипы не измерены**: харвест-пасс `-v` стоит в рецепте `battery`
ПОСЛЕ цели `test` и не исполнялся вовсе — «0 скипов» здесь значило бы «скипы не показаны».
**Это НЕ квадратичность, а ложное срабатывание пина под ПАРАЛЛЕЛЬНОЙ нагрузкой.** Пере-снято на копии
дерева одним прибором с обеих сторон:
| прибор | ratio | вердикт |
|---|---|---|
| `go test ./internal/terminology/ -run …DoesNotGrowQUADRATICALLY… -count=1 -v`, три отдельных прогона | 3.4 · 4.3 · 3.0 | PASS ×3 |
| то же с `-race`, три отдельных прогона | 3.5 · 4.0 · 3.2 | PASS ×3 |
| `go test ./... -race -count=1 -timeout=20m` на той же копии | — | `GOTEST_EXIT=0`, **24 пакета, 0 FAIL**, `terminology ok 1.228s` |
**посылка собственного доккоммента теста опровергнута замером.** Он утверждает (`internal/terminology/evidence_test.go:55-58`):
«IT ASSERTS A RATIO, NOT A DURATION. A wall-clock threshold on a shared machine is a flake; the shape of the
curve is the property». Отношение защищает от РОВНОЙ нагрузки и слепо к её ИЗМЕНЕНИЮ между двумя половинами:
обе меряются ПОСЛЕДОВАТЕЛЬНО, а `go test ./...` гоняет до 8 пакетов сразу. В упавшем прогоне малая половина
шла 42.5 мс против изолированных 22 мс — то есть уже вдвое медленнее, — а большая словила ещё худшее окно.
**Красное на входе — не мой предмет** (§2 промта); передано пингом оркестратору №23, он признал это дефектом
своей приёмки (принял пак с `MAKE_EXIT=0` на ТОМ ЖЕ коммите) и забрал ряд и эрратy себе. Форма лечения,
которую он взял дословно: мерить обе половины ВПЕРЕМЕЖКУ (A-B-A-B, медиана) либо нормировать на опорный
замер той же секунды.
##### 1. Инвентарь ИСПОЛНЕНИЕМ: где встаёт английская книга. Восемь стен, каждая с командой
Книга — `books/Kristoff_Jay_-_Empire_of_the_Vampire_3_-_Empire_of_the_Dawn.epub`. Прогоны — из
`~/tm-c5-stand/enprobe/` (вне репозитория), `book.yaml` мой, пайплайн — копия боевого `pipeline-c1.yaml`.
| № | стена | адрес | исход |
|---|---|---|---|
| 1 | `ceilings` не заданы | `internal/config/book.go` | `EXIT=10`, «a ledger with no ceiling is forbidden» — моя ошибка конфига, не свойство пары |
| 2 | нет промтов пары | `internal/config/pipeline.go:545` | `EXIT=10`, **ЧЕТЫРЕ** пути названы разом: `en-ru/editor.md` · `en-ru/terminologist.md` · `en-ru/classifier.md` + `prompt_override` стадии draft |
| 3 | формат промта | загрузчик шаблонов | `EXIT=1`, «lacks the "---USER---" separator between system and user parts» |
| 4 | **`mining.contrast_path`** | `internal/config/pipeline.go:590` и `:1197` | `EXIT=10`, требует частотный корпус ИСХОДНОГО языка; **в §4 промта этой стены нет вовсе, а стоит она РАНЬШЕ гейта терминолога** |
| 5 | `classify_types` без гейта | `internal/config/pipeline.go` | `EXIT=10`, «classify_types is on but terminology.enabled is false» — **гасится ОТДЕЛЬНО**, в §4.3 этого шага нет |
| 6 | гейт терминолога без пака | `internal/pipeline/runner.go:364` | `EXIT=10`, «this book cannot mine a bank: it needs a langpack … with a catalog directory for the pair "en-ru"» |
| 7 | langpack: каталог пары ЕСТЬ, файлов нет | `internal/lang/langpack.go:247` | `EXIT=1`, `open …/langpacks/en/surnames-single.txt: no such file` |
| 8 | langpack: манифест объявляет только транслитерацию | там же | `EXIT=1`, `open …/langpacks/en-ru/palladius.txt: no such file` — то есть ПИНЬИНЬ |
⭐ **А ВОТ ЧТО УЖЕ РАБОТАЕТ, и это предъявлено, а не предположено:**
- `tmctl manifest --config book.yaml`**`EXIT=0`**, `chapters=71 units=351 chunks=356`,
`chapter structure: declared`, `expected cost: $6.616773` на 1 601 395 знаков исходника,
`smallest workable ceiling: $0.135318`. **Ряд 315 пере-снят моим прибором, а не принят со слов.**
**ИСПР. при сдаче: эти числа описывают форму книги ДО пар-слоя и сняты на ПРОБНОМ конфиге** — они
остаются в записке как след замера, но числом готовности больше не являются. Пере-снято на живом
`configs/pipeline-c1.yaml` после сдачи пар-слоя: `chapters=71` **`units=379 chunks=385`**,
`expected cost: $8.565366` на 1 601 339 знаков (из них $2.000000 — потолок терминологии, он берётся
раз на книгу), `smallest workable ceiling: $0.136900`, `EXIT=0`. Нашёл мой же адверсариальный веер:
оценка `fertility.other` 0.4203 против фолбэка 0.3852 двигает нарезку, а числа готовности этого не
знали. ⛔ **Два состояния НЕ сопоставимы напрямую** — разные конфиги и разное число знаков исходника;
подаю оба со своим конфигом, а не как «одно перешло в другое».
- **Путь ДАННЫМИ вокруг гейта терминолога (§4.3) работает СКВОЗНЫМ прогоном:**
`gates.terminology.enabled: false` + `gates.terminology.classify_types: false` + `gates.banknote.enabled: false`
`tmctl translate` доходит до `calling model … estimate_usd=0.000000 … stage=draft role=translator` и
встаёт только потому, что локальной Ollama на машине нет (`dial tcp 127.0.0.1:11434: connection refused`).
**Никакого `configs/langpacks/en/` на этом пути не требуется вообще.**
##### 2. ⛔ ГЛАВНАЯ НАХОДКА ИНВЕНТАРЯ: двери, которую §4.2 промта объявила, НЕ СУЩЕСТВУЕТ
§4.2 утверждала: «`en/manifest.txt` с единственной строкой `channel<TAB>source-morphology` снимает пиньинь
целиком, без единой строки Go». Про пиньинь — верно. Про то, что за этой дверью, — нет.
Замер №1, юнит-проба на копии, пять написаний манифеста, **с контрольной строкой** (живой `zh-ru` грузится
из настоящего дерева: `version=langpack-v2-43b3ebed3362`, требуемых `srcFiles` = **11** — значит прибор
спрашивал существующий предмет):
| `configs/langpacks/en/manifest.txt` | исход `lang.Load(root, "en", "ru")` |
|---|---|
| файла нет | `open …/en/surnames-single.txt: no such file` |
| `channel⇥source-morphology` | `open …/en/surnames-single.txt: no such file` |
| `channel⇥transliteration` | `open …/en-ru/palladius.txt: no such file` |
| обе строки | `open …/en/surnames-single.txt: no such file` |
| только комментарий | `manifest declares no channel — omit the file to ship all channels, or list at least one` |
Замер №2 — то же **живым движком**: `tmctl translate` на настоящей книге (стены 7 и 8 таблицы выше).
⇒ **написания манифеста, при котором английский источник грузится, не завезя ЛИБО 11 таблиц китайской формы,
ЛИБО палладиевы файлы, НЕ СУЩЕСТВУЕТ.** Это ряд **347** дословно, и он не «когда-нибудь»: он **на пути
сегодня**, раньше, чем §4.3 предполагала.
И вторая половина, которая решает вопрос «а нельзя ли заполнить 11 таблиц по-английски честно»: **их
единственный потребитель — майнер имён** (`internal/miner/miner_patterns.go:36,73,76,230,236` и
`miner_alias.go:47`; вне `internal/lang/` других не-тестовых чтений нет), а его алфавит кандидатов — только
ханьские иероглифы (`internal/miner/miner_substrate.go:44` `isMinerHan``unicode.Is(unicode.Han, r)`;
`hanRuns` собирает прогоны только из них). ⇒ **на английском источнике эти одиннадцать файлов не читает
НИКТО**, и заполнение их не меняет ни одного байта поведения — это удовлетворение валидатора, а не описание
языка. **Я их не пишу**; оркестратор №23 подписал этот отказ, назвав довод в полную силу.
**Цена отказа, названная прямо и первой строкой, а не в скобках:** английская книга поедет с ВЫКЛЮЧЕННЫМ
терминологом и выключенной банкнотой, то есть **без сквозной консистентности терминов — частичная потеря
цели №1 канона**. Это цена состояния дерева, а не выбор пака.
##### 3. Нарезка глав: популяция движковая, и настоящий предмет ОКАЗАЛСЯ ДРУГИМ
Замер снят с `--json`-манифеста, то есть **прибором самого движка** (71 запись глав, сумма
`price.source_chars` = 1 601 395 = ровно то, что печатает сводка):
| | |
|---|---|
| глав | **71** · `heading` НЕПУСТ у **0** из 71 · `title_raw` непуст у **71** из 71 |
| крупных (≥100 тыс. знаков) | **6**: BOOK TWO 392 312 · BOOK ONE 345 264 · BOOK FIVE 277 493 · BOOK FOUR 260 214 · BOOK THREE 182 030 · BOOK SIX 140 022 |
| крошечных (<200 знаков) | **64**, все вида `Chapter II. To the Dawn` (2339 знаков) |
| средних | **1**: `Chapter VII. Execution`, 2143 знака |
⛔ **И вот чем 64 крошечные главы оказались НА САМОМ ДЕЛЕ — это не «страницы-разделители» (§4.4) и не
«строки заднего листинга» (отчёт 05.09), а РАЗРЕЗАННАЯ НА ФАЙЛЫ СТРАНИЦА «Contents».** Замер по EPUB
напрямую (`zipfile` + `toc.ncx`): navPoint'ов **71**, **ноль** из них с фрагментом `#`, целей-документов
**71** различных. Первые шесть целят в `index_split_007/015/025/029/033/041.html` (страницы-титулы книг),
остальные — в `index_split_059.html` и далее, а `index_split_058.html` (583 руны) начинается словами
«Contents · Title Page · Copyright Notice … Book One. Deathseeker · Chapter I. Parting Gifts …» и обрывается
на 25-й записи. Дальше каждая запись оглавления лежит СВОИМ документом: `059` = «Chapter II. To the Dawn»
(23 руны), `060` = «Chapter III. Of These Wounds» (27 рун), и так до `124` = «Table of Contents …».
**А НАСТОЯЩИЕ ГЛАВЫ В TOC НЕ НАЗВАНЫ ВООБЩЕ.** Проза живёт в документах между титулами книг
(`index_split_008.html` 31 725 рун, `009` 54 433, `010` 37 516 …), и ни у одного из них navPoint'а нет —
поэтому `groupChapters` ветвью `default` приписывает их к ПРЕДЫДУЩЕЙ главе, и BOOK ONE вырастает до 345 264
знаков. Заголовок главы при этом **внутри документа есть**, и его форма — английская:
```html
<p class="calibre_2">III</p>
<p class="calibre_2">SPLINTERING</p>
```
то есть **голая РИМСКАЯ цифра отдельной строкой, под ней название капсом** — и ни одного `<h1>``<h6>` во
всём документе (проверено: `h-заголовки=[]` у всех прочитанных). Собственное оглавление книги называет эту
же главу иначе — «Chapter III. Splintering».
**Ни один слот данных, который есть в движке сегодня, этого не выражает.** `SourceStructure` требует
`marker` литералом (`internal/lang/structure.go:195` «structure needs a marker»), а здесь маркера нет вовсе;
класс цифр в заголовке — `[0-9-` + китайские цифры`]` (`structure.go:75`), римских в нём нет.
**РЕШЕНИЕ: нарезку EPUB в этом паке НЕ чиню, и вот довод.** (1) Промт прямо говорит, что нарезка
эксперимент не блокирует, и это подтверждается: BOOK THREE = 148 782 знака без пробелов ≈ **40 874 токена**
при цели 41 027 — промах **0.37 %**, одна глава движка без единой правки (знаменатель мой:
`source_chars_sparse` из манифеста ÷ 3.64 знака на токен, `experiments/01-token-calibration.md`).
(2) Починка требует НЕ порога в данных, а нового рода грамматики (безмаркерный заголовок + римские цифры) и
разреза ВНУТРИ документа EPUB — это тело ряда **283**, чужой пак. (3) Порог «сколько знаков делает главу
главой», который §4.4 предлагает как данные, **проблему не решает**: он убрал бы 64 крошечные записи и
оставил бы шесть полотен, то есть сделал бы выдачу хуже, а не лучше.
⇒ отдаю ряду 283 замер и форму заголовка; в отчёте это будет секцией, а не умолчанием.
**Граница названа явно (§4.4 требует):** ряд **303** (не-CJK **TXT** режется в одну главу) этим паком НЕ
починен. Пере-снял с контролем на второй живой английской книге: `books/fifty_shades_1_en.txt`, строк
`^[[:space:]]*Chapter ` в файле — **26** (`command grep -cE`), а `tmctl manifest` даёт **chapters=1
units=146 chunks=147** и БЕЗ `en/structure.txt`, и С файлом `marker⇥Chapter` — числа побайтно те же.
⚠ И оговорка о приборе: `chapter structure: none` в обоих прогонах **не доказывает, что файл не прочли**
`structureOf` (`internal/chunk/ingest.go:169-171`) отдаёт `none` при `len(chapters) < 2` независимо от того,
откуда взялась грамматика. Свидетель тут один — счёт глав.
##### 4. Что я строю — по порядку, с тем, чем предъявлю
| # | предмет | почему это ДАННЫЕ, а не код | чем предъявлю |
|---|---|---|---|
| 1 | `backend/prompts/en-ru/` — промт-пакет пары, состав решаю сам | конвенция пути `prompts/<пара>/<роль>.md` | загрузка движком + сквозной прогон до `calling model`; состав с доводом по каждому файлу |
| 2 | `backend/configs/langpacks/en/structure.txt` | грамматика заголовка — факт ИСХОДНОГО языка (`12-go-style-notes.md` §0.1) | замер: что меняется и что НЕ меняется на двух английских книгах |
| 3 | `backend/configs/langpacks/en/speech-cue.txt` | «реплика — это кавычки плюс атрибуция рядом» — факт источника | юнит-замер числа реплик на настоящих чанках книги |
| 4 | `backend/configs/langpacks/en-ru/heading.txt` | целевой рендер заголовка — факт ПАРЫ | загрузка + замер рендера |
| 5 | `backend/configs/langpacks/en-ru/terminology.txt` | ширина окна в РУНАХ — факт плотности источника (1.38 знака/токен у zh против 3.64 у en) | арифметика с командой + загрузка |
| 6 | `backend/configs/pairs/en-ru.yaml` — блок `segmentation` ОЦЕНКОЙ | пар-калибровка | оценка названа оценкой; прогоном не выдана (§4.8) |
| 7 | замер порога эха 0.15 на латинице | — | распределение, снятое ТЕМ ЖЕ кодом, что движок |
| 8 | замер `lintLatinResidue` на русской прозе | — | число срабатываний со знаменателем |
| 9 | замер нормализации ключа банка на латинице | — | число ключей, фырящих на обычных словах |
| 10 | замер реверс-секции банка на латинице (одобрен оркестратором) | — | исполнение; **на результате ничего не строю без его слова** |
| 11 | мутации на КАЖДУЮ новую ветку, пометка `battery`, прогон каталога ЦЕЛИКОМ | — | таблица, выжившие поимённо |
##### 5. Что НЕ делаю — и это исходы, а не умолчания
- **Одиннадцать таблиц морфологии `en/`** — отказ с замером (§2 выше), подписан оркестратором.
- **Ни одной строки Go под ряд 347** — без слова оркестратора (§4.9 промта).
- **Нарезку EPUB / ряд 283** — довод в §3 выше.
- **Ряд 303 (не-CJK TXT)** — вход, не предмет; граница пере-снята с контролем.
- **Не-Han майнер банка (ряд 35)**, **целевую латинописьменную пару (ряд 259)**, **японскую пару**,
**транслитерационный канал под пиньинь** — вне пака.
- **`gates.repair` остаётся выключенным**; включение — отдельное решение с ценой.
- **Русские целевые данные (`configs/langpacks/ru/`) не трогаю** — английская пара наследует их даром.
- **Полный срез и эксперимент двух переводов** — не этот пак (решение владельца).
##### 6. Чего я НЕ смогу предъявить числом, и говорю это до начала, а не в конце
**Качество английских данных и промтов не измеряется в этом заходе.** Размеченного корпуса для en→ru в
репозитории нет вовсе (сообщено оркестратором: из трёх размеченных каталогов — `labels`/`oracle`/`gold`
все три китайские), человеческого эталона книги в дереве нет, покупка эталона — открытый вопрос владельцу.
⇒ батарея зелена при ЛЮБОМ содержании этих файлов, и единственный рубеж здесь — я и фабл-советчик.
Самодельную метрику вместо замера не изобретаю: она выглядела бы замером, не будучи им.
#### ⚠ ПИНГ ОРКЕСТРАТОРА №23 (17.09) — ТРИ ЯКОРЯ `backend/docs/` УЕХАЛИ ИЗ-ЗА МОЕГО ВЫНОСА; ЧИНИТЬ ВАМ, В ВАШУ ЗОНУ Я НЕ ЛЕЗУ
17.09 по заказу владельца я срезал этот журнал с 5178 строк до 634: отчёты десяти ПРИНЯТЫХ паков уехали в