textmachine/backend/docs/EN_RU_PAIR_BASIS.md

319 lines
37 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

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

# Пара en→ru: на чём стоит каждое число и решение
Носитель провенанса пар-пакета. Промты его не несут: комментариев в промтах нет по слову владельца
17.09 («не нужны ни в каком виде»), а знание обязано жить в репозитории.
## 1. Что пара везёт
| файл | что в нём |
|---|---|
| `prompts/en-ru/translator.md` | рамка двух браков + пять осей, русская и английская стороны |
| `prompts/en-ru/translator-banknote.md` | тело переводчика + канал ⟦TM-BANK-v1⟧: та же системная часть плюс ОДНА вставка, различие стережёт пин `TestBanknotePromptIsItsTranslatorPromptPlusOneBlock` — правку веди в ОБА файла |
| `prompts/en-ru/editor.md` | шесть осей правки, десять проверок, ДИСКУРС-перевёрстка, два FEWSHOT — ⚠ блок примеров едет только на АРМАХ: `c1`/`c2` держат `few_shot: false` (D38.5, reasoning-редактор), и на боевом пути модель их не видит |
| `prompts/en-ru/terminologist.md` | имена по языку происхождения, топонимы по составу, титулы по смыслу |
| `prompts/en-ru/classifier.md` | класс × род; cue-слова английские, `they` об одном лице → `none` |
| `prompts/en-ru/judge-selector.md` | роль не исполняется фазой 0; ⚠ «выведи только номер» — ЗАГЛУШКА до парсера фазы 2 |
| `prompts/en-ru/repair/latin_residue.md` | ⟦TM-NOCHANGE⟧ — главная ветка; имя чинится только при очевидной форме |
| `prompts/en-ru/repair/broken_word.md` | целевой класс, копия zh: дефект русского выхода от источника не зависит |
| `configs/pairs/en-ru.yaml` | оценка `fertility.other` + коридор |
## 2. Почему промт вообще стоит работы — замер, а не вкус
`docs/experiments/23-editor-tier.md:5536` — разрывы в долях собственного порога, панель `p4`,
16 английских глав этой книги, 16 отдельных слепых читателей:
```
удалить ВЕСЬ ролевой промт (RE↔RQ) 1.50 / 1.13 ≈ 1.3 порога ⚠ см. поправку (б) ниже
удалить дорогую стадию (Z0↔ZD) 1.38 / 0.85 ≈ 1.6 порога
```
Первичный эндпойнт объявлен ДО чисел (`:5530`): 13 глав из 16 в одну сторону, знаковый p=0.0213.
⇒ ролевой промт по весу сопоставим с целой платной стадией.
## 3. Рамка двух браков — решения ВЛАДЕЛЬЦА, не наши
Формулировка взята из `eval/dovodka/rol.py` (второе определение `_BRAK`, после приёмки), её основания:
- 16.08, дословно: «штрафовать за вольность нельзя, живой язык — приоритет; штрафовать можно только
за перевирания смысла» (`eval/dovodka/prompts/onepass-core.md:13`). Там же: «Ни один боевой промт
такого разрешения не давал — оба только ЗАПРЕЩАЛИ».
- 20.08, дословно: «присутствие одного языка в другом… полное отсутствие художественности и родного
звучания… машинный перевод грубо говоря… перевод это отчасти какое-то но творчество, без
перевирания смысла нужно написать текст, чтоб он звучал естественно» (`eval/dovodka/rol.py:187-190`).
- Слепое чтение 17.08 забраковало БОЕВОЙ перевод по РЕГИСТРУ: ярость передана словом «шествовала»,
мат смягчён, вежливое «Пойдёмте» в реплике, которую выплёвывают (`eval/dovodka/prompts/onepass-core.md:15-19`).
- Абляция редакций: `RB > Z0 > RC > RN` (`eval/dovodka/SESSION2-LOG.md` §15.21), RN дороже всех по
размышлению (28 809 против 23 301, §15.19). ⚠ **Контроль шума КРАСНЫЙ** — порядок при n=3 не
разрешим; уцелевает только «RB не хуже продакшена».
В боевых `prompts/zh-ru/` этих решений НЕТ. Внесение туда — деньги (см. §6), решение оркестратора.
⛔ **И ЧЕГО ЭТА РАМКА МОЖЕТ НЕ ДЕЛАТЬ — назвать обязательно, иначе первый же замер на английском
припишет промту то, что сделал ТАРИФ.** Полигон записал механизм победы `RB` прямо
(`eval/dovodka/SESSION2-LOG.md:1392`, сверено мной): «`RB` думает 23 301 токен и пишет 94100% текста
в уме — то есть покупает качество той же дорогой монетой. Дешёвый `RC` (11 268) написал хуже. **Качество
здесь пропорционально не удачности формулировки, а количеству черновиков, которые модель успела
написать про себя.**» Цена клетки: `RB` $0.1050 против ~$0.025 у боевой связки — вчетверо (`:1299-1300`).
**переносится ФОРМУЛИРОВКА, а работал, возможно, БЮДЖЕТ РАЗМЫШЛЕНИЯ.** На en→ru при другом усилии та
же рамка может не дать ничего. Наверняка переносится только одно: это решение ВЛАДЕЛЬЦА.
⚠ Поправка к красному контролю шума, прочитанному мной слабее, чем он есть: читатель НЕ спутал
близнецов — он написал, что `ZF` «маскируется под `Z0`», родство опознал и всё равно развёл арма на 2-е
и 5-е место ⇒ это разброс АРМА, а не шум читателя.
**ДВЕ ПОПРАВКИ, КОТОРЫЕ ПРИШЛИ ПОЗЖЕ И ОТМЕНЯЮТ ДВА МОИХ УТВЕРЖДЕНИЯ.**
**(а) Механизм дефекта ингеста я назвала НЕВЕРНО ДВА РАЗА, и оба раза со словом «проверено».** Сперва:
«движок отдаёт перенос на каждый уровень вложенности `<blockquote>`» — избыток пустых строк БЕЗВРЕДЕН,
`splitParagraphs` (`internal/chunk/chunker.go:470-478`) их отбрасывает, а `blockTags` держит `blockquote`
НАМЕРЕННО (без него «a whole chapter collapses into one paragraph»). Затем: «`<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» … ⇒ это **прозаический эпиграф, разбитый конвертером на строки по ~32 знака**, каждая
своей цепочкой; движок отдаёт каждую отдельным абзацем. Правило промта поэтому ВЕРНО по выводу и
пере-формулировано по признаку: «несколько коротких абзацев подряд, каждый продолжает предыдущий» — без
опоры на знаки конца предложения (они у пар разные, и такой признак ветвился бы по языку).
⚠ Число «726 абзацев без знака конца предложения» о стихе НЕ говорит: разложение показало заголовки,
обрывки оглавления и реплики, оборванные тире. Ряд 499 пере-формулирует оркестратор.
**(б) `restore_paragraphs` мне НЕ подходит, и совет взять его отозван его же автором.** Он чинил дефект
ПОЛИГОННОГО скрипта (`pair_en.raw_text` сносил теги регексом), а не движка.
**НО СЛЕДСТВИЕ ТОГО ПОЛИГОННОГО ДЕФЕКТА ОСТАЁТСЯ, И ОНО БЬЁТ ПО ЧИСЛАМ ВЫШЕ.** Их собственная
диспозиция «починка экстрактора абзацев — до любого нового английского замера, весь материал искажён нами»
(`eval/dovodka/KONSILIUM-22-08.md:141`) НЕ исполнена, арм `RA` НЕ куплен. ⇒ **английские СУДЕЙСКИЕ числа
полигона сняты на тексте с потерянными границами абзацев**, и это касается ровно двух чисел, на которые я
ссылаюсь: вес ролевого промта (§2) и «редактор на английском покупает» (1.22 против 2.78, §1 таблицы).
Оба помечены в тексте. ⚠ Плюс их же оговорка о приборе: разрешение рангового прибора на английской паре
**2.15 места против 1.63 на китайской** — на en-стороне «неразличимо» наступает раньше.
**УТОЧНЕНИЕ ОТ САМОГО ПОЛИГОНА, и оно возвращает основание:** дефект подачи был обойдён ОСОЗНАННО
вход у ВСЕХ армов одинаково плоский (`eval/dovodka/rol.py:110-127`: «`RN / ZP` — эффект ПРОМТА, вход у обоих
ОДИНАКОВЫЙ, плоский; `RA / RN` — эффект ПОДАЧИ»), 273 английские клетки, у восстановленного арма `RA` — 0.
**контрасты промтов между собой ЧИСТЫ**, и порядок `RB > RC > RN` держится. Не держится АБСОЛЮТНЫЙ уровень
качества и **всё, что про абзацный строй и оформление диалога**: модель видела сплошной блок вместо 11 447
абзацев. ⚠ Мои правила об абзацах и диалоге на их английских наблюдениях НЕ стоят — они стоят на
`docs/research/12-failure-modes-ru-target.md` §10 (норма Розенталя) и на МОИХ замерах прибором движка
(2370 из 2532 абзацев, 11 203 абзаца по всем главам).
**И факт, который надо записать раньше, чем он понадобится:** если бэкенд починит ингест, английские числа
полигона и новые станут НЕСОПОСТАВИМЫ (не «неверны», а сняты на разном тексте). Причина, по которой полигон
не починил свой экстрактор, — цена: uid единицы = `sha1(source.strip())`, правка пробелов переименовывает
все единицы и **289 оплаченных клеток на $2.64 теряют адресата**.
⇒ ЧТО ЭТИМ НЕ ЗАТРОНУТО: подсчёты по тексту книги (`feet` ×161, `François` ×517 и прочие) — это счёт, а не
судейство; абляция рамки куплена на ZH (`--buy zh RC RB`), не на английской панели; постинструкция A1
мерена на zh и grok; мои собственные замеры движком (2370 из 2532 абзацев и т. д.).
## 4. Правила русской стороны — носители
Все из `docs/research/12-failure-modes-ru-target.md`: ты/вы как событие §2 · вид §3 · рема в конец §4 ·
деепричастие с общим субъектом §5 · несобственно-прямая речь без бэкшифта §6 · диалект компенсацией
§7 · брань §8 · междометия §9 · тире-вёрстка диалога §10. Блок-лист транслит-междометий уже лежит в
данных: `internal/lang/data/target-ru.txt`, ключ `translit_interjection`.
⚠ Правило «плотность жестов» у ПЕРЕВОДЧИКА снято: за ним не стоит замера, а прореживание требует
сверки с исходником — это работа редактора. У редактора оставлено.
## 5. Английская сторона — числа по этой книге
Подсчёты полигона (`docs/experiments/21-role-topology.md`) и мои по EPUB (вхождения, не строки):
`François` ×517 · `Fabién` ×180 · `château` ×93 · `Aveléne` ×21 · `Niamh` ×15 · `feet` ×161 ·
`miles` ×25 · `inch` ×16 · `fathom` ×4 · `fucking` ×136.
**`stone` ×228 — и ни одного раза МЕРОЙ ВЕСА.** Единственное вхождение с числительным — «five stone
bowls», то есть прилагательное. ⇒ правило «отличай stone-меру от stone-камня» снято из переводчика и
редактора: оно требовало различения там, где различать нечего, и тем самым ставило под сомнение 228
законных «камней». Это частный случай ратифицированного правила владельца (17.09): данные пары обязаны
так же хорошо отрабатывать ТАМ, ГДЕ ЯВЛЕНИЯ НЕТ, — правило либо про КЛАСС без опоры на конкретную меру,
либо уходит. Рамочный рассказ: в крупнейшей главе движка 2370 абзацев из 2532
открываются «“», закрывающая «”» стоит у 183 — непарная кавычка есть КОНВЕНЦИЯ, а не ошибка набора.
Примеры в промтах ролей, чей ответ становится законом банка (терминолог, классификатор, банкнота),
взяты ВНЕ книги. Замер по САМИМ ПРИМЕРАМ, а не по именам вообще: двадцать пять терминов-примеров
(`Ashlyn Vale`, `the Ashen Reach`, `the Long Dark`, `the Quiet One`, `Michel du Bois`, `ORourke`,
`Corwin`, `Highmarch`, `Ravenshire`, `kilnstone`, `wyrmling`, `drakeling`, `Marchwarden`, `Marie-Claire`,
`Sévrine`, `Thibault`, `Oisín`, `the Elder`, `Gaspard`, `Lord Marshal`, `Brother Confessor`,
`the Ninth Canticle`, `Saint-Aubin`, `Ashlyn`, `Sable`) — в тексте книги **0 вхождений каждый**; прибор
прочёл 1 626 475 рун, контроль на том же тексте: `François` **517**. Последние семь нашёл советчик — мой
список был на семь короче, и это разница между «посчитала примеры» и «посчитала ВСЕ примеры». ⚠ Отдельные СЛОВА из примеров в книге, разумеется, есть (`Vale` 45,
`Reach` 23, `Dark` 29) — законом банка становится строка-термин целиком, и спрашивать надо о ней.
## 6. Цены, которые надо знать прежде, чем править
- **Снятие комментариев из промта — $0 ТОЛЬКО ПРИ УСЛОВИИ, и условие стоит одного переноса строки.**
`stripPromptComments` (`internal/pipeline/render.go:104-120`) снимает РОВНО `<!--…-->` и оставляет
окружающие пробелы; SHA берётся по всей очищенной форме ДО разбора и до `TrimSpace`. Замер функцией
движка на `classifier.md`, три операции над одним файлом: снятие ТОЛЬКО тега — `885766fd1e37`
(хеш не двигается); тег вместе с ОДНИМ хвостовым переносом — `82759ef35326`; тег вместе с ДВУМЯ —
`f7bc660330a3`. ⚠ Первая редакция этого абзаца печатала `f7bc660330a3` под словами «вместе с хвостовым
переносом», то есть приписывала число не той операции; пере-снято.
⚠ Хеш промта чувствителен к пробелам, которых модель НЕ ВИДИТ (`System` проходит `TrimSpace`).
НО ЦЕНА ЭТОГО НЕ ВЕЗДЕ ОДНА, и первая редакция этого раздела сказала шире, чем держится.
Потребителей файлового `tpl.SHA256` ровно два: `internal/pipeline/snapshot.go:495` (промты СТАДИЙ) и
`:169` (классы РЕМОНТА). Банк-роли туда НЕ входят — они опознаются ОТРЕНДЕРЕННЫМ `tpl.System`
(`internal/pipeline/bankbasis.go:209-215`), то есть уже `TrimSpace`-нутым и к пробелам нечувствительным. ⇒ для трёх
файлов, где комментарии были (`classifier`, `terminologist`, `editor-mono`), неаккуратная уборка
сдвинула бы хеш, но денег бы НЕ стоила; денежной она была бы у стадийных промтов и ремонта, а в них
комментариев не было. Ведущие пустые строки в трёх файлах оставлены как гигиена, а не как экономия.
- **Правка ТЕКСТА банк-роли — деньги.** `internal/pipeline/bankbasis.go:183-187` хеширует
ОТРЕНДЕРЕННЫЙ системный текст терминолога И классификатора в личность продюсера: решённые термины
перестают отдаваться из базиса и пере-спрашиваются из ПОЖИЗНЕННОГО бюджета роли. На английской
книге сегодня $0 — банка нет.
- **Любой файл в `configs/langpacks/en-ru/` делает незапускаемой английскую книгу, ОБЪЯВИВШУЮ
`langpack_root`** — и вот условие, при котором вывод перестаёт держаться: книга без этого ключа
выходит раньше (`internal/pipeline/runner.go:432`, `if r.Book.LangpackRoot == "" { return nil }`) и
каталога не видит вовсе. Дальше загрузчик включается по существованию каталога ПАРЫ
(`runner.go:436`) и затем требует у источника `en` либо одиннадцать таблиц КИТАЙСКОЙ морфологии, либо
пиньинь. Замер живым движком: с
созданным `langpacks/en-ru/` (один `heading.txt`) `tmctl translate` падает
`open …/langpacks/en/surnames-single.txt: no such file`, EXIT=1. ⇒ `heading.txt` («Глава {n}») и
`terminology.txt` (ширины KWIC) завести НЕЛЬЗЯ до строки бэклога 347.
## 7. Чего пара НЕ может предъявить
**Качество этих данных не измерено и в этом заходе измерено не будет.** Размеченного корпуса для
en→ru в репозитории нет, человеческого эталона книги в дереве нет. Батарея зелена при любом их
содержании. Единственный рубеж — консилиум: сессия плюс советчик Fable 5, шесть кругов.
⚠ И у этого рубежа названа своя граница: обе стороны читают один текст одними приборами, поэтому дефект,
невидимый обоим, консилиум не ловит — в этом паке его дважды поймали ТРЕТЬИ читатели (§10).
## 8. Провенанс, переехавший из промтов
Из `prompts/zh-ru/` комментарии сняты по слову владельца. ⚠ **Здесь — то, что несло ВЫВОД, а не весь их
текст:** перечни нот, цифры и примеры из снятых комментариев сюда не переносились (замер веером: из
19 опрошенных носителей до этого раздела доехали 6). Полный прежний текст берётся одной командой —
`git show HEAD:backend/prompts/zh-ru/<файл>`, и это адрес, а не обещание.
- `terminologist.md`: третье поле ответа — уверенность 0100, **НЕ арбитр**, только порядок ручного
ревью; ни весов, ни порогов, ни сравнения между моделями (`D39.102`; разбор поля — `internal/terminology/terminology.go:710-738`).
- `classifier.md`: третье поле — род; производителя у него не было вовсе (терминолог его не
возвращает, майнер брал из сида, на несидированной книге ось мертва), и этот проход читает те же
контексты по тем же кандидатам ⇒ род стоит ноль новых вызовов. Значение вне словаря
`male|female|neuter|none` движок считает и ОТБРАСЫВАЕТ, класс при этом сохраняется. `hidden` в
словарь не входит НАМЕРЕННО: это решение о спойлерной политике книги, а не наблюдение по
контекстам, и остаётся ручным, в сиде (`internal/terminology/classify.go:42`).
- `editor-mono.md`: **СПИТ.** Монолингвальный вариант редактора (D30.1, подтверждающий арм D13.1).
Проверено исполнением: живых ключей, ссылающихся на него, — **0** (все 17 упоминаний в
`books/` и `configs/` суть комментарии). Файл держит пин `TestEditorPromptIsBilingual`
(`internal/pipeline/runner_memory_test.go:320`, утверждение про `{{text}}``:346`): файл обязан
существовать у своей пары и НЕ ссылаться на `{{text}}`. ⚠ Пин пере-написан этим паком на цикл по
парам, `editor-mono` опционален на пару — прежний адрес `:331` после правки указывает в другую строку.
## 9. Оговорки советчика, взятые дословно
- Текст рамки двух браков — ВТОРАЯ редакция `_BRAK`, и это **доказано кодом, а не предположено**
(пере-снято полигонной сессией, сверено мной): в `eval/dovodka/rol.py` два присваивания ОДНОМУ имени —
`:192` и `:214` — при единственном использовании на `:226`; в Python побеждает последнее, значит первая
редакция мертва. Коммит `3075566` («Freeze two ablation variants») добавил ОБА определения сразу ⇒ первая
была мёртвым кодом с рождения, а не устаревшей версией.
⚠ Артефактами это недоказуемо: провод в клетках полигона не хранится. Пере-снято на правильной
популяции — в `books/dovodka` **1345** JSON и 82 txt (прежняя редакция печатала 5161, это сумма по
ЧЕТЫРЁМ корпусам `books/`, то есть контроль был снят не с того предмета). Ключей `prompt`, `system`,
`messages`**0 файлов**; фраза рамки «БРАКУЮТСЯ ДВА ИСХОДА» — **0**. Контроль прибора на той же
выдаче: ключ `uid` найден в **1235** файлах ⇒ читались существующие клетки. Доказательство редакции
`_BRAK` поэтому механическое, по коду.
- `judge-selector.md`: «выведи ТОЛЬКО номер» — **заглушка до парсера фазы 2**. Парсера ответа судьи в
движке нет, роль отказывается фазой 0; когда формат определит движок, промт подгоняется под него.
- Вес промта (§2) измерен на жильце `gemini-3.1-flash-lite` при вендор-дефолте (`eval/dovodka/rol.py:630`), не на
боевом редакторе. Переносится НАПРАВЛЕНИЕ, не величина.
## 10. Как собран пакет
Шесть кругов консилиума сессии и советчика Fable 5 (заказ владельца 17.09: «пока вы оба не окните»).
Круг 1 — инвентарь механизмов английского. Круг 2 — 19 механизмов, вердикты по каждому правилу,
7 дефектов китайского промтинга. Круг 3 — язык инструкций (решение владельца: русский), три
китайских комментария, разбор пере-писанного пакета. Круг 4 — шесть правок переводчику, три
редактору, одна классификатору. Круг 5 — одна висящая ссылка и пере-формулировка признака
стихотворного блока после того, как полигон отозвал свой же совет. Круг 6 — пакет целиком под
ратифицированным правилом владельца «данные обязаны так же хорошо отрабатывать там, где явления нет»:
подтверждены чистыми семь правил, найдены НЕ чистыми два (обоснование «в мире книги метрической системы
нет» — факт этой книги; признак стихотворного блока ловил оборванные реплики) и досчитаны примеры
законодателей с 18 до 25. Восемь ОК с обеих сторон.
**И то, чего консилиум НЕ даёт:** обе стороны читают один и тот же текст одними и теми же приборами.
Дефект, невидимый обоим, консилиум не ловит — в этом паке его дважды ловил ТРЕТИЙ читатель (оркестратор
№23: утечка конкретной книги в пар-слой; полигонная сессия: отозванный механизм ингеста).
## 11. Три заказанных замера — результаты (§4.5, §4.6, §4.7 промта пака)
Все три сняты кодом САМОГО движка на корпусе из 75 русских переводов ЭТОЙ книги
(`books/role-topology/en2-*.json`, 15 исходных чанков × 5 армов), контроли напечатаны рядом.
**§4.5 ПОРОГ ЭХА — НЕ ДВИГАТЬ.** Функция `sourceScriptShare` с `lang.LangScripts("en")`, порог
`cjkEchoThreshold = 0.15`:
| | |
|---|---|
| доля латиницы в русском выходе | min 0.0000 · медиана 0.0000 · max 0.1211 |
| выше порога 0.15 | **0 единиц из 75** |
| по 14 прозаическим чанкам из 15 | максимум **0.0136** (запас к порогу 11×) |
| единственный чанк у порога | 0.1211 — выходные данные издательства, не проза (запас 1.24×) |
| контроль прибора | чистый английский выход = **0.8095**, то есть прибор различает эхо |
| контроль данных | `len(LangScripts("en")) = 1` — детектор не мерит пустоту |
⇒ порог трогать нечем: ложных срабатываний на прозе нет, а пере-снапшот стоил бы движения
`classifierVersion` (подстрока `echo015`). Ряд бэклога **260** этим замером не закрыт: он про
латиницу-тяжёлый русский на ДРУГОЙ паре, и мой корпус его клетку не покрывает.
**§4.6 ДЕТЕКТОР ЛАТИНИЦЫ — порог не трогать, лечение аллоу-листом, и у него найден свой дефект.**
Боевой путь `checks.RunCheapGates` с чекерами цели `ru` (контроли: `TargetActive()=true`,
`TargetScriptNonLatin()=true`, подставная утечка «something» ловится):
- сработало **10 единиц из 75**, и по прозе хиты ровно двух родов: французские вставки, которые
правило пары велит СОХРАНЯТЬ (`oui` ×3, `gens` ×2, `armes` ×2), и собственное слово книги
(`Vampyr`/`VAMPYR`);
- остальные хиты — выходные данные издательства на служебной странице (`macmillan`,
`newslettersignup`, `jaykristoff`, `New`, `York`, `Times`, `Today`, `USA`, `Aurealis`, `Publishing`,
`Group`, `Martin`), то есть не проза.
**И дефект самого детектора, найденный по ходу:** `isLatinLetterOrDigit` (`internal/checks/checkers.go:596`) —
только ASCII, поэтому акцентированное слово дробится на осколки. Замер функцией движка:
`Aveléne` → хит **`Avel`**; `Château Impérial`**ТРИ** хита `Imp`, `rial`, `teau`. ⇒ штатное лечение
аллоу-листом (`book.yaml style_allowlist`) на акцентированных именах НЕ РАБОТАЕТ: в список пришлось бы
вписывать `teau`. Передано оркестратору рядом; на этой паре экспозиция низкая, потому что правило пары
велит имена транслитерировать.
**§4.7 КЛЮЧИ БАНКА НА ЛАТИНИЦЕ — подозрение подтверждено и сужено.** Прогон нормализатором движка
(`text.NormalizeSourceKey`) по 25 поверхностям реально предложенного банка этой книги
(`books/role-topology/bank-en.json`; контроль: 25 из 25 встречаются в книге):
| | |
|---|---|
| ключей со строчным омографом | **3 из 25**: `Dead` 167/143 · `Empire` 11/84 · `Marquis` 155/2 |
| чистых (личные имена) | 22 |
| `collisionProneKey` | false у всех — все ≥4 значащих рун, короткий-ключевой порог не при чём |
| шире по книге, тот же класс | `Silver` 19/177 · `Will` 19/288 · `Faithful` 18/51 · `Dawn` 17/61 · `Forever` 209/76; чисты `Grail` 293/0 и `Almighty` 57/0 |
⇒ дефект реален и узок: он бьёт по заглавным НАРИЦАТЕЛЬНЫМ (фракция «the Dead», держава «the Empire»),
а не по личным именам. Лечение БЕЗ правки Go — дисциплина промтов: банкнота и терминолог этой пары
велят не канонизировать одиночное заглавное нарицательное. Правка `norm.go` передана оркестратору
рядом, с ценой: `bankRoleProducer` делает правку текста банк-роли пере-спросом решённых терминов.
## 12. Нарезка глав (§4.4) — что решено и почему
Замер прибором самого движка (`--json`-манифест, 71 запись; сумма `price.source_chars` = 1 601 395
совпадает со сводкой): глав **71**, `heading` НЕПУСТ у **0** из 71, `title_raw`у 71 из 71;
крупных (≥100 тыс. знаков) — **6** (BOOK TWO 392 312 … BOOK SIX 140 022); крошечных (<200) **64**;
средних **1**.
64 крошечные главы НЕ «страницы-разделители»: это **разрезанная на файлы страница «Contents»**.
Замер по EPUB напрямую: navPoint'ов 71, с фрагментом `#` **ноль**, целей-документов 71 различных;
`index_split_058.html` (583 руны) начинается словами «Contents · Title Page Chapter I. Parting Gifts»
и обрывается на 25-й записи, дальше каждая запись оглавления лежит СВОИМ документом. Настоящие главы
в TOC не названы вовсе: проза живёт в документах между титулами книг, navPoint'а у них нет, и
`groupChapters` приписывает их к предыдущей главе. Заголовок главы ВНУТРИ документа есть, и его форма
английская голая РИМСКАЯ цифра отдельной строкой, под ней название капсом; `<h1>``<h6>` нет ни одного.
**РЕШЕНИЕ: нарезку EPUB в этом паке НЕ чиню.** (1) Эксперимент она не блокирует: BOOK THREE = 148 782
знака без пробелов **40 874 токена** при цели 41 027, промах 0.37 %. (2) Починка требует не порога в
данных, а нового рода грамматики (безмаркерный заголовок + римские цифры) и разреза ВНУТРИ документа
это тело ряда **283**. (3) Порог «сколько знаков делает главу главой» проблему не решает: он убрал бы
64 крошечные записи и оставил шесть полотен.
**Граница ряда 303 названа явно:** не-CJK TXT этим паком НЕ починен. Пере-снято с контролем на второй
английской книге: `books/fifty_shades_1_en.txt`, строк `^[[:space:]]*Chapter ` **26**, а
`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.8 бюджет нарезки** оценка заведена в `configs/pairs/en-ru.yaml`, названа оценкой (см. §2 того файла).