# Промт бэкенд-сессии: ГРАНИЦА ГЛАВЫ — СКЛЕИТЬ ТО, ЧТО ДВИЖОК УЖЕ ЗНАЕТ > Оркестратор очереди №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** (по 2–7) | | ярлык навигации против «номер + имя» из прозы | побайтно **0 из 81**; при нормализации регистра и апострофа **65 из 81** ⇒ 16 глав навигация не называет вовсе | Контроль, доказывающий, что прибор читал книгу: абзацев с атрибутом класса — 11 397 (счёт регекспом `]*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 документов по 2–7 глав). Она ломает три допущения 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`). На заголовке С сепаратором после юнита длиной 61–84 руны ингест говорит «нет», чанкер «да»; `第零章` ингест режет, а чанкер заголовок не снимает — сырой маркер уезжает модели. Без сепаратора расхождения нет. Направление названо в самом ряду: сведение двух предикатов к ингестовским стражам. Пин `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 — отдельным пунктом. - [ ] Числа сняты ПОСЛЕ последней правки; гейт зоны прогнан целиком, полнота — сверкой СПИСКА пакетов; всё живое — в дереве. - [ ] Явное **«работа завершена, править не планирую»**. ⛔ **Ответ, к которому пак ведёт:** тождество, СОПОСТАВЛЕННОЕ заголовку в прозе, решает движок, потому что это факт книги, а не порог; АДРЕС границы даёт грамматика, ИМЯ — тот, кто его несёт; всё, что сверх этого, — данные, которые ведут себя верно там, где явления нет. Решение, ставящее догадку движка на место факта книги, не готово, сколько бы тестов ни было зелёными.