From 3251aec90ee6ac82a7c7e417abf332f63e29eb73 Mon Sep 17 00:00:00 2001 From: heaven Date: Wed, 16 Sep 2026 18:42:37 +0300 Subject: [PATCH] Give the contract's anchors their tokens and move eleven of them onto the lines their prose quotes --- docs/architecture/14-api-contract/README.md | 26 ++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/architecture/14-api-contract/README.md b/docs/architecture/14-api-contract/README.md index 36d62748..575b7173 100644 --- a/docs/architecture/14-api-contract/README.md +++ b/docs/architecture/14-api-contract/README.md @@ -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).