diff --git a/docs/PROGRESS.md b/docs/PROGRESS.md index bb60ff2c..f4bb5dc3 100644 --- a/docs/PROGRESS.md +++ b/docs/PROGRESS.md @@ -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`): вариант РОЛИ резолвится конвенцией +`/<пара>/<роль>-<вариант>.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.5–4.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г. ПРО ЧТО ВЕЕР И КОНСИЛИУМ МОЛЧАЛИ ОБА — поймали ТРЕТЬИ читатели + +⛔ **Механизм дефекта ингеста я назвала неверно ДВА РАЗА, и оба раза со словом «проверено».** Сперва +«перенос на каждый уровень вложенности `
`», потом «`

` внутри `

` — строка стиха». +Пере-снято МОИМ прибором по EPUB (126 документов): **`

` внутри `

` — 0**. Такого механизма +нет. ⭐ Что есть: цепочек `blockquote` **88**, пустых 0, **87 из 88 несут ровно одну строку**, медиана +**32 знака**, и шесть подряд читаются как прозаический эпиграф, разбитый конвертером по строкам. ⇒ вывод +правила верен, объяснение было ложным; признак пере-формулирован без опоры на знаки конца предложения (они +у пар разные — такой признак ветвился бы по ЯЗЫКУ). Поймала полигонная сессия, подтвердил советчик, +пере-снято мной. +⚠ **Вторая форма стиха в этой книге моим правилом НЕ накрывается, и я это знаю:** оркестратор №23 замерил, +что курсив теряется в ингесте ПО ПОСТРОЕНИЮ, а среди потерянного — **154 строки гимнов, набранных +курсивными абзацами по строке** (ещё 32 блока). Носитель не доезжает до чанка ⇒ в промте это не лечится. +Забрано в следующий пак; от меня правок ноль, и молчать об этом было бы удобнее. + +##### 5. НАХОДКИ О ДЕРЕВЕ — переданы оркестратору, каждая с ценой + +| находка | замер | состояние | +|---|---|---| +| Манифест пары: двери для не-Han источника НЕТ | 5 написаний + живой `tmctl translate` | ряд 347, оркестратор | +| Реверс-секция банка РАБОТАЕТ на латинице | 4 поверхности → 4 строки дельты, четыре контроля | оговорка ряда 347 пере-решена | +| `mining.contrast_path` требует китайский корпус у ЛЮБОЙ пары | `EXIT=10`; с ПУСТЫМ контрастом майнер даёт те же нули | ряд, оркестратор | +| Ингест рвёт стихи: вложенные `
` до 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`) читает `//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. **Правило о разорванных стихах — ОБХОД реального дефекта движка, и Я НАЗВАЛА ЭТОТ ДЕФЕКТ НЕВЕРНО ДВА + РАЗА, оба раза со словом «проверено».** Сперва: «движок отдаёт перенос на каждый уровень вложенности + `
`» — неверно, `splitParagraphs` (`internal/chunk/chunker.go:470-478`) отбрасывает пустые + абзацы, а `blockTags` держит `blockquote` намеренно (без него глава схлопывается в один абзац). Затем: + «`

` внутри `

` — разметка издателя для СТРОКИ СТИХА» — тоже неверно: пере-снято МОИМ + прибором прямо по EPUB (126 документов), **`

` внутри `

` = 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 токен и пишет 94–100% текста в уме… Качество здесь пропорционально не удачности + формулировки, а количеству черновиков, которые модель успела написать про себя». Цена клетки вчетверо выше + боевой связки. ⇒ я переношу ФОРМУЛИРОВКУ, а работал, возможно, БЮДЖЕТ РАЗМЫШЛЕНИЯ. Названо в доке зоны, + чтобы первый замер на английском не приписал промту то, что сделал тариф. +3. **Капитель-открывашка секции не покрыта ни одним правилом:** 40 чанков книги начинаются словами, где + первые 3–4 слова набраны капителью, и ни один гейт движка результат не судит. Нашёл адверсариальный + проход; правила я не внесла — у него нет замера, а пакет и так на пределе плотности инструкций. +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` с единственной строкой `channelsource-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` (23–39 знаков) | +| средних | **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 +

III

+

SPLINTERING

+``` + +то есть **голая РИМСКАЯ цифра отдельной строкой, под ней название капсом** — и ни одного `

`–`

` во +всём документе (проверено: `h-заголовки=[]` у всех прочитанных). Собственное оглавление книги называет эту +же главу иначе — «Chapter III. Splintering». + +⇒ **Ни один слот данных, который есть в движке сегодня, этого не выражает.** `SourceStructure` требует +`marker` литералом (`internal/lang/structure.go:195` «structure needs a marker»), а здесь маркера нет вовсе; +класс цифр в заголовке — `[0-90-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: отчёты десяти ПРИНЯТЫХ паков уехали в