326 lines
36 KiB
Markdown
326 lines
36 KiB
Markdown
# Промт сессии: БЭКЕНД — «число согласия на пути второй покупки»
|
||
|
||
> **Роль:** бэкенд. **Зона записи:** `backend/`. Чужие зоны (`platform/`, `frontend/`, `eval/`)
|
||
> читаешь, не правишь; в `docs/` пишешь ТОЛЬКО в секцию «Бэкенд» журнала `docs/PROGRESS.md` — это
|
||
> единственное разрешённое каноном исключение. **Не коммитишь** и не трогаешь индекс и историю —
|
||
> полный список запретов и причина: `CLAUDE.md`, «Git-координация мультисессий».
|
||
> Норматив стиля — `docs/architecture/12-go-style-notes.md`.
|
||
|
||
## Какая проблема и что изменит твой результат
|
||
|
||
Продукт продаёт главы **частями**. Покупатель берёт кусок, потом ещё кусок — и на этом пути число,
|
||
которым движок спрашивает согласия на оплату, **врёт** (занижает при смене модели стадии и не
|
||
раскрывает, какая его часть — старые деньги), а один юнит может быть оплачен дважды. После пака
|
||
покупатель, берущий книгу частями, видит число, которое не занижает молча, признаётся, какая его
|
||
часть — старые деньги, и не платит второй раз за юнит, который уже двигал; а три гарантии, которые
|
||
сегодня держатся только на честном слове, держатся тестом и записью в мутационном каталоге.
|
||
|
||
## Карта чтения — пять позиций, дальше только по их ссылкам
|
||
|
||
1. Шапка-таблица `docs/architecture/09-target-architecture.md` — что построено.
|
||
2. `backend/README.md` · `docs/architecture/03-implementation-notes.md` (через баннер).
|
||
3. `docs/architecture/15-money-path.md` — денежный путь целиком, включая §2 «Деньги ДВИЖКА».
|
||
4. Строки **232** и **197** единого бэклога (`docs/PROGRESS.md`).
|
||
⚠ **Строка 197 — УКАЗАТЕЛЬ, а не фикс-лист:** её собственный текст отсылает тело списка в
|
||
`docs/archive/PROGRESS-2026-08-17.md`, запись приёмки №18 (проверь: `grep -n '^| 197 ' docs/PROGRESS.md`).
|
||
Определения ФЧ-1 и ФЧ-4, которые ты исполняешь, продублированы ниже В ТЕЛЕ ЭТОГО ПРОМТА — читать
|
||
архив ради них НЕ надо. Если всё же захочешь дословный оригинал, законный вход ровно один и он
|
||
назван здесь: `sed -n '68p' docs/archive/PROGRESS-2026-08-17.md` (`grep -n 'ФЧ-1 (HIGH' docs/archive/PROGRESS-2026-08-17.md` → `68`).
|
||
Инструкции из архива НЕ исполняются — он источник ФОРМУЛИРОВКИ, приказ несёт этот промт.
|
||
5. Журнал решений, два номера грепом: **D39.150** (`grep -n '^## D39.150' docs/architecture/05-decisions-log.md` → `535`)
|
||
и **D39.181** (`grep -n '^## D39.181' docs/architecture/05-decisions-log.md` → `1712`).
|
||
|
||
## Состав — четыре пункта, в этом порядке
|
||
|
||
### 1. ФЧ-5 — ось МОДЕЛИ в числе согласия. Ратифицирован 17.08 (D39.150 п.1) и НЕ построен
|
||
|
||
**«Делай РОВНО так» — состав ратификации. D39.150 п.1 несёт ЧЕТЫРЕ обязательства, не три:**
|
||
|
||
1. **прайсить по модели, которую стадия резолвит СЕЙЧАС**, а не по той, что ответила тогда;
|
||
2. **при невозможности знать — округлять ВВЕРХ**;
|
||
3. **называть оговорку в тексте согласия**;
|
||
4. **обещание ТОЧНОСТИ снимается с провода.** Дословно из ноты: «Следствие: обещание точности
|
||
снимается с провода — комментарий „`status` не может назвать сумму, отличную от `translate`“ …
|
||
при исполнении ФЧ-5 **обязан быть заменён** честной формулой „оценка, ошибается вверх, вот чем“».
|
||
Контракт механизма после пака — **не точность, а НАПРАВЛЕНИЕ ошибки: «никогда не занизить молча»**;
|
||
завышение безопасно (оператор согласился на большее, чем заплатит), занижение — тот вред, ради
|
||
которого чинилась строка 181.
|
||
|
||
⚠ **Пункт 4 — это правка ТЕКСТА в двух живых местах, и оба надо снять, иначе ФЧ-5 придётся
|
||
переоткрывать** (класс «текст обещает больше числа» — ровно тот, ради которого заведён фикс-лист):
|
||
|
||
- `backend/internal/pipeline/status.go:217`=`can never quote a different number` — «…so status can never quote a different number than the
|
||
one translate enforces» (`grep -n 'can never quote a different number' backend/internal/pipeline/status.go` → `217`);
|
||
- `backend/internal/pipeline/reprice.go:24`=`NOT projected (like the content axis` — шапка файла: «NOT projected (like the content axis in
|
||
rebill.go): **ROUTING**. A row is priced by the model that ANSWERED, not by the one its stage resolves
|
||
to now» (`grep -n 'NOT projected (like the content axis' backend/internal/pipeline/reprice.go` → `24`).
|
||
Это заявление становится ЛОЖНЫМ ровно в тот момент, когда ты исполнишь пункт 1.
|
||
|
||
Нота помечает ФЧ-5 обязательным **до первого пере-прогона со сменой модели стадии** (D39.150 п.2).
|
||
Замер вреда из приёмки: **`$0.003640` против честных `$0.036400`** при `HistoricalRows=0`
|
||
(`grep -on '\$0.003640 против честных \$0.036400' docs/archive/PROGRESS-2026-08-17.md` → `68:...`).
|
||
|
||
⚠ **Проверь исходное состояние САМ и не бери с моих слов.** Противоречащая ратификации шапка — в
|
||
`reprice.go` (см. выше); шапка `rebill.go` про это НЕ говорит, там речь про `$0`-строку. Формулируй
|
||
по коду, который увидишь.
|
||
|
||
**«Решаешь сам и аргументируешь»:** форма хранения и проводки «модели, которую стадия резолвит сейчас»
|
||
в числе согласия; конкретная формула округления вверх при незнании; точные слова оговорки и обеих
|
||
заменяемых формул.
|
||
|
||
### 2. Строка 232, ВТОРАЯ половина — слот объёмного гранта
|
||
|
||
Первая половина (читающий метод `store.AnnouncedOnceKeys()`) исполнена 31.08. Живой остаток по строке:
|
||
**юнит, прерванный МЕЖДУ волнами (signature stop, денежный потолок, Ctrl-C), тратит слот объёмного
|
||
гранта повторно** — покупатель платит за N глав и получает меньше. Замер строки — **4 купленных юнита
|
||
→ 2 главы** (`grep -on '4 купленных юнита → 2 главы' docs/PROGRESS.md` → `175:...`). Разбор —
|
||
`backend/docs/MONEY_HONESTY_REPORT.md` §4.5 (`grep -n '^### 4.5' backend/docs/MONEY_HONESTY_REPORT.md` → `206`).
|
||
|
||
⚠ **Остатков в коде названо ДВА, а не один — и это НЕ одно и то же.** Докстринг, приземлённый тем же
|
||
коммитом, перечисляет их под заголовком «⚠ TWO RESIDUALS, named rather than implied»
|
||
(`grep -n 'TWO RESIDUALS' backend/internal/pipeline/volume.go` → `523`):
|
||
|
||
- **(1) конвейер, получающий ПЕРВУЮ редакторскую стадию**, двигает отгружающую волну с draft на edit,
|
||
и уже прочитанные юниты репортятся свежими: «closing it needs a record of what the shipping wave WAS,
|
||
which nothing stores today». **ВНЕ СКОУПА этого пака** — закрытие требует носителя того, чем была
|
||
отгружающая волна, а пак схему хранилища не трогает (см. ПОРЯДОК ДЕПЛОЯ). ⚠ Строка 232 считает свою
|
||
первую половину ИСПОЛНЕННОЙ, а §4.5 отчёта называет только слот — то есть остаток (1) живёт СЕГОДНЯ
|
||
только в этом докстринге. **Назови его в отчёте, чтобы он не умер молча вместе с паком.**
|
||
- **(2) слот гранта** — В СКОУПЕ, это и есть твой пункт 2.
|
||
|
||
**Закрытие 232 объявляется ТОЛЬКО по остатку (2).** Написать «строка 232 закрыта» без этой оговорки —
|
||
ошибка отчёта.
|
||
|
||
⚠ **«Делай РОВНО так» — ратифицированный ответ на развилку, которую строка 232 требует назвать в
|
||
промте.** Ключ анонса несёт ВОЛНУ (`grep -n 'unitOnceKey is the identity' backend/internal/pipeline/events.go`
|
||
→ `396`), значит «юнит отгружен» — факт per-wave, и надо решить, ПО КАКОЙ волне судить. Ответ есть и
|
||
он не новый механизм: **отгрузкой считается волна, владеющая ОТГРУЖАЮЩЕЙ (последней) стадией —
|
||
`finalStageWave`** (`grep -n 'finalStageWave is the wave that owns the SHIPPING' backend/internal/pipeline/snapshot.go`
|
||
→ `243`; сама функция — `247`). На редакторском конвейере это `edit`, на черновом-только — `draft`.
|
||
**Не draft-волна и не «любая»:** иначе черновой-только конвейер получит ось, которая НИКОГДА ничего не
|
||
считает отгруженным. Отступление от этого — пинг, не решение.
|
||
|
||
**«Решаешь сам и аргументируешь»:** где именно вычитается уже потраченный слот, как это переживает
|
||
рестарт, и что происходит с частично двинутым юнитом.
|
||
|
||
⚠ **Оговорка веса, проверь её:** платформа сегодня продаёт денежным потолком (`--ceiling-usd`), а
|
||
`--max-units` не передаёт вовсе — то есть вред пока не доезжает до пользователя ЧЕРЕЗ платформу. Это
|
||
меняет приоритет, но не отменяет дефект. Проводка `--max-units` в платформу — отдельный ГЕЙЧЕНЫЙ пункт
|
||
очереди, не твой (`grep -n 'Проводка .--max-units. в платформу остаётся ГЕЙЧЕНОЙ' docs/PROGRESS.md` → `19`).
|
||
|
||
### 3. ФЧ-4 — раскрытие «часть суммы — старые деньги»
|
||
|
||
⚠ **У ФЧ-4 ДВЕ половины. Закрыт = ОБЕ.** Дословно из фикс-листа: «раскрытие „часть суммы — старые
|
||
деньги“ не доезжает до `status`/`--json` (`HistoricalRows` теряется на границе `status.go`), **а также**
|
||
второй операторский текст отказа (`--accept-rebill`) цитирует пере-прайсенное число без basis».
|
||
|
||
- **(а)** `HistoricalRows` теряется на границе отчёта: `rebillOutcome` возвращает
|
||
`(basis, units, usd, outputUnits)` и роняет его (`grep -n 'rebillOutcome' backend/internal/pipeline/status.go`),
|
||
в `StatusReport` соответствующего json-тега нет. Покупатель не может отличить новую трату от уже
|
||
оплаченной.
|
||
- **(б)** текст отказа по названному потолку `--accept-rebill=<usd>` печатает `proj.USD` **без**
|
||
`projectionBasis` и **без** `HistoricalRows`, тогда как оба других текста согласия их несут
|
||
(`grep -n 'caps consent at' backend/internal/pipeline/rebill.go` → `425`, ветка
|
||
`r.AcceptRebill.Capped`; для сравнения `grep -n 'func projectionBasis' backend/internal/pipeline/rebill.go` → `305`).
|
||
|
||
⚠ **Инвариант, которому подчиняется этот пункт — закон раскрытия D39.181 п.1** (ратифицирован словом
|
||
владельца 31.08, самая свежая норма зоны): четыре обязанности — **не молчать · не называть причину,
|
||
которую не сравнивал · ФИГУРА ЕДЕТ С БАЗИСОМ · КАНАЛ НАЗНАЧАЕТ ПОТРЕБИТЕЛЬ**. Ты добавляешь денежную
|
||
фигуру на опубликованную поверхность — обе выделенные обязанности про твой случай прямо.
|
||
⚠ **И не рассчитывай, что сборка тебя поправит:** спроектированный гейт Г1 (реестр раскрытия +
|
||
рефлективный конформанс-тест), который поймал бы новое поле без записи, **НЕ построен** —
|
||
`grep -rn 'Consumers\b' backend/internal --include=*.go | wc -l` → `0`. Компилятор молчит.
|
||
|
||
**«Делай РОВНО так»:** обе половины, и фигура едет с базисом. **«Решаешь сам и аргументируешь»:** форма
|
||
раскрытия исторических строк на проводе и в операторском тексте (имя поля, форма basis, что печатать
|
||
при `HistoricalRows=0`).
|
||
|
||
### 4. ФЧ-1 — посадки на гарантии, чьи мутации ПЕРЕЖИВАЮТ зелёную батарею
|
||
|
||
⚠ **«Делай РОВНО так» — ограничь ТРЕМЯ, и вот они поимённо.** D39.149 п.5
|
||
(`grep -n '^## D39.149' docs/architecture/05-decisions-log.md` → `523`; сам пункт — `533`) говорит «Три HIGH фикс-листа —
|
||
не дефекты поведения, а НЕПРИБИТЫЕ гарантии: мутации переживали зелёную батарею», но поимённо называет
|
||
ровно ОДНУ; остальные две живут только в теле фикс-листа. Поэтому все три вписаны сюда, и брать надо
|
||
ЭТИ, а не изобретать свои:
|
||
|
||
1. **Снятие фильтра по книге в `CheckpointUsageForBook`** — `WHERE j.book_id = ?` не валит ни store-,
|
||
ни денежные pipeline-тесты (`grep -n 'func (s \*Store) CheckpointUsageForBook' backend/internal/store/ledger.go`
|
||
→ `367`, сам фильтр — `371`). Единственная защита от того, чтобы деньги ЧУЖОЙ книги вошли в число
|
||
согласия. **Воспроизведено оркестратором ЛИЧНО.** Существующий тест
|
||
(`internal/store/ledger_test.go:10`=`func TestCheckpointUsageForBookReturnsInsertionOrder`) пинит только
|
||
порядок вставки.
|
||
2. **Ключ ячейки можно лишить `chunk_idx`** — обход начнёт съедать деньги соседнего чанка (во всех
|
||
фикстурах глава = один чанк, поэтому никто не краснеет).
|
||
3. **Ветка пометки «строка не пере-оценена» не ловится на продовом пути** — `fromHistory` из
|
||
`(rp *repricer) usd` (`grep -n 'func (rp \*repricer) usd' backend/internal/pipeline/reprice.go` → `113`).
|
||
|
||
⚠ **Честность про источник:** гарантия (1) воспроизведена приёмкой лично, а **(2) и (3) приняты СО СЛОВ
|
||
мутационной линзы** — приёмка №18 записала это в свою секцию «что НЕ проверено». Значит первый твой шаг
|
||
по каждой из них — **воспроизвести мутацию и увидеть ЗЕЛЁНУЮ батарею**; если мутация на самом деле
|
||
краснеет, гарантия уже прибита, и это **находка**, а не повод молча заменить её своей.
|
||
|
||
⚠ **Механизм посадок в зоне УЖЕ ПОСТРОЕН — не пиши четвёртый одноразовый харнесс.**
|
||
`backend/cmd/tmmutate` + каталог `backend/cmd/tmmutate/mutations.json` (**73** записи:
|
||
`python3 -c "import json;print(len(json.load(open('backend/cmd/tmmutate/mutations.json'))))"` → `73`).
|
||
Его собственный докстринг объясняет, зачем он в репозитории: «Two packs and one acceptance in a row have
|
||
each written this harness from scratch in a scratch directory, and it died with the session every time».
|
||
Денежного пути в каталоге сегодня НЕТ вовсе — `grep -c 'reprice.go\|rebill.go\|volume.go\|ledger.go' backend/cmd/tmmutate/mutations.json`
|
||
→ `0`, то есть твои три гарантии туда и просятся.
|
||
|
||
⚠⚠ **ЛОВУШКА РЕПОЗИТОРИЯ, читай прежде чем запускать:** `-root` **без дефолта**, и копия дерева — **не
|
||
предложение**. Работать ТОЛЬКО на копии:
|
||
|
||
```
|
||
cp -a backend /tmp/mut/backend && cd /tmp/mut/backend
|
||
go run ./cmd/tmmutate -root . # весь каталог
|
||
go run ./cmd/tmmutate -root . -id A-lock-arbiter # выборочно
|
||
go run ./cmd/tmmutate -root . -logs /tmp/mutlogs # сохранить полный вывод тестов
|
||
```
|
||
|
||
Причина в докстринге прямая: однажды посадка просидела в ОБЩЕМ дереве сорок минут после таймаута, и
|
||
независимый ревьюер намерил по нему несуществующий дефект. Здесь параллельные сессии — это цена чужой
|
||
работы.
|
||
|
||
**«Делай РОВНО так»:** ровно три гарантии выше · каждая заводится **ЗАПИСЬЮ в `mutations.json`**, а не
|
||
только тестом · `tmmutate` гоняется на копии. **«Решаешь сам и аргументируешь»:** форма самих посадок
|
||
(какую строку и как ломать), уровень теста (store / pipeline / оба), формулировка `why` в каталоге.
|
||
|
||
⚠ Это ПОСЛЕДНИЙ пункт: он берётся, если после первых трёх осталось время. Не превращай в бесконечный
|
||
список — если времени хватило только на одну гарантию, это законный исход, назови его в отчёте.
|
||
|
||
## Границы — что НАМЕРЕННО не берём
|
||
|
||
- **Строка 160 «структура глав, Этап 0»** — хотя слово владельца 15.08 ставит её ближайшим паком и её
|
||
блокер снят 30.08 — строки 231 и 236 в таблице БОЛЬШЕ НЕТ
|
||
(`grep -n '236 сужена D39.175' docs/PROGRESS.md` → `256`). Причина техническая и она в ПОРЯДКЕ ДЕПЛОЯ ниже: строка требует бампа
|
||
**формы манифеста**, а параллельно идёт платформенный пак. Берётся отдельно, со стоп-миром.
|
||
- **Читающая сторона банка — гейты РАЗНЫЕ, и их надо различать** (проверено по ячейкам:
|
||
`for n in 221 224 226 228 230; do grep "^| $n " docs/PROGRESS.md | awk -F'|' '{print $4" | "$5}'; done`):
|
||
- **221** — гейт «разморозка фронта», то есть слово владельца. Вопрос вынесен ему отдельно
|
||
⚠ (следа этого вопроса в репозитории нет — если тебе это важно для планирования, спроси, а не считай фактом).
|
||
- **224** — «держит экран подписи вместе с 221», зона «бэкенд + платформа». **Не берём: ресурс пака.**
|
||
- **226** — «диагностики нет вовсе». **Не берём: ресурс пака.**
|
||
- **228** — гейт «ЗАКАЗ по читающей стороне банка», то есть отдельный заказ оркестратора, а не слово
|
||
владельца. **Не берём: гейт — отдельный заказ.**
|
||
- **230** — зона «бэкенд + контракт». **Не берём: пак версию контракта не двигает** (см. ПОРЯДОК ДЕПЛОЯ).
|
||
- **Остальная свободная работа зоны в этот пак НЕ входит:** строки **246** (СРОЧНО — две копии полосы
|
||
отказов обещают разное), **247**, **233**, **229**, **141**-остаток, **131**. Из свободной очереди пак
|
||
берёт ровно **232** и **197** (`grep -n 'Свободная работа зоны' docs/PROGRESS.md` → `254`).
|
||
- **Следующий платный замер** — не в этом паке: у его оси «эффорт off против low» не разрешено
|
||
предусловие, и носитель предусловия назван — **строка 237(б)**, вендор-сверка маппинга эффорта
|
||
`deepseek-v4-pro` (`grep -n '^| 237 ' docs/PROGRESS.md` → `178`; реестр
|
||
`docs/architecture/13-tech-debt-anchors.md` §Б-108). По гардрейлу владельца закрывается ТОЛЬКО
|
||
вендор-докой. До решения владельца замер не заказывается.
|
||
|
||
## ⚠ ПОРЯДОК ДЕПЛОЯ — почему пак безопасен параллельно платформе
|
||
|
||
**Пак НЕ меняет форму манифеста, схему хранилища и версию контракта.** Понадобилось — **стоп и пинг**,
|
||
не «сделаю аккуратно». Почему это жёстко:
|
||
|
||
- **Форма манифеста БЕЗОПАСНОГО ПОРЯДКА НЕ ИМЕЕТ.** Гейт платформы — строгое равенство ОДНОЙ константе:
|
||
`if m.Version != KnownManifestVersion` (`grep -n 'if m.Version != KnownManifestVersion' platform/internal/ingest/manifest.go`
|
||
→ `112`; сама константа — `grep -n 'KnownManifestVersion = ' platform/internal/ingest/manifest.go` →
|
||
`88`, `"tm-manifest-v2"`). Окна из двух версий НЕТ. Поэтому «платформа первой» так же смертельно, как
|
||
«движок первым»: выкатив любую сторону в одиночку, ты отправляешь КАЖДУЮ новую книгу в отказ
|
||
(`ReasonParserUnavailable`, который жжёт бюджет попыток). Бамп формы = **стоп-мир** либо специально
|
||
построенное временное окно двух версий. ⛔ **Рантбук зоны платформы советует обратное:**
|
||
`platform/deploy/README.md:213`=`сначала платформа, потом движок`. По коду этот совет опасен —
|
||
дефект чужой зоны, он передан платформенному паку; тебе он важен тем, что «платформа первой» НЕ
|
||
является безопасным обходом, если ты вдруг упрёшься в форму манифеста.
|
||
- **Схема хранилища — «движок первым»**, и это документировано: движок первым → `tmctl migrate` по
|
||
каждой книге до прогонов → и только потом платформа (D39.158 п.6,
|
||
`grep -n 'движок первым' docs/architecture/05-decisions-log.md` → `715`).
|
||
- **Версия контракта** — пак её не двигает. Твоё новое поле в `status --json` аддитивно и безопасно:
|
||
платформа читает отчёт аллоулистом (`ingest.StatusReport`, `runner/engine.go` «decodes the allowlisted
|
||
subset»), неизвестные поля игнорирует. Это ПРОВЕРЕНО, но проверь и ты — клейм «зоны независимы по
|
||
коду» держится именно на этом.
|
||
|
||
## Свобода и её разметка — сводка
|
||
|
||
Каждый пункт состава размечен внутри себя; здесь только свод, тело — выше.
|
||
|
||
| Пункт | «Делай РОВНО так» (отступление = пинг) | «Решаешь сам и аргументируешь» |
|
||
|---|---|---|
|
||
| 1 ФЧ-5 | четыре обязательства D39.150 п.1, включая снятие обещания точности в ОБОИХ живых местах | форма проводки текущей модели, формула округления вверх, слова оговорки |
|
||
| 2 строка 232 | ось = `finalStageWave`; закрытие объявляется только по остатку «слот»; остаток «первая редакторская стадия» — вне скоупа и НАЗЫВАЕТСЯ в отчёте | где вычитается потраченный слот, как переживает рестарт |
|
||
| 3 ФЧ-4 | обе половины; фигура едет с базисом (D39.181 п.1) | форма раскрытия на проводе и в тексте отказа |
|
||
| 4 ФЧ-1 | ровно три названные гарантии; запись в `mutations.json`; `tmmutate` только на копии | форма посадок, уровень тестов, текст `why` |
|
||
|
||
Плюс общее «ровно так»: **порядок пунктов** · **границы выше** · **три запрета из ПОРЯДКА ДЕПЛОЯ**.
|
||
Всё, что здесь не названо, — твоё решение с аргументом в отчёте. Мои приоры **опровергаются аргументом
|
||
или замером**; неопровергнутое исполняется как написано.
|
||
|
||
## Мандат самопроверки — исполнением
|
||
|
||
`make battery` — **не отчёт, а предусловие** (проверено на этой машине: `cd backend && make battery` →
|
||
EXIT=0, `golangci-lint` `0 issues`). Зелёная батарея НИЧЕГО не доказывает про твою работу — весь смысл
|
||
пункта 4 в том, что мутации её переживают.
|
||
|
||
**Обязательны, и каждое — с ПРЕДЪЯВЛЯЕМЫМ АРТЕФАКТОМ в отчёте:**
|
||
|
||
1. **Дифф `^func Test` исполнением, а не памятью.** Команда:
|
||
`grep -rn '^func Test' backend --include=*_test.go | wc -l` (на HEAD этой смены → `1083`) — и
|
||
пофамильный дифф имён до/после. **Удалённых имён должно быть 0**; если не 0 — назвать каждое и
|
||
объяснить.
|
||
2. **Собственные адверсариальные посадки ВНЕ трёх гарантий пункта 4** — механизм тот же `tmmutate` на
|
||
копии дерева. Артефакт: **красный вывод на каждую посадку**, и отдельно — список посадок, которые
|
||
батарея ПЕРЕЖИЛА (это и есть находки).
|
||
3. **Отдельный проход по СВОЕЙ ГОТОВОЙ работе свежим контекстом.** **Субагенты разрешены явно; модель
|
||
задавай ИМЕНЕМ и знай, сколько их у тебя работает** (Fable 5 — рекомендация одного-двух, не потолок;
|
||
веер под предмет выбираешь ты).
|
||
⚠ **Артефакт прохода — СПИСОК НАХОДОК С ДИСПОЗИЦИЯМИ в отчёте.** «Прошёл, находок нет» отчётом НЕ
|
||
является: ноль находок обосновывается тем, ЧТО ИСКАЛОСЬ и какими командами.
|
||
|
||
**Оси ревью, которые я называю уязвимыми ИМЕННО В ЭТОМ ПАКЕ** (1–3 хватит; **вправе заменить с
|
||
аргументом**, если найдёшь уязвимее):
|
||
|
||
1. **Направление ошибки.** Округление ВВЕРХ ложится на путь, где старое поведение занижало. Классика
|
||
этого места — **двойной счёт** (округлили и там, и там) и **перелёт порога согласия** (число выросло
|
||
настолько, что гейт спрашивает там, где раньше не спрашивал, или наоборот).
|
||
2. **`HistoricalRows` на новой границе** — не теряется и не удваивается; текст отказа и `--json` говорят
|
||
ОДНО И ТО ЖЕ число с одним и тем же базисом.
|
||
3. **Слот гранта на черновом-только конвейере** — `finalStageWave` на нём равен `draft`; убедись
|
||
исполнением, что ось не выродилась в «никогда ничего не отгружено».
|
||
|
||
⚠ **Особо недоверчиво к `usd()`:** его собственный докстринг называет вывод принадлежности к поколению
|
||
«an inference, not an identity — **the one place in here worth distrusting**» и перечисляет ДВЕ
|
||
предпосылки, каждая из которых ломается (`sed -n '86,112p' backend/internal/pipeline/reprice.go`). Твоя
|
||
правка ложится прямо на него.
|
||
|
||
⚠ Запрет подгонки тестов — `CLAUDE.md` (D39.183). Край, который тебе понадобится: **этот промт
|
||
заказывает смену поведения в пунктах 1 и 3** (обещание точности снимается, текст отказа меняется), и
|
||
протухший под неё тест правится как обслуживание — но правка ОБЪЯВЛЯЕТСЯ в отчёте: что изменилось,
|
||
какой тест это описывал, куда уехала гарантия. Нет в промте и нет ратификации — **пинг**.
|
||
|
||
⚠ Перед отчётом **сверь каждый клейм с результатом инструмента ЭТОЙ сессии**. Последний абзац — план
|
||
или обещание? Сделай сейчас.
|
||
|
||
## Отчёт
|
||
|
||
**Записка-план ДО работы** — эхо-протокол старта, ≤10 строк «скоуп · инварианты · не-делать», в секцию
|
||
«Бэкенд» `docs/PROGRESS.md`. Первым действием, до кода.
|
||
|
||
**Комплектность против заказа — механически:** пройди по четырём пунктам состава и по таблице разметки и
|
||
отчитайся ПО КАЖДОМУ. ⚠ Эта тема трижды проваливалась на том, что исполнялся первый пункт, а нумерованный
|
||
остаток бросался.
|
||
|
||
**Итог — туда же, и «заявление = команда»:** каждое число и каждая категорика — **с командой получения**,
|
||
которая это число реально печатает. Приёмка пере-ранит твои команды; команда, печатающая «ok» вместо
|
||
числа, считается отсутствующей.
|
||
|
||
**Обязательная секция «Что НЕ удалось и что НЕ проверено».** ⚠ «Не проверено» ≠ «опровергнуто» — это
|
||
РАЗНЫЕ исходы, и **третий законен**: «взялся, не смог, вот где встал» — полноценный результат смены, а не
|
||
провал. Сюда же обязательно попадает остаток «первая редакторская стадия» (пункт 2) и любая гарантия
|
||
ФЧ-1, до которой не дошли руки.
|
||
|
||
**Конфликт промта с кодом или доками — ПИНГ через владельца, не интерпретация.** И у тебя есть **право
|
||
сказать «этого делать не надо»** с аргументом: сессия, приносящая развилку вместо тихой девиации, делает
|
||
правильно. Этот промт писан по коду на HEAD своей смены; код первичен, и если ты видишь другое — это
|
||
находка, а не твоя ошибка.
|
||
|
||
## Прямой канал
|
||
|
||
Механизм целиком — `CLAUDE.md`, «Связь между сессиями»: свой блок в `/tmp/textmachine-channel`, сверка
|
||
с `ListAgents` перед отправкой, канала нет — нормальный случай, сессии подряд не опрашивать. Что
|
||
добавляет этот пак: **эхо-записку отправь ПЕРВЫМ действием по адресу оркестратора** — это и есть
|
||
проверка канала.
|