# Промт: бэкенд, пак «честные числа и статусы» — строки 176 · 181 · 172-г · 187 > Выдан оркестратором №18, 16.08.2026. Запуск — по слову владельца. > Вес пака — лёгкий-средний: четыре точечных места, приёмка инлайн. ## 0. Зачем (проблема, понятная без истории проекта) Движок — CLI (`tmctl`), который переводит книгу платными вызовами LLM и которым снаружи управляет процесс-супервизор (платформа). Наружу он сообщает три вещи: **число денег**, **код выхода** и **вердикт гейта**. Сегодня в четырёх местах сообщаемое расходится с происходящим: 1. **Число, на которое оператор даёт согласие при пере-покупке, посчитано по СТАРЫМ ценам.** Цены провайдера сменились 16.08 (до ×4.4 в пике), проекция пере-покупки складывает исторический `cost_usd`, а резерв и расчёт считают новой таблицей. Оператор соглашается на одну сумму, платит другую. Траты защищены потолками — врёт именно ЧИСЛО СОГЛАСИЯ (строка 181). 2. **Паника Go-рантайма неотличима от успеха.** Непойманная паника даёт exit 2, а 2 в контракте означает «завершено, есть флагнутые главы» — потребитель записывает упавшему посреди работы прогону «готово». Деньги при этом целы (считаются из `status --json`), врёт статус (строка 176). 3. **Ратифицированный порог приёмки классификатора не доехал до тестового рига.** Владелец 15.08 подписал ВЫБОРОЧНУЮ форму порога, риг требует прежнюю — и сам предупреждает, что порог и выборка расходятся. Ближайший прогон вахты упадёт ложно (строка 172-г). 4. **Два комментария кода описывают снятое поведение** — читатель кода получает неверный закон о том, что попадает в `memory_version` (строка 187). **Что решит твой результат:** ни одно из четырёх мест больше не врёт, и каждое прибито тестом, который на до-фиксном коде ПАДАЕТ. После пака можно честно пере-прогонять старую книгу (сейчас нельзя — п.1) и честно читать исход прогона снаружи (п.2). ## 1. Зона записи и git Пишешь ТОЛЬКО в `backend/`. Итог сессии — краткой записью в `docs/PROGRESS.md`, секция «Бэкенд» (это единственный файл вне `backend/`, куда тебе можно писать). **Ты не коммитишь — лендит оркестратор.** `git add` / `git commit` / `git reset` / `git checkout` / `git stash` не звать вовсе; файлы застейдженными не оставлять. Карв-аут к «пишешь только в `backend/`»: **пробные проекты в `~/books/…` — легитимная запись** (они вне git, и норма «персист, не scratch» требует, чтобы сырьё платной пробы легло рядом с проектом пробы, а не в `/tmp`). Это касается только пункта 5. ⚠ **В дереве прямо сейчас работают ДВЕ чужие живые сессии** — полигон (`eval/`, `docs/experiments/`) и платформа (`platform/`). Их незакоммиченные файлы читать можно, трогать — нельзя ни при каких обстоятельствах. `.env` не читать никогда (там ключи). `frontend/` не трогать. ## 2. Карта чтения (≤5, больше не нужно) 1. `CLAUDE.md` — гардрейлы и инвариант общности (Go не ветвится по языковой паре). 2. `backend/README.md` + `docs/architecture/12-go-style-notes.md` §0 — норматив зоны. 3. Тела строк **176 · 181 · 172-г · 187** в таблице «Бэклог» файла `docs/PROGRESS.md` — это ЗАКАЗ; в них лежат `file:line` отправные точки. Строки писала нейросеть: якоря могли уплыть, формулировка могла устареть — **код первичен**, расхождение строки с кодом называй вслух в отчёте. 4. `docs/architecture/05-decisions-log.md`: **D39.131** (половина 0–5 контракта кодов выхода) · **D39.134 п.2** (полоса отказов 10–19 и её обещание) · **D39.137** (пере-пин цен — откуда взялась строка 181). Греп по номеру: сначала живой файл, потом слайсы `docs/archive/architecture/`. 5. `docs/experiments/00-provider-quirks.md` — **только если** дойдёт до пункта 5 (живой прогон вахты). Всё остальное — код, и его ты достаёшь сам. ## 3. Состав Пункты 1–4 — **«делай РОВНО так» по ПРЕДМЕТУ** (что чинится, решено); **форма фикса внутри — твоя, аргументируй в отчёте**. Отступление от предмета = пинг, не интерпретация. **1. Строка 181 — число согласия на пере-покупку.** Проекция пере-покупки обязана считать ТОЙ ЖЕ ценовой таблицей, которой считают резерв и расчёт, а не складывать исторические суммы. Отправные точки заказа: `internal/pipeline/rebill.go` (сложение исторического `cost_usd`; гейт согласия и его порог), `internal/pipeline/stagerun.go` (резерв и сеттл новой таблицей). **Тест обязателен и обязан падать на до-фиксном коде** (сценарий: единицы куплены по старой цене → цена сменилась → согласие спрашивают на новую сумму). ⚠ Комментарий `rebill.go` про «over-estimating is the safe direction» после фикса обязан стать правдой или уйти. **`projected_book_usd` у `status` — В СКОУПЕ, а не «проверь и назови»**: заказ строки утверждает ту же болезнь, и оставить её значит оставить `status` врущим. ⚠ **Развилка, которую обязан разрешить явно:** сам ПОРОГ согласия тоже считается из этой проекции — починить числитель новой таблицей и оставить базу порога исторической значит получить полу-исторический гейт. Реши обе половины вместе и назови решение в отчёте; считаешь, что вторая половина не влезает — **пинг**, а не тихое сужение. **2. Строка 176 — паника не должна читаться как успех.** Непойманная паника рантайма обязана приходить наружу кодом, который потребитель прочтёт как ПРОВАЛ. ⚠ **Обе полосы кодов — ЗАМОРОЖЕНЫ, это шов, их словарь двигается только ратификацией.** - **0–5 не трогать** (ратифицированный словарь, D39.131; шапка `cmd/tmctl/main.go`). В частности **exit 2 НЕ переносить**: значение «завершено с флагами» зашито у потребителя намертво (`platform/internal/ingest/exit.go:24,89` · `platform/internal/runs/reconcile.go:484` → `ready`), и «развести номера, оставив полосу 10–19 нетронутой» **сломает шов, не нарушив буквы этого запрета** — каждый честно флагнутый прогон станет `failed`, а чтение денег сломается вместе с ним. - **10–19 не расширять и для паники НЕ использовать** — полоса обещает «ничего не произошло, ничего не потрачено, ничего не записано» (D39.134 п.2г), а паника случается посреди оплаченной работы; посадить её на 19 значит соврать наоборот. - **Безопасное направление:** код, который сегодняшняя платформа читает как `failed` — то есть **1** либо номер ВНЕ обеих полос. Выбрал не 1 — аргумент в отчёт и пинг, потому что это словарь шва. ⚠ **Ловушка, на которой фикс выглядит зелёным и молчит на настоящем пути:** платный путь исполняется пулом воркер-горутин (`internal/pipeline/waverun.go:260`), а `recover` в `main`/`run` ловит только главную горутину. **Предмет — «паника ЛЮБОЙ горутины движка не читается как успех»**, и тест обязан это покрывать; фикс, падающий только на синтетической панике в main, заказ не закрывает. Стек паники обязан доехать до stderr: диагностика важнее лаконичности. **Попутно тем же касанием** (сам заказ строки): usage-строка `cmd/tmctl/invocation.go:96` не знает команд `migrate` / `backup` / `seed-lint`. ⚠ Её байты запинены тестом замороженного контракта (`cmd/tmctl/invocation_test.go:23`) — **обновить тест ВМЕСТЕ со строкой здесь санкционировано** (ратифицированная правка контракта, D39.134 п.3): это не подгонка под зелень, и §4-запрет сюда не применяется. Любая ДРУГАЯ правка замороженных байтов — пинг. **3. Строка 172-г — выборочный порог в риг вахты.** Внести ратифицированную форму порога (**D39.136 п.6б: «≥4/5 прогонов при N=5 достигают 6/6»**) в `internal/pipeline/live_reprobe_test.go` вместо действующего «6/6 на КАЖДОМ прогоне». Комментарий рига, объявляющий расхождение порога и выборки открытым вопросом владельца, обязан быть переписан: вопрос ЗАКРЫТ, сошлись на выборочной форме. Риг под тегом `live` — компилируемость проверяется `make battery` (в `vet` оба набора тегов). ⚠ **Порог не «смягчить», а внести ратифицированный.** Подгонять гейт под желаемый результат недопустимо; если считаешь ратифицированную форму неверной — пиши пинг, не правку. ⚠ Ратифицирована форма **для N=5**; риг допускает переопределение размера выборки переменной окружения — зафиксируй в коде и комментарии, что порог определён на N=5, а иное N выводит прогон из-под гейта (изобретать формулу для произвольного N — не твоя работа, это ратификация). **4. Строка 187 — два лживых комментария.** `internal/pipeline/snapshot.go` («auto/draft исключены per D8») и докстринг `internal/membank/memory.go` («Approved-only») описывают до-паковое поведение; код с пака-20 сворачивает в хеш КАЖДУЮ строку любого статуса. $0, поведение не двигается. **5. Живой прогон вахты весов — ТОЛЬКО при явной санкции владельца в твоём запуске.** Если санкция названа: прогнать риг из п.3 живьём (`TM_LIVE=1 TM_CLASSIFY6_CONFIG=<стендовый book.yaml> go test -tags live -run TestLiveClassifierHarmSet -v ./internal/pipeline/`), сырьё персистить рядом с проектом пробы, ЛЕДЖЕР не сбрасывать, принимать только `finish=stop`, потратить не больше названной владельцем суммы. ⚠ **Стартовать вне пиковых окон DeepSeek (01–04 и 06–10 UTC)** — в пике вызов стоит вдвое; суммы копеечные, но правило стоячее. **Санкции нет в твоём запуске — пункт НЕ исполняется**, и это не obstacle, а норма: платные вызовы без явно названной суммы запрещены. **Чего НЕ делать (жёстко).** - Не трогать ничего, что двигает провод: тела промптов, состав инъекции, версии снапшота, `RequestHash`, `memory_version`, голден. Этот пак **wire-нейтрален** — все правки обязаны оставить голден бит-в-бит; расхождение голдена = стоп и пинг, а не пере-съём голдена. - Не чинить попутно другие строки бэклога, даже если увидишь. Увидел — **в отчёт списком находок**, оркестратор заведёт строки. - Не ветвить Go-логику по языковой паре (инвариант общности): ревью-вопрос «заработает ли на паре, которой в репо нет, без правки Go». - Не запускать платных вызовов вне пункта 5. ## 4. Самопроверка ИСПОЛНЕНИЕМ (обязательный механизм, не перечитывание) - **Батарея:** `cd backend && make battery` — EXIT=0, и в её хвосте список SKIP: каждый скип объясни (скип, который ты не объяснил, читается как непокрытое место). - **Голден бит-в-бит** — командой (`go test ./internal/pipeline/ -run Golden -count=1`), а не «батарея прошла»; результат в отчёт. - **Фиксы пунктов 1 и 2 (включая usage-строку) прибиты тестом, падающим на до-фиксном коде** — покажи это ИСПОЛНЕНИЕМ: временно откати свой фикс (в рабочем дереве, без git-команд), покажи красный, верни. Формулировка «тест добавлен» без красного до-фиксного прогона не принимается. **Для пунктов 3 и 4 требование НЕ применяется и имитировать его не надо:** п.4 — правка двух комментариев, поведения не двигает вовсе; п.3 живёт под тегом `live`, и «красный до-фиксный прогон» там означал бы платный вызов, запрещённый вне п.5. Их доказательство другое: п.3 — компиляция ОБОИХ тег-сетов (`make battery` гоняет `vet` по обоим) плюс юнит на пороговую арифметику, если она выносима из платного пути; п.4 — цитата кода против цитаты комментария в отчёте. - **Дифф `^func Test` — исполнением**: `grep -rh '^func Test' backend --include='*_test.go' | wc -l` до и после; удалённых имён тестов быть не должно (проверь по именам, не по числу). - **Править или удалять существующий тест/голден/гейт ради зелени — НЕДОПУСТИМО.** Несогласие с тестом — пинг, а не правка. - **Адверсариальное ревью финалом — механизмом: субагенты РАЗРЕШЕНЫ и ожидаются, спавнь.** ≥2 независимых ревьюера по финальному диффу, author≠reviewer: (а) **денежная линза** — по строке 181 пере-считать вручную, из сырого леджера, число согласия ДВУМЯ независимыми путями и сверить с тем, что печатает движок. ⚠ **Только на КОПИИ стендовой БД, вне живого проекта** — `translate` пишет в проект ещё до гейта согласия (пре-флайт бэкап), и «проба на живом» испортит и стенд, и улику; (б) **линза шва** — инвентарь ВСЕХ кодов выхода и их потребителей ЧТЕНИЕМ кода платформы (`platform/internal/ingest/`, `platform/internal/runs/`), а не по твоему списку: изменил ли пункт 2 то, что платформа читает. Плюс **свои посадки-мутации** в новые тесты (не из ожидаемого тобой списка). **Артефакт — таблица «находка → диспозиция»** в отчёте; ноль находок = не верить прогону, спавнить третьего. Считаешь, что для этого пака вернее другие оси ревью, — **замени с аргументом**; молча сузить нельзя. - **Записка-план:** перед сдачей — таблица «пункт заказа 1–5 → исполнено (где) / отказ (почему)», механической сверкой против §3, а не по памяти. - Сессия длинная — **интервальная самоверификация субагентом** против §3 и §4 в середине работы, не только в конце. ## 5. Дисциплина отчёта - **Заявление = команда.** Каждое число и каждая категорика отчёта — с командой, которой получены; приёмка их пере-ранит. Эрудиция не улика: либо `file:line`/замер, либо пометка «мнение». - **Перед отправкой отчёта сверь КАЖДЫЙ клейм с результатом инструмента ЭТОЙ сессии** — не с памятью о том, как обычно бывает. - **Последний абзац отчёта — план или обещание? Значит, сделай это сейчас**, а не пиши про это. - **Obstacle reporting — обязательная секция:** что НЕ удалось · что не проверено · где остановился и почему. Пустая секция при непустой работе не бывает. - Плотность, а не объём. Без саги, без пересказа диалога, без шаблонных оговорок. ## 6. Канал вопросов и право отказа Промт против кода, доков или спеки — **пинг через владельца, НЕ интерпретация**: промт писала нейросеть, и он может быть неправ. Право сказать «этого делать не надо» — есть, с аргументом; такое возражение ценнее тихой девиации. Промежуточный вопрос, блокирующий работу, — тоже пинг: не гадай. ## 7. Старт и сдача **Эхо-протокол:** первым деливераблом — ≤10 строк «скоуп / инварианты / чего не делаю», ДО работы. **Сдача:** запись в `docs/PROGRESS.md` секция «Бэкенд» (записка-план · команды · таблица адверсариального ревью · obstacle · список находок вне заказа), дерево НЕзакоммиченное.