textmachine/docs/CONTRACT_MINOR_REPORT.md

372 lines
41 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Отчёт контрактной сессии: минор 0.4.0 → 0.5.0
> Сессия по промту `docs/CONTRACT_MINOR_SESSION_PROMPT.md` (оркестратор №19, 27.08.2026).
> Файл ведётся ПО ХОДУ работы (§7): секция 1 написана ДО правок. Зона записи — два файла контракта
> плюс этот отчёт; сессия НЕ коммитит.
## 1. Эхо-протокол (§9) и записка-план — ДО правок
**Скоуп:** снос отменённой пер-термной модели подписи (§3.1) · объявление двери правок банка,
выведенной из словаря `tmctl bank-apply` (§3.2) · судьба счётчиков `pending_decisions`/`complete`
(§3.2-бис) · предупреждение о конверте вне `/v0` (§3.3) · версия `0.5.0`.
**Инварианты:** словарь двери — из `membank/decisions.go` + `pipeline/bankdecisions.go`, не
изобретаю; неизвестный кортеж — НЕ ошибка (форма добавления терма); `undecided` — только вместе с
запретительным контрактом `SignatureState`, обе половины; коды 14/15 различимы на проводе; конверт
ошибки — существующий `Problem`/`ErrorCode`; узость окна, отклонение сид-терма, необслуживаемость —
явно в каноне; машиночитаемый признак «не построено» обязателен.
**Не-делать:** не коммичу; `platform/`/`frontend/`/`backend/`/`eval/` не трогаю; полоса прогресса
(строка 200) не берётся (D39.160); семантика прогресса `openapi.yaml:1293` не меняется; гейт
платформы не правится — его красный ожидаем; в `docs/PROGRESS.md` не пишу.
### Записка-план: что меняю, где, чем проверю
**Канон `openapi.yaml`:**
1. `version: 0.4.0 → 0.5.0`; пример `contract_version``0.5.0`.
2. §3.1 снос: путь `:469-505` · проза `:1830` (`TermStatus`) · схемы `:1939-2008`
(`BankDecision`/`BankDecisionsRequest`/`BankDecisionsResult`). Мой греп подтвердил список промта
и НЕ нашёл иных носителей четырёх имён (команда в §5 ниже).
3. §3.2-бис: снос `pending_decisions`+`complete` из `BankPage` (`:1924-1934`) и — находка МОЕГО
грепа, в списке промта её нет — из `EventBank` (`:2367-2372`). Ратифицированная проза «ONE act»
в `listBankTerms` сохраняется, клауза счётчиков и фраза «marked unverified inside the service»
(снята ещё ФБ-8 как обещание без носителя, но в `:445` уцелела) — уходят.
4. §3.2 дверь: `POST /books/{bookId}/bank/corrections` + схемы (`BankCorrection`,
`BankCorrectionsRequest`, `BankCorrectionsReceipt`, `BankSignatureCount`, `CorrectionRefusal`) +
два корневых кода (`bank_corrections_refused` 409, `bank_corrections_incomplete` 503) + признак
`bank_corrections_enabled` в `Capabilities` (прецедент `intake_enabled`; false ⇒ 404).
5. §3.3: в `info.description` (после `:35-37`) — предупреждение о конверте вне `/v0` без
обязательного `code`, ссылкой на компаньон §2.14 (один носитель на факт).
6. Тег `:127` «Memory bank and term signing» — переформулировать без пер-термной подписи.
**Компаньон `README.md`:** шапка (статус 0.5.0, без самозаписи ратификации) · `:124` и `:724`
(списки мест правила «схема + слова» — преемник) · `:674` (историческая строка сохраняется, статус
дописывается) · `:685` (строка про недоезд `decline` — пере-снята: новая дверь пишет файлы движка) ·
`:358` §2.9 (остаток пере-привязан к живым носителям) · новая секция §2.19 (вывод двери, провенанс) ·
§3 таблица (строка двери: движок построен, платформа — пак 2в) · Приложение А-2 (две строки кодов).
**Чем проверю (§5):** (1) YAML-парс + линтер, если найдётся в окружении; (2) сверка `$ref` против
`components.schemas` в обе стороны + loader-хук на дубли ключей; (3) гейт платформы на копии
`cp -a --parents platform docs/architecture/14-api-contract` — красный ИМЕННО на версии и с
ожидаемым текстом. Плюс опровергатели (§5 промта, заказ): 24 агента, мандат «дверь против словаря
глагола» + оси §6.
## 2. Обоснование формы двери (§3.2)
Полная таблица «провод ← движковый источник, file:line» и решения ◆ — в компаньоне, новая секция
§2.19 (`docs/architecture/14-api-contract/README.md`); здесь — сами решения с разобранными
альтернативами. Всё выведенное (✓) взято из `membank/decisions.go` + `pipeline/bankdecisions.go` +
`cmd/tmctl/main.go:69-75` и в канон попало без пересочинения.
**2.1. Форма поверхности — один `POST /books/{bookId}/bank/corrections` с документом целиком.**
Альтернатива «ресурсная» (`PATCH /bank/terms/{id}`) отвергнута: глагол атомарен и
всё-или-ничего (`ApplyDecisions`, `decisions.go:282-307`), а пер-строчные мутации обещали бы
частичную применимость и правку строк банка, которых этот вызов не меняет (вид пересобирается на
границе прогона — `18-bank-ontology.md`). Альтернатива «двух путей» (`…/preview` отдельным POST)
отвергнута: два пути = два места, где растёт форма, а закон шва п.7 требует, чтобы проекция была
той же операцией, что мутация («a report printed by the same call that already wrote is not a
projection» — `bankdecisions.go:44-45`).
**2.2. Имя `corrections`.** «decisions» вернуло бы имена снесённых схем с другой семантикой
(генерённый дифф читался бы как правка старой двери); «edits» — `edit` в грепе-гейте §5 компаньона
неотличим от имени волны движка. Продуктовое слово владельца — «правка» (D39.144).
**2.3. `book_id` в теле, обязательный, при живом `{bookId}` в пути.** Движок держит ДВЕ разные
проверки: документ обязан НАЗЫВАТЬ книгу (`decisions.go:141-143`) и отдельно сверяется с открытой
книгой (`bankdecisions.go:267-269`) — причина названа в коде: решения несут слова пользователя в
канон книги, и набор, посчитанный для другой книги, даунстрим не заметит. Если бы book_id вводила
платформа из пути, сверка стала бы вакуумной — клиент, POST-нувший набор книги A в путь книги B,
прошёл бы молча. Цена — одно поле.
**2.4. Кортеж требует все четыре члена** (`src`,`sense`,`since_chapter`,`until_chapter`; движок
дефолтит опущенные — `decisions.go:469,479-482`). Провод строже движка сознательно: неизвестный
кортеж здесь легально ДОБАВЛЯЕТ терм, поэтому цена опущенного `sense` — не отказ, а тихая
параллельная строка (клиент хотел править (src, sense="X"), а назвал (src, "")). `null`-семантика
окна — как у `BankTerm` (0.3.0 развёл сентинел `0` на `null`); проекция `null→0` — платформа,
закон шва п.6.
**2.5. `preview` — обязательное булево тела.** Закон шва п.7 (проекция прежде мутации) +
прецеденты тотальной обязательности (`stop_requested` — §6в J компаньона; в запросах —
`RunRequest.stop_for_signing`). Query-параметр на POST отвергнут: в этом каноне тело — единственный
носитель семантики небезопасных вызовов, и опциональность дала бы «мутацию по умолчанию».
**2.6. Раскладка полосы отказов.** Ратифицированная полоса 1019 (`main.go:69-75`) ложится так:
- **14 → `409` `bank_corrections_refused`** + member `refusals[]`. Отдельный корневой код, не общий
`400`: это законный отказ, по которому ПОЛЬЗОВАТЕЛЬ пере-решает (совет промта принят; довод —
разные адресаты ремеди). `409`, не `422`: канон весь класс state-зависимых отказов держит на 409,
а отказ здесь — о книге как она стоит (сид, коллизии набора).
- **15 → `503` `bank_corrections_incomplete`**: «документ ПРИНЯТ, слать ТОТ ЖЕ» — ремеди машинный и
специфичный, потому код свой, а не общий `service_unavailable`; ретрай сходится по байтовому
no-op (`bankdecisions.go:209-221`).
- **12 → `409` `run_in_flight`**: словарь канона уже имеет точное слово («книга уже переводится»);
движковая причина (флок живого прогона, `bankdecisions.go:159-163`) совпадает по смыслу.
- **10/11/13 → без пер-операционных кодов**: это «деплой сломан, чинит человек» — `5xx` общего вида
(500 канон сознательно не документирует — Zalando-правило из А-2).
- **потолок 1 МиБ → `413`** (`payload_too_large` дообъяснён), **потолок 5000 → схема
(`maxItems: 5000`) + слова**, нарушение = `400` `invalid_request` (нарушение объявленной формы;
движковый класс 14 для него — за платформенной валидацией и на провод не выходит).
**2.7. Причины пер-решенческих отказов — `refusals[].detail`, developer-facing, не показываются.**
У движка причины — свободный текст (`RejectedDecision.Reason`); машинного словаря причин нет, и
таблица перевода (закон п.6) переводит только структуры, не прозу. Замораживать в каноне пересказ
двадцати формулировок = вторая копия растущего словаря. Альтернатива «коды причин на платформе»
отвергнута: платформа для этого парсила бы английские предложения движка. Названная щель — в §6.
**2.8. Что НЕ пошло на провод из отчёта глагола** (каждое — решение, не забывчивость): пути файлов
и `written_delta`/`written_rejects` (серверная топология; ремеди клиента один — «слать тот же»);
`canonical_rewrite*` (предупреждение оператору файлов на диске, у клиента продукта нет ни файла, ни
комментариев в нём); ТЕКСТЫ `preexisting_problems` (свободный текст движка) — но их СЧЁТ
(`preexisting_faults`) едет, потому что «книга уже больна, следующий прогон может встать» экрану
нужен; `replaced[]` (свободный текст) — свёрнут в булев `displaced`, несущий ровно то свойство,
ради которого поле существует («перекрыл чужое слово — видь это», `decisions.go:225-228`);
`mode` — раскладывается на `preview`/`changed`/HTTP без остатка; `decisions_version`/
`report_version` — версии документов ШВА, на проводе их роль играет `contract_version`.
**2.9. `depth`: `edit_wave` → `refinement`.** Движковая константа несёт имя волны — запрещённый на
проводе словарь (гейт §5). Продуктовое слово с тем же смыслом; обе половины смысла («следующий
прогон»; «черновик не пере-формируется» → «не пере-переводится с нуля») продублированы словами.
Поле оставлено (не свёрнуто в прозу), потому что движок сделал его ПОЛЕМ с версией ровно затем,
чтобы будущая смена глубины была наблюдаемой (`decisions.go:51-57`).
**2.10. `signature` — опубликован с ОБЕИМИ половинами контракта** (`bankdecisions.go:88-118`):
положительная (счёт согласован с правилом сворачивания — полезен экрану) и запретительная
(не гейт; не отвечает «погаснет ли стоп» ни в одну сторону; `undecided: 0` ничего не обещает;
решать — ПРАВО; `unreadable` = числа не значат ничего). `map` (путь) не едет; «карты ещё нет»
выражено `signature: null` — иначе `0/0` без карты был бы байтово неотличим от «всё решено», тот же
класс дыры, который движок закрыл флагом `unreadable`.
**2.11. Признак «не построено» — `Capabilities.bank_corrections_enabled: boolean`.** `Capabilities`
годится: плоский документ деплоя, уже дом `intake_enabled` (булев + объявленный `404`) и
`export_formats` («пусто = не построено»). Булев, а не пустой список: у двери нет оси форматов —
нечего перечислять. Поведение при `false` объявлено (`404`), зеркаля интейк.
**2.12. Квитанция — НЕ чтение:** без `revision`/`structure_version`, кадр `bank` не испускается,
строки `GET /bank` не меняются до следующего прогона — сказано в каноне прямо (иначе первый же
экран прочтёт «исправил, а банк не изменился» как баг). Это проекция однонаправленного потока
онтологии (источники → вид → проекции, `18-bank-ontology.md`).
## 3. Решение по счётчикам (§3.2-бис): СНЕСТИ — со всех ТРЁХ носителей
Мой греп нашёл носителей больше, чем названо в промте: `pending_decisions`/`complete` жили в
`BankPage` (`:1924-1934`), в квитанции `BankDecisionsResult` (`:1997-2008`, умерла со схемой) **и в
кадре `EventBank` (`:2367-2372`, required)** — третий носитель в списке промта отсутствовал
(команда: `grep -n "pending_decisions\|'complete'\|complete:" openapi.yaml` до правок — хиты
442, 1924, 1929, 1997, 2000, 2004, 2367, 2371-2372).
Из трёх заказанных исходов выбран **снос**, довод в компаньоне §2.19-бис: пере-определить нельзя —
честный счёт движковый (`SignatureState`), и read-модель его не вычислит, не пере-реализовав
движковый закон (запрещено D39.156 п.6; «Чего эта форма НЕ несёт» онтологии); пометить нельзя —
обязательное вечно-нулевое поле это PD-370 в поле вместо пути. Ратифицированная проза «Signing the
bank is ONE act…» СОХРАНЕНА в `listBankTerms`; попутно из того же абзаца снята фраза «marked
unverified inside the service» — обещание без носителя, снятое ещё ФБ-8 (компаньон §6б) и
уцелевшее в одном месте. Цена сноса названа в каноне и компаньоне: чтение банка больше не отвечает
«сколько осталось»; счёт едет квитанцией двери (`signature`); возврат в чтение — когда закажут
экран подписи и движок опубликует нерешённость проекцией (носитель — `18-bank-ontology.md`).
## 4. Исполнения самопроверки (§5) — команды и вывод
**4.1. Канон парсится + дубли ключей** (loader-хук, § 5 п.1-2; скрипт `check_canon.py` в
скратчпаде сессии):
```
$ python3 .../check_canon.py
PARSE OK, no duplicate keys. version = 0.5.0
```
**4.2. Ссылки, обе стороны** (тот же скрипт: все `$ref` резолвятся; все компоненты на кого-то
ссылаются):
```
refs total: 272; dangling: 0
components.schemas: 63 defined, unreferenced: none
components.responses: 10 defined, unreferenced: none
components.parameters: 11 defined, unreferenced: none
components.headers: 2 defined, unreferenced: none
```
Тем же скриптом пере-ран гейт §5 компаньона (утечка конвейерного словаря) по ФИНАЛЬНОЙ спеке:
`stage` — 1 хит, сама формулировка запрета (легально); `edit` — 2 хита, оба прежние легальные
английские глаголы (`:283` «not an edit», `:1683` «editing the source» — инвентарь 0.4.0, новых
нет; команда: `grep -n "\bedit" openapi.yaml | grep -v credit`); `verdict` — 2 хита БЫЛИ моими в
`CorrectionRefusal`, исправлено на «refusal» до сдачи, пере-ран чист.
**4.3. Настоящий линтер и генератор** (пины зоны фронта, поверх п.1):
```
$ ./frontend/node_modules/.bin/spectral lint --ruleset frontend/.spectral.yaml docs/architecture/14-api-contract/openapi.yaml
No results with a severity of 'error' found!
$ ./frontend/node_modules/.bin/openapi-typescript <канон 0.4.0 из HEAD> → OK (exit 0)
$ ./frontend/node_modules/.bin/openapi-typescript <канон 0.5.0> → OK (exit 0)
```
Дифф генерённых типов 0.4.0 → 0.5.0 — 380 строк, ВСЕ в заявленной поверхности: путь и operationId ·
минус три схемы и счётчики (`BankPage`, `EventBank`) · плюс шесть схем · `ErrorCode` +2 значения ·
`Capabilities` +1 обязательное поле · `Problem.refusals`. Неожиданных сдвигов нет (команда: `diff
types-040.ts types-050.ts`). Замечание генератора: `oneOf`-ветки идентичности `BankCorrection`
сворачиваются в `& (unknown | unknown)` — тип не дискриминирует ветки; это известный класс К-11
(генератор игнорирует и `if`/`then`), правило «схема + слова» применено, слова в описании стоят.
**4.4. Гейт платформы краснеет ПРЕДСКАЗУЕМО** (§5 п.3; копия ВМЕСТЕ с каноном, как велит промт):
```
$ cp -a --parents platform docs/architecture/14-api-contract $SCRATCH/gatecopy/
$ cd $SCRATCH/gatecopy/platform && go test ./internal/gates/ -run TestTheAnnouncedContractVersionIsTheOneTheCanonRatified
--- FAIL: TestTheAnnouncedContractVersionIsTheOneTheCanonRatified (0.00s)
contract_test.go:40: this build announces contract 0.4.0 and the ratified canon is 0.5.0; the
constant is raised in the same change as the code that implements a minor, never afterwards
FAIL
```
Красный ИМЕННО на несовпадении версий и ИМЕННО с ожидаемым текстом; константу поднимает оркестратор
при лендинге тем же коммитом (§4 промта, D39.160).
## 5. Находки опровергателей — все, включая отвергнутые с причиной
Панель: 3 агента (в пределах веера 24, §5 промта), по осям §6 — «словарь двери против словаря
глагола» (заказ) · «холодный потребитель/генератор» · «что читатель узнает о том, чего нет».
Workflow `wf_20c22060-e6e`, 349k токенов, 0 упавших. Каждый ключевой клейм пере-сверен МОИМ чтением
кода до вправления (файлы и строки в диспозициях). **Итог: 21 находка; принято и вправлено 17,
отвергнуто 4 (с причиной ниже).**
### Приняты и вправлены (после каждой — куда легла правка)
**Ось «словарь глагола»:**
1. **MAJOR. Decline сид-поверхности уплощён до безусловного отказа.** Движок отказывает ТОЛЬКО
инертному (`decisions.go:374`, условие `!deltaHoldsSurface`); когда правки книги держат свою
строку той же поверхности, decline принимается и снимает её — ремонт ливлока, ради которого
правило и переписывалось. Мой канон запрещал ремонт. → канон (`BankCorrection`, список
«NOT correctable») + компаньон §2.19 (строка сид-терма).
2. **MAJOR. Decline алиаса уплощён.** Движок судит РЕЗУЛЬТАТ и отказывает только алиасу
ПОДПИСАННОГО терма (`aliasOwner` пропускает `status != approved`, `decisions.go:644-659`);
decline терма и его алиаса одним документом — оба принимаются. → канон (условная формулировка
«once this document is applied, would remain only an ALIAS an approved correction still fires
for») + компаньон.
3. Алиасы на проводе НЕ публикуются (`BankTerm` их не несёт, D39.136 п.4б), а вывод-таблица
читалась как будто публикация есть; клиент не может увидеть, что поверхность — алиас. → канон
(скобка «the alias set itself is not published on this surface») + компаньон (названная щель).
4. Класс 12 → `run_in_flight` точен только при сериализации платформой СВОИХ вызовов двери (флок
держит любой глагол, включая превью). → компаньон: обязательство монтажа (в), «точное слово»
переквалифицировано.
5. `400` `errors[/book_id]` не имеет движкового производителя (движковая сверка — класс 10):
производит платформа до спавна. → компаньон: обязательство монтажа (б).
6. Оба потолка у движка — класс 14, канон раскладывает в `400`/`413`: платформа мерит их на
проводной форме до спавна; остаток (движковый документ после рендера > 1 МиБ) падает в `409`.
→ компаньон: обязательство монтажа (а); канон: описание `bank_corrections_refused` несёт
«a set larger than the service applies in one act».
7. `preexisting_faults` «may stop at the bank» читался как благой signing-stop, и объект был сужен
до файлов правок (движок считает и фолты сид-строк). → канон: «bank inputs», «would FAIL at
the bank — a fault, not the signing stop».
8. «`mode` раскладывается без остатка» — ложь: исход `stopped` не был разложен. → компаньон:
назван (`5xx` рестарта, ничего не записано, ретрай сходится).
9. Усечение отказа: на `409` движок печатает полный отчёт, провод несёт только `refusals[]`
не было названо. → компаньон: названо ценой v1.
10. `kind` на проводе сужен до `TermKind`, движок принимает любую строку; источник пятёрки —
классификатор чтения, не `decisions.go`. → компаньон: сужение задекларировано ◆ с доводом.
**Ось «холодный потребитель»:**
11. **MAJOR. Счёт `signature` недостижим, пока нечего послать** (у `corrections` `minItems: 1`,
пустой документ и движок отказывает классом 10). Решено НЕ ослаблением `minItems` (движок
пустой документ не принимает — ослабление дало бы дверь, врущую о глаголе), а НАЗВАННОЙ
узостью: канон (`signature` квитанции + `listBankTerms`) говорит прямо «only there; a client
with nothing to correct or preview cannot ask for it yet»; носитель возврата счёта в чтение —
§2.19-бис.
12. **MAJOR. Семантика `sense`/окна при `decline` в кортежной форме не была определена.** → канон:
«say which row the receipt reports and do NOT narrow the effect», для поверхности вне банка —
`sense: ""` и `null`-окна (сверено: движковый decline ключуется нормализованным `src`,
`addReject`).
13. **MAJOR. Неизвестный `id` — двоякое прочтение (400 c `errors[] unknown` против 409).** → канон
называет код явно: `409` `bank_corrections_refused`, вход в `refusals[]` (движок: класс 14).
14. **MAJOR. Отказ за decline алиаса опирался на данные, невидимые клиенту** — слился с №2/№3.
15. «Would change nothing» как причина 409 против гарантии `already_applied` — граница не была
проведена. → канон: «a `decline` nothing recorded answers to; re-sending an already-recorded
correction is NOT this — that answers `200` with `already_applied`».
16. `AcceptedCorrection.dst` — третье незаявленное исключение из правила шапки
«required+nullable». → канон: `dst` теперь required, `[string, 'null']`, «null on decline».
17. Переиспользованные `TooLarge`/`ServiceUnavailable` несли чужую конкретику (интейк/прогоны) —
докстроки врали бы на этой операции. → канон: описания компонентов обобщены, `503` отсылает к
диспетчеризации по `code`.
18. `BankTerm.id` «its surfaces» (мн.ч.) читалось как «id зависит от dst». → канон: «its SOURCE
surface … not from `dst`, so a corrected rendering keeps the id».
19. Протухший пример `EventHello.contract` `0.4.0`. → канон: `0.5.0`.
20. `Problem.code` обязателен схемой, а вне `/v0` может отсутствовать — правило жило только в
шапке, генератор его не видит. → канон: оговорка в описании `Problem`.
**Ось «чего нет»:**
21. **MAJOR. «Канон и деплой при лендинге СОВПАДАЮТ» — переклейм.** Сверено кодом: `wireBankPage`
(`platform/internal/httpapi/reading.go`) продолжает слать `pending_decisions`/`complete`, и
они НЕ нули — `bankCountsTx` (`pgstore/readmodel.go`) считает «все proposed-строки» с
комментарием «the wire fields are the canon's» (теперь ложным). Совпадение точно по ПУТЯМ, не
по полям. → компаньон: шапка переписана честно, §2.19-бис несёт сверенную правду вместо
«навсегда нули», строка `GET /bank` в §3 пере-снята, носитель снятия — пункт (2в). ⚠ Это
расхождение с БУКВОЙ промта пака (§4 п.2 «СОВПАДУТ точно», §3.2-бис «поля навсегда нули») —
**пинг оркестратору, см. §6.**
22. Композиция «до монтажа 2в счёт недоступен НИГДЕ» была только выводимой. → компаньон
§2.19-бис, названо тремя половинами цены.
23. А-2: «гейт полноты ДЕМОНТИРУЕТСЯ в P7» — будущее время при снятом гейте (сверено:
`reconcile.go`, ветка `awaiting_bank`). → компаньон: «ДЕМОНТИРОВАН, сверено с кодом».
24. §2.9: баннер 0.5.0 стоял ПОСЛЕ перекрытой клаузы — против «баннер прежде содержимого». →
компаньон: переставлен перед ней.
25. Позитив: все семь обязательных «явных фактов» оси 3 подтверждены с картой line-номеров
(вердикт панели, находка-нота) — в канон изменений не требует.
### Отвергнуты, с причиной
1. **`Capabilities.intake_max_bytes` обязателен и не-nullable у read-only деплоя** — реальный
дефект, но 0.3.0/0.4.0-наследие ВНЕ состава этого пака (§3 промта); правка сейчас раздула бы
ломающую поверхность минора без заказа. Оставлено оркестратору как кандидат следующего касания.
2. **`TermKind`/`TermStatus`/`TermOrigin` без пер-схемных нот толерантности** — паттерн 0.3.0, вне
состава пака; общее правило шапки формально покрывает. Кандидат следующего касания (вместе с
№1).
3. **Байт-зеркало фронта (0.2.3) несёт снесённую модель** — отставание РАТИФИЦИРОВАНО (D39.142
п.5, D39.147, фриз фронта); шапка компаньона его уже несёт. Не дефект этого минора.
4. **`unreadable`: «the call was refused before it could count» не имеет носителя на проводе** —
принято НАПОЛОВИНУ: формулировка-триггер из описания снята (правда), но само поле оставлено —
первый триггер («не читается состояние») жив и на 200-квитанции (карта/файлы нечитаемы, вызов
при этом принят byte-no-op'ом… нет: нечитаемые файлы — отказ класса 10; нечитаемой может быть
КАРТА подписи — вызов принят, счёт не измерен). Ровно этот случай поле и несёт.
## 6. Obstacle — что НЕ удалось и что НЕ проверено (§10)
1. **Расхождение промта с кодом — пинг оркестратору (§11 промта):** промт утверждал «платформа
свою половину уже снесла 22.08, после твоего сноса они СОВПАДУТ точно» (§4 п.2) и «поля
навсегда нули» (§3.2-бис). Сверка с кодом (`httpapi/reading.go` `wireBankPage`;
`pgstore/readmodel.go` `bankCountsTx`) показала: путь снесён, а ПРОЕКЦИЯ ЧТЕНИЯ продолжает
слать оба поля, и `pending_decisions` — живое число всех proposed-строк, не ноль. Я не
интерпретировал в свою пользу и не обходил: канон 0.5.0 поля снимает (это и есть заказ), а
расхождение записано в шапку компаньона с носителем (пункт 2в) и сюда. **Оркестратору решить:**
достаточно ли носителя «пункт 2в» для снятия двух полей из `wireBankPage`, или нужна отдельная
строка бэклога платформы (я её завести не могу — не моя зона).
2. **Не проверено исполнением:** поведение НАСТОЯЩЕЙ платформы против 0.5.0 (маршрута нет — 404
проверить не на чем до монтажа); рендер экранов фронта (зона заморожена ратифицированно);
`spectral` гонялся ТОЛЬКО с рулсетом зоны фронта (`spectral:oas`) — иных рулсетов в репо нет.
3. **Названные щели v1 (в канон/компаньон внесены, но не закрыты):** машинного словаря причин
отказов нет (едут developer-facing `detail`); алиасы невидимы клиенту; счёт `signature`
недостижим без правки/превью; на `409` не едут `preexisting`/`signature`; счётчики деплой шлёт
до монтажа 2в.
4. **Гипотетический остаток раскладки потолков:** случай «HTTP-тело < 1 МиБ, движковый документ
после рендера платформой > 1 МиБ» назван и покрыт кодом 409, но живьём не воспроизводился
(двери нет); замер — работа монтажа.
5. Дифф генерённых типов пере-ран после вправлений панели (`types-050b.ts`, exit 0), но
пост-фиксовый ПОЛНЫЙ дифф против 0.4.0 построчно не пере-инвентаризировался — сверены только
изменённые правками места (`AcceptedCorrection.dst`, примеры, описания).
## 7. Таблица комплектности против §3 (§7)
| Пункт заказа | Что сделано | Исполнение-подтверждение |
|---|---|---|
| §3.1 снос: канон, 9 позиций | путь+операция (`:469-505` стар.) · проза `:1830` · три схемы `:1939-2008` — снесены; замена — дверь corrections | `grep -n "bank/decisions\|submitBankDecisions\|BankDecision\b\|BankDecisions\|pending_decisions\|term_id" openapi.yaml` → exit 1 (0 хитов) |
| §3.1 снос: компаньон, 5 позиций | `:124` (список К-11-мест) · `:674` (историческая строка сохранена, статус дописан) · `:685` (пере-снята на живые носители) · `:724` (К-11) · `:1173` (⚠-баннер истории §6в K) | `grep -n "submitBankDecisions\|BankDecisionsRequest\|BankDecisionsResult" README.md` → 0 хитов вне ⚠-контекстов; пер-позиционные диффы в дереве |
| §3.1 «свой греп обязателен, ещё и по `dst`/`UnknownTermError`/`BankPage`» | исполнен до правок | команда и хиты — секция 3 отчёта; `UnknownTermError` — 0 хитов в обоих файлах |
| §3.2 дверь объявлена, тело выведено из глагола | `POST /books/{bookId}/bank/corrections` + 6 схем + 2 корневых кода + member `refusals` | вывод-таблица §2.19 компаньона (каждое поле — file:line движка); панель-опровергатель по оси словаря — секция 5 |
| §3.2 машиночитаемый признак «не построено» | `Capabilities.bank_corrections_enabled` (required; `false``404`) | канон; прецеденты `intake_enabled`/`export_formats` — §2.19 |
| §3.2 ⛔ signature только с запретительным контрактом | `BankSignatureCount` несёт ОБЕ половины D39.144 + `unreadable` + `null`-семантика | канон `:2217+`; проверка панелью (ось 3, факт 7 подтверждён с line-номерами) |
| §3.2-бис счётчики: решить обязан | решено — СНОС с трёх носителей (третий найден моим грепом) | секция 3 отчёта: греп-команда; §2.19-бис компаньона |
| §3.3 конверт вне `/v0`, строка 203(а) | предупреждение в `info.description` + оговорка в `Problem`; ссылка на компаньон §2.14 | буква (а) сверена: `docs/PROGRESS.md:146` (греп `строка 203`); канон `:39-43` |
| §3.4 прогресс НЕ трогать | семантика `:1293` не тронута | `git diff openapi.yaml | grep -c "segment\|counter starts again"` → 0 правок в блоке `Progress` |
| §4 версия | `0.5.0`; гейт платформы краснеет предсказуемо | секция 4.4: команда копии и вывод FAIL с ожидаемым текстом |
| §5 п.1 парс | исполнено | секция 4.1 |
| §5 п.2 ссылки + дубли | исполнено, обе стороны | секция 4.2 |
| §5 п.3 гейт на копии | исполнено, `cp -a --parents` | секция 4.4 |
| §5 опровергатель (заказ) | 3 агента, 21 находка, 17 вправлено, 4 отвергнуто с причиной | секция 5; workflow `wf_20c22060-e6e` |
| §7 записка-план до правок | секция 1 написана до первой правки файлов контракта | git-история дерева не создавалась (не коммичу); порядок виден по этому файлу |
| §9 эхо · §10 obstacle · §11 состав | секции 1, 6; состав сдачи — три файла | `git status` перед сдачей — см. финал сессии |