203 lines
29 KiB
Markdown
203 lines
29 KiB
Markdown
# Промт: сессия БАТЧ 0.3.0 — ломающая правка контракта API v0 по принятому ревью (строка 183)
|
||
|
||
> Выдан оркестратором №17 16.08.2026 по ратификации D39.138 (приёмка контракт-ревью research/28;
|
||
> решения владельца 16.08 — его §8). Исполняет ОТДЕЛЬНАЯ сессия со своим онбордингом (норма D39.120 п.2).
|
||
> Запуск — по слову владельца.
|
||
|
||
## 0. Какую проблему ты решаешь и что решит твой результат
|
||
|
||
Проект — SaaS-перевод книг: движок (Go, `backend/`) ↔ платформа (control plane, `platform/`) ↔
|
||
веб-фронт (`frontend/`). Между фронтом и платформой стоит ратифицированный контракт **API v0**
|
||
(OpenAPI 3.1). Он рос точечными правками 0.2.0→0.2.3 под давлением строек, и целостного ревью не
|
||
имел. 15–16.08 отдельная сессия провела такое ревью (`docs/research/28-contract-review.md` — ПРИНЯТ,
|
||
D39.138): ядро контракта здорово, дефекты сосредоточены там, где контракт писался вперёд без
|
||
потребителя — ошибки, поток, экспорт, замечания, глава. Владелец разобрал доклад вопрос-за-вопросом
|
||
и принял решения (§8 отчёта); оркестратор ратифицировал их нотой **D39.138 п.2**.
|
||
|
||
Твоя работа — **исполнить эти решения правкой спеки**: батч 0.3.0. Момент дешёвый и не повторится:
|
||
**платформа не отвечает на 8 операций из 16** (сервера за ними нет вовсе, а фронт заморожен и живёт
|
||
на моках), поэтому правка их формы сегодня стоит только правки документа. Сразу после тебя платформа строит читающую
|
||
поверхность (пак P7) **по твоей спеке** — каждый пропущенный тобой дефект она отольёт в код, миграции
|
||
и воркер, где он подорожает на порядок. Отнесись к каждой форме ответственно: этот документ — закон
|
||
для трёх зон.
|
||
|
||
## 1. Зона и git (читать ДО первой правки)
|
||
|
||
**Ты не коммитишь — лендит оркестратор.** Твоя зона записи — РОВНО три файла:
|
||
1. `docs/architecture/14-api-contract/openapi.yaml` — нормативная спека (канон);
|
||
2. `docs/architecture/14-api-contract/README.md` — компаньон (правится ВМЕСТЕ со спекой, §5 ниже);
|
||
3. `docs/archive/reports/CONTRACT_BATCH_0.3.0_REPORT.md` — твой отчёт (новый файл).
|
||
|
||
Всё остальное — read-only: код трёх зон читать можно и нужно, править нельзя. **Зеркало
|
||
`frontend/docs/api-contract/openapi.yaml` НЕ трогать** — зона фронта заморожена (D39.136 п.2), зеркало
|
||
синхронизируют лендинг и первое касание зоны; временное расхождение канона и зеркала — известное
|
||
состояние, не дефект (ратифицируется при лендинге). Чужие незакоммиченные файлы в дереве (живой
|
||
полигон: `eval/`, `docs/experiments/`, `docs/POLYGON_*`) не трогать. `.env` не читать. Никаких
|
||
`git add`/`commit`/`reset`/`checkout` — дерево остаётся как есть, git трогает только оркестратор.
|
||
|
||
## 2. Что читать (карта, ≤5 позиций; порядок важен)
|
||
|
||
1. **`docs/research/28-contract-review.md` — ЦЕЛИКОМ, это носитель твоего задания.** Состав и порядок
|
||
батча — §5 · что резать — §5а · транспорт/сеть — §5б · решения владельца — §8 · форма модели
|
||
ошибок — §8 п.4 и §8а · инструкции лендинга — §8б. ⚠ Ревью-шапка приёмки в голове файла несёт
|
||
ПОПРАВКИ (важнейшие: К-10 закрывается «НЕ строить»; Б-0/Б-11а/Б-23 добавлены ПОСЛЕ адверсариального
|
||
судейства исходной сессии — их основания проверяй строже, одна подмена уже опрокинута эрратой
|
||
16.08-г) — читать тело через неё.
|
||
2. **D39.138 п.2 (живой `docs/architecture/05-decisions-log.md`, с хвоста)** — ратификация решений.
|
||
При расхождении формулировок research/28 и ноты побеждает НОТА.
|
||
3. **Канон 0.2.3 + компаньон** (`docs/architecture/14-api-contract/`) — целиком, до правок: ты обязан
|
||
знать, что ломаешь и почему оно было таким (у половины форм есть записанные обоснования — их
|
||
судьба решается, а не игнорируется).
|
||
4. Код трёх зон — по мере нужды, read-only. `file:line`-якоря отчёта research/28 — отправные точки,
|
||
**код первичен**: перед тем как записать в спеку факт о поведении сервера/клиента, открой место
|
||
и перепроверь (якоря могли уплыть).
|
||
5. `CLAUDE.md` (корень) — гардрейлы проекта; `docs/glossary.md` — жаргон.
|
||
|
||
## 3. Ратифицировано — делай РОВНО так (отступление = пинг владельцу, не тихая девиация)
|
||
|
||
Состав и порядок — **research/28 §5** (здесь не пересказывается — не дублировать носитель).
|
||
Несущие рамки из D39.138 п.2, которые обязаны выжить в любой твоей редакции:
|
||
|
||
- **Порядок исполнения не косметика:** Б-1 (модель ошибок) — ПЕРВОЙ: от словаря кодов зависят
|
||
формулировки Б-2/Б-3/Б-8/Б-14а/§8а.
|
||
- **Б-0:** конвейер уходит с провода. `Progress` → один счётчик до ближайшей остановки, знаменатель —
|
||
КУПЛЕННЫЙ объём (после подписи банка полоса заново); **счётчик ГЛАВЫ — той же сегментной логикой**
|
||
(«сделано в текущем сегменте / всего в сегменте»), иначе дерево глав читает ноль всю черновую волну —
|
||
исходная жалоба К-10, снятие фаз её само по себе не лечит; `finalizing` снять из словарей (устная
|
||
фраза владельца, не норма — §8 п.15); `verify_bank` → `stop_for_signing` без упоминания следующей
|
||
фазы; `TermOrigin` снять/переименовать (`ruby` — паро-специфика, настоящая утечка); ⚠ **`TermStatus`
|
||
ОСТАВИТЬ осью** (эррата 16.08-г: это продуктовый «главный фильтр работы» экрана подписи, шов клиента
|
||
его уже потребляет) — переименовать лишь значения, читающиеся движковыми (`auto`); `Unit` описать без
|
||
«edit unit» и «1.9 на главу»; из ВСЕХ описаний вычистить конвейерные слова — они компилируются в
|
||
JSDoc клиента.
|
||
- **Б-1 — вариант B (§8 п.4 + §8а):** машинный `code` (двухуровневый: стабильный корневой +
|
||
расширяемый вложенный) + `request_id` (значение на сервере уже есть); `title`/`detail` —
|
||
developer-facing, клиент НЕ показывает; серверная локализованная фраза — отдельным полем ТОЛЬКО
|
||
для неперечислимых причин; `errors[]` с указателем поля для валидации. Два класса конкретности:
|
||
класс 1 (детерминированные — вход/счёт) — конкретика максимальная; класс 2 (модельные — прескрин /
|
||
отказ провайдера / фильтр) — ОДИН грубый код на весь класс, без вариации между попытками (К-9:
|
||
`rejected` + грубый код, 12-й статус НЕ заводить).
|
||
- **В-6:** `run-options` и 409 на старте прогона получают `blocked: {code, book_id}` — почему вторая
|
||
книга не стартует (D39.138 п.2з; в 0.2.3 поля НЕТ — заводишь ты). **К-13-остаток:** описание
|
||
`paused_reason` `:879` «null in every other state» противоречит ратифицированному «paused+null» —
|
||
поправить (D39.138 п.4).
|
||
- **Б-11а/§5б шаги 3–4 — В БАТЧ (заказ ПОВЕРХ §5: в его перечне Б-11а нет — дыра носителя, вписано
|
||
пост-ревью 16.08):** правило кадра «несёт применимую дельту ЛИБО счётчик + скоуп (id сущности +
|
||
версия), но не заставляет перечитывать коллекцию» — вместо нынешнего необязательного «сервер МОЖЕТ
|
||
склеивать»; форма дельта-чтения банка/замечаний `?after_version=` — контрактная (иначе «кадр банка
|
||
на главу = 372 МБ/прогон» встраивается в P7 и снимается второй ломкой; строка 186 маршрутизирует
|
||
семантику сюда).
|
||
- **`Idempotency-Key` — семантику решаешь ТЫ, не P7:** окно хранения, область ключа, ответ на повтор
|
||
с другими параметрами — записать в спеку; P7 только реализует.
|
||
- **Жанр — выкинуть** из `BookIntake` и `Book` (Б-23; остальные половины удаления — строка 184, не твои).
|
||
- **Экспорт остаётся** и получает состояние отказа (Б-4: `state` вместо булева `ready`, `failure_code`,
|
||
`expires_at`, эхо формата, правило доступа к ссылке — ПТ-34).
|
||
- **Б-19:** запрет клиентской служебной метки «Глава {n}» СНЯТЬ (ратифицировано, решение 09.08).
|
||
⚠ Не путать две вещи: `title_raw`/`kind` — ВЫБОР ТВОЙ (заложить формой сейчас ЛИБО явно передать
|
||
дизайн-паку 161 записью в компаньоне — аргументируй); **структурная ВЕРСИЯ — обязательна батчу**
|
||
(Б-7, §5 п.9: версия в ответах и `hello`, `410` на исчезнувшую главу, `If-None-Match`/304) — её в
|
||
161 не сдвигать.
|
||
- **Версия = 0.3.0**, обычный ломающий минор; право ломать в 0.x — весь бета-период (§8 п.17).
|
||
- **НЕ заводить в батч:** `POST /books/{id}/parts` (строка 185, дизайн — пак 161) · историю прогонов
|
||
(в МВП не нужна) · двухшаговую загрузку · ленту изменений структуры · поиск/фильтр · «грубую группу
|
||
статуса». В компаньон они записываются НАПРАВЛЕНИЯМИ: где строка бэклога существует — с её номером
|
||
(185), где нет — с носителем «research/28 §5 „не в батч"» (строк под них сознательно не заводили;
|
||
выдумывать номера нельзя).
|
||
- **Не финализировать формы без источника (§5а-оговорка):** словарь ступеней замечаний НЕ проектировать
|
||
(К-6: владелец — «решим потом»), поля `BankTerm` НЕ добавлять (D39.136 п.4б) — чтения замечаний и
|
||
банка держать минимально-достаточными (Note.id/адресация и снимок подписи — Б-9/Б-14а — входят).
|
||
- **Гейт на утечку конвейера** (тест по образцу языкового) — фронт-половина, тебе НЕ строить (носитель —
|
||
пинг фронту 16.08 в `frontend/docs/frontend-PROGRESS.md`, исполнение при разморозке); ты записываешь
|
||
в компаньон само правило «на проводе нет имён стадий/волн и движковых словарей» как ревью-вопрос
|
||
каждой правки.
|
||
- **Граница «ровно так / сам» внутри пунктов §5:** ЧТО делать — ратифицировано; КАК выразить формой —
|
||
твоё везде, где §5/§8/D39.138 не фиксируют форму явно. Зависимость исполнения: словарь кодов (Б-1)
|
||
определи ДО формулировок Б-2/Б-3/Б-8/Б-14а — порядок списка §5 (Б-0 нулевым) этому не противоречит.
|
||
|
||
## 4. Реши сам и аргументируй в отчёте
|
||
|
||
Точные имена полей и значений словаря кодов (класс 1 — из реальных причин `fail()` платформы, читай
|
||
код) · формы схем (пять конвертов списков на `allOf` — §5а «слить формально») · состав и глубина
|
||
резки §5а (мёртвые поля/кадры — с обоснованием на каждое) · как записать сеть — РАЗВОДИ по
|
||
наблюдаемости, чтобы не упереться в Б-16: условные чтения (`ETag`/`If-None-Match`/304/`Vary`) —
|
||
нормативная спека, клиент это видит и обязан уметь; «включить gzip на edge» — эксплуатационное
|
||
примечание, не норма (Б-16 выносит требования деплоя из контракта) · формулировки всех описаний ·
|
||
размер страницы
|
||
замечаний: замера масштаба нет (500 выбрано без числа — открытый вход строки 183), нового числа не
|
||
выдумывай — оставь с оговоркой в компаньоне. Совет-приор (опровергается
|
||
аргументом): для правил, которые OpenAPI не выражает (межполевые инварианты, условная обязательность),
|
||
образец уже есть в спеке — `BankDecision.dst` через `if/then` плюс прозу; помни улику К-11: генераторы
|
||
`if/then` игнорируют, значит правило обязано жить и словами для клиента.
|
||
|
||
## 5. Компаньон — ВМЕСТЕ со спекой (не после)
|
||
|
||
(а) Снять опровергнутые утверждения: ответ §5 «добавлена волна → фронт не правится» (опровергнут
|
||
исполнением, Б-0) · «канала банка нет» §3 против собственной строки 267 (Б-7а) · resume-абзац
|
||
(Б-7а п.4: лечение «новый прогон с бОльшим потолком» существует). (б) Завести таблицу
|
||
«чтение → источник → строка бэклога» и правило «предупреждение о недостроенном несёт номер строки»
|
||
(Б-21). (в) Обновить провенанс-классы ✓/◆/○ под 0.3.0. (г) Приложение А (карта «код → фраза»):
|
||
структуру перевести на словарь кодов Б-1, СЛОВА не заполнять — фразы пишет владелец (строка 148).
|
||
(д) Генезис-прозу из спеки (история ратификаций, апологии RFC — §5а называет места) переносить в
|
||
компаньон, не удалять.
|
||
|
||
## 6. Мандат самопроверки — исполнением, не заявлением
|
||
|
||
1. **Линт (форма проверена исполнением 16.08):** `cd frontend && npx spectral lint
|
||
../docs/architecture/14-api-contract/openapi.yaml --ruleset .spectral.yaml --fail-severity=warn`
|
||
— exit 0 (предупреждение валит так же, как ошибка). Читать/запускать фронт-тулинг можно,
|
||
писать в зону фронта — нет.
|
||
2. **Записка-план** (норма D39.121): каждый пункт §5 research/28 (включая однострочники и §5а)
|
||
И каждый подпункт §5(а)–(д) ЭТОГО промта (компаньон — половина заказа) получает строку
|
||
«исполнено, где / отказ, почему» — сдача = все ID с диспозицией; это же — скелет твоего отчёта.
|
||
Комплектность против заказа — механически, не по памяти.
|
||
3. **Предметные оси** (право снять/добавить свою — с аргументом): (а) «второй клиент» — РЕАЛЬНО
|
||
прогони генератор по своей схеме (`cd frontend && npx openapi-typescript ../docs/architecture/14-api-contract/openapi.yaml -o /tmp/schema-probe.ts`
|
||
— read-only использование фронт-тулинга, вывод вне зон): не указывает ли схема нарушить
|
||
собственную прозу (класс PD-172: порядок свойств `BookIntake` указывал класть файл вторым);
|
||
«мысленная генерация» исполнением не считается; (б) анти-утечка — греп
|
||
финальной спеки по словарю конвейера (draft/edit/wave/stage/mined/ruby/finalizing и что найдёшь
|
||
сам); (в) каждое «оставить как есть» в спорном месте несёт записанный контраргумент (анти-инерция).
|
||
4. **Заявление = команда:** каждое числовое/категорическое утверждение отчёта — с командой, которой
|
||
получено; приёмка их пере-ранит.
|
||
5. **Адверсариальное селф-ревью — МЕХАНИЗМОМ, не стилем чтения (норма 6а: субагенты РАЗРЕШЕНЫ явно,
|
||
спавнь их).** После завершения правок запусти ≥2 независимых ревьюера-субагента, author≠reviewer —
|
||
они видят только артефакты, НЕ твой ход мысли: (а) **опровергатель полноты** — получает research/28
|
||
§5/§5а/§8а + D39.138 п.2 и финальный дифф спеки, мандат «найди пункты заказа, исполненные неверно
|
||
или неполно, и правки СВЕРХ заказа»; (б) **холодный потребитель** — получает ТОЛЬКО новую спеку
|
||
(без ревью, без компаньона, без диффа), мандат «ты пишешь клиента с нуля: назови всё непонятное,
|
||
противоречивое и места, где схема указывает нарушить собственную прозу». Проверяемый артефакт:
|
||
секция отчёта — таблица их находок, КАЖДАЯ с диспозицией (исправлено / отклонено-с-причиной);
|
||
ноль находок у обоих = повод не верить прогону, а не праздновать.
|
||
6. Несогласие с ратифицированным решением — СТОП по этому пункту и пинг через владельца с аргументом;
|
||
у тебя есть право сказать «этого делать не надо» — но не право молча сделать иначе.
|
||
|
||
## 7. Эхо-протокол старта
|
||
|
||
Первый деливерабл — ≤10 строк: «что я понял: скоуп / инварианты / чего НЕ делаю». Расхождение чинится
|
||
на минуте пять, не на приёмке.
|
||
|
||
## 8. Сдача
|
||
|
||
Отчёт `docs/archive/reports/CONTRACT_BATCH_0.3.0_REPORT.md`: записка-план §6.2 с диспозициями ·
|
||
таблица находок адверсариального селф-ревью §6.5 с диспозициями · спорные формы с вариантами и твоим
|
||
выбором · **obstacle reporting — что НЕ удалось/не сделано и почему (обязательная секция)** ·
|
||
дифф-сводка «было → стало» по операциям. Без саги. Дерево оставить
|
||
незакоммиченным. Вопросы и конфликты промта с кодом/доками — пинг оркестратору через владельца,
|
||
НЕ интерпретация.
|
||
|
||
---
|
||
|
||
## ДОФИКС-РАУНД (заказ приёмки D39.142, 16.08; аддендум — доезжает релеем владельца, подтверди эхом)
|
||
|
||
Батч ПРИНЯТ и заленден (панель: слепая сверка — потерь 0/искажений 0; аудит отчёта — 25+ клеймов сошлись). Дофикс — находки ХОЛОДНОГО ПОТРЕБИТЕЛЯ (линза, которой у твоего селф-ревью не было: только финальная спека + tsc-проба) и хвосты аудита. Зона и гейты прежние. Ратификации приёмки, которые НЕ двигать: прогонный поток снят · `Note.code` вместо `message` · `content_refused` остаётся · единый `page_size_default` принят. По каждому ФБ — диспозиция в дополнении к отчёту.
|
||
|
||
**ФБ-1 (HIGH).** Wire-форма SSE-кадра неоднозначна: `EventEnvelope{event,id,data}` как объект против `event:`/`id:` как SSE-фрейминг — два верных чтения (улика: A3 панели). Записать однозначно.
|
||
**ФБ-2 (HIGH).** Книга в покое без единого кадра истории: `hello` не имеет id последнего кадра → клиент без `Last-Event-ID` → «всегда новый поток» → hello→end→close→reconnect навечно (A4). Определить поведение.
|
||
**ФБ-3 (HIGH).** «`note` не теряется» не переживает reconnect: буфер не гарантирован, resync не шлётся (A5). Записать обязанность клиента: дельта-чтение `/notes?after_version=` после КАЖДОГО переподключения (механизм уже есть — назвать долг).
|
||
**ФБ-4 (HIGH).** `Revision` противоречит себе: «каждое книжное чтение несёт одно число» vs «рваное чтение = ревизия СТАРЕЙШЕЙ страницы» vs водяной знак «ревизия только что полученного конверта» (C1/A6); `BookDetail.revision` vs `book.revision` — равенство не заявлено (C2). Свести в одну модель; правило водяного знака при много-страничной дельте — явно.
|
||
**ФБ-5 (MED).** `EventEnd`/`EventResyncRequired` — пустые `allOf`-члены дают необитаемые типы (`Record<string,never>`, B1); дать им явные `properties` (хотя бы `{}` честной формой) и подсказку маппинга event→payload машинно-дружелюбнее (B2 — можно прозой-таблицей + непересекающимися формами).
|
||
**ФБ-6 (MED).** Спека приказывает предлагать «новый прогон» как лечение стопа по потолку, но resumable-статусы не перечислены, а `paused_reason:null` описан «нейтрально, continuable» (A1/A2). БЕЗ нового значения enum (ратификацию D39.132 п.2а не двигать): записать — «новый прогон с бОльшим потолком» легален для ЛЮБОГО paused; перечислить, что делает `resume` по каждому останавливающему статусу.
|
||
**ФБ-7 (MED).** Правило «ответ НЕ `problem+json`» (прокси 502, HTML, обрыв) — потерянный пункт заказа (Б-1 рек. п.4): клиенту нельзя показывать серверный текст и нечем взять код — записать нейтральный fallback (E1).
|
||
**ФБ-8 (MED, пачка одной строкой каждая).** merge-patch `title:null`→400 против RFC 7386 — объяснить в описании (C6) · `X-TM-Client` required против освобождения bearer — записать разводку в самом параметре (C8) · список «Refusals:» пометить неисчерпывающим (C5) · правило резолюции `Location` (A7) · тождество `Idempotency-Key` на multipart + путь ретрая 408-под-тем-же-ключом (A9) · `min_chapters` при `max=0` (A11) · приоритет пяти носителей «нет кредита» (A12) · «carried forward marked as unverified» — носителя на проводе нет: снять или дать (A13) · 409 у `createExport` объяснить (A14) · код для неизвестного `term_id` в decisions (A15).
|
||
**ФБ-9 (LOW).** `parser_unavailable` — имя компонента в enum, переименовать по эффекту (L1) · внутренние ссылки `research/28 §…`/«companion К-6» уезжают в исходники клиента — вычистить из описаний, оставить в компаньоне (L3).
|
||
**ФБ-10 (отчёт).** Пере-ран чисел ПОСЛЕ последней правки: строки файла (2315, не 2290) · `ErrorCode` 16, не 15 · генератор 2608 · «26 находок» → фактические 57/67 · «все девять» §5.3 → 11 строк · «8 из 20 не отвечает» → 12 из 20 · якорь `mining.go:201` → :81/:243 · «строка 21» → 18; скрипт мерки прозы/формы приложить в отчёт или снять вывод о доле; дописать строки записки-плана Б-23/К-10/В-6; ярлык §5.5 «исполнено иначе» → «отступление, аргумент»; README §6а — фраза «апологии перенесены» → «ужаты на месте».
|