# Промт: полигон-пак «ХОЛОДНЫЙ ПРОГОН A — от двери до ФАЙЛА, настоящая книга, настоящие деньги» > ⛔ **АРХИВ — ЗАКРЫТО СЛОВОМ ВЛАДЕЛЬЦА 11.09: «полигон это вообще не наш скоуп».** Заказ снят не по > качеству промта и не по исчерпанию предмета: зона выведена из работы целиком. **Инструкции отсюда НЕ > ИСПОЛНЯТЬ** (правило архива). Пере-открывается только новым словом владельца; до тех пор содержимое — > история, а не задание. ⚠ Ссылки на этот файл из журнала решений и старых отчётов сознательно не > правлены: тела нот не переписываются, и их адреса указывают в историю. > ⚠ **Редакция 2 (11.09).** Первая редакция прошла опровергателя и получила **двадцать** находок, из них > четыре денежных и три, обнулявших смысл прогона. Все внесены. Места, где я ошибался, помечены > «⛔ ИСПР.» — читай их внимательнее прочего: там сказано, чему НЕ верить. ## 1. Какая проблема и что решит твой результат Мы построили весь путь: гость заводит книгу → платформа берёт деньги в холд → движок переводит → человек подписывает банк терминов → редакторская волна → выгрузка → файл. **Каждый кусок предъявлен по отдельности. Книги, прошедшей его ЦЕЛИКОМ до конца, не было ни разу.** Это строка бэклога **16** дословно: «цена ДОВЕДЁННОЙ ДО КОНЦА книги не измерена». Ближайшая попытка — 04.09 — дошла до скачанного EPUB, но упёрлась в денежный потолок. ⛔ **ИСПР. 1: СУДЬИ НА ЭТОМ ПУТИ НЕТ.** Боевой конфиг `pipeline-c1.yaml` несёт ДВЕ стадии — `draft` и `edit`; `role: judge` живёт только в `c2` и Фазой 0 прямо не исполняется (`backend/internal/config/pipeline.go:506-508`). Там же `escalation.budget_usd: 0` ⇒ эскалация НЕ исполняется вовсе, и `gates.coverage.enabled: false` — один из пяти гейтов выключен. Путь, который ты проверяешь: **черновик → редактор → четыре $0-гейта → выгрузка**. Так и пиши в пре-реге; «судья» из моей первой редакции — моя ошибка. **Твой результат:** одна настоящая книга (3 главы zh→ru) проведена от двери до файла, открытого человеком, и **у каждого узла напечатано, ЧЕМ он предъявлен**. Плюс честный список того, что на этом пути сломано: прогон **ничего не чинит**, он только называет. ## 2. Зона записи и git **Зона: `eval/` + `docs/experiments/`**, пинг оркестратору — секция «Полигон» в `docs/PROGRESS.md`. **Сессия НЕ коммитит — КРОМЕ пре-рег-фризов** (право полигона, единственное исключение в проекте). Канон git — `CLAUDE.md` §«Git-координация мультисессий». ⛔ `backend/` и `platform/` — ЧИТАТЬ, не править; недостающие артефакты класть **в worktree-копию**, не в главное дерево. `.env` **не читать**. ⛔ **ИСПР. 2 — АДРЕСАТ ФРИЗ-ОБЪЯВЛЕНИЯ.** Канон говорит «объявляется ВЛАДЕЛЬЦУ вслух до коммита», но владелец отошёл, а §13 запрещает его беспокоить. Разрешаю так: **объявление идёт мне по каналу; канала нет ⇒ объявление печатается ОТДЕЛЬНОЙ секцией отчёта ДО строки фриз-коммита, и это засчитывается.** ⛔ **Правка ЗАКАЗА на лету доезжает только РЕЛЕЕМ:** я пере-передаю её отдельным сообщением, ты эхо-подтверждаешь своими словами и выносишь отдельным пунктом отчёта. ## 3. Карта чтения — ЗАКОН, дальше только по её ссылкам 1. `CLAUDE.md` — цели владельца и гардрейлы. 2. `docs/experiments/09-pilot-protocol.md` + `eval/README.md` — устройство полигон-зоны и пре-регистрация. 3. `docs/experiments/00-provider-quirks.md` — **оплаченные** провайдерские факты; ДО первого платного вызова. 4. `platform/docs/STACK_DECISIONS.md` §«Стенд разработчика» (строка 463) — рецепт стенда и инвентарь каналов. 5. Строки бэклога **16** и **224** (`docs/BACKLOG.md`, греп `^| N |`). **Ратифицированное и замеренное — в теле промта, не искать:** - **`D39.144`** — банк подписывается ВЕСЬ ОДНИМ ОК; резюм снимает стоп при ЛЮБОМ состоянии решений. - **`D39.178`** — сборка выгрузки идёт `--partial`. ⛔ **ИСПР. 3: я огрубил ноту.** Полностью: неполная книга уходит **С ПОМЕТКОЙ и маркером на месте КАЖДОЙ дыры**; «молчаливый полный файл на книге с дырой ПО-ПРЕЖНЕМУ ЗАПРЕЩЁН»; граница `D25.1` осталась открытой. То есть дверь строит всегда, но обязана СКАЗАТЬ. - **`D39.194` п.1** — цикл замкнут живьём 04.09, EPUB прошёл `epubcheck` 5.3.0. ⚠ Слова `complete` в теле ноты нет: что книги, доведённой до `complete = true`, не было, говорит строка **16**, а не нота. - **Претрейн:** 蛊真人 узнаётся моделями 4 из 5 ⇒ **пак НЕ делает утверждений о КАЧЕСТВЕ перевода.** Узлы судятся механизмом — кадрами, флагами, леджером. - **Норма денег полигона:** «не влезает в бюджет — СТОП и пинг, не резать молча»; подъём потолка просят при СРАБАТЫВАНИИ стопа, не по проекции. ⚠ Носитель — ролевой промт оркестратора; атрибуцию `D39.108` п.1 я снял 11.09 фантом-гардом (в теле ноты формулировки нет). - **Живость проверяется АКТИВНО:** один вызов редактора законно идёт до ~21 минуты (`attempt_max_s: 1240`, `backend/configs/models.yaml:78` — ⚠ это ПОТОЛОК уровня ПРОВАЙДЕРА, не типичная длительность). ⛔ **ИСПР. 4: `events.jsonl` и `request_log` — ОДИН носитель** (диск одного процесса), и растущий лог не есть работа. Сторожи по РАЗНЫМ осям: число строк `request_log` (движок) **и** `book_events` / `run_attempts.last_seq` (платформа), плюс `systemctl show` юнита. Каденция — раз в 30–40 минут, доклад «жив» — мне, одной строкой с двумя числами. ⚠ **Какие полигонные нормы здесь действуют, а какие нет — ИСПРАВЛЕНО.** «Пороги различимости» и «запрет судьи-родственника» не работают: судейской линзы и сравнения рук в паке нет. **Но «арм без фактора» и «декой» работают, и я был неправ, объявив их неприменимыми** — см. §4.0 п.3 и §5 п.10. Пре-регистрация ожидаемых исходов (§4.3) действует в полную силу. ## 4. Состав: четыре фазы. Порядок ЖЁСТКИЙ ### 4.0 Фаза 0 — $0-ДЫМ. **Делай РОВНО так, и это первая работа пака** ⛔ **Ни одного платного вызова, пока дым не прошёл целиком.** 1. **Инструмент заглушки — ОДИН, и он ШТАТНЫЙ: провайдер `kind: local` на `127.0.0.1:11434`.** ⛔ **ИСПР. 5 (две правки, вторая — МОЯ ОШИБКА, снятая полигоном 11.09).** **(а)** Чужой `~/tm-p9-work/fake_provider.py` не брать: это двухнедельный скрипт в чужом домашнем каталоге, а не механизм проекта. **(б)** ⛔ **Но моё «с `local` они несовместимы, разные адаптеры» — НЕВЕРНО, и вот чем предъявлено:** заглушка живёт В РЕПО портированной — `platform/internal/runner/translate_resnapshot_live_test.go:115`, комментарий дословно «fakeProvider is the P9 live-probe's $0 stand-in (fake_provider.py), ported», — и обслуживает она ровно провайдера `kind: local`. Рядом лежит готовый рендер $0-конфига `zeroCostPipeline` (`platform/internal/runner/bankapply_live_test.go:116`), который выбирает первую модель с `Providers[m.Provider].Kind == "local"`. ⇒ **бери эти два носителя как образец.** ⚠ **И «sed по `model:`» из рецепта стенда СЕГОДНЯ НЕДОСТАТОЧЕН** — тот же рендер снимает сверх моделей стадий ещё четыре вещи: модели ГЕЙТОВ (`model` И `classify_model` — второй падает обратно на первый только когда ПУСТ, и его собственный комментарий называет это уже случавшимся провалом), `escalate_to`, `label_models`, `escalation.budget_usd`, и абсолютизирует `mining.contrast_path`. ⇒ **пин фазы 0: после рендера напечатай счёт платных слагов в получившемся конфиге — ноль, при контрольном счёте тех же слагов в `pipeline-c1.yaml` — не ноль.** Молчащий греп и чистый конфиг иначе неотличимы. 2. **Что дым обязан доказать ДО денег:** стенд поднят и порт отвечает ТВОЕМУ pid · гость заведён · книга принята · прогон стартовал · кадры доехали · узел подписи ответил · резюм прошёл · **выгрузка собралась и файл скачался** · все сборщики следов печатают то, что обещали. 3. ⛔ **ПОЗИТИВНЫЙ КОНТРОЛЬ КАЖДОГО СБОРЩИКА — обязателен, стоит $0 и снимает сразу три дыры пака.** Засей в стендовую БД заведомо НЕНУЛЕВОЙ банк и заведомо удержанный юнит и **потребуй, чтобы сборщики стали КРАСНЫМИ**. Сборщик, не покрасневший на подсадке, в платную фазу НЕ ДОПУСКАЕТСЯ. Довод: критерии §5 п.1 и §4.4 одинаково удовлетворяются молчащим прибором — «счётчики нулевые» и «прибор ничего не прочитал» неотличимы, а банковый сборщик на платной руке работает первый раз в жизни (на заглушечной прозе банку неоткуда взяться). 4. ⚠ **Дым меняет ТРИ фактора разом** (провайдер + книга + база) — значит при провале платной руки он не разделяет причину. Держи это в голове и, где дёшево, меняй по одному. 5. **Прибор §4.5 п.2 (счёт расхождения форм) строится и пинится ЗДЕСЬ**, на бесплатном материале (`books/gu-zhenren/coldrun-v16/guzhenren-coldrun-v16.db.book.epub`), а не после траты денег. ### 4.1 Предусловия стенда — **делай РОВНО так; список пере-снят и ИСПРАВЛЕН** 1. ⛔ **Артефакта контраста майнинга на ФС нет ни одного** (два независимых полных скана; контроль: под `$HOME` просмотрено 390 083 файла). `CheckMiningContrast` откажет на старте `translate` — $0, но останется `failed`-прогон, и следующий старт той же книги пойдёт как ПРОДОЛЖЕНИЕ. Рецепт и пин — `docs/experiments/16-bank-mining.md:183`: jieba 0.42.1 `dict.txt`, sha256 `7197c3211ddd98962b036cdf40324d1ea2bfaa12bd028e68faa70111a88e12a8`. ⚠ **Ловушка имени:** в конфигах файл зовётся `mining-contrast.zh.txt` (`backend/configs/pipeline-c1.yaml:139`) и резолвится ОТ КАТАЛОГА `pipeline.yaml`, а источник — `jieba_dict_general_zh.txt`. ⛔ **И ловушка проверки: гард делает только `os.Stat`** — рядом на диске лежит ФАЛЬШИВЫЙ кандидат `~/tm-p9-work/cfg/contrast-zh.txt` (992 байта, sha не тот), и гард им удовлетворится. **Сверяй sha, а не имя.** 2. **jieba ставится, это НЕ блокер** (испр.: `python3 -m venv` есть, `ensurepip` даёт pip 25.1.1, pypi достижим). 3. **Кластер Postgres поднят, но БЕЗ TCP-порта:** `listen_addresses` пуст, слушает только unix-сокет. Подключаться `-h /tmp -p 55433 -U postgres` (ОС-роль `ubuntu-26` в нём не заведена). ⛔ Кластер НЕ сносить, чужие базы не трогать — там данные платного прогона 04.09; заводи СВОЮ. 4. ⛔ **ИСПР. 6: `epubcheck`/`java` на хосте нет, и поставить их сессия НЕ может** — passwordless sudo отсутствует, а §13 запрещает беспокоить владельца. ⇒ **валидатор EPUB НЕ обязателен.** Узел судится `txt`-выгрузкой плюс структурным чтением EPUB (zip + `container.xml` + `nav`), и «файл ОТКРЫТ» значит **человек прочитал первый абзац перевода и сказал, что это связный русский текст**, а не `cat`. Ставишь `epubcheck` без sudo из тарбола в `~/.local` — законно, версию назови числом. 5. **Порт может отвечать ЧУЖИМ процессом** (`PD-447`): опознавай стенд по pid-на-порту. Сегодня стенд не поднят вовсе: `tmplatformd`-процессов 0, дефолтный `127.0.0.1:8080` свободен. 6. ⛔ **Годится ТОЛЬКО бинарь из фриз-воркри.** Настоящих стендовых копий `tmctl`/`tmvet`/`tmmutate` — **34** (вне `$HOME` и `/tmp` — 0); среди них бинарь от 24.08 на `PATH` (`~/.local/bin/tmctl`), носитель `PD-432`. Копии заводятся и в скретчпадах ⇒ негоден ЛЮБОЙ бинарь не из фриз-воркри. 7. ⛔ **ИСПР. 7 — ПЯТЬ ПЕРЕМЕННЫХ ОКРУЖЕНИЯ РЕШАЮТ, СУЩЕСТВУЕТ ЛИ ПУТЬ ВООБЩЕ, и в первой редакции их не было.** `TM_PLATFORM_EXPORT_FORMATS` по умолчанию **ПУСТ** ⇒ все три ручки выгрузки НЕ монтируются, и последняя треть пути для тебя не существует (404) · `TM_PLATFORM_ENGINE_BIN` пуст ⇒ нет ни прогонов, ни интейка · `TM_PLATFORM_BOOKS_DIR` пуст ⇒ нет `POST /v0/books` · `TM_PLATFORM_ENGINE_KEYS_PATH` — см. п.8. ⛔ **ИСПР. 19: `TM_PLATFORM_ENGINE_CEILING_ARG` из этой пятёрки ВЫЧЕРКНУТ — я был неправ.** У переменной есть дефолт `--ceiling-usd {{usd}}` (`platform/internal/config/config.go:550`), демон печатает его на буте как `source=default`, и прогон стартует, стоит и завершается, пока она не задана вовсе. Замерено полигоном исполнением на стенде 11.09. Остальные четыре в силе. **Пин ДО фриза: `GET /v0/capabilities` показывает непустой `export_formats`.** 8. ⛔ **Ключи провайдера.** Значение `TM_PLATFORM_ENGINE_KEYS_PATH` даю я; в окружении его сейчас нет, и правдоподобного кандидата на диске тоже. **Нет значения ⇒ СТОП ДО фриза** — платного пути без него не существует, а `.env` читать запрещено гардрейлом. 9. **Субъект и деньги заводятся НА МАШИНЕ, не по HTTP:** самореги нет (маршрутов с `auth` в таблице — 0 из 19), пополнения по HTTP нет (`credit`/`grant`/`balance` — 0 из 19). Путь: `POST /auth/dev-login` при `TM_PLATFORM_DEV_LOGIN` (тогда деплой не может быть с OIDC) либо `tmplatformctl token issue`; деньги — `tmplatformctl grant --user --usd `. 10. ⛔ **Каталог книги `coldrun-v16/` УЖЕ занят прошлым прогоном** — там `project.db` (68 строк `request_log` на $0.436), `events.jsonl`, сайдкары банка, `bin/tmctl` без VCS-штампа, и `book.yaml`, указывающий в ЧУЖОЙ домашний каталог. **Исходник читается ТОЛЬКО как файл; рабочий каталог платной книги — новый и пустой; шаблон `book.yaml` оттуда НЕ переиспользовать.** ### 4.2 Фриз — **делай РОВНО так** **Фриз = sha коммита ПЛЮС бинари, собранные из ЛОКАЛЬНОГО КЛОНА** (`git clone <репо> <путь>`). Довод — не «дерево грязное», а **главное дерево движут параллельные сессии**: в нём прямо сейчас работают движковая и платформенная. Драйвер перед каждым платным шагом печатает `go version -m` и ОТКАЗЫВАЕТ при `vcs.modified=true`, чужом revision **или ОТСУТСТВИИ строк `vcs.*`**. ⛔ **ИСПР. 18 — МОЙ ЦЕНТРАЛЬНЫЙ ГЕЙТ БЫЛ ПИНОМ, УТВЕРЖДАЮЩИМ МОЛЧАНИЕ. Замерено полигоном 11.09, я пере-проверил своим прибором.** Первая редакция велела собирать из `git worktree add`. Бинарь, собранный в ЛИНКОВАННОМ воркри, не несёт VCS-штампа **ВООБЩЕ** — не `vcs.modified=true`, а НИ ОДНОЙ строки `vcs.*` (24 строки `go version -m`, из них `vcs.*` — 0). Причина: у линкованного воркри `.git` — ФАЙЛ, и поиск корня VCS в Go его пропускает; выше по дереву репозитория нет, поэтому сборка не падает, а **тихо выходит без штампа** — тот же результат, что от запрещённого `-buildvcs=false`, только без единого предупреждения. ⇒ правило «отказывать при `vcs.modified=true`» на воркри-бинаре выполнялось ВСЕГДА и не проверяло ничего. **Контроль, доказывающий, что механизм на этом хосте жив:** та же сборка из ГЛАВНОГО дерева даёт `vcs.revision=…` и `vcs.modified=true`. ⇒ **Фриз-дерево — ЛОКАЛЬНЫЙ КЛОН:** у него `.git` настоящий КАТАЛОГ, и бинари несут `vcs.revision= · vcs.modified=false` (проверено на всех трёх). Гейт получает зубы: «штампа нет» и «штамп чужой» становятся отличимы от «штамп мой и чистый». ⚠ **И в клоне НЕТ `books/`** — внешний репозиторий держит их в `.gitignore`, книги версионируются ОТДЕЛЬНЫМ репозиторием. Исходник читается из главного дерева как ФАЙЛ (read-only), а его провенанс — пара sha256 (срез и оригинал) в пре-реге. Артефакт контраста кладётся в КЛОН, рядом с его `pipeline.yaml`. ⛔ **ИСПР. 8 — ВТОРОЙ СПОСОБ ОБНУЛИТЬ ФРИЗ-ГЕЙТ, и он остаётся в силе для КЛОНА тоже.** Напоровшись на посторонний `/tmp/.git`, сборка падает с «error obtaining VCS status», и штатное лечение `GOFLAGS=-buildvcs=false` **стирает штамп целиком** (эррата `D39.202`). ⇒ **перед сборкой `test ! -e /tmp/.git`; `-buildvcs=false` в фриз-сборке ЗАПРЕЩЁН; фриз-дерево — вне репозитория и вне общего скретчпада.** ⚠ И штамп снимается **на КАЖДУЮ попытку**, а не один раз: резюм может сменить бинарь под тем же прогоном (`TM_PLATFORM_RESUME_MAY_CHANGE_ENGINE`, колонка `runs.engine_binary`) — сверяй по `run_attempts`, а не по тому, что лежит на PATH в конце. **В фриз-коммит:** `docs/experiments/24-<имя>.md` — пре-рег с таблицей ожидаемых исходов (§4.3), sha256 исходника и **sha256 ФАКТИЧЕСКОГО pipeline-YAML** (платформа берёт файл ЦЕЛИКОМ через `TM_PLATFORM_BOOK_TEMPLATE`, пер-полевого оверрайда нет ⇒ «прогон на c1» без sha — утверждение без носителя), список глав с `units_total`; `eval/<каталог>/` — драйвер, сборщики следов и сверка; шаблон `book.yaml` с абсолютными путями в worktree. **Без пере-фриза** (но печатается в отчёт): грант, `TM_PLATFORM_HOLD_FACTOR_PERCENT`, TTL выгрузки. **Граница:** меняется ЧТО покупается или чем судится — новый фриз; меняется СКОЛЬКО тратить — объявление. ⚠ Правка собственного драйвера после фриза — тоже новый фриз. ### 4.3 Пре-регистрация ожидаемых исходов — **главный рубеж пака** **До первого платного вызова** в фриз-коммите лежит таблица: **узел → что ДОЛЖНО произойти, числом или строкой → чем предъявлено → что считается ПРОВАЛОМ узла.** **Следы — по РАЗНЫМ носителям:** **(1) Postgres стенда** (`books`·`chapters`·`units`·`runs`·`run_attempts`· `reservations`·`credit_ledger`·`book_events`·`exports`); **(2) диск движка и systemd** (`events.jsonl` с кадрами `hello/progress/unit_done/bank_stop/ceiling/spend/finished`; `project.db`/`request_log` — читать `mode=ro` можно НА ХОДУ, WAL это разрешает; сайдкары `.bank.json`, `mined-signature.yaml`, `.bank-stop.txt`; **systemd-маркер выхода** `/runs/-.exit` — это маркер ЮНИТА systemd, не переводческого юнита); **(3) HTTP и файл** — ответы ручек, SSE, скачанные БАЙТЫ и их sha256. ⛔ **ИСПР. 9 — И ЧЕСТНО ПРО НЕЗАВИСИМОСТЬ: следов не три.** Postgres платформы **материализуется из `events.jsonl` движка** (`Sink materializes a stream into the reporting database… not an event store`), а текст, сверку и файл платформа получает теми же `tmctl export/status/build`. ⇒ **«три следа сошлись» означает "одна БД согласна сама с собой"**. По-настоящему независимы только скачанные БАЙТЫ и их sha256; биллинга провайдера у нас нет. Так и напиши в пре-реге — это не отменяет сверку, но меняет, что она доказывает. ⛔ **ИСПР. 10 — ДЕНЕЖНОЕ РАВЕНСТВО НАЗВАНО НЕТОЧНО.** Кадр несёт `committed_micro_usd` (целые микро-доллары), а `committed_usd` — поле ДРУГОГО носителя, `tmctl status --json`; конверсия округляет ВВЕРХ. `request_log` объявлен ТЕЛЕМЕТРИЕЙ, а не источником денег («деньги живут в spend/checkpoints»), и редрайв удаляет чекпойнты — это законный класс расхождения. ⇒ печатай в МИКРО-долларах и как ПРОВЕРКУ, а не тождество: Σ `request_log.cost_usd` ≈ `spend.committed_micro_usd` ≈ Σ `credit_ledger` settlement ≈ (грант − баланс); расхождение — назвать, а не подогнать. **Открытых резерваций на конце — 0** (холд дебетует баланс отдельной строкой `kind='hold'`). ### 4.4 Фаза 2 — платный прогон **Книга:** `books/gu-zhenren/coldrun-v16/guzhenren-ch1-10.gb18030.txt` (57838 байт, sha256 `0b5f9b0266d8c32ac717a41211d2ed15d4f2a07f37a701fb686e255ab6c89f37`, 10 глав маркерами `第一节…第十节`). ⚠ Имя эксперимента — НЕ `coldrun-a`: каталог занят прогоном 24.08. ⛔ **ИСПР. 11 — ОБЪЁМ ЗАКАЗА БЫЛ ДВУСМЫСЛЕН, реши и объяви в пре-реге.** Интейк главами резать НЕ умеет (форма несёт `title`/`source_lang`/`target_lang`), объём покупается членом `chapters` на старте прогона. Значит либо **(а)** режешь файл до 3 глав и грузишь срез — тогда `units_total` книги и заказ совпадают; либо **(б)** грузишь весь файл и заказываешь 3 главы — тогда узел выгрузки судится по `ordered_chapters` / `delivered_chapters`, а НЕ по `units_total`. **Рекомендую (а)**: сверка честнее и дешевле. ⚠ И `delivered` — это `finished.volume.delivered`, а секции `volume` у цельнокнижного заказа НЕТ вовсе (платформа не передаёт `--max-units`); плюс `Delivered` считает только юниты, «never completed before» — после резюма это уже не `units_total`. ⛔ **ИСПР. 12 — ГЛАВЫ 1–3 ТОЛЩЕ СРЕДНЕЙ.** Замер по БД прошлого прогона того же исходника: глава 1 — 4 чанка, глава 2 — 3, глава 3 — 2, остальные по 2 (контроль: всего 23 строки `chunk_status`). **9 из 23 чанков = 39 % книги в 30 % глав.** ⚠ И пин «≥1 глава с `units_total ≥ 2`» из первой редакции охраняет то, чего не бывает (таких глав все десять) и НЕ охраняет то, что случится — недооценку объёма. Замени пин на **«сумма `units_total` по заказанным главам совпадает с пре-регом»**. **УЗЕЛ ПОДПИСИ БАНКА — самое ценное место прогона, и здесь я ошибался дважды.** ⛔ **ИСПР. 13a: читатель у секции предложений ПОСТРОЕН.** Платформа считает `bank_terms` (`count(*)` и `filter (where status='approved')`), а строки туда пишет `SaveBank` из движкового сайдкара. Наблюдённый ноль объясняется МОМЕНТОМ обновления: банк пересчитывается, только когда книга «в покое» (нет прогонов с `finished_at is null`), а при банк-стопе статус уходит в `awaiting_bank` РАНЬШЕ закрытия строки прогона. ⇒ **ожидаемый исход: платформа показывает ноль ПОКА строка прогона не закрыта и НЕнулевое ПОСЛЕ.** Ноль после закрытия — дефект; ненулевое до — тоже факт. ⛔ Прежняя формулировка («узел засчитан, только если платформа показала ноль») НАКАЗЫВАЛА исправное поведение — снята. ⛔ **ИСПР. 13b: улику уничтожает резюм, который пак сам заказывает.** `proposed[]` в `.bank.json` берётся из поля в памяти ОДНОГО процесса, а `exportBank` зовётся в том числе на СТАРТЕ каждого прогона и перезаписывает файл атомарно. ⇒ **сними sha256 и КОПИЮ `.bank.json` в момент `awaiting_bank`, ДО `bank/corrections` и ДО резюма.** Более живучие улики того же факта — `mined-signature.yaml` и `.bank-stop.txt`: они пишутся при каждом заходе в майнинг. ⛔ **ИСПР. 13c: банк-стопа может не случиться вовсе.** Стоп требует трёх условий разом: флаг `--verify-bank` И наличие edit-волны И **кластер, которого не показывал ни один прежний стоп** (движок помнит показанные поверхности). Иначе — авто-продолжение с неподписанным банком, и **второй прогон по той же книге не остановится никогда**. Это девятый способ выродиться: узел не пройден не потому, что сломан, а потому, что не наступил. Назови исход явно. **Дверь решения зовётся `POST /v0/books/{bookId}/bank/corrections`**, `action ∈ approve|decline`, пачкой (персональных ручек по терминам нет, таблица `bank_decisions` мертва). «Подпись» завершается одним `POST /v0/runs/{runId}/resume`. **Решение, которое принимаешь ты:** провести ОДНО настоящее решение через дверь (рекомендую — иначе дверь правок остаётся непройденной) либо резюмить неподписанным. Объяви ДО прогона. **Чего делать НЕЛЬЗЯ:** чинить найденное · править `backend/`/`platform/` · менять срез или пайплайн после фриза без нового фриза · тихо пополнять баланс · интерпретировать провайдерскую аномалию без вендор-доки. ### 4.5 Фаза 3 — $0 после прогона 1. **Сверка каждой строки пре-рег-таблицы**: ожидание → факт → сошлось/нет → чем предъявлено. 2. **Механический счёт расхождения форм по ОТГРУЖЕННОМУ тексту** (прибор построен в фазе 0, §4.0 п.5): сколько канонических терминов отданы более чем одной передачей и в каких главах. ⚠ Это МЕХАНИЧЕСКИЙ счёт, не суждение о качестве. Он нужен, потому что такой меры по финальному тексту сегодня не существует вовсе (строка бэклога **406**). 3. **Список сломанного** — строкой на находку: что · где · чем предъявлена · «замерено / прочитано / подозрение». Ряды бэклога заведу я. ## 5. Как прогон вырождается — десять способов и их снятие 1. ⛔ **Дверь выгрузки ВСЕГДА строит** (`--partial`). **Снятие:** `exports.complete = true` И нулевые счётчики отчёта сборки И `finished.outcome` в списке успеха И все `units.state='translated'`. ⛔ **ИСПР. 14: ни `complete`, ни счётчики на API НЕ ОТДАЮТСЯ.** `wireExport` несёт 7 полей, и запрет умышленный («what does NOT cross: … whether the file came out whole»). ⇒ `complete` читается **из Postgres**, счётчики — **из stdout `tmctl build` или лога платформы**. ⚠ И проверяй не пять полей, а **семь**: к `pending/withheld/incomplete/stale/ghost` добавь `stale_unknown` и `config_drift` — под дрейфом конфига `stale_units` механически 0, и `complete: true` при этом ЗАКОНЕН. Ноль без `stale_unknown=false` не доказывает ничего. 2. **Срез не тот, что в пре-реге.** Снятие: $0-манифест ДО фриза (`tmctl manifest --json` даёт `units_total` и по книге, и по главе; ⚠ он ПЕРЕЗАПИСЫВАЕТ `.manifest.json` и требует записываемого каталога), сверка после интейка, расхождение — стоп ДО оплаты. 3. **Узел подписи** — §4.4, три исправления. 4. **Деньги мимо сверки** — §4.3 ИСПР. 10; строки `request_log` с непустым `err` или `finish_reason ≠ stop` перечисляются поимённо. (На опорном прогоне 08.09 таких было **32 % трат**.) 5. ⛔ **ИСПР. 15 — СТОРОЖ ПОТОЛКА СМОТРЕЛ НА СТРОКУ, КОТОРОЙ НЕ БУДЕТ.** `credit_exhausted` «больше не производится для собственного потолка прогона» — это счёт АККАУНТА; потолок прогона даёт **`run_limit_reached`**. Полный словарь: `run_limit_reached · credit_exhausted · daily_ceiling · ceiling_unknown`. ⇒ **ЛЮБОЕ непустое `paused_reason` = СТОП и пинг.** Прогон при этом не `failed` — контракт это запрещает. 6. **Чужой стенд и ложная зелень:** порт чужого процесса · ничьи базы · старый `tmctl` · `vcs.modified`. Снятие: pid-на-порту · своя база · штампы по КАЖДОЙ попытке · контрольные числа **и по `runs`, и по `run_attempts`** (резюм после банк-стопа гарантирует вторую попытку — «прогонов = 1» этого не видит). 7. **Отказ на старте не бесплатен для ЭКСПЕРИМЕНТА** (артефакт контраста): $0 по деньгам, но после `failed` книга уже не холодная. Снятие: дым и предусловия ДО загрузки платной книги; платной книге — свежий id. 8. **Претрейн** — никаких суждений о качестве. 9. ⛔ **НОВОЕ: прогон может НЕ КУПИТЬ НИЧЕГО и выйти успешным — реплей чекпойнтов.** `RequestHash` адресует чекпойнт, попадание пропускает вызов провайдера и стоит $0 (колонка `request_log.tm_hit` — «ответ взят из чекпойнта»); гварда «`project_db` обязан быть новым» в коде НЕТ. Если платная книга ляжет на путь, где остались чекпойнты дыма под тем же снапшотом, прогон пройдёт зелёным почти бесплатно и измерит пустоту. **Снятие:** `select distinct model_actual from request_log` **не содержит `local-*`** — это НЕСУЩИЙ пин; `tm_hit` печатается **с разбивкой по попыткам**, а не суммой; `test ! -e ` до старта — дешёвая добавка. ⛔ **ИСПР. 20: «`tm_hit = 0` после прогона» — НЕВЕРНО для прогона с банк-стопом, и это моя ошибка.** Замерено полигоном на дыме: 3 строки из 13 пришли с `tm_hit=1`, и это ЗАКОННО — резюм переигрывает чекпойнты СВОЕЙ ПЕРВОЙ попытки, за которые уже заплачено. Суммарный ноль тут означал бы, что стопа не было. Различает не сумма, а разбивка: попадания внутри одной попытки — подозрение, попадания второй попытки в чекпойнты первой — норма. 10. ⛔ **НОВОЕ: молчащий прибор удовлетворяет три центральных критерия сразу** (§5 п.1, §4.4, §4.3). **Снятие — позитивный контроль сборщиков в фазе 0** (§4.0 п.3). Если вносить в пак что-то одно, вносить это. ⚠ **Мандат самопроверки ИСПОЛНЕНИЕМ:** ревью СВОЕГО кода драйвера, СВОИХ запросов и ПОЛУЧЕННЫХ результатов. Субагентов спавнить **РАЗРЕШЕНО и требуется**, модель задавай ЯВНО. ⛔ Отрицательный замер печатает КОНТРОЛЬНУЮ ВЕЛИЧИНУ рядом с нулём. ⛔ **Критик полноты — на КАЖДУЮ фазу.** ## 6. Предметные оси ревью **Полигон/замеры:** пере-вывод чисел из СЫРЬЯ; вывод на агрегате до вскрытия единиц запрещён; ⚠ про «независимость сигналов» — читай §4.3 ИСПР. 9: здесь она ограничена, и это надо не обходить, а назвать. **Деньги:** из сырого леджера двумя путями; леджер — нижняя граница. ## 7. Записка-план ДО работы До первой команды — мне ≤15 строк: как ведёшь фазы · где ждёшь сопротивления · что считаешь спорным в заказе. Пре-рег-таблица §4.3 присылается ОТДЕЛЬНО и ДО фриза — я её читаю. Канала нет — обе идут секциями отчёта. ## 8. Заявление = команда Каждое число и каждая категорика — с командой и её выводом. **Число называет ДЕРЕВО и ПОПУЛЯЦИЮ.** ## 9. Эхо-протокол старта ДО первой команды — мне первым действием, по адресу из `/tmp/textmachine-channel` (`SendMessage`, роль `ОРКЕСТРАТОР`), ≤10 строк: скоуп · инварианты · не-делать — **СВОИМИ словами**. ## 10. Что НЕ удалось — обязательная секция отчёта Что не проверено · что не воспроизвелось · где данных не хватило · какой узел объявлен непройденным и почему. **«Не измерено» вместо догадки.** ## 11. Канал вопросов и право отказаться Конфликт промта с кодом — **пинг мне, НЕ интерпретация**. Право сказать «этого делать не надо» с аргументом — есть. Всё про деньги сверх названного — через меня. ## 12. Прямой канал `CLAUDE.md` §«Связь между сессиями»: `/tmp/textmachine-channel`, свой блок первым делом, живость — `ListAgents`. Роли нет или имя не отвечает ⇒ **КАНАЛА НЕТ, это НОРМАЛЬНЫЙ случай**, вопрос — секцией в отчёт. ## 13. Критерий завершённости Работа завершена, когда: **каждая строка пре-рег-таблицы имеет исход** · **у каждого пункта §4 есть исход** (сделано · не делаю с доводом · пинг) · **круги СОШЛИСЬ** — последний проход критика полноты не дал НОВЫХ находок · файл скачан и ПРОЧИТАН человеком (см. §4.1 п.4 — что это значит) · деньги сведены и расхождения названы · находки размечены «замерено / прочитано / подозрение» · фризы и девиации названы · артефакты в ДЕРЕВЕ · явное **«работа завершена, править не планирую»**. ⛔ **Пак доводишь до конца ТЫ.** Владельца не беспокоить, меня не тегать «просто так». ## Деньги — ДВА числа, и первое ИСПРАВЛЕНО ⛔ **ИСПР. 16: ожидание $0.30 было занижено дважды.** (а) главы 1–3 несут 39 % книги, а не 30 %; (б) опорный замер 08.09 снят на стенде с книжным потолком терминологии **$0.07**, тогда как у `c1` он **$2.00** — в 28 раз выше. ⇒ **ожидание $0.35–0.50, хвост до $0.65.** ⛔ **ИСПР. 17 — САМОЕ ДОРОГОЕ: «грант обязан покрывать холд, иначе допуск откажет» — НЕВЕРНО.** При нехватке баланса холд САМ ужимается ровно на книжный бонд и прогон **допускается** с `bondFunded = false` (`platform/internal/pricing/pricing.go:198-224`: `if base+bookOnce <= balance { … } return base, false`; пин зоны — баланс $1.00, книга 5 глав, бонд $2.00 → `covers_all`, `AffordableChapters = 5`, `BondFunded = false`). Отказ достижим только при балансе ниже ≈$0.26. **Следствие:** грант $2.00 даёт стартующий прогон, чей `--ceiling-usd` не несёт бонда, и терминологическая консолидация с классификатором ловят отказ резерва — «потолок, слишком малый для них, стоит КАЧЕСТВА, а не прогресса». Пре-рег измерит пайплайн без фазы майнинга и не узнает об этом. ⇒ **грант ≥ 1.25×expected + step_max + 2.00. $2.5 безопасно, $2.3 впритык, $2.0 — ТИХАЯ ДЕГРАДАЦИЯ.** **Пин пре-рега: `term_consistency_funded: true` в ответе ручки, иначе СТОП ДО оплаты.** ⛔ **Стоп-правила — каждое остановка и пинг, а не решение сессии:** - фактическая трата дошла до **$1.00** (порог поднят с $0.80: один оборванный ответ его сорвал бы); - `paused_reason` НЕПУСТО — любое из четырёх значений; - срез не совпал с пре-регом — стоп ДО оплаты; - `term_consistency_funded: false` — стоп ДО оплаты; - бинарь не из фриза — стоп до устранения. ## Отчёт `docs/experiments/24-<имя>.md` (пре-рег + результаты) + `eval/<каталог>/` + секция «Полигон» в `docs/PROGRESS.md` + сообщение мне: таблица «узел → ожидание → факт → чем предъявлено» · деньги с названными расхождениями · список сломанного с разметкой уверенности · что сказал критик полноты по КАЖДОЙ фазе · секция §10 · **что ты сам считаешь слабым местом прогона**. ⛔ Последний абзац отчёта — план или обещание? Значит работа не кончена: сделай сейчас.