textmachine/docs/BACKEND_CHAPTER_STRUCTURE_SESSION_PROMPT.md

382 lines
44 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.

# Промт бэкенд-сессии: ГРАНИЦА ГЛАВЫ — СКЛЕИТЬ ТО, ЧТО ДВИЖОК УЖЕ ЗНАЕТ
> Оркестратор очереди №23. Пак **$0**, платных вызовов в нём нет. Зона записи — `backend/`. Ты не коммитишь:
> дерево передаётся оркестратору на лендинг. Именование пака и его границы ратифицированы нотой **`D39.270`**
> (греп `^## D39.270` в `docs/architecture/05-decisions-log.md`); при расхождении промта с нотой побеждает нота.
>
> Предмет пака — **кто и на каком основании решает, где начинается глава и как она называется.** Осколки
> оглавления английской книги — самый дешёвый симптом, а не предмет.
---
## 1. Какая проблема и что решит твой результат
Движок переводит длинные книги мультиагентным пайплайном. Пары языков — ДАННЫЕ, а не код; ревью-вопрос по
умолчанию: «заработает ли пара, которой в репо ещё НЕТ, без правки Go?».
Скоро идёт платный холодный прогон двух книг через API платформы: около 20 глав китайской и равный по
токенам срез английской — `books/Kristoff_Jay_-_Empire_of_the_Vampire_3_-_Empire_of_the_Dawn.epub` (EPUB 2.0,
навигация — `toc.ncx`, `nav.xhtml` нет). ⛔ **Слово владельца, под которым выдан пак:** «цель — не бежать
поскорее приступить к холодному прогону, а подготовить бэкенд так, чтоб этот холодный прогон исполнить
**максимально правильно**. Халтурить не надо, подгонять тоже ничего не надо, спиливаем долг из бэкенда,
реализуем актуальный, нужный, чистый архитектурно код».
**Корень, найденный владельцем одной фразой** — «у нас есть статический код, который смотрит, глава ли это и
как она названа, там как-то это всё должно склеиваться». Замер подтвердил дословно: диспетчер ингеста отдаёт
грамматику источника только текстовому пути —
`backend/internal/chunk/ingest.go:243`=`func ingestTXT(p, encoding, sourceLang string, st *lang.SourceStructure)`
а `backend/internal/chunk/ingest.go:678`=`func ingestEPUB(p string, im *lang.InlineMarkup)` её не получает
вовсе. ⇒ механизм, умеющий сказать «это глава и вот её имя», работает на одном пути из двух; на EPUB границу
единолично назначает навигация издателя.
**Что эта навигация делает с книгой прогона** (всё снято $0 питоном по архиву; пере-снимешь своим прибором):
| что | число |
|---|---|
| целей навигации | **71** = 6 ярлыков частей (`BOOK ONE`…) + 65 ярлыков глав (`Chapter XIX. A Taste of Home`) |
| тела целей | **60** побуквенно равны своему ярлыку · **7** коротки и НЕ равны (2 титула частей с подзаголовком · 4 осколка оглавления, чья вторая строка — имя следующей части · 1 осколок с хвостом оглавления: `Dawn · Acknowledgments · Also by · About the Author · Copyright`) · **4** несут прозу |
| документов spine без навигационной цели | **55 из 126** = 35 прозаических (≥9 тыс. знаков) + 20 прочих; среди прочих `index_split_058` и `_124`ТЕКСТ оглавления вне навигации |
| печатное оглавление книги (`058`, осколки `059…123`, второе оглавление в `124`) | Dramatis Personae · Sunset · **81** «Chapter» · Dawn · служебные |
| форма главы в прозе | римское числительное отдельным абзацем, затем имя прописными, затем проза |
| абзацев, чей текст — голое римское числительное | **84**: у 81 имя следом, у 3 нет — все три в разделе `SUNSET` (`006`), где за номером сразу проза |
| разделов БЕЗ номера | 2: `SUNSET` (`006`) и `DAWN` (`049`, ~13.7 тыс. знаков; открыт абзацем `DAWN`) |
| номеров глав в документах, у которых ЕСТЬ цель навигации | **12** (`015`:1 · `025`:5 · `033`:3 · `041`:3) |
| документов, несущих 2 и больше глав | **28** (по 27) |
| ярлык навигации против «номер + имя» из прозы | побайтно **0 из 81**; при нормализации регистра и апострофа **65 из 81** ⇒ 16 глав навигация не называет вовсе |
Контроль, доказывающий, что прибор читал книгу: абзацев с атрибутом класса — 11 397 (счёт регекспом
`<p[^>]*class=`; другой парсер на тот же вопрос дал 11 522 — подписывай способ счёта рядом с числом).
**Сводка одной строкой, и это сердце пака:** навигация несёт правильные ИМЕНА и неправильные АДРЕСА; проза
несёт правильные АДРЕСА и расщеплённое имя. Ни один источник не лжёт целиком, и ни одного не хватает одного.
**Твой результат:** английская книга режется по своим настоящим главам, каждая получает имя, книга без этого
явления не меняется ни на байт — и всё это без ветки по языку или книге в Go.
---
## 2. Зона записи и git
Пишешь только в `backend/` и в свою секцию `docs/PROGRESS.md`. Чужие зоны (`platform/`, `frontend/`,
`eval/`, прочие `docs/`) читать можно, править нельзя. Не коммитишь; в дереве могут работать другие сессии —
их незакоммиченное не трогай. Фоновое гасишь по своему PID, а не по имени команды.
**НИКОГДА не читай `.env` и `.env.*`** — там боевые ключи.
Артефакты: что должно пережить рестарт — в РЕПОЗИТОРИЙ (доказательная база уедет в `docs/archive/reports/` при
приёмке); питон-пробы и копии дерева — в скретчпаде, не в репо; базы прогонов — только на чтение
(`python3` + `sqlite3.connect('file:<путь>?mode=ro', uri=True)`).
---
## 3. Карта чтения — минимум из пяти позиций
Карта — МИНИМУМ, а не потолок (`D39.258` п.9): `docs/`, `research/`, `experiments/` грепай в любое время.
Код-факты добываешь САМА: адреса в промте — отправные точки, а не истина.
1. `CLAUDE.md` — канон, цели, гардрейлы.
2. `backend/docs/CHAPTER_STRUCTURE_DESIGN.md` — шапка и §7.1-бис · §7.2 · §7.3 · §7.4 · §8.1 · §8.2. Статус
документа — **ПРЕДЛОЖЕНИЕ, НЕ РАТИФИЦИРОВАНО** (`D39.245`: четыре круга без сходимости; устояла предметная
часть «глава — идентичность», механика — нет). Брать оттуда ФОРМУ можно и нужно, ссылаться как на решённое —
нельзя. Большой перекрой его §9 (ряд 161) этот пак НЕ строит.
3. `backend/internal/chunk/``ingest.go` и `epubtoc.go`: диспетчер, оба пути, разбор навигации, группировка.
4. `backend/internal/lang/structure.go` — грамматика заголовка, её лестница загрузки и отпечаток.
5. `docs/BACKLOG.md`, ряды **303 · 346 · 283 · 284 · 201 · 302**.
---
## 4. Работа
### 4.0 Что ратифицировано и вложено сюда, чтобы не открывать ноты
- **Этот пак есть «пак 2» по ряду 303** (`D39.270` п.1). Запрет `D39.224` п.7 («ось „обязательность юнита" вне
пака 2 не трогать») условен и этим паком **исполняется, а не снимается**: ось трогать можно и нужно. Прочие
запреты того же пункта действуют: `Runner` не переписывать, `internal/pipeline` не дробить.
- **Ряд 346 половина (б) едет в этом паке** (`D39.270` п.7) — отступление от `D39.224` п.4(а) («шаги 2+3 — одна
перенарезка») ратифицировано там же; цена второй перенарезки $0 при условии `D39.224` п.5.
- **Стандарт владельца** (`D39.258` п.3): «согласно нашим проектным высоким стандартам по решению проблемы
художественного перевода»; «не хакайте плохие решения или те, что не работают, пишите чистый код и там, где
надо, рефакторинг»; техдолг не копить. ⇒ где чистое решение требует перестройки, заказана перестройка, и
отчёт называет, что отрефакторено и почему.
- **Слово владельца о языке и книге:** «Бэкенд не должен иметь конкретных механизмов под язык\книгу, максимум
в данных, и то они так же должны хорошо отрабатывать, где этих французских слов нет».
- **Холодный прогон идёт через API платформы, целиком** (слово владельца). Это задаёт §4.2.
### 4.1 РОВНО ТАК: правила, которые следуют из замера
**(а) ДОКУМЕНТ, ЧЬЁ ТЕЛО РАВНО ЕГО ЯРЛЫКУ, — НЕ ГЛАВА, НО ИМЯ ОН НЕСЁТ.** Это тождество, а не порог.
Исключается **существующим каналом**`backend/internal/chunk/ingest.go:79`=`Excluded NAMES every service page that was not read`
(имя документа, роль, размер; инвариант сохранения его уже учитывает) — с НОВОЙ ролью. Отдельный счётчик не
заводить: код объясняет почему — `backend/internal/chunk/ingest.go:81`=`A NUMBER HERE WOULD HIDE THE ONE THING WORTH SEEING`.
Докблок `backend/internal/chunk/epubtoc.go:289`=`NO DOCUMENT IS DROPPED HERE` переписывается тем же движением и
называет условие, при котором вывод держится.
**Условие, без которого исключение есть пропуск текста** (`D39.205`: «без пропусков»; пропущенный кусок главы —
критический): исключение ничего не теряет, ТОЛЬКО если ярлык сохранён там, где его увидит читатель. Сегодня
он туда не доезжает (§4.3). ⇒ исключай тождество, чей ярлык СОПОСТАВЛЕН заголовку в прозе, либо назови другое
условие — и поставь пин на книгу 1:1, где тождественная страница «PART ONE» стоит перед главой со своей целью:
её текст обязан уцелеть.
⛔ Порога «почти равно» не заводить. **Остаток решается, а не называется:** 7 коротких не-тождеств и документы
`058`/`124`у каждого исход (граница · преамбула · исключение с ролью) с доводом и числом.
**(б) ГРАНИЦЫ — ОБЪЕДИНЕНИЕ ДВУХ НАБОРОВ.** Цели навигации, пережившие (а), плюс заголовки грамматики В ЛЮБОЙ
позиции, в том числе внутри документа, у которого есть цель; совпавшие позиции склеиваются, и **имя на совпавшей границе берётся у заголовка грамматики**, а ярлык части
решается судьбой титула (§4.2): у 4 частей из 6 титул делит документ с главой I (`015` · `025` · `033` · `041`),
и правило «ярлык ОТКРЫВШЕГО документа» назвало бы главу I второй части «BOOK TWO». ⚠ «Грамматика
только там, где навигация молчит» теряет 12 глав в четырёх документах с целью. Контроли: isekai — 44 главы до
и 44 после; Кристофф — 12 номеров в документах с целью разрезаны.
**(в) РЕЗКА ВНУТРИ ДОКУМЕНТА — В ПАКЕ, потому что без неё книгу не разрезать** (28 документов по 27 глав). Она
ломает три допущения EPUB-пути, построенных на целых документах; для каждого назови, как оно держится:
- имя главы — ярлык ОТКРЫВШЕГО документа: `backend/internal/chunk/ingest.go:925`=`The chapter's source title is the label of the document that OPENED it`;
- инвариант «глава — ровно её документы»: `backend/internal/chunk/ingest.go:949`=`a chapter is EXACTLY its documents plus the separators`;
- номер главы у ruby-чтений, от которого зависит `since_ch` памяти: `backend/internal/chunk/ingest.go:961`=`The chapter number ruby carries MUST equal the number SplitChunks assigns`.
Обходчик `backend/internal/chunk/ingest.go:1155`=`func extractXHTML(data []byte, ir *inlineRules)` отдаёт ruby
без позиции и НЕ трогается (четыре пина байт-паритета, ошибка тихая); если без него нельзя — пинг, а не правка.
⚠ Ряд 302 в форме «якоря навигации внутри документа» НЕ строится (у этой книги фрагментов 0); резка по грамматике
на извлечённом тексте — строится.
**(г) ТИТУЛ ЧАСТИ ОСТАЁТСЯ ГРАНИЦЕЙ.** Сегодня его спасает подзаголовок; титул без подзаголовка был бы
тождеством, и (а) сняло бы границу целой части молча. Пин: тождественный титул, за которым идут документы без
целей навигации ⇒ граница сохраняется.
**(д) ПРОВЕНАНС СМЕШАННОЙ НАРЕЗКИ НАЗЫВАЕТСЯ.** Сегодня метка утверждает, что границы провёл ровно один путь —
`backend/internal/chunk/ingest.go:186`=`exactly one of them drew every boundary`; после пака это ложь. Платформа
доверяет только `detected` (`platform/internal/ingest/manifest.go:284`=`IS DELIBERATELY NOT — which is the opposite`),
и от метки зависит, в главах или в знаках пользователь видит заказ (`D39.196` п.1). ⇒ назови метку, словарь
расширяй аддитивно, пин на метку; строкой отчёта — что увидит форма заказа.
**(е) ЕДИНИЦА ПРАВИЛА — АБЗАЦ, А НЕ СТРОКА.** Существующая машина заголовков читает СТРОКИ
(`backend/internal/chunk/ingest.go:289`=`for _, ln := range strings.Split(chapter`), а исходник держит переводы строк
внутри абзаца: по строкам голых римских числительных 104, из них **20 ложных «I» в стихах** («KNOW THEE, WHO | I
| AM»). 84 по строкам на английской паре выходит лишь потому, что глиф курсива пары превращает «I» в `*I*`
верный ответ неверным методом. ⇒ правило не вправе зависеть от данных пары; тестовый `ingest(p)` передаёт
разметку `nil` — проверь на нём.
**(ж) КАКАЯ СИСТЕМА СЧИСЛЕНИЯ — РЕШАЮТ ДАННЫЕ ГРАММАТИКИ; КАК ЕЁ ЧИТАТЬ — ОБЩИЙ АЛГОРИТМ.** Класс числительного
сегодня зашит в Go (`backend/internal/lang/structure.go:75`=`s.headerRE = regexp.MustCompile`): арабские плюс CJK
из встроенного `cjk-section.txt`. Выбор системы и её таблица (символ или слово → значение) — **новым ключом в
`structure.txt` языка источника**, со своим отпечатком в крое. Алгоритм системы (аддитивно-вычитательный для
римских, составной словарный для числительных-слов) — Go, как уже позиционный CJK-парсер `parseSectionNumeral`.
**НЕ через `numeral.txt`**: этот файл — канал МАЙНЕРА имён (`backend/internal/lang/langpack.go:285`=`"rank-word.txt", "topo-suffix.txt", "grade-prefix.txt", "numeral.txt"`),
у `en` манифест каналов — `none`, и подключение туда сложило бы грамматику глав в версию пакета: правка
грамматики двигала бы крой по чужой денежной оси, а тест остался бы зелёным. ⚠ Системы нужны ДВЕ: римская
(Кристофф) и числительные-слова (`fifty_shades_1_en.txt`: «Chapter Twenty-six», вход ряда 303).
**(з) ТРИ МЕСТА «ЮНИТ ОБЯЗАТЕЛЕН» — ПРЕДМЕТ РЯДА 303:** `backend/internal/chunk/ingest.go:366`=`if r != unit {` ·
`backend/internal/chunk/ingest.go:290`=`for _, u := range st.UnitOrdered {` ·
`backend/internal/chunk/ingest.go:397`=`for _, unit := range st.UnitOrdered {`. Грамматика вида «Chapter One» (маркер +
номер словом, без юнита) книгу не режет, хотя чанкер такой заголовок снять уже умеет. Форма лечения
набросана в дизайне §8.2 (доминанта над формами заголовка, «без юнита» — последним); не ратифицирована — вправе
предложить другую с доводом.
**(и) `en-ru/heading.txt` НЕ СОЗДАВАТЬ.** Любой шаблон отвечает на вопрос владельца В-1 (`D39.258` п.8: какой
номер главы видит читатель) и включает `ApplyHeading` — ряд 201. Назови строкой отчёта.
### 4.2 РЕШИ САМА, с одним обязательным ответом: откуда берётся знание о заголовках этой книги
**Книжные данные до книги, идущей через API платформы, сегодня не доезжают.** `book.yaml` такой книги
рендерится один раз из шаблона оператора
(`platform/internal/config/config.go:259`=`BookTemplate is the operator's starting`), платформа вписывает только
идентичность, языки и имя файла, а крой снимается на интейке. Существующий книжный оверлей грамматику тоже не
понесёт — он отказывает любому файлу вне манифеста пары
(`backend/internal/lang/langpack.go:463`=`an overlay merges only the source/pair manifest files`), а лестница
грамматики (`backend/internal/lang/structure.go:142`=`func LoadSourceStructure(root, sourceLang string)`) книжной
ступени не имеет.
**решение пака обязано работать для книги прогона БЕЗ книжных данных.** Законные источники, по слову
владельца: то, что уже несёт сама книга (тождество, имена навигации, печатное оглавление), и языковые данные
источника (`structure.txt` — данные ЯЗЫКА ИСТОЧНИКА, не пары) — последние только с доказанной инертностью на
корпусе дерева: прогон «до/после» по ВСЕМ исходным книгам `books/`, и где явления нет, число глав не
меняется. Книжная ступень не запрещена, но и не требуется; если строишь — ступенью лестницы со своим
отпечатком (`backend/internal/lang/structure.go:127`=`func structureFingerprint(origin string, b []byte) string`),
не через оверлей и не полем брифа.
**Имя главы на извлечённом тексте:** класса абзаца там нет (обходчик его не отдаёт). Развилка твоя, но выбором
из трёх: (i) канал из обходчика с пином байт-паритета — это снятие запрета (в), только пингом; (ii) признак
имени значением ДАННЫХ грамматики; (iii) имя только от навигации или печатного оглавления. ⛔ Правило «прописные
= имя» в Go — ветка по письменности, запрещено. ⚠ Не путать со свёрткой регистра ПРИ СРАВНЕНИИ: это общая
Unicode-операция, она разрешена — и без неё сопоставление ярлыка с прозой даёт 0 из 81 вместо 65.
**Судьбы, которые объявляешь ты, и они входят в приёмочное число N:** `SUNSET` (одна глава или три
безымянных) · `DAWN` (голое числительное приклеит его к главе «Execution») · шесть титулов частей с эпиграфами
(отдельная глава или преамбула главы I).
### 4.3 Докуда имя доезжает — граница, которую пак не переходит
Имя доедет до манифеста движка. Платформа его не читает (`platform/internal/ingest/manifest.go:124`=`type ManifestChapter struct`
— поля id, номер, юниты, цена), а в книге читателя заголовок берётся из шаблона пары, которого у английской
нет: `backend/internal/pipeline/bookbuild.go:554`=`t := ce.Heading`, при пустом —
`backend/internal/pipeline/bookbuild.go:556`=`t = strconv.Itoa(ce.Chapter)`. Это долг рядов 284 и 201;
назови его строкой отчёта и не чини здесь.
### 4.4 ЗАМЕР ПЕРЕД СТРОЙКОЙ — ПЕРВЫМ ДЕЛОМ, БЕЗ ЕДИНОЙ СТРОКИ Go
Реализуй правило на python и прогони по книге прогона и по корпусу. Ответь числами: сколько границ даёт
объединение (б) · сколько глав получили имя и откуда · сколько безымянных · N против печатного оглавления и
против 71 записи навигации · сколько ложных срабатываний на корпусе. ⚠ Кандидаты, ложные для приоров имени (замер круга, пере-сними):
абзацы `044…047` по одному слову прописными (`SHARP.` `AS.` `THREE.` `SWORDS.` — стилизованная фраза по
странице) и подпись эпиграфа в `015` (`—LUIS BETTENCOURT`) — тот же класс абзаца, всё прописными, и ни одно
не имя главы; у трёх номеров `SUNSET` следом идёт проза. ⇒ **приёмочное число N объявляешь ты**
вместе с судьбами §4.2, и оно входит в записку-план числом.
### 4.5 ЧТО ПАК СДВИНЕТ В ДЕНЬГАХ
Правка правила ингеста бампает версию нарезки — конвенция самого кода:
`backend/internal/pipeline/manifest.go:355`=`treats an ingest-rule change as a chunkerVersion bump`. Версия
сворачивается в ключ манифеста (`backend/internal/pipeline/manifest.go:383`=`Chunker: chunkerVersion`, рядом
`backend/internal/pipeline/manifest.go:385`=`Structure: r.structure.Fingerprint()`) и в снапшот
(`backend/internal/pipeline/snapshot.go:463`=`ChunkerVersion: chunkerVersion`). ⇒ **ключ манифеста КИТАЙСКОЙ
книги сдвинется** — через версию нарезки, а не через отпечаток (у неё отпечаток CJK-грамматики, пустой
`-none` — английский свидетель). §4.1-бис ниже вдобавок меняет ТЕКСТ чанка.
Сегодня это бесплатно при названном условии: ни одну существующую базу с оплаченными чанками никто не
продолжает (корпус одноразовый — `D39.63` (3), `D39.190` п.4). Продуктовый путь на этом хосте не проверен
(`TM_PLATFORM_BOOKS_DIR` не задан ⇒ «не нашёл», а не «проверил»). Пак лендится ДО фриза прогона; промт
прогона переписывает оркестратор. **Тебе — строкой отчёта: что сдвинулось, у каких книг, какой пере-снапшот.**
### 4.1-бис Ряд 346 (б): правило заголовка разъехалось по двум предикатам — сведи в одно
Страж длины живёт только в ингесте (`backend/internal/chunk/ingest.go:341`=`const chapterHeaderMaxRunes = 60`),
осмысленность номера — только в чанкере (`backend/internal/chunk/chunker.go:315`=`v := section + num`). На
заголовке С сепаратором после юнита длиной 6184 руны ингест говорит «нет», чанкер «да»; `第零章` ингест режет,
а чанкер заголовок не снимает — сырой маркер уезжает модели. Без сепаратора расхождения нет. Направление
названо в самом ряду: сведение двух предикатов к ингестовским стражам. Пин
`backend/internal/chunk/headingparity_test.go:106`=`THE FIX IS NOT IN SCOPE HERE AND IT IS NOT $0` краснеет
ровно при фиксе — **ты тот фиксер**: переворачиваешь его вместе с правилом и объявляешь как заказанную смену
поведения. ⚠ У пина расхождения записи в каталоге мутаций нет — заведи посадку под новое правило и введи в гейт.
В китайском корпусе `第零章` — 0 и заголовков длиннее 60 рун — 0; скажи это числом в отчёте.
### 4.6 Чего пак не делает
Большой перекрой (ряд 161, дизайн §9, миграции) · ряд 302 в форме якорей навигации · правку обходчика
`extractXHTML` · правки платформы (чужая зона; что ей нужно — строкой отчёта) · `en-ru/heading.txt` · провод
счётчиков к пользователю (носитель — ноты ингеста, дальше не тянуть).
---
## 5. Самопроверка исполнением — и четыре места, где этот пак мягок
Ревью исполнением: своего кода, своих проб, своих чисел. **Субагенты и воркфлоу разрешены.** Советчики —
**до двух фаблов** (`model: "fable"` явно) с ПОСТОЯННЫМ контекстом; советоваться на ПРОЕКТИРОВАНИИ и на ПРИЁМКЕ;
спрашивать: сомнение · развилка · не построено ли уже · не противоречит ли ратифицированному. Советчик — не
источник истины, его посылки проверяются деревом. Внутри воркфлоу тот же потолок. **Механизм обязателен:**
интервальная самоверификация субагентом против списка §13 — по готовности каждого из (а)(з) и перед сдачей.
1.**Верный ответ неверным методом.** Число глав сойдётся построчной машиной на английской паре — через
курсив пары. Проверяй метод, а не число: `ingest(p)` с разметкой `nil`, абзац, а не строка.
2.**Резка внутри документа и ruby.** Контрольный набор устроен 1:1 и эту форму не ловит. Синтетический
CJK-EPUB: две главы в одном документе, ruby во второй — пин на номер главы у чтения. ⚠ **Ожидаемый исход
назван заранее:** обходчик отдаёт ruby без позиции, поэтому пин без его правки невыполним — итог либо пинг
(правка обходчика снимает запрет (в)), либо атрибуция по документу, объявленная ограничением в отчёте.
Третьего исхода — эвристики «найти базу ruby по тексту главы» — промт не санкционирует.
3.**Исключение как пропуск — и пины, которые зелены без правила.** Оба пина (г) и «PART ONE» ОТРИЦАТЕЛЬНЫЕ:
они проходят и при полном отсутствии правила (а), а на книге 1:1 правило не срабатывает вовсе. ⇒ обязателен
ДИФФЕРЕНЦИАЛЬНЫЙ синтетический пин: осколок-тождество, чей ярлык сопоставлен заголовку в прозе ⇒ исключён с
ролью, глав на одну меньше; ТОТ ЖЕ осколок, чей ярлык прозе не сопоставлен ⇒ остаётся. Без второй половины
условие «сопоставлен» не стережёт ничего. Условие исключения — в докблоке.
4.**Грамматика этой книги под видом грамматики языка.** Всё, что выведено из Кристоффа, меряется на корпусе:
`books/fifty_shades_1_en.epub` (NCX 34 цели 1:1 — правило (а) обязано не сработать ни разу),
`books/isekai_majutsushi_jp.epub` (44 цели; сегодня грамматики на EPUB-пути не получает, после пака получит —
44 до и 44 после), `books/fifty_shades_1_en.txt` (52 строки «Chapter…», номера словами, цифр 0 — вход ряда
303). Пин не строится на той же фикстуре, из которой выведено правило; образец правильного шва —
`backend/internal/chunk/epubtoc_test.go:428`=`func TestANewLanguageCutsFromItsDataFileAlone`.
**Мутации — часть пака.** В каталоге `backend/cmd/tmmutate/mutations.json` 557 записей, в гейте 346
(`backend/Makefile:116`=`run ./cmd/tmmutate -root`). Предмету принадлежат **12 записей ВНЕ гейта:**
`EPUB-preamble-joins-chapter-one` · `EPUB-conservation-no-document-leaves-unaccounted` ·
`EPUB-unresolved-counts-only-what-it-promises` · `EPUB-service-pages-are-exactly-two-roles` ·
`TITLE-raw-epub-half-comes-from-the-label` · `PP-structure-provenance` · `DF-competition-order-loses-a-chapter` ·
`EPUB-collapsed-targets-downgrade-the-provenance` · `EPUB-service-role-at-a-point-keeps-the-document` ·
`INGEST-every-count-reaches-the-operator` · `MANIFEST-key-carries-the-structure-grammar` ·
`TITLE-raw-follows-the-kept-index`. Потерянный якорь покраснеет сам (проверка гниения каталога идёт по всему
каталогу), но ловит ли тест посадку, которая всё ещё сажается, — вне гейта не меряет никто. ⇒ прогони их
поимённо через `-id` на копии; введи в гейт или скажи, почему нет. Популяция таблицы = гейт + эти 12 + новые.
---
## 6. Оси ревью (вправе заменить с аргументом)
- **Код и швы:** батарея + живые пробы + свои посадки вне списка; крой принимается прогоном через настоящий
драйвер ингеста, а не чтением диффа.
- **Общность:** для каждого правила — «заработает ли книга без явления без правки Go» числом на корпусе.
- **Провенанс и деньги:** метка нарезки и ключ манифеста двигаются ровно тогда, когда должны.
**Кодовому паку дополнительно:** пин на УСЛОВНОЕ сообщение обязан иметь фикстуру, где оно ОБЯЗАНО прозвучать ·
перед отчётом сверь каждый клейм с результатом инструмента ЭТОЙ сессии · последний абзац отчёта оказался
планом — сделай сейчас · **править или удалять тесты ради зелени недопустимо**; правка, вызванная ЗАКАЗАННОЙ
сменой поведения, — обслуживание и ОБЪЯВЛЯЕТСЯ · дифф `^func Test` предъявляй исполнением · комментарий,
несущий вывод, называет условие, при котором вывод перестаёт держаться; прозы и гарантий без пина в коде нет.
---
## 7. Записка-план
До первой правки кода: замысел (проектирование раньше кода) · порядок · что спорно · N из §4.4 числом ·
комплектность против заказа — таблица «пункт §4 → как будет сделан». Советчик смотрит записку до стройки.
---
## 8. Заявление есть команда
Каждое число — с командой повторения. У каждого НУЛЯ печатается контрольная величина. Эрудиция — не улика:
утверждение грунтуется `file:line` или замером, иначе помечается «мнение».
**Ловушки среды (каждая даёт тихий ложный ноль):** обёртка `grep` чтит игнор-файлы и не видит `books/` — бери
`command grep`; `books/` — симлинк, и `find` без `-L` в него не заходит; `find` здесь bfs (относительное время
только `-mmin`); CLI для баз нет; знаки и байты — разные популяции.
---
## 9. Эхо старта
Первым действием — ≤10 строк **СВОИМИ словами** (дословный пересказ подтверждает канал, но не понимание):
скоуп · инварианты · чего не делаешь. Шлёшь оркестратору по адресу из канала (§12) — это и проверка канала.
---
## 10. Что НЕ удалось и где прибор слеп
Обязательная секция отчёта, две половины: «что не получилось» и **«что ты знаешь и не сказала»** — что
невидимо · почему не чинила · чем закрывается. В коде названо, в отчёте нет — значит для следующей смены не
названо.
---
## 11. Канал вопросов и право отказаться
Конфликт промта с деревом или с журналом решений — **пинг, а не интерпретация**: оркестратору через канал, а
нет канала — секцией отчёта, владелец пере-передаст. Право сказать «этого делать не надо» с аргументом есть и
поощряется. Дополнения к паку в ходе работы приходят ТОЛЬКО релеем владельца; приём эхо-подтверждается и
идёт отдельным пунктом отчёта.
---
## 12. Прямой канал
Механизм — `CLAUDE.md`, раздел «Связь между сессиями». Файл — `/tmp/textmachine-channel`: впиши свой блок
первым делом, адрес оркестратора возьми оттуда и сверь с `ListAgents` — адрес из файла не доказывает, что
сессия жива. **Канала нет ⇒ НЕ искать**: вопрос — секцией отчёта, работа продолжается.
---
## 13. Когда пак считается завершённым
- [ ] Замер §4.4 предъявлен числом до первой правки Go; N и судьбы `SUNSET` · `DAWN` · титулов частей ·
7 не-тождеств · `058`/`124` объявлены с доводом.
- [ ] У каждого пункта §4 — исход: сделано · не делаю с доводом · пинг.
- [ ] Английская книга режется на N глав — прогоном настоящего драйвера; у каждой главы назван источник имени.
- [ ] Контроли: isekai 44/44 · `fifty_shades_1_en.epub` — (а) сработало 0 раз · 12 номеров в документах с целью
разрезаны · корпус «до/после» по всем исходным книгам `books/` — таблицей.
- [ ] Ряд 303: безъюнитная грамматика режет `fifty_shades_1_en.txt` одним файлом данных (строки с отступом и
CRLF, номера СЛОВАМИ — вторая система счисления, §4.1(ж)) — или ряд назван открытым с доводом; оба исхода
штатные.
- [ ] Китайская книга не изменилась ПО ТЕКСТУ — побайтным равенством текстов глав и чанков; сдвиг её КЛЮЧА
манифеста назван отдельно (§4.5).
- [ ] Ни одной ветки по языку, паре или письменности в Go — грепом с контрольной величиной.
- [ ] Таблица мутаций: гейт + 12 + новые, ТРИ исхода — поймано · выжило · **НЕ ИЗМЕРЕНО**; вердикт по тексту
падения, а не по цвету.
- [ ] Круги СОШЛИСЬ: последний не дал новых находок; прежние закрыты таблицей «находка → что сделано → чем
предъявлено».
- [ ] Список «что отрефакторено и почему» — или «не потребовалось» с доводом; стандарт и аддендум `D39.258`
п.3/п.9 — отдельным пунктом.
- [ ] Числа сняты ПОСЛЕ последней правки; гейт зоны прогнан целиком, полнота — сверкой СПИСКА пакетов; всё
живое — в дереве.
- [ ] Явное **«работа завершена, править не планирую»**.
**Ответ, к которому пак ведёт:** тождество, СОПОСТАВЛЕННОЕ заголовку в прозе, решает движок, потому что это
факт книги, а не порог; АДРЕС границы даёт грамматика,
ИМЯ — тот, кто его несёт; всё, что сверх этого, — данные, которые ведут себя верно там, где явления нет. Решение,
ставящее догадку движка на место факта книги, не готово, сколько бы тестов ни было зелёными.