Give the contract's anchors their tokens and move eleven of them onto the lines their prose quotes

This commit is contained in:
heaven 2026-09-16 18:42:37 +03:00
parent f6e304ef78
commit 3251aec90e

View file

@ -156,16 +156,16 @@ cmp-сверка обязательна (D39.138 п.3).
### 2.1. Язык — код, никогда не имя — ✓ выведено
Движок держит коды (`backend/internal/config/book.go:26-27`), ключ пары — `zh-ru`
Движок держит коды (`backend/internal/config/book.go:26-27`=`SourceLang string`), ключ пары — `zh-ru`
(`configs/langpacks/zh-ru/`). Имя языка в данных — пар-специфика в общем слое, запрещённая §2
канона. Вторая цена, дороже: `lang` элемента берётся из данных книги, и пара ja→ru с именем вместо
кода отрисует кандзи китайскими начертаниями молча.
**0.3.0 дополнил:** форма кода — не то же, что умение пары. Платформа проверяет только ФОРМУ
(`platform/internal/books/books.go:118-121`) и равенство `source == target` не проверяет никто, а
(`platform/internal/books/books.go:118-121`=`books: the intake form is not usable`) и равенство `source == target` не проверяет никто, а
пар-промпты в репозитории есть ТОЛЬКО для `zh-ru`; отсутствие промпта пары — жёсткая ошибка
конфигурации, не деградация («no prompt for pair %q role %q … never silently substitute another
pair's conventions», `backend/internal/config/pipeline.go:952-956`). До 0.3.0 книга в
pair's conventions», `backend/internal/config/pipeline.go:1038`=`no prompt for pair` — ⚠ испр. 16.09: было :952-956). До 0.3.0 книга в
неподдерживаемой паре принималась, ложилась на диск, разбиралась, проводила пользователя через
денежный экран — и умирала на старте прогона без причины. Отсюда `Capabilities.language_pairs[]`
со статусом и код отказа на интейке (`errors[].code: unsupported_pair`).
@ -173,8 +173,8 @@ pair's conventions», `backend/internal/config/pipeline.go:952-956`). До 0.3.0
### 2.2. Идентификаторы непрозрачны — ✓ выведено, классы стабильности разведены в 0.3.0
`glossary.id` — свежий автоинкремент на каждой пересборке банка и намеренно не хешируется
(`store/migrate.go:173-174`); номер главы плотный, «Chapters that yield no text … do NOT consume a
chapter number» (`chunk/chunker.go:99-105`), поэтому правка исходника сдвигает номера последующих
(`backend/internal/store/migrate.go:173-174`=`glossary.id is a fresh autoincrement each replace`); номер главы плотный, «Chapters that yield no text … do NOT consume a
chapter number» (`backend/internal/chunk/chunker.go:99-105`=`Chapters that yield no text`), поэтому правка исходника сдвигает номера последующих
глав.
**0.3.0:** одно предложение «Stability across runs is the platform's job» покрывало пять сущностей
@ -189,7 +189,7 @@ the book, while chapter ids survive» (`backend/internal/pipeline/manifest.go:18
**Движок сегодня делает ОБРАТНОЕ**, и это надо назвать прямо: титул рендерится детерминистически из
шаблона пары (`configs/langpacks/zh-ru/heading.txt`), исходный маркер вырезается из текста для модели
(`chunk/chunker.go:110-114`), а на экспорте титул вклеивается внутрь текста первого юнита
(`backend/internal/chunk/chunker.go:110-114`=`SplitChunksWithChapters is SplitChunks plus`), а на экспорте титул вклеивается внутрь текста первого юнита
(`backend/internal/pipeline/export.go:219`=`newestStatusWrite renders the newest updated_at` — ⚠ испр. 16.09: было :215). Комментарий движка прямо запрещает подавать этот рендер как метку книги
(`backend/internal/pipeline/manifest.go:80-86`=`A POINTER, AND THAT IS THE WHOLE COST OF BEING ADDITIVE`). Развилка — К-2.
@ -212,9 +212,9 @@ the book, while chapter ids survive» (`backend/internal/pipeline/manifest.go:18
### 2.4. Состояние — у прогона; у главы выполнение — ✓ выведено
Подпись банка это один стоп на всю книгу (`pipeline/mining.go:81,243`), поэтому «глава ждёт подписи,
Подпись банка это один стоп на всю книгу (`backend/internal/pipeline/mining.go:57`=`func (r *Runner) runBankMiningStop` — ⚠ испр. 16.09: было :81,243), поэтому «глава ждёт подписи,
пока соседняя финализируется» — невозможная картина. У главы движок держит `ChapterPassport`
(`pipeline/status.go:37-55`).
(`backend/internal/pipeline/status.go:37-55`=`how a consumer tells "no such phase"`).
### 2.5. Прогресс — ОДНА полоса до ближайшей остановки, в главах (0.3.0) — ◆ решение владельца
@ -266,7 +266,7 @@ SQL и до 0.3.0 не отдавалась: `b.chapter_count - (select count(*)
Лестница «загрузка → разбор → перевод → подпись банка → финал → готово» пришла из строки 95.
`stopped`, `rejected`, `not_started` контракт ВЫВОДИТ из поведения процесса, а не получает полем:
механика стопа у движка есть (`cmd/tmctl/main.go:63`), но «кто нажал» знает платформа.
механика стопа у движка есть (`backend/cmd/tmctl/main.go:98`=`bank-mining signature stop` — ⚠ испр. 16.09: было :63), но «кто нажал» знает платформа.
**Стоп по потолку — не `failed`** ✓ выведено: «Ceiling is a hard, book-wide stop … the job stays
'pending' and resume continues once the ceiling is raised» (`backend/internal/pipeline/stagerun.go:639`=`resume continues once the ceiling is raised` — ⚠ испр. 16.09: было :488-489).
@ -289,7 +289,7 @@ SQL и до 0.3.0 не отдавалась: `b.chapter_count - (select count(*)
### 2.7. Состояние пары выводится из ПАРЫ — ✓ выведено
Флагнутый юнит легально приходит С ТЕКСТОМ в двух случаях: косметическая зачистка санитайзера («the
chunk is NOT lost — the cleaned text is committed as the export», `pipeline/disposition.go:96-104`) и
chunk is NOT lost — the cleaned text is committed as the export», `backend/internal/pipeline/disposition.go:160`=`the cleaned text is committed as the export` — ⚠ испр. 16.09: было :96-104) и
c-lite member-drop (`pipeline/export.go:203-207`). Поэтому состояние выводится из ПАРЫ (вердикт +
наличие финального текста): флаг+текст → `translated` с замечанием; флаг+пусто → `withheld`.
@ -312,8 +312,8 @@ drop юнит несёт причину ПЕРВОГО выпавшего чле
| Поле | Словарь 0.3.0 | Что было у движка | Грунт |
|---|---|---|---|
| `status` | `proposed · in_progress · approved` | `auto · draft · approved` | `store/migrate.go:191`; только `approved` — канон |
| `kind` ◆ | `name · place · title · term · nickname` **плюс `null`** | то же | `terminology/classify.go:27` (`CandidateTypes` — единственный носитель `nickname`; ⚠ испр. 07.09: прежние `classify.go:15` + `banknote.go:74` мертвы — `Types` не несёт `nickname`, а `bankTypeOK` снесён паком «гейт вместо прозы» и сведён к `CandidateTypes`); пустое — `membank/memseed.go:323-326` |
| `status` | `proposed · in_progress · approved` | `auto · draft · approved` | `backend/internal/store/migrate.go:192`=`auto|draft|approved (term status machine` — ⚠ испр. 16.09: было :191; только `approved` — канон |
| `kind` ◆ | `name · place · title · term · nickname` **плюс `null`** | то же | `backend/internal/terminology/classify.go:27`=`var CandidateTypes = map[string]bool` (`CandidateTypes` — единственный носитель `nickname`; ⚠ испр. 07.09: прежние `classify.go:15` + `banknote.go:74` мертвы — `Types` не несёт `nickname`, а `bankTypeOK` снесён паком «гейт вместо прозы» и сведён к `CandidateTypes`); пустое — `membank/memseed.go:323-326` |
| `origin` | `given · annotated · found` | `seed · ruby · mined` | пути записи, см. ниже |
| `sense` | свободный текст, пустая строка = «нет различителя» | то же | `store/migrate.go:182` |
| окно | `since_chapter`/`until_chapter`, **`null` = без границы** | целые, `0` = без границы | `store/migrate.go:189-190` |
@ -359,7 +359,7 @@ drop юнит несёт причину ПЕРВОГО выпавшего чле
Конвейер заменяет банк целиком (`store/migrate.go:169-170`), поэтому `PATCH /term/{id}` молча не
работает. Механика дословно: «for EACH term either promote it into the mined-delta file OR decline it
in the mined-rejects file, then resume» (`pipeline/mining.go:81,243`; ⚠ фраза «the stop clears once
in the mined-rejects file, then resume» (`backend/internal/pipeline/mining.go:57`=`func (r *Runner) runBankMiningStop` — ⚠ испр. 16.09: было :81,243; ⚠ фраза «the stop clears once
every proposed term is promoted or rejected» ОПРОКИНУТА D39.144 — движок авто-продолжает с
неподписанным, D39.42 п.3). Отсюда живое: решение на термин · информационный счётчик «решено N из M»
· частичное сохранение ◆. Запрет «продолжить» при неполном наборе — СНЯТ (подпись = один resume).