# Промт: платформа, пак P10 — мина под правкой банка и дверь пере-прохода > **Выдан оркестратором №19, 28.08.2026.** Основание — **D39.165** (три продуктовых развилки сняты > словом владельца). Пак закрывает ОДНУ поломку и ОДНУ дыру, и обе лечатся теми же двумя флагами в > одной функции сборки аргументов — поэтому это один пак, а не два. ## §0. Какая проблема и что решит твой результат **1. Мина, которую взвёл наш собственный вчерашний лендинг.** Правка банка двигает снапшот. Движок при сдвинутом снапшоте **останавливается ГРОМКО**, если ему не передали `--resnapshot`: > `backend/internal/pipeline/stagerun.go:54-58` — «was started under snapshot … the config/prompts > changed; already-paid checkpoints become invalid and calls will be re-paid; re-run with > `--resnapshot` to accept this explicitly». Платформа не передаёт ни его, ни `--accept-rebill` (`platform/internal/runner/engine.go:90-98`, `TranslateArgs`). До 28.08 это не кусало: до движка не доезжало ни ключей, ни правок. Вчера заленджены и `--keys-file`, и дверь правок банка (D39.162). Носитель — строка **199**(б). ⚠ **ТОЧНЫЙ ТРИГГЕР, без которого ты соберёшь ЛОЖНОЕ репро (эррата 28.08-и — моя ошибка, найдена опровергателем).** Первая редакция этого промта и ноты утверждала «первый же продолжающий прогон после первой же правки УПАДЁТ». Это ПЕРЕОЦЕНКА. Гард стреляет по СУЩЕСТВУЮЩЕМУ джобу (`stagerun.go:47` — `EnsureJob` заводит джоб стадии в момент её первого исполнения), а правка в главном окне — стоп подписи `awaiting_bank` — двигает edit-снапшот, когда edit-джобов ЕЩЁ НЕТ: возобновление создаёт их свежими и гард молчит. **Мина бьёт по правке, сделанной ПОСЛЕ появления edit-джобов** — пауза потолком посреди редактуры и ДОЧИТАННАЯ книга. Срочность от этого не падает: флагманский случай продукта — «поправил имя героя в дочитанной книге» — ровно тот, где edit-джобы существуют. **2. Дыра: продать пере-проход нечем, а движок его умеет.** Механизм построен практически целиком: `translate --resnapshot` после `bank-apply` определяет затронутые термином юниты **байт-сверкой** отрендеренного запроса (`stagerun.go:88-100` — «POINTWISE RE-EDIT … the request is the same request and the stored result is served for $0, with the row RE-PINNED»), незатронутые пере-привязывает за **$0**, считает смету ДО первого резерва и **под порогом согласия продолжает сам, без флагов** (`backend/internal/pipeline/rebill.go`, порог — свой у книги, иначе `min($0.50, 5% × книги)`). Не хватает ровно платформенной половины. И канон при этом **противоречит сам себе на дочитанной книге, в двух фразах**: правка «takes effect on the NEXT run» (`docs/architecture/14-api-contract/openapi.yaml:505`), а поднять потолок можно только у ПРИОСТАНОВЛЕННОЙ книги и «finished work is not bought twice» (`:590`). У дочитанной книги следующего прогона купить нечем — **правка принята и умирает**. **Что решит результат:** главный пользовательский цикл продукта — «поправил термин → правка доехала в уже переведённый текст» — становится исполнимым, а купленный вчера механизм перестаёт быть недостижимым. ## §1. Зона записи и git **Твоя зона — `platform/`.** Итоги, находки, вопросы — зонный журнал `platform/docs/platform-PROGRESS.md`. - **Ты НЕ коммитишь.** Лендит оркестратор после адверсариальной приёмки. - ⚠ **`backend/` НЕ ТРОГАТЬ.** Движковая половина построена и в этом паке правок не требует. Нужна правка там — это ПИНГ, а не правка. - ⚠ **`docs/` — не твоя зона**, включая канон контракта. Контрактную половину (§3.4) ты **описываешь предложением в своём журнале**, правлю её я. Причина не бюрократическая: канон и константа версии обязаны сойтись в ОДНОМ коммите, а коммичу я. - В дереве незакоммиченная работа полигона (20 позиций) — не касаться. ## §2. Карта чтения — ≤5 позиций, ЗАКОН 1. **`platform/internal/runner/engine.go:79-99`** (`TranslateArgs` — argv строится в одном месте) · **`platform/internal/runs/spawn.go:140-215`** (`spec`, `ceilingFor`, `bookCap`). 2. **`platform/internal/runs/runs.go:200-300`** — допуск прогона, шкала, `Pricing.Scale`; и `platform/internal/pricing/pricing.go:50-90`. 3. **`platform/internal/ingest/resync.go:10-46`** — ⚠ **аллоулист `StatusReport`, читать ВНИМАТЕЛЬНО: `rebill` исключён НАМЕРЕННО** («engine vocabulary that must not cross the seam, contract §2.12»). Это не недосмотр, и §3.3 — про то, как это законно изменить. 4. **`docs/architecture/17-seam-inbound-law.md`** — закон шва: п.7 (мутирующий глагол сначала даёт ПРОЕКЦИЮ), п.2 (посреди прогона внутрь только сигнал). ⚠ **Строка `:102` таблицы говорит, что consent-флаги «гейчена 192» — ЭТОТ ГЕЙТ СНЯТ, см. §0-бис ниже. Не откажись от пака, упершись в неё.** 5. **`docs/architecture/05-decisions-log.md`, тело D39.165** — основание всего пака (греп `^## D39.165`). ## §0-бис. Гейт, который СНЯТ — знать до чтения закона шва `D39.144` п.1 запрещает **проектировать механику** пост-ридинговых правок до итогов полигона, и закон шва помечает эти флаги «гейчена 192». **Владелец снял это 28.08 (D39.165):** открыть дверь к УЖЕ ПОСТРОЕННОМУ движковому механизму — не то же самое, что проектировать продуктовый цикл пост-ридинга. **Гейченным остаётся цикл**: отдельная ручка «перегенерировать», `resnapshot --dry-run`, доезд правки до ЧЕРНОВИКА через сид. Этого не строить. ## §3. Состав пака ### §3.1. Мина — ЗАКАЗ, форма свободна; чинить ПЕРВЫМ **Заказано:** продолжающий прогон по книге, чей банк двигался, больше не падает на гарде снапшота. **Что знать, прежде чем выбирать форму** (проверено мной, пере-проверь): - `--resnapshot` принимает пере-привязку и пере-перевод затронутых юнитов. `--accept-rebill` — другое: он принимает ПЕРЕ-ПЛАТУ сверх порога. **Это ортогональные флаги**, и так сказано в самом движке: `backend/cmd/tmctl/main.go:252` — «The three money flags are ORTHOGONAL». ⚠ Там же предупреждение, которое тебя касается напрямую: `--ceiling-usd` — НЕ бюджет прогона, он говорит «книга может дойти до $X», а не «этот прогон потратит $X». - ⛔ **ОДНОГО `--resnapshot` НЕ ХВАТИТ, и первая редакция промта здесь ошибалась (нашёл опровергатель).** Отказ консент-гейта — ПЛОСКИЙ `fmt.Errorf` (`backend/internal/pipeline/rebill.go:322`), а не типизированный отказ ⇒ `tmctl` выходит кодом **1**, и платформа запишет `failed` ПОСЛЕ взятого холда. А порог низкий: `min($0.50, 5% × книги)`, и по замеру D39.165 десятиглавая книга стоит $0.12–0.19 ⇒ порог около ПОЛУЦЕНТА. Правка частотного термина — имени героя, флагманский случай §0 — почти гарантированно НАД порогом. **Дверь, передающая только `--resnapshot`, не сможет продать ровно то, ради чего строится.** Значит согласие на СУММУ обязано доезжать тоже. - ⚠ **Носителя факта «банк двигался» СЕГОДНЯ НЕТ — его надо ПОСТРОИТЬ, и промт этого не скрывает.** `ApplyBankCorrections` (`platform/internal/runs/bank.go:90-187`) в Postgres не пишет НИЧЕГО: квитанция уходит звонящему и умирает. Носитель — твой предмет, зона твоя. ⚠ Его края назови сам и проверь: превью (`preview`) и ответ `changed:false` фактом считаться НЕ должны · правка в окне `awaiting_bank` относится к ТОМУ ЖЕ прогону · argv обязан быть СТАБИЛЕН при респавне попытки, иначе флаг появится посреди прогона. - ⛔ **«Банк двигался» НЕ РАВНО «снапшот двигался только из-за банка», и это дыра в моём же условии.** Снапшот на SaaS двигают и деплойные причины: промпты пары и langpack складываются в него (`backend/internal/config/book.go:86,92` — «a pack edit is a loud --resnapshot»), то есть апгрейд деплоя двигает снапшот ВСЕХ книг. На книге со свежей квитанцией банка условный `--resnapshot` примет и ЭТОТ дрейф — а `repinnable` отвечает false для не-банковых сдвигов (`stagerun.go:94-95`), значит юниты пойдут в пере-оплату, и под порогом — МОЛЧА. **Заказ: форма обязана различать банковый сдвиг от деплойного либо делать согласие явным. Как — решаешь ты, но «свежая квитанция» сама по себе основанием НЕ является.** ### §3.2. Дверь: допуск пере-прохода — ЗАКАЗ **Заказано:** на книге, где остаток нулевой, но банк двигался после последнего прогона, старт прогона ДОПУСКАЕТСЯ. Сегодня он невозможен: шкала клампится остатком (`platform/internal/pgstore/books.go:969-973`, `ChaptersLeft` «it clamps the ceiling scale»), у дочитанной книги `Scale` даёт `Max=0`, и любой старт отбивается (`platform/internal/runs/runs.go:268-281`). ⚠ **Размер холда — думай отдельно, это деньги, и ломает он в ОБЕ стороны.** Завышенный: пере-проход стоит ЦЕНТЫ (незатронутое идёт за $0), а холд в главах × $0.03 завысит его в разы. Заниженный: `CeilingTemplate.Args` отказывает неположительному потолку (`platform/internal/runner/engine.go:64-69`), а `--ceiling-usd` — КУМУЛЯТИВНЫЙ книжный кап (`spawn.go:187-213`, `bookCap`), поэтому холд обязан остаться строго положительным ПРИРАЩЕНИЕМ к уже потраченному. Форма твоя; вариант «холд от сметы» — §3.3. ### §3.3. Смета через шов — ЗАКАЗ на ФОРМУ, и здесь есть настоящий вопрос Движок уже публикует смету в `status --json`: `rebill_units` и `rebill_usd` (`backend/internal/pipeline/status.go:202-209`). Платформа их не берёт — **и это НАМЕРЕННОЕ исключение аллоулиста** (`resync.go:10-13`). ⚠ **ПОПРАВКА К ПЕРВОЙ РЕДАКЦИИ ПРОМТА (нашёл опровергатель): `rebill_usd` через ШОВ пускать МОЖНО.** Я ошибочно запретил это ссылкой на D39.84 — но D39.84 запрещает ПРОЕКЦИЮ денег в API-ответ и в INFO-лог, а не пересечение шва. Деньги шов уже пересекают законно и хранятся: `platform/internal/ingest/resync.go:31-37`, `Spend *money.MicroUSD` — «stored in the credit tables and NEVER projected into an API response or an INFO log (D39.84)». D39.165 и строка 215 говорят про ОБА поля. **Бери оба; наружу, в API, доллары не выпускай.** Без долларовой половины холд от сметы невыразим — пер-юнитной цены у платформы нет вовсе. **Мой довод про аллоулист — прими с проверкой либо опровергни:** `rebill_units` — СЧЁТ РАБОТЫ, той же природы, что уже пересекающие шов `total_units`, `done`, `flagged`, `pending`. ⚠ **Но лёгким этот пропуск НЕ будет, и вот почему:** компаньон контракта в §2.12 (`docs/architecture/14-api-contract/README.md:505-511`) называет «ре-билл» В ЗАПРЕТНОМ СПИСКЕ ПОСЛОВНО. Спор о природе счёта ратифицированного списка не снимает — значит показ юнитов пользователю требует правки §2.12, и она входит в контрактную половину §3.4. **Заказано:** пользователь до покупки видит, **сколько юнитов затронет** пере-проход. Это прямое исполнение п.7 закона шва — проекция прежде мутации. ### §3.4. Контрактная половина — ОПИСАТЬ, НЕ ПРАВИТЬ Опиши предложением в журнале, правлю я: - фраза «finished work is not bought twice» (`openapi.yaml:590`) в нынешнем виде запрещает то, что пак разрешает — нужна оговорка про пере-проход; - поле «затронуто N юнитов» в ответе опций прогона; - ⚠ **правка §2.12 компаньона** — он держит «ре-билл» в запретном списке пословно, и без неё код разойдётся с каноном (см. §3.3); - ⚠ **вопрос, а НЕ заказ: нужен ли проводу «вид покупки» вообще.** D39.165 ратифицирует показ «затронуто N юнитов» и о видах покупки не говорит НИ СЛОВА. И не обосновывай открытый словарь аналогией с `Progress.stage`: D39.163 запрещает такой довод буквально — «третьего исключения нет, и „раз уж есть два“ аргументом не будет; каждое следующее — отдельная нота». Считаешь, что вид покупки нужен, — приноси довод по существу, я заведу ноту. ### §3.5. Чего в паке НЕТ — пропуски подписаны - **Ценообразование от объёма исходника** (D39.165 §1) — НЕ в этом паке. Оно гейчено калибровкой, а калибровка — строкой **202** (живой прогон текущего стека). Константу $0.03 не трогать. - **Потолок объёма в движке** — движковый предмет, не твой. - **Эпоха смены формы конвейера** (`PD-403`/`PD-404`, D39.165 §2) — отдельный пак той же зоны, но НЕ этот: он про счёт готовности, а этот про покупку. Не смешивать. - **Доезд правки до ЧЕРНОВИКА** — гейчено полигоном, см. §0-бис. ## §4. Самопроверка ИСПОЛНЕНИЕМ — «перечитал сам» её не удовлетворяет 1. **Батарея зоны** под `-race` с живым Postgres, линтер 0 issues; числа — с командами. ⚠ **`TM_PLATFORM_TEST_DSN` ставить ОБЯЗАТЕЛЬНО:** без него значительная часть батареи уходит в SKIP, а зелень рапортуется всё равно — ловушка, на которой приёмка уже ловила сдачу (D39.162). **Число пропусков посчитай КОМАНДОЙ и приведи в отчёте** (с DSN и без) — константу из прошлого пака сюда не переписывай, дерево с тех пор двигалось. 2. **Мина доказывается ПОСТ-ФИКСНЫМ инвариантом, и ⛔ НЕ на движке-заглушке.** Первая редакция этого пункта была ВЫРОЖДЕННОЙ (нашёл опровергатель): у заглушки гарда снапшота нет вовсе, поэтому «прогон дошёл до движка» зелено при ЛЮБОМ коде — это проверка argv в маскировке. **Не-вырожденная форма существует и дешева:** живой `tmctl`, прецедент в твоей же зоне — `platform/internal/runner/bankapply_live_test.go`. Гард достижим БЕЗ провайдерских ключей и без единого платного вызова: без флага он стреляет ДО первого вызова модели, с флагом $0-репин проходит. ⚠ И состояние обязано быть правильным: **edit-джоб существует ДО правки** — иначе репро зелено без фикса (эррата 28.08-и). 3. **Дверь доказывается допуском:** на дочитанной книге с подвинутым банком старт ПРОХОДИТ, на дочитанной книге без движения банка — по-прежнему отбивается. 4. **Свои посадки мутаций:** минимум по одной на пункт; вердикт — по ДЕЛЬТЕ против чистой базовой линии и по ТОПИЧНОСТИ упавшего теста, не по цвету батареи. 5. **Субагенты РАЗРЕШЕНЫ явно.** Опровергатель на §3.3 (пропуск `rebill_units` через аллоулист) — **ЗАКАЗ, не право**: он получает мой довод и мандат «покажи, где это нарушает §2.12 контракта или D39.84». Веер соразмеряй предмету, численного потолка нет. ## §5. Оси ревью — 1–3, вправе заменить с аргументом 1. **Ось денег:** может ли пак купить больше, чем показал; может ли холд разойтись с фактом; не превращает ли `--resnapshot` громкую ошибку в тихую покупку. 2. **Ось «пара, которой в репо нет»:** ветвления по паре/книге в Go быть не должно; вид покупки на проводе — открытый словарь. 3. **Ось детерминизма:** трогаешь argv движка — не сдвинулись ли снапшоты и хеши так, что прогон перекупается. ## §6. Записка-план, комплектность **До правок** — записка-план в зонном журнале. **В конце** — таблица комплектности против §3: пункт → что сделано → каким ИСПОЛНЕНИЕМ подтверждено. Слово вместо команды = пункт НЕ сделан. ⚠ **Журнал `docs/PROGRESS.md` — НЕ твой**, пиши только в зонный. (Оркестратор 28.08 унёс чужую секцию своим коммитом ровно из-за общего окна записи — механизм плохой, не повторяй его с другой стороны.) ## §7. Эхо-протокол старта ДО работы — ≤10 строк: **скоуп · инварианты · не-делать**. Первое действие — вписать свой блок в файл канала (§10), сразу второе — послать мне эхо. ## §8. Obstacle — обязательная секция **«Что НЕ удалось и что НЕ проверено»** отдельной секцией, не россыпью. ## §9. Канал вопросов и твоё право отказаться Конфликт промта с кодом или доками — **пинг, не интерпретация в свою пользу**. ⚠ **У тебя есть право сказать «этого делать не надо» — с аргументом.** Промт писал не тот, кто живёт в этом коде. За последние сутки исполнители опровергли ДВА моих заказа и оба раза были правы; один из них я пере-проверил своей посадкой и отозвал. Отказ с разбором дороже послушного исполнения. ⚠ **Тесты и гейты не подгонять под зелень** (D39.121). ## §10. Как со мной связаться **Адрес — в файле `/tmp/textmachine-channel`** (механизм — `CLAUDE.md`). Впиши свой блок первым делом, чужие не трогай. ⚠ **Канала нет ⇒ НЕ искать:** вопрос секцией в отчёт, работа продолжается.