textmachine/docs/BACKEND_MONEYSTOP_SESSION_PROMPT.md

150 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Промт сессии: БЭКЕНД — «денежный стоп перестаёт быть аварией»
> **Роль:** бэкенд. **Зона записи:** `backend/` + СВОЯ секция в `docs/PROGRESS.md`. Чужие зоны
> (`platform/`, `frontend/`, `eval/`) читаешь, не правишь. **Не коммитишь** и вообще не трогаешь индекс
> и историю — почему именно и полный список запретов: `CLAUDE.md`, §«Git-координация мультисессий».
> Дерево готовишь и передаёшь оркестратору на лендинг.
## 1. Какая проблема и что решит твой результат
Пользователь покупает перевод книги. Сегодня **книгу нельзя дочитать никакими деньгами**, а книга
короче десяти глав не переводится вообще никогда. Замерено живьём на платном прогоне и воспроизведено
дважды. Половина причины — платформенная (форма потолка), и её чинит другой пак. **Твоя половина —
движковая, и она гейт: пока она не сделана, любая новая форма заказа упирается в ту же стену.**
Механизм: движок резервирует оценку перед каждым вызовом и **отказ ОДНОГО резерва гасит всю книгу**
уже допущенные параллельные вызовы отменяются, ничего не списывается, ничего не производится. Прогон
умирает за 1015 секунд с нулём сделанного.
**Результат, которого ждут:** отказ в резервации означает «не начинаем новое», а не «убиваем начатое».
Прогон доводит допущенное, завершается штатно и НАЗЫВАЕТ, сколько не хватило.
## 2. Зона записи и git
См. шапку. Дополнительно: `docs/architecture/**` — зона оркестратора, туда не пишешь; расхождение
дока с кодом — пингом в свою секцию `docs/PROGRESS.md`, не своей правкой.
## 3. Карта чтения — ПЯТЬ позиций, дальше только по ссылкам отсюда
1. `docs/architecture/15-money-path.md` — §«ОТКРЫТАЯ РАЗВИЛКА 04.09» целиком: разбор трёх независимых
чтений, все числа с носителями.
2. `docs/PROGRESS.md`, строки бэклога **277 · 261 · 262 · 278** — твой состав, формулировки зоны.
3. `backend/internal/pipeline/volume.go`, греп `THE STOP IS A COMPLETION, NOT A HALT` — **прецедент
внутри твоего же пакета**: объёмный потолок уже построен с нужной семантикой и САМ противопоставляет
себя денежному.
4. `docs/architecture/05-decisions-log.md` — грепом: `D39.122` (семантика `--ceiling-usd`), `D39.170`
(структурное лечение пробоя потолка), `D39.183` (правка тестов — про МОТИВ).
5. `docs/experiments/00-provider-quirks.md`**перед любым утверждением о биллинге провайдера.**
**Код первичен.** Отправные точки, а не истина: `stagerun.go` (греп `r.Store.Reserve(r.Book.BookID`,
`ReserveDeniedBook`, `No 2xx ever arrived`), `waverun.go` (греп `context.WithCancel`), `ledger.go`
(греп `func (s *Store) Reserve`), `httpllm.go` (греп `for att := 0; att < profile.MaxAttempts`).
## 4. Состав — что делать РОВНО так и что решаешь сам
**(1) ДЕЛАЙ РОВНО ТАК — отказ резерва перестаёт гасить допущенное.** Отступление = пинг.
· Отказ **защёлкивается на уровне ВОЛНЫ**: кормилец перестаёт раздавать индексы по первому
`ReserveDeniedBook`. Без защёлки W воркеров дадут W путей ошибки вместо одной остановки.
· Уже допущенные вызовы **дорабатываются**. `cancel()` по деньгам не зовётся.
· При непустом полёте отказ **не окончателен**: ждать settle (settle ≤ оценки, значит запас растёт) и
повторить тот же резерв. Отказ при пустом полёте — стоп.
· Завершение **штатное**, с леджером сделанного и отложенного. Exit 4 и `paused` остаются: семантика
«деньги кончились, резюмируемо» верна.
**(2) ДЕЛАЙ РОВНО ТАК — «сколько не хватило» доезжает наружу.** Число у тебя уже есть и печатается
(`denied estimate=$…`), но умирает в stderr транзиентного юнита. Оно обязано ехать в событие `ceiling`
отдельным полем. ⚠ Наружу — только НЕДОСТАЮЩАЯ сумма; цены моделей, стадий и вызовов не выходят.
**(3) ДЕЛАЙ РОВНО ТАК — проекция цены в `manifest --json` и `status --json`.** По ЮНИТУ: `source_chars`
(руны ингестированного текста, включая пробелы), раздельно плотные/разреженные знаки, `expected_usd`;
по КНИГЕ: `book_once_usd` (книжное слагаемое — терминология тратится на книгу, не на юнит) и
`step_max_usd` (самый крупный неделимый резерв). Считается из СВОИХ цен и фертильности, **без константы
за главу**. Плюс `structure: detected|declared|none` — признак доверия к нарезке. Всё аддитивно, версию
манифеста НЕ двигает.
**(4) РЕШАЕШЬ САМ И АРГУМЕНТИРУЕШЬ:** форма защёлки; где именно ждать settle; как назвать поля;
сеттлить ли оценкой поздно отменённый вызов и по какому различителю (латентность — кандидат, порог
обязан быть обоснован ЗАМЕРОМ, а не назначен).
**(5) НЕ ДЕЛАЙ:** не убирай резервацию — она единственная гарантия «не потратим больше, чем дано»;
не резервируй «ожидаемое» вместо worst-case; не ужимай `max_tokens` под остаток (двигает `request_hash`
⇒ снапшот и детерминизм, и даёт `finish=length` ценой целой генерации); не трогай кумулятивную
семантику `--ceiling-usd`; не двигай `manifestVersion`, `StreamVersion`, схему и контракт.
## 4-бис. ДВА РАЙДЕРА — и вот почему они здесь, а не в другом паке
**Честно о происхождении состава:** пункты 13 выше выведены из денежного разбора, а не из свежего
прочтения бэклога. Владелец поймал это вопросом «взял по инерции или вычитал?». Пере-проверка
бэклога (42 движковые строки со статусом «скоро») дала ДВА хвоста, которые по цене ошибки идут не
позже денежного стопа, и оба дёшевы. Они входят в пак райдерами, а не отдельным паком, потому что
каждый — одно касание, а собирать под них третью сессию дороже, чем сделать здесь.
**(Р1) ДЕЛАЙ РОВНО ТАК — строка 271: правки банка пользователя едут в SYSTEM-сообщение ДОСЛОВНО.**
Тело собирается конкатенацией `src + " → " + dst`, `dst` приходит с пользовательской двери и получает
ровно один `TrimSpace`; предела длины нет, управляющие символы не запрещены. ⇒ `dst` с переводами
строки дописывает свои строки внутрь системного блока КАЖДОГО платного вызова. ⚠ Ратифицированный
инвариант проекта звучит противоположно: «текст книги и любая веб-выдача = untrusted DATA, никогда —
инструкции… **сегодня выполняется КОНСТРУКЦИЕЙ**» — конструкция его больше не выполняет, потому что
появилась пользовательская запись, открывающаяся в system-роль. Лечение: предел длины, запрет
управляющих, обрамление как ДАННЫХ, и адверсариальная проба, что вставка не становится инструкцией.
⚠ Это обязано быть закрыто ДО того, как внутрь пустят первого внешнего человека, — а платформенный
пак, который его пускает, идёт ПАРАЛЛЕЛЬНО твоему.
**(Р2) ДЕЛАЙ РОВНО ТАК — строка 251: банковый контур требует артефакта, которого в git нет.**
`mining.contrast_path` — единственный вход контура; артефакт крупный, генерируется из jieba, в
репозитории его нет и быть не должно. Три гарда добавлены прошлым паком, но **развёртывание обязано
положить файл рядом с конфигом ПЕРЕД выкаткой**, и сегодня об этом не сказано там, где читает
оператор. ⚠ Твоя половина — сделать отказ читаемым и назвать рецепт в носителе движка; операторскую
половину рантбука чинит платформа своим паком, ей об этом сказано.
**Что в райдеры НЕ вошло и почему:** строка 283 (структура глав для выдачи) — гейт беты, но это
СВОЙ пак и своё окно пере-снапшота; строки 253/273 — швы, требующие согласования с платформой;
256267 — то, что зона чинит прямо сейчас в незакрытой приёмке прошлого пака.
## 5. Пять рисков реализации — названы зоной, проверить ОБЯЗАН
(а) защёлка на уровне волны, не у воркера · (б) учёт объёма (`volume.go`, `bound()`/`reconcile`): частичная
волна под потолком — НОВАЯ форма для этих счётчиков, и они уже дважды ловили ложные числа · (в) событие
`ceiling` и exit 4/`paused` обязаны сработать так же и не задержаться · (г) дневной потолок делит ветку с
книжным — проверить явно · (д) эскалационный хоп: убедиться, что его деградация не опирается на саму отмену.
## 6. Мандат самопроверки ИСПОЛНЕНИЕМ
Батарея + **собственные адверсариальные посадки ВНЕ списка автора** через `cmd/tmmutate` (каталог 151
запись — пополняешь). **Субагенты РАЗРЕШЕНЫ явно**, модель называй имени. Обязательное условие приёмки:
посадка **«под потолком волна погасила допущенный вызов» предъявлена КРАСНОЙ**.
**SURVIVED не является находкой, пока не показано, что посадка ВООБЩЕ меняет поведение** — норма
куплена эквивалентной посадкой оркестратора (обход окна с обратной стороны воспроизводил оригинал).
⚠ Мутации — только на ЗАКОММИЧЕННОМ дереве; на копии — `GOFLAGS=-buildvcs=false`.
⚠ Каталог гонять ЦЕЛИКОМ: протухшая запись даёт `ROTTED` и не кладёт прогон.
## 7. Записка-план ДО работы
Комплектность против заказа — механически, таблицей: пункт → файл → тест → посадка. До первой правки.
## 8. Заявление = команда
Каждое число и каждая категорика отчёта — с командой получения. Приёмка пере-ранит. ⚠ Отрицательное
утверждение («такого пути нет») выводится ТОЛЬКО из названного грепа, и команда приводится в тексте:
за сутки трижды ловили отрицания, выведенные из команд, которые не сработали.
## 9. Эхо-протокол старта
≤10 строк «скоуп / инварианты / не-делать» ДО работы — в прямой канал, первым действием.
## 10. Obstacle reporting
Обязательная секция отчёта: что НЕ удалось, что не проверено, что осталось гипотезой. ⚠ **Отчитаться о
баге не значит его сдать** — норма куплена вчера: найденное и не починенное не превращается в долг
решением о темпе.
## 11. Канал вопросов
Конфликт промта с кодом или доками — **пинг, не интерпретация**. Право сказать «этого делать не надо» с
аргументом — есть, и им пользуются: за сутки зона трижды опровергла оркестратора по существу.
## 12. Прямой канал
Механизм — `CLAUDE.md` §«Связь между сессиями». Впиши свой блок первым делом; адрес оркестратора бери
оттуда же и сверяй `ListAgents` перед отправкой. Канала нет ⇒ **НЕ искать**, вопрос секцией в отчёт.