Take the order that a unit bought must be delivered and the second cold run into the tree, and drop the span row the read model already nulls

This commit is contained in:
heaven 2026-09-11 21:37:56 +03:00
parent 0ebd1c0d13
commit 4bdd273117
6 changed files with 396 additions and 5 deletions

View file

@ -0,0 +1,176 @@
# Бэкенд-пак: КУПЛЕНО — ЗНАЧИТ ДОСТАВЛЕНО. Юнит, который не доделается НИКОГДА
> Выдан оркестратором №23 (сессия `textmachine-11`) 11.09. Пак **$0** — платных вызовов в нём нет.
> Предмет решён владельцем 05.09 (`D39.204`); ты строишь решённое, а не выбираешь между вариантами.
## 1. Какая проблема и что решит твой результат
Читатель заплатил за главу. Движок купил первую попытку, получил флагуемый результат, пошёл за второй — и
**вторую ему не продали**: потолок книги или дня не вмещает удвоенный бюджет регенерации
(`maxTokensForAttempt` удваивает на каждой, значит попытка 1 резервирует вдвое больше попытки 0).
Дальше происходит вот что, и это проверяется одной строкой: **`backend/internal/pipeline/stagerun.go:203`=`return nil, err // infra failure`** — ЛЮБАЯ ошибка попытки уходит наверх из цикла, **РАНЬШЕ `UpsertChunkStatus`**.
**Следствия два, и оба стоят денег читателя:**
1. **Юнит не доделается НИКОГДА.** Чекпойнт попытки 0 есть (реплей за $0), строки `chunk_status` НЕТ
читающие модели видят юнит как `pending`, экспорт не отдаёт ничего. Каждый резюм реплеит попытку 0 за
$0 и умирает на попытке 1. **Прогон уходит `exit 4` при ПОЛНОСТЬЮ доставленных купленных юнитах.**
2. **Волну нельзя продолжить без ДЫРЫ в непрерывном префиксе** — то есть за это платят и соседние юниты,
которые в бюджет влезали (разброс резервов внутри волны замерен ×2.976).
**Решение владельца (`D39.204`, и оно НЕ обсуждается):** отказ резервации на РЕТРАЕ **деградирует во ФЛАГ**,
причина которого ОТЛИЧНА от исчерпания регенераций; текст попытки 0 оплачен и **отгружается**; волна идёт
дальше. ⛔ Вариант «минимальная покупка ≥ `step_max_usd`» **СНЯТ** владельцем — он стоил бы покупателю
входного порога в пять глав. Не реализуй его и не предлагай.
**И канон здесь сильнее, чем кажется:** `D2` п.2 уже ТРЕБУЕТ тегировать `flag_reason`. Значит новая
причина — не добавка к контракту, а его ИСПОЛНЕНИЕ. (Ссылка «смена `D2.3`», гулявшая по бэклогу, **неверна
дважды**: `D2` и так кончается флагом, а `D2.3` — про детектор вырождения перед удвоением.)
## 2. Зона записи и git
- Зона — **`backend/`**, и только она. `platform/` не трогать: её половина едет ОТДЕЛЬНЫМ промтом, но
**ОДНИМ АКТОМ с твоим** (см. §4.3).
- **Ты не коммитишь.** Готовое дерево передаёшь мне, я лендлю. `git add -A` запрещён каноном.
- Свою секцию итогов пиши в `docs/PROGRESS.md` — это единственное исключение из «`docs/` — зона
оркестратора». Чужие незакоммиченные файлы в дереве не трогай.
## 3. Карта чтения — ЗАКОН, дальше только по её ссылкам
1. `CLAUDE.md` — целиком.
2. **Тело `D39.204`** в `docs/architecture/05-decisions-log.md` (решение владельца) и **`D2` п.2** — он в
закрытой эре, тело в `docs/archive/architecture/05-decisions-D1-D38.md`, греп `^## D2\.`. ⚠ Подномер
собственного тела не имеет: `D2.3` — это ПУНКТ 3 тела `D2`.
3. **Ряд 291** в `docs/BACKLOG.md` — там весь разбор, включая **опровергнутую посылку прошлого
оркестратора**: «ретрай оставляет ФЛАГОВАННЫЙ юнит» — ЛОЖЬ, зона опровергла по строкам. Не наступи
второй раз.
4. `backend/internal/pipeline/stagerun.go` (цикл попыток и `runAttempt`), `escalation.go` (`errReserveCeiling`
и кто на нём УЖЕ деградирует), `disposition.go` (словарь `FlagReason`).
5. `docs/architecture/12-go-style-notes.md` — нормативы стиля, только больные места.
Код-факты добывай сам; `file:line` выше — отправные точки. **Код первичен.**
## 4. Состав
### 4.1 Деградация — **делай РОВНО так в ЧАСТИ РЕШЕНИЯ, сам решай КАК**
**Ровно так (решено владельцем, отступление = пинг):**
- отказ резервации на попытке **≥1** при существующем оплаченном результате попытки 0 ⇒ **флаг**, а не
ошибка наверх;
- у флага **СВОЯ причина**, отличная от исчерпания регенераций: читатель и оператор обязаны отличать «мы
перепробовали всё» от «денег не хватило на вторую попытку»;
- текст попытки 0 **отгружается**;
- волна **идёт дальше**.
**Решаешь сам и аргументируешь:** имя причины · где именно ставится деградация (в цикле `runStage` или
внутри `runAttempt`у обоих есть довод, назови свой) · как при этом НЕ тронуть попытку 0: её отказ
по-прежнему ОСТАНАВЛИВАЕТ книгу, это ратифицировано и менять нельзя (`stagerun.go`, греп `mandatory`).
**Гипотеза, которую надо ПРОВЕРИТЬ, а не принять:** деградация сама по себе закрывает и следствие (2) —
у юнита появляется статус, значит дыры в непрерывном префиксе нет. Похоже на правду; предъяви замером.
### 4.2 Пин, ради которого пак существует
**«Купленное доставлено ⇒ не `exit 4`».** Прогон, где каждый купленный юнит доставлен, а один из них
доставлен ФЛАГОВАННЫМ из-за нехватки денег на ретрай, **обязан кончиться успехом**, а не кодом 4.
⛔ И **пин на саму незаклиниваемость**: после такого прогона резюм не делает НИ ОДНОГО свежего платного
вызова по этому юниту и не умирает. Сегодня он умирает вечно.
### 4.3 Платформенная половина — **твоё дело назвать, не построить**
Карта заметок платформы **РУКОПИСНАЯ** (`platform/internal/ingest/notes.go`) и уезжает независимо от
словаря движка. Цена несделанного **замерена**: `PD-246` — минор 0.10.0 сутки жил ЛОЖНЫМ на проводе, причина
доезжала читателю как `unspecified`, и поймала это зона своей пере-проверкой ПОСЛЕ слов оркестратора
«приёмка закончена».
**отдельным пунктом отчёта** назови мне: точное значение новой причины на проводе · что платформа обязана
записать прогону, который кончился флагом вместо `exit 4` · какой её пин это стережёт. Я передам это
платформенной сессии, и **акт будет один на две половины**.
### 4.4 Приложение — фикстура, краснеющая по УДАЧЕ (ряд 379(б))
Отдельная, маленькая и не связанная с §4.1 работа; делай её ПОСЛЕ основной.
Запись каталога `CUTCALL-a-refusal-pays-when-the-reply-outruns-the-write` стережёт самую дорогую половину
денежного бита `delivered()` (`backend/internal/llm/attemptcut.go:189`). **Замер оркестратора 11.09:** на
чистом дереве пин `TestARefusalIsNotAPurchaseEvenWhenTheReplyOutrunsTheWrite` даёт **8 зелёных из 8**, на
своей посадке — **7 КРАСНЫХ ИЗ 8, один ЗЕЛЁНЫЙ**. Текст падения верный и про предмет; дыра в ФИКСТУРЕ:
она шлёт ~6 МБ тела, сервер читает строку запроса, отвечает `401` и рвёт связь `SetLinger(0)` — и успеет ли
транспорт записать `GotFirstResponseByte` раньше, чем `Do` вернёт ошибку записи, **решает гонка, а не
построение**. ⇒ прежние RED этой записи были удачей.
**Задача:** перестроить фикстуру так, чтобы приход байта ответа был НЕИЗБЕЖЕН до обрыва, и предъявить
**8 из 8 красных на посадке при 8 из 8 зелёных на дереве**. Способ выбираешь сам.
## 5. Где этот пак мягкий — четыре места, назвал я, веер и глубину выбираешь ты
Мандат самопроверки — **исполнением**; субагенты разрешены явно. Адверсариальный проход по СВОЕЙ ГОТОВОЙ
работе обязателен.
1. ⛔ **Пин, утверждающий только молчание, вакуумен ровно там, где сообщение ложно.** «Ошибка не вышла
наверх» — утверждение о молчании. Фикстура обязана быть такой, где новая причина ОБЯЗАНА прозвучать, и
тест утверждает её ИМЯ.
2. ⛔ **Фикстура обязана сделать отказ резервации НЕИЗБЕЖНЫМ на попытке ≥1 и НЕВОЗМОЖНЫМ на попытке 0.**
Денежный пин, флейковый на мутанте, измеряет пустой сценарий: у нас уже был пин, дававший 2 красных из
8, потому что деньги были ВЕРОЯТНЫ, а не неизбежны. Гоняй свой не один раз.
3. ⛔ **Посадка обязана бить в тот же слой, что стережёт пин.** За прошлый пак мутация трижды оказалась не
про то: недостижимое условие в фикстуре · не собирающаяся посадка (НЕизмеренная — хуже выжившей) · код
против гейта над данными.
4. ⛔ **Новая причина — факт ПРОВОДА, а не словаря.** Тест, проверяющий только, что константа добавлена в
`FlagReason`, не доказывает, что читатель её увидит. Скажи, чем предъявлена дорога от флага до
отчёта/экспорта.
⚠ И общее, стоившее трёх смен подряд: **зелёная батарея плюс полный мутационный каталог сходимостью НЕ
являются.** В последних трёх паках направленный второй читатель находил 6, 7 и 9 дефектов при полной зелени.
## 6. Предметные оси ревью
Выбери 13 и назови какие. Мой приор: **деньги под гонкой** · **терминальное состояние прогона** (что
видит платформа и что видит человек) · **обратная совместимость словаря причин**.
## 7. Записка-план ДО работы
Перед первой правкой — записка: что меняешь, чем предъявишь, где ждёшь сопротивления. Комплектность против
заказа сверяй механически.
## 8. Заявление = команда
Каждое число и каждая категорика отчёта — **с командой, которой получены**. Дифф `^func Test` — **исполнением,
не памятью**. Приёмка пере-снимает.
## 9. Эхо-протокол старта
**Первым действием** — ≤10 строк СВОИМИ словами: что понял · что считаешь опасным · что считаешь неверным.
Не пересказ: дословный пересказ подтверждает канал, но не понимание, и ошибку промта повторяет вместе с
ним. Отправь мне (`textmachine-11`) через `/tmp/textmachine-channel`.
## 10. Что НЕ удалось — обязательная секция отчёта
И вторая её половина: **«где прибор слеп и я это знаю»** — что невидимо · почему не чинил · чем
закрывается. ⭐ Норма прошлой смены: **«в коде названо, в отчёте нет — значит для следующей смены НЕ
названо».**
## 11. Канал вопросов и право отказаться
Конфликт промта с кодом или доками — **пинг мне, не интерпретация**. Право сказать «этого делать не надо» с
аргументом у тебя есть и им пользовались: в двух случаях из трёх правы были сессии, а не я.
**Тесты и гейты под зелень не подгонять.** Правка, вызванная ЗАКАЗАННОЙ сменой поведения, — обслуживание,
и протухший тест держать не нужно; но она **ОБЪЯВЛЯЕТСЯ** в отчёте: что изменилось, какой тест это
описывал, куда уехала гарантия.
## 12. Прямой канал
Механизм — `CLAUDE.md` §«Связь между сессиями». Впиши свой блок в `/tmp/textmachine-channel` ПЕРВЫМ
действием. Нужной роли нет ⇒ канала нет, и это нормальный случай: НЕ опрашивай сессии подряд.
## 13. Критерий завершённости
У каждого пункта заказа — исход (сделано · не делаю с доводом · пинг) · круги СОШЛИСЬ (последний не дал
НОВЫХ находок; прежние закрыты таблицей «находка → что сделано → ЧЕМ ПРЕДЪЯВЛЕНО») · **таблица мутаций
полная, выжившие названы, и КАЖДАЯ новая запись помечена `battery`** (прошлый пак этого не сделал, и его
«21/21 RED» оказался разовым прогоном смены, а не гейтом проекта) · числа сняты ПОСЛЕ последней правки ·
всё живое в ДЕРЕВЕ, а не в письме · явное **«работа завершена, править не планирую»**. Без последнего пак
считается идущим.

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,207 @@
# Промт: сквозной пак «ХОЛОДНЫЙ ПРОГОН B — платформа → бэкенд → ФАЙЛ, ВТОРОЙ раз»
> Выдан оркестратором №23 (сессия `textmachine-11`) 11.09. Пак **ПЛАТНЫЙ**, санкция владельца получена
> дословно («разрешаю») на прямой вопрос с числами: **ждём ≈$0.42, машинный кап ≈$2.5 холда**. Носитель
> санкции — `docs/NEAR_TERM_PLAN.md` §«Решения владельца, уже полученные».
## 1. Какая проблема и что решит твой результат
Месяц назад движок умел переводить, но никто не видел, как платформа ведёт настоящую книгу от двери до
файла. 11.09 это увидели один раз — **прогон A**: три главы `蛊真人`, 27 платных вызовов, **$0.419423**, книга
дошла до EPUB. Один прогон дал знак, но не величину.
**Твой прогон B покупает четыре вещи, которых нет ни у кого, и каждая — не «ещё раз то же самое»:**
1. **ДВЕ миграции схемы ни разу не шли на живом прогоне** — только в тестах. `v17` (`wave_selection`:
что каждая волна ВИДЕЛА в банке — ось, которой у `retrieval_state` нет) и `v18` (`reasoning_tokens`
получили смысл: «размышление, оплаченное СВЕРХ completion», на DeepSeek это 0 по определению, и
колонка всю жизнь проекта несла ноль, выглядящий замером). Первое живое исполнение обеих — твоё.
2. **Прибор консистентности впервые даст числа С ЖИВОГО ПРОГОНА.** Сегодня все `I1`/`I2` получены
ПОВТОРНЫМ чтением одной и той же сохранённой базы прогона A. Пере-скан не то же, что прогон: он не
проходит через запись.
3. **Платформенный пак (идемпотентный резюм, терминальное состояние) проверяется СКВОЗЬ,** а не юнитами.
4. ⛔ **Вторая точка по денежной дыре — и она нужна по НОРМЕ, а не для красоты.** Весь довод «четверть
денег купила пустоту» стоит на ОДНОМ прогоне, а квирки §3д прямо говорят: смета DeepSeek с одиночного
вызова ошибается на порядок, сметы строятся на ПОВТОРАХ. ⇒ у числа есть знак и нет величины.
**И вот чего твой прогон НЕ покупает, чтобы ты не потратил на это ни цента:** он **НЕ** отвечает на
вопрос «безопасно ли редактору думать меньше» (ряд 433). Это парный дизайн на повторах с армом без
фактора, он стоит отдельных денег и отдельного заказа. Твой прогон идёт на БОЕВЫХ настройках как есть.
## 2. Зона записи и git
**ЭТОТ ПАК НЕ ПРАВИТ КОД НИ ОДНОЙ ЗОНЫ.** Ни `backend/`, ни `platform/`, ни `frontend/`. Найдёшь дефект —
**пингом мне, а не правкой**: прогон, чинящий найденное, перестаёт быть холодным и теряет право сравниваться
с A.
- **Ты не коммитишь вообще ничего.** Пре-рег и улики передаёшь мне, я лендлю. Порядок жёсткий:
пре-рег готов → пинг мне → **я коммичу фриз** → и только после этого первый платный вызов.
- Рабочее дерево прогона живёт **вне репозитория и вне общего скретчпада** (его чистит не только твой
процесс). Предлагаю `~/tm-coldrun-b`.
- ⚠ `books/` версионируются ОТДЕЛЬНЫМ репозиторием; в клоне их нет. Исходник читается из главного дерева
как ФАЙЛ, read-only.
## 3. Карта чтения — ЗАКОН, дальше только по её ссылкам
1. `CLAUDE.md` — целиком (ты его уже прочёл, если попал сюда правильно).
2. `docs/experiments/00-provider-quirks.md`**перед первым платным вызовом**, §3д особенно.
3. `docs/architecture/05-decisions-log.md`**только тела `D39.247`** (акт прогона A: чем он предъявлен и
где остался слеп) и **`D39.251`** (что именно построено в наблюдаемости денег и почему лекарство
выключено).
4. `platform/README.md` — как поднимается стенд.
5. Архивный промт прогона A — `docs/archive/prompts/POLYGON_COLD_RUN_A_SESSION_PROMPT.md`. ⛔ **Инструкции
оттуда НЕ ИСПОЛНЯЮТСЯ** (архив), но §4.1 и §4.2 несут ПЕРЕ-СНЯТЫЕ предусловия стенда и механику фриза,
и переписывать их сюда значило бы завести копию, которая стареет молча. Читай как СПРАВКУ и проверяй
каждое утверждение своим прибором: часть из них снята исправлениями ПОСЛЕ выдачи.
Код-факты добывай сам. `file:line` ниже — отправные точки, а не истина: **код первичен**.
## 4. Состав. Порядок фаз ЖЁСТКИЙ
### 4.0 Фаза 0 — $0-ДЫМ. **Делай РОВНО так, и это первая работа пака**
**Ни одного платного вызова, пока дым не прошёл целиком.** Довод не гигиенический: первая же
инфраструктурная осечка на платной руке сожжёт «холодность» книги — прогон уйдёт в `failed`, и следующий
старт той же книги пойдёт как ПРОДОЛЖЕНИЕ, а не как холодный.
Дым обязан доказать: стенд поднят и порт отвечает ТВОЕМУ pid · гость заведён · деньги начислены · книга
принята · прогон стартовал · кадры доехали · узел подписи ответил · резюм прошёл · **выгрузка собралась и
файл скачался**. Инструмент заглушки — ШТАТНЫЙ провайдер `kind: local`; образцы рендера $0-конфига лежат в
репо (`platform/internal/runner/bankapply_live_test.go`, греп `zeroCostPipeline`).
**Пин фазы 0, без которого дым вырожден:** после рендера **напечатай счёт платных слагов в получившемся
конфиге — ноль**, при контрольном счёте тех же слагов в `backend/configs/pipeline-c1.yaml`**не ноль**.
Молчащий греп и чистый конфиг иначе неотличимы.
### 4.1 Предусловия — **проверь КАЖДОЕ своим прибором, список от прогона A мог устареть**
Известное на 11.09 (справка, не истина): локальной модели на машине НЕТ (ни `ollama`, ни слушателя на
11434) ⇒ настоящие узлы проходятся только платно · кластер Postgres поднят на `-h /tmp -p 55433 -U postgres`,
ОС-роль `ubuntu-26` в нём НЕ заведена · артефакт контраста майнинга нужен `CheckMiningContrast` и сверяется
**по sha256, а не по имени** (рядом на диске лежит фальшивый кандидат) · четыре переменные окружения решают,
существует ли путь вообще (`TM_PLATFORM_EXPORT_FORMATS` пуст по умолчанию ⇒ ручки выгрузки не монтируются,
и последней трети пути для тебя нет) · `epubcheck`/`java` на хосте нет и поставить их нельзя.
**Ключи провайдера.** Значение `TM_PLATFORM_ENGINE_KEYS_PATH` даю я по твоему пингу. **Нет значения ⇒
СТОП ДО фриза.** `.env` читать запрещено гардрейлом.
### 4.2 Фриз — **делай РОВНО так**
**Фриз = sha коммита ПЛЮС бинари, собранные из ЛОКАЛЬНОГО КЛОНА** (`git clone <репо> <путь>`). Довод —
главное дерево движут параллельные сессии.
**Не `git worktree`.** Бинарь из ЛИНКОВАННОГО воркри не несёт VCS-штампа **ВООБЩЕ** (замер: 24 строки
`go version -m`, из них `vcs.*` — 0), потому что `.git` воркри — ФАЙЛ и поиск корня VCS в Go его пропускает.
⇒ правило «отказывать при `vcs.modified=true`» на таком бинаре выполняется ВСЕГДА и не проверяет ничего.
У клона `.git` — настоящий каталог, и штамп живой. **Третье условие отказа обязательно: отсутствие строк
`vcs.*`.** Перед сборкой — `test ! -e /tmp/.git`; `GOFLAGS=-buildvcs=false` в фриз-сборке **ЗАПРЕЩЁН**.
⚠ Штамп снимается **на КАЖДУЮ попытку**, а не один раз: резюм может сменить бинарь под тем же прогоном —
сверяй по `run_attempts`, а не по тому, что лежит на PATH в конце.
### 4.3 Пре-регистрация — **главный рубеж пака, и он дороже самого прогона**
**ЗНАМЕНАТЕЛЬ ПРЕ-РЕГИСТРИРУЕТСЯ ДО ДЕНЕГ, иначе B ответит числом на другой вопрос.** B — ЕЩЁ ОДИН
одиночный прогон, и две точки распределением не станут. Настоящая ценность B не «вторая точка к 25.4 %», а
`request_log` ВСЕХ единиц прогона ⇒ **доля выброшенных первых попыток ПО ЕДИНИЦАМ, а не по вызовам.**
**Мера задана мной, делай РОВНО так** (я снял её на прогоне A своим прибором, числа ниже — твой базис
сравнения):
- **единица** = `(chapter, chunk_idx, stage, role)`;
- **знаменатель** = единицы, за которые заплачено хоть раз (`sum(cost_usd) > 0`);
- **числитель** = единицы, где есть хоть одна оплаченная и НЕ принятая попытка (`ok = 0 AND cost_usd > 0`);
- **прогон A: 4 из 17 = 23.5 %**, тогда как по ВЫЗОВАМ то же событие даёт 4 из 27 = **14.8 %**. Две меры
расходятся в полтора раза — вот почему мера объявляется заранее.
**Второй путь к тому же числу обязателен и считается НЕЗАВИСИМО** (без колонки `degraded`): у меня оба
пути на A дали ровно $0.106472 = 25.4 % цены книги. Сойдутся у тебя — число крепкое; разойдутся — это
находка, а не помеха.
В пре-рег идут также: **ожидаемый исход КАЖДОГО шага, написанный ДО прогона** · sha256 исходника · sha256
ФАКТИЧЕСКОГО pipeline-YAML (платформа берёт файл ЦЕЛИКОМ, пер-полевого оверрайда нет ⇒ «прогон на c1» без
sha — утверждение без носителя) · список глав с `units_total` · грант, TTL выгрузки.
**Претрейн:** `蛊真人` узнаётся моделями 4 из 5 ⇒ пре-рег объявляет, что клеймов О КАЧЕСТВЕ пак не делает
вовсе. Узлы судятся механизмом (кадры, флаги, леджер), а не чтением текста.
### 4.4 Платная фаза
**Реши сам и аргументируй:** какую книгу и сколько глав брать. Мой приор, опровергается замером: те же
главы 13 той же книги, что и в A (`books/gu-zhenren/coldrun-v16/guzhenren-ch1-10.gb18030.txt`) — тогда
числа сравнимы поединично. Возьмёшь другое — сравнение A↔B становится слабее, и это надо назвать.
**Приёмка каждого узла — по ТРЁМ независимым следам** (Postgres · диск и systemd · HTTP), не по
самоотчёту движка.
**Живость длинного прогона проверяется АКТИВНО:** не жди финального уведомления — раз в пару часов сверяй
рост числа вызовов и трат по леджеру ДВУМЯ чтениями. **Зависшая задача от идущей по сигналу завершения
неотличима, и у зависания нет цвета.**
**Деньги: ждём ≈$0.42, кап ≈$2.5 холда.** Упёрся в потолок — **СТОП и пинг мне**, не режь молча и не
проси подъёма «по проекции»: прогнозный запрос оставляет ложный след «владелец согласился на пере-оплату»,
которой не было.
### 4.5 Фаза 3 — $0 после прогона
Прибор консистентности по ОТГРУЖЕННОМУ тексту (`I1`/`I2` с печатаемыми знаменателями), выгрузка, структурное
чтение EPUB (zip + `container.xml` + `nav`), и **обе новые миграции предъявлены данными**: `wave_selection`
несёт строки обеих волн, `reasoning_tokens` — то, что провайдер прислал, а не ноль.
## 5. Где этот пак мягкий — четыре места, назвал я, веер выбираешь ты
Мандат самопроверки — **исполнением**, субагенты разрешены явно. Направление:
1. **Сборщик, который молчит, и сборщик, который прочитал ноль, — неотличимы.** Засей в стендовую БД
заведомо ненулевой банк и заведомо удержанный юнит и потребуй, чтобы сборщики стали КРАСНЫМИ. Не
покрасневший на подсадке сборщик в платную фазу НЕ ДОПУСКАЕТСЯ.
2. **Дым меняет ТРИ фактора разом** (провайдер + книга + база) ⇒ при провале платной руки он не разделяет
причину. Где дёшево — меняй по одному.
3. **Отрицательный замер обязан доказать, что спросил существующее.** Рядом с каждым нулём ПЕЧАТАЙ
контрольную величину. И помни две ловушки среды: `grep` здесь — обёртка над ugrep, чтит `.gitignore` и
**не видит `books/`**; `sqlite3` как CLI на машине НЕТ — только `python3` + `mode=ro`.
4. **Число, выведенное из соседнего поля, не краснеет нигде.** Если в строке есть поле, прямо отвечающее на
вопрос (номер попытки живёт в `trace_id`), любой ВЫВОД ответа — по времени, по порядку, по соседству —
уже дефект метода, даже когда сходится.
## 6. Предметные оси ревью
Выбери 13 и назови какие: **деньги под гонкой** · **граница «холодности»** (что в прогоне перестало быть
первым разом) · **провенанс каждого числа** (чем снято, каким прибором, на какой клетке).
## 7. Записка-план ДО работы
Перед первой командой — записка: фазы, что чем предъявляется, где ждёшь осечки. Комплектность против
заказа сверяй механически, а не памятью.
## 8. Заявление = команда
Каждое число и каждая категорика отчёта идут **с командой, которой получены**. Приёмка пере-снимает.
## 9. Эхо-протокол старта
**Первым действием** — ≤10 строк СВОИМИ словами: что понял · что считаешь опасным · что считаешь неверным.
Дословный пересказ подтверждает канал, но не понимание, и ошибку промта повторяет вместе с ним. Отправь
мне (`textmachine-11`) через `/tmp/textmachine-channel`.
## 10. Что НЕ удалось — обязательная секция отчёта
И вторая её половина, без которой она вырождена: **«где прибор слеп и я это знаю»** — что невидимо · почему
не чинил · чем закрывается. ⭐ Формулировка прошлой смены, идущая нормой: **«в коде названо, в отчёте нет —
значит для следующей смены НЕ названо».**
## 11. Канал вопросов и право отказаться
Конфликт промта с кодом или доками — **пинг мне, не интерпретация**. И у тебя есть право сказать «этого
делать не надо» с аргументом: прошлые три сессии возражали, и в двух случаях правы были они.
## 12. Прямой канал
Механизм — `CLAUDE.md` §«Связь между сессиями». Впиши свой блок в `/tmp/textmachine-channel` ПЕРВЫМ
действием. Нужной роли нет ⇒ канала нет, и это нормально: НЕ опрашивай сессии подряд.
## 13. Критерий завершённости
У каждого пункта заказа — исход (сделано · не делаю с доводом · пинг) · круги СОШЛИСЬ (последний не дал
НОВЫХ находок) · числа сняты ПОСЛЕ последней правки · всё живое в ДЕРЕВЕ или у меня, а не в письме ·
явное **«работа завершена, править не планирую»**. Без последнего пак считается идущим.

View file

@ -45,12 +45,12 @@
| 2 | **платформа** | правда у двери: `PD-455` · `PD-448` (разбор) · `PD-162` | $0 | ✅ **ЗАКРЫТ АКТОМ `D39.246`** с дофиксом по двум находкам приёмки |
| 3 | ~~полигон~~ | **прогон A**: настоящая книга до ФАЙЛА, платный провайдер | **факт $0.419424** | ✅ **ЗАКРЫТ АКТОМ `D39.247`**; строка 16 закрыта замером; ⚠ зона ВНЕ СКОУПА с 11.09 |
| 4 | **бэкенд** | ⛔ **КОНСИСТЕНТНОСТЬ, КОТОРУЮ МОЖНО ПРЕДЪЯВИТЬ**: ряды **406** · **407** · **408** · **409**, плюс купленные прогоном **417** (закон банка не виден в тексте) и **419** (стеммер: 11 из 18 промахов — ложные) | пак, почти весь $0 | ⏳ **ВЫДАН 11.09** сессии `textmachine-c9`; приёмка, круг 2 (шесть посадок выжили → дофикс) |
| 5 | **бэкенд** | «ВЫДАЧА, КОТОРУЮ ВИДИТ ЧИТАТЕЛЬ»: ряды **284** · **201** · **283** · **307** · **291** | пак | после 4; форму гранулярности решает дизайн глав |
| 5 | **бэкенд** | «ВЫДАЧА, КОТОРУЮ ВИДИТ ЧИТАТЕЛЬ» — ⛔ **РАЗОБРАН 11.09 ЧТЕНИЕМ РЯДОВ И РАЗВЕДЁН НА ДВА ПАКА, один ряд закрыт замером.** **(а) `291` ВЫДАН** — `BACKEND_BOUGHT_MEANS_DELIVERED_SESSION_PROMPT.md`, решено владельцем (`D39.204`), дефект жив и предъявлен строкой `stagerun.go:203`; акт ОДИН с платформенной половиной. **(б) `307` ЗАКРЫТ, а не заказан:** честная форма ПОСТРОЕНА и запинена коммитом `6ceb133``runOrderedChapters = (case when r.ordered_units is not null then null else r.ceiling_chapters end)`, плюс `TestACharacterOrdersVolumeIsPublishedInTheUnitItWasSoldIn`; ряд снят с таблицы. Заказать его значило бы заказать готовое — мой повторяющийся класс. **(в) `283` + `284` + `201` — СЛЕДУЮЩИЙ пак «структура и заголовки», и он идёт ПОСЛЕ прогона B:** 283 требует единственного окна пере-снапшота, а пере-снапшот двигает НАРЕЗКУ ⇒ единицы A и B станут несравнимыми, и B ответит на другой вопрос (поправка старшего коллеги, принята). У 284 сверх того нет слова владельца о ПОДПИСИ стадии | пак, $0 | ⏳ (а) выдан · (б) закрыт · (в) ждёт B |
| 6 | **фронт** | поверхность показа | пак | разморозка + пункты 15 |
| 7 | ~~полигон~~ | ⛔ **ЗОНА ВНЕ СКОУПА — слово владельца 11.09**; четыре промта уведены в `archive/prompts/` с баннерами | — | снято |
| 8 | **бэкенд/деньги** | ⛔ **«ПАДЕНИЕ, КОТОРОЕ ВИДНО»** — четверть COGS в одном механизме (**415**), слепые приборы отказа (**414**, **422**), молчащая подстановка цены. ⚠ Пин цены **413** из пака ВЫНУТ: это данные и отдельное решение | пак, $0 | ✍️ **НАПИСАН 11.09**`BACKEND_FAILURE_YOU_CAN_SEE_SESSION_PROMPT.md`; выдаётся СВЕЖЕЙ сессии сразу по закрытии 4 ⛔ **КРИТЕРИЙ ПРИЁМКИ ПАКА — МЕХАНИЗМ, А НЕ ПРОПОРЦИЯ** (поправка старшего коллеги 11.09): лекарство есть распространение ратифицированного образца `D2` п.3 на вторую причину, и оно верно при 25 % и при 5 % — пропорция задаёт очерёдность, не форму. ⇒ судить по строкам «ни одного удвоения без вердикта о вырождении; каждая выброшенная попытка — строкой леджера с причиной», а не по «с 25.4 % до X». Значит прогон B пак не гейтит и паком не гейтится.|
| 9 | **платформа+бэкенд** | ⭐ **ХОЛОДНЫЙ ПРОГОН B — платформа → бэкенд → файл, ВТОРОЙ раз.** Уточнение владельца 11.09: спрашивая «перепрогоны нужны», он имел в виду именно сквозной прогон, а не пере-запуск тестов. Покупает ЧЕТЫРЕ вещи, которых нет ни у кого: **(1)** миграция **v17** (`wave_selection`) пака консистентности ни разу не шла на живом прогоне — только в тестах; **(2)** прибор консистентности впервые даст числа с ЖИВОГО прогона, а не с пере-скана сохранённой базы прогона A — сегодня все `I1`/`I2` получены повторным чтением одних и тех же данных; **(3)** платформенный пак (идемпотентный резюм, терминальное состояние) проверяется сквозь, а не юнитами; **(4)** ⛔ **вторая точка по денежной дыре, и она нужна по норме, а не для красоты** — весь довод «четверть денег купила пустоту» стоит на ЧЕТЫРЁХ одиночных розыгрышах, а квирки §3д прямо говорят: смета DeepSeek с одиночного вызова может ошибиться на порядок, сметы строятся на ПОВТОРАХ. ⇒ у числа 25.4 % есть знак и нет величины, пока прогон не повторён. **Цена ≈$0.42 по образцу прогона A, машинный кап ≈$2.5.****ПРЕ-РЕГИСТРАЦИЯ ЗНАМЕНАТЕЛЯ, иначе B ответит числом на другой вопрос** (поправка старшего коллеги 11.09): B — ЕЩЁ ОДИН одиночный прогон, и две точки распределением не станут. Настоящая ценность B не «вторая точка к 25.4 %», а `request_log` ВСЕХ единиц прогона ⇒ **доля выброшенных первых попыток ПО ЕДИНИЦАМ, а не по вызовам.** Это и пре-регистрируется. ⚠ И идёт B **ПАРАЛЛЕЛЬНО** паку о падениях, а не после: они в РАЗНЫХ слотах (бэкенд против платформы), и правило «один промт на зону» их не сталкивает | ≈$0.42 | ждёт лендинга паков 4 и 7-платформенного |
| 9 | **платформа+бэкенд** | ⭐ **ХОЛОДНЫЙ ПРОГОН B — платформа → бэкенд → файл, ВТОРОЙ раз.** Уточнение владельца 11.09: спрашивая «перепрогоны нужны», он имел в виду именно сквозной прогон, а не пере-запуск тестов. Покупает ЧЕТЫРЕ вещи, которых нет ни у кого: **(1)** миграция **v17** (`wave_selection`) пака консистентности ни разу не шла на живом прогоне — только в тестах; **(2)** прибор консистентности впервые даст числа с ЖИВОГО прогона, а не с пере-скана сохранённой базы прогона A — сегодня все `I1`/`I2` получены повторным чтением одних и тех же данных; **(3)** платформенный пак (идемпотентный резюм, терминальное состояние) проверяется сквозь, а не юнитами; **(4)** ⛔ **вторая точка по денежной дыре, и она нужна по норме, а не для красоты** — весь довод «четверть денег купила пустоту» стоит на ЧЕТЫРЁХ одиночных розыгрышах, а квирки §3д прямо говорят: смета DeepSeek с одиночного вызова может ошибиться на порядок, сметы строятся на ПОВТОРАХ. ⇒ у числа 25.4 % есть знак и нет величины, пока прогон не повторён. **Цена ≈$0.42 по образцу прогона A, машинный кап ≈$2.5.****ПРЕ-РЕГИСТРАЦИЯ ЗНАМЕНАТЕЛЯ, иначе B ответит числом на другой вопрос** (поправка старшего коллеги 11.09): B — ЕЩЁ ОДИН одиночный прогон, и две точки распределением не станут. Настоящая ценность B не «вторая точка к 25.4 %», а `request_log` ВСЕХ единиц прогона ⇒ **доля выброшенных первых попыток ПО ЕДИНИЦАМ, а не по вызовам.** Это и пре-регистрируется. ⚠ И идёт B **ПАРАЛЛЕЛЬНО** паку о падениях, а не после: они в РАЗНЫХ слотах (бэкенд против платформы), и правило «один промт на зону» их не сталкивает | ≈$0.42 | **ВЫДАН 11.09** сессии `textmachine-82`, санкция владельца получена и положена в носитель ниже |
**ПОЧЕМУ 4 ВСТАЛ ПЕРЕД 5 (решение 11.09 по мерилу владельца).** Мерило — «качественный КОНСИСТЕНТНЫЙ
перевод длинных книг». Аудит банка 11.09 показал, что **книжного вопроса о консистентности не задаёт ни один
@ -103,6 +103,12 @@ API не было: 04.09 упёрлось в потолок (`PD-440`, с тех
## Решения владельца, уже полученные (носитель — ЗДЕСЬ; заведён 11.09, прежде его не было ни в одном доке)
- ✅ **СКВОЗНОЙ ПРОГОН B РАЗРЕШЁН** (слово 11.09: «разрешаю», в ответ на прямой вопрос с числами —
«ждём ≈$0.42, кап ≈$2.5 холда»). ⚠ Санкция названа ЗДЕСЬ и датирована, потому что норма «согласие —
ДО траты, явным словом» уже однажды стоила смены: промты ссылались на разрешение как на факт, а в
дереве его не было ни строкой. Предусловие санкции, объявленное вместе с ней: **пре-регистрация
знаменателя** — доля выброшенных первых попыток ПО ЕДИНИЦАМ, а не по вызовам, — и **фриз HEAD и
бинарей** (`git archive`), чтобы лендинги во время прогона не двигали прибор под замером.
- ✅ **ПЛАТНЫЙ ПРОГОН A РАЗРЕШЁН** (слово 11.09: «Разрешаю»). Ожидание ≈$0.30, машинный кап ≈$2.5 (холд, см.
раздел выше). ⚠ Санкция названа ЗДЕСЬ, потому что опровергатель 11.09 поймал: промты ссылались на неё как
на факт, а в дереве её не было ни строкой — «известное со слов» не носитель.

View file

@ -24,6 +24,8 @@
- **Активные хендофф-промты — какой файл ТВОЙ** (состав обновляется при каждом лендинге, D39.80; хроника, причины и статусы РАБОТ — CURRENT-STATE и D-лог):
| Роль | Активный промт | Статус |
|---|---|---|
| **Бэкенд · КУПЛЕНО — ЗНАЧИТ ДОСТАВЛЕНО** | [BACKEND_BOUGHT_MEANS_DELIVERED_SESSION_PROMPT.md](BACKEND_BOUGHT_MEANS_DELIVERED_SESSION_PROMPT.md) | ✍️ **написан 11.09**, выдаётся `textmachine-b1`. Предмет решён владельцем (`D39.204`): отказ резервации на РЕТРАЕ деградирует во флаг с отдельной причиной. Сегодня он уходит наверх из цикла попыток раньше `UpsertChunkStatus` ⇒ юнит виден `pending` НАВСЕГДА, прогон уходит `exit 4` при доставленных купленных юнитах. Платформенная половина — отдельным промтом, акт ОДИН на две. $0 |
| **Сквозной · ХОЛОДНЫЙ ПРОГОН B** | [COLD_RUN_B_SESSION_PROMPT.md](COLD_RUN_B_SESSION_PROMPT.md) | ✍️ **написан 11.09**, выдаётся `textmachine-82`. ⛔ **ПЛАТНЫЙ, санкция владельца получена** («разрешаю»): ждём ≈$0.42, кап ≈$2.5 холда. Покупает первое ЖИВОЕ исполнение миграций `v17`+`v18`, числа консистентности с прогона (а не с пере-скана), платформенный пак сквозь и вторую точку по денежной дыре с ПРЕ-РЕГИСТРИРОВАННЫМ знаменателем (по ЕДИНИЦАМ: на A — 4 из 17 = 23.5 %). Кода не правит |
| Оркестратор | [ORCHESTRATOR_SESSION_PROMPT.md](ORCHESTRATOR_SESSION_PROMPT.md) | роль и нормы; счётчик роли — CURRENT-STATE |
| Бэкенд · ДВЕ ОСТАНОВКИ | активного НЕТ | пак ОТМЕНЁН ВЛАДЕЛЬЦЕМ 10.09 до лендинга — акт **D39.240**; промт в `archive/prompts/` с баннером. Причина — размах правки, не качество. ⚠ Предмет ЗАМЕНЁН и сузился: остановка остаётся жёсткой, **деньги терять допустимо**, но она обязана быть КОРРЕКТНОЙ (без гонок, без половинчатых состояний, верное возобновление). ⭐ Пак успел купить `D39.236``D39.238` и строку **385** |
| Платформа · ДВЕ ОСТАНОВКИ | активного НЕТ | пак ОТМЕНЁН ВЛАДЕЛЬЦЕМ 10.09 до лендинга — акт **D39.240**; промт в `archive/prompts/` с баннером. Причина — размах правки, не качество. ⚠ Предмет ЗАМЕНЁН и сузился: остановка остаётся жёсткой, **деньги терять допустимо**, но она обязана быть КОРРЕКТНОЙ (без гонок, без половинчатых состояний, верное возобновление). ⭐ Пак успел купить `D39.236``D39.238` и строку **385** |

View file

@ -58,9 +58,10 @@
| Зона | Промт | Сессия | Состояние |
|---|---|---|---|
| бэкенд | — | — | 🟢 **СЛОТ СВОБОДЕН** — пак `textmachine-61` принят актом `D39.251`, промт в архиве с баннером |
| бэкенд | `BACKEND_BOUGHT_MEANS_DELIVERED_SESSION_PROMPT.md` | **textmachine-b1** | ✍️ написан 11.09, опровергатель идёт; выдаётся по его итогам |
| платформа | — | — | 🟢 **СЛОТ СВОБОДЕН** — пак принят актом `D39.250`, минор 0.15.0 |
| полигон | — | — | ⛔ **ЗАКАЗ СНЯТ ВЛАДЕЛЬЦЕМ 11.09** («полигон не надо выдавать»); промт готов и лежит, пере-выдача — только его словом |
| сквозной (вне кодовых зон) | `COLD_RUN_B_SESSION_PROMPT.md` | **textmachine-82** | ✍️ написан 11.09, ПЛАТНЫЙ, санкция владельца получена; опровергатель идёт |
| фронт | заморожен | — | разморозка по критерию `NEAR_TERM_PLAN.md` |
**Резерв израсходован: `textmachine-61` получила пак о падениях 11.09, как только слот освободился актом `D39.249`.**