24 KiB
Промт: платформа, пак 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--resnapshotto 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 позиций, ЗАКОН
platform/internal/runner/engine.go:79-99(TranslateArgs— argv строится в одном месте) ·platform/internal/runs/spawn.go:140-215(spec,ceilingFor,bookCap).platform/internal/runs/runs.go:200-300— допуск прогона, шкала,Pricing.Scale; иplatform/internal/pricing/pricing.go:50-90.platform/internal/ingest/resync.go:10-46— ⚠ аллоулистStatusReport, читать ВНИМАТЕЛЬНО:rebillисключён НАМЕРЕННО («engine vocabulary that must not cross the seam, contract §2.12»). Это не недосмотр, и §3.3 — про то, как это законно изменить.docs/architecture/17-seam-inbound-law.md— закон шва: п.7 (мутирующий глагол сначала даёт ПРОЕКЦИЮ), п.2 (посреди прогона внутрь только сигнал). ⚠ Строка:102таблицы говорит, что consent-флаги «гейчена 192» — ЭТОТ ГЕЙТ СНЯТ, см. §0-бис ниже. Не откажись от пака, упершись в неё.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. Самопроверка ИСПОЛНЕНИЕМ — «перечитал сам» её не удовлетворяет
- Батарея зоны под
-raceс живым Postgres, линтер 0 issues; числа — с командами. ⚠TM_PLATFORM_TEST_DSNставить ОБЯЗАТЕЛЬНО: без него значительная часть батареи уходит в SKIP, а зелень рапортуется всё равно — ловушка, на которой приёмка уже ловила сдачу (D39.162). Число пропусков посчитай КОМАНДОЙ и приведи в отчёте (с DSN и без) — константу из прошлого пака сюда не переписывай, дерево с тех пор двигалось. - Мина доказывается ПОСТ-ФИКСНЫМ инвариантом, и ⛔ НЕ на движке-заглушке. Первая редакция этого
пункта была ВЫРОЖДЕННОЙ (нашёл опровергатель): у заглушки гарда снапшота нет вовсе, поэтому
«прогон дошёл до движка» зелено при ЛЮБОМ коде — это проверка argv в маскировке.
Не-вырожденная форма существует и дешева: живой
tmctl, прецедент в твоей же зоне —platform/internal/runner/bankapply_live_test.go. Гард достижим БЕЗ провайдерских ключей и без единого платного вызова: без флага он стреляет ДО первого вызова модели, с флагом $0-репин проходит. ⚠ И состояние обязано быть правильным: edit-джоб существует ДО правки — иначе репро зелено без фикса (эррата 28.08-и). - Дверь доказывается допуском: на дочитанной книге с подвинутым банком старт ПРОХОДИТ, на дочитанной книге без движения банка — по-прежнему отбивается.
- Свои посадки мутаций: минимум по одной на пункт; вердикт — по ДЕЛЬТЕ против чистой базовой линии и по ТОПИЧНОСТИ упавшего теста, не по цвету батареи.
- Субагенты РАЗРЕШЕНЫ явно. Опровергатель на §3.3 (пропуск
rebill_unitsчерез аллоулист) — ЗАКАЗ, не право: он получает мой довод и мандат «покажи, где это нарушает §2.12 контракта или D39.84». Веер соразмеряй предмету, численного потолка нет.
§5. Оси ревью — 1–3, вправе заменить с аргументом
- Ось денег: может ли пак купить больше, чем показал; может ли холд разойтись с фактом;
не превращает ли
--resnapshotгромкую ошибку в тихую покупку. - Ось «пара, которой в репо нет»: ветвления по паре/книге в Go быть не должно; вид покупки на проводе — открытый словарь.
- Ось детерминизма: трогаешь argv движка — не сдвинулись ли снапшоты и хеши так, что прогон перекупается.
§6. Записка-план, комплектность
До правок — записка-план в зонном журнале. В конце — таблица комплектности против §3: пункт → что сделано → каким ИСПОЛНЕНИЕМ подтверждено. Слово вместо команды = пункт НЕ сделан.
⚠ Журнал docs/PROGRESS.md — НЕ твой, пиши только в зонный. (Оркестратор 28.08 унёс чужую
секцию своим коммитом ровно из-за общего окна записи — механизм плохой, не повторяй его с другой
стороны.)
§7. Эхо-протокол старта
ДО работы — ≤10 строк: скоуп · инварианты · не-делать. Первое действие — вписать свой блок в файл канала (§10), сразу второе — послать мне эхо.
§8. Obstacle — обязательная секция
«Что НЕ удалось и что НЕ проверено» отдельной секцией, не россыпью.
§9. Канал вопросов и твоё право отказаться
Конфликт промта с кодом или доками — пинг, не интерпретация в свою пользу. ⚠ У тебя есть право сказать «этого делать не надо» — с аргументом. Промт писал не тот, кто живёт в этом коде. За последние сутки исполнители опровергли ДВА моих заказа и оба раза были правы; один из них я пере-проверил своей посадкой и отозвал. Отказ с разбором дороже послушного исполнения. ⚠ Тесты и гейты не подгонять под зелень (D39.121).
§10. Как со мной связаться
Адрес — в файле /tmp/textmachine-channel (механизм — CLAUDE.md). Впиши свой блок первым
делом, чужие не трогай. ⚠ Канала нет ⇒ НЕ искать: вопрос секцией в отчёт, работа продолжается.