From 02a732900a72c8e2f7392dd940c8e6c362c65c29 Mon Sep 17 00:00:00 2001 From: heaven Date: Sun, 30 Aug 2026 23:58:24 +0300 Subject: [PATCH] Move both lived pack dumps into the backend archive slice: a quarter of the journal was evidence already ratified in note bodies --- docs/PROGRESS.md | 491 +---------------------- docs/archive/PROGRESS-2026-08-backend.md | 491 +++++++++++++++++++++++ 2 files changed, 495 insertions(+), 487 deletions(-) diff --git a/docs/PROGRESS.md b/docs/PROGRESS.md index e82cd9c1..c71ea3b0 100644 --- a/docs/PROGRESS.md +++ b/docs/PROGRESS.md @@ -281,493 +281,10 @@ > порча» — `D39.164` (`7d0c6f2`), пак «деньги» — `D39.170`, гейт схемы — `D39.173`. -### 📝 ЗАПИСКА-ПЛАН — пак «писатель книги» (промт `docs/archive/prompts/BACKEND_BOOKWRITER_PACK_SESSION_PROMPT_2026-08-30.md`, строка 236), сессия `textmachine-main-fc`, 30.08 - -**Что беру (зона `backend/`, HEAD на старте `67c05be`, дерево чисто).** -1. Прод-пакет `backend/internal/bookfile` (только stdlib — `archive/zip`, `encoding/xml`; без `import "testing"`): - `container.go` — OCF-контейнер (`mimetype` первым и `zip.Store`, `container.xml`, запись entry в порядке вызовов, - нулевые таймметки) — `chunktest/epub.go` переводится на него, его OPF-заглушка и XHTML-декой остаются тестовыми; - `epub.go` — EPUB 3 из нейтральной модели `Book{Identifier, Title, Language, Modified, Description, - Chapters[]{Title, Paragraphs[]}}`: `dc:identifier`/`dc:title`/`dc:language`/`dcterms:modified`, nav - (`properties="nav"`, ⛔ НЕ в spine), один XHTML на главу, `

` = заголовок главы, `

` = абзац; - `txt.go` — чистый текст из той же модели (заголовок строкой, абзацы через пустую строку, главы через - пустую строку; ни баннеров, ни флагов, ни `gapMarker`). -2. Сборка из `BookExport` — `backend/internal/pipeline/bookbuild.go`: `Runner.BuildBook(formats, partial)` → - `Export(false)` → дыры → отказ либо файл. Запись `writeFileAtomic` рядом с ProjectDB - (`.book.`, как `.manifest.json`/`.bank.json`), путь публикуется в - `StatusArtifacts.BookFiles` (`book_files`: map формат→путь, аддитивно) — приор промта принят: платформа - пути не выводит сама (17 §1). Существующий файл — перезапись: производный детерминированный артефакт, как - манифест; бэкап отказывает потому, что он точка восстановления, а файл книги пересобирается из стора. -3. Аддитивные поля `tm-export-v1` (форма не меняется, все `omitempty`): `ChunkExport.Heading` (`heading`) — - литерал `u.Members[0].Heading` в момент сборки записи (и у pending-юнита тоже, он из манифеста); - `BookExport.GhostUnits` (`ghost_units`: `[{chapter,chunk_idx}]`) — ключи ghost-строк, чтобы маркер стоял - в главе, а не только в счётчике; `BookExport.TextModified` (`text_modified`, `CCYY-MM-DDThh:mm:ssZ`) — - max(`chunk_status.updated_at`) по финальным строкам, вошедшим в файл (колонка `NOT NULL DEFAULT - datetime('now')`, `store/migrate.go:37`; в `ChunkStatus` дочитывается доп. полем). Это и есть - `dcterms:modified`: последнее изменение отгруженного текста — факт стора, не часов процесса. -4. Глагол `tmctl build --config b.yaml [--format epub,txt] [--out path] [--partial]` (по умолчанию оба формата; - `--out` — только при одном формате). Stdout — JSON-конверт `tm-build-v1` (пути, счётчики, `complete`). - Новый глагол, а не флаг `export`: `export` — чистое чтение в stdout, писать файлы из него — смешать - аудит-проекцию с артефактом; `manifest` — прецедент глагола-писателя сайдкара. `dispatchCommands` и - usage-строка расширяются — контрактное расширение того же рода, что `bank-apply` (тест - `TestParseNoArgsUsage` сам перечисляет такие расширения); чужим глаголам новые флаги ОТКАЗЫВАЮТСЯ - (дисциплина `--keys-file`/`--max-units`). -5. Отказ — новый `pipeline.RefusalBookIncomplete = "book_incomplete"` → exit **16** (полоса 10–19; таблица - тотальна по `TestTheRefusalTableIsTotal`); сообщение перечисляет дыры `глава/юнит/причина`. -6. Читательские слова — ДАННЫЕ: `//reader.txt` (`keyvalue`, плейсхолдеры - `{chapter} {unit} {dropped} {holes} {total} {ghost}`), читает ОТДЕЛЬНЫЙ загрузчик `lang.LoadReaderWords`; - в `Pack.Version()` НЕ фолдится (пин тестом «наличие reader.txt не меняет Version()» + `current_snapshot` - minirun до/после). Ключ — язык ЦЕЛИ, не пара: слова читает читатель целевого языка, и они не зависят от - исходного. Поставляю `backend/configs/langpacks/ru/reader.txt`. Каталог `/` загрузчик пака не - читает (`Load` — только `/` и `/`, `langpack.go:215-330`), так что канал вне фолда по - построению, а не по соглашению. - -**Политика §3.2 — по умолчанию ОТКАЗ, `--partial` — файл с пометкой; довод:** -- Дыры: pending · withheld (`Disposition!="pending" && FinalText==""`) · incomplete (`DroppedMembers>0` при - непустом тексте) — арифметика `render.go:573-587` выносится в общий хелпер `pipeline`, которым пользуется и - `renderExport` (вывод `--plaintext` побайтово прежний) · **ghost — тоже дыра**: при укрупнении нарезки - строка-лидер несёт текст ПРЕЖНЕГО, более короткого юнита, а остаток источника лежит в ghost-строках и в - файл не попадает (acceptance: 57 строк → 37 юнитов, 20 ghost при `pending 0` — ровно «молча полная» - книга). Позиция ghost внутри главы неизвестна → маркер в конце главы с числом потерянных строк. -- Default = отказ: D29.1(б) — reader-facing выдача fail-closed; дверь платформы получит `--partial` для - контрактного «may be exported, finished or not» (14 §createExport). -- `--partial`: пометка неполноты — первый абзац первого документа spine (то, что читатель видит, открыв - книгу) + `dc:description`; маркер — отдельный абзац на месте КАЖДОЙ дыры (pending/withheld — вместо текста - юнита; incomplete — перед текстом юнита, как `gapMarker`; ghost — в конце главы). Форма — из `reader.txt`; - без пака (acceptance, `runner.go:346`) — несловесная: `⚠ {chapter}.{unit}` у дыры, `⚠ {holes}/{total}` в - пометке (символ + числа, никакого словаря в Go). В `FinalText`/`export.go` маркер не попадает. -- drift — НЕ дыра: текст файла побайтово текст прогона (`export.go`, комментарий к `exportConfigDrift`); - попадает в JSON-конверт `build` и в WARN, в файл — нет («config drift» — операторский словарь). - Следствие §4 заявляю сразу: чистого бездрейфового файла на реальной книге на этом HEAD НЕТ — чистый - путь доказывается синтетикой, реальные книги — посадки на дыры. -- Оглавление и `

` при `Heading==""` — номер главы цифрами (пустая ссылка nav невалидна; цифры — - единственный лейбл, который не решает открытый К-3 «какой лейбл видит читатель у главы без заголовка»; - словесный шаблон в данных — 1 строка после ратификации, вопрос владельцу в отчёте). При `Heading!=""` — - срез известного префикса `heading+"\n\n"` из `FinalText` (`chunker.go:186-192`), `

` = Heading. -- Абзац = непустая строка `FinalText`. Замерено на `minirun/export.json`: юнит 1/0 — 14 разделителей `\n\n` - и 7 одиночных `\n`, юнит 2/0 — 56 и 0: редактор чередует их без семантики, различать = выдумать - различие; строка — единица абзаца исходника-вебновеллы. Круг §4 сравнивает абзацы ингеста с абзацами, - которые положил писатель. -- Метаданные: `dc:title` = `config.Book.Title` как есть (на стенде `蛊真人` — ограничение в отчёт), `dc:language` - = `TargetLang`, `dc:identifier` = `urn:textmachine:book:`, `dc:creator` нет (источника нет). -- 0 юнитов — отказ `sourceHasNoContent` (spine без элементов невалиден); 1 юнит — обычная книга. - -**Что НЕ беру:** платформу и дверь `createExport`/`getExport`; лестницу D25.1 в коде и в `BookExport`; -строки 160/201 (`ApplyHeading` и три точки склейки не трогаю; модельные заголовки в прозе не извлекаю и не -правлю); `--resnapshot` и любые платные вызовы; `langpack_root` в копию acceptance; направление письма -(`dir`/`page-progression-direction`) — в `internal/lang` данных о направлении нет (`lang-script.txt` — -только скрипты), RTL-цели в репо нет → вопрос в отчёт, не литерал; CSS/обложку; новые зависимости. - -**Чем докажу:** герметично — `bookfile` (mimetype первым/stored, nav не в spine, детерминизм двух сборок, -экранирование, 0/1 глава), `pipeline` (круг `IngestEncoded` равенством абзацев на прогоне fake-провайдера; -pending через потолок; withheld через санитайзер; **ghost — усадка исходника после прогона (посадки в -тестах не было, строю)**; drift — бамп `prompt_version`; синтетический `BookExport` на incomplete), `cmd/tmctl` -(incomplete бинарём через `setupGapProject`; парс флагов; exit 16 через totality-тест), `lang` (парс -`reader.txt`; `Version()` не меняется от его наличия). На копиях книг в песочнице с переписанными путями: -minirun — оракул июля 14/14 по `final_text/snapshot_id/disposition`, `current_snapshot` до/после -`reader.txt`, `cmp` двух ПРОЦЕССОВ, epubcheck 5.3.0 `0 fatal / 0 error`, круг ингестом; acceptance — отказ с -перечнем и `--partial`-файл с несловесными маркерами; coldrun-a — отказ 14/14 pending; -`git -C books status --short -- gu-zhenren` до/после одинаков (снят до старта: 6 строк `D …-wal/-shm`). -`make battery` + `-race`; в середине — субагент-ревью готовой части против критериев; в конце — -адверсариальный проход по направлениям §4. - -### ✅ ИТОГ — пак «писатель книги» (промт `docs/archive/prompts/BACKEND_BOOKWRITER_PACK_SESSION_PROMPT_2026-08-30.md`, строка 236), сессия `textmachine-main-fc`, 30.08 - -**Что построено (зона `backend/`, поверх `67c05be`; НЕ закоммичено — дерево на лендинг оркестратору; `git status`: 10 изменённых + 8 новых путей в `backend/`, плюс этот журнал).** -- `internal/bookfile/` (новый прод-пакет, только stdlib, без `testing`): `container.go` — OCF-контейнер (`mimetype` первым, `Store`, через `CreateRaw` — без data-descriptor, флаги `0x0000`; `container.xml`; entry в порядке вызовов; нулевые zip-таймметки); `epub.go` — EPUB 3 (`dc:identifier`+`unique-identifier`, `dc:title`, `dc:language`, `dcterms:modified`, nav `properties="nav"` ⛔ не в spine, XHTML на главу: `

` + `

`); `txt.go` — чистый текст; `model.go` — модель `Book/Chapter`, `Blocks(i)` (единственное определение содержимого документа главы), `CleanText` (общая чистка XML-недопустимых символов для обоих форматов), экранирование. -- `internal/chunk/chunktest/epub.go` переведён на `bookfile.NewContainer`; тест-декои (OPF-заглушка, `c