From 58bca1949c28fabe5bbb304a40af04074aac00c2 Mon Sep 17 00:00:00 2001 From: heaven Date: Fri, 4 Sep 2026 20:23:11 +0300 Subject: [PATCH] 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 --- docs/PROGRESS.md | 87 +++++++++++++++--- docs/README.md | 2 +- docs/STACK.md | 13 ++- docs/architecture/05-decisions-index.md | 3 +- docs/architecture/05-decisions-log.md | 79 ++++++++++++++++- docs/architecture/10-prompt-architecture.md | 2 +- docs/architecture/13-tech-debt-anchors.md | 2 +- docs/architecture/14-api-contract/README.md | 68 ++++++++++++-- .../architecture/14-api-contract/openapi.yaml | 88 +++++++++++++++++-- ...TFORM_EXPORT_SESSION_PROMPT_2026-09-04.md} | 12 +++ docs/experiments/23-editor-tier.md | 4 +- docs/scripts/counts.py | 34 +++++-- 12 files changed, 353 insertions(+), 41 deletions(-) rename docs/{PLATFORM_EXPORT_SESSION_PROMPT.md => archive/prompts/PLATFORM_EXPORT_SESSION_PROMPT_2026-09-04.md} (92%) diff --git a/docs/PROGRESS.md b/docs/PROGRESS.md index 7c3ab650..03c35945 100644 --- a/docs/PROGRESS.md +++ b/docs/PROGRESS.md @@ -1,6 +1,6 @@ # Журнал прогресса -> **⟶ ТЕКУЩЕЕ СОСТОЯНИЕ** (на 2026-09-04, голова D39.193 — КУРС: движок и платформа до «работает и отдаёт результат», фронт ЗАМОРОЖЕН и P7 его НЕ размораживает (D39.147). **ОЧЕРЕДЬ №22** (единственный носитель — здесь; роль передана 01.09, №21 закрыт нотой передачи D39.184). ⚠ **ЗАКАЗ ВЛАДЕЛЬЦА 01.09 — ПЕРВЫМ:** (0а) **ревизия документации на ПРОТУХШЕЕ** — по всем зонам, не только тронутым; (0б) **планы доработок в БЭКЕНД и ПЛАТФОРМУ** по остатку бэклога и регистра; (0в) **вынос неактуального в АРХИВ** (`docs/archive/`, `platform/docs/archive/`) — за сутки 31.08 закрыто много, и часть носителей стала историей. ⚠ Трезвость по масштабу (пере-считано 02.09): **94** живых дока в `docs/` (пере-счёт 04.09: `find docs -name '*.md' -not -path 'docs/archive/*' | wc -l`), 8 в `platform/docs`, 9 в `backend/docs` — ⚠ из 94 ВРЕМЕННЫЙ остался ОДИН (`DOC_CLEANUP_PLAN`, живой до закрытия батчей Б14/Б15/Б17); два прежних временных уехали в `archive/reports/` 02.09; счёт бэклога — бюллетенем ниже, открытых рядов регистра платформы — 95 (major 3) ⚠ (ревизией 02.09 ряды **154** и **157** переведены из «скоро» в «когда-нибудь»: их гейтом стоял первый холодный прогон, он ОТРАБОТАЛ 31.08 и оба предусловия оказались другими — разбор в самих ячейках, ни одна НЕ закрыта). ⚠ Числа доков `counts.py` НЕ сторожит — при переносе файлов пере-считывать руками командой `find docs -name '*.md' -not -path 'docs/archive/*' | wc -l`. ⚠ И предупреждение о МЕТОДЕ, купленное сменой №21: «выглядит протухшим» ≠ «протухло». Три факта оркестратора опровергнуты ЗАМЕРОМ сессий, а якоря `15-money-path.md` в девяти случаях из двенадцати РОДИЛИСЬ верными и сгнили дрейфом — то есть ревизия обязана быть исполнением, а не чтением. ⚠ **ОЧЕРЕДЬ, унаследованная от №21** (три лендинга 31.08 — секция «СОСТОЯНИЕ ПАКОВ» ниже): **(1) ~~РАЗРЫВ ЦИКЛА~~ ЗАМКНУТ ЖИВЬЁМ 04.09** — пользователь получил EPUB настоящего ПЛАТНОГО перевода ЧЕРЕЗ API, `epubcheck` 5.3.0 на СКАЧАННОМ файле 0/0/0/0 (книга `bk_SS5VES2JELESJSTR`, потрачено $0.278319 из гранта $0.60 при потолке пака $1.5, санкция D39.189). Дверь выдачи построена и проверена исполнением: `202`+`Location`, поллинг с `Retry-After`, Range 206 · второй клиент 200 · аноним 401 · чужая книга 404, TTL с GC, идемпотентность третьего создающего вызова. Все ТРИ сценария строки 216 предъявлены живьём (подпись банка · halt на потолке с exit 4 · `409 run_not_resumable/ceiling_reached` и лечение новым прогоном). +> **⟶ ТЕКУЩЕЕ СОСТОЯНИЕ** (на 2026-09-04, голова D39.194 — КУРС: движок и платформа до «работает и отдаёт результат», фронт ЗАМОРОЖЕН и P7 его НЕ размораживает (D39.147). **ОЧЕРЕДЬ №22** (единственный носитель — здесь; роль передана 01.09, №21 закрыт нотой передачи D39.184). ⚠ **ЗАКАЗ ВЛАДЕЛЬЦА 01.09 — ПЕРВЫМ:** (0а) **ревизия документации на ПРОТУХШЕЕ** — по всем зонам, не только тронутым; (0б) **планы доработок в БЭКЕНД и ПЛАТФОРМУ** по остатку бэклога и регистра; (0в) **вынос неактуального в АРХИВ** (`docs/archive/`, `platform/docs/archive/`) — за сутки 31.08 закрыто много, и часть носителей стала историей. ⚠ Трезвость по масштабу (пере-считано 02.09): **94** живых дока в `docs/` (пере-счёт 04.09: `find docs -name '*.md' -not -path 'docs/archive/*' | wc -l`), 8 в `platform/docs`, 9 в `backend/docs` — ⚠ из 94 ВРЕМЕННЫЙ остался ОДИН (`DOC_CLEANUP_PLAN`, живой до закрытия батчей Б14/Б15/Б17); два прежних временных уехали в `archive/reports/` 02.09; счёт бэклога — бюллетенем ниже, открытых рядов регистра платформы — 101 (major 5), всего рядов 447 (пере-счёт `python3 docs/scripts/counts.py`; с 04.09 оба числа под гардом `--check`, прежние 95/3 разошлись молча) ⚠ (ревизией 02.09 ряды **154** и **157** переведены из «скоро» в «когда-нибудь»: их гейтом стоял первый холодный прогон, он ОТРАБОТАЛ 31.08 и оба предусловия оказались другими — разбор в самих ячейках, ни одна НЕ закрыта). ⚠ Числа доков `counts.py` НЕ сторожит — при переносе файлов пере-считывать руками командой `find docs -name '*.md' -not -path 'docs/archive/*' | wc -l`. ⚠ И предупреждение о МЕТОДЕ, купленное сменой №21: «выглядит протухшим» ≠ «протухло». Три факта оркестратора опровергнуты ЗАМЕРОМ сессий, а якоря `15-money-path.md` в девяти случаях из двенадцати РОДИЛИСЬ верными и сгнили дрейфом — то есть ревизия обязана быть исполнением, а не чтением. ⚠ **ОЧЕРЕДЬ, унаследованная от №21** (три лендинга 31.08 — секция «СОСТОЯНИЕ ПАКОВ» ниже): **(1) ~~РАЗРЫВ ЦИКЛА~~ ЗАМКНУТ ЖИВЬЁМ 04.09** — пользователь получил EPUB настоящего ПЛАТНОГО перевода ЧЕРЕЗ API, `epubcheck` 5.3.0 на СКАЧАННОМ файле 0/0/0/0 (книга `bk_SS5VES2JELESJSTR`, потрачено $0.278319 из гранта $0.60 при потолке пака $1.5, санкция D39.189). Дверь выдачи построена и проверена исполнением: `202`+`Location`, поллинг с `Retry-After`, Range 206 · второй клиент 200 · аноним 401 · чужая книга 404, TTL с GC, идемпотентность третьего создающего вызова. Все ТРИ сценария строки 216 предъявлены живьём (подпись банка · halt на потолке с exit 4 · `409 run_not_resumable/ceiling_reached` и лечение новым прогоном). > ⛔⛔ **НО КНИГУ ЧЕРЕЗ API НЕЛЬЗЯ ДОВЕСТИ ДО КОНЦА — найдено тем же прогоном 04.09 и воспроизведено дважды.** Прирост потолка на прогон = `chaptersLeft × $0.03` (ставка `DefaultPerChapter`, занижена ×4.47 — D39.179 п.1), и после первой готовой главы это $0.27, тогда как движок при `waves.workers: 4` резервирует под редакторский шаг ~$0.28 ⇒ **отказ резервации, прогон встаёт, книга не двигается**. Два прогона подряд дали одно и то же: `committed` не сдвинулся, холд вернулся. ⇒ **занижение ставки — не «шкала короче», а СТОП ПРОДУКТА: с какого-то момента каждая следующая покупка не покупает ничего.** Лечить придётся согласованно двумя сторонами (ставка платформы + резерв движка под шаг с параллельными воркерами), носитель — ряд регистра зоны, вес `major` **за недостижимость продукта, а не за деньги**: сам стоп НЕ ЖЖЁТ ничего — замер платформы 04.09 показал отмену ДО ухода запроса (латентность 20–31 мс, `model_actual` пуст, токенов ноль), и вся книга сходится до микро-доллара по трём источникам (`request_log` 0.278319 · `spend.committed_usd` 0.278318752 · платформенный `committed` 278319 микро). > ⛔ **ЗАТО HALT НА ПРОГОНЕ, КОТОРЫЙ ПРОДВИНУЛСЯ, ЖЖЁТ — отдельная находка того же прогона и свежая датированная точка строки 78 («леджер = НИЖНЯЯ граница»).** Четыре редакторских вызова ушли параллельно; один дошёл ($0.063404) и своим коммитом сорвал потолок, три других отменены в тот же миг, **отработав 120756, 156469 и 156470 мс** — и легли в леджер нулём. Незаписанное ≈ **$0.05–0.19 на ОДИН halt** против $0.278 за всю книгу, то есть механизм, защищающий от перерасхода, сам создаёт неучтённый расход. ⚠ Списание провайдером НЕ доказано (биллинга у нас нет) — утверждается ровно наблюдаемое: вызовы шли 2–2.6 минуты, их цены в леджере нет. > ⇒ **Дыра НЕ в принципе, а в покрытии, и это делает её заказом, а не наблюдением** (разбор оркестратора 04.09 по коду): консервативная оценка уже построена и ратифицирована — `backend/internal/pipeline/stagerun.go`, греп `settling the reservation estimate to keep the ceiling honest` (pack-13 point-9), — но её условие требует ОТВЕТА провайдера (`resp.Usage`), а отменённый в полёте вызов ответа не получает и уходит другим путём. Направление лечения: сеттлить оценку при отмене вызова, который успел уйти; различитель — факт ухода (латентность кандидат, порог обязан быть обоснован замером, а не назначен). Половина ДВИЖКОВАЯ. ⚠ Прежняя формулировка пункта — ниже, она о состоянии ДО 04.09. Движок пишет файл с 30.08 (`tmctl build` — EPUB 3 + чистый txt, D39.175), и холодный прогон 31.08 предъявил это живьём: собранный EPUB настоящего перевода прошёл `epubcheck` 0/0/0/0 и передан владельцу. Открыто ровно одно: канон обещает `createExport`/`getExport`, а платформа их НЕ монтирует (смонтировано 15 операций из 20; нет также `getRun`, `updateBook`, `deleteBook`). Долг числится с P8 (`platform/BACKLOG.md` П-17), и НИ ОДИН пак платформы после P7 его не взял (проверка вместо ручного счёта, чтобы не гнило при каждом лендинге: `grep -rn 'createExport\|getExport' platform/internal/ --include=*.go` — пусто). **Слово «отдаёт результат» ложно по букве ТОЛЬКО платформенной половиной** (п.4) · **(2) ~~холодный прогон движка~~ ОТРАБОТАЛ 31.08, закрыт РЕШЕНИЕМ ВЛАДЕЛЬЦА «не доводить»** (отчёт — `archive/reports/COLDRUN_V16_REPORT_2026-08-31.md`, числа относятся к `065d8ac`). Потрачено **$0.436110** из санкции $0.80. ПРЕДЪЯВЛЕНО живьём: объёмный потолок · D39.158 ОБЕИМИ половинами (стоп и не-стоп) · exit 16 · строки 154/198/239/240. ⚠ ~~**Причина большой доли редактора НЕ УСТАНОВЛЕНА**~~ — **УСТАНОВЛЕНА пробой полигона 02.09 по четырём осям: РЕДАКТОР ДУМАЕТ, А НЕ ПИШЕТ.** Размышление — **77.9%** цены редактора без ручки и 45.7% с `low`; у `glm-5` с выключенным thinking — 0.0%. Замер куплен и закончен ($6.17 из $9.50). ⚠ `research/30` §2.4 того же полигона повторяет «причина не установлена» — это про ДРУГОЙ вопрос (доля роли в прогоне против доли размышления в цене роли), и различение обязано попасть в ревью-шапку 30. Доля редактора идёт с ДВУМЯ знаменателями: **49.3%** от всего прогона ($0.214865 из $0.436110) и **81.3%** внутри порции П1 (⚠ ходившее «73%» — фантом, в отчёте его нет ни разу). Следующий шаг — контролируемая проба по ЧЕТЫРЁМ осям (роли осей и три требования, купленные ошибками этого прогона, — §14 отчёта; ось `stale` НЕДОСТИЖИМА — §10 там же). ⚠ **Цена: слово владельца 31.08 — ≈$0.60, потолок $0.80, ДЕСЯТЬ глав ПОЛНОЙ цепью включая редакторскую волну.** ⚠ **КЛЮЧИ: гейт снят словом владельца 30.08, разбор двух путей — D39.176 п.6.** Живое отсюда: конвенционного `.env` НЕТ НИ У ОДНОЙ книги корпуса (заполнены только `projects/textmachine/backend/.env` и `.../eval/.env`), поэтому прогон движка обязан передавать `--keys-file` абсолютным путём и только на `translate`; для п.3 нужен ДРУГОЙ файл — `TM_PLATFORM_ENGINE_KEYS_PATH`, тоже АБСОЛЮТНЫМ путём (`platform/internal/config/config.go`, греп `must be an absolute path`). Лечение операционное и $0 — направить переменную на уже заполненный файл; проверять ПРОГОНОМ, не чтением (гардрейл `.env`) · **(3) живой сквозной прогон через API платформы** — форма манифеста, сайдкара банка и карта причин флагов сочинены платформой САМОСТОЯТЕЛЬНО. ⚠ Уточнено 01.09: гейт СНЯТ холодным прогоном, и настоящие артефакты движка теперь ЕСТЬ (каталог `books/gu-zhenren/coldrun-v16/`), но сверка вышла ТОНКОЙ: на шов реально вышло **одно значение `flag_reason` из пятнадцати** (`sanitizer_stripped`), остальные четырнадцать по-прежнему только чтением кода, а манифест против `platform/internal/ingest/manifest.go` не сверялся вовсе · **(4) дверь выдачи** — строго ПОСЛЕ (3) (⚠ слово владельца 30.08: дверь ВСЕГДА строит файл — отказ юзеру не отдаётся, неполная книга уходит с пометкой, т.е. дверь зовёт `tmctl build --partial`; отказ по умолчанию остаётся операторской ручкой CLI; D29.1(б) «fail-closed» читать как «никогда молча» — честность несут пометки) · **(5) проводка `--max-units`** — снятие гейта, а не стройка: механизм в движке стоит (D39.170), живое основание гейта — `PD-422` · **(6) разморозка фронта** — ПОСЛЕ (4): зеркало отстало на СЕМЬ миноров (`frontend/docs/api-contract/openapi.yaml` — `0.2.3` против канона `0.9.0`, и первый из них — ЛОМАЮЩИЙ 0.3.0), 16 операций против 20; отставание ратифицировано D39.142 п.5 на время фриза и две ручки разъехались, размораживать раньше значит перегенерировать типы дважды. ⚠ **ДВА ЗАГЕЙЧЕННЫХ ТРИГГЕРА НАЖАТЫ И НЕ ОТРАБОТАНЫ — строка бэклога 237** (`go.work` · вендор-сверка эффорта `deepseek-v4-pro`; реестр `13-tech-debt-anchors.md` §Б-108). ⚠ **Состояние git — снимать КОМАНДАМИ, не чтением** (ветка `polygon` ушла вперёд, коммит здесь не цитирую): работа полигона лежит на ней и в `main` НЕ влита, а `git status -- eval/` в main-дереве пуст ПО ПОСТРОЕНИЮ и уводит в ложный вывод «работы нет»; ⚠ **«развязка git с origin» — арбитр ПЕРЕ-СНЯТ 04.09 и прежний вердикт БОЛЬШЕ НЕ ВЕРЕН:** `git merge-base --is-ancestor origin/main main` → **rc 1**, `git log main..origin/main` → `afa7700 temp` (коммит владельца 04.09, которым он передавал работу зон). Локальная линия ушла вперёд на семнадцать коммитов и содержит ВСЁ содержимое `afa7700` — оно снято `reset --soft` и заленджено раздельными зонными коммитами, — но формально ветки разошлись. Лечение — force-push рукой владельца; **не пуллить** (его же правило). ⚠ Пункт «развязка git с origin» в листе владельца ниже держится ТОЛЬКО как вопрос про force-push его рукой; утверждением о расхождении дерева он не является — арбитр этой пары именно здесь. @@ -11,15 +11,15 @@ > - **Сделано (сводно)** — снимок ленты закрытых эр в [archive/PROGRESS-2026-08-04-09.md](archive/PROGRESS-2026-08-04-09.md); детали — D-лог и слайсы. > - **Курс:** этапы ОБЩНОСТЬ · КАЧЕСТВО БАНКА · ПАКЕТ-ЧЕКЕРОВ · ФРОНТ-ЭРА · шов/платформа/движковые блокеры — ПРОЙДЕНЫ (D39.59–123). Хвосты курса живут строками: 16 (полная цена холодного старта; edit-волна на малых прогонах отработала и оплачена — 58 вызовов волновым драйвером 23–25.07 плюс 648 до драйвера, счёт по леджерам `~/books/gu-zhenren/**/*.db`) · 46 (дизайн заморожен D39.92/93, промт ждёт выдачи) · coldrun-b фаза C заморожена чекпойнтом легитимно (D39.86; эталон денег/поведения — coldrun-a, read-only); развилка 0731 решена и исполнена (D39.87/91, код `553f1a3`). > - **Горизонт (D39.62/67, освежён D39.95):** **ДОБОР ИДЕАЛА** (первым прогоном: оси голоса 24 · авто-режим · цена 16; жильцы ролей решаются ДО прогона эксп-22 — строка 149 · веса K1–K12 13а · вне-претрейн чекпоинт 55; остаток арбитража банка = рецензент спорных кластеров при ре-пробе 74 — D39.102) → ВТОРАЯ ПАРА живьём (ja→ru; преп 81) → МАСШТАБ → пилот Ф2.5 (гейт резюме-строки 80; строки 62–68, 85) → Ф3 ридер-IDE (69–71). **Стоячие:** ToS-триггер 25.10 · Ш-2 до go1.27 (⚠ + x/text Unicode 17 тем же тулчейном — строка 119, реестр §Б-108 справочника якорей) · платные прогоны разблокированы (проба провода — D39.97, конфиги 112 залендены). -> - **Стек (полная карта роль→модель→конфиг→квирки — [STACK.md](STACK.md), D39.126):** draft deepseek-v4-flash thinking-ON `low` **⚠0731** → терминолог (та же модель) → editor deepseek-v4-pro БИЛИНГВ ИНТЕРИМ (топология ПОДТВЕРЖДЕНА при неразличимости жильцов — D39.117; закон-блок ОБЯЗАТЕЛЕН — строка 134; glm-5 резерв; вахта маппинга эффорта pro — §Б-108) → судья gemini (Ф2, в движке НЕ построен — строка 33); канал B Mistral+grok; ~$0.85/ранобэ (D30.4) — ⚠ **ТРИГГЕР ПЕРЕ-КАЛИБРОВКИ СРАБОТАЛ 31.08** (испр. 02.09): платный прогон отработал и дал собственную оценку движка `projected_book_usd = 1.1377277707` на десяти главах при куплённых $0.436110; число D30.4 держать как июльское. ⚠ **Вендор-факты 13–15.08 (пере-пин ИСПОЛНЕН и ПРИНЯТ, D39.137):** таблица цен запинена ПИКОМ (flash 0.44/1.32 · pro 1.32/3.96/кэш-хит 0.044 за 1M; счёт шиппинг-c1 = 100% DeepSeek ⇒ ×4.2–4.4 в пике / ×2.1–2.2 в долине — замер по трём прогонам); ⚠ про эффорт pro носители ПРОТИВОРЕЧАТ, до вендор-сверки в силе канон — разбор строкой **237**(б); ⚠ ВЕСА pro сменились под тем же слагом (V4-Pro-0813, класс D39.61) — вахта-риг готов (остаток 172); покупки фазы Д на deepseek до 16.08 16:00 UTC — по старым ценам. ⚠ **ВЕСЬ банковый контур (банкнота+терминолог+классификатор) в shipping-c1 НЕ включён** — жив ран-локальным конфигом книги (строка 140; сверка STACK.md 09.08 — факт шире прежней декларации «одна банкнота»); эскалация в shipping за `budget_usd: 0` (STACK.md §примечания). -> - **ЕДИНЫЙ БЭКЛОГ — секция «Бэклог» ниже** (одна таблица, единственный трекер; каждая петля обязана иметь диспозицию: решено / отложено-с-записью / отклонено; ведёт оркестратор). **СЧЁТ ОЧЕРЕДИ на 30.08 (скриптом по таблице — `python3 docs/scripts/counts.py`; обновлять при каждом лендинге):** всего **192** строки · зона бэкенд **88** строго / **126** широко (⚠ колонки счётчик читает С КОНЦА — испр. D39.116) · **блокеров очереди 0** (236 закрыта D39.175), платные прогоны разблокированы · «скоро» **60** (перечень — грепом по таблице, рукописный список снят D39.126) · гейт-строки эксп-22: 55·153 (плюс 150 — руки владельца); строка 5 — остаток гейчен ре-пробой 74, носитель события теперь строка 188 (аудит D39.140); остальное «когда-нибудь». ⚠ Счёт — НИЖНЯЯ граница долга, не потолок (разбор — легенда таблицы ниже). +> - **Стек (полная карта роль→модель→конфиг→квирки — [STACK.md](STACK.md), D39.126):** draft deepseek-v4-flash thinking-ON `low` **⚠0731** → терминолог (та же модель) → editor deepseek-v4-pro БИЛИНГВ ИНТЕРИМ (топология ПОДТВЕРЖДЕНА при неразличимости жильцов — D39.117; закон-блок ОБЯЗАТЕЛЕН — строка 134; glm-5 резерв; вахта маппинга эффорта pro — §Б-108) → судья gemini (Ф2, в движке НЕ построен — строка 33); канал B Mistral+grok; ~$0.85/ранобэ (D30.4) — ⚠ **ТРИГГЕР ПЕРЕ-КАЛИБРОВКИ СРАБОТАЛ 31.08** (испр. 02.09): платный прогон отработал и дал собственную оценку движка `projected_book_usd = 1.1377277707` на десяти главах при куплённых $0.436110; число D30.4 держать как июльское. ⚠ **Вендор-факты 13–15.08 (пере-пин ИСПОЛНЕН и ПРИНЯТ, D39.137):** таблица цен запинена ПИКОМ (flash 0.44/1.32 · pro 1.32/3.96/кэш-хит 0.044 за 1M; счёт шиппинг-c1 = 100% DeepSeek ⇒ ×4.2–4.4 в пике / ×2.1–2.2 в долине — замер по трём прогонам); ⚠ про эффорт pro носители ПРОТИВОРЕЧАТ, до вендор-сверки в силе канон — разбор строкой **237**(б); ⚠ ВЕСА pro сменились под тем же слагом (V4-Pro-0813, класс D39.61) — вахта-риг готов (остаток 172); покупки фазы Д на deepseek до 16.08 16:00 UTC — по старым ценам. ⚠ **ВЕСЬ банковый контур (банкнота+терминолог+классификатор) ВКЛЮЧЁН в shipping-c1 с `b8154cd`** — `enabled: true` у обоих гейтов и `classify_types: true`, бюджеты по $1.00 (прежде жил только ран-локальным конфигом книги; строка 140 — ⛔ его единственный вход `mining.contrast_path` в git ОТСУТСТВУЕТ, развёртывание обязано положить артефакт, иначе контур не исполняется вовсе, носитель — строка 251; сверка STACK.md 09.08 — факт шире прежней декларации «одна банкнота»); эскалация в shipping за `budget_usd: 0` (STACK.md §примечания). +> - **ЕДИНЫЙ БЭКЛОГ — секция «Бэклог» ниже** (одна таблица, единственный трекер; каждая петля обязана иметь диспозицию: решено / отложено-с-записью / отклонено; ведёт оркестратор). **СЧЁТ ОЧЕРЕДИ на 30.08 (скриптом по таблице — `python3 docs/scripts/counts.py`; обновлять при каждом лендинге):** всего **191** строки · зона бэкенд **88** строго / **126** широко (⚠ колонки счётчик читает С КОНЦА — испр. D39.116) · **блокеров очереди 0** (236 закрыта D39.175), платные прогоны разблокированы · «скоро» **60** (перечень — грепом по таблице, рукописный список снят D39.126) · гейт-строки эксп-22: 55·153 (плюс 150 — руки владельца); строка 5 — остаток гейчен ре-пробой 74, носитель события теперь строка 188 (аудит D39.140); остальное «когда-нибудь». ⚠ Счёт — НИЖНЯЯ граница долга, не потолок (разбор — легенда таблицы ниже). > - Архивы хроники: `archive/PROGRESS-2026-07-04-10.md` (D31) · `-10-13` (D39.6-гигиена) · `-13-25` (стройка паков 11–16, rerun2) · **`-25-31` (паки 17–20 · мини-прогон · полигон-пакеты 5–8 · ToS · холодный прогон; D39.26–58)** · **`-08-01-02` (сессии №9/№10: общность · качество банка · coldrun-b · открытие фронта/платформы; D39.59–90, срез D39.105)** · **`-08-02-04` (сессии №11–№13: ручки эффорта · стандарты · контракт API · платформа P0 · банк-арбитраж; D39.91–105 + снимок шапки эры №15)** · `-08-04-09` (пинги закрытых паков эры №15) · **`-08-14-15` (закрытые бэкенд-записи №16–17: эмиттер шва · migrate · пере-пин DeepSeek; вынесено D39.139)**. Записи ниже — живой хвост (№16+, эра D39.124+; подрезка D39.139). ## 📌 СОСТОЯНИЕ ПАКОВ **Залендены и ратифицированы, приёмочные дампы — телами нот:** платформенный **P11** — D39.169 · движковый пак **«деньги»** — D39.170 · платформенный **P12** — D39.180 (вместе с контрактным минором **0.9.0**; `PD-425` закрыт им же) · бэкенд-пак **«деньги и честность выдачи»** — D39.182 (тестов 1045→1083, удалённых ноль) · **закон раскрытия** движка — D39.181, ратифицирован владельцем и применён к одиннадцати экземплярам. -**ВЫДАНЫ 04.09 и РАБОТАЮТ ПАРАЛЛЕЛЬНО** (зоны независимы по коду; сцеплений ДВА, и второе найдено 04.09 уже после выдачи промтов — оба про то, чтобы не сорвать платный прогон платформы: +**ВЫДАНЫ 04.09; ПЛАТФОРМЕННЫЙ ОТРАБОТАН, ПРИНЯТ И ЗАЛЕНДЖЕН `adf5e53` (D39.194) — контрактный минор 0.10.0 ратифицирован тем же актом, промт в `archive/prompts/`; ДВИЖКОВЫЙ заленджен КОДОМ `b8154cd`, но его приёмка НЕ ЗАКРЫТА: зона крутит петлю D39.191 над своей же работой, круг 3 отработал (68 посадок, 20 переживших, все закрыты), акт с диспозициями строк 210·113·46·134·140·184·232 пишется по её итогу. РАБОТАЛИ ПАРАЛЛЕЛЬНО** (зоны независимы по коду; сцеплений ДВА, и второе найдено 04.09 уже после выдачи промтов — оба про то, чтобы не сорвать платный прогон платформы: > **(1) форма манифеста ЗАМОРОЖЕНА на окно** (`D39.190` п.5): гейт интейка — строгое равенство одной константе, бамп отправил бы каждую книгу в `parser_unavailable`. > **(2) ⚠ ДАННЫЕ ЯЗЫКОВОГО ПАКЕТА — ТОЖЕ.** Правка `backend/internal/lang/data/*.txt` двигает `EmbeddedVersion` → `cutTag` (докстринг `backend/internal/pipeline/manifest.go`: «the embedded data feeds the CJK numerals and sentence terminators that place boundaries») → ключ валидности манифеста → на платформе `recut := storedKey != in.ManifestKey` (`platform/internal/pgstore/readmodel.go`) → `delete from unit_resolutions where book_id`. То есть у книги, за которую заплачено, исчезают замечания читателя и счётчики глав — это строка бэклога **198**. ⇒ **Лендинг правки данных не кладётся, пока книга платного прогона живая**; порядок лендинга — обязанность оркестратора, зоны об этом предупреждены пингами 04.09. Рычаг у бэкенда есть и он объявлен предпочтительным: снять рендер в Go, данные не трогать): бэкенд — вайр-батч `docs/BACKEND_WIREBATCH_SESSION_PROMPT.md`; платформа — «закрыть цикл» `docs/PLATFORM_EXPORT_SESSION_PROMPT.md`. ⚠ Строка **160** взята, но идёт СВОИМ паком ПОСЛЕ двери: она бампает `manifestVersion`, у которого безопасного порядка деплоя нет (`D39.190` п.2). Строка **142** — после шагов 0–1 полигона (`D39.190` п.3). > **Предыдущие паки ОТРАБОТАНЫ 03.09, ПРИНЯТЫ С ДОФИКСОМ и заленджены** (`D39.187` движок, `D39.188` платформа; промты в `archive/prompts/` с баннерами исхода; план паков отработал и ушёл в `archive/reports/NEXT_PACKS_PLAN_2026-09-03.md`; решения — D39.190, промты ВЫДАНЫ 04.09): платформенный **P13** «шов возврата оплаченного прогона» (`docs/PLATFORM_P13_SESSION_PROMPT.md`: `PD-168` бюджет из холда · `PD-89` ключ на пути ошибки · `PD-426`/`PD-214` чужая строка не карантинит проекцию · `PD-374` гейт батареи · гейт против класса серьёзности · строка рантбука деплоя) и бэкендовый **«число согласия на пути второй покупки»** (`docs/BACKEND_CONSENT_SESSION_PROMPT.md`: ФЧ-5 ось модели · строка 232 остаток слота · ФЧ-4 обе половины · ФЧ-1 три гарантии). ⚠ **Сцепление по деплою названо в обоих: у формы манифеста БЕЗОПАСНОГО ПОРЯДКА НЕТ** — гейт интейка `platform/internal/ingest/manifest.go:112`=`if m.Version != KnownManifestVersion` сравнивает со строгим равенством одной константе, окна двух версий нет; рантбук `platform/deploy/README.md:232`=`сначала платформа, потом движок` советует обратное и отдан на починку паку P13 пунктом 6. @@ -116,7 +116,7 @@ | 136 | **Write-ahead intent + состояние `uncertain`-эскроу + `closing`**: холд НЕ освобождается по выходу юнита (сигнал обгоняет денежные события); spend не постится без свидетельства провайдера; расход сверх холда — полной суммой, превышение явной строкой убытка | платформа/бэкенд | скоро (промты по команде владельца) | стройка по research/25 | D39.106 | | 137 | **Ночная сверка расходов с данными провайдера** (в движок цены входят float64 по ручной таблице `ledger/pricing.go` — систематика процентная; сверка приоритетнее споров об округлении) | платформа | когда-нибудь (до первого платного пользователя) | стройка по research/25 | D39.106 | | **— НАХОДКИ ПРИЁМКИ ЭКСПОВ 18–20 (D39.108) —** | | | | | | -| 140 | **Банковый контур в shipping-c1 НЕ включён — и это ШИРЕ прежней постановки про одну банкноту (сверка STACK.md, D39.126 п.2а): терминолог и классификатор тоже живут только ран-локальным конфигом книги** (ратифицированный путь D39.42 п.4; coldrun 56/128; `gates.terminology`/`gates.banknote` в c1 = 0 вхождений); решить: включить в c1 (двигает промпт драфта → RequestHash — цену назвать) либо поправить декларацию; родня 36г | владелец → бэкенд | скоро | СТОП-решение | D39.108, exp20 §6, **D39.126** | +| 140 | **Банковый контур в shipping-c1 НЕ включён — и это ШИРЕ прежней постановки про одну банкноту (сверка STACK.md, D39.126 п.2а): терминолог и классификатор тоже живут только ран-локальным конфигом книги** (ратифицированный путь D39.42 п.4; coldrun 56/128; `gates.terminology`/`gates.banknote` в c1 = 0 вхождений); решить: включить в c1 (двигает промпт драфта → RequestHash — цену назвать) либо поправить декларацию; родня 36г ⚠ **ВНЕСЁН `b8154cd` (вайр-батч, п.4): в shipping-c1 стоят `gates.banknote.enabled: true`, `gates.terminology.enabled: true` и `classify_types: true`.** Лид строки выше описывает состояние ДО лендинга и оставлен как история. **ОСТАТОК, которым строка ещё жива:** развёртывание — `mining.contrast_path` в git отсутствует и обязан лечь рядом с конфигом ПЕРЕД выкаткой, иначе контур не исполняется вовсе (три гарда добавлены, отказ по имени пути до первого платного вызова); пар-перекос корпуса контраста — строка 251. Закрытие — актом приёмки движкового пака. | владелец → бэкенд | скоро | СТОП-решение | D39.108, exp20 §6, **D39.126** | | 141 | **ОСТАТОК — работа В ДЕТЕКТОРЕ, и она НЕ про потерю текста.** ⚠ **Дыра, которой строка была заведена, ЗАКРЫТА лендингом D39.164:** сноска с ханьцзы («`[1] 蛊真人 — название романа.`») мимо детектора примечаний проходит по-прежнему, но поднимает класс `CJKLeak`, он `CosmeticOnly` (`backend/internal/checks/sanitizer.go:161-163`), юнит уходит `sanitizer_stripped` — и маркер дыры выдачи, заведённый паком «тихая порча», для НЕГО правдив. То есть читатель дыру ВИДИТ. Осталось: сноска БЕЗ ханьцзы («`[1] Название романа.`») не поднимает ни одного класса (замер сессии: `total=0`) и едет как есть — но текста при этом НЕ теряет, это лишняя добавка, а не дыра, и маркер на ней ДЕЗИНФОРМИРОВАЛ бы. Ловля таких сносок — правка самого детектора, отдельный предмет | бэкенд | когда-нибудь | правка детектора + тест | D39.108 (приёмка 20); половина закрыта D39.164 | | 142 | **Механизм «гейты флагают → точечная починка по флагу» как прод-путь**: exp20 §3.3 — $0.0002/дефект, 12/12 (при ИДЕАЛЬНОЙ детекции); механизм конкурентов (research/22:179), у нас петля пака-16 за `enabled:false` (строка 13); детекторы «выдуманное слово»/«инверсия» прототипированы эксп-21. **ДИСПОЗИЦИЯ D39.117:** ОТКЛОНЁН как замена редактора (`C2/A_law` −3.75 Holm 0.0006; «$0.0002 чинит всё» мерилось при идеальных флагах и при реальной детекции пало), ПРИНЯТ формой «механический ПРЕ-ГЕЙТ перед редактором» — брак 5 клеток против 10/23 при половинной цене ($0.00298/$0.00602); ремонт ТОЛЬКО с банком (без банка ломает канон 0.917→0.895) | владелец → бэкенд | скоро (форма решена D39.117; стройка — бэкенд-промтом по команде владельца) | бэкенд-промт | D39.108, **D39.117** | | 143 | **Абсорбция норматива судейства в `09-pilot-protocol.md`**: разброс инструмента ДО замера · объявленный порог различимости · MQM-lite/error-span первичен, pairwise только для стиля · декой обязателен · запрет судьи семейства жильца арма | полигон/оркестратор | скоро ($0) | правка дока | D39.108, exp20 §7 | @@ -168,7 +168,7 @@ | 198 | **Апгрейд движка стирает замечания и счётчики книги БЕЗВОЗВРАТНО — композиция двух половин, каждая известна по отдельности** (приёмка P7, линза «вне карты», обе половины пере-прочитаны оркестратором). Платформа при смене `manifest_key` сносит ВСЕ `unit_resolutions` книги (`platform/internal/pgstore/readmodel.go:164-165`), рассчитывая, что поток их пере-наполнит; движок анонсирует юнит РОВНО ОДИН РАЗ за жизнь книги — ключ `unit::::` БЕЗ метки нарезки (`backend/internal/pipeline/events.go:399-400`), а леджер анонсов переживает прогоны (`backend/internal/store/outbox.go:96` «already announced… by one that ran before it») ⇒ совпавшие координаты не переанонсируются НИКОГДА. Обостряется порядком: долг на материализацию ставится только на ГРАНИЦАХ работы, поэтому первая зачистка после апгрейда случается в КОНЦЕ первого пост-апгрейдного прогона и сносит замечания ТОГО ЖЕ прогона, за который заплачено. Следствия на проводе: «0 из N» на переведённой книге навсегда · шкала снова предлагает купить переведённое · замечания читателя исчезают. **Лечится с обеих сторон:** движковая половина — метка нарезки в ключе анонса (решение зоны движка), платформенная — не сносить вслепую либо восстанавливать из экспорта. ⚠ Гейт холодного прогона: смысл упражнения — гонять книгу против МЕНЯЮЩЕГОСЯ движка, то есть первый же апгрейд обнулит библиотеку | бэкенд + платформа | **скоро (до первого реального пользователя И до холодного прогона с апгрейдами)** | связка: решение по ключу анонса в движке → правка платформы | приёмка P7 (D39.153) | | 201 | **Движковое «Глава N» доезжает читателю ВНУТРИ текста, обходя дисциплину `heading: null`** (линза шва P7, пере-прочитано оркестратором): `backend/internal/pipeline/export.go:58`=`ApplyHeading` (испр. оркестратором №20 30.08: якорь уезжал с `:230` и с `:266` — код растёт) приклеивает детерминированный порядковый к экспортному тексту первой юнит-главы (`ce.FinalText = chunk.ApplyHeading(...)`), колонка `Source` при этом остаётся heading-stripped. Платформа переносит обе как есть и честно отдаёт `heading: null` — то есть клиент нарисует СВОЙ порядковый на языке своего интерфейса над абзацем, который уже начинается с русского «Глава N», а исходная колонка соответствующего маркера не несёт: пара визуально рассинхронизирована на каждой первой главе. Конкретное следствие открытого К-2 контракта; родня движковой строки **160** (глава без заголовка) | бэкенд | когда-нибудь (с 160) | отдельное решение | приёмка P7 (D39.153) | | 202 | **Живой перевод книги НАСКВОЗЬ через API платформы не гонялся НИ РАЗУ** (obstacle сессии P7, подтверждён приёмкой): всё после «прогон стартовал и остановился» — подпись банка, halt на потолке, резюм после пополнения — покрыто батареей против живого Postgres, но с движком-заглушкой; настоящий манифест, сайдкар банка и причины флагов будут ПЕРВЫМИ данными, форму которых платформа не сочинила сама. Форма проверки (решена): только через API, как ходил бы клиент — интейк → старт → живой движок с ключами провайдера → поток событий → подпись и продолжение → чтение глав/юнитов/замечаний/банка и сверка с тем, что движок реально произвёл; качество перевода НЕ предмет (полигон). ⚠ **Цена ≈$0.05 СНЯТА как протухшая** (D39.179 п.1: пере-пин DeepSeek, множитель ×4.47; испр. 02.09). Замер 31.08 на ровно такой десятиглавой книге: **куплено $0.436110** при собственной проекции движка **`projected_book_usd = 1.1377277707`** и полном оттоке кассы **≈$1.44** (§4 отчёта). ⚠ Это цена НЕПОЛНОГО захода — доставлено 3 юнита из 14; как смету для покупателя брать нельзя. ⚠ Путь ключей платформы — переменная `TM_PLATFORM_ENGINE_KEYS_PATH`, требует АБСОЛЮТНОГО пути (греп по `platform/internal/config/`). **Решение владельца 20.08: ПОСЛЕ холодного прогона движка** — гонять одну неготовую систему против другой смысла нет | платформа | скоро (⚠ прежний гейт «холодный прогон движка» ПАЛ 31.08; живой блокер теперь один — файл ключей платформы `TM_PLATFORM_ENGINE_KEYS_PATH`, лечение операционное и $0) | короткая сессия по промту оркестратора | слово владельца 20.08, D39.153 | -| 203 | **Хвосты контракта после синка 0.4.0 — ОТКРЫТ ОДИН ПУНКТ, остальное исполнено** (тела релеев — `platform/docs/archive/P7_ACCEPTANCE_HANDOFF_2026-08-17.md` §7; сюда переписан НЕ текст, а статус — один носитель на факт). **ИСПОЛНЕНЫ и сверены грепом при лендинге:** (а) минором 0.5.0 (D39.161) · (б) · (д) · (и) поле `stop_requested` (D39.152) · (л)(м)(н)(о) контрактной сессией — остаток по фразам Приложения А несёт строка **204** и лист владельца. **(г) наполовину** — `unspecified` ратифицирован в каноне (`docs/architecture/14-api-contract/openapi.yaml:1903`=`is reserved and is the server`), открыта только ГРАНИЦА ступеней замечаний (две ступени при девяти рангах движка); ⚠ её прежний носитель — строка 148 — СНЯТ 21.08 по слову владельца. **(з) СНЯТ как ратификация 22.08 сквозной трассировкой (разбор, на который ссылается строка 191):** конфликта моделей НЕТ — гейт движка проверяет полноту не ПОДПИСЕЙ, а ФАЙЛА решений, и ОДИН файл со всем банком его снимает (`loadMinedDelta` штампует только `Source`, `mining.go:855-867` → опущенный статус дефолтится в `approved`, `membank/memseed.go:96`=`status = "approved"` → `unsignedEngineSurfaces` выбрасывает лишь `Source=="mined" && Status!="approved"`, `mining.go:710-719`). Пере-диспозиция 27.08 (D39.158 п.7): движковый гейт полноты УСТРАНЁН, не обойдён; остаётся снять обход в платформе — одна боевая строка (`platform/internal/runs/spawn.go`, `--verify-bank` не передаётся на resume) плюс семь строк ставшего ложным обоснования, работа платформенного пака. **ОТКРЫТО РЕАЛЬНО — (к):** ключ `project_db` в `book.yaml`, договорить, кто им владеет: шаблон оператора его не содержит, движок делает необязательным. ⚠ Следствие «на штатном деплое банк не читается» ОПРОВЕРГНУТО живым кодом: путь публикует ДВИЖОК конвертом артефактов, пустой путь — ГРОМКИЙ отказ (`platform/internal/runner/artifacts.go:39`=`the engine published no bank read-out path`); остаток (к) чисто договорной| контракт/доки | скоро (следующее касание контракта) | контрактная сессия | приёмка P7 (D39.153) | +| 203 | **Хвосты контракта после синка 0.4.0 — ОТКРЫТ ОДИН ПУНКТ, остальное исполнено** (тела релеев — `platform/docs/archive/P7_ACCEPTANCE_HANDOFF_2026-08-17.md` §7; сюда переписан НЕ текст, а статус — один носитель на факт). **ИСПОЛНЕНЫ и сверены грепом при лендинге:** (а) минором 0.5.0 (D39.161) · (б) · (д) · (и) поле `stop_requested` (D39.152) · (л)(м)(н)(о) контрактной сессией — остаток по фразам Приложения А несёт строка **204** и лист владельца. **(г) наполовину** — `unspecified` ратифицирован в каноне (`docs/architecture/14-api-contract/openapi.yaml:1948`=`is reserved and is the server`), открыта только ГРАНИЦА ступеней замечаний (две ступени при девяти рангах движка); ⚠ её прежний носитель — строка 148 — СНЯТ 21.08 по слову владельца. **(з) СНЯТ как ратификация 22.08 сквозной трассировкой (разбор, на который ссылается строка 191):** конфликта моделей НЕТ — гейт движка проверяет полноту не ПОДПИСЕЙ, а ФАЙЛА решений, и ОДИН файл со всем банком его снимает (`loadMinedDelta` штампует только `Source`, `mining.go:855-867` → опущенный статус дефолтится в `approved`, `membank/memseed.go:96`=`status = "approved"` → `unsignedEngineSurfaces` выбрасывает лишь `Source=="mined" && Status!="approved"`, `mining.go:710-719`). Пере-диспозиция 27.08 (D39.158 п.7): движковый гейт полноты УСТРАНЁН, не обойдён; остаётся снять обход в платформе — одна боевая строка (`platform/internal/runs/spawn.go`, `--verify-bank` не передаётся на resume) плюс семь строк ставшего ложным обоснования, работа платформенного пака. **ОТКРЫТО РЕАЛЬНО — (к):** ключ `project_db` в `book.yaml`, договорить, кто им владеет: шаблон оператора его не содержит, движок делает необязательным. ⚠ Следствие «на штатном деплое банк не читается» ОПРОВЕРГНУТО живым кодом: путь публикует ДВИЖОК конвертом артефактов, пустой путь — ГРОМКИЙ отказ (`platform/internal/runner/artifacts.go:39`=`the engine published no bank read-out path`); остаток (к) чисто договорной| контракт/доки | скоро (следующее касание контракта) | контрактная сессия | приёмка P7 (D39.153) | | 204 | **Движок не публикует причины флагов ДАННЫМИ — карта причин у платформы рукописная и расходится молча** (релей §7(в) хендоффа P7; зона платформы в чужой бэклог не пишет и просила строку сюда — `platform/docs/archive/platform-PROGRESS-P7.md:206`). Сегодня `platform/internal/ingest/notes.go` держит рукописную копию закрытого словаря ЧУЖОЙ зоны: 15 причин движка → коды замечаний контракта, сверено побайтно на 20.08 и верно СЕЙЧАС. Импортировать движок платформе нельзя (D39.85 — разные модули), поэтому расхождение появится молча в тот день, когда движок добавит причину: платформа отдаст `unspecified` и напишет ERROR в лог, то есть деградация честная, но карта протухнет незаметно. ⚠ **Правила заполнения контрактных фраз по этим причинам УЖЕ НАПИСАНЫ** и выводить их заново не надо — компаньон `14-api-contract/README.md`, греп `по ДОККОММЕНТУ` (фраза пишется по доккомменту `disposition.go`, а не по имени константы; класс 2 схлопывается в ОДИН код). Лечение: движок публикует свой словарь причин артефактом-данными (тем же классом, что манифест и сайдкары банка), платформа читает его вместо копии. ⚠ Класс: носителем был ТОЛЬКО регистр платформы (PD-246) — обязательство к ЧУЖОЙ зоне жило внутри зоны автора | бэкенд | когда-нибудь (со следующим касанием эмиссии флагов) | отдельное решение | приёмка P7 (D39.153), релей §7(в) | | 205 | **Гейт якорей ИСПОЛНЕН 21.08** — `docs/scripts/counts.py --lint`, область `docs/` + `platform/docs` + `frontend/docs`, сверка по СОДЕРЖИМОМУ, двусторонняя дельта. ⚠ Быстрый выход по «коммит не трогает docs/» из хука убран НАМЕРЕННО: цели якорей — в основном КОД, и главный двигатель протухания приезжал ровно тем коммитом, на котором хук молчал. Форма якоря: ОПТ-ИН токен ожидания `` `путь:12-14`=`подстрока` ``, сверка ПРОБЕЛЬНО-нормализованная. ⚠ **Слепота печатается САМИМ гейтом каждый прогон — читать оттуда, копии здесь нет.** Одна её грань в вывод не попала: в ручном прогоне «дельта» = всё незакоммиченное кем угодно, поэтому ТРЕБОВАНИЕ токена живёт только под `--from-index` (ПРОВЕРКА уже написанных токенов дельтой не ограничивается вовсе — токен был истинным при записи, значит упавший есть гниль по построению). **ОСТАТОК:** миграция корпуса на токен-форму органическая — токен требуется на ЗАТРОНУТЫХ строках, счёт растёт сам с каждым касанием. ⚠ Числа здесь НЕ держим (прежняя редакция держала «4 из ~580» и протухла за сутки): текущий счёт токенов, якорей и доков гейт печатает КАЖДЫЙ прогон| оркестратор/доки | сделано 21.08, миграция органическая | исполнено; остаток гасится касаниями | аудит работы №18 + разбор с внешним ревьюером, 21.08 | | 207 | **Пол самосогласованности манифеста стоит только у материализатора, интейк тот же документ ПРИНИМАЕТ — и по такой книге можно ОПЛАТИТЬ прогон** (`PD-367`, вторая волна ревью P8-FIX). Манифест `{ChaptersTotal: 120, UnitsTotal: 400}` с пустым списком глав `Whole()` отвергает, а `books.Parse` заводит книгу `not_started` с `chapter_count=120` и пустым деревом; потолок считается ОТ `chapter_count`. **Очевидное лекарство опровергнуто исполнением самой зоной:** применить `Whole()` на интейке нельзя — вся батарея интейка ездит на манифестах без списка глав, контракт интейка это только счётчики. Значит решение не зонное: либо контракт интейка меняется, либо пол ставится в другом месте цепи | оркестратор → платформа | скоро | нужно решение (лекарство ломает запиненный контракт интейка) | D39.154 п.10, `PD-367` | @@ -178,7 +178,7 @@ | 214 | **Подпись банка не оставляет на банке НИ ОДНОГО следа.** Единственная долговечная запись акта подписи — булев `bank_released` на прогоне (`platform/internal/pgstore/runs.go`, греп `bank_released` (номер строки двигает живая сессия зоны)): кто и когда подписал, что именно вошло в подписанный набор — не хранится нигде. Следствие: пост-фактум ответить «почему в книге этот перевод термина» нельзя, а при пере-нарезке или пере-прогоне восстановить намерение человека не из чего. ⚠ **ЧАСТИЧНЫЙ ответ появился с дверью правок (D39.162):** её документы решений — долговечная запись того, ЧТО владелец решил, и они переживают прогон. Не отвечено по-прежнему: КТО и КОГДА подписал, и что именно вошло в подписанный набор. Всплыло трассировкой цепи банка 22.08, подтверждено пере-проверкой | платформа + бэкенд | когда-нибудь (с трубой доставки правок, D39.156) | отдельное решение о провенансе подписи | трассировка цепи банка 22.08, пере-проверено №19 | | 216 | **Подпись банка, halt на потолке и резюм после пополнения не проверялись против ЖИВОГО движка ни разу.** Проверки этих путей в батарее платформы стоят на фейках; единственный живой прогон движка в батарее — не по этим маршрутам. То есть три несущих сценария продукта держатся на договорённости о поведении чужой стороны, а не на замере. ⚠ Гейтится тем же, чем и живой прогон книги (строка 202): холодный прогон движка | платформа | когда-нибудь (с 202) | живой прогон по трём маршрутам | трассировка цепи банка 22.08, пере-проверено №19 | | 227 | **`signature` в квитанции двери правок считается от карты, которую переписывает ЛЮБАЯ граница майнинга** (находка воркфлоу-ревью P9, 28.08): запись карты стоит ВЫШЕ решения о стопе (`backend/internal/pipeline/mining.go:191`=`writeFileAtomic(r.signatureMapPath()`), поэтому `signature != null` НЕ означает состоявшегося стопа подписи; `surfaces`/`undecided` дрейфуют между двумя вызовами владельца, а `undecided: 0` достижим при НЕпредъявленных решениях (кап top-200 вытесняет). ⚠ Починка аддитивна и носитель для неё уже есть: карта несёт СВОЙ идентификатор (`backend/internal/membank/decisions.go:955`=`id, err := seed.SignatureMapID(content)`), а шов его не читает — отдать идентификатор в квитанцию и судить по нему. Цена сегодня мала (поле информационное, гейтом не служит) и растёт вместе с экраном подписи: именно он будет решать «что я подписываю» по этому числу | бэкенд | когда-нибудь (гейт: заказ экрана подписи) | аддитивная правка квитанции | воркфлоу-ревью P9, D39.162 | -| 228 | **Отклонённая поверхность возвращается АЛИАСОМ уцелевшей строки — движок не держит того, что канон уже обещает** (находка воркфлоу-ревью P9 в форме Д1, УЗКО пере-сформулирована бэкенд-сессией 28.08 и принята приёмкой): канон говорит дословно «declining a surface removes EVERY window of that surface» (`docs/architecture/14-api-contract/openapi.yaml:2079`=`declining a surface removes EVERY window`; адрес пере-нацелен 02.09 — минор 0.9.0 сдвинул прежний 2051), а эмиссия майнера энтити-широка (`backend/internal/pipeline/miner_emit.go`, `clusterTouches`), тогда как фильтр авто-банка ключуется только по собственному `src` строки (`backend/internal/pipeline/mining.go:662`). ⚠ **Правильная форма — снять АЛИАС со строки, а не снести строку:** расширение `decline` до энтити противоречило бы ратифицированному контракту, и именно поэтому бэкенд-сессия применила право §9 и НЕ чинила это попутно. Предмет — банковая онтология (`18-bank-ontology.md`), не тихая порча | бэкенд | скоро (гейт: заказ по читающей стороне банка) | отдельный заказ узкой формы | воркфлоу-ревью P9; форма — бэкенд-сессия 28.08, D39.164 | +| 228 | **Отклонённая поверхность возвращается АЛИАСОМ уцелевшей строки — движок не держит того, что канон уже обещает** (находка воркфлоу-ревью P9 в форме Д1, УЗКО пере-сформулирована бэкенд-сессией 28.08 и принята приёмкой): канон говорит дословно «declining a surface removes EVERY window of that surface» (`docs/architecture/14-api-contract/openapi.yaml:2124`=`declining a surface removes EVERY window`; адрес пере-нацелен 02.09 — минор 0.9.0 сдвинул прежний 2051), а эмиссия майнера энтити-широка (`backend/internal/pipeline/miner_emit.go`, `clusterTouches`), тогда как фильтр авто-банка ключуется только по собственному `src` строки (`backend/internal/pipeline/mining.go:662`). ⚠ **Правильная форма — снять АЛИАС со строки, а не снести строку:** расширение `decline` до энтити противоречило бы ратифицированному контракту, и именно поэтому бэкенд-сессия применила право §9 и НЕ чинила это попутно. Предмет — банковая онтология (`18-bank-ontology.md`), не тихая порча | бэкенд | скоро (гейт: заказ по читающей стороне банка) | отдельный заказ узкой формы | воркфлоу-ревью P9; форма — бэкенд-сессия 28.08, D39.164 | | 229 | **Снапшот не фолдит модель ВНУТРЕННИХ гейтов — флип провода под неизменным `request_hash`** (самонаходка бэкенд-сессии 28.08, подтверждена приёмкой): снапшот фолдит `Capability` СТАДИЙНЫХ моделей и их эскалации (`backend/internal/pipeline/snapshot.go:316-340`), но модель `gates.terminology.model` / `gates.repair.model` (`backend/internal/config/internal_call.go:72`) не фолдится сознательно — а терминолог шлёт ДВА системных сообщения, так что смена оси `capabilities.system_messages` у провайдера, которым пользуется только гейт, меняет байты запроса при неизменном хеше: тихий false-hit класса D5.2. ⚠ **Сегодня ЛАТЕНТНА и денег не стоит — проверено приёмкой: гейта `terminology` нет НИ В ОДНОМ конфиге репозитория** (`grep -c terminology configs/pipeline-c1.yaml` = 0). Триггер починки — день, когда гейт включат с провайдером, объявляющим НЕдефолтную возможность. ⚠ Цена лечения — денежная: фолд гейт-моделей сдвигает хеши и обесценивает чекпойнты; дешёвая форма — фолдить ТОЛЬКО недефолтное (приём `omitempty`, прецедент `MinMaxTokens`), тогда сегодняшние снапшоты остаются байт-равными | бэкенд | когда-нибудь (гейт: включение внутреннего гейта либо следующее касание снапшот-контракта) | правка снапшот-контракта | самонаходка бэкенд-сессии, D39.164 | | 230 | **Инертный `decline` подписанного сид-терма отвечает `already_applied` вместо единственной работающей инструкции** (названный размен пака «тихая порча», D39.164): сузив отказ по поверхности ради СХОДИМОСТИ повтора, движок потерял поучение в одном углу — когда отказ и записан, и по-прежнему инертен против `glossary_seed`, пользователь получает «уже применено» вместо «убери терм из сида». Сходимость сочтена более тяжёлой обязанностью (на ней стоит вся раскладка класса 15 и синхронная дверь платформы), но размен РЕАЛЕН. **Форма закрытия — поле отчёта со стоячим фактом**, то есть аддитивная правка формы шва: платформенный `BankReport` — аллоулист, лишнее поле на провод не уедет само | бэкенд + контракт | скоро (с ближайшим касанием отчёта двери) | аддитивное поле отчёта | размен пака «тихая порча», D39.164 | | 232 | **Ось «свежий/пере-делка» выведена из ПОЛНОТЫ СТРОК, а не из факта отгрузки** (D39.170, находки охотника 3 и 4). Следствия ДЕНЕЖНЫЕ на слух покупателя: добавление стадии в пайплайн превращает ДОЧИТАННУЮ книгу в «3 unit(s) NEVER delivered» и приглашает купить её снова; юнит, прерванный между волнами (signature stop, денежный потолок, Ctrl-C), второй раз считается свежим и тратит слот гранта повторно — замерено 4 купленных юнита → 2 главы. Носитель у движка УЖЕ есть: реестр анонсов `events_outbox.once_key` (`backend/internal/pipeline/events.go:396`=`unitOnceKey is the identity of one announcement`), ключ `unit:<книга>:<волна>:<глава>:<юнит>`, монотонный на всю жизнь книги и переживающий и добавление стадии, и обрыв между волнами. ⚠ **ПЕРВАЯ ПОЛОВИНА ИСПОЛНЕНА 31.08** (`bb541a8`, экземпляр A11; испр. 02.09): читающий метод `store.AnnouncedOnceKeys()` построен, его докстринг называет эту строку по номеру, предикат — `delivered[key] && unitShipped(rows)`. **ЖИВОЙ ОСТАТОК — ВТОРАЯ ПОЛОВИНА:** юнит, прерванный МЕЖДУ ВОЛНАМИ, повторно тратит слот гранта (разбор — `backend/docs/MONEY_HONESTY_REPORT.md` §4.5). ⚠ РАЗВИЛКА, которую надо назвать в промте: ключ несёт ВОЛНУ, значит «юнит отгружен» — факт per-wave. **Ответ есть и он не новый механизм:** отгрузкой считается волна, владеющая ОТГРУЖАЮЩЕЙ (последней) стадией — `backend/internal/pipeline/snapshot.go:243`=`finalStageWave is the wave that owns the SHIPPING (last) stage`; на редакторском конвейере это edit, на черновом-только — draft. Проверять надо ИМ, иначе черновой-только конвейер получит ось, которая никогда ничего не считает отгруженным (предложено движковой сессией при сдаче, сверено мной по коду) | бэкенд | скоро | Читающий метод стора + перевод оси на факт отгрузки; отдельный пак | приёмка D39.170 | @@ -190,13 +190,12 @@ | 243 | **Остаток аудита доков 30–31.08: 19 удержанных находок НЕ применены** (аудит — 5 линз + верификатор на каждую, 57 находок, 55 удержаны, 36 применены сменой №20). Перечень: ~~**arch-3**~~ **ЗАКРЫТ 31.08 — разбор телом D39.179 п.5** (был вдвое больше заявленного: 51 указатель вместо 13, и дороже адресов оказались ЛОЖНЫЕ КЛЕЙМЫ) · **arch-5** (правило языка знает две корзины, `reader.txt` — третья) · **arch-7** (§2 закона шва: дисциплина флока не описывает новый глагол-писатель) · **arch-9** (реестр загейченных триггеров не знает нажатых 30.08) · ~~**arch-10**~~ и ~~**arch-11**~~ **ЗАКРЫТЫ 02.09** (числа словаря событий сняты в пользу кода; отвергнутый ключ назван отвергнутым) · **arch-12** (шапка `09-target` сама зовёт себя неполной — строку под таблицей слоёв надо внести; ⚠ ЖИВ на 02.09: греп `D39.181` по `docs/architecture/09-target-architecture.md` — 0 хитов, греп `D39.182` — 0 хитов, то есть лендинги 31.08 в док слоёв не внесены) · **contract-8** (эррата 15.08-в в шапке D-лога указывает на промт, уехавший в архив) · **contract-10** (`Export.failure_code` «becomes an enum with the first built format» — формат построен, условие наступило) · **progress-6/7/8/10/11/12/13/14/15** (мелочь CURRENT-STATE и строк бэклога: протухшие «запушена»/«строка 200»/якорь `miner_emit.go`/дубль 238 внутри 160 и пр.). ⚠ Отчёт аудита жил в песочнице сессии №20 и умирает с ней — здесь ЕДИНСТВЕННЫЙ носитель списка; воспроизведение = повторный аудит (5 агентов, ~2 часа) | оркестратор | скоро | пройти списком | аудит доков 30–31.08, сдача смены №20 | | 244 | **Гейт якорей на пре-коммите ломается всякий раз, когда зона правит КОД и СВОЙ реестр одним незакоммиченным деревом** — и врёт в обе стороны. Механика: хук судит ЗАКОММИЧЕННЫЙ док против РАБОЧЕГО кода, поэтому пере-нацеленные, но не залёнджённые якоря читаются как битые. Замерено на приёмке P12 31.08: у оркестратора хук напечатал 13 битых якорей `platform/docs/DEFECT_REGISTER.md`, у зоны `counts.py --lint` на том же дереве дал **0**; права зона — в HEAD `internal/runs/runs.go:323`, в рабочем `:347`, и токен по новому адресу на месте. ⚠ Обратная сторона опаснее и не замерена: якорь, ставший битым ПО-НАСТОЯЩЕМУ, тем же механизмом может оказаться зелёным. Свойство общее, не про этот пак | оркестратор | когда-нибудь | либо судить обе стороны из одного состояния (`--from-index` уже есть — проверить, покрывает ли он случай), либо печатать, что сравниваются РАЗНЫЕ состояния | приёмка P12 оркестратором №21, 31.08, разрешено командой | | 245 | **Pathspec-форма коммита молча роняет UNTRACKED-файлы, и сломанный коммит выглядит нормальным до первого чужого прогона.** `git commit -- <пути>` обходит ИНДЕКС и берёт рабочее дерево только для ОТСЛЕЖИВАЕМЫХ путей: предварительный `git add` нового файла она игнорирует. Поймано на лендинге P12 31.08 — коммит `e1cb692` унёс `migrations.sha256`, уже ссылавшийся на три миграции, а сами миграции 00029/00030/00031 и три теста остались снаружи; починено амендом секундного неопубликованного коммита при пустом индексе (`0a680a3`). ⚠ Канон git-координации в `CLAUDE.md` объясняет про pathspec ТОЛЬКО то, что она не трогает чужой индекс — то есть учит половине правды и ровно этим создаёт ловушку. Норма, которую предлагаю вписать: новые файлы стейджить явно и проверять состав `git show --name-only`, а не доверять форме. ⚠ **ПОЛОВИНА ПОСТРОЕНА 31.08** (`94381bb`, испр. 02.09): в `docs/scripts/githooks/pre-commit` стоит warn-блок, который перед каждым коммитом печатает неотслеживаемые файлы в каталогах коммита. Живой остаток — блок ПРЕДУПРЕЖДАЕТ, но не блокирует, и на свежем клоне хук вообще не установлен (строка 220) | оркестратор | скоро (решение владельца — его канон) | одна строка в `CLAUDE.md` §«Git-координация мультисессий»; вписывает владелец или оркестратор по его слову | лендинг P12 оркестратором №21, 31.08 | -| 246 | ⚠ **ДВЕ КОПИИ ПОЛОСЫ ОТКАЗОВ 10–19 ОБЕЩАЮТ РАЗНОЕ — потребитель держит гарантию, которую производитель ОТОЗВАЛ.** Движок (`backend/cmd/tmctl/main.go:53`=`Nothing was written` is NOT the band's promise any more): «„Nothing was written“ is NOT the band's promise any more … **exit 15 legitimately answers with files on disk**». Платформа (`platform/internal/ingest/exit.go:38`=`nothing this process would have written was written`): «… and nothing this process would have written was written». ⚠ Опасность не теоретическая: по `PD-196` интейк действует по полосе РАЗРУШИТЕЛЬНО (отклоняет книгу и удаляет загрузку), а `exit 15` теперь легитимно оставляет файлы на диске. Хвост: движковый `exitBookIncomplete = 16` у платформы константы НЕ имеет вовсе (её словарь 10·11·12·13·14·15·19). ⚠ **Денежная половина ЦЕЛА в обеих копиях** (`nothing was spent` — по одному хиту в каждой), поэтому запрет отказывать классом полосы там, где деньги уже потрачены, в силе. Предсказано п.6 закона шва 17 ⚠ **ЗАКРЫТА 04.09 райдером платформенного пака «закрыть цикл».** Копия потребителя приведена к производителю: фраза «nothing this process would have written was written» СНЯТА, на её месте абзац, который отзыв называет прямо и цитирует движковую формулировку; `ExitBookIncomplete = 16` внесён в полосу, число подтверждено ЖИВЫМ движком. Денежная половина («nothing was spent») цела в обеих копиях — об этом в новом абзаце сказано отдельно. ⚠ **Якорь этой строки на `exit.go:38` МЁРТВ ОТ ЛЕЧЕНИЯ, а не от порчи:** фразы больше нет ни на одной строке, и пере-указывать его значило бы воскрешать дефект в доке. Якорь уходит вместе со строкой (разбор платформенной сессии 04.09, принят оркестратором). ⚠ Вес «СРОЧНО» был ПЕРЕОЦЕНЕН и это записано отдельно: интейк удаляет загрузку только на классе 11, а exit 15 производит один глагол — `bank-apply` | платформа (правка) + оркестратор (маршрут) | СРОЧНО ⚠ **ВЕС ПЕРЕ-СНЯТ 04.09 (сверка контролёра, пере-проверено): «разрушительно по полосе» ПЕРЕОЦЕНЕНО.** Интейк удаляет загрузку ТОЛЬКО на классе 11 (`platform/internal/books/parse.go`, греп `only source_unreadable removes it`), а exit 15 производит один глагол — `bank-apply`. Живой остаток — комментарий `platform/internal/ingest/exit.go` плюс константа `ExitBookIncomplete = 16`, которую дверь выдачи и так добавит; идёт РАЙДЕРОМ платформенного пака, а не срочным пунктом. ⚠ **ЛЕЧЕНИЕ В ДЕРЕВЕ 04.09, строка закрывается АКТОМ ЛЕНДИНГА платформенного пака** — до него держится как открытая, чтобы закрытие имело коммит. | зона платформы приводит свою копию к движковой ЛИБО обе стороны идут в ратификацию, если расхождение намеренное | пак «деньги и честность», находка A15 вне заказа, 31.08; пере-проверено оркестратором дословно обеими копиями; ЛЕЧЕНИЕ — райдер пака «закрыть цикл» 04.09 | | 247 | **§2.2 закона раскрытия опровергает себя следующей же строкой — эррата зонного дока.** Формальная фраза требует «держит ОБА операнда сравнения и обязано их НАПЕЧАТАТЬ», а её собственный пример тут же говорит обратное: честная форма — НАЗВАТЬ ОСЬ («снапшот разошёлся» честно, «конфиг/промпты изменились» ложно). ⚠ **Ратифицированный текст D39.181 п.1 требования «напечатать» НЕ СОДЕРЖИТ ВОВСЕ** — оно живёт только в `backend/docs/DISCLOSURE_LAW_DESIGN.md`, значит противоречия с ратификацией нет и решает ЗОНА, не владелец. ⚠ Довод «граница прячет имена моделей и хеши» ОПРОВЕРГНУТ исполнением: эти значения уже едут по тому же stderr штатным INFO-логом, включая `memory_version=<12 hex>` — значение того самого поля. Цена бездействия на живых данных = НОЛЬ (единственная сдвинувшаяся ось — хешевая, печать дала бы две несравнимые строки SHA) | бэкенд | когда-нибудь | эррата к §2.2: операнды называются осью, а не значением | приёмка D39.182 + разведка оркестратора 31.08 | | 248 | **Полнота самообъявления о правках чужих тестов ничем не проверяется — и трижды оказалась неполной.** P11 назвала файл, которого не трогала; P12 не назвала тест, у которого переписаны ОБА утверждения; сессия пака «деньги и честность» в первой редакции комментария утверждала неверное о силе собственной правки. ⚠ **Мой метод проверки был слабее, чем я его подал:** греп `^[-+].*t\.(Error|Fatal)` ловит строку СООБЩЕНИЯ, а утверждение — это строка СРАВНЕНИЯ, и она другая (замер: греп локализует утверждение в 1 случае из 475). Предложение разведки: warn-only гейт-детектор при лендинге — список пред-существующих тестов с изменёнными строками утвержденческой формы ВНУТРИ пред-существующих тел; прототип ~25 строк sh прогнан на двух лендингах и указал ровно на `bankfixpack_test.go`. Площадка есть — `docs/scripts/githooks/pre-commit` уже warn-only. ⚠ Ложняки измерены: целиком новый `t.Run` внутри старого `func` даёт срабатывание (1 из 6 на P12) | оркестратор | скоро | гейт-детектор warn-only + пункт чек-листа приёмки | разведка оркестратора 31.08 по вопросу владельца | | 249 | **Девять рядов бэклога потеряли слово веса, и гейт на них НЕ краснеет.** ⚠ **Лечение ПОСТРОЕНО (сверено кодом 02.09): вес судится ПРЕФИКСОМ ячейки** — `docs/scripts/counts.py`, греп `BACKLOG_WEIGHTS` (три слова: «блокер-очереди» · «скоро» · «когда-нибудь»), и «скоро» считается тем же префиксом. Этим убита ВТОРАЯ половина класса: подстрока ловила слово в ПРОЗЕ, и фраза «переведена из «скоро»» ре-добавляла ряд в счёт — число скакнуло **53 → 56** при одной новой строке (замер 02.09, пере-счёт скриптом). ⚠ Гейт рождён ЗЕЛЁНЫМ, а не красным: девять известных рядов внесены «дедовщиной» — греп `WEIGHT_GRANDFATHERED` там же, ряды **5 · 13б · 94 · 96 · 97 · 149 · 205 · 221 · 246**. **ЖИВОЙ ОСТАТОК — сами ячейки:** у 96/97 прочерк ЗАКОНЕН (надгробия строк, уехавших в зонный бэклог, D39.84), остальные семь потеряли вес молча и чинятся оркестратором — каждая починенная выходит из списка дедовщины. ⚠ Два ряда шире класса: **149** («исполнен и заленден 10.08») и **205** («сделано 21.08») объявляют себя ИСПОЛНЕННЫМИ прямо в колонке веса, хотя по правилу таблицы закрытые строки в ней не живут — это либо живой остаток без веса, либо непойманный класс C; **246** несёт самодельное «СРОЧНО», которого в словаре нет. | оркестратор | скоро ($0, гигиена трекера) | правка семи ячеек → выход из `WEIGHT_GRANDFATHERED` | ревизия доков 02.09, приёмка контролёра | | 217 | **Скрипты полигона захардкодили АБСОЛЮТНЫЕ пути двух корней и не работают на этой машине вовсе.** ДВА РАЗНЫХ слома. **Корень репо** — смена пользователя: литерал в 121 файле, из них 104 дословно `REPO = Path("/home/ubuntu/projects/textmachine")`, портабельных форм всего 5. **Корень книг** — оба события порознь: литерал `/home/ubuntu/books` 86 файлов (пользователь), портабельный `Path.home()/"books"` 89 файлов (переезд каталога; на прежних машинах работал). Объединение 173 файла. Пользователь теперь `ubuntu-26`, книги переехали в `<репозиторий>/books` ⇒ ломается и то и другое, включая ЖИВОЙ гейт фазы Д `eval/conformance.py:49`=`REPO = Path("/home/ubuntu/projects/textmachine")`. Живых носителей 26 по корню книг (среди них портабельная форма преобладает 20:6) плюс корневые гейты и сборщики корпусов; остальное — скрипты закрытых эксп-12–16, их владелец велел ВЫБРОСИТЬ, а не чинить (D39.157 п.4а). Форма правки — за зоной; приор оркестратора: один модуль путей, корень резолвится МАРКЕРОМ вверх по дереву (движок так и делает — `backend/internal/miner/miner_parity_test.go:29`=`derived from the repository MARKER`), книги от него, обе ручки перекрываются env | полигон | скоро (блокирует любой прогон зоны) | пак путей полигона | переезд машины 24.08, №19 | | 219 | **Line-якоря в тела D-лога обречены съезжать, и механизм именно в дисциплине эррат.** Эрраты вписываются в КАРТУ ШАПКИ (append-only, D23.3), то есть в начало файла, — значит каждая эррата сдвигает номера строк ВСЕХ тел ниже, и любой якорь вида `05-decisions-log.md:NNN` умирает молча. ⚠ Замерено на себе 27.08: три эрраты за сессию убили якоря в `docs/architecture/17-seam-inbound-law.md` (греп `Эррата, которую ратифицирующая нота обязана поставить`) и `docs/research/25-seam-cold-review.md:5`=`адресуем НОМЕРОМ, а не строкой` (оба целили в `:232`, тело уехало на `:239`; ⚠ 02.09 обе площадки уже переведены на форму номера ноты — прежний голый указатель `17-seam-inbound-law.md:120` показывает пустую строку). Лечение — не пере-нацеливание (оно повторится через эррату), а СМЕНА ФОРМЫ якоря: в тела D-лога целиться номером ноты (`^## D39.106`), который стабилен навсегда, а не строкой. ⚠ **Первая половина лекарства ПОСТРОЕНА:** `counts.py --lint` сверяет якоря в тела D-лога СТРУКТУРНО и без токена — владелец целевой строки (ближайший `^## D<номер>`) обязан совпасть с номером, названным рядом; остаётся перевести живые якоря на форму номера | оркестратор | скоро (растёт с каждой эрратой) | `--lint` учит форму `файл:^## D<номер>`, живые якоря в D-лог переводятся на неё | ревью доков 24.08, механизм и отсутствие носителя — 27.08, D39.160 | -| 220 | **Репо-широкий гейт доков бутстрапится пакетным менеджером ОДНОЙ зоны, и та заморожена.** Диспетчер `.git/hooks/pre-commit` зоно-нейтрален по построению (`for hook in */scripts/githooks/pre-commit`, `#!/bin/sh`, node не нужен) и судит `CLAUDE.md` + `docs/**` + `platform/docs/**` + `frontend/docs/**` (`docs/scripts/counts.py:536`=`ROOT / "CLAUDE.md"`), но единственный его УСТАНОВЩИК — `frontend/scripts/githooks/install.mjs`, вызываемый ключом `prepare` из `frontend/package.json`. Охват и бутстрап не совпадают ⇒ инструмент решает свою задачу не в полной мере. Проверено исполнением 24.08: на этой машине `.git/hooks/` содержал только `*.sample`, гейт МОЛЧАЛ, ничего не проверив, и поймал первые четыре дефекта только после ручной установки; сессия бэкенда или доков `npm install` не делает никогда. Приор: зоно-нейтральный установщик в `docs/scripts/githooks/` как ЕДИНСТВЕННЫЙ писатель диспетчера, `prepare` фронта зовёт его — фронтовая половина выписана пингом №19 в зонный журнал фронта. ⚠ Ручная установка — временная мера, пока строка открыта; записывать её как порядок работы ЗАПРЕЩЕНО (это ровно тот обход, цену которого называет шапка `CLAUDE.md`) | доки + фронт | скоро | зоно-нейтральный бутстрап + правка `prepare` при разморозке | аудит переезда 24.08, №19 | +| 220 | **Репо-широкий гейт доков бутстрапится пакетным менеджером ОДНОЙ зоны, и та заморожена.** Диспетчер `.git/hooks/pre-commit` зоно-нейтрален по построению (`for hook in */scripts/githooks/pre-commit`, `#!/bin/sh`, node не нужен) и судит `CLAUDE.md` + `docs/**` + `platform/docs/**` + `frontend/docs/**` (`docs/scripts/counts.py:554`=`ROOT / "CLAUDE.md"`), но единственный его УСТАНОВЩИК — `frontend/scripts/githooks/install.mjs`, вызываемый ключом `prepare` из `frontend/package.json`. Охват и бутстрап не совпадают ⇒ инструмент решает свою задачу не в полной мере. Проверено исполнением 24.08: на этой машине `.git/hooks/` содержал только `*.sample`, гейт МОЛЧАЛ, ничего не проверив, и поймал первые четыре дефекта только после ручной установки; сессия бэкенда или доков `npm install` не делает никогда. Приор: зоно-нейтральный установщик в `docs/scripts/githooks/` как ЕДИНСТВЕННЫЙ писатель диспетчера, `prepare` фронта зовёт его — фронтовая половина выписана пингом №19 в зонный журнал фронта. ⚠ Ручная установка — временная мера, пока строка открыта; записывать её как порядок работы ЗАПРЕЩЕНО (это ровно тот обход, цену которого называет шапка `CLAUDE.md`) | доки + фронт | скоро | зоно-нейтральный бутстрап + правка `prepare` при разморозке | аудит переезда 24.08, №19 | | 49 | **Этапы Б+В спеки D15.2** (content-addressed resume / `guard_hash` — D39.31 сознательно не строил) ; этап В = tmctl export-контракт D29.1 (annot-v1 · цвет-мап+rollup · политика красных fail-closed) + операторский протокол-документ релиза гендер-твиста (D5.1): сам механизм УЖЕ построен — until_ch-правка → точечный re-edit со сметой и $0-пере-пином (`repin.go`/`rebill.go`, D39.42 п.5/D39.45) | бэкенд | скоро (ПОДТЯНУТА D39.81: annot-v1 = источник замечаний для фронта — критический путь подключения) | отдельное решение (annot-половина — по контракту 14, D39.99) | D39.34(4), D33 п.5, D39.81 | | 49а | **ALTER-шаги миграций v8–v14 не идемпотентны вопреки шапке `migrate.go:9-11`** (полу-применённая БД не сходится; счётчик версий скрывает) — находка критика полноты пака-19 | бэкенд | когда-нибудь | отдельное решение | D39.56, PACK19_BUILD §6.9 | | 50 | F3-остаток идемпотентности | бэкенд | когда-нибудь | отдельное решение | D39.34(4) | @@ -504,6 +503,70 @@ Go: `terminology.Genders` + `ParseTypes` возвращает `types, genders, s ### Числа круга Батарея `MAKE_EXIT=0`, `0 issues`, 19 пакетов, скипы те же три. **Голден БАЙТ-ИДЕНТИЧЕН** тому, что был до починок круга (единственное движение голдена за круг — `classifier_version` от вывода версии экрана из констант; вердикты не двинулись). Тесты **1105 → 1156**. Каталог **92 → 120**, записи `WB1`–`WB29` красные одним прогоном. Удалённых имён по-прежнему одно — переименование `TestEditorSectionFollowsProvenance`. +## КРУГ 3 ПЕТЛИ (`D39.191`) — ЗАМКНУЛСЯ ПО СОДЕРЖАНИЮ, НО НЕ ПО УСЛОВИЮ: веер нашёл 20 переживших посадок и 1 дыру исполнением, все закрыты + +⚠ **Условие замыкания не выполнено и здесь.** Круг замыкается, только когда проход с непустым веером не нашёл НИ ОДНОЙ пережившей посадки. Этот нашёл двадцать — плюс дыру, найденную не посадкой, а исполнением. Ниже веер, все находки с диспозициями, что я перепроверила сама, и чего круг не покрыл. + +### Веер +**Два источника, и это первый круг, где второй — не мой агент.** (1) Агент `fable`, read-only, работавший в СВОИХ копиях дерева (рабочее дерево не тронуто — подтверждено им и сверено по `git status`): **68 посадок в семи предметах**, 48 красных, 20 переживших, 0 несостоявшихся. (2) **Круг оркестратора** — независимый веер по тому же батчу, девять находок, пять новых для меня. По трём пунктам два веера сошлись НЕЗАВИСИМО (дедуп полисемии · порог без пина · класс структурных утверждений), и это первое за три круга свидетельство, что находки воспроизводимы между читателями, а не являются вкусом одного. + +### ⛔ ГЛАВНОЕ: денежная дыра, которую круг 2 ОБЪЯВИЛ ЗАКРЫТОЙ, была открыта + +Мой фикс круга 2 внёс банк-роли в `ReachableModels()` и на этом остановился. **`CheckKeys` читает этот список ТОЛЬКО в лейбл-ветке.** Безлейбловая книга — shipping-дефолт — идёт второй веткой, которая собирала модели стадий руками и про ворота не знала. Проверено исполнением: терминолог, классификатор и ремонт на провайдере с пустым `api_key_env` проходили префлайт целиком, `CheckKeys` возвращал nil. Прогон покупал черновую волну и умирал на воротах. + +**Почему тест круга 2 был зелёным поверх дыры:** он утверждал СПИСОК, а не префлайт. Пин на списке не есть пин на проверке, которая его читает. + +**И вторая половина той же дыры:** рантайм-список `reachableModels()` тоже не был прибит — посадка «только стадии» (без ремонта и банк-ролей) держала ВЕСЬ пакет `pipeline` зелёным. Причина — совпадение `pipeline-c1`, воспроизведённое в фикстурах: каждая фикстура ставит воротам `model: fake-model`, ту же модель, что у стадий. **Закрыто:** одно определение `gateModels()`, которое читают обе ветки `CheckKeys` и `ReachableModels`; тест зовёт `CheckKeys`, а не смотрит список; и фикстура, где банк-роль ходит СОБСТВЕННОЙ моделью, с пином на пре-строенной карте клиентов. + +### Что нашлось ещё — по классам + +**А. ЦЕЛЬ С CJK-ПИСЬМОМ НЕ ЭКРАНИРОВАЛАСЬ ВООБЩЕ** (находка оркестратора). Гейт `!isCJKTarget` принадлежал ЭХО-правилу, а держал оба правила сразу. «Вывод в письме ИСТОЧНИКА» для →ja бессмысленно — верный перевод zh-книги полон ханьцзы; «вывод в письме ЦЕЛИ» отвечается прекрасно. Итог: →ja/→zh/→ko не судились ничем, при том что доккоммент `langscreen` обещал обратное. **Это бьёт в цель проекта №2:** на ревью-вопрос «заработает ли пара, которой в репо нет, без правки Go» ответ для CJK-целей был «нет». Экран вынесен из-под гейта, эхо-правило осталось под ним. Документированный предел супермножества (китайский вывод для →ja не флагуется) прибит **как ПРОМАХ**, чтобы никто не принял экран за защиту от zh-эха на →ja. + +⚠ **`classifierVersion` НЕ двигали — ратифицировано оркестратором.** Для →ru поток управления побайтово тот же (`!isCJKTarget` истинно и до, и после, обе ветки в том же порядке), →CJK-снапшотов не существует, а строка в этом батче уже сдвинулась дважды и пере-снапшот уже предписан единым актом. Различитель на будущее: **бамп должен любой смене, способной пере-вердиктить СУЩЕСТВУЮЩИЙ снапшот** — не «кажется, безопасно». + +**Б. ПРОИЗВОДНОСТЬ ВЕРСИИ ЭКРАНА БЫЛА ЗАЯВЛЕНА И НЕ ДЕРЖАЛАСЬ (3 посадки).** Доккоммент `Version` говорит «выведена по построению, поэтому сдвиг порога забирает громкий `--resnapshot` с собой». Не проверял никто. Посадка: переписать `var` литералом, который он сейчас печатает, и сдвинуть порог 0.50 → 0.45 — строка не двинулась, голден не двинулся, оба интервальных пина прошли (0.45 внутри пустой полосы), весь пакет зелёный. Резюмированный чанк пере-вердиктился бы порогом, за который никто не платил. Третья дверь: `%.2f` не выражает 0.504 — окно точности ±0.005. **Закрыто:** тест пересчитывает строку из констант, и round-trip-guard требует, чтобы напечатанный порог читался обратно тем же числом. Формат НЕ расширен намеренно — это стоило бы `--resnapshot` всем книгам за правило, которое не менялось; расширение теперь осознанный акт. + +**В. ГРАНИЦА СРАВНЕНИЯ, КОТОРУЮ НЕ ВЫРАЖАЕТ НИ ОДНА КОНСТАНТА.** `share < floor` → `<=` пережило весь пакет: ни одна фикстура не сидела ровно на линии. Прибито фикстурой ровно на 200 буквах, из которых ровно 100 целевых — доля 0.50 без плавающего люфта. + +**Г. ВАЛИДАТОР ПЛЕЙСХОЛДЕРОВ — ТРИ ДВЕРИ.** (1) Сканирование только System-части пережило всё — каждая фикстура кладёт плохой маркер в системную половину, а самое вероятное место для автора — пользовательский хвост, где живут почанковые переменные. (2) Снятие проверки незакрытого `{{` пережило. (3) Тест «равенства множеств» обходит `placeholderNames()`, то есть таблицу РЕНДЕРЕРА, и доказывает только «рендерер ⊆ валидатор»; дорогое направление — обратное, и оно было прибито четырьмя ЛИТЕРАЛЬНЫМИ словами, так что пятое слово проходило насквозь. **Закрыто устранением, а не пином: валидатор ТЕПЕРЬ ЕСТЬ РЕНДЕРЕР** — `CheckPlaceholders` рендерит по настоящей таблице значений. Второго списка не существует, расходиться нечему. + +**Д. ЗАКОН-БЛОК: ПОДПИСЬ ПРОТИВ УВЕРЕННОСТИ (5 посадок).** Подпись — это СТАТУС, а не уверенность матча: подписанная строка, сработавшая по сомнительному ключу, всё равно канон, которому уступают. Ключевание набора подписей на диспозиции пережило. Уступать должен ЛЮБОЙ неподписанный статус, а не только `draft` — `auto` пишет майнер, то есть ровно та строка, ради подчинения которой правило и существует. Плюс: подписанная строка с ПУСТЫМ переводом не канон (иначе термин исчезает из блока), несимметричный `TrimSpace` разрушает набор, и однопроходная версия зависит от порядка. **Отдельно — вакуумность в моём собственном тесте:** его комментарий утверждал, что случай (1) держит независимость от порядка, а стоящий там же `sortByPriority` это утверждение обнулял. Комментарий исправлен, независимость от порядка вынесена в отдельный случай, который рендерит блок НАПРЯМУЮ, в обоих порядках. + +**Е. ЛИПКИЙ ПЕРЕНОС: ПОЛОВИНА ДИСПОЗИЦИИ.** Перенос наследует обе половины, но пересчёт диспозиции ИЗ СОБСТВЕННОЙ ПОВЕРХНОСТИ строки пережил: в прибитой фикстуре `src` сам и есть сомнительный ключ, поэтому пересчёт воспроизводит тот же ответ. Разделяющая фикстура (ханьский `src`, сомнительный кана-алиас) существовала, но утверждала только `KeyTrusted`. Под посадкой перенос молча повышался до `Confirmed` — пропуск принудительного пост-чека и место повыше в бюджете, — а провод молчал, потому что половина доверия цела. Это D16.2-повышение в чужом пальто. + +**Ж. ЛЕДЖЕР КОРПУСА ПИНИЛ ЭКСТРЕМУМ, А НЕ ПОПУЛЯЦИЮ (5 посадок).** Второй по трудности здоровый образец можно было смягчить, второй по низости целевой — тоже, а трудную строку — заменить числами лёгкой ПОД ЕЁ ЖЕ id: счётчики, экстремумы и множество id держались. И у интервала не было записи про ВТОРУЮ сторону: доля off-target могла уехать 0.000 → 0.490 при всех зелёных тестах, и порог 0.50 сел бы прямо на образец, пока леджер говорит «полоса пуста». **Закрыто:** запись `wantBestOffTargetTgt` и **дайджест по всей популяции** (id · метка · четыре счётчика, сортировка по id) — пере-взятие корпуса стало осознанным актом, переписывающим строку в том же коммите. + +**З. ОПЕРАТОРСКОЕ ПРЕДЛОЖЕНИЕ: ЧИСЛО ФЛАГОВ ПЕЧАТАЛОСЬ ЧИСЛОМ ПЕРЕДЕЛОК.** Пережило весь пакет: обе фикстуры, читающие это предложение, имели `Reworked == Flagged == 1`. Разведены. + +**И. ФЛАГ, РАДИ КОТОРОГО ПОСТРОЕН ПУНКТ 2, БЫЛ САМЫМ БЕЗОБИДНЫМ В ПАСПОРТЕ** (находка оркестратора). `flagReasonSeverity` не знал `off_target_lang` → дефолт 8, ниже `length` (6). Глава, вернувшаяся не на том языке, показывала «length» как худшую проблему. У функции не было ни одного теста. **Закрыто:** switch стал картой, а исчерпаемость держит тест, читающий константы `FlagReason` **из исходника через go/ast** — список в тесте гнил бы ровно так же, как список в коде, и заверял бы гниль. + +**К. ВТОРОЙ CALL-SITE `classify`** (находка оркестратора). `repairReGate` собирал `classifyInput` руками из тех же полей, что `classifyOutput`. Поле `TargetScripts` однажды уже забыли там, починили руками — и посадка показала, что починку не держит ничто. **Закрыто устранением:** один конструктор `classifyInputFor`, пин на нём через рефлексию — любое поле, пришедшее нулевым, валит тест. Список полей в тесте не пишется: его обновлял бы тот же, кто забыл обновить конструктор. + +**Л. ДВЕРЬ 3 ГЕНДЕРНОГО ТЕСТА ОБЕЩАЛА НЕ ТО, ЧТО ДЕРЖИТ** (находка оркестратора, подтверждена исполнением). Её комментарий говорил: «впустят mined-строки в базовый банк — покраснею». Не краснеет: внутри ОДНОГО прогона черновая волна покупается ДО ответа классификатора, поэтому никакое правило про банк не положит род на тот провод. Утверждение об отсутствии оставлено как утверждение о ПОРЯДКЕ, а денежный контракт теперь утверждается там, где живёт — на двух материализованных банках: обогащённый несёт mined-строку, базовый её не выбирает. + +**М. ИНСТРУМЕНТ ТЕРЯЛ СВОЙСТВО «ГОНЯЕТСЯ ЦЕЛИКОМ»** (находка оркестратора). Протухший якорь `AF-keys-file-reason-covers-all` (протух ещё до этого пака, на `8adcb86`) возвращал ОШИБКУ ПРОГОНА и клал весь каталог на 33-й записи из 120 — а прогоны через `-id` продолжали проходить, и никто не видел. **Закрыто:** протухание стало ПЕРЗАПИСНЫМ вердиктом `ROTTED` — прогон идёт дальше, выход остаётся ненулевым, запись предъявляется. Якорь починен. + +### Что я перепроверила САМА, не приняв на слово +- **Три находки оркестратора, где код на вид противоречил заголовку** (`repair.go` передаёт `TargetScripts`; `CheckPlaceholders` сканирует весь `canon` и ловит незакрытый `{{`; `TestUnionStickyNewestWins` на вид ловит keep-first) — прогнала собственные посадки. Две подтвердились как непокрытость, одна — нет. +- **`UnionSticky` (его находка №4) — ОТВЕДЕНА.** Четыре независимые посадки красные. Оркестратор проверил свою на чистой копии `b8154cd` и снял её сам с точным разбором: его «инверсия» (обход новое→старое с keep-first) ПОВЕДЕНЧЕСКИ ЭКВИВАЛЕНТНА оригиналу (обход старое→новое с перезаписью). **Третий класс ложной зелени за сутки — посадка, не меняющая поведения**, рядом с моими двумя: упавшая сборка, прочитанная как зелень, и обрезанный вывод, прочитанный как ноль. Общее у всех трёх: **читатель верит ВЕРДИКТУ, не проверив, что его произвело.** +- **Дыра `CheckKeys`** — не поверила отчёту агента: написала тест, увидела его красным на всех трёх воротах, потом чинила. +- **Каждая из 19 новых записей каталога предъявлена красной прогоном.** Одна (`WB41`) вернулась SURVIVED — **моя фикстура случайно давала верный ответ и под посадкой** (неподписанная строка была `Confirmed` и сама наполняла набор подписей). Фикстура переписана так, что подпись — единственный возможный источник; предъявлена красной. + +### ⚠ Чего круг НЕ покрыл +- **Причина `S6e`** — совпадение ли это фикстур или у банк-ролей есть второй путь к клиенту помимо `clientFor`. Названо агентом, не открыто; я закрыла СЛЕДСТВИЕ (пин на карте клиентов), не причину. +- **Сквозной прогон дыры `CheckKeys`** через `NewRunner` → волна: закрыто на уровне `CheckKeys` и пре-строенной карты, но что происходит на живом проводе с ключом-пустышкой, никто не гонял. +- **Резюме через смену версии** — end-to-end пере-вердикта резюмированного чанка нет ни одного теста; вся аргументация про `--resnapshot` держится на чтении. +- **Конвенционный путь стадийного промпта** — пер-путевой тест гоняет только `prompt_override`. Маркер внутри вырезаемого комментария проходит по построению, и НАМЕРЕННОСТЬ этого никем не проверена. +- **Два НЕПОДПИСАННЫХ ряда одной поверхности** оба рендерятся: «один приказ на термин» держится только когда подпись есть. Наблюдение агента, теста нет ни в ту, ни в другую сторону. +- **`precomputeSticky`** — сброс на границе главы и запись переноса, заблокированного спойлером. +- **Сам харнесс `tmmutate`** (отпечаток и восстановление) и единственная запись `expect: survives` (`G-byte-gate`) не ревьюились ни одним кругом из трёх. +- **Ракурсы, унаследованные непокрытыми из круга 2 и не открытые снова:** `$0`-проекции на дефектной книге · липкий перенос до редакторского провода сквозным · настоящая латинописьменная цель (`target-en.txt` в репо нет) · `eval/`-харнессы вне модуля. +- **F11 остаётся риском дизайна, не чинен:** порог экрана калиброван на ОДНОЙ сянься-новелле; на латино-тяжёлом здоровом русском даёт ложный `off_target` (0.461 с пиньинь-глоссами, 0.077 с shell-командами), а ложный флаг ЭСКАЛИРУЕТ — то есть стоит платного вызова. Оркестратор забрал носителем. +- **Круг 3 не ревьюил мои правки круга 3.** Копии агента сняты до них. Четвёртый круг, если он будет, начинается отсюда. + +### Числа круга +Батарея `MAKE_EXIT=0`, `0 issues`, все пакеты `ok` (`pipeline` 571 s под `-race`), скипы те же. **Голден в этом круге не трогали, и `TestGoldenDeterminism` проходит против него** — круг не сдвинул ни одного байта провода. Тесты **1156 → 1173**. Каталог **120 → 141**; **все двадцать одна новая запись предъявлена КРАСНОЙ** (`WB41` — со второй попытки, после починки фикстуры, которая случайно давала верный ответ и под посадкой). + ## Файлы **Изменены:** `internal/pipeline/{disposition,chunkrun,waverun,events,manifest,mining,terminologist,repair,render,runner}.go` · `internal/membank/{memory,mempostcheck,decisions}.go` · `internal/terminology/{terminology,classify}.go` · `internal/miner/miner_emit.go` · `internal/checks/sanitizer.go` · `internal/config/{book,pipeline}.go` · `internal/lang/embedded.go` · `internal/store/migrate.go` · `cmd/tmctl/render.go` · `cmd/tmmutate/mutations.json` (92 → 96) · `configs/pipeline-{c1,c2,arm-*}.yaml` · `prompts/zh-ru/*.md` (шесть — жанр; `classifier.md` — третье поле) · `example/book.yaml` · тесты и голден. @@ -635,13 +698,13 @@ python3 -c "import json;print(len(json.load(open('backend/cmd/tmmutate/mutations | `docs/architecture/15-money-path.md:24` | `pipeline/status.go:290` «book_ceiling_usd,omitempty» | `:311` | | `docs/architecture/15-money-path.md:24` | `pipeline/status.go:788` «100 * (committed + reserved)» | `:811` | | `docs/PROGRESS.md:179` (тело строки 232) | `pipeline/status.go:866` «IT IS NO LONGER THE READ PATH'S FIRST ANSWER» | `:901` | -| `docs/BACKEND_CONSENT_SESSION_PROMPT.md:52` | `pipeline/status.go:217` «can never quote a different number» | **снят по заказу (ФЧ-5 п.4)** | -| `docs/BACKEND_CONSENT_SESSION_PROMPT.md:54` | `pipeline/reprice.go:24` «NOT projected (like the content axis» | **снят по заказу (ФЧ-5 п.4)** | +| `docs/archive/prompts/BACKEND_CONSENT_SESSION_PROMPT_2026-09-02.md` (строка 52 на момент выдачи; в архиве номера сдвинул баннер исхода) | `pipeline/status.go:217` «can never quote a different number» | **снят по заказу (ФЧ-5 п.4)** | +| `docs/archive/prompts/BACKEND_CONSENT_SESSION_PROMPT_2026-09-02.md` (строка 54 на момент выдачи) | `pipeline/reprice.go:24` «NOT projected (like the content axis» | **снят по заказу (ФЧ-5 п.4)** | Первые четыре — сдвиг номеров от моих вставок; последние два промт заякорил на тексте, который сам же велел снять, поэтому их «поломка» и есть признак исполнения. ⚠ **Про остальные 12 я сперва написала здесь «все в `docs/experiments/**`, пришли с полигонным мержем» — это было неверно, и поправлено разбором с платформенной сессией.** Перечисляю по владению; ⚠ **общее число гейта — величина ПОДВИЖНАЯ**, обе смены правят дерево параллельно: на момент того разбора `python3 docs/scripts/counts.py --lint` печатал 18, на момент сдачи дофикса — **20** (в отчёте пака стояло «все 18 строк», и это было верно только для того часа). Разбивка по владению взята с той, 18-строчной выдачи: -- **4 — платформенной сессии** (`textmachine-37`): `docs/PROGRESS.md:19`, `docs/PLATFORM_P13_SESSION_PROMPT.md:286` и `docs/BACKEND_CONSENT_SESSION_PROMPT.md:227` целятся в одну снятую ею строку рантбука `platform/deploy/README.md:213` «сначала платформа, потом движок»; плюс `docs/PLATFORM_P13_SESSION_PROMPT.md:166` на уехавший `Quarantine`. ⚠ Третий из них живёт В МОЁМ промте (это его ⛔-оговорка о том, что совет рантбука опасен), но сломан не мной — целью владеет платформа. +- **4 — платформенной сессии** (`textmachine-37`): `docs/PROGRESS.md:19`, `docs/archive/prompts/PLATFORM_P13_SESSION_PROMPT_2026-09-02.md` (строка 286 на момент выдачи) и `docs/archive/prompts/BACKEND_CONSENT_SESSION_PROMPT_2026-09-02.md` (строка 227 на момент выдачи) целятся в одну снятую ею строку рантбука `platform/deploy/README.md:213` «сначала платформа, потом движок»; плюс `docs/archive/prompts/PLATFORM_P13_SESSION_PROMPT_2026-09-02.md` (строка 166 на момент выдачи) на уехавший `Quarantine`. ⚠ Третий из них живёт В МОЁМ промте (это его ⛔-оговорка о том, что совет рантбука опасен), но сломан не мной — целью владеет платформа. - **8 — полигонных**, пришли с мержем `2a63c37`: семь в `docs/experiments/**` и один в теле бэклога — `docs/PROGRESS.md:190` на `eval/conformance.py:48`. - ⚠ Якорь в `docs/experiments/23-editor-tier.md:6196` целится в строку 679 этого журнала, которой в нём нет: он был мёртв и до пака (тогда в файле было 472 строки), а мои вставки лишь меняют общее число, которым гейт объясняет смерть. ⚠ Записан здесь СЛОВАМИ, без токена «путь:номер» в обратных кавычках: гейт читает такой токен как якорь, и первая редакция этой строки сама добавила себе двадцатую поломку. diff --git a/docs/README.md b/docs/README.md index 89a791cc..636ef4e4 100644 --- a/docs/README.md +++ b/docs/README.md @@ -23,7 +23,7 @@ |---|---|---| | Оркестратор | [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) | - | Платформа | [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) — перекрытый снимок, читать не как курс) | | Фронт | активного НЕТ | **ЗОНА ЗАМОРОЖЕНА** (D39.136 п.2 + D39.147: разморозка отдельным словом владельца, не привязана к P7); перечень первого касания — в зонном журнале | | Контракт | активного НЕТ | канон — `architecture/14-api-contract/`; ⚠ версию брать ФАЙЛОМ (`grep '^ version:' openapi.yaml`), не отсюда: миноры ратифицируются D-нотами и их содержание грепается по реестру нот. | diff --git a/docs/STACK.md b/docs/STACK.md index 2927dd38..8e2f27bd 100644 --- a/docs/STACK.md +++ b/docs/STACK.md @@ -5,9 +5,9 @@ | Роль | Модель (слаг) | 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`) | -| **+ банкнота** (WHAT-канал драфта) | та же flash, промпт `translator-banknote.md` | как draft | ⚠ НЕ в shipping-c1 — ран-локальный конфиг книги: `~/books/gu-zhenren/coldrun-b/pipeline.yaml` (`gates.banknote` + `prompt_override`) | ⚠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 | -| **классификатор** (типы кандидатов) | flash (`classify_model` пуст ⇒ = model) | та же ручка | там же: `classify_types: true` + `classify_budget_usd` | проба/полигон; в shipping выключен ВЕЗДЕ | латентный мис-вердикт `cjk_artifact` — `13-tech-debt-anchors.md` §Б-105 | +| **+ банкнота** (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"` (одна ручка на обе бэнк-роли) | `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: 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-резерв** | `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 | @@ -17,6 +17,13 @@ ## Примечания - **⚠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 (статус ручки — в строке редактора выше). - **Цена:** ~$0.85/ранобэ (D30.4; тело — `archive/architecture/05-decisions-D1-D38.md`, карта — шапка D-лога) — ⚠ число ДО пере-пина цен 13–15.08: таблица запинена ПИКОМ, счёт шиппинга = 100% DeepSeek ⇒ ×4.2–4.4 в пике и ×2.1–2.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. diff --git a/docs/architecture/05-decisions-index.md b/docs/architecture/05-decisions-index.md index 04de1f0e..b51cb79e 100644 --- a/docs/architecture/05-decisions-index.md +++ b/docs/architecture/05-decisions-index.md @@ -1,4 +1,4 @@ -# Реестр D-нот — карта актуальности v2 (D1–D39.190; титул — носитель головы, бампать при каждом аппенде) +# Реестр D-нот — карта актуальности v2 (D1–D39.194; титул — носитель головы, бампать при каждом аппенде) > ⚠ **Колонку «тело» `counts.py --check` НЕ сторожит по устройству:** он сверяет полноту НОМЕРОВ, а не > место тела, поэтому колонка держится дисциплиной лендинга. Не нашёл тело по колонке — иди в слайсы, @@ -252,3 +252,4 @@ | D39.191 | 04.09 | **Норма приёмки: после дофикса — ВТОРОЙ адверсариальный круг по ИСХОДНЫМ пунктам заказа, петля до замыкания** (слово владельца). Закрывает окно, в котором дофикс ревьюировал только его автор. Цена окна замерена дважды в тот же день: двенадцать посадок первого круга пережили зелёную батарею (семь гарантий жили только как код), а платформенная сессия объявила починенной находку, снятие различителя в которой переживало батарею — у ручки над ДЕНЬГАМИ. Форма круга: пере-посадить находки самому · атаковать САМ ДОФИКС · проверить новые тесты на вакуумность · сажать мутации И В ДАННЫЕ | жив | ЖИВОЕ: круг без предъявленных посадок кругом не считается | приёмка норма петля | | D39.192 | 04.09 | **Класс дефекта, названный ЗОНОЙ: «утверждение о СТРУКТУРЕ, выданное за гарантию»** — верное по факту и не прибитое ничем. Три из семи переживших посадок второго круга оказались им: «две функции читают одну таблицу» · «проверка в единственной воронке» · «порог в пустом интервале». Падает не от порчи ЗНАЧЕНИЯ, а от ЗАВЕДЕНИЯ ВТОРОГО ПУТИ, и падает молча. Форма посадки против него — «заведи обход», а не «сломай значение». ⚠ Норма о мутациях В ДАННЫЕ окупилась первой попыткой: размягчённая фикстура прошла батарею и отрапортовала число ЛУЧШЕ реального, потому что тест утверждал ПОЛ, а пол не измерение ⇒ число-доказательство обязано иметь леджер записанных значений | жив | ЖИВОЕ: карта слепых зон полна только с обеими осями — что не смотрели И чем нельзя опровергнуть | приёмка класс мутации данные | | 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 не находка, пока посадка не показала, что меняет поведение; бамп версии должен смене, способной пере-вердиктить СУЩЕСТВУЮЩИЙ снапшот | лендинг контракт минор ложная-зелень мутации гейт | diff --git a/docs/architecture/05-decisions-log.md b/docs/architecture/05-decisions-log.md index a63d0709..dd50866b 100644 --- a/docs/architecture/05-decisions-log.md +++ b/docs/architecture/05-decisions-log.md @@ -1,4 +1,4 @@ -# Журнал решений оркестратора — контракт D1–D39.193 (живой файл: карта · эрраты · живые тела · голова D39.124+ (подрезка D39.139); тела закрытых эр — в слайсах `docs/archive/architecture/`, указатель ниже; реестр всех нот — `05-decisions-index.md`) +# Журнал решений оркестратора — контракт D1–D39.194 (живой файл: карта · эрраты · живые тела · голова D39.124+ (подрезка D39.139); тела закрытых эр — в слайсах `docs/archive/architecture/`, указатель ниже; реестр всех нот — `05-decisions-index.md`) > **⟶ КАРТА АКТУАЛЬНОСТИ (ревизия 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+). @@ -2046,3 +2046,80 @@ Fable 5.1 со сквозным контекстом (решение владе **3. ⚠ ДЕДУП ЗАКОН-БЛОКА: моя ратификация была НЕВЕРНА, и правильная редакция — зоны.** Оркестратор велел «один приказ на исходный термин, побеждает подписанная». Формула шире правила: ключ уникальности банка — `(src, sense, since, until)`, значит одна поверхность ЗАКОННО несёт несколько ПОДПИСАННЫХ канонов (фамилия и направление у одного написания), и дедуп по голому `src` ронял подпись МОЛЧА, при том что трансляторный блок продолжал рендерить обе — два провода разъезжались. **Ратифицируется редакция зоны: уступает НЕПОДПИСАННАЯ строка и только ПОДПИСАННОЙ; подпись не роняется никогда.** Содержание исходного решения (конфликт подписанной с авто-консолидацией даёт один приказ) исполнено целиком; полисемия двух подписанных канонов конфликтом не является. ⚠ Класс ошибки называю прямо: **ратификация, выданная без проверки ключа уникальности предмета, внесла дефект в код** — и поймала его ЗОНА своим кругом петли, а не приёмка. **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`) объявляет себя носителем головы, но не сверялся: держал `D1–D39.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). **Различитель впредь:** бамп должен любой смене, способной +пере-вердиктить СУЩЕСТВУЮЩИЙ снапшот, — не «на всякий случай» и не «раз трогали файл». diff --git a/docs/architecture/10-prompt-architecture.md b/docs/architecture/10-prompt-architecture.md index f60158fb..2a073de2 100644 --- a/docs/architecture/10-prompt-architecture.md +++ b/docs/architecture/10-prompt-architecture.md @@ -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-mono.md` | референс-вариант D13.1 (не боевой) | узкий моно-мандат | — | | `zh-ru/judge-selector.md` | Ф2 (не исполняется) | — | — | diff --git a/docs/architecture/13-tech-debt-anchors.md b/docs/architecture/13-tech-debt-anchors.md index bbdf97a2..82b407ec 100644 --- a/docs/architecture/13-tech-debt-anchors.md +++ b/docs/architecture/13-tech-debt-anchors.md @@ -163,7 +163,7 @@ Go-гейт стоит на v1 без поглощения кавычек: backe ### Б-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.5–2.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.5–2.9 при невскрытой причине; D21.4/D21.10 закрыты явно). **Эксп-21 (D39.117):** полный regen выигрывает у точечного ремонта (`C2/A_law` −3.75 Holm 0.0006) — довод против диффов, НЕ опровержение: чинил дешёвый фиксер по предложению, а не сильный редактор узким мандатом; гейт «перепроверить до стройки» в силе, приоритет понижен ### Б-108 — тело строки 108 на 09.08.2026 diff --git a/docs/architecture/14-api-contract/README.md b/docs/architecture/14-api-contract/README.md index 9b540c68..ff5c6629 100644 --- a/docs/architecture/14-api-contract/README.md +++ b/docs/architecture/14-api-contract/README.md @@ -3,10 +3,10 @@ батч 0.3.0 — D39.138, 16.08.2026, оркестратор №17; синк с платформой 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 РЯДОМ. ⚠ Зонная копия 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; > при вопросе «почему так» — этот файл. > -> **Статус: РАТИФИЦИРОВАН по 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) — ломающий минор по > целостному ревью research/28** · **0.4.0 (D39.152, 20.08) — синк с платформой, §6в** · > **0.5.0 (D39.161, 27.08) — снос отменённой пер-термной модели подписи (PD-370) + дверь правок @@ -48,9 +48,18 @@ cmp-сверка обязательна (D39.138 п.3). > заново продолжает ровно с места остановки. Приехал ОДНИМ лендингом с платформенным паком P11** · > **0.9.0 (D39.180; ратифицирован №20 31.08 по пингу зоны ДО стройки, заленджен №21 с паком P12) — ВТОРАЯ > граница пересчёта `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` и три его > схемы, из `BankPage` и `EventBank` сняты `pending_decisions`/`complete` (§2.19-бис), в @@ -903,6 +912,40 @@ the original request was never applied». Каждый `POST /books` созда `structure_version`). Через эпоху считается ТОЛЬКО пожизненный счёт книги; остаток — открытая строка регистра платформы `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. Зависимости: чтение → источник → строка бэклога **Правило, введённое 0.3.0 (Б-21): предупреждение о недостроенном ОБЯЗАНО нести номер строки @@ -1373,6 +1416,7 @@ heartbeat · форма `id` кадра. Сжатие как ТРЕБОВАНИ |---|---|---|---|---| | `hard_refusal` · `soft_refusal` · `content_filter` · `hard_block` | 0 | `content_withheld` (ОДИН на все четыре — класс 2) | ⬜ | ⬜ | | `cjk_artifact` | 1 | `source_residue` | ⬜ | ⬜ | +| `off_target_lang` | 1 ⚠ | `wrong_language` | ⬜ | ⬜ | | `excision_suspect` | 1 | `text_possibly_dropped` | ⬜ | ⬜ | | `coverage_fail` | 1 | `incomplete_coverage` | ⬜ | ⬜ | | `sanitizer_defect` | 2 | `markup_defect` | ⬜ | ⬜ | @@ -1385,7 +1429,19 @@ heartbeat · форма `id` кадра. Сжатие как ТРЕБОВАНИ | `upstream_not_ok` | 8 (по умолчанию) | `unavailable` | ⬜ | ⬜ | | незнакомая причина | 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`) и падает в ранг по умолчанию, как и любая будущая причина. ⚠ Номер строки здесь намеренно не ставится: прежняя ссылка `:174` протухла за один пак (там теперь `GlossaryMissFlagged`) — поймано синком 20.08, п. L записки. diff --git a/docs/architecture/14-api-contract/openapi.yaml b/docs/architecture/14-api-contract/openapi.yaml index a6593202..c5f67b85 100644 --- a/docs/architecture/14-api-contract/openapi.yaml +++ b/docs/architecture/14-api-contract/openapi.yaml @@ -2,7 +2,7 @@ openapi: 3.1.0 info: title: TextMachine API - version: 0.9.0 + version: 0.10.0 summary: Ratified contract between the frontend and the TextMachine platform. description: | **RATIFIED contract.** Canonical copy: `docs/architecture/14-api-contract/`; @@ -904,6 +904,51 @@ paths: '401': { $ref: '#/components/responses/Unauthorized' } '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: securitySchemes: sessionCookie: @@ -2544,19 +2589,46 @@ components: failure_code: type: [string, 'null'] minLength: 1 + enum: [book_empty, deployment_error, build_interrupted, build_failed, null] description: | 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: type: [string, 'null'] - format: uri + format: uri-reference 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 - origin as this API, and expiring at `expires_at`. A browser NAVIGATES to it: it is a - download, not a call. + **Bound to the authenticated owner**, never indexed, on the same origin as this API, and + expiring at `expires_at`. A browser NAVIGATES to it: it is a 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: type: object diff --git a/docs/PLATFORM_EXPORT_SESSION_PROMPT.md b/docs/archive/prompts/PLATFORM_EXPORT_SESSION_PROMPT_2026-09-04.md similarity index 92% rename from docs/PLATFORM_EXPORT_SESSION_PROMPT.md rename to docs/archive/prompts/PLATFORM_EXPORT_SESSION_PROMPT_2026-09-04.md index 01f3d403..2d6b6b56 100644 --- a/docs/PLATFORM_EXPORT_SESSION_PROMPT.md +++ b/docs/archive/prompts/PLATFORM_EXPORT_SESSION_PROMPT_2026-09-04.md @@ -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/docs/platform-PROGRESS.md` (в `docs/PROGRESS.md` платформа НЕ пишет). > **Не коммитишь** и не трогаешь индекс и историю — запреты и причина: `CLAUDE.md`, diff --git a/docs/experiments/23-editor-tier.md b/docs/experiments/23-editor-tier.md index 93fe49f0..073374b2 100644 --- a/docs/experiments/23-editor-tier.md +++ b/docs/experiments/23-editor-tier.md @@ -6193,7 +6193,7 @@ n = 16 английских единиц = 7.89 главы Гу · k = 5 арм * **Находка 1 (декой) — диспозиция за приёмкой**, не за сессией. От неё зависит, считать ли Шаг 4 закрытым по букве или по цели. * **Находка 11** — пометы «контраст условный» на телах Д23/Д24 не поставлены. -* `docs/PROGRESS.md:679`=`ЖИВОЙ ДЕФЕКТ ДВИЖКА` — шапка пинга №19 теперь ложна дважды (дефект +* ⚠ `docs/PROGRESS.md`, фраза «ЖИВОЙ ДЕФЕКТ ДВИЖКА» — **ЦЕЛИ БОЛЬШЕ НЕТ** (испр. оркестратором №22, 04.09): утверждение снято переписью шапки, а не сдвинуто. Пере-указывать по СХОДСТВУ нельзя — ближайшее «ЖИВОЙ ДЕФЕКТ, внесённый моим же дофиксом» говорит о другом. Якорь снят с формы `файл:строка`, чтобы цитата мёртвого адреса сама не стала якорем — шапка пинга №19 теперь ложна дважды (дефект движка закрыт 28.08; терялся промт, а не глоссарий) и баннера не имеет. **Чужая зона, пинг дан.** --- @@ -7868,7 +7868,7 @@ completion, уходящие в размышление** (Д49), — это пл 1. **Митигация «25 узких вопросов да/нет вместо MQM»** (+35 пунктов к доле, где судья предпочёл человека) — это метрика **LiTransProQA**, и она уже в репозитории **в трёх местах**, включая - `docs/architecture/02-mvp-plan.md:49`=`судья-анкета узких вопросов`. ⚠ Хуже: её же τ = −0.124 в другом месте того же отчёта + `docs/architecture/02-mvp-plan.md:46`=`судья-анкета узких вопросов`. ⚠ Хуже: её же τ = −0.124 в другом месте того же отчёта объявлен опорой «судья награждает MT» — то есть одна метрика подана и как лекарство, и как болезнь. 2. **Работа про гранулярность** уже пересказана у нас **в девяти местах**, включая `09-pilot-protocol.md:59` с пометкой «верифицировано по PDF, вкл. en→ru». diff --git a/docs/scripts/counts.py b/docs/scripts/counts.py index 5ca2d430..ee174b2d 100644 --- a/docs/scripts/counts.py +++ b/docs/scripts/counts.py @@ -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)) for l in dlog.splitlines() if (m := NOTE.match(l))] notes = [f[2] for f in found] @@ -302,13 +302,20 @@ def head(dlog: str, prog: str) -> dict: break last = notes[-1] if notes else None b = banner.group(1) if banner else None + # ⚠ ТРЕТИЙ носитель головы, добавлен 04.09 (оркестратор №22) после того, как разошёлся МОЛЧА: + # реестр нот держал «D1–D39.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 { "максимум по номеру": top, "последняя по порядку файла": last, "порядок = номер": last == top, "шапка D-лога": b, + "титул реестра нот": i, "голова в CURRENT-STATE": claimed, - "сходится": bool(top) and top == claimed == b, + "сходится": bool(top) and top == claimed == b == i, } @@ -330,6 +337,17 @@ LITERALS = [ # платформы (закрыто 10 строк за 20 минут) превратил правдивую запись в «расхождение», и # предписанное лечение было бы «перепиши историю». Живой счёт живёт в зонном журнале платформы, # проверять его отсюда — значит винить зону 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 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 src = "содержимое коммита (индекс/HEAD)" if FROM_INDEX else "рабочее дерево" @@ -686,7 +704,8 @@ def main() -> int: if not h["сходится"]: bad.append( 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"]: bad.append(f"дубли ID строк бэклога: {b['дубли ID']}") @@ -705,7 +724,12 @@ def main() -> int: texts = {PROGRESS: prog, REGISTER: reg} 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)) if not found: bad.append(