Ratify the export door as built: the contract gains a minor, the shipping config's bank contour stops being described as off, and the number gate grows two carriers

This commit is contained in:
heaven 2026-09-04 20:23:11 +03:00
parent adf5e53d7e
commit 58bca1949c
12 changed files with 353 additions and 41 deletions

File diff suppressed because one or more lines are too long

View file

@ -23,7 +23,7 @@
|---|---|---| |---|---|---|
| Оркестратор | [ORCHESTRATOR_SESSION_PROMPT.md](ORCHESTRATOR_SESSION_PROMPT.md) | роль и нормы; счётчик роли — CURRENT-STATE | | Оркестратор | [ORCHESTRATOR_SESSION_PROMPT.md](ORCHESTRATOR_SESSION_PROMPT.md) | роль и нормы; счётчик роли — CURRENT-STATE |
| Бэкенд | [BACKEND_WIREBATCH_SESSION_PROMPT.md](BACKEND_WIREBATCH_SESSION_PROMPT.md) | **ВЫДАН 04.09** — вайр-батч «род, экран цели, заголовки инъекций»: строки 210 · 113→46 · 134 · 140 · 184(а) + дофикс чужого пака и ФЧ-7. Пере-снапшот батча ратифицирован единым актом (**D39.190** п.4). Предыдущий пак принят с дофиксом 03.09 (**D39.187**), промт в [archive/prompts/](archive/prompts/BACKEND_CONSENT_SESSION_PROMPT_2026-09-02.md) | | Бэкенд | [BACKEND_WIREBATCH_SESSION_PROMPT.md](BACKEND_WIREBATCH_SESSION_PROMPT.md) | **ВЫДАН 04.09** — вайр-батч «род, экран цели, заголовки инъекций»: строки 210 · 113→46 · 134 · 140 · 184(а) + дофикс чужого пака и ФЧ-7. Пере-снапшот батча ратифицирован единым актом (**D39.190** п.4). Предыдущий пак принят с дофиксом 03.09 (**D39.187**), промт в [archive/prompts/](archive/prompts/BACKEND_CONSENT_SESSION_PROMPT_2026-09-02.md) |
| Платформа | [PLATFORM_EXPORT_SESSION_PROMPT.md](PLATFORM_EXPORT_SESSION_PROMPT.md) | **ВЫДАН 04.09** — «закрыть цикл»: живой ПЛАТНЫЙ сквозной прогон через API (санкция **D39.189**, потолок — грант $1.5, эррата 04.09-а о механизме) · дверь выдачи `createExport`/`getExport` · `PD-424` · дофикс и три райдера. Предыдущий — P13, принят с дофиксом 03.09 (**D39.188**) | | Платформа | активного НЕТ | **ПАК ОТРАБОТАН И ЗАЛЕНДЖЕН 04.09** (`adf5e53`, **D39.194**): цикл замкнут живьём — платный EPUB через API, `epubcheck` 0/0/0/0; контрактный минор **0.10.0** ратифицирован тем же актом. Промт — в [archive/prompts/](archive/prompts/PLATFORM_EXPORT_SESSION_PROMPT_2026-09-04.md) с баннером исхода. ⚠ Следующий пак собирается по двум мажорам, найденным самим прогоном (`PD-440` книгу нельзя дочитать до конца · `PD-441` halt не пишет цену отменённых вызовов) |
| Полигон | [POLYGON_EXP2223_REDO_SESSION_PROMPT.md](POLYGON_EXP2223_REDO_SESSION_PROMPT.md) (отложенный — [POLYGON_PACKAGE4_SESSION_PROMPT.md](POLYGON_PACKAGE4_SESSION_PROMPT.md), строка 85) | фаза Д ИДЁТ; ⚠ живой носитель курса — в `eval/dovodka/`, какой именно называет зона (⚠ [POLYGON_PHASE_D_HANDOFF.md](POLYGON_PHASE_D_HANDOFF.md) — перекрытый снимок, читать не как курс) | | Полигон | [POLYGON_EXP2223_REDO_SESSION_PROMPT.md](POLYGON_EXP2223_REDO_SESSION_PROMPT.md) (отложенный — [POLYGON_PACKAGE4_SESSION_PROMPT.md](POLYGON_PACKAGE4_SESSION_PROMPT.md), строка 85) | фаза Д ИДЁТ; ⚠ живой носитель курса — в `eval/dovodka/`, какой именно называет зона (⚠ [POLYGON_PHASE_D_HANDOFF.md](POLYGON_PHASE_D_HANDOFF.md) — перекрытый снимок, читать не как курс) |
| Фронт | активного НЕТ | **ЗОНА ЗАМОРОЖЕНА** (D39.136 п.2 + D39.147: разморозка отдельным словом владельца, не привязана к P7); перечень первого касания — в зонном журнале | | Фронт | активного НЕТ | **ЗОНА ЗАМОРОЖЕНА** (D39.136 п.2 + D39.147: разморозка отдельным словом владельца, не привязана к P7); перечень первого касания — в зонном журнале |
| Контракт | активного НЕТ | канон — `architecture/14-api-contract/`; ⚠ версию брать ФАЙЛОМ (`grep '^ version:' openapi.yaml`), не отсюда: миноры ратифицируются D-нотами и их содержание грепается по реестру нот. | | Контракт | активного НЕТ | канон — `architecture/14-api-contract/`; ⚠ версию брать ФАЙЛОМ (`grep '^ version:' openapi.yaml`), не отсюда: миноры ратифицируются D-нотами и их содержание грепается по реестру нот. |

View file

@ -5,9 +5,9 @@
| Роль | Модель (слаг) | thinking / effort | Носитель конфига | Статус | Квирки | | Роль | Модель (слаг) | thinking / effort | Носитель конфига | Статус | Квирки |
|---|---|---|---|---|---| |---|---|---|---|---|---|
| **draft** (translator) | `deepseek-v4-flash` | thinking ON, `reasoning:"low"` явно (D39.87/91 «вариант б») | `configs/pipeline-c1.yaml`, стадия `draft` | боевой ИНТЕРИМ (exp13; бейк-офф эксп-22 заленден 10.08 — черновик менять не на что, но выводы заморожены до фазы Д, НЕ ратифицированы) | quirks §0731 п.1 (дефолт-эффорт пробивает флор 8000), п.3а (не слать эффорт = ехать на `high`), п.4 (`low` пере-вооружает эхо), п.6 (эхо стохастично по вызову; ре-ген дешевле эскалации ×7.6). Thinking-OFF — НИКОГДА (эхо-мина, `echoMineViolation`) | | **draft** (translator) | `deepseek-v4-flash` | thinking ON, `reasoning:"low"` явно (D39.87/91 «вариант б») | `configs/pipeline-c1.yaml`, стадия `draft` | боевой ИНТЕРИМ (exp13; бейк-офф эксп-22 заленден 10.08 — черновик менять не на что, но выводы заморожены до фазы Д, НЕ ратифицированы) | quirks §0731 п.1 (дефолт-эффорт пробивает флор 8000), п.3а (не слать эффорт = ехать на `high`), п.4 (`low` пере-вооружает эхо), п.6 (эхо стохастично по вызову; ре-ген дешевле эскалации ×7.6). Thinking-OFF — НИКОГДА (эхо-мина, `echoMineViolation`) |
| **+ банкнота** (WHAT-канал драфта) | та же flash, промпт `translator-banknote.md` | как draft | НЕ в shipping-c1 — ран-локальный конфиг книги: `~/books/gu-zhenren/coldrun-b/pipeline.yaml` (`gates.banknote` + `prompt_override`) | ⚠0731; включение в c1 = СТОП-решение владельца (строка 140: двигает RequestHash) | те же | | **+ банкнота** (WHAT-канал драфта) | та же flash, промпт `translator-banknote.md` | как draft | `configs/pipeline-c1.yaml`, блок `gates.banknote`**ВКЛЮЧЕНА в shipping с `b8154cd`** (`enabled: true` + `prompt_override` на банкнотный промпт стадии draft: гейт лишь СРЕЗАЕТ блок, инструкцию его писать несёт промпт) | ⚠0731; включение в c1 = СТОП-решение владельца (строка 140: двигает RequestHash) | те же |
| **терминолог** | `deepseek-v4-flash` | thinking ON, `gates.terminology.reasoning:"low"` (одна ручка на обе бэнк-роли) | ран-локальный `~/books/gu-zhenren/coldrun-b/reprobe/bank-low/pipeline.yaml:68-78`; схема — `internal/config/pipeline.go:298`=`type TerminologyGate struct` (TerminologyGate); в shipping-c1 гейта НЕТ (opt-in OFF) | боевой по факту прогонов; носитель — конфиг книги | quirks §0731 п.3а: пустой `reasoning` = вендор-`high` → 4/5 `length` с пустым телом; экран `target_script: Cyrillic` обязателен при гейте ON | | **терминолог** | `deepseek-v4-flash` | thinking ON, `gates.terminology.reasoning:"low"` (одна ручка на обе бэнк-роли) | `configs/pipeline-c1.yaml`, блок `gates.terminology`**ВКЛЮЧЁН в shipping с `b8154cd`** (`enabled: true`, `budget_usd: 1.00`); схема — `internal/config/pipeline.go`, греп `type TerminologyGate struct` | боевой по факту прогонов; носитель — конфиг книги | quirks §0731 п.3а: пустой `reasoning` = вендор-`high` → 4/5 `length` с пустым телом; экран `target_script: Cyrillic` обязателен при гейте ON |
| **классификатор** (типы кандидатов) | flash (`classify_model` пуст ⇒ = model) | та же ручка | там же: `classify_types: true` + `classify_budget_usd` | проба/полигон; в shipping выключен ВЕЗДЕ | латентный мис-вердикт `cjk_artifact``13-tech-debt-anchors.md` §Б-105 | | **классификатор** (типы кандидатов) | flash (`classify_model` пуст ⇒ = model) | та же ручка | там же: `classify_types: true` + `classify_budget_usd: 1.00` | **ВКЛЮЧЁН в shipping с `b8154cd`** (прежде — только проба/полигон) | латентный мис-вердикт `cjk_artifact``13-tech-debt-anchors.md` §Б-105 |
| **editor** | `deepseek-v4-pro` **БИЛИНГВ** | thinking ON; `reasoning:"off"` = осознанный NO-OP (ReasoningNone); ⚠ **ручка эффорта у `pro` ЕСТЬ — прежний клейм «ручки НЕТ (`low`→`high`)» СНЯТ 04.09 сверкой с квирк-каноном.** Канон пере-снят полигоном 30.08 живым `curl` (§3а: «ТАБЛИЦА У ВЕНДОРА ИЗМЕНИЛАСЬ, И ЗАПИСЬ НИЖЕ БОЛЬШЕ НЕ ВЕРНА»), а поведенческая проба того же дня (§3г, $0.038276) показала: **параметр `low` на `pro` ТЕПЕРЬ ДОХОДИТ ДО МОДЕЛИ** (79 prompt_tokens). ⚠ **Фиксируем ровно «ручка доходит», НЕ «ручка работает»:** ВЕЛИЧИНА эффекта не установлена (§3д: разброс ×38, причина не установлена), и это живой остаток строки 172(г). ⚠ **НОСИТЕЛИ ПРОТИВОРЕЧАТ, и это НЕ решено:** `PROGRESS.md` утверждает обратное (пинг зоне полигона + строка бэклога **237**(б)): вахта §Б-108 сработала 13.08 changelog'ом вендора — pro/flash получили low/high/max. Кто прав, из репозитория НЕ выводится: замера поведением после 13.08 нет ни у одной стороны. ⚠ **D39.137 про эффорт МОЛЧИТ** (11 строк, ноль упоминаний) — ссылаться на неё как на «ручка появилась 13.08» уже пробовали (испр. №18 20.08): конфабуляция по смежности, `V4-Pro-0813` — чекпойнт ВЕСОВ при вендорском «Model names remain unchanged», а не дата появления ручки. **Закрывается вендор-сверкой, а не выбором стороны**; до неё в силе КАНОН | `configs/pipeline-c1.yaml` блок редактора; floor 16000 — `models.yaml` ключ `deepseek-v4-pro`, поле `min_max_tokens` | боевой ИНТЕРИМ (D30.1/D39.22); D39.117: топология 2-прохода ПОДТВЕРЖДЕНА (`A/F3` +2.50 Holm 0.0004), жильцы dspro/glm-5 неразличимы ⇒ выбор = цена; закон-блок ОБЯЗАТЕЛЕН (строка 134) | quirks §0731 п.3а (маппинг pro), п.3б (замер `low` на pro ОТОЗВАННЕ УСТАНОВЛЕНО); вахта смены маппинга «early August 2026» — §Б-108 | | **editor** | `deepseek-v4-pro` **БИЛИНГВ** | thinking ON; `reasoning:"off"` = осознанный NO-OP (ReasoningNone); ⚠ **ручка эффорта у `pro` ЕСТЬ — прежний клейм «ручки НЕТ (`low`→`high`)» СНЯТ 04.09 сверкой с квирк-каноном.** Канон пере-снят полигоном 30.08 живым `curl` (§3а: «ТАБЛИЦА У ВЕНДОРА ИЗМЕНИЛАСЬ, И ЗАПИСЬ НИЖЕ БОЛЬШЕ НЕ ВЕРНА»), а поведенческая проба того же дня (§3г, $0.038276) показала: **параметр `low` на `pro` ТЕПЕРЬ ДОХОДИТ ДО МОДЕЛИ** (79 prompt_tokens). ⚠ **Фиксируем ровно «ручка доходит», НЕ «ручка работает»:** ВЕЛИЧИНА эффекта не установлена (§3д: разброс ×38, причина не установлена), и это живой остаток строки 172(г). ⚠ **НОСИТЕЛИ ПРОТИВОРЕЧАТ, и это НЕ решено:** `PROGRESS.md` утверждает обратное (пинг зоне полигона + строка бэклога **237**(б)): вахта §Б-108 сработала 13.08 changelog'ом вендора — pro/flash получили low/high/max. Кто прав, из репозитория НЕ выводится: замера поведением после 13.08 нет ни у одной стороны. ⚠ **D39.137 про эффорт МОЛЧИТ** (11 строк, ноль упоминаний) — ссылаться на неё как на «ручка появилась 13.08» уже пробовали (испр. №18 20.08): конфабуляция по смежности, `V4-Pro-0813` — чекпойнт ВЕСОВ при вендорском «Model names remain unchanged», а не дата появления ручки. **Закрывается вендор-сверкой, а не выбором стороны**; до неё в силе КАНОН | `configs/pipeline-c1.yaml` блок редактора; floor 16000 — `models.yaml` ключ `deepseek-v4-pro`, поле `min_max_tokens` | боевой ИНТЕРИМ (D30.1/D39.22); D39.117: топология 2-прохода ПОДТВЕРЖДЕНА (`A/F3` +2.50 Holm 0.0004), жильцы dspro/glm-5 неразличимы ⇒ выбор = цена; закон-блок ОБЯЗАТЕЛЕН (строка 134) | quirks §0731 п.3а (маппинг pro), п.3б (замер `low` на pro ОТОЗВАННЕ УСТАНОВЛЕНО); вахта смены маппинга «early August 2026» — §Б-108 |
| **editor-резерв** | `glm-5` | thinking OFF ЯВНО (`extra_body {thinking:{type:disabled}}`, иначе таймауты ×3) | `configs/pipeline-arm-glm.yaml` блок редактора + `models.yaml` ключ `glm-5` | резерв; флип = один арм-конфиг. mistral-арм есть, но mistral ИСКЛЮЧЁН как редактор (D39.20) | quirks thinking-таблица (glm-5); эхо-экспозиция билингва при thinking-OFF НЕ измерена (`sourceEchoExposure`) | | **editor-резерв** | `glm-5` | thinking OFF ЯВНО (`extra_body {thinking:{type:disabled}}`, иначе таймауты ×3) | `configs/pipeline-arm-glm.yaml` блок редактора + `models.yaml` ключ `glm-5` | резерв; флип = один арм-конфиг. mistral-арм есть, но mistral ИСКЛЮЧЁН как редактор (D39.20) | quirks thinking-таблица (glm-5); эхо-экспозиция билингва при thinking-OFF НЕ измерена (`sourceEchoExposure`) |
| **судья Ф2** | Gemini (нативный адаптер — Ф2, строка 33); в C2-скелете провизорно `glm-5` | Gemini: thinking mandatory | `models.yaml` ключ `gemini-3.1-pro-preview`; `pipeline-c2.yaml` блок `select` («DO NOT FLIP») | Ф2/полигон — в движке НЕ построен; C2 неисполняем | quirks: `thinking_budget:0` → HTTP 400; учёт `additive_total`; судья ЭРОТИКИ непригоден (PROHIBITED_CONTENT неконфигурируем, D22.6) → первичный судья 18+ = grok | | **судья Ф2** | Gemini (нативный адаптер — Ф2, строка 33); в C2-скелете провизорно `glm-5` | Gemini: thinking mandatory | `models.yaml` ключ `gemini-3.1-pro-preview`; `pipeline-c2.yaml` блок `select` («DO NOT FLIP») | Ф2/полигон — в движке НЕ построен; C2 неисполняем | quirks: `thinking_budget:0` → HTTP 400; учёт `additive_total`; судья ЭРОТИКИ непригоден (PROHIBITED_CONTENT неконфигурируем, D22.6) → первичный судья 18+ = grok |
@ -17,6 +17,13 @@
## Примечания ## Примечания
- **⚠0731 (D39.61):** развилка решена вариантом (б) — явный `reasoning_effort:"low"` черновику + ручка эффорта бэнк-ролям (код `553f1a3`). - **⚠0731 (D39.61):** развилка решена вариантом (б) — явный `reasoning_effort:"low"` черновику + ручка эффорта бэнк-ролям (код `553f1a3`).
- ⛔ **РАЗВЁРТЫВАНИЕ КОНТУРА: `mining.contrast_path` — единственный вход, и в git его НЕТ.** Артефакт
крупный, генерируется из jieba (рецепт и SHA — `experiments/16-bank-mining.md`); без него стоп
майнинга возвращается рано и терминолог с классификатором не исполняются ВООБЩЕ, чем бы ни были
заполнены их гейты. Загрузка конфига это ПРОВЕРЯЕТ и отказывает по имени пути до первого платного
вызова (`internal/config`, греп `mining.contrast_path`). Носитель — строка бэклога 251.
⚠ И перекос слоя, вскрытый включением: корпус контраста — факт ИСХОДНОГО языка, а лежит в
пар-агностичном конфиге пайплайна. Пара, которой в репо нет, потребует своего корпуса и своего ключа.
- **Вахта эффорта pro:** реестр загейченных триггеров — `architecture/13-tech-debt-anchors.md` §Б-108 (статус ручки — в строке редактора выше). - **Вахта эффорта pro:** реестр загейченных триггеров — `architecture/13-tech-debt-anchors.md` §Б-108 (статус ручки — в строке редактора выше).
- **Цена:** ~$0.85/ранобэ (D30.4; тело — `archive/architecture/05-decisions-D1-D38.md`, карта — шапка D-лога) — ⚠ число ДО пере-пина цен 1315.08: таблица запинена ПИКОМ, счёт шиппинга = 100% DeepSeek ⇒ ×4.24.4 в пике и ×2.12.2 в долине (D39.137). ⚠ **Пере-калибровки НЕТ:** первый платный прогон редакторской волной отработал 31.08 (D39.184; числа — `archive/reports/COLDRUN_V16_REPORT_2026-08-31.md`), пересчёта книги из него никто не сделал — фактура и статус довода «редактор не гонялся» в `PROGRESS.md` строка 16. Ставка платформы $0.03/глава (D39.123 п.2г). Цены слагов — `models.yaml` (**`2026-08-15`**: `backend/configs/models.yaml:34`=`prices_checked: "2026-08-15"`; ⚠ бампнут факт-чеком ТОЛЬКО по DeepSeek; катовер 0731 цен не менял). - **Цена:** ~$0.85/ранобэ (D30.4; тело — `archive/architecture/05-decisions-D1-D38.md`, карта — шапка D-лога) — ⚠ число ДО пере-пина цен 1315.08: таблица запинена ПИКОМ, счёт шиппинга = 100% DeepSeek ⇒ ×4.24.4 в пике и ×2.12.2 в долине (D39.137). ⚠ **Пере-калибровки НЕТ:** первый платный прогон редакторской волной отработал 31.08 (D39.184; числа — `archive/reports/COLDRUN_V16_REPORT_2026-08-31.md`), пересчёта книги из него никто не сделал — фактура и статус довода «редактор не гонялся» в `PROGRESS.md` строка 16. Ставка платформы $0.03/глава (D39.123 п.2г). Цены слагов — `models.yaml` (**`2026-08-15`**: `backend/configs/models.yaml:34`=`prices_checked: "2026-08-15"`; ⚠ бампнут факт-чеком ТОЛЬКО по DeepSeek; катовер 0731 цен не менял).
- **Ключи API:** какой ключ нужен провайдеру — поле `api_key_env` в `models.yaml`, один носитель на факт. **`.env` НЕ читать** (гардрейл CLAUDE.md), `.env.example` можно. Ключи деплоя доезжают до движка аргументом `--keys-file` (движковая половина — D39.158, платформенная — пак P9); в окружение юнита ключи НЕ кладутся, и каталог пользовательского контента их больше не несёт. Строка бэклога **211** ЗАКРЫТА — история дефекта и его разбор в D39.156/D39.162. - **Ключи API:** какой ключ нужен провайдеру — поле `api_key_env` в `models.yaml`, один носитель на факт. **`.env` НЕ читать** (гардрейл CLAUDE.md), `.env.example` можно. Ключи деплоя доезжают до движка аргументом `--keys-file` (движковая половина — D39.158, платформенная — пак P9); в окружение юнита ключи НЕ кладутся, и каталог пользовательского контента их больше не несёт. Строка бэклога **211** ЗАКРЫТА — история дефекта и его разбор в D39.156/D39.162.

View file

@ -1,4 +1,4 @@
# Реестр D-нот — карта актуальности v2 (D1D39.190; титул — носитель головы, бампать при каждом аппенде) # Реестр D-нот — карта актуальности v2 (D1D39.194; титул — носитель головы, бампать при каждом аппенде)
> ⚠ **Колонку «тело» `counts.py --check` НЕ сторожит по устройству:** он сверяет полноту НОМЕРОВ, а не > ⚠ **Колонку «тело» `counts.py --check` НЕ сторожит по устройству:** он сверяет полноту НОМЕРОВ, а не
> место тела, поэтому колонка держится дисциплиной лендинга. Не нашёл тело по колонке — иди в слайсы, > место тела, поэтому колонка держится дисциплиной лендинга. Не нашёл тело по колонке — иди в слайсы,
@ -252,3 +252,4 @@
| D39.191 | 04.09 | **Норма приёмки: после дофикса — ВТОРОЙ адверсариальный круг по ИСХОДНЫМ пунктам заказа, петля до замыкания** (слово владельца). Закрывает окно, в котором дофикс ревьюировал только его автор. Цена окна замерена дважды в тот же день: двенадцать посадок первого круга пережили зелёную батарею (семь гарантий жили только как код), а платформенная сессия объявила починенной находку, снятие различителя в которой переживало батарею — у ручки над ДЕНЬГАМИ. Форма круга: пере-посадить находки самому · атаковать САМ ДОФИКС · проверить новые тесты на вакуумность · сажать мутации И В ДАННЫЕ | жив | ЖИВОЕ: круг без предъявленных посадок кругом не считается | приёмка норма петля | | D39.191 | 04.09 | **Норма приёмки: после дофикса — ВТОРОЙ адверсариальный круг по ИСХОДНЫМ пунктам заказа, петля до замыкания** (слово владельца). Закрывает окно, в котором дофикс ревьюировал только его автор. Цена окна замерена дважды в тот же день: двенадцать посадок первого круга пережили зелёную батарею (семь гарантий жили только как код), а платформенная сессия объявила починенной находку, снятие различителя в которой переживало батарею — у ручки над ДЕНЬГАМИ. Форма круга: пере-посадить находки самому · атаковать САМ ДОФИКС · проверить новые тесты на вакуумность · сажать мутации И В ДАННЫЕ | жив | ЖИВОЕ: круг без предъявленных посадок кругом не считается | приёмка норма петля |
| D39.192 | 04.09 | **Класс дефекта, названный ЗОНОЙ: «утверждение о СТРУКТУРЕ, выданное за гарантию»** — верное по факту и не прибитое ничем. Три из семи переживших посадок второго круга оказались им: «две функции читают одну таблицу» · «проверка в единственной воронке» · «порог в пустом интервале». Падает не от порчи ЗНАЧЕНИЯ, а от ЗАВЕДЕНИЯ ВТОРОГО ПУТИ, и падает молча. Форма посадки против него — «заведи обход», а не «сломай значение». ⚠ Норма о мутациях В ДАННЫЕ окупилась первой попыткой: размягчённая фикстура прошла батарею и отрапортовала число ЛУЧШЕ реального, потому что тест утверждал ПОЛ, а пол не измерение ⇒ число-доказательство обязано иметь леджер записанных значений | жив | ЖИВОЕ: карта слепых зон полна только с обеими осями — что не смотрели И чем нельзя опровергнуть | приёмка класс мутации данные | | D39.192 | 04.09 | **Класс дефекта, названный ЗОНОЙ: «утверждение о СТРУКТУРЕ, выданное за гарантию»** — верное по факту и не прибитое ничем. Три из семи переживших посадок второго круга оказались им: «две функции читают одну таблицу» · «проверка в единственной воронке» · «порог в пустом интервале». Падает не от порчи ЗНАЧЕНИЯ, а от ЗАВЕДЕНИЯ ВТОРОГО ПУТИ, и падает молча. Форма посадки против него — «заведи обход», а не «сломай значение». ⚠ Норма о мутациях В ДАННЫЕ окупилась первой попыткой: размягчённая фикстура прошла батарею и отрапортовала число ЛУЧШЕ реального, потому что тест утверждал ПОЛ, а пол не измерение ⇒ число-доказательство обязано иметь леджер записанных значений | жив | ЖИВОЕ: карта слепых зон полна только с обеими осями — что не смотрели И чем нельзя опровергнуть | приёмка класс мутации данные |
| D39.193 | 04.09 | **Три ратификации по оси рода, выданные каналом и НЕ внесённые в журнал** (долг оркестратора, предъявлен приёмкой: греп `KeyTrusted` по D-логу → 0). Производитель рода — КЛАССИФИКАТОР (ноль новых вызовов, закрытый словарь парсера; следствие: банковый контур в c1 — предпосылка) · замок расщеплён: род гейтится МАТЧЕМ (`KeyTrusted`), а не статусом, в ОБОИХ блоках · ⚠ дедуп закон-блока по голому `src` РОНЯЛ ПОДПИСЬ — ратификация оркестратора была неверна, принята редакция зоны: уступает только неподписанная | жив | ЖИВОЕ: ратификация без проверки ключа уникальности предмета вносит дефект; каждая посадка предъявляется КРАСНОЙ | род ратификация дедуп | | D39.193 | 04.09 | **Три ратификации по оси рода, выданные каналом и НЕ внесённые в журнал** (долг оркестратора, предъявлен приёмкой: греп `KeyTrusted` по D-логу → 0). Производитель рода — КЛАССИФИКАТОР (ноль новых вызовов, закрытый словарь парсера; следствие: банковый контур в c1 — предпосылка) · замок расщеплён: род гейтится МАТЧЕМ (`KeyTrusted`), а не статусом, в ОБОИХ блоках · ⚠ дедуп закон-блока по голому `src` РОНЯЛ ПОДПИСЬ — ратификация оркестратора была неверна, принята редакция зоны: уступает только неподписанная | жив | ЖИВОЕ: ратификация без проверки ключа уникальности предмета вносит дефект; каждая посадка предъявляется КРАСНОЙ | род ратификация дедуп |
| D39.194 | 04.09 | **Платформенный пак «закрыть цикл» ПРИНЯТ и ЗАЛЕНДЖЕН `adf5e53`** (39 файлов; цикл замкнут живьём — платный EPUB через API, `epubcheck` 0/0/0/0). Строка бэклога 246 закрыта, её якорь мёртв ОТ ЛЕЧЕНИЯ. **Контрактный минор 0.10.0** описывает построенную дверь: `failure_code` — enum из четырёх кодов, `Export.url``uri-reference` с честным механизмом вместо несуществующей капабилити, третий адрес получает `downloadExport`, шестнадцатая причина — `wrong_language`. Ошибка ратификации «вхождений два» исправлена ДО правки: второе — `about:blank` по RFC 9457. Отзыв причины смертей стенда (не хост, а группа процессов сессии) и вышедшая из него `PD-447`: рецепт глушил коллизию портов ложной зеленью. **Три класса ложной зелени** — упавшая сборка · обрезанный вывод · ЭКВИВАЛЕНТНАЯ ПОСАДКА (класс оркестратора). Гейт чисел получил два носителя: титул реестра нот и живой счёт регистра. `classifierVersion` НЕ двигать | жив | ЖИВОЕ: SURVIVED не находка, пока посадка не показала, что меняет поведение; бамп версии должен смене, способной пере-вердиктить СУЩЕСТВУЮЩИЙ снапшот | лендинг контракт минор ложная-зелень мутации гейт |

View file

@ -1,4 +1,4 @@
# Журнал решений оркестратора — контракт D1D39.193 (живой файл: карта · эрраты · живые тела · голова D39.124+ (подрезка D39.139); тела закрытых эр — в слайсах `docs/archive/architecture/`, указатель ниже; реестр всех нот — `05-decisions-index.md`) # Журнал решений оркестратора — контракт D1D39.194 (живой файл: карта · эрраты · живые тела · голова D39.124+ (подрезка D39.139); тела закрытых эр — в слайсах `docs/archive/architecture/`, указатель ниже; реестр всех нот — `05-decisions-index.md`)
> **КАРТА АКТУАЛЬНОСТИ (ревизия D31, продлена до D38.2 [12.07]; исторические записи ниже НЕ переписываются — дисциплина D23.3).** Работая с контрактом (греп номера: живой файл → слайсы, целиком НЕ читать — D39.125), держи под рукой, что чем перекрыто: > **КАРТА АКТУАЛЬНОСТИ (ревизия D31, продлена до D38.2 [12.07]; исторические записи ниже НЕ переписываются — дисциплина D23.3).** Работая с контрактом (греп номера: живой файл → слайсы, целиком НЕ читать — D39.125), держи под рукой, что чем перекрыто:
> ⚠ **Эррата 09.08 (D39.125):** D39.111 п.1 предписывал промту S3 «максимум = баланс МИНУС открытые холды» — формула ОШИБОЧНА (вычитание дважды), исправлена D39.115 п.2(а): максимум = Balance КАК ЕСТЬ; тело D39.111 живёт ниже в этом файле (голова D39.106+). > ⚠ **Эррата 09.08 (D39.125):** D39.111 п.1 предписывал промту S3 «максимум = баланс МИНУС открытые холды» — формула ОШИБОЧНА (вычитание дважды), исправлена D39.115 п.2(а): максимум = Balance КАК ЕСТЬ; тело D39.111 живёт ниже в этом файле (голова D39.106+).
@ -2046,3 +2046,80 @@ Fable 5.1 со сквозным контекстом (решение владе
**3. ⚠ ДЕДУП ЗАКОН-БЛОКА: моя ратификация была НЕВЕРНА, и правильная редакция — зоны.** Оркестратор велел «один приказ на исходный термин, побеждает подписанная». Формула шире правила: ключ уникальности банка — `(src, sense, since, until)`, значит одна поверхность ЗАКОННО несёт несколько ПОДПИСАННЫХ канонов (фамилия и направление у одного написания), и дедуп по голому `src` ронял подпись МОЛЧА, при том что трансляторный блок продолжал рендерить обе — два провода разъезжались. **Ратифицируется редакция зоны: уступает НЕПОДПИСАННАЯ строка и только ПОДПИСАННОЙ; подпись не роняется никогда.** Содержание исходного решения (конфликт подписанной с авто-консолидацией даёт один приказ) исполнено целиком; полисемия двух подписанных канонов конфликтом не является. ⚠ Класс ошибки называю прямо: **ратификация, выданная без проверки ключа уникальности предмета, внесла дефект в код** — и поймала его ЗОНА своим кругом петли, а не приёмка. **3. ⚠ ДЕДУП ЗАКОН-БЛОКА: моя ратификация была НЕВЕРНА, и правильная редакция — зоны.** Оркестратор велел «один приказ на исходный термин, побеждает подписанная». Формула шире правила: ключ уникальности банка — `(src, sense, since, until)`, значит одна поверхность ЗАКОННО несёт несколько ПОДПИСАННЫХ канонов (фамилия и направление у одного написания), и дедуп по голому `src` ронял подпись МОЛЧА, при том что трансляторный блок продолжал рендерить обе — два провода разъезжались. **Ратифицируется редакция зоны: уступает НЕПОДПИСАННАЯ строка и только ПОДПИСАННОЙ; подпись не роняется никогда.** Содержание исходного решения (конфликт подписанной с авто-консолидацией даёт один приказ) исполнено целиком; полисемия двух подписанных канонов конфликтом не является. ⚠ Класс ошибки называю прямо: **ратификация, выданная без проверки ключа уникальности предмета, внесла дефект в код** — и поймала его ЗОНА своим кругом петли, а не приёмка.
**4. Норма, купленная тем же кругом:** тест, написанный на конфигурации, где различаемые величины СОВПАДАЮТ, физически не может упасть — сессия завела пин на `pipeline-c1.yaml`, где модель банк-роли равна модели черновика, посадка сказала `SURVIVED`, и только это её и спасло. ⇒ **каждая новая посадка предъявляется КРАСНОЙ, а не объявляется**; чтение такого не ловит по построению. (04.09.2026, оркестратор №22) ✅ **4. Норма, купленная тем же кругом:** тест, написанный на конфигурации, где различаемые величины СОВПАДАЮТ, физически не может упасть — сессия завела пин на `pipeline-c1.yaml`, где модель банк-роли равна модели черновика, посадка сказала `SURVIVED`, и только это её и спасло. ⇒ **каждая новая посадка предъявляется КРАСНОЙ, а не объявляется**; чтение такого не ловит по построению. (04.09.2026, оркестратор №22) ✅
## D39.194 — ПЛАТФОРМЕННЫЙ ПАК «ЗАКРЫТЬ ЦИКЛ» ПРИНЯТ И ЗАЛЕНДЖЕН `adf5e53`; контрактный минор 0.10.0 описывает построенную дверь; три класса ложной зелени за сутки и гейт чисел, получивший два недостающих носителя (04.09). ✅
**1. Пак принят с дофиксом и заленджен — `adf5e53`, 39 файлов.** Цикл замкнут живьём: EPUB настоящего
ПЛАТНОГО перевода выдан через API, `epubcheck` 5.3.0 на СКАЧАННОМ файле 0/0/0/0, потрачено $0.278319
при потолке $1.5 (санкция D39.189). Батарея зоны 747/747 под `-race`, скипов 0. ⚠ **Число позиций
`git status` и число ФАЙЛОВ здесь расходятся — 38 против 39**, потому что новый каталог показывается
одной позицией; `git commit -- <пути>` роняет untracked молча, и зонный хук этого не ловит по
построению (читает индекс, который pathspec не наполняет). Проверка после коммита — `git show --stat
HEAD -- platform/ | tail -1` обязан сказать 39; сказал.
**2. Строка бэклога 246 ЗАКРЫТА** этим лендингом: копия потребителя приведена к производителю, фраза
«nothing this process would have written was written» снята, `ExitBookIncomplete = 16` внесён в полосу
и подтверждён живым движком, денежная половина цела в обеих копиях. ⚠ **Якорь строки МЁРТВ ОТ
ЛЕЧЕНИЯ, а не от порчи** — фразы больше нет ни на одной строке, и пере-указывать его значило бы
воскрешать дефект в документе; якорь уходит вместе со строкой.
**3. Контрактный минор 0.10.0 — четыре позиции, каждая правит КАНОН, а не код.** Состав вынесен
зоной, канон правил оркестратор: `failure_code` становится enum из четырёх кодов, которые деплой
ПРОИЗВОДИТ · `Export.url` объявлен `uri-reference` (отдаётся относительный путь) и получает честное
описание механизма вместо «minted for THIS response», описывавшего подписанную капабилити, которой
никто не строил · третий адрес двери получает `operationId` `downloadExport` · шестнадцатая причина
замечания `off_target_lang` получает код `wrong_language`. Провенанс — `14-api-contract/README.md`
§2.23; ранг причины приезжает движковым лендингом и до него объявлен обещанием, а не фактом.
**4. ⚠ Ошибка ратификации, исправленная ДО правки канона.** Оркестратор объявил зоне, что вхождений
`format: uri` два, а не одно, сверив грепом и не прочитав второе место. Второе — поле `type` проблемы
RFC 9457 со значением `about:blank`, абсолютный URI по стандарту; правка там была бы дефектом.
Правлено ОДНО вхождение. Класс тот же, что в D39.193 п.3: ратификация, выданная без чтения предмета.
Различитель дешёвый и обязателен впредь: греп даёт МЕСТА, а ратифицируется СМЫСЛ — читать контекст
каждого хита до, а не после.
**5. Отзыв причины смертей стенда — зона отозвала сама, проверено поимённо.** Утверждалось «хост
убивал демона по памяти, `dmesg` даёт 56 убийств». Число верное, вывод нет: `dmesg | grep -i 'killed
process' | grep -ci tmplatformd` → **0**, все 56 жертв — чужие `python3`. Настоящая причина своя:
демон поднимался фоновой задачей сессии и жил в её группе процессов, поэтому останов задачи уносил
его. Лечение в рецепте (`setsid` + `disown`, лидер сессии). ⚠ В `docs/` ложная причина НЕ осела —
проверено грепом; единственным носителем был зонный журнал, там она названа неверной, а не
отредактирована задним числом. Остаётся верным: состояние пережило все три смерти целиком —
D39.106 предъявил себя в бою трижды.
**6. Из отзыва вышла находка тяжелее отозванного — `PD-447`.** Рецепт подъёма стенда сам
воспроизводил коллизию портов и глушил её ЛОЖНОЙ ЗЕЛЕНЬЮ: демон стартовал на дефолтном `8080`, где
четвёртые сутки живёт чужой стенд, свой умирал на «порт занят», а следующие две строки того же
рецепта — проверка живости — отвечали `ok`/`ready` от ЧУЖОГО процесса. Предъявлено исполнением обеими
сторонами. Деплойный рецепт был дороже: по нему сид дарил $25 и грузил книгу в чужую базу. Лечения
три (явный адрес · проба опознаёт ПРОЦЕСС по pid, а не ответ по коду · `--noproxy`), и дефолт `8080`
в коде НЕ меняется — решение зоны, довод принят: коллизия здесь `tmplatformd` против `tmplatformd`,
смена номера её имитирует, а не лечит.
**7. ТРИ КЛАССА ЛОЖНОЙ ЗЕЛЕНИ ЗА ОДНИ СУТКИ — и это одна норма, а не три случая.** (а) Упавшая
сборка: `go test` даёт ненулевой выход без единого `--- FAIL:`, и это NOTHING, а не SURVIVED (зона
движка). (б) Обрезанный вывод: `--lint` капит показ на 25, зона считала свои красные грепом по `✗` и
прочла ноль при восьми (лечится разбивкой по корню цели, D39.192-лендинг). (в) **Эквивалентная
посадка — класс оркестратора:** посадка, названная «oldest wins», обходила окно от новейшего к
старому и оставляла первое увиденное, то есть воспроизводила исходное «newest wins» — поведение не
менялось, зелень ничего не значила, а была прочитана как «гарантия не прибита». Проверено
исполнением на чистой копии `b8154cd`. **Норма:** SURVIVED не является находкой, пока не показано,
что посадка ВООБЩЕ меняет поведение. Общее у трёх: гейт печатает данные и вердикт, а читатель верит
вердикту.
**8. Гейт чисел получил два носителя, которых у него не было.** (а) Титул реестра нот
(`05-decisions-index.md`) объявляет себя носителем головы, но не сверялся: держал `D1D39.190` при
голове `D39.193`, и `--check` печатал «сходится: True». (б) Живой счёт регистра платформы в
CURRENT-STATE: строка говорила «95 (major 3)» при пере-счёте 101/5, и скрипт печатал верное число
экраном ВЫШЕ ложного литерала. ⚠ Литерал регистра был снят с проверки 08.08 ОСОЗНАННО — возвращён не
вопреки тому разбору, а потому, что его посылка не держится: тогда носителем была ИСТОРИЧЕСКАЯ фраза
о находках приёмки, сегодня — живая строка состояния, обязанная ехать вместе с ним. Разбор оставлен
в самом скрипте рядом со старым.
**9. `classifierVersion` НЕ двигать — ратификация по запросу движковой зоны.** Смена, разведшая
эхо-правило и экран цели, не может пере-вердиктить ни один существующий снапшот: для →ru поток
управления побайтово тот же, →CJK-снапшотов не существует. Сильнее того: строка уже сдвинулась в этом
батче дважды (`classify-v2``v3` лендингом `b8154cd`, и ещё раз, когда `langscreen.Version` стал
производным от собственных калиброванных чисел), пере-снапшот уже предписан и ратифицирован ЕДИНЫМ
актом (D39.190 п.4, цена сегодня $0). **Различитель впредь:** бамп должен любой смене, способной
пере-вердиктить СУЩЕСТВУЮЩИЙ снапшот, — не «на всякий случай» и не «раз трогали файл».

View file

@ -19,7 +19,7 @@
| Файл | Роль | Что внутри | Пара | | Файл | Роль | Что внутри | Пара |
|---|---|---|---| |---|---|---|---|
| `zh-ru/translator.md` | черновик (flash) | брифинг-переменные `{{lang/genre/honorifics/transcription/venuti/footnotes}}` + слабая вёрстка-однострочка (D30.2) | zh→ru | | `zh-ru/translator.md` | черновик (flash) | брифинг-переменные `{{source_lang/target_lang/audience/honorifics/transcription/venuti/footnotes}}` плюс `{{title}}`/`{{text}}` (снято ИСПОЛНЕНИЕМ: `grep -o '{{[^}]*}}' backend/prompts/zh-ru/translator.md`; ⚠ `{{genre}}` в списке БОЛЬШЕ НЕТ — жанр выкинут словом владельца 16.08, строка бэклога 184, а `{{lang}}` разошёлся на пару) + слабая вёрстка-однострочка (D30.2) | zh→ru |
| `zh-ru/editor.md` | редактор (deepseek-v4-pro БИЛИНГВ ИНТЕРИМ, D39.22; glm-5 резерв), v3 | 4 мандата + ДИСКУРС-ПЕРЕВЁРСТКА (Ван Цуй) + чэнъюй-атом + структурные few-shot (`---FEWSHOT---`, тумблер per-stage) | zh→ru | | `zh-ru/editor.md` | редактор (deepseek-v4-pro БИЛИНГВ ИНТЕРИМ, D39.22; glm-5 резерв), v3 | 4 мандата + ДИСКУРС-ПЕРЕВЁРСТКА (Ван Цуй) + чэнъюй-атом + структурные few-shot (`---FEWSHOT---`, тумблер per-stage) | zh→ru |
| `zh-ru/editor-mono.md` | референс-вариант D13.1 (не боевой) | узкий моно-мандат | — | | `zh-ru/editor-mono.md` | референс-вариант D13.1 (не боевой) | узкий моно-мандат | — |
| `zh-ru/judge-selector.md` | Ф2 (не исполняется) | — | — | | `zh-ru/judge-selector.md` | Ф2 (не исполняется) | — | — |

View file

@ -163,7 +163,7 @@ Go-гейт стоит на v1 без поглощения кавычек: backe
### Б-106 — тело строки 106 на 09.08.2026 ### Б-106 — тело строки 106 на 09.08.2026
**Слой 3 НЕ достроен: контракт редактора = full-regen, а целевой — узкие мандаты + ДИФФЫ.** `docs/architecture/09-target-architecture.md:106`=`узкие мандаты + диффы` дословно: «research/07 предписывает узкие мандаты + диффы, а не полную перегенерацию — сейчас ровно наоборот (4 мандата, full-regen), что и породило хвост инверсий» (⚠ прежний голый якорь `:121-126` съехал на слой 5/6); целевой контракт — редактор правит anchored search/replace-спанами с детерминированным Go-apply (ограниченный blast-radius, дешевле, аудируемо, структурно omission-safe). Пак-16 построил петлю РЕМОНТА (починка флагнутого спана постфактум), а не diff-контракт роли ⇒ это разные вещи. **Строки не было ни одной** — дыра учёта, найденная сверкой 02.08 (грепы `diff`/`мандат`/`span` по бэклогу = 0). Смежное: арм Q4b «diff-fidelity+style редактор» (`exp15:108`) не прогонялся НИ РАЗУ, хотя трек B объявлен завершённым. **ЭМПИРИКА ПОЛУЧЕНА (D39.108, экспы 19/20):** дифф-контракт механически исправен (комплаенс 0.966 на боевой единице, аппликатор 15/15), но по замороженному гейту Q4b диффы ОТЛОЖЕНЫ (fidelity-trap 11/12; дороже full-regen на dspro×ru ×2.52.9 при невскрытой причине; D21.4/D21.10 закрыты явно). **Эксп-21 (D39.117):** полный regen выигрывает у точечного ремонта (`C2/A_law` 3.75 Holm 0.0006) — довод против диффов, НЕ опровержение: чинил дешёвый фиксер по предложению, а не сильный редактор узким мандатом; гейт «перепроверить до стройки» в силе, приоритет понижен **Слой 3 НЕ достроен: контракт редактора = full-regen, а целевой — узкие мандаты + ДИФФЫ.** `docs/architecture/09-target-architecture.md:109`=`узкие мандаты + диффы` дословно: «research/07 предписывает узкие мандаты + диффы, а не полную перегенерацию — сейчас ровно наоборот (4 мандата, full-regen), что и породило хвост инверсий» (⚠ прежний голый якорь `:121-126` съехал на слой 5/6); целевой контракт — редактор правит anchored search/replace-спанами с детерминированным Go-apply (ограниченный blast-radius, дешевле, аудируемо, структурно omission-safe). Пак-16 построил петлю РЕМОНТА (починка флагнутого спана постфактум), а не diff-контракт роли ⇒ это разные вещи. **Строки не было ни одной** — дыра учёта, найденная сверкой 02.08 (грепы `diff`/`мандат`/`span` по бэклогу = 0). Смежное: арм Q4b «diff-fidelity+style редактор» (`exp15:108`) не прогонялся НИ РАЗУ, хотя трек B объявлен завершённым. **ЭМПИРИКА ПОЛУЧЕНА (D39.108, экспы 19/20):** дифф-контракт механически исправен (комплаенс 0.966 на боевой единице, аппликатор 15/15), но по замороженному гейту Q4b диффы ОТЛОЖЕНЫ (fidelity-trap 11/12; дороже full-regen на dspro×ru ×2.52.9 при невскрытой причине; D21.4/D21.10 закрыты явно). **Эксп-21 (D39.117):** полный regen выигрывает у точечного ремонта (`C2/A_law` 3.75 Holm 0.0006) — довод против диффов, НЕ опровержение: чинил дешёвый фиксер по предложению, а не сильный редактор узким мандатом; гейт «перепроверить до стройки» в силе, приоритет понижен
### Б-108 — тело строки 108 на 09.08.2026 ### Б-108 — тело строки 108 на 09.08.2026

View file

@ -3,10 +3,10 @@
батч 0.3.0 — D39.138, 16.08.2026, оркестратор №17; батч 0.3.0 — D39.138, 16.08.2026, оркестратор №17;
синк с платформой 0.4.0 — 20.08.2026, контрактная сессия; РАТИФИЦИРОВАН D39.152, 20.08.2026, оркестратор №18) синк с платформой 0.4.0 — 20.08.2026, контрактная сессия; РАТИФИЦИРОВАН D39.152, 20.08.2026, оркестратор №18)
СТАТУС: РАТИФИЦИРОВАН как контракт API v0 по 0.9.0 включительно (D39.180; перечень миноров и их СТАТУС: РАТИФИЦИРОВАН как контракт API v0 по 0.10.0 включительно (D39.194; перечень миноров и их
провенанс — ниже по файлу, здесь НЕ дублируется). Нормативная поверхность — openapi.yaml РЯДОМ. провенанс — ниже по файлу, здесь НЕ дублируется). Нормативная поверхность — openapi.yaml РЯДОМ.
⚠ Зонная копия frontend/docs/api-contract/ ВРЕМЕННО ОТСТАЁТ (0.2.3 при каноне ⚠ Зонная копия frontend/docs/api-contract/ ВРЕМЕННО ОТСТАЁТ (0.2.3 при каноне
0.9.0 — СЕМЬ миноров) — ратифицировано D39.142 п.5 на время фриза фронта; синк байт-в-байт + перегенерация типов = 0.10.0 — ВОСЕМЬ миноров) — ратифицировано D39.142 п.5 на время фриза фронта; синк байт-в-байт + перегенерация типов =
первое касание зоны при разморозке; после него правило прежнее: расхождение = дефект лендинга. первое касание зоны при разморозке; после него правило прежнее: расхождение = дефект лендинга.
Генерация типов фронта после этой ратификации идёт из ЭТОЙ копии. Генерация типов фронта после этой ратификации идёт из ЭТОЙ копии.
@ -32,7 +32,7 @@ cmp-сверка обязательна (D39.138 п.3).
> сверку со стандартами, разобранные альтернативы). При расхождении по ФОРМЕ побеждает YAML; > сверку со стандартами, разобранные альтернативы). При расхождении по ФОРМЕ побеждает YAML;
> при вопросе «почему так» — этот файл. > при вопросе «почему так» — этот файл.
> >
> **Статус: РАТИФИЦИРОВАН по 0.9.0 включительно.** 0.2.0 (D39.115, 08.08) · 0.2.1 (D39.123, 09.08) · > **Статус: РАТИФИЦИРОВАН по 0.10.0 включительно.** 0.2.0 (D39.115, 08.08) · 0.2.1 (D39.123, 09.08) ·
> 0.2.2 (D39.129, 10.08) · 0.2.3 (D39.135, 15.08) · **0.3.0 (D39.138, 16.08) — ломающий минор по > 0.2.2 (D39.129, 10.08) · 0.2.3 (D39.135, 15.08) · **0.3.0 (D39.138, 16.08) — ломающий минор по
> целостному ревью research/28** · **0.4.0 (D39.152, 20.08) — синк с платформой, §6в** · > целостному ревью research/28** · **0.4.0 (D39.152, 20.08) — синк с платформой, §6в** ·
> **0.5.0 (D39.161, 27.08) — снос отменённой пер-термной модели подписи (PD-370) + дверь правок > **0.5.0 (D39.161, 27.08) — снос отменённой пер-термной модели подписи (PD-370) + дверь правок
@ -48,9 +48,18 @@ cmp-сверка обязательна (D39.138 п.3).
> заново продолжает ровно с места остановки. Приехал ОДНИМ лендингом с платформенным паком P11** · > заново продолжает ровно с места остановки. Приехал ОДНИМ лендингом с платформенным паком P11** ·
> **0.9.0 (D39.180; ратифицирован №20 31.08 по пингу зоны ДО стройки, заленджен №21 с паком P12) — ВТОРАЯ > **0.9.0 (D39.180; ратифицирован №20 31.08 по пингу зоны ДО стройки, заленджен №21 с паком P12) — ВТОРАЯ
> граница пересчёта `chapters_done` и непрозрачный `Book.shape_epoch`, которым она себя называет; > граница пересчёта `chapters_done` и непрозрачный `Book.shape_epoch`, которым она себя называет;
> провенанс — §2.22**. > провенанс — §2.22** ·
> **0.10.0 (D39.194, 04.09; ратифицирован ПОСЛЕ стройки, по составу, вынесенному платформенной
> сессией из пака «закрыть цикл») — дверь выдачи, описанная тем, что построено: `failure_code`
> становится enum из ЧЕТЫРЁХ кодов, которые эта реализация ПРОИЗВОДИТ (условие «becomes an enum with
> the first built format» наступило); `Export.url` объявлен `uri-reference`, потому что отдаётся
> ОТНОСИТЕЛЬНЫЙ путь, а прежняя формулировка «minted for THIS response» описывала подписанную
> капабилити, которой никто не строил; третий адрес двери получает `operationId` `downloadExport`
> до этого единственная поверхность, по которой браузер НАВИГИРУЕТ, жила в каноне только прозой;
> шестнадцатая причина замечания `off_target_lang` получает код `wrong_language` (Приложение А).
> Провенанс — §2.23**.
> Дом канона — этот каталог; > Дом канона — этот каталог;
> `frontend/docs/api-contract/openapi.yaml` — байт-зеркало ⚠ НА ФРИЗЕ ЗОНЫ РАВЕНСТВО ПРИОСТАНОВЛЕНО (D39.142 п.5): зеркало 0.2.3, канон 0.9.0. > `frontend/docs/api-contract/openapi.yaml` — байт-зеркало ⚠ НА ФРИЗЕ ЗОНЫ РАВЕНСТВО ПРИОСТАНОВЛЕНО (D39.142 п.5): зеркало 0.2.3, канон 0.10.0.
> >
> ⚠ **0.5.0 ломающий по построению (мажор `0`): снесены путь `POST …/bank/decisions` и три его > ⚠ **0.5.0 ломающий по построению (мажор `0`): снесены путь `POST …/bank/decisions` и три его
> схемы, из `BankPage` и `EventBank` сняты `pending_decisions`/`complete` (§2.19-бис), в > схемы, из `BankPage` и `EventBank` сняты `pending_decisions`/`complete` (§2.19-бис), в
@ -903,6 +912,40 @@ the original request was never applied». Каждый `POST /books` созда
`structure_version`). Через эпоху считается ТОЛЬКО пожизненный счёт книги; остаток — открытая строка `structure_version`). Через эпоху считается ТОЛЬКО пожизненный счёт книги; остаток — открытая строка
регистра платформы `PD-435`. регистра платформы `PD-435`.
### 2.23. Дверь выдачи, описанная построенным (0.10.0) — ✓ выведено из работающей двери
**Что.** Первый минор, целиком собранный из расхождений «канон обещает — код делает», найденных
живым ПЛАТНЫМ прогоном и адверсариальным проходом зоны. Четыре позиции, каждая правит КАНОН, а не
код: код здесь оказался прав.
**`failure_code` — enum из четырёх.** Поле само поставило себе условие («becomes an enum with the
first built format»), и условие наступило. Набор — то, что деплой ПРОИЗВОДИТ, а не то, что можно
вообразить: `book_empty` · `deployment_error` · `build_interrupted` · `build_failed`
(`platform/internal/exports/exports.go`, греп `the Export.failure_code vocabulary`). ⚠ `book_empty`
намеренно ОДИН код на две ситуации — книга нарезана и пуста, и книга, которую ещё никто не нарезал:
факт читателя один («в этой книге нечего отдавать») и лечение одно. ⚠ `deployment_error` не назван по
формату: тот же класс покрывает книгу без языкового тега, нечитаемый langpack и недоступный каталог,
и фраза «формат недоступен» была бы ложной для большинства причин — это находка адверсариального
прохода, а не переименование по вкусу.
**`Export.url``uri-reference`, и честный механизм.** Отдаётся ОТНОСИТЕЛЬНЫЙ путь; абсолютный
заставил бы сервис знать свой публичный ориджин, которого за edge-прокси он не знает. Прежняя
формулировка «minted for THIS response» читалась как подписанная капабилити — механизма такого никто
не строил, ссылка АУТЕНТИФИЦИРОВАННАЯ и защищена сессией. Это строго сильнее: утёкшая ссылка чужому
бесполезна, и деплойного секрета, который никто не ротирует, она не требует. ⚠ **Вхождение ОДНО.**
Оркестратор №22 при ратификации объявил их два, сверив грепом `format: uri` и не прочитав второе
место: там поле `type` проблемы RFC 9457 со значением `about:blank`, абсолютный URI по стандарту, и
трогать его нельзя. Ошибка исправлена ДО правки канона; класс — тот же, что в D39.193 (ратификация,
выданная без чтения предмета).
**Третий адрес двери получает `operationId`.** `…/exports/{exportId}/content` жил в каноне только
прозой, и генерируемый клиент про него не знал — при том что браузер по нему НАВИГИРУЕТ, и это
единственный способ существования поверхности. Теперь `downloadExport`, с объявленными `206` на Range
и `410` на протухшую ссылку.
**Шестнадцатая причина замечания.** `off_target_lang``wrong_language`; разбор и ⚠ о ранге — в
Приложении А.
## 3. Зависимости: чтение → источник → строка бэклога ## 3. Зависимости: чтение → источник → строка бэклога
**Правило, введённое 0.3.0 (Б-21): предупреждение о недостроенном ОБЯЗАНО нести номер строки **Правило, введённое 0.3.0 (Б-21): предупреждение о недостроенном ОБЯЗАНО нести номер строки
@ -1373,6 +1416,7 @@ heartbeat · форма `id` кадра. Сжатие как ТРЕБОВАНИ
|---|---|---|---|---| |---|---|---|---|---|
| `hard_refusal` · `soft_refusal` · `content_filter` · `hard_block` | 0 | `content_withheld` (ОДИН на все четыре — класс 2) | ⬜ | ⬜ | | `hard_refusal` · `soft_refusal` · `content_filter` · `hard_block` | 0 | `content_withheld` (ОДИН на все четыре — класс 2) | ⬜ | ⬜ |
| `cjk_artifact` | 1 | `source_residue` | ⬜ | ⬜ | | `cjk_artifact` | 1 | `source_residue` | ⬜ | ⬜ |
| `off_target_lang` | 1 ⚠ | `wrong_language` | ⬜ | ⬜ |
| `excision_suspect` | 1 | `text_possibly_dropped` | ⬜ | ⬜ | | `excision_suspect` | 1 | `text_possibly_dropped` | ⬜ | ⬜ |
| `coverage_fail` | 1 | `incomplete_coverage` | ⬜ | ⬜ | | `coverage_fail` | 1 | `incomplete_coverage` | ⬜ | ⬜ |
| `sanitizer_defect` | 2 | `markup_defect` | ⬜ | ⬜ | | `sanitizer_defect` | 2 | `markup_defect` | ⬜ | ⬜ |
@ -1385,7 +1429,19 @@ heartbeat · форма `id` кадра. Сжатие как ТРЕБОВАНИ
| `upstream_not_ok` | 8 (по умолчанию) | `unavailable` | ⬜ | ⬜ | | `upstream_not_ok` | 8 (по умолчанию) | `unavailable` | ⬜ | ⬜ |
| незнакомая причина | 8 (по умолчанию) | **`unspecified`** (обязанность сервера, п.5; клиент рисует ту же нейтральную фразу, что и на незнакомый код) | ⬜ нейтральная, НЕ «ошибка» | ⬜ | | незнакомая причина | 8 (по умолчанию) | **`unspecified`** (обязанность сервера, п.5; клиент рисует ту же нейтральную фразу, что и на незнакомый код) | ⬜ нейтральная, НЕ «ошибка» | ⬜ |
Причин пятнадцать; `upstream_not_ok` не имеет своей ветки в `flagReasonSeverity` ⚠ **Ряд `off_target_lang` (минор 0.10.0) — шестнадцатая причина, и его РАНГ приезжает не с этой правкой.**
Причина заведена движковым вайр-батчем (`backend/internal/pipeline/disposition.go`, греп
`FlagOffTargetLang`) и на сегодняшнем HEAD своей ветки в `flagReasonSeverity` НЕ имеет, то есть падает
в ранг по умолчанию 8 — «недоступно», что для внятного ответа на чужом языке ложно. Ранг 1 (рядом с
эхом, `source_residue`) — то, чем это чинится, и он приезжает лендингом движкового пака; до него
клетка читается как обещание, а не как факт. Код `wrong_language` ратифицирован по ДОККОММЕНТУ, а не
по имени константы (правило 1): движок формулирует «the answer is not in the language that was asked
for», и это ровно то, что видит читатель, — не «артефакт исходного письма» и не «недоступно».
⚠ Имя не переиспользует `source_residue` намеренно: доккоммент прямо разбирает, почему повторное
использование эхо-флага было бы ЛОЖЬЮ о причине (D39.93 п.2), — беглый английский черновик
демонстративно не является артефактом исходного письма.
Причин шестнадцать; `upstream_not_ok` не имеет своей ветки в `flagReasonSeverity`
(`backend/internal/pipeline/status.go`, функция `flagReasonSeverity`) и падает в ранг по умолчанию, (`backend/internal/pipeline/status.go`, функция `flagReasonSeverity`) и падает в ранг по умолчанию,
как и любая будущая причина. ⚠ Номер строки здесь намеренно не ставится: прежняя ссылка `:174` как и любая будущая причина. ⚠ Номер строки здесь намеренно не ставится: прежняя ссылка `:174`
протухла за один пак (там теперь `GlossaryMissFlagged`) — поймано синком 20.08, п. L записки. протухла за один пак (там теперь `GlossaryMissFlagged`) — поймано синком 20.08, п. L записки.

View file

@ -2,7 +2,7 @@ openapi: 3.1.0
info: info:
title: TextMachine API title: TextMachine API
version: 0.9.0 version: 0.10.0
summary: Ratified contract between the frontend and the TextMachine platform. summary: Ratified contract between the frontend and the TextMachine platform.
description: | description: |
**RATIFIED contract.** Canonical copy: `docs/architecture/14-api-contract/`; **RATIFIED contract.** Canonical copy: `docs/architecture/14-api-contract/`;
@ -904,6 +904,51 @@ paths:
'401': { $ref: '#/components/responses/Unauthorized' } '401': { $ref: '#/components/responses/Unauthorized' }
'404': { $ref: '#/components/responses/NotFound' } '404': { $ref: '#/components/responses/NotFound' }
/books/{bookId}/exports/{exportId}/content:
parameters:
- $ref: '#/components/parameters/BookId'
- $ref: '#/components/parameters/ExportId'
get:
tags: [export]
operationId: downloadExport
summary: Download the built file.
description: |
The address `Export.url` names. Given an `operationId` in 0.10.0 because until then this was
the one surface of the door described in prose only: a generated client did not know the
address a browser actually NAVIGATES to.
**Range requests are answered**, so a download of tens of megabytes survives an interruption
instead of starting over.
The body is `application/octet-stream` and deliberately not a per-format media type: the
formats are a DEPLOYMENT's declaration, so a table here would be a second list to keep in
step with the engine — and it would be wrong for exactly the format nobody remembered to
add. The file NAME carries the extension, which is what a browser and an operating system
dispatch on.
responses:
'200':
description: The file.
headers:
Content-Disposition:
description: |
Carries the file name a reader sees — the book's TITLE, because that is what a
library is sorted by, and the export id only when the title is unusable. Declared
here because a client that ignores it saves the file under an opaque identifier.
schema: { type: string, minLength: 1 }
content:
application/octet-stream:
schema: { type: string, format: binary }
'206':
description: |
The requested part of the file, in answer to a `Range` request.
content:
application/octet-stream:
schema: { type: string, format: binary }
'401': { $ref: '#/components/responses/Unauthorized' }
'404':
$ref: '#/components/responses/NotFound'
'410': { $ref: '#/components/responses/Gone' }
components: components:
securitySchemes: securitySchemes:
sessionCookie: sessionCookie:
@ -2544,19 +2589,46 @@ components:
failure_code: failure_code:
type: [string, 'null'] type: [string, 'null']
minLength: 1 minLength: 1
enum: [book_empty, deployment_error, build_interrupted, build_failed, null]
description: | description: |
Machine reason when `state` is `failed`, `null` otherwise; the phrase is the client's. Machine reason when `state` is `failed`, `null` otherwise; the phrase is the client's.
Not enumerated — how an export can fail depends on formats that do not exist yet. It
becomes an enum with the first built format; the companion carries why it is open. **Enumerated since 0.10.0** — the condition this field set for itself («becomes an enum
with the first built format») is met. The set is what a deployment PRODUCES, not what one
can imagine:
· `book_empty` — there is no text in the book to make a file out of. One code for two
situations, because the reader's fact is one and so is the remedy: a book that was cut
and is empty, and a book nobody has cut yet. The door may not refuse by a book's state,
so «nothing to write» travels as this export's outcome rather than as a `409`.
· `deployment_error` — the engine refused THIS deployment's configuration: a format it
does not build, a book without a language tag, a reader-words file it cannot read, a
directory it may not write. The operator's files need fixing; the user can do nothing,
and is told a machine reason rather than a lie. ⚠ Deliberately NOT named after the
format: the same class covers all of the above, so «that format is unavailable» would
be false for most of them.
· `build_interrupted` — the build did not finish and nobody is coming back for it.
Asking again converges.
· `build_failed` — the file could not be produced and this build has no better word. It
is an answer that ENDS the poll, which is the one thing this resource must never fail
to give.
url: url:
type: [string, 'null'] type: [string, 'null']
format: uri format: uri-reference
description: | description: |
Where to download it from; `null` unless `state` is `ready`. Where to download it from; `null` unless `state` is `ready`. The operation is
`downloadExport`.
**Minted for THIS response and for the authenticated owner**, never indexed, on the same **Bound to the authenticated owner**, never indexed, on the same origin as this API, and
origin as this API, and expiring at `expires_at`. A browser NAVIGATES to it: it is a expiring at `expires_at`. A browser NAVIGATES to it: it is a download, not a call.
download, not a call.
⚠ **A RELATIVE reference** — hence `uri-reference` and not `uri` since 0.10.0. An
absolute URL would require the service to know its own public origin, which behind an
edge proxy it does not. ⚠ The wording before 0.10.0 («minted for THIS response») read as
a signed capability and described a mechanism nobody built: the link carries no secret
and no expiring token, it is protected by the session like every other read here. That is
strictly stronger — a leaked link is useless to a stranger — and it needs no deployment
secret that nobody rotates.
EventEnvelope: EventEnvelope:
type: object type: object

View file

@ -1,5 +1,17 @@
# Промт сессии: ПЛАТФОРМА — «закрыть цикл: сквозной прогон и дверь выдачи» # Промт сессии: ПЛАТФОРМА — «закрыть цикл: сквозной прогон и дверь выдачи»
> ⚠⚠ **АРХИВ. ПРОМТ ОТРАБОТАН — ИНСТРУКЦИИ ОТСЮДА НЕ ИСПОЛНЯЮТСЯ.**
> Выдан 04.09, сдан 04.09, принят с дофиксом и ЗАЛЕНДЖЕН `adf5e53` (`D39.194`). Исход: **цикл замкнут
> живьём** — EPUB настоящего ПЛАТНОГО перевода выдан через API, `epubcheck` 5.3.0 на СКАЧАННОМ файле
> 0/0/0/0, потрачено $0.278319 из потолка $1.5. Дверь выдачи построена и предъявлена исполнением; три
> сценария строки 216 показаны живьём. Заказ дал БОЛЬШЕ, чем просил: два мажора найдены самим прогоном
> (`PD-440` — книгу через API нельзя дочитать до конца, `PD-441` — halt не пишет цену отменённых в
> полёте вызовов), и они и есть главный результат пака.
> ⚠ Ратификация «артефакт с пометкой» ПАЛА ПОД ЗАМЕРОМ зоны — артефакта не существует, движок выходит
> с кодом 11 и файла не пишет; возражение принято целиком.
> ⚠ Часть указателей этого файла мертва по построению: пак переписал цели.
> Живые носители: `D39.194` · `platform/docs/platform-PROGRESS.md` · регистр дефектов зоны.
> **Роль:** платформа. **Зона записи:** `platform/`. Чужие зоны читаешь, не правишь; итоги и пинги — > **Роль:** платформа. **Зона записи:** `platform/`. Чужие зоны читаешь, не правишь; итоги и пинги —
> ЗОННЫЙ журнал `platform/docs/platform-PROGRESS.md``docs/PROGRESS.md` платформа НЕ пишет). > ЗОННЫЙ журнал `platform/docs/platform-PROGRESS.md``docs/PROGRESS.md` платформа НЕ пишет).
> **Не коммитишь** и не трогаешь индекс и историю — запреты и причина: `CLAUDE.md`, > **Не коммитишь** и не трогаешь индекс и историю — запреты и причина: `CLAUDE.md`,

View file

@ -6193,7 +6193,7 @@ n = 16 английских единиц = 7.89 главы Гу · k = 5 арм
* **Находка 1 (декой) — диспозиция за приёмкой**, не за сессией. От неё зависит, считать ли Шаг 4 * **Находка 1 (декой) — диспозиция за приёмкой**, не за сессией. От неё зависит, считать ли Шаг 4
закрытым по букве или по цели. закрытым по букве или по цели.
* **Находка 11** — пометы «контраст условный» на телах Д23/Д24 не поставлены. * **Находка 11** — пометы «контраст условный» на телах Д23/Д24 не поставлены.
* `docs/PROGRESS.md:679`=`ЖИВОЙ ДЕФЕКТ ДВИЖКА` — шапка пинга №19 теперь ложна дважды (дефект * `docs/PROGRESS.md`, фраза «ЖИВОЙ ДЕФЕКТ ДВИЖКА» — **ЦЕЛИ БОЛЬШЕ НЕТ** (испр. оркестратором №22, 04.09): утверждение снято переписью шапки, а не сдвинуто. Пере-указывать по СХОДСТВУ нельзя — ближайшее «ЖИВОЙ ДЕФЕКТ, внесённый моим же дофиксом» говорит о другом. Якорь снят с формы `файл:строка`, чтобы цитата мёртвого адреса сама не стала якорем — шапка пинга №19 теперь ложна дважды (дефект
движка закрыт 28.08; терялся промт, а не глоссарий) и баннера не имеет. **Чужая зона, пинг дан.** движка закрыт 28.08; терялся промт, а не глоссарий) и баннера не имеет. **Чужая зона, пинг дан.**
--- ---
@ -7868,7 +7868,7 @@ completion, уходящие в размышление** (Д49), — это пл
1. **Митигация «25 узких вопросов да/нет вместо MQM»** (+35 пунктов к доле, где судья предпочёл 1. **Митигация «25 узких вопросов да/нет вместо MQM»** (+35 пунктов к доле, где судья предпочёл
человека) — это метрика **LiTransProQA**, и она уже в репозитории **в трёх местах**, включая человека) — это метрика **LiTransProQA**, и она уже в репозитории **в трёх местах**, включая
`docs/architecture/02-mvp-plan.md:49`=`судья-анкета узких вопросов`. ⚠ Хуже: её же τ = 0.124 в другом месте того же отчёта `docs/architecture/02-mvp-plan.md:46`=`судья-анкета узких вопросов`. ⚠ Хуже: её же τ = 0.124 в другом месте того же отчёта
объявлен опорой «судья награждает MT» — то есть одна метрика подана и как лекарство, и как болезнь. объявлен опорой «судья награждает MT» — то есть одна метрика подана и как лекарство, и как болезнь.
2. **Работа про гранулярность** уже пересказана у нас **в девяти местах**, включая 2. **Работа про гранулярность** уже пересказана у нас **в девяти местах**, включая
`09-pilot-protocol.md:59` с пометкой «верифицировано по PDF, вкл. en→ru». `09-pilot-protocol.md:59` с пометкой «верифицировано по PDF, вкл. en→ru».

View file

@ -286,7 +286,7 @@ def register(text: str) -> dict:
} }
def head(dlog: str, prog: str) -> dict: def head(dlog: str, prog: str, idx: str) -> dict:
found = [(int(m.group(2)), int(m.group(3)), m.group(1)) found = [(int(m.group(2)), int(m.group(3)), m.group(1))
for l in dlog.splitlines() if (m := NOTE.match(l))] for l in dlog.splitlines() if (m := NOTE.match(l))]
notes = [f[2] for f in found] notes = [f[2] for f in found]
@ -302,13 +302,20 @@ def head(dlog: str, prog: str) -> dict:
break break
last = notes[-1] if notes else None last = notes[-1] if notes else None
b = banner.group(1) if banner else None b = banner.group(1) if banner else None
# ⚠ ТРЕТИЙ носитель головы, добавлен 04.09 (оркестратор №22) после того, как разошёлся МОЛЧА:
# реестр нот держал «D1D39.190» при голове D39.193, а гейт печатал «сходится: True», потому что
# сверял только шапку D-лога и CURRENT-STATE. Титул реестра сам объявляет себя носителем головы
# («бампать при каждом аппенде»), полноту рядов скрипт уже сторожит — не хватало ровно диапазона.
ib = re.search(r"D1(D\d+\.\d+)", idx.splitlines()[0]) if idx else None
i = ib.group(1) if ib else None
return { return {
"максимум по номеру": top, "максимум по номеру": top,
"последняя по порядку файла": last, "последняя по порядку файла": last,
"порядок = номер": last == top, "порядок = номер": last == top,
"шапка D-лога": b, "шапка D-лога": b,
"титул реестра нот": i,
"голова в CURRENT-STATE": claimed, "голова в CURRENT-STATE": claimed,
"сходится": bool(top) and top == claimed == b, "сходится": bool(top) and top == claimed == b == i,
} }
@ -330,6 +337,17 @@ LITERALS = [
# платформы (закрыто 10 строк за 20 минут) превратил правдивую запись в «расхождение», и # платформы (закрыто 10 строк за 20 минут) превратил правдивую запись в «расхождение», и
# предписанное лечение было бы «перепиши историю». Живой счёт живёт в зонном журнале платформы, # предписанное лечение было бы «перепиши историю». Живой счёт живёт в зонном журнале платформы,
# проверять его отсюда — значит винить зону docs за состояние чужого файла. Предсказано ревью. # проверять его отсюда — значит винить зону docs за состояние чужого файла. Предсказано ревью.
#
# ⚠ ВОЗВРАЩЁН 04.09 (оркестратор №22) — и возвращён НЕ вопреки разбору выше, а потому, что его
# посылка больше не держится. Тот разбор про ИСТОРИЧЕСКУЮ фразу («что нашла приёмка»), которую
# гард заставлял бы переписывать при каждом чужом фиксе. Сегодня носитель ДРУГОЙ: живая строка
# CURRENT-STATE «трезвость по масштабу», которая утверждает ТЕКУЩЕЕ состояние и обязана ехать
# вместе с ним. Цена дыры предъявлена: строка говорила «95 (major 3)» при пере-счёте 101/5, и
# скрипт печатал верное число экраном выше ложного литерала, объявляя «литералы сходятся».
# ⚠ Регистр меняет ЗОНА, но коммитит его оркестратор — значит правка числа ложится тем же актом,
# что и правка регистра, и «переписывать историю» этот гард ни от кого не требует.
(PROGRESS, "current-state", r"открытых рядов регистра платформы — (\d+)", ("регистр-статус", "open")),
(PROGRESS, "current-state", r"открытых рядов регистра платформы — \d+ \(major (\d+)\)", ("регистр-вес", "major")),
] ]
@ -664,7 +682,7 @@ def main() -> int:
return 1 if problems else 0 return 1 if problems else 0
dlog, prog, reg = read(DLOG), read(PROGRESS), read(REGISTER) dlog, prog, reg = read(DLOG), read(PROGRESS), read(REGISTER)
b, r, h = backlog(prog), register(reg), head(dlog, prog) b, r, h = backlog(prog), register(reg), head(dlog, prog, read(NOTE_INDEX))
check = "--check" in sys.argv check = "--check" in sys.argv
src = "содержимое коммита (индекс/HEAD)" if FROM_INDEX else "рабочее дерево" src = "содержимое коммита (индекс/HEAD)" if FROM_INDEX else "рабочее дерево"
@ -686,7 +704,8 @@ def main() -> int:
if not h["сходится"]: if not h["сходится"]:
bad.append( bad.append(
f"голова разошлась: максимум по номеру {h['максимум по номеру']}, " f"голова разошлась: максимум по номеру {h['максимум по номеру']}, "
f"шапка D-лога {h['шапка D-лога']}, CURRENT-STATE {h['голова в CURRENT-STATE']}" f"шапка D-лога {h['шапка D-лога']}, титул реестра {h['титул реестра нот']}, "
f"CURRENT-STATE {h['голова в CURRENT-STATE']}"
) )
if b["дубли ID"]: if b["дубли ID"]:
bad.append(f"дубли ID строк бэклога: {b['дубли ID']}") bad.append(f"дубли ID строк бэклога: {b['дубли ID']}")
@ -705,7 +724,12 @@ def main() -> int:
texts = {PROGRESS: prog, REGISTER: reg} texts = {PROGRESS: prog, REGISTER: reg}
for path, reg_name, pattern, (kind, key) in LITERALS: for path, reg_name, pattern, (kind, key) in LITERALS:
want = b[key] if kind == "backlog" else r["вес открытых"].get(key, 0) if kind == "backlog":
want = b[key]
elif kind == "регистр-статус":
want = r["по статусу"].get(key, 0)
else:
want = r["вес открытых"].get(key, 0)
found = re.search(pattern, region(texts[path], reg_name)) found = re.search(pattern, region(texts[path], reg_name))
if not found: if not found:
bad.append( bad.append(