textmachine/docs/archive/prompts/CONTRACT_BATCH_SESSION_PROMPT_2026-08-16.md

29 KiB
Raw Blame History

АРХИВ — ОТРАБОТАН ЦЕЛИКОМ (батч + дофикс-раунд ФБ-1..10). Исполнен спек-сессией 16.08.2026, принят приёмками D39.142 (панель трёх линз) и D39.143 (дофикс): канон 0.3.0 + компаньон в каноне, отчёт — docs/archive/reports/CONTRACT_BATCH_0.3.0_REPORT.md. Инструкции отсюда не исполнять.

Промт: сессия БАТЧ 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 под давлением строек, и целостного ревью не имел. 1516.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_bankstop_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б шаги 34 — В БАТЧ (заказ ПОВЕРХ §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а — фраза «апологии перенесены» → «ужаты на месте».