Write the two session prompts to canon: the engine takes the wire batch that gender needs, the platform closes the cycle with a grant as its ceiling

This commit is contained in:
heaven 2026-09-04 10:39:17 +03:00
parent 0917cff003
commit 9a45b121b3
2 changed files with 451 additions and 0 deletions

View file

@ -0,0 +1,254 @@
# Промт сессии: БЭКЕНД — вайр-батч «род, экран цели, заголовки инъекций»
> **Роль:** бэкенд. **Зона записи:** `backend/` и своя секция «Бэкенд» в `docs/PROGRESS.md` — это
> единственное разрешённое каноном исключение из «`docs/` — зона оркестратора». Чужие зоны
> (`platform/`, `frontend/`, `eval/`) читаешь, не правишь. **Не коммитишь** и не трогаешь индекс и
> историю — полный список запретов и причина: `CLAUDE.md`, «Git-координация мультисессий».
> Норматив стиля — `docs/architecture/12-go-style-notes.md`.
## Какая проблема и что изменит твой результат
Движок обещает род персонажей на проводе — директива ратифицирована `D39.21`, механизм доставки
построен и работает. **Данных ему не даёт никто:** промпт терминолога возвращает ровно три поля
(термин · перевод · уверенность), поля рода в ответе нет, а майнер берёт `gender` только из ручного
сида. Значит на любой книге, которую никто не сидировал руками, ось рода мертва **по построению**, и
«плывущий род» в тексте — не дефект рендера, а отсутствие входа. Рядом лежат ещё три правки того же
провода, каждая ратифицирована и ни одна не построена.
После пака: род производится авто-путём · полный связный перевод на чужой язык перестаёт проходить
как здоровый · редактор получает единый закон-блок вместо двухсекционки · банковый контур включён в
боевой конфиг · жанр ушёл из промптов. И всё это одним пере-захватом голдена, а не пятью.
## Карта чтения — пять позиций, дальше только по их ссылкам
1. `backend/README.md` — устройство движка · `docs/architecture/12-go-style-notes.md` — норматив.
2. `docs/PROGRESS.md`: CURRENT-STATE и строки бэклога **210 · 46 · 113 · 134 · 140 · 184 · 197 · 198 · 204**
(греп по номеру в таблице).
3. `docs/NEXT_PACKS_PLAN.md` §1 — состав этого пака и что намеренно НЕ берётся. Читать целиком: там
разобрано, почему пункты собраны вместе и какие две строки батч задевает сам.
4. Журнал решений, номера грепом (`grep -n '^## D39.NNN'`): **D39.21** (род должен доезжать) ·
**D39.93** (форма экрана цели) · **D39.104** (банк на проводе — закон) · **D39.105/D39.108**
(доктрина заголовков и павший гейт) · **D39.147** п.2в (140 — стройка, не развилка) ·
**D39.138** п.2в (жанр выкидываем) · **D39.64** П0 (безусловный фолд `EmbeddedVersion`).
5. `docs/architecture/15-money-path.md` — денежный путь; читать §2 про суб-бюджеты банк-ролей.
⚠ Ратифицированное вложено в тело этого промта; **код-факты добываешь САМ** — указатели ниже
отправные точки, код первичен. Числа даны с командой получения: пере-ранишь — сойдётся; не сошлось —
это находка, неси пингом, а не подгоняй работу под текст.
## Состав — шесть пунктов, в этом порядке
### 1. Строка 210 — РОД НЕ ПРОИЗВОДИТСЯ ВОВСЕ (цель №1 бэклога)
Механизм доставки построен: `backend/internal/membank/memory.go` (греп `genderConstraintNote`) кладёт
род в черновую инъекцию. Входа нет:
```
grep -n -i gender backend/prompts/zh-ru/terminologist.md # ноль полей рода
grep -n 'meta.gender' backend/internal/miner/miner_emit.go # род только из сида
```
**Делай РОВНО так:** род начинает производиться авто-путём, и это доказывается СКВОЗНЫМ прогоном
«терминолог произвёл → отрендерилось в инъекции», а не юнит-тестом на конструкцию.
**Решаешь сам и аргументируешь — развилка НЕ выбрана за тебя:** поле рода в ответе терминолога ·
отдельный проход · признать сид-только и закрыть строку отказом. Выбор объявляешь с ценой (байты
батча терминолога двигают его `RequestHash`).
**ВТОРОЙ ЗАМОК, без которого первый пункт не даёт НИЧЕГО.** Род рендерится только у строк со
статусом `Confirmed`, а произведённое терминологом приезжает auto-строкой. Снятие замка следует из
доктрины `D39.104` (банк на проводе — закон для всех строк независимо от статуса), **но оно обязано
быть СКАЗАНО и вынесено пингом на ратификацию оркестратору, а не выведено тобой молча.** Пока замок
не снят, поле у терминолога ничего не меняет на проводе — так и напиши в отчёте, если решишь не
снимать.
Вес: следующий платный замер полигона (15 глав с характер-листами) без этого пункта
**ложно-отрицателен по построению** — «полей пола в банке нет вовсе».
### 2. Строка 113 → потом 46 — экран целевого языка. ПОРЯДОК ОБЯЗАТЕЛЕН
**Сначала 113, и это не формальность.** Числа, на которых стоит вся строка 46 («18 из 20 · 0 ложных
на 1055 · запас 13×»), получены ВРЕМЕННЫМ тестом, который сессия удалила; воспроизвести их сегодня
нечем. **Делай РОВНО так:** корпус-фикстура в репо (~20 off-target + ~40 здоровых, с движковой
предобработкой) плюс регресс-тест на реальный запас.
**СТОП и пинг**, если фикстура не воспроизводит 18/20 при нуле ложных или запас меньше 3×: тогда
предпосылка строки 46 пала, и стройка по ней — трата.
Затем сам экран. Дизайн ЗАМОРОЖЕН и ратифицирован: closed-set причин (`D39.92` п.1) и изолированный
модуль с именованными причинами (`D39.93`).
⚠ **Три вещи, которых нет в спеке, и они меняют работу:**
- `EFFORT_HANDLE §5.4` шаг 6 велит переиспользовать `FlagCJKArtifact` — **это СНЯТО `D39.93` п.2**
(именованный флаг + явный вход в `escalatable()`). Нота бьёт спеку.
- Вторая половина дыры — `detectLatinInsertion` без `TargetScriptNonLatin()`
(`backend/internal/checks/sanitizer.go`); реестр §Б-46 велит «чинить тем же диффом».
- Новый именованный флаг — **16-я причина**, а карта платформы рукописная на 15
(`grep -c '":' platform/internal/ingest/notes.go` → 15) ⇒ платформа отдаст `unspecified` с ERROR.
Носитель — строка **204** / ряд `PD-246`. **Пинг платформе обязателен** (в отчёт, чужую зону не правишь).
**Решаешь сам и аргументируешь:** состав и форма корпус-фикстуры 113 · имя и текст новой причины
флага · где именно стоит вход в `escalatable()`.
### 3. Строка 134 — инжект-заголовки под доктрину D39.105
Гейт ПАЛ (`D39.108`): текст = отправленная строка пробы 18 **БЕЗ** оговорки области (оговорка
опровергнута §A.4 — НЕ вносить).
**Делай РОВНО так — ТЕКСТ заголовка не меняется вовсе.** Меняется рендер: секция
`editor_unverified_header` не рендерится (двухсекционка → один блок) · маркер ⟨проверить⟩ не
рендерится · то же у заголовка транслятора. Статусы строк и подписная таблица **не трогаются**
(`D39.104` п.1).
**МИНА, и выбор твой, но объявленный.** Правка `backend/internal/lang/data/injection.txt` двигает
`EmbeddedVersion` БЕЗУСЛОВНЫМ фолдом (`D39.64` П0) и `cutTag` манифеста ⇒ пере-чеканку ВСЕХ `unit.id`
⇒ платформа при смене `manifest_key` СНОСИТ `unit_resolutions` книги
(`platform/internal/pgstore/readmodel.go`, греп `recut :=` и `delete from unit_resolutions`) — это
строка **198**, и её гейт «до первого реального пользователя». Рычаг у тебя есть: **снять рендер в
Go, данные не трогать** — тогда двигается только `RequestHash`, мёртвые строки данных допустимы до
следующего касания. **Решаешь сам и аргументируешь, но выбор ОБЪЯВЛЯЕШЬ явно** и, если тронул
данные, пишешь об этом первой строкой отчёта.
### 4. Строка 140 — банковый контур в shipping-c1: СТРОЙКА, не развилка
⚠ Текст строки называет это «СТОП-решением» — он СТАРШЕ ратификации. `D39.147` п.2(в) уточнением
владельца 17.08: внесение «ратифицированно живёт в wire-батче 182 — одним касанием перед первым
платным прогоном; **отдельной развилки нет**». Журнал бьёт бэклог.
```
grep -n 'terminology\|banknote\|classify' backend/configs/pipeline-c1.yaml # 0 — не построено
```
**Делай РОВНО так:** банковый контур (банкнота + терминолог + классификатор) включается в c1.
**Суб-бюджеты банк-ролей калибровать ×4.47**`15-money-path.md` §2 прямо говорит, что сегодня они
«режут ОПЛАЧЕННУЮ работу по протухшей калибровке»: на холодном прогоне `classify_budget_usd` 0.02
оборвал классификатор дважды. **Решаешь сам:** конкретные числа после умножения и надо ли поднимать
их сверх множителя.
**Цена НАЗЫВАЕТСЯ в отчёте** (двигает промпт черновика ⇒ `RequestHash` книг на c1), но не спрашивается.
### 5. Строка 184(а) — снять `{{genre}}` из промптов пары
Слово владельца 16.08, `D39.138` п.2в дословно: «Просто выкидываем». Состав числом не держим:
```
grep -rln '{{genre}}' backend/prompts/ # сегодня шесть файлов
```
**Делай РОВНО так:** снять из промптов И поле из канона брифа (двигает `BriefHash`, то есть КАЖДЫЙ
`RequestHash` — потому и внесено в это окно, а не потом). Влияние жанра на качество не измерено и уже
не будет.
**Свободы здесь нет намеренно:** пункт предписан целиком, решать в нём нечего. Упрёшься во что-то,
чего промт не предусмотрел, — пинг, а не своё усмотрение.
### 6. ДОФИКС чужого пака + ФЧ-7 — одним пунктом
**Почему это здесь.** По канону дофикс адресуется той же сессии, что делала пак. Её больше нет
(проверено `ListAgents` 04.09), поэтому остаток едет сюда. **Это чужая недоделка, а не новый заказ**
и в отчёте её надо называть отдельно от своей работы.
Остаток приёмки (`D39.187` п.4):
- **Развилка операторской строки прибита с ОДНОЙ стороны.** `VolumeStop.String()` развёл предложение
на «книга кончилась» и «грант придержал», но две посадки в новый код переживают весь пакет: под ними
в смешанном состоянии (`Carried=3, Left()=1`) печатается «reached the END of the book … Still in the
book: 1 unit(s) NEVER delivered» — то же самопротиворечие в зеркальной форме. Лог-развилка при этом
прибита с обеих сторон, то есть образец рядом.
- **Граница `bound()` не прибита:** `Carried > 0``Carried > 1` переживает пакет, и прогон с ОДНИМ
перенесённым юнитом на конце книги не отдаёт отчёт вовсе — тихий лимит, анти-паттерн `D39.165` §1б.
- **Три числа отчёта протухли снова** — сняты до последней правки каталога.
**Делай РОВНО так:** каждая из двух посадок получает тест, который от неё краснеет, И запись в
`backend/cmd/tmmutate/mutations.json`.
**ФЧ-7 фикс-листа (строка 197) — паника поверх ПОЙМАННОГО потолка.** Денежный шов, не проверялся
никем. **Форма — проверка ИСПОЛНЕНИЕМ, а не стройка: воспроизвести, и чинить ТОЛЬКО если
воспроизводится.** Тем же касанием пере-скоупить строку 197: ФЧ-1/4/5 закрыты, ФЧ-6 по коду выглядит
закрытым, **ФЧ-2/3/8 остаются НЕ ПРОВЕРЕННЫМИ и обязаны быть названы непроверенными**, а не тихо
опущены.
## Границы — что НЕ делать
- ⛔ **Не двигать:** схему хранилища движка · `manifestVersion` · `StreamVersion` · версию контракта.
Понадобилось — **стоп и пинг**, не «сделаю аккуратно».
- ⛔ **Не заводить новый embed-файл** (реестр §Б-46: это перекупка всех пар).
- ⛔ **Не переиспользовать `FlagCJKArtifact`** (снято `D39.93` п.2).
- ⛔ **Не менять семантику переноса слота** — владелец 03.09 отложил её словом «подумаем».
- ⛔ **Не брать строки 131 · 105(а) · 14 · 119 · 124 · 115 · 160 · 161 · 142** — они жильцы того же
окна или отдельных паков, и их очередь решает оркестратор, не ты.
- ⛔ Не трогать чужие зоны, `.env`, соседний worktree `/home/ubuntu/projects/textmachine`.
- ⚠ **Общность движка:** Go-логика не ветвится по паре и книге. Ревью-вопрос по умолчанию —
«заработает ли пара, которой в репо ещё НЕТ, без правки Go?». Пара-данные — `internal/lang` и
`configs/langpacks/`, книго-каноны — сид и бриф.
## Свобода и её разметка
**«Делай РОВНО так» (отступление = пинг):** порядок 113 → 46 · СТОП по фикстуре, если запас < 3× ·
текст заголовка не меняется · статусы и подписная таблица не трогаются · нота бьёт спеку у
`FlagCJKArtifact` · суб-бюджеты ×4.47 · жанр снимается и из промптов, и из канона брифа · обе посадки
дофикса краснеют · ФЧ-7 — проверка, а не стройка · все запреты раздела «Границы».
**«Решаешь сам и аргументируешь» — и только это:** развилка производства рода · снимать ли второй
замок (со СКАЗАННЫМ пингом) · трогать ли данные в 134 (с объявлением) · конкретные числа суб-бюджетов ·
форма фикстуры 113 · форма тестов и записей каталога · порядок работ внутри пака.
⚠ Катч-олла «всё остальное — сам» нет: чего нет ни в одном списке — это пинг, а не твоё усмотрение.
## Мандат самопроверки — исполнением, не перечитыванием
`make battery`**предусловие, а не отчёт.** Обязательны все четыре, каждое с ПРЕДЪЯВЛЯЕМЫМ артефактом:
1. **Дифф `^func Test` исполнением, а не памятью:** `grep -rn '^func Test' backend --include=*_test.go | wc -l`
до и после, плюс пофамильный дифф. **Удалённых имён должно быть 0**; не 0 — назвать каждое.
2. **Голден пере-захватывается с МАСКИРОВАННЫМ диффом:** в нём меняются только названные версионные
оси и **ровно две строки диспозиций**. ⛔ Изменилась хоть одна здоровая строка — **СТОП и
эскалация**, а не пере-захват.
3. **Собственные адверсариальные посадки ВНЕ шести пунктов** — механизм `cmd/tmmutate` на копии дерева
(`cp -a backend /tmp/<имя>/backend`). Артефакт: красный вывод на каждую посадку и **отдельный список
тех, что батарея ПЕРЕЖИЛА** — это и есть находки.
4. **Отдельный проход по СВОЕЙ ГОТОВОЙ работе свежим контекстом.** Субагенты разрешены явно; модель
задавай ИМЕНЕМ и знай, сколько их у тебя работает.
**«Прошёл, находок нет» отчётом НЕ является:** ноль обосновывается тем, ЧТО искалось и какими
командами.
**Отчёт о движении провода обязателен:** двинулся ли `cutTag` — предъяви `tmctl manifest` до и после
на стендовой книге и дифф `unit.id`.
### Предметные оси ревью — уязвимы ИМЕННО в этом паке
1. **Ложные срабатывания экрана цели на ЗДОРОВОМ русском с латинскими термами.** Положительный
контроль — фикстура 113: 18/20 при нуле ложных и запас ≥3×. Без него экран не сдан.
2. **Род: все существующие тесты конструируют его руками.** Нужен сквозной контроль «терминолог
произвёл → отрендерилось» И отрицательный «сид побеждает произведённое».
3. **134: маркер снят, а пост-чек жив.** Проверь, что снятие маркера не сломало обработку `Ambiguous`.
4. **140: бюджеты режут оплаченную работу.** После ×4.47 предъяви, что классификатор на стендовой
книге не обрывается.
⚠ Запрет подгонки тестов и гейтов — `CLAUDE.md` (`D39.183`). Край, который тебе понадобится: **этот
промт ЗАКАЗЫВАЕТ смену поведения в пунктах 15**, и протухший под неё тест правится как обслуживание —
но правка ОБЪЯВЛЯЕТСЯ: что изменилось, какой тест это описывал, куда уехала гарантия.
## Отчёт
**Записка-план ДО работы** — эхо-протокол старта, ≤10 строк «скоуп · инварианты · что НЕ делаю», в
секцию «Бэкенд» `docs/PROGRESS.md`. Первым действием, до кода.
**Комплектность против заказа — механически:** пройди по шести пунктам состава и по таблице разметки и
отчитайся **ПО КАЖДОМУ**. Эта тема проваливалась несколько раз на том, что исполнялся первый пункт, а
нумерованный остаток бросался.
**«Заявление = команда»:** каждое число и каждая категорика — с командой получения, которая это число
реально печатает. Приёмка пере-ранит твои команды; команда, печатающая «ok» вместо числа, считается
отсутствующей. Гейты и счёты гнать **ПОСЛЕДНИМ действием**, после того как текст дописан.
**Обязательная секция «Что НЕ удалось и что НЕ проверено».** Исходов ТРИ, и «не проверено» ≠
«опровергнуто» ≠ «сделано»; третий законен и ожидаем. Сюда обязательно попадают ФЧ-2/3/8 и решение по
второму замку рода, если ты его не снял.
**Конфликт промта с кодом или доками — ПИНГ через владельца, не интерпретация.** И у тебя есть **право
сказать «этого делать не надо»** с аргументом, включая пункты состава и границы: сессия, приносящая
развилку вместо тихой девиации, делает правильно. Промт писан по коду на HEAD своей смены; код
первичен, и если ты видишь другое — это находка, а не твоя ошибка.
## Прямой канал
Механизм целиком — `CLAUDE.md`, «Связь между сессиями»: свой блок в `/tmp/textmachine-channel`, сверка
с `ListAgents` перед отправкой, канала нет — нормальный случай, сессии подряд не опрашивать. Что
добавляет этот пак: **эхо-записку отправь ПЕРВЫМ действием по адресу оркестратора** — это и есть
проверка канала.

View file

@ -0,0 +1,197 @@
# Промт сессии: ПЛАТФОРМА — «закрыть цикл: сквозной прогон и дверь выдачи»
> **Роль:** платформа. **Зона записи:** `platform/`. Чужие зоны читаешь, не правишь; итоги и пинги —
> ЗОННЫЙ журнал `platform/docs/platform-PROGRESS.md``docs/PROGRESS.md` платформа НЕ пишет).
> **Не коммитишь** и не трогаешь индекс и историю — запреты и причина: `CLAUDE.md`,
> «Git-координация мультисессий».
> **Обязателен к ссылке:** `platform/docs/ENGINEERING_STANDARDS.md`; отступление — пинг, не
> самовольство. Направление зоны — `platform/docs/PLATFORM_DIRECTION.md`.
## Какая проблема и что изменит твой результат
Цикл не замкнут: движок собирает книгу файлом с 30.08 (EPUB 3 + чистый txt), холодный прогон предъявил
это живьём — собранный EPUB настоящего перевода прошёл `epubcheck` 0/0/0/0. **Пользователь этот файл
получить не может:** канон обещает `createExport`/`getExport`, платформа их не монтирует. Долг числится
с P8, и ни один пак после P7 его не взял.
Вторая половина той же проблемы: **живой перевод книги насквозь через API не гонялся НИ РАЗУ.** Всё
после «прогон стартовал и остановился» покрыто батареей против живого Postgres, но с движком-заглушкой.
Настоящий манифест, сайдкар банка и карта причин флагов будут ПЕРВЫМИ данными, форму которых платформа
не сочинила сама.
После пака: книга доходит до пользователя файлом, и это предъявлено живым прогоном на настоящем
движке, а не фикстурой.
## Карта чтения — пять позиций
1. `platform/README.md` — устройство зоны · `platform/docs/ENGINEERING_STANDARDS.md` (обязателен).
2. `platform/docs/platform-PROGRESS.md` — зонный журнал: пинги оркестратора и отчёты паков P12/P13.
3. `docs/NEXT_PACKS_PLAN.md` §2 — состав этого пака, что намеренно не берётся, и разбор механизма
потолка. Читать целиком.
4. `docs/architecture/14-api-contract/` — канон; **зеркало фронта НЕ норматив**. Ряды регистра по
номеру: `PD-424` · `PD-418` · `PD-438` · `PD-217` · `PD-246`.
5. Журнал решений грепом: **D39.189** и **эррата 04.09-а к нему** (механизм потолка) · **D39.176** п.3
(возобновление явным действием) · **D39.178** (дверь всегда строит файл) · **D39.175** п.2
(`BuildReport` — оператору) · **D39.85** (закон шва: импорта чужого модуля нет).
⚠ Ратифицированное вложено сюда; код-факты добываешь САМ. Числа — с командой получения.
## ⚠ ПРЕДУСЛОВИЕ: четыре условия хоста + ключи
Условий батареи ЧЕТЫРЕ, и цель `make conditions` печатает их состояние сама — **начни с неё**, а не с
догадки. На этом хосте: `~/go/bin` существует и держит `sqlc` (без `export PATH=$HOME/go/bin:$PATH`
`make check` не стартует вовсе), сокет Postgres — `/tmp/.s.PGSQL.55433`, DSN — в
`platform/docs/STACK_DECISIONS.md`.
**Ключи провайдера для платного прогона.** Конвенционного `.env` нет ни у одной книги корпуса.
Платформе нужен `TM_PLATFORM_ENGINE_KEYS_PATH` **абсолютным путём** на уже заполненный файл
(`platform/internal/config/config.go`, греп `must be an absolute path`). ⛔ **Сам файл НЕ читать**
гардрейл `CLAUDE.md`. Проверять ПРОГОНОМ, а не чтением.
## Состав — четыре пункта
### 1. Строка 202 — живой сквозной прогон книги через API. ПЛАТНЫЙ
**Санкция владельца ДАНА** (`D39.189`, 03.09: «разрешаю платные прогоны с ключами для тестов»).
⛔ **ПОТОЛОК — ЭТО ГРАНТ, А НЕ ФЛАГ. Читай внимательно, здесь легко сделать хак.**
На пути через API `--ceiling-usd` руками не ставит никто: платформа выводит число сама —
`bookCap = committed + increment` (`internal/runs/spawn.go`, греп `func (m meter) bookCap`), а
`increment` считается по ставке `DefaultPerChapter = 30_000` ($0.03,
`internal/pricing/pricing.go`), которая занижена ×4.47 (`D39.179` п.1).
**Делай РОВНО так:** потолок пака = **грант тест-аккаунту ровно на $1.5**
(`tmplatformctl grant --user <id> --usd 1.5`) — холд делает перерасход невозможным по построению.
**`TM_PLATFORM_USD_PER_CHAPTER` НЕ КРУТИТЬ** — это подгонка окружения под тест, запрещённая
каноном. Ставка занижена, и это известный ряд, а не твоя задача.
**Путь до завершённой книги идёт цепочкой «покупка → пауза по потолку → пополнение → новый прогон»,
и это НЕ обход, а продуктовый путь** (`D39.176` п.3; `resume` прогона, остановленного потолком,
отбивается — `internal/runs/runs.go`, греп `ErrCeilingReached`, и `PD-217` называет лечение: «новый
прогон»). Тремя явными сценариями закрывается строка **216**: подпись банка · halt на потолке ·
резюм после пополнения.
**Стартовать в ДОЛИНУ:** у DeepSeek пиковые окна 0104 и 0610 UTC дают ×2 (строка 172а).
Операционное правило дешевле любой правки Go.
**Что сверить — то, что до сих пор не сверялось ни разу:** на шов реально вышло ОДНО значение
`flag_reason` из пятнадцати, а манифест против `internal/ingest/manifest.go` не сверялся вовсе.
⚠ Четырнадцать причин флагов прогоном не вызвать — **так и напиши**, не выдавай непроверенное за
проверенное.
**Решаешь сам:** книга и её объём, порядок сценариев, форма фиксации артефактов.
### 2. Дверь выдачи — `createExport` / `getExport`
Не построено: `grep -rn 'createExport\|getExport' platform/internal/ --include=*.go` → 0 (контроль:
`listBankTerms` → есть). Смонтировано 15 маршрутов при 20 `operationId` канона.
**Делай РОВНО так — слово владельца 30.08:** дверь **ВСЕГДА строит файл**. Отказ пользователю не
отдаётся; неполная книга уходит **с пометкой**, то есть дверь зовёт `tmctl build --partial`
(`D39.178`). Отказ по умолчанию остаётся операторской ручкой CLI. `BuildReport` — оператору в лог, не
читателю (`D39.175` п.2). Денег на проводе нет (`D39.84`).
⚠ **Четыре факта кода, каждый меняет работу:**
- `ExportFormats` захардкожен пустым (`cmd/tmplatformd/runner.go`, греп `ExportFormats`), а форматы
движок публикует только Go-переменной `bookfile.Formats` — **импорт чужого модуля запрещён**
(`D39.85`). Значит нужен КАНАЛ: переменная деплоя либо движок публикует данными. Это вопрос закона
входной двери — **решаешь сам и аргументируешь, но если ответ требует правки движка — пинг, не правка**.
- Декодера `tm-build-v1` / `BuildReport` в платформе НЕТ (ноль хитов при живых `DecodeExport`, `DecodeBank`).
- `build` открывает стор read-only без flock ⇒ канонное «книгу можно экспортировать во время
перевода» исполнимо.
- `ExitBookIncomplete = 16` у платформы отсутствует (`internal/ingest/exit.go`).
**Минор канона — состав назвать в отчёте, правку согласовать:** `Export.failure_code` становится enum
с первым построенным форматом (`contract-10` строки 243, условие наступило) · механизм подписанной
ссылки и её TTL плюс GC файлов · строка **241** (канон противоречит себе на дочитанной книге).
⚠ Прецедент есть: миноры 0.6.0/0.7.0/0.9.0 приезжали с паками зоны через ратификацию оркестратора.
**Делай РОВНО так:** канон правится ТОЛЬКО через ратификацию, не своей рукой.
### 3. `PD-424` — терминальная ручка для живого прогона с заблокированной расплатой (`major`)
Половина «невидим» вылечена P12; половина «ручки нет» стоит. `run abandon` ветвится по
`runs.finished_at` (`internal/pgstore/runs.go`, греп `AbandonRun`) и на живом прогоне уходит в живую
ветку, а `AbandonRun` отказывает над попыткой, ещё называющей юнит.
⚠ Это **НОВАЯ разрушительная операторская поверхность над деньгами**. **Делай РОВНО так:** её дизайн
называется явно и целиком — кто вправе звать · чем доказывается отсутствие процесса · что происходит,
если процесс вернётся (двойная расплата). **Решаешь сам:** форма ручки и глубина.
⚠ Дописать `PD-418`: та же ветвь по `finished_at`, долговечное лечение — «ветвить по НАЛИЧИЮ
осиротевшей попытки». Либо входит в тот же дизайн, либо **явно объявляется вне его**.
### 4. Дофикс чужого пака + три райдера
**Почему это здесь.** По канону дофикс шёл бы той же сессии, но её больше нет (`ListAgents` 04.09).
**Это чужая недоделка, а не новый заказ** — в отчёте называть отдельно от своей работы.
- **Записка о предусловии хоста** (`platform-PROGRESS.md`) различает хосты **именем машины**, а имя у
этого хоста то же самое (`DESKTOP-IN1MCEA`) при противоположных условиях: `~/go/bin` существует и
держит `sqlc`, `make tools-check` на дефолтном PATH падает, сокет только 55433. Различает
пользователь и `$HOME`, а не хост. **Делай РОВНО так:** ключевать записку пользователем/`$HOME`.
- **Райдер `246`:** `internal/ingest/exit.go` обещает «nothing this process would have written was
written», а движок это прямо отрицает. Остаток — комментарий плюс константа 16, которую дверь и так
добавит. ⚠ Прежняя формулировка «разрушительно по полосе» ПЕРЕОЦЕНЕНА: интейк удаляет загрузку
только на классе 11.
- **Райдер `234`:** `internal/runs/bank.go` объясняет отказ снятой посылкой («status projects the
STORED memory…»), опровергнутой `D39.170`. Одна правка комментария.
- **Райдер `PD-438`-остаток:** лечение в дереве, но припаркованная попытка не видна ни в `runs`, ни
гейджем, ни колонкой. **Решаешь сам:** закрывать сейчас или назвать отложенным — но НАЗВАТЬ обязан.
## Границы — что НЕ делать
- ⛔ Не трогать форму манифеста · схему хранилища движка · `docs/scripts/counts.py`.
- ⛔ Не править канон своей рукой — только через ратификацию.
- ⛔ Не крутить `TM_PLATFORM_USD_PER_CHAPTER` и не обходить холд.
- ⛔ Не решать `PD-439` и не переносить ряды между секциями регистра — статус есть акт лендинга.
- ⛔ Не брать `PD-410` · `PD-412`/`413` · `PD-386``392`: первый архитектурный и крупнее двери,
остальные — отдельный пак наблюдаемости.
- ⛔ Не трогать бэкенд-половину, `.env`, соседний worktree.
## Свобода и её разметка
**«Делай РОВНО так»:** грант как потолок и запрет крутить ставку · цепочка покупка→пауза→пополнение→
новый прогон · дверь всегда строит, `--partial`, `BuildReport` оператору · канон только через
ратификацию · дизайн `PD-424` назван целиком · записка ключуется пользователем · все запреты границ.
**«Решаешь сам и аргументируешь»:** книга и объём прогона · порядок сценариев · канал форматов
(с пингом, если упирается в движок) · форма ручки `PD-424` · судьба `PD-438`-остатка · форма
подписанной ссылки и GC.
⚠ Чего нет ни в одном списке — пинг, а не усмотрение.
## Мандат самопроверки — исполнением
1. **Живая проба каждого пункта поимённо**, с пометкой, нужен ли DSN.
2. **Собственные адверсариальные посадки ВНЕ списка** — на копии дерева (`cp -a platform /tmp/<имя>/`),
каждая с командой и выходом; пережившие батарею — находки, и они объявляются.
3. **Отдельный проход по своей готовой работе** свежим контекстом. Субагенты разрешены явно, модель
ИМЕНЕМ, число знай.
4. ⚠ «Прошла, находок нет» отчётом не является.
### Предметные оси ревью — под предмет этого пака
1. **Идемпотентность третьего создающего вызова** (`internal/pgstore/idempotency.go`, греп
`beginIdempotent`): дверь — новая создающая поверхность.
2. **Жизнь и GC выданных файлов**: ссылка чеканится на ответ и владельца и истекает — что после.
3. **Экспорт ВО ВРЕМЯ живого прогона** (read-only без flock это разрешает — проверь, что не врёт).
4. **`PD-424`: возврат процесса после «признали отсутствующим»** — двойная расплата.
5. **Положительный контроль, без которого дверь не сдана:** `epubcheck` на ВЫДАННОМ файле и скачивание
по чеканенной ссылке ВТОРЫМ клиентом.
⚠ Запрет подгонки тестов — `CLAUDE.md` (`D39.183`); заказанная смена поведения объявляется в отчёте.
## Отчёт
**Записка-план ДО работы** (скоуп · инварианты · что НЕ делаю, ≤10 строк) — в
`platform/docs/platform-PROGRESS.md`, и тем же текстом первым действием по каналу.
**Пройди по четырём пунктам состава и таблице разметки и отчитайся ПО КАЖДОМУ.**
**Каждое число — с командой получения**; приёмка пере-ранит. Гейты гнать ПОСЛЕДНИМ действием.
**Обязательная секция «Что НЕ удалось и что НЕ проверено»** — третий исход законен; сюда обязательно
попадают четырнадцать причин флагов, которые прогоном не вызвать.
**Конфликт с кодом — пинг, не интерпретация.** Право сказать «этого делать не надо» с аргументом у
тебя есть, включая состав и границы.
## Прямой канал
Механизм — `CLAUDE.md`, «Связь между сессиями»: свой блок в `/tmp/textmachine-channel`, сверка с
`ListAgents`, канала нет — нормальный случай. Эхо-записку отправь ПЕРВЫМ действием по адресу
оркестратора — это и проверка канала.