# Промт: платформа, пак P7 — читающая поверхность по контракту 0.3.0 + модель ошибок + форварды (П-17, строка 169 единого) > Выдан оркестратором №17 16.08.2026 (очередь D39.133; входы — D39.134 п.4 · D39.135 п.2в · D39.138 · > пинги №17 в зонном журнале). Запуск — по слову владельца, ПОСЛЕ лендинга батча 0.3.0 (§1). ## 0. Какую проблему ты решаешь и что решит твой результат Платформа — control plane между веб-фронтом и движком перевода. К сегодняшнему дню построено всё СТАТУСНОЕ и денежное: вход, кредиты с холдами, очередь и раннер, интейк книг, потребительская половина шва с движком (события `events.jsonl` уже пишутся движком и материализуются в Postgres, включая пер-юнитные разрешения). Чего нет — **читающей поверхности**: фронт не может прочитать ни главы, ни юниты, ни замечания, ни банк, ни живой поток; из 16 операций контракта платформа отвечает на 8. Из-за этого фронт живёт на моках и ЗАМОРОЖЕН, а центральный экран продукта (подпись банка) не строится вовсе. Второе: причины отказов не существуют в машинном виде — сервер шлёт английскую фразу, которую русский интерфейс печатает как есть. Твой пак делает платформу ЧИТАЕМОЙ и её отказы — машинными. Результат разблокирует разморозку фронта и экран подписи. Контракт только что пере-согласован целостным ревью (research/28, принят D39.138) и сломан минором 0.3.0 ровно для того, чтобы ты строил новые ручки СРАЗУ по правильной форме — не строй по памяти о старой. ## 1. ПРЕДУСЛОВИЕ — проверить до первой строки кода Нормативная спека — **канон `docs/architecture/14-api-contract/openapi.yaml`**, `info.version` обязана быть **0.3.0**. Если там 0.2.3 — батч ещё не заленден: исполни только пункты 0–2 состава (§4 — они от батча не зависят), затем СТОП и пинг владельцу. ⚠ Зонное зеркало `frontend/docs/api-contract/openapi.yaml` во фризе фронта может ОТСТАВАТЬ от канона — это известное состояние; читать только канон. ## 2. Зона и git (канон — CLAUDE.md; здесь напоминание) **Ты не коммитишь — лендит оркестратор.** Зона записи — только `platform/`. Прогресс, отчёт и вопросы — ТОЛЬКО зонный журнал `platform/docs/platform-PROGRESS.md`. Чужие зоны read-only; чужие незакоммиченные файлы (живой полигон: `eval/`, `docs/experiments/`) не трогать; `.env` не читать; никаких `git add`/`git commit`/`reset`/`checkout`/переписывания истории — git не трогаешь вовсе, файлы застейдженными не оставлять. Ревью-гард D39.85: путь Go-модуля платформы никогда не вкладывать под путь движка. ## 3. Что читать (карта, ≤5 позиций) 1. **Канон 0.3.0 + компаньон** (`docs/architecture/14-api-contract/`) — целиком: форма каждой новой ручки уже решена там, не изобретай параллельную. 2. **`docs/research/28-contract-review.md`** §5 (состав правок и зачем) · §8/§8а (решения владельца: классы конкретности отказов) · §5б (сеть: что строить, чего НЕ строить) · §9 (находки по твоей зоне) + **D39.138 п.2** (ратификация; при конфликте побеждает нота). 3. **Свой журнал `platform-PROGRESS.md`** — три пинга №17 (15–16.08) и аддендум: там входы этого пака (PD-104, форварды, протухшие тексты твоих доков) и попутные находки §9, которые ты судишь сам. 4. **Read-out поверхности движка** — пинг №15 в том же журнале (D39.122): манифест `.manifest.json` (`tm-manifest-v2`), банк `.bank.json` + стоп-таблица `.bank-stop.json` (пишутся атомарно, читать можно во время прогона); плюс твоя же таблица `unit_resolutions` (миграция 00015) — источник юнитов/замечаний. 5. `CLAUDE.md` — гардрейлы; `docs/glossary.md` — жаргон. ## 4. Состав пака — в этом порядке. **СОСТАВ пунктов 0–5 — «делай РОВНО так» (ратифицирован); свобода — в ФОРМАХ исполнения внутри пунктов, где канон/промт форму не фиксируют. Пункт 6 — судишь сам. ⚠ Пункты 0–2 от батча 0.3.0 не зависят — при запуске до батча исполняй их и стоп перед п.3.** **0. Рантбук деплоя живым `migrate` — end-to-end на дев-стенде ($0, первым шагом).** Прогнать собственный `deploy/README.md` настоящим новым бинарём движка по каждой книге стенда (`tmplatformctl books --migratable` → `tmctl migrate`) — предусловие ПЕРВОГО выката (мнение оркестратора из пинга 15.08; движковая половина финальна — D39.134; твой журнал честно фиксирует «живьём не гонялся»). Попутно починить мёртвый текст ошибки схемы в `deploy/README.md:131` (движок теперь печатает токен `schema_mismatch found=N expected=M`, exit 13) и комментарий-образец `cmd/tmplatformctl/runs.go:45` (зовёт голый `tmctl` из PATH — воспроизводит тихий no-op старым бинарём); якорь П-1 в своём BACKLOG обновить. **1. Форварды 0.2.3 (РОВНО так, малые):** читать `BookIntake.title` (сегодня падает в «unknown field is IGNORED» — `internal/httpapi/v0.go:369-376`, якорь-отправная точка, код первичен) · проецировать `books.reject_reason` на провод (`v0.go:497` — «kept for an operator and never projected»). **2. PD-104 (РОВНО так, слово владельца 16.08):** `SignupGrantMicroUSD` дефолт → **0** (бета: начисление руками через админ-CLI; возврат $5 — вместе с суточным потолком при появлении платежей) + тест; регистр и протухшие «$5» в `PLATFORM_DIRECTION.md` §2 / BACKLOG П-7 — поправить. ⚠ Ветка «грант 0 при неверифицированном email» (`login.go:306-308`) УЖЕ существует — это не баг и не твоя правка, не перепутай с ней. **3. Модель ошибок (Б-1/§8а) — ПЕРВОЙ из контрактной половины,** от неё зависят формы остальных ручек: структура `Problem` по 0.3.0 (машинный `code` двухуровневый + `request_id` — значение уже штампуется, `internal/reqid`). ⚠ **Словарь кодов УЖЕ определён каноном** (батч вывел его из твоих же веток `fail()`) — РЕАЛИЗУЙ словарь канона, не выводи свой заново: не хватает причины для реальной ветки — пинг, не изобретение (два независимых вывода из одного источника гарантированно разойдутся именами). Класс 2 (прескрин/провайдер/фильтр) — ОДИН грубый код, без вариации между попытками. `WWW-Authenticate` на 401; две причины 403 развести (нет `X-TM-Client` ≠ кросс-origin). **4. Читающая поверхность по 0.3.0 (ядро пака):** главы / юниты / замечания (с `id` и `created_at` — форма 0.3.0) / банк (проекция сайдкаров движка + снимок стопа подписи `pending/complete`) / `POST /bank/decisions` / **SSE-поток** в форме 0.3.0 (канал КНИГИ, кадры конца разбора и конца прогона, `204` переподключению к завершённому, склейка ТОЛЬКО снимкам — `note`-класс не склеивать). ⚠ **Пофазность у главы НЕ строить** (К-10 отвечен «НЕТ», D39.138 п.5): колонки `units_draft_done`/ `units_edit_done` лежат в read-модели готовыми и «бесплатная проекция» напрашивается — фазы на провод не выходят НИ у книги, ни у главы; глава отдаёт один счётчик по канону. Сюда же сеть, шаги 1–2 §5б (строка 186): **gzip на текстовых ответах (НЕ на SSE)** и `ETag`/`If-None-Match` → 304 на списочных GET. Совет-приор: ревизия у тебя уже читается одной транзакцией со страницей (PD-163) — ETag из неё. **5. Правки построенного под 0.3.0:** `wireProgress` → один счётчик до остановки (Б-0; ⚠ колонки БД и словарь шва с движком НЕ трогать — фазы остаются внутренним делом); `GET /capabilities` (Б-2: пары из конфигурации · порог интейка · форматы · размеры страниц · версия контракта); подрезка `limit` до максимума вместо сброса к дефолту (Б-10); трейлинг-части интейка → 400 вместо тихой потери + `Location` на 201 + `Idempotency-Key` (Б-3); `blocked: {code, book_id}` на run-options/409 (В-6); отказ по неподдерживаемой паре кодом на интейке (сегодня ja/en-книга умирает `failed`-ом на валидации движка в конце пути); `Run.failure_reason` (Б-8 — словарь исхода у движка уже есть); переименование `verify_bank` → `stop_for_signing` на проводе (живёт в построенном: `v0.go:127,154`) и сворачивание `finalizing` из словарей валидации (`runs.go:229`, `sink.go:435`; судьбу CHECK-констрейнтов read-модели реши по канону — значение никем не пишется). **6. Свой регистр — судишь сам (кроме помеченного):** PD-201 (самолечение «поймал exit 13 → migrate → повтор» — движковая половина ФИНАЛЬНА, можно строить); кандидаты PD-219 / PD-217 / PD-162; **обновить протухшие статусы (РОВНО так):** PD-172/PD-173/PD-174/PD-180 — диспозиция «спек-правка» ИСПОЛНЕНА ещё 0.2.3 · PD-199 — ратифицирован закрытым D39.132 п.2а, в регистре до сих пор open; находки §9 research/28 — каждой явную диспозицию (берёшь / P8 с причиной / отклоняешь с причиной): незакрываемые расчёты (бюджет висения холда) · флаг аккаунта сканом всех книг (после PD-203) · `ReadRunForSpawn` O(живых) · **`/metrics` без аутентификации (защита — только 127.0.0.1)** · лимитер входа на процесс · сырой Go-текст в карантине. Протухшие тексты зоны: баннер §3 `PLATFORM_DIRECTION.md` привести к D39.132 п.2б и §4 п.5 (склейка сузилась — только снимкам). Инструменты: **sqlc — ПРИВЯЗАН к этому паку (D39.132 п.2б, ратифицировано):** внедряй на читающей поверхности с `overrides` на денежные типы, отступление = пинг; oapi-codegen — кандидат, реши сам и аргументируй. **Явно отложено в P8 (не тихо):** `PATCH /books/{id}` (title-only) + `DELETE` + `GET /runs/{id}` · эскроу П-18 (денежный промт) · всё, что не влезло, — списком с причинами в отчёте. ## 5. Нормы исполнения - **Самопроверка исполнением:** батарея `make check` + ОБА гейта (`TM_PLATFORM_TEST_DSN` + `TM_PLATFORM_TEST_ENGINE_BIN`/`_BOOK_TEMPLATE`) — **скипов 0 это гейт**; физически неустранимый скип = obstacle, объяви и объясни; дифф `^func Test` — исполнением, не памятью; живые пробы новых ручек против дев-стенда (сид P6). - **Заявление = команда:** каждое число/категорическое утверждение отчёта — с командой; приёмка пере-ранит. - **Записка-план по §4** (D39.121): каждый пункт (0–6 и отложенные) — строка «исполнено, где / отказ, почему»; сдача = все с диспозицией, комплектность против заказа механически. - **Шов:** если касаешься ЛЮБОГО канала движка — сначала инвентарь ВСЕХ его каналов и кодов чтением чужого кода, не по памяти (урок D39.132: `status --json` упустили все, кроме панели приёмки). - Посадки мутаций — дисциплина `ENGINEERING_STANDARDS.md` §3, пункт «посадки» (списочный пункт 3, ~:67-69; ⚠ нумерации «§3.3» в файле нет — не ищи заголовок). - **Предметная ось зоны:** индустриальный первоисточник прежде велосипеда — RFC 9457 (problem+json), WHATWG SSE (204/переподключение), RFC 9110/9111 (условные запросы, `Vary` при gzip); stdlib/устоявшаяся библиотека прежде своего. Право добавить свою ось или снять эту — с аргументом. - **Деньги:** пак денег не двигает (PD-104 — константа гранта); если что-то денежное всё же затронул — два независимых пути счёта из сырого леджера. - **Адверсариальное селф-ревью финалом вехи — МЕХАНИЗМОМ, не стилем чтения (субагенты РАЗРЕШЕНЫ явно, спавнь их; норма CLAUDE.md 12.07 + урок 14.08 «author≠reviewer ≠ перечитал сам»):** ≥2 независимых ревьюера-субагента по финальному диффу, author≠reviewer, разные линзы — (а) контракт-конформность: ревьюер получает канон 0.3.0 и твои ручки, мандат «найди расхождение формы провода со спекой» (пере-раном живых проб, не чтением); (б) деньги/шов: мандат «найди путь, где холд/расчёт/канал движка ведёт себя не так, как записано» — с инвентарём каналов, не по списку автора. Плюс **СВОИ посадки мутаций** в новые гейты/ручки (дисциплина посадок `ENGINEERING_STANDARDS.md` §3: свойство считается запиненным, когда посадка роняет тест — посадки НЕ из списка, который ты сам ожидаешь). Проверяемый артефакт: таблица находок и посадок в отчёте, каждая с диспозицией (исправлено / отклонено-с-причиной); ноль находок = повод не верить прогону. - **Obstacle reporting** — обязательная секция отчёта: что НЕ удалось, что не проверено. - **Канал вопросов:** непонятно / промт конфликтует с кодом, спекой или доками → пинг оркестратору через владельца, НЕ интерпретация. Право сказать «этого делать не надо» — с аргументом. ## 6. Эхо-протокол и сдача Первый деливерабл — ≤10 строк «что я понял: скоуп / инварианты / не-делать». Сдача: отчёт в `platform-PROGRESS.md` (записка-план · команды батареи · живые пробы · таблица находок и посадок адверсариального селф-ревью с диспозициями · obstacle reporting · диспозиции §4.6), дерево незакоммиченное, регистру дефектов — новые строки по находкам. Без саги.