Add the chapter-structure pack: formats and an honest provenance vocabulary, with the cut gated on the stand book reproducing byte for byte
This commit is contained in:
parent
75a586ae50
commit
dba8a0bb76
1 changed files with 374 additions and 0 deletions
374
docs/CHAPTER_STRUCTURE_SESSION_PROMPT.md
Normal file
374
docs/CHAPTER_STRUCTURE_SESSION_PROMPT.md
Normal file
|
|
@ -0,0 +1,374 @@
|
|||
# ПАК «ФОРМАТЫ И ЧЕСТНЫЙ СЛОВАРЬ» — движковая сессия
|
||||
|
||||
> **ВЫДАН 05.09 сессии `textmachine-main-fe`.** Три круга совместного ревью (оркестратор + Fable 5);
|
||||
> состав пака и словарь — итог восьми кругов сходимости, тела разборов в `D39.202`/`D39.207`.
|
||||
|
||||
**Зона записи:** `backend/`. **Коммитит оркестратор** (`textmachine-main-27`), ты готовишь дерево и
|
||||
передаёшь. **Отчёт:** секция «Бэкенд» в `docs/PROGRESS.md`. **Денег:** $0, ни одного платного вызова.
|
||||
|
||||
---
|
||||
|
||||
## 0. КАРТА ЧТЕНИЯ — ПЯТЬ ПОЗИЦИЙ, ОНА ЗАКОН
|
||||
|
||||
Дальше — только по её ссылкам. Голову журнала решений целиком НЕ читать (канон это запрещает).
|
||||
|
||||
1. **`backend/internal/chunk/ingest.go`** целиком — предмет пака живёт здесь.
|
||||
2. **`docs/research/27-chapter-detection.md`** — через его ревью-шапку. Дизайн НЕ ратифицирован;
|
||||
это материал, а не заказ.
|
||||
3. **`## D39.205`** (пропущенный кусок — критическая поломка) и в `## D39.202` — **только п.3-бис**
|
||||
(гейт умирает вытеснением) **и п.9** (чего не сторожит ничто). Тело ноты целиком не нужно.
|
||||
⚠ **ПОДНОМЕР своего тела не имеет** — `D2.3` живёт пунктом внутри `^## D2`.
|
||||
4. Строки бэклога **297** (словарь провенанса) и **299** (имя, не разрешающееся ни во что) в
|
||||
`docs/PROGRESS.md`.
|
||||
5. **`docs/architecture/12-go-style-notes.md`** — норматив стиля, только больные места.
|
||||
|
||||
**Код читаешь по мере правки. Несущие файлы, которые ты ТОЧНО будешь править:**
|
||||
`chunk/ingest.go` · `pipeline/manifest.go` (ключ, тег, `title_raw`) · `chunk/chunker.go`
|
||||
(`stripHeading`, `matchHeaderLine`) · `lang/langpack.go` (⚠ `parseHeading` СЕГОДНЯ ТРЕБУЕТ `marker`,
|
||||
`:677-679` — после «только `template`» он упадёт, это заказанная правка) · `lang/embedded.go`.
|
||||
|
||||
---
|
||||
|
||||
## 1. ЧТО УЖЕ ПОСТРОЕНО — НЕ ЗАКАЗЫВАТЬ ЗАНОВО
|
||||
|
||||
Самый дорогой раздел: половина ошибок прошлых паков — постройка второго носителя.
|
||||
|
||||
- **Провенанс разреза уже есть** — поле `Document.Structure`, и оно **спроектировано верно**:
|
||||
отвечает на «КАКОЙ ПУТЬ провёл границы» (`ingest.go:94-95`). ⛔ Неверна его первая строка (`:70`),
|
||||
рекламирующая «how much the chapter cut can be trusted», — и именно её списала платформа.
|
||||
**Поле не переделывать; чинить словарь и формулировку.**
|
||||
- ⛔ **Валидатор V2-7 «формат провёл ВСЕ границы» (`ingest.go:170-176`) — ЗАМЕЩАЕТСЯ конкуренцией
|
||||
(§2.4), а не сохраняется рядом с ней.** После конкуренции его предикат
|
||||
(`len(parts)>1 && len(chapters)==len(parts)`, `:177`) становится мёртвым кодом. Не пытайся
|
||||
сохранить обе логики — это прямо противоречащие друг другу правила.
|
||||
- **Доминирующий юнит с полом ≥2** для CJK уже есть (`detectChapterUnit`, `ingest.go:249-263`) —
|
||||
это мини-индуктор, а не список паттернов. **Пол ≥2 — единственный валидатор, живущий в паке 1.**
|
||||
- **Читательские слова цели** уже разведены и грузятся СВОИМ загрузчиком по ЯЗЫКУ, вне пар-пака
|
||||
(`lang.LoadReaderWords`, `reader.go:87`) — **прецедент, по образцу которого делается структура
|
||||
источника.**
|
||||
- **Скрипт языка** уже выводится (`lang.LangScripts`, `script.go:67`), CJK-дефолт живёт данными.
|
||||
|
||||
---
|
||||
|
||||
## 2. ЧТО ЗАКАЗАНО
|
||||
|
||||
### 2.1 Шаг 0 — ПРИБОР ДО ПРАВОК. Поведение не меняется, $0
|
||||
|
||||
Без него пак не имеет права ложиться: под ним подписанный банк владельца (окна в ординалах глав)
|
||||
и боевая книга.
|
||||
|
||||
1. ⛔ **Пин — ПОЛНЫЙ МАНИФЕСТ до правок**, а не хеш: id глав + номера (лучше весь JSON). Из хеша
|
||||
не построить карту сдвигов §2.5, а она заказана. Хеш — производное, снимай и его.
|
||||
⛔ **НО: под `books/` не запускай НИЧЕГО.** `tmctl manifest` пишет сайдкар рядом с проектной базой
|
||||
книги (`manifestPath()` = `ProjectDB + ".manifest.json"`, `pipeline/manifest.go:189`), то есть
|
||||
ПИШЕТ в каталог книги — а запись там запрещена (§7). **Форма: копируешь исходник и `book.yaml`
|
||||
в собственный каталог сессии** (не `/tmp` — см. §4, не `books/`) **и все замеры и пины делаешь
|
||||
на копии.**
|
||||
⛔ **В копии обязательно перенаправь `project_db` и `source_file`.** `project_db` — ЯВНОЕ поле
|
||||
yaml (`config/book.go:86`), и «рядом с yaml» подставляется, только если оно ПУСТО (`:199-201`);
|
||||
у стендовых книг там абсолютные пути. Скопируешь как есть — сайдкар уедет обратно под `books/`
|
||||
(запись, которая запрещена) или по мёртвому пути.
|
||||
⚠ **А `langpack_root` / `langpack_extend` НЕ трогай** — они только читаются, и подмена дала бы
|
||||
другой `Pack.Version()`, то есть другой `cutTag`: пин снялся бы с другого разреза, и сравнивать
|
||||
было бы нечего.
|
||||
2. **Синтетические фикстуры по стандартам:** EPUB 3 с `nav`, EPUB 2 с NCX. Сегодня тестовый билдер
|
||||
пишет только `container→OPF→spine→xhtml` и **nav/NCX не пишет вовсе** (`chunktest/epub.go:42-82`).
|
||||
3. **Оракул — КОД, не замер:** EPUB с `nav` разворачивается в txt, путь разреза обязан восстановить
|
||||
nav-границы. Ground truth **без ручной разметки и без единого вызова модели**. ⚠ Сам ЗАМЕР — пак 2.
|
||||
4. **Замеры ДО правок, каждый числом в отчёт:** есть ли `\f` в стенд-книгах · есть ли главы-огрызки
|
||||
от print-TOC · сбрасывается ли нумерация по томам.
|
||||
|
||||
**Файлы стенда — поимённо** (см. §7 о доступе): 蛊真人 (GB18030 txt, ~2283 «第N节») · EPUB владельца
|
||||
Кристофф/en · EPUB владельца isekai/ja. ⚠ Платная книга платформы `bk_SS5VES2JELESJSTR` живёт в
|
||||
workdir платформы, **гейту §3 не видна и в него не входит**; её заметки теряются по слову оркестратора.
|
||||
|
||||
### 2.2 Данные структуры — ПО ИСТОЧНИКУ, вне пар-пака
|
||||
|
||||
Ревью-вопрос проекта: «заработает ли пара, которой в репо НЕТ, без правки Go?»
|
||||
|
||||
- `marker`/`units`/выбор читателя номеров/грамматика шаблона → **файл структуры ИСТОЧНИКА**, свой
|
||||
загрузчик по `Book.SourceLang`, **по образцу `reader.txt`**.
|
||||
- ⛔ **В пар-пак класть НЕЛЬЗЯ:** книга без каталога пары идёт с nil-паком (`runner.go:397-407`).
|
||||
- ⛔ **ОДИН ИСТОЧНИК НА ФАКТ.** Ингест И `stripHeading` чанкера читают **тот же самый файл**.
|
||||
Сегодня чанкер берёт `HeadingRule` пары; после разведения `heading.txt` оставляет ТОЛЬКО
|
||||
`template`. Оставить marker в обоих местах = вернуть дрейф ingest↔chunker, который pair-14 закрыл
|
||||
(«ONE source, no ingest↔chunker byte-drift», `ingest.go:181-186`).
|
||||
- **Лестница при отсутствии данных:** язык → скрипт → embedded-дефолт ПО СКРИПТУ → честное `none`.
|
||||
⛔ **Дефолт НЕЛЬЗЯ класть под `internal/lang/data/`**, хотя прецедент `cjk-section.txt` туда и манит:
|
||||
`EmbeddedVersion()` хеширует **весь каталог** (`embedded.go:44-56`, `ReadDir("data")`; «a byte edit
|
||||
of ANY embedded file is a loud --resnapshot»). Положишь туда — нарушишь «не в снапшот» МЕХАНИЗМОМ,
|
||||
тест §4 п.3 покраснеет, и самый соблазнительный «фикс» будет хаком (руками исключить файл из
|
||||
обхода). Клади в ОТДЕЛЬНЫЙ embed-каталог со своей версией (`internal/lang/structure/` или как
|
||||
назовёшь).
|
||||
- **Объём читателей номеров в паке 1 — РОВНО СУЩЕСТВУЮЩИЙ** (арабские + CJK). Схема данных пишется
|
||||
под общий случай, но **римские/словесные читатели НЕ строятся** — их заказывает пак 2, если замер
|
||||
покажет нужду.
|
||||
|
||||
⛔ **ВЕРСИОНИРОВАНИЕ — ТОЧНО, иначе воспроизводится F1 MAJOR (D39.122).** Данные структуры решают
|
||||
ГРАНИЦЫ ⇒ обязаны войти в **`cutInputs`** (`manifest.go:240-255`) ⇒ двигают **`cutTag`** ⇒ двигают
|
||||
**unit-id**. `manifestKey` фолдит компоненты ПОРОЗНЬ (`manifest.go:336-354`), и одного его
|
||||
НЕДОСТАТОЧНО: правка данных перережет книгу, а id юнитов переживут — ровно тот дефект, ради которого
|
||||
тег и заведён. **В снапшот волн — НЕ класть.** Тест `TestEveryCutInputMovesTheTag`
|
||||
(`cuttag_test.go:26`) получает новый компонент.
|
||||
|
||||
**ФОРМА компонента — не на твоё усмотрение, она уже задана прецедентом:**
|
||||
`Structure: <версия парсера> + sha256(байты структурных данных, РЕАЛЬНО загруженных для этой книги —
|
||||
`<source>/structure.txt` либо дефолт по скрипту)`. **Никогда `omitempty`** — дефолт есть всегда.
|
||||
Считается ОДИНАКОВО на пишущем и читающем пути (`runner.go:384-386`: «loaded on BOTH the write path
|
||||
and the read-only path so status/export/report reproduce the identical snapshot»). Это ровно форма
|
||||
`Langpack: r.packVersion()`.
|
||||
|
||||
⛔ **ЧТО НЕ ПЕРЕЕЗЖАЕТ, и это тихая ловушка:** **числительные** (`Zero`/`Digit`/`Unit`/`Magnitude`)
|
||||
**остаются в `data/cjk-section.txt`**. Их читает не только ингест — на них стоят ДЕНЕЖНЫЕ $0-гейты
|
||||
величины чисел (`checks/cheapgates.go:601, 636, 649, 666` — `lang.DefaultCJKSection()`), а это
|
||||
ВЕРДИКТНЫЕ данные, и им место в снапшоте. Уносишь числительные — **молча меняются вердикты гейтов**.
|
||||
Переезжают ТОЛЬКО `marker` / `units` / грамматика шаблона.
|
||||
|
||||
### 2.3 EPUB по стандарту
|
||||
|
||||
- Читать **`nav` (EPUB 3) и NCX (EPUB 2)**; spine — порядок ЧТЕНИЯ, а не оглавление.
|
||||
- Учитывать `linear` и `properties` — сегодня `opfPackage` их не разбирает (`ingest.go:500-509`).
|
||||
|
||||
**Нормализация nav — правилами, а не на усмотрение** (research/27 — материал, не заказ):
|
||||
цели сортируются **по позиции в spine** · цели вне spine или неразрешимые — игнор со счётом ·
|
||||
вложенные `ol` **сплющиваются** (каждая цель — граница; иерархия томов — §5) · дубли целей
|
||||
схлопываются · приоритет **nav → NCX → spine** · nav с нулём разрешимых целей = отсутствует.
|
||||
|
||||
⛔ **ТЕКСТ КНИГИ НЕ ТЕРЯЕТСЯ НИКОГДА** (`D39.205`: пропущенный кусок — критическая поломка):
|
||||
- **служебные документы — НЕ текст книги и исключаются со счётом**, и список ТОЧНЫЙ, потому что
|
||||
наивная форма не сработает: исключаются (1) документ с `properties="nav"`; (2) документы, чья роль — `toc`
|
||||
или `cover` — объявлена **в landmarks (EPUB 3) ЛИБО в OPF `<guide>` через `<reference type=…>`
|
||||
(EPUB 2)**. ⛔ Обе формы обязательны: landmarks — конструкция EPUB 3, **у EPUB 2 nav-документа нет
|
||||
вовсе**, и сессия, проверившая только landmarks, приклеит `toc.xhtml` к главе 1 ровно на том
|
||||
«массовом EPUB 2», которым это правило себя и мотивирует. ⚠ `properties="cover-image"` стоит на ИЗОБРАЖЕНИИ, а не на
|
||||
документе, и среди документов spine не исключит ничего; landmarks — это `<nav epub:type="landmarks">`
|
||||
ВНУТРИ nav-документа, в `properties` их нет. Грепнуть один `properties` и на этом успокоиться —
|
||||
значит приклеить к главе 1 текстовую страницу оглавления (`toc.xhtml` в spine — массовый EPUB 2)
|
||||
и титул. Больше НИЧЕГО не исключается;
|
||||
- ⛔ **`linear="no"` НИКОГДА не начинает главу**, даже если nav на него указывает (сноски,
|
||||
приложения) — прикрепляется к предыдущему по spine;
|
||||
- **непокрытые контент-документы ДО первой цели nav** (титул, обложка-страница) прикрепляются к
|
||||
**ПЕРВОЙ** главе — зеркало правила преамбулы txt;
|
||||
- **остальные непокрытые** — к **предыдущей** главе;
|
||||
- каждое прикрепление считается; число в WARN и в отчёт.
|
||||
|
||||
⚠ **Вырожденный nav — ОЖИДАЕМЫЙ исход пака 1, а не твой баг.** Скрейп с тремя целями на триста
|
||||
документов даст три главы-кита с ярлыком `declared` и огромным счётом прикреплений. Словарь честен,
|
||||
разрез — нет; лечение (валидаторы `runt`/`whale`, кросс-аудит) — пак 2 (§5). **Тревога здесь — СЧЁТ**,
|
||||
и это всё, что от пака 1 требуется. Не лезь чинить кита.
|
||||
|
||||
### 2.4 Словарь: четвёртое значение и КОНКУРЕНЦИЯ свидетелей
|
||||
|
||||
**Словарь: `declared` · `delimited` · `detected` · `none`.**
|
||||
|
||||
- `declared` — формат утверждает СТРУКТУРУ ГЛАВ (nav/NCX).
|
||||
- **`delimited` (новое)** — в файле был РАЗДЕЛИТЕЛЬ, но «это глава» — допущение движка. Сюда уходят
|
||||
**и EPUB-spine, и `\f` в txt**: spine объявляет порядок чтения, form feed — разрыв СТРАНИЦЫ.
|
||||
⚠ Реальный источник `\f` — не человек, а извлечение из PDF (`pdftotext` ставит его на каждом
|
||||
разрыве страницы по умолчанию).
|
||||
- `detected` — движок вывел границу из СОДЕРЖИМОГО.
|
||||
- `none` — свидетеля нет (и при <2 главах — уже так).
|
||||
|
||||
⛔ **КОНКУРЕНЦИЯ вместо сложения — заказанная СМЕНА ПОВЕДЕНИЯ.** Сегодня txt режется по `\f`, а
|
||||
ПОТОМ каждая часть — по шапкам (`ingest.go:159-167`), пути СКЛАДЫВАЮТСЯ. Заказано: **есть шапки →
|
||||
режем по шапкам, книга `detected`; шапок нет → режем по `\f`, книга `delimited`.** Смешанного случая
|
||||
не остаётся **по построению**, агрегировать нечего, `structureOf` сводится к «`none` при <2 главах,
|
||||
иначе свидетель победившего пути».
|
||||
|
||||
⛔ **И ГЛАВНОЕ — ЧТО С БАЙТАМИ ПРОИГНОРИРОВАННОГО `\f`.** `text.NormalizeSource` form feed **не
|
||||
трогает** (`ingest.go:44-46`). Сегодня он до провода не доходит, потому что он и есть символ разреза;
|
||||
после конкуренции проигнорированный `\f` **останется в тексте главы** и уедет модели, в контент-хеш
|
||||
и в чекеры. ⇒ **игнорируемый `\f` заменяется на разрыв абзаца (`\n\n`) в ингесте, до нормализации**,
|
||||
и считается.
|
||||
|
||||
**Слабость выражается СЧЁТОМ, не классом:** `form feeds ignored: N`, `documents attached: M` — в WARN
|
||||
и в отчёт, **НЕ в манифест**: потребителя на проводе у счёта сегодня нет, а поле без потребителя —
|
||||
механизм ради галочки.
|
||||
|
||||
⚠ **Провенанс — свойство ГРАНИЦЫ.** Глав N, границ N−1; у первой главы открывающей границы нет.
|
||||
⚠ **ПРАВИЛО ПРЕАМБУЛЫ ЗАМОРОЖЕНО:** текст до первой шапки сливается в главу 1, и код объясняет
|
||||
зачем — «dense numbering aligns with the section numbers», «第一节» обязано быть главой 1
|
||||
(`splitTextChapters`, `ingest.go:265-270`). Не трогать: правка сдвинет нумерацию ВСЕЙ стенд-книги.
|
||||
⚠ Следствие, которое надо знать, а не чинить: у главы 1 шапка стоит НЕ в её начале, значит
|
||||
`title_raw` главы 1 берётся из проглоченной шапки.
|
||||
|
||||
### 2.5 `title_raw` и карта сдвигов
|
||||
|
||||
- **`title_raw`** едет по проводу **аддитивно**. Определение: **строка шапки как в источнике** (txt)
|
||||
/ **`navLabel` дословно** (EPUB). ⛔ Обоснование — собственное: заголовок, не едущий по проводу,
|
||||
невозможно отрендерить. **НЕ ссылаться на «шесть заголовков из семнадцати»: у числа нет носителя**
|
||||
(эррата 05.09-е).
|
||||
- ⛔ **ПОНИЖЕНИЕ подзаголовка в прозу (`chunker.go:155-177`) НЕ ТРОГАТЬ.** Снимешь — изменятся чанки
|
||||
и модель перестанет переводить подзаголовок. `title_raw` добавляется РЯДОМ, не вместо.
|
||||
- ⚠ В EPUB-экспорт и в `nav` `title_raw` в этом паке НЕ входит — он на языке источника.
|
||||
- ⛔ **БАМП `chunkerVersion` — ОДИН РАЗ, И ЭТО ЗАКАЗАНО ЯВНО.** Пак меняет РАЗРЕЗ (EPUB spine→nav,
|
||||
конкуренция `\f`), а правило ингеста по конвенции покрывается `chunkerVersion` (`text/source.go`:
|
||||
«covered by chunkerVersion (a deliberate re-translation, not a silent one)»). Забыть бамп —
|
||||
оставить протухший манифест выглядящим текущим.
|
||||
⇒ `chunker_version` уезжает в снапшот, и **голден краснеет: `testdata/golden/capture.golden`
|
||||
несёт ЧЕТЫРЕ строки `chunker_version`** (проверено `grep -c`).
|
||||
**Голден пере-захватывается ОДИН раз, в самом конце, и ТОЛЬКО после того, как ты предъявишь пин:
|
||||
разрез самого голдена не изменился** (его фикстура — ja-txt с `第一章`, форм-фидов ноль).
|
||||
Объявление по D39.183 обязательно.
|
||||
⚠ Без этого абзаца ты упёрся бы в красный голден и по §7 обязан был бы остановиться и пинговать —
|
||||
поэтому он здесь: правка ЗАКАЗАНА.
|
||||
- **Карта сдвигов — МАШИННАЯ (JSON), set-diff по id и номеру: `same/moved/gone/new`.** Прозой нельзя:
|
||||
на прозе не построить мигратор потом. Мигратор в пак НЕ входит — **пак производит УЛИКУ, а не
|
||||
ремонт**, и это сказано вслух.
|
||||
|
||||
---
|
||||
|
||||
## 3. ГЕЙТ ЛЕНДИНГА
|
||||
|
||||
**Зелено, если выполнено ОДНО из двух:**
|
||||
|
||||
- **(а)** разрез стенд-книги воспроизводится **байт-в-байт** против пина §2.1, ЛИБО
|
||||
- **(б)** расхождение **перечислено**, приложена **машинная карта сдвигов**, в отчёте **ЯВНО названа
|
||||
цена: что именно теряется и у кого**, и это **подписано владельцем**.
|
||||
|
||||
⛔ **Почему не только (а).** Чистое «байт-в-байт» защищало бы ОШИБКИ нынешнего разреза: правильный
|
||||
детектор чинит главы-огрызки, а гейт бы его за это не пустил. Это **девятая форма ложной зелени —
|
||||
гейт, ЗАЩИЩАЮЩИЙ дефект** (`D39.202`). ⚠ Такого детектора **в паке 1 нет** (он в §5, пак 2) — довод
|
||||
объясняет ФОРМУ гейта на будущее, а не заказывает тебе детектор.
|
||||
|
||||
⚠ **Ветка (б) честна ровно наполовину, и это записано сознательно:** мигратора окон банка нет, и пак
|
||||
его не строит. Сдвиг окна = новый `TermID` = каскад на решения владельца в платформе. Поэтому (б)
|
||||
обязывает НАЗВАТЬ потерю, а не починить.
|
||||
|
||||
⚠ **Поток подписи — не твой.** Ты сдаёшь карту и названную цену в отчёте; **оркестратор несёт
|
||||
владельцу; лендинг — после его слова.** Не жди сам и не «подписывай» сам.
|
||||
|
||||
⚠ **ГЕЙТ ПРИМЕНЯЕТСЯ ТОЛЬКО К 蛊真人** — под ней подписанный банк владельца (окна в ординалах глав). **EPUB владельца
|
||||
под гейт НЕ попадают: их разрез ОБЯЗАН измениться (spine → nav), это и есть заказ пака.** Для них
|
||||
ветка (а) провалена по построению, и требовать под них подпись владельца бессмысленно. Они — прибор
|
||||
§2.1 п.3: их новый разрез **ИЗМЕРЯЕТСЯ и идёт в отчёт числом**, а не гейтится.
|
||||
|
||||
⚠ **Ожидаемый исход для 蛊真人 — ветка (а).** В паке 1 её разрез может сдвинуть только
|
||||
`\f`-конкуренция. Ветка (б) существует на случай, если `\f` там окажется.
|
||||
|
||||
---
|
||||
|
||||
## 4. САМОПРОВЕРКА — ИСПОЛНЕНИЕМ, И ВЕЕР НАПРАВЛЕН
|
||||
|
||||
Самоотчёт «проверено» без исполнения регулярно оказывается ложным. После кода — **адверсариальный
|
||||
проход по СВОЕЙ готовой работе**. Глубину и веер выбираешь ты; направление — вот что уязвимо здесь:
|
||||
|
||||
1. ⛔ **Резка xhtml по якорям `nav`** (несколько глав в одном файле) — самое уязвимое место пака.
|
||||
У `extractXHTML` **не меньше четырёх пинов байт-паритета** (`ingest_test.go:323, 359, 423, 467`:
|
||||
void-теги, несбалансированный ruby, raw-text-элементы, голый амперсанд). Ошибка здесь ТИХАЯ,
|
||||
и ломает она именно их.
|
||||
2. **Загрузчик структуры обязан достигать книги БЕЗ пар-пака** — тест на книгу без `langpack_root`.
|
||||
3. **Данные структуры реально двигают `cutTag`** (и через него unit-id) **и в payload `manifestKey` (`manifest.go:336-354`), и НЕ
|
||||
двигают снапшот волн** — тест на каждое из трёх.
|
||||
4. **Байты игнорируемого `\f`** — тест, что в тексте главы его не остаётся.
|
||||
5. **Выравнивание `title_raw` с ПЛОТНОЙ нумерацией** — тест с ПУСТОЙ главой между двумя непустыми:
|
||||
пустая глава номер не потребляет, а `title_raw` поедет параллельным срезом, и промах на одну
|
||||
позицию даст заголовок главы N на главе N+1 **молча**. Тот же класс уже чинили для ruby
|
||||
(`ingest.go:568-605`, `denseNo`).
|
||||
6. **Именованный артефакт:** посади дефект в разбор `nav` так, чтобы одна глава потерялась молча,
|
||||
и предъяви **имя покрасневшего теста**. Не краснеет ничто — это находка, а не повод двигаться.
|
||||
|
||||
⚠ **Каталог мутаций** (`backend/cmd/tmmutate`): `-root` обязан быть КОПИЕЙ; копия вне git ⇒
|
||||
`GOFLAGS=-buildvcs=false`. **Не работай под `/tmp`:** посторонний `/tmp/.git` ломает `go build`
|
||||
всему, что там собирается, и уже дал этой смене ложную зелень.
|
||||
|
||||
---
|
||||
|
||||
## 5. ГРАНИЦЫ — ЧЕГО В ЭТОМ ПАКЕ НЕТ
|
||||
|
||||
Названо, чтобы не открылось по ходу и не было сделано «по здравому смыслу»:
|
||||
|
||||
- **Лексиконы не-CJK, корпус, ЗАМЕР оракулом, сбор файлов, сеть** — пак 2. Пак 1 ничего не собирает.
|
||||
- ⛔ **Структурные валидаторы (монотонность номеров, коридор hits/объём, headSpread, runt/whale) —
|
||||
ПАК 2.** В паке 1 живёт только уже построенный пол ≥2. **Причина не стилистическая:** у стенд-книги
|
||||
нумерация СБРАСЫВАЕТСЯ по томам (`eval/dovodka/narezka.py:18`), и валидатор монотонности отверг бы
|
||||
или перекроил её шапки — то есть уронил бы гейт §3 на верной книге.
|
||||
- **Индуктор скелетов строк** — пак 2, и только если замер покажет нужду.
|
||||
- **Мигратор** окон банка, `chunk_status`, `unit_resolutions` — не здесь (строка 298, D15.2).
|
||||
- **Идентичность по ИСХОДУ** (`cutTag` как дайджест нарезки) — свой пак. Здесь только сравнение
|
||||
манифестов до/после в приборе шага 0.
|
||||
- **Публикация провенанса по главе, `kind`, вердикт качества, иерархия томов, print-TOC-линковка,
|
||||
`split/merged` в карте** — не строить. Потребителя нет, фронт заморожен.
|
||||
- **FB2** — только если владелец скажет, что у беты есть FB2-источники.
|
||||
- **Платформенное:** предикат «двух свидетелей» и `structure_version` · снятие временного правила
|
||||
по `declared` (строка 297) · глагол «перечитать журнал» — **всё это НЕ твоя зона.** Не добавляй
|
||||
полей «для платформы».
|
||||
- ⛔ **Рендер при сбросе нумерации по томам — ВОПРОС ВЛАДЕЛЬЦА, не чинить.** Ты УВИДИШЬ в `nav`
|
||||
платного EPUB несколько глав с одним номером. Это выбор рендера (номер книги против плотного
|
||||
ординала), он вне пака. Увидел — запиши числом в отчёт и иди дальше.
|
||||
- **`narezka.py` полигона** (второй приватный zh-детектор) — пинг полигону от оркестратора, не твоё.
|
||||
- ⛔ **Сквозного прогона не-CJK НЕ БУДЕТ и не заказывается:** промтов пары для en/ja не существует
|
||||
(`backend/prompts/` — только `zh-ru`). Не-CJK путь проверяется **только на уровне ingest/manifest,
|
||||
$0**. Не пытайся «доказать бету» — не сможешь, и это не твой дефект.
|
||||
|
||||
---
|
||||
|
||||
## 6. ОБЯЗАТЕЛЬСТВО, КОТОРОЕ ПАК ДАЁТ ПЛАТФОРМЕ
|
||||
|
||||
**Пак НЕ бампает `manifestVersion`.** Значения и поля аддитивны; платформа игнорирует неизвестные
|
||||
поля и деградирует на неизвестных значениях. Бамп понадобился бы, только если читатель прочтёт
|
||||
документ **как текущий и НЕВЕРНО**: единица без плотного номера или с дубликатом · тотал, не равный
|
||||
списку · пустой id · смена ФОРМЫ id.
|
||||
|
||||
⇒ **Граница обязательства: каждая единица манифеста нумерована ПЛОТНО и 1-based.** «Фрагмент» —
|
||||
атрибут нумерованной единицы, а не отсутствие номера.
|
||||
⚠ Контракт при этом обещает `number: null` как законный — и **шов его отвергает**; противоречие
|
||||
записано эрратой 05.09 в `openapi.yaml`. Снимать его — не в этом паке.
|
||||
|
||||
⚠ **Стыковка с платформой — предусловие ЛЕНДИНГА и забота ОРКЕСТРАТОРА, не твоя** (`platform/` —
|
||||
чужая зона). От тебя нужно одно: **сдать в отчёте манифест-фикстуру со значением `delimited`**,
|
||||
чтобы платформенный тест мог на ней проверить деградацию в «знаки».
|
||||
|
||||
---
|
||||
|
||||
## 7. ДИСЦИПЛИНА
|
||||
|
||||
- **Доступ к книгам.** `books/` — симлинк в соседнее дерево. **ЧИТАТЬ файлы под `books/` РАЗРЕШЕНО
|
||||
и необходимо** (§2.1 без этого неисполним). ⛔ **ЗАПРЕЩЕНО:** любая запись под `books/`, любые
|
||||
git-операции там, и что-либо ещё в `/home/ubuntu/projects/textmachine` вне `books/`.
|
||||
- **Тесты и гейты не подгонять под зелень.** ⚠ Правка, вызванная **заказанной** сменой поведения, —
|
||||
обслуживание. **Заказанные здесь правки тестов, поимённо:**
|
||||
· `priceprojection_test.go:144` — кейс «a form feed is the format speaking» ждёт
|
||||
`StructureDeclared`; **станет `delimited`**;
|
||||
· тест V2-7 «формат провёл ВСЕ границы» — меняются ДВА кейса, не один: «один случайный `\f`
|
||||
среди шапок» (шапки побеждают, книга `detected`) **и ПЕРВЫЙ кейс `ingest_test.go:68`
|
||||
«the format drew every boundary» (`ГЛАВА A\fГЛАВА B` → `StructureDeclared`), который становится
|
||||
`delimited`**. ⛔ И **само имя** `TestTXTStructureIsDeclaredOnlyWhenTheFormatDrewEVERYBoundary`
|
||||
после конкуренции ни во что не разрешается — **переименовать тем же актом** (класс строки 299,
|
||||
который этот же промт требует ниже для комментариев);
|
||||
· `ingest_encoding_test.go:218-227` (GB18030, `第一章…\f第二章…`) — **счёт глав сохранит** (две
|
||||
шапки побеждают), но его **комментарий про разрез по `\f` станет ложью** — поправить текст
|
||||
комментария, это класс строки 299;
|
||||
· ⚠ `TestIngestTXTFormFeedChapters` (`ingest_test.go:34-46`) проверяет разрез `A\fB\fC`, где шапок
|
||||
нет — **при конкуренции НЕ меняется**, меняется только ярлык на `delimited`. Не «чини» его.
|
||||
**Каждая такая правка ОБЪЯВЛЯЕТСЯ в отчёте:** что изменилось в поведении, какой тест это описывал,
|
||||
куда уехала гарантия. Не заказано и не ратифицировано — **пинг, не правка**.
|
||||
- **Комментарии, описывающие сменённое поведение, — тоже носители.** Правь их вместе с кодом; в
|
||||
частности протухает `bookfile/epub.go:15-19` («ридер делает главу из КАЖДОГО документа spine»).
|
||||
Это класс строки 299 — имя или утверждение, которое больше ни во что не разрешается.
|
||||
- **Не хакать вокруг ошибки.** Нашёл дефект в чужой зоне — опиши, не чини.
|
||||
- **Никогда не читать `.env`.** PUML не рендерить. **Не коммитить.** Не двигать HEAD. Не трогать
|
||||
чужое незакоммиченное. ⚠ Якорный линт доков (`docs/scripts/counts.py --lint`) — гейт ОРКЕСТРАТОРА;
|
||||
доки с якорями ты не пишешь, но знай, что он есть, и не строй второй такой.
|
||||
- **Утверждение о замере — с КОМАНДОЙ** (`D39.207` п.5): пишешь «проверено» или «не проверено,
|
||||
потому что X» — рядом стоит команда, которой это показано.
|
||||
- ⛔ **Идентификатор, не виденный ЦЕЛИКОМ в выводе команды, не воспроизводить по памяти** — ни хеш,
|
||||
ни номер строки. Обрезающий `cut`/`head` молча превращает улику в догадку (`research/29` §5.6:
|
||||
так был сфабрикован sha256, совпавший на 52 знака из 64).
|
||||
|
||||
---
|
||||
|
||||
## 8. ЧТО ПРИСЛАТЬ И В КАКОМ ПОРЯДКЕ
|
||||
|
||||
1. **Эхо старта:** своими словами — что понял предметом и что считаешь границей. До кода.
|
||||
2. **Записка-план** в отчёт: что делаешь, в каком порядке, и **чем сдача осмысленна, если тебя
|
||||
оборвут на середине**. До кода.
|
||||
3. **Замеры шага 0 — числами**, до правок.
|
||||
4. Код.
|
||||
5. **Отчёт:** батарея (команда, скипы числом, EXIT) · каталог · посадка именованного артефакта
|
||||
(`file:line` · что подменено · **какое ИМЯ теста покраснело**) · объявления по D39.183 · счета
|
||||
`form feeds ignored` / `documents attached` · манифест-фикстура с `delimited` · что НЕ проверено
|
||||
и почему.
|
||||
|
||||
⚠ **Споткнулся о невыполнимое, о противоречие в самом задании или о нехватку доступа — пиши сразу,
|
||||
не обходи молча.** Обход тихо становится нормой, и следующая смена наследует его как факт.
|
||||
Loading…
Add table
Reference in a new issue