550 lines
54 KiB
Markdown
550 lines
54 KiB
Markdown
# Промт: ХОЛОДНЫЙ ПРОГОН ДВИЖКА на схеме v16 (бэкенд-сессия, ПЛАТНАЯ)
|
||
|
||
> Выдан оркестратором №21, 31.08. Очередь — п.2 CURRENT-STATE в `docs/PROGRESS.md`.
|
||
> **ДЕНЬГИ САНКЦИОНИРОВАНЫ ВЛАДЕЛЬЦЕМ 31.08: ≈$0.60, потолок $0.80, ДЕСЯТЬ глав ПОЛНОЙ ЦЕПЬЮ
|
||
> включая редакторскую волну.** Прежняя цифра очереди «≈$0.05» снята как протухшая (§1в).
|
||
> ⚠ Промт прошёл два рубежа: механическую сверку 12 блоков и опровергатель в четыре линзы —
|
||
> 53 находки применены, 8 из них блокеры. Фактура ниже пере-проверена ИСПОЛНЕНИЕМ; где не смогли —
|
||
> сказано прямо.
|
||
|
||
## 0. Какая проблема и что решит твой результат
|
||
|
||
Движок переводит книги за деньги. С **27.08** в него легло семь коммитов и ~15 ратифицированных
|
||
решений: входная дверь шва, стоп банка ФЛАЖКОМ внутри движка, схема хранилища **v16**, полоса отказов
|
||
в два яруса с классом 15, объёмный потолок `--max-units`, гейт схемы, писатель книги (`tmctl build`).
|
||
**Ни одно из них не проверено деньгами.**
|
||
|
||
Проверено исполнением: последний платный вызов движка в корпусе — **17.08** (5 вызовов классификатора
|
||
в `coldrun-b/reprobe/classify6`, $0.005582), всё остальное — до 02.08. Ни один существующий леджер не
|
||
стоит на сегодняшней схеме, и ни один не гонял ПОЛНУЮ цепь на HEAD.
|
||
|
||
Значит все эти решения сегодня — обещания кода и тестов, а не факты о работающей системе.
|
||
|
||
**Твой результат** — первый платный сквозной прогон на текущем HEAD, который отвечает на один вопрос:
|
||
**переводит ли движок книгу насквозь и отдаёт ли файл — на настоящих деньгах, настоящих ключах,
|
||
настоящем провайдере.** Не «зелёная батарея», а книга, которую можно открыть.
|
||
|
||
Он же снимает гейт с чужих работ, ждущих его с 20.08: строки бэклога **202** (живой прогон через API
|
||
платформы) и **216** (подпись банка · halt на потолке · резюм после пополнения против ЖИВОГО движка).
|
||
Слово владельца 20.08: «гонять одну неготовую систему против другой смысла нет» — поэтому первым идёт
|
||
движок, один. Попутно и почти даром закрываются строки **154**, **157**, **160**, **198** (§5.7).
|
||
|
||
⚠ **Качество перевода — НЕ твой предмет.** Художественную оценку делает полигон. Ты меряешь МЕХАНИКУ и
|
||
ДЕНЬГИ. Границы предмета: ты не судишь, хорош ли перевод, не калибруешь ставку платформы и не трогаешь
|
||
дверь выдачи (её в платформе просто нет — `createExport`/`getExport` не смонтированы).
|
||
|
||
## 1. Что именно ты делаешь
|
||
|
||
### 1а. Форма прогона — делай РОВНО так
|
||
|
||
**Новый проект, новый каталог, новый `book_id`.** Ни один существующий стенд не переиспользуется.
|
||
Причины механические, все проверены исполнением:
|
||
|
||
1. **Схема.** Проектные БД корпуса стоят на **v7–v15** (на v14 — 13 из 36, одна на v15), бинарь HEAD —
|
||
на **v16**; число применяемых версий у каждого стенда своё. Мигрировать чужой стенд ради холодного
|
||
прогона — значит необратимо тронуть чужую улику.
|
||
2. **Конфиг.** Старый `book.yaml` с ключами `mined_delta:`/`mined_rejects:` **ОТКАЗЫВАЕТСЯ, exit 10**
|
||
(D39.158 п.5): пути решений теперь выводятся конвенцией `<каталог>/<book_id>.mined-delta.yaml`.
|
||
Такие ключи несут 17 файлов корпуса, включая оба прежних холодных прогона.
|
||
3. **Потолки.** Потолки существующих стендов пробиты новой ценой и защищать перестали (`coldrun-a`
|
||
`book_usd: 0.25` против пересчитанных ≈$0.56).
|
||
|
||
**Каталог:** `books/gu-zhenren/coldrun-v16/` — создаёшь ты.
|
||
|
||
**Исходник:** `books/gu-zhenren/coldrun-a/guzhenren-ch1-10.gb18030.txt`
|
||
(sha256 `0b5f9b0266d8…`, 28 174 знака без переводов строк, 10 глав). Копируешь к себе, оригинал не
|
||
трогаешь. Тождество байтов выбрано НАРОЧНО: **ровно этот файл лежит и под `bank-low`, и под `minirun`**,
|
||
то есть под обоими историческими базлайнами, с которыми ты сравниваешь деньги (§5.3).
|
||
|
||
**`pipeline.yaml` — копия `coldrun-b/reprobe/bank-low/pipeline.yaml`** с починенными по §1б путями.
|
||
Любое отличие выпиши в записку-план ПОСТРОЧНО: сравнимость денег держится на конфиге, а не только на
|
||
байтах исходника. **`escalation.budget_usd` обязан быть > 0** — в репозиторном шаблоне он 0, и тогда
|
||
«эскалационные хопы» §5.3 и запас $0.60→$0.80 меряют пустоту. **Сид: идём БЕЗ `glossary_seed`**, как
|
||
bank-low; решишь иначе — это пинг, а не выбор.
|
||
|
||
### 1б. ⚠ ЛОВУШКА ПУТЕЙ — главная в этом паке, проверь ПЕРВЫМ делом
|
||
|
||
На машине **ДВА чекаута** одного репозитория:
|
||
|
||
| Путь | Ветка | Что там |
|
||
|---|---|---|
|
||
| `/home/ubuntu/projects/textmachine-main` | `main` | ТВОЙ. HEAD с паком писателя книги |
|
||
| `/home/ubuntu/projects/textmachine` | **`polygon`** | ЧУЖОЙ, ветка полигона |
|
||
|
||
`books/` в твоём дереве — **СИМЛИНК** на `/home/ubuntu/projects/textmachine/books`; `/home/ubuntu/books`
|
||
— **тот же симлинк**. То есть корпус физически лежит в чужом чекауте и версионируется ОТДЕЛЬНЫМ git-репо.
|
||
|
||
⚠ **`book.yaml` несёт СЕМЬ абсолютных путей под ДВУМЯ разными корнями.**
|
||
- Под `/home/ubuntu/projects/textmachine/` — только **`models:`** и **`langpack_root:`**.
|
||
⇒ **ОБА переведи в `/home/ubuntu/projects/textmachine-main/backend/configs/…`.**
|
||
- Под `/home/ubuntu/books/` — `pipeline:`, `source_file:`, `project_db:`, `langpack_extend:`.
|
||
Это твой каталог прогона; они и должны смотреть туда.
|
||
- `prompt_override:` — если используешь, это `…-main/backend/prompts/`, НЕ `configs/`.
|
||
|
||
⚠ **ЕДИНСТВЕННОЕ ИСКЛЮЧЕНИЕ — `mining.contrast_path`.** Jieba-контраст лежит ТОЛЬКО в
|
||
`/home/ubuntu/projects/textmachine/eval/exp16/data/jieba_dict_general_zh.txt` (5 МБ, gitignored); в
|
||
`textmachine-main` его нет, а репозиторный `pipeline-c1.yaml` секции `mining:` не несёт вовсе. Оставь
|
||
путь в polygon-дереве как есть (чтение чужого чекаута законно) либо скопируй файл к себе. **Без него
|
||
`--verify-bank` отказывает, и ось §5.4 закрывается целиком.**
|
||
|
||
**Зачем всё это.** В polygon-дереве **нет каталога `langpacks/ru`** — он есть только в `main`. Два
|
||
чекаута `backend` различаются ТОЛЬКО этим: `models.yaml` и промпты совпадают побайтово, так что снапшот
|
||
прогона от выбора чекаута не зависит. Но `ru/reader.txt` — это слова, которые читатель видит на дыре.
|
||
`LoadReaderWords` на отсутствующий каталог возвращает дефолты **без ошибки**.
|
||
|
||
**Проверки исполнением, обе обязательны:**
|
||
1. `ls -d <твой langpack_root>/ru/reader.txt` — ДО покупки.
|
||
2. Ось закрывается только вторым шагом из §5.1 (`--partial` на книге с дырой). ⚠ **На complete-книге
|
||
ловушка НЕВИДИМА:** сборка с `langpacks/ru` и без него даёт побайтно один файл и ни одного WARN.
|
||
|
||
⚠ Дисциплина симлинка: `find books -name X` **без `-L` даёт ЛОЖНЫЙ НОЛЬ** (оркестратор на этом уже
|
||
попался). Всегда `find -L`. И никогда не создавай симлинков внутрь `books/`.
|
||
|
||
### 1в. Деньги — санкция владельца, делай РОВНО так
|
||
|
||
Очередь несла «≈$0.05». **Цифра устарела в ~4.5 раза:** DeepSeek пере-пинен коммитом **15.08**
|
||
(`76049bb`, D39.137) под вендорские цены, вступившие в силу **16.08 16:00 UTC** — flash
|
||
`input 0.14→0.44`, `output 0.28→1.32`; pro `0.435→1.32` / `0.87→3.96`. Заход `bank-low`, стоивший
|
||
$0.045095 в июльских деньгах, по этим ценам стоит **$0.2017** (множитель 4.47, пере-считано из его же
|
||
токенов).
|
||
|
||
**Слово владельца 31.08: ≈$0.60, потолок $0.80, ДЕСЯТЬ глав, ПОЛНАЯ ЦЕПЬ включая редакторскую волну.**
|
||
|
||
⚠ **«Потолок» здесь не абсолютный.** Он сверяется ДО каждого вызова против `committed + reserved`, но
|
||
против ОЦЕНКИ, а списывается факт — поэтому итог может выйти за $0.80 на величину порядка одной
|
||
максимальной резервации (`backend/internal/store/ledger.go` — «do not overshoot the ceiling by more
|
||
than one maximum reservation»). На этом объёме это центы; знать об этом обязана ты, а не отчёт.
|
||
|
||
Обязательны все три ручки:
|
||
|
||
- **`--ceiling-usd 0.80`** на `translate` — КНИЖНЫЙ КУМУЛЯТИВНЫЙ потолок, перекрывает `book.yaml`,
|
||
назад не пишется, обязан быть > 0;
|
||
- **`ceilings: { book_usd: 0.80, day_usd: 1.00 }`** в `book.yaml` — продублировать ОБА (Р7: конфиг
|
||
падает, если оба ≤ 0; день не должен срабатывать раньше книги);
|
||
- **`--max-units` — ДВУМЯ ПОРЦИЯМИ, и это несущее требование, а не оптимизация.**
|
||
- **Первая покупка:** `--max-units` заведомо малый (2–3 юнита). Обязана дать **exit 0** и строку
|
||
«Next: N output unit(s) … have never been delivered». Это **единственное живое предъявление
|
||
объёмного потолка** — механизма, который §0 называет среди проверяемых. При `--max-units` =
|
||
`units_total` он не сработает НИ РАЗУ и останется там же, где был: в тестах.
|
||
- **Вторая покупка:** остаток, `--max-units` = `units_total` из `tmctl manifest --json`. Уже
|
||
оплаченные юниты не считаются и не пере-оплачиваются. Сохрани WARN про майнящую банк книгу и
|
||
ЗАФИКСИРУЙ, потребовался ли `--resnapshot` — это живое основание `PD-422` и п.5 очереди.
|
||
|
||
⚠ **$0.60 — ОЖИДАНИЕ, $0.80 — потолок. Между ними запас на ретраи и эскалационные хопы**, которые
|
||
объёмный потолок не тратит, а деньги тратят. **Упёрся в $0.80 — это exit 4, СТОП и ПИНГ, а не тихая
|
||
пере-нарезка скоупа.** Подъём потолка просят при СРАБАТЫВАНИИ стопа, не по проекции: прогнозный запрос
|
||
оставляет ложный след «владелец согласился на пере-оплату», которой не было.
|
||
|
||
⚠ **Сметы ПЕРВОЙ покупки у движка НЕТ** — `--dry-run` у `translate` отвергается явно. Потолки и есть
|
||
твоя единственная защита. Смета ПЕРЕ-прохода существует, она $0 и без ключей.
|
||
|
||
⚠ **Гони в ДОЛИНУ.** У DeepSeek цена ходит окнами: пики **UTC 01–04 и 06–10 вдвое дороже**. Цены в
|
||
`models.yaml` пинованы ПИКОВЫЕ, поэтому в долине леджер завысит — это в безопасную сторону. **Время
|
||
старта запиши ПОЛЕМ в артефакт:** перенос машины обнулил mtime всего сырья, на mtime не опирается никто.
|
||
|
||
### 1г. Состав прогона
|
||
|
||
Гони **полную цепь, включая редакторскую волну, на ДЕСЯТИ главах** — объём и состав заданы словом
|
||
владельца (§1в), тобой не выбираются.
|
||
|
||
Довод, почему не draft-only, и он честный: проверено исполнением по всем **36** базам корпуса — роль
|
||
`judge` не вызывалась **НИ РАЗУ нигде**, а редакторская волна **гонялась и оплачена** на малых
|
||
прогонах (19 баз), но **НЕ на холодном старте**: у `coldrun-a` и во всей семье `coldrun-b` ноль
|
||
редакторских вызовов. Именно это держит строку бэклога **16**. Не измерена не «редактура вообще», а
|
||
ПОЛНАЯ ЦЕПЬ ОДНИМ ЗАХОДОМ на холодном старте: draft+терминолог и edit меряли разные стенды под разными
|
||
конфигами.
|
||
|
||
Десять глав выбраны ради сравнимости: тот же байтовый исходник и тот же объём, что у обоих исторических
|
||
базлайнов, поэтому множитель «июль → сегодня» получается без экстраполяции (§5.3).
|
||
|
||
⚠ Приор оркестратора, **опровергается твоим замером**: draft+терминолог ≈$0.20, редакторская волна на
|
||
тех же десяти главах ≈$0.38–0.40, итого ≈$0.58 при потолке $0.80. Не влезает — **стоп и пинг, не режь
|
||
скоуп молча**.
|
||
|
||
## 2. Зона записи и git
|
||
|
||
**Пишешь:** `books/gu-zhenren/coldrun-v16/` (каталог создаёшь) + отчёт сессии.
|
||
|
||
**Не пишешь:** `backend/`, `platform/`, `frontend/`, `eval/`. **`docs/` — тоже не пишешь**, и это
|
||
ОСОЗНАННОЕ сужение канона на этот пак: `CLAUDE.md` разрешает бэкенд-сессии писать итог в свою секцию
|
||
`docs/PROGRESS.md`, но здесь итог и пинги едут ОТЧЁТОМ, а в `PROGRESS.md` и `archive/reports/` их кладёт
|
||
оркестратор — иначе твоя строка уедет чужим коммитом из живого дерева. Пинг = секция отчёта либо
|
||
прямой канал §12.
|
||
|
||
- **Ты НЕ коммитишь.** Ни в этот репозиторий, ни в репозиторий книг. Лендит оркестратор.
|
||
- ⛔ **Книга и производные в репозиторий `textmachine` не коммитятся НИКОГДА** (CLAUDE.md).
|
||
- ⛔ **НИКОГДА:** `git add -A` · `git add .` · `git commit -a` · `reset --hard` · `checkout` поверх
|
||
грязного дерева · перезапись истории · `git stash` (стек общий с другими сессиями).
|
||
- В дереве лежит незакоммиченная работа ДРУГИХ живых сессий (`platform/**`) — **не трогать вообще**.
|
||
|
||
⚠ **Прогон НЕИЗБЕЖНО пачкает репозиторий КНИГ, и роли для него в проекте не определено.** Тот
|
||
репозиторий ОТСЛЕЖИВАЕТ `.db` (и `-wal`/`-shm`), а `.book.epub`/`.book.txt` его `.gitignore` не
|
||
покрывает; `tmctl migrate` переписывает отслеживаемый файл БД. В ролевой таблице `CLAUDE.md` зоны
|
||
`books` **нет вообще**. ⇒ **Ничего там не коммить и не прибирать.** Оставь `git -C books status`
|
||
грязным, назови его состояние в отчёте дословно, вопрос «кто коммитит книги» подними пингом.
|
||
|
||
⛔ **И ЧИТАТЬ чужие БД не безобидно.** `sqlite3 <db> …` **без `?mode=ro`** открывает базу НА ЗАПИСЬ,
|
||
чекпойнтит WAL и УДАЛЯЕТ отслеживаемые `-wal`/`-shm`. Проверено исполнением при подготовке пака: одна
|
||
SELECT-выборка по `coldrun-a` оставила две строки ` D` в чистом до того репозитории. ⇒ **Любое чтение
|
||
чужой базы — только `sqlite3 'file:<путь>?mode=ro'`.**
|
||
|
||
**Нашёл баг движка — ПИШИ, не чини.** Правка `backend/` — отдельный пак. Исключение ровно одно: если
|
||
без однострочной правки прогон физически не стартует, ты **пингуешь** и ждёшь, а не патчишь молча.
|
||
|
||
## 3. Карта чтения — ЗАКОН, пять позиций
|
||
|
||
1. **`docs/experiments/00-provider-quirks.md`** — ЦЕЛИКОМ и ДО первого платного вызова. Обязательное
|
||
пре-чтение перед любым обращением к провайдеру: живые слаги, thinking, `finish_reason`,
|
||
игнорируемые параметры. ⚠ Проба падает или ведёт себя странно ⇒ **идём в вендор-доку, НЕ гадаем**.
|
||
2. **`docs/architecture/18-bank-ontology.md`** — ратифицирована D39.158, обязательное пре-чтение перед
|
||
всем, что трогает банк. Три роли носителей · единственные писатели · дисциплина проекции.
|
||
3. **`backend/README.md`** — механика движка: волны, стадии, чанкование, артефакты.
|
||
4. **`docs/architecture/15-money-path.md` §2 «Деньги ДВИЖКА»** — леджер, оба потолка, leftover-reserved.
|
||
⚠ Якоря дока пере-проверены и починены 31.08, им можно верить.
|
||
5. **`docs/architecture/17-seam-inbound-law.md`** — закон входной двери шва.
|
||
|
||
Всё остальное — код первичен, достаёшь сама грепом. Ратифицированное вложено в тело этого промта.
|
||
|
||
## 4. Разметка свободы
|
||
|
||
**Делай РОВНО так (отступление = пинг оркестратору, не интерпретация):**
|
||
|
||
- новый каталог, новый `book_id`, `pipeline.yaml` — копия bank-low с `escalation.budget_usd > 0`,
|
||
без сида; чужие стенды не мигрировать и не переиспользовать (§1а);
|
||
- пути: `models:` и `langpack_root:` — в `textmachine-main`; `mining.contrast_path` — исключение (§1б);
|
||
- **число глав ДЕСЯТЬ и `--max-units` двумя порциями — санкция владельца (§1в), не твой выбор.**
|
||
⚠ Меньшее N на ВТОРОЙ покупке даёт остановку по объёму, а она печатает **exit 0** — ШТАТНОЕ
|
||
ЗАВЕРШЕНИЕ, неотличимое в коде от «книга переведена». Скоуп молча усохнет;
|
||
- бинарь `tmctl` **собрать из HEAD** своего дерева и записать `sha256`. Причина не в том, что стендовый
|
||
`~/.local/bin/tmctl` чего-то не умеет — он от 30.08 23:17 и пак писателя книги в нём есть, а на 31.08
|
||
он побайтно совпадает с HEAD-сборкой. Причина в том, что **личность бинаря, которым куплен прогон,
|
||
обязана быть зафиксирована числом**, а стенд пере-собирают чужие сессии без предупреждения;
|
||
- ключи — `--keys-file` **абсолютным** путём. Цепь резолва: окружение → `--keys-file` → `.env` рядом с
|
||
`book.yaml` → `./.env` в CWD. `--keys-file` **падает громко** на нечитаемом или пустом файле и
|
||
принимается **только `translate`**. Единственные заполненные файлы ключей на машине —
|
||
`/home/ubuntu/projects/textmachine/backend/.env` и `.../eval/.env` (576 Б, оба тронуты 30.08 01:01,
|
||
что совпадает со словом владельца «починил ключи 30.08»). ⛔ **Файлы ключей НЕ ОТКРЫВАТЬ** — ни тебе,
|
||
ни субагентам. Наполненность проверяется ПРОГОНОМ;
|
||
- оба денежных потолка выставлены до первого платного вызова (§1в);
|
||
- деньги считаются **из сырого леджера ДВУМЯ независимыми путями** (§6.3);
|
||
- **`make battery` в `backend/` ДО первой покупки.** Не `go test ./...` — батарея держит ещё
|
||
`vet -tags live`, `gofmt`, `golangci-lint` и `-race`, и только она гейт зоны. Скипы вслух;
|
||
- **`tmctl migrate` отдельным шагом** — что он применит и что печатает, см. §1а п.1 и §6.2;
|
||
- ⛔ **ПЕРВАЯ ЖЕ правка исходника закрывает платную часть НАВСЕГДА** — правило §5.6, и оно бьёт твою
|
||
свободу выбирать порядок фаз.
|
||
|
||
**Решаешь сама и аргументируешь:**
|
||
|
||
- порядок фаз внутри платной части и где ставить свои стоп-точки;
|
||
- нужен ли `--verify-bank` и в какой фазе (см. §5.4);
|
||
- какие дополнительные $0-пробы дёшевы и стоят того.
|
||
|
||
## 5. Что прогон обязан предъявить — по осям
|
||
|
||
### 5.1 Сквозной путь, структура глав и файл книги
|
||
|
||
`translate` → `status` → `report` → `manifest --json` → `export --json --pairs` (и отдельно голый
|
||
`export` — это РАЗНЫЕ каналы) → **`build`**.
|
||
|
||
**Шесть состояний честности D39.175 — это pending · withheld · incomplete · ghost · stale · drift, и
|
||
живут они в ТРЁХ разных местах**, отчего и разъезд счёта «шесть состояний, но пять дыр». Четыре —
|
||
перечисление `HoleKind` (`HolePending` · `HoleWithheld` · `HoleIncomplete` · `HoleStale`; пятая
|
||
константа `HoleNone` = дыры нет). Пятое, **ghost**, — не `HoleKind`, а счётчик `BookExport.GhostRows`:
|
||
переведённый текст, которому текущая нарезка не находит места; целостность он рубит наравне с дырами
|
||
(`complete := len(holes) == 0 && exp.GhostRows == 0`). Шестое, **drift**, — булево поле отчёта и WARN,
|
||
в файл не пишется.
|
||
|
||
**Твой прогон штатно даст ОДНО:** `complete=true` либо `pending`. Остальные — $0-провокации ПОСЛЕ
|
||
платной части, и порядок у них жёсткий: **§5.6**.
|
||
|
||
⚠ **`config_drift=false` и `stale_unknown=false` — самая дешёвая НОВАЯ фактура прогона.** Оба поля ни
|
||
разу не имели честного «нет»: все стендовые книги под дрейфом. **`stale_unknown=true` на свежей книге
|
||
означает СБОЙ, а не дрейф** — ищи его в WARN. ⇒ **Сохраняй stderr прогона целиком.**
|
||
|
||
**Структура глав — узел строки бэклога 160, и он $0.** По `manifest --json` назови: сколько глав
|
||
получили `heading` из текста, а сколько — цифровой рендер движка; совпадает ли число глав с 10; что
|
||
напечатано меткой главы в собранных EPUB и txt. На листе владельца висит ровно этот вопрос (В-4/Ф-30,
|
||
лейбл главы без заголовка) — приложи **дословные метки**, а не пересказ.
|
||
|
||
⚠ **Две ловушки `build`:**
|
||
1. `build --format epub` **МОЛЧА УДАЛЯЕТ** лежащий рядом `.book.txt` (и наоборот): набор рядом с БД
|
||
всегда от ОДНОЙ сборки. А `StatusArtifacts.book_files` публикует ПОЛНУЮ карту форматов независимо от
|
||
того, что записано. ⇒ **Собирай ОБА формата одной командой** (без `--format`) и не считай наличие
|
||
пути в `book_files` доказательством наличия файла.
|
||
2. После коммита файлов `build` удаляет копии незапрошенных форматов, и сбой этого `os.Remove`
|
||
возвращается ГОЛОЙ ошибкой ⇒ **exit 1 при том, что новые файлы УЖЕ на диске, а `BuildReport` не
|
||
печатается вовсе**. ⇒ **При ЛЮБОМ ненулевом коде посмотри, что реально лежит на диске.**
|
||
|
||
⛔ **ПОРЯДОК СБОРКИ.** Чистая книга собирается и СОХРАНЯЕТСЯ **до** любой правки исходника: собери оба
|
||
формата одной командой, скопируй пару файлов в `artifacts/clean/` внутри каталога прогона — и только
|
||
потом провоцируй. Демонстрацию `--partial` гони с `--out` в отдельный путь, иначе она перезапишет НА
|
||
МЕСТЕ ровно тот файл, который ты отдаёшь владельцу.
|
||
|
||
⚠ **Ось «издательский результат».** Клейм очереди «0 fatals / 0 errors на трёх стендовых EPUB» был «со
|
||
слов сессии»; **две трети пере-проверены независимо** при подготовке промта: `epubcheck` на машине НЕТ,
|
||
но java 21 есть и валидатор приносится одной командой; пере-собранный бинарём HEAD EPUB настоящего
|
||
перевода (стенд `minirun`) дал 0 fatals / 0 errors. Третья точка — **твой** EPUB.
|
||
⚠ Третий стенд (`acceptance`, единственный с `ghost`/`withheld`/`incomplete`) дёшево не пере-собирается
|
||
— его pipeline-конфиг протух по трём классам. Эти три состояния либо возникнут у тебя сами, либо
|
||
**останутся непроверенными, и так и запиши**.
|
||
⚠ **Живой читалки на машине нет ни одной.** Не изобретай: **передай файл владельцу** и назови ось
|
||
открытой до его ответа.
|
||
|
||
### 5.2 Коды выхода — таблица, сверяй фактические
|
||
|
||
| Код | Что случилось |
|
||
|---|---|
|
||
| 0 | чисто (в т.ч. остановка по `--max-units` — это ЗАВЕРШЕНИЕ) |
|
||
| 1 | инфраструктура, ошибка разбора флага, пойманная ПАНИКА |
|
||
| 2 | завершено С ФЛАГАМИ |
|
||
| 3 | стоп подписи банка (намеренная человеко-в-цикле пауза, НЕ падение) |
|
||
| 4 | halt по денежному потолку (книга или день) |
|
||
| 5 | graceful stop (пойман SIGINT/SIGTERM) |
|
||
| 10 | конфиг не поедет: нечитаем, неразбираем, невалиден, нет ключа |
|
||
| 11 | исходник КНИГИ не читается/не декодируется |
|
||
| 12 | проект залочен другим `tmctl` |
|
||
| 13 | схема проекта не этого бинаря — нужен `tmctl migrate` |
|
||
| 14 | документ решений прочитан и отклонён — решает ПОЛЬЗОВАТЕЛЬ |
|
||
| 15 | документ принят, запись не завершилась — отчёт называет, какой файл лёг; шли тот же документ снова |
|
||
| 16 | `build` отказался писать книгу с дырами — либо доделать, либо `--partial` |
|
||
| 19 | класс отказа, номера которому этот бинарь не знает |
|
||
|
||
Каждый код, который ты увидишь, — с командой и фактическим `$?`. Кода, которого не видела, не называй.
|
||
⚠ **Exit 15 у `build` на этом прогоне НЕДОСТИЖИМ** без инъекции сбоя ФС между двумя `rename` — не
|
||
заказываю. Но знай: 15 означает, что ЧАСТЬ файлов уже на диске.
|
||
|
||
### 5.3 Деньги
|
||
|
||
Разложи стоимость по стадиям и ролям и положи на **ОБА** исторических базлайна — они меряли разное, и
|
||
только вместе покрывают твою цепь:
|
||
|
||
- **`bank-low`** (`coldrun-b/reprobe/bank-low/guzhenren-bank-low.db`) — терминологический контур:
|
||
draft flash $0.021289 + draft pro $0.010350 = $0.031639 · терминолог $0.005750 · классификатор
|
||
$0.007706 · **весь заход $0.045095**;
|
||
- **`minirun`** (`books/gu-zhenren/minirun/guzhenren-minirun.db`) — РЕДАКТОРСКИЙ контур на том же
|
||
исходнике побайтно: draft flash $0.018834 (58) · draft pro $0.003371 (3) · **edit editor pro
|
||
$0.092086 (16)** · весь заход $0.114291.
|
||
|
||
Оба — в ИЮЛЬСКИХ деньгах. Твоя задача — дать то же разложение в СЕГОДНЯШНИХ и назвать множитель.
|
||
|
||
⚠ **Леджер = НИЖНЯЯ граница** (строка 78). «Оплаченный хвост» собирается из **ДВУХ таблиц**:
|
||
- по `checkpoints` — ретраи (`attempt>0`) и эскалационные хопы (`escalation=1`). ⚠ У `checkpoints`
|
||
**НЕТ `book_id`** — связь только через `JOIN jobs j ON c.job_id = j.id WHERE j.book_id=…`;
|
||
- по `request_log` — `ok=0 AND cost_usd>0` и `estimated=1`. ⚠ Колонок `attempt`/`escalation` в
|
||
`request_log` НЕТ, запрос по букве старой редакции упал бы.
|
||
|
||
⛔ **НЕ путь к сумме:** `chapters[].cost_usd` из `status --json` — это стоимость только ПОСЛЕДНЕЙ
|
||
резолюции строки.
|
||
|
||
⚠ **В денежных таблицах НЕТ идентификатора прогона:** `checkpoints` и `spend` пожизненные по книге,
|
||
единственная ось разделения прогонов в них — `checkpoints.created_at` (UTC). Ось прогона есть только в
|
||
телеметрии (`request_log.trace_id`). **Ты покупаешь ДВУМЯ порциями (§1в) — спланируй разбор заранее.**
|
||
|
||
### 5.4 Банк и стоп подписи
|
||
|
||
Стоп банка стал **флажком на НОВИЗНЕ** (D39.158 п.1): `--verify-bank` останавливает прогон перед
|
||
edit-волной **только** если в карте есть кластер, вся поверхность которого ещё не предъявлялась; память
|
||
предъявления — `bank_stop_presented`, схема v16. Прогон, который НЕ стопится, обязан свернуть
|
||
неподписанные строки в банк ПЕРЕД стадией.
|
||
|
||
⚠ **Нота проверяется ДВУМЯ прогонами — реши сама, влезает ли.** Первая половина: первый `--verify-bank`
|
||
даёт РОВНО ОДИН стоп. Вторая: повторный `--verify-bank` **БЕЗ единого решения по термам НЕ стопится
|
||
второй раз** — это и есть новизна-как-флажок. Проверив только первую, ты проверишь ноту наполовину, и
|
||
так и напиши. Наблюдаемое: `exit 3` · строка «the delta holds terms no stop has shown before» · строки
|
||
в `bank_stop_presented` · файл `<db>.mined-signature.yaml`. Провал записи памяти НЕ валит прогон — он
|
||
даёт один лишний доброкачественный стоп, и это штатно.
|
||
|
||
Форматы, изменившиеся и ни разу не виденные на живых данных: `<db>.mined-signature.yaml` получила
|
||
конверт `map_version: tm-signature-map-v1` + `map_id`; `<db>.bank.json` — якорь свежести `as_of`.
|
||
|
||
⚠ **Атомарность сайдкаров пере-проверена по коду 31.08:** через `writeFileAtomic` идут **ЧЕТЫРЕ** —
|
||
`<db>.manifest.json`, `<db>.bank.json`, `<db>.mined-signature.yaml`, `<db>.auto-bank.yaml`; неатомерен
|
||
**ОДИН** — `<db>.bank-stop.txt` (`os.WriteFile` с усечением; это отрендеренная ТАБЛИЦА, не JSON).
|
||
**Файла `bank-stop.json` не существует.** Форматы книги идут через staged-commit. ⚠ Прежняя запись №18
|
||
(«атомарны три из шести, среди них `bank-stop.json`») в этой части УСТАРЕЛА — если встретишь её в
|
||
доках, это она, а не твой результат.
|
||
|
||
**Строка бэклога 240** («оплаченный стоп подписи может исчезнуть МОЛЧА») заведена оркестратором №20
|
||
ЧТЕНИЕМ КОДА и честно помечена **PLAUSIBLE — сценарий не воспроизведён**. Её платформенную половину
|
||
берёт пак P12. Дёшево предъявишь что-то ЗА или ПРОТИВ — это ценнее чтения кода; дорого — не гонись,
|
||
скажи в obstacles.
|
||
|
||
### 5.5 Что ты оставляешь платформе (это и есть снятие гейта 202/216)
|
||
|
||
Платформа **сочинила сама** форму артефактов шва и никогда не видела настоящих. Каналов **ПЯТЬ**, а не
|
||
три: **манифест** (`manifest --json`) · **сайдкар банка** (`<db>.bank.json`) · **причины флагов** ·
|
||
**`events.jsonl`** (аутбокс схемы v15 — главный канал шва, который твой прогон и создаёт) ·
|
||
**`export --json --pairs`** (единственный канал, несущий ТЕКСТ).
|
||
|
||
**Чего ждёт другая сторона — читай в ЕЁ коде, не по памяти и не из этого промта** (D39.132): манифест —
|
||
`platform/internal/ingest/manifest.go`, сайдкар банка — `platform/internal/ingest/bank.go`, причины
|
||
флагов — `platform/internal/ingest/notes.go` (рукописный словарь причин → коды замечаний контракта).
|
||
Читать чужую зону можно, писать в неё нельзя.
|
||
|
||
⚠ **Карта причин флагов — НЕ файл движка:** движок отдаёт причины значениями `flag_reason` в
|
||
`export`/`status`; это и есть строка бэклога 204. Сравнивай наблюдённые значения со словарём
|
||
`notes.go`. ⚠ **Расхождений может не быть вовсе** — «сверено, расхождений ноль, вот обе стороны
|
||
списком» полноценный результат, а не пустая работа.
|
||
|
||
Каталог прогона остаётся на диске целиком; в отчёт положи ФОРМУ артефактов (структура, ключи, примеры
|
||
значений) — отчёт уедет в репозиторий, каталог нет.
|
||
|
||
**Дёшево и сверх заказа, если останется время** (обе пробы $0, обе после платной части): назови в
|
||
отчёте путь к своей БД и её размерности (глав/юнитов/строк) — `PD-297` платформы ждёт корпусную книгу
|
||
для замера round-trip, и без этого следующая сессия пере-покупает прогон.
|
||
|
||
### 5.6 $0-провокации ПОСЛЕ платной части — ЖЁСТКИЙ ПОРЯДОК
|
||
|
||
⛔ **ГЛАВНОЕ ПРАВИЛО, и оно бьёт твою свободу выбирать порядок фаз (§4): ПЕРВАЯ ЖЕ правка исходника
|
||
закрывает платную часть НАВСЕГДА.** После неё ни `translate`, ни `redrive` по этой книге не
|
||
запускаются. Причина — строка бэклога **238**, подтверждённая обеими половинами: резюм-фаст-пас
|
||
требует совпадения И `content_hash`, И снапшота; правка исходника НА МЕСТЕ (исходник в снапшот не
|
||
входит) роняет фаст-пас, и `translate` **перекупает юниты БЕЗ предупреждения в смете**. Гейт
|
||
`--accept-rebill` этот путь не ловит по конструкции. Единственный видимый след — INFO-строка
|
||
`manifest: the stored manifest is stale (source or cut changed)`.
|
||
|
||
Порядок проб — ровно такой:
|
||
|
||
1. **`stale`** — правка исходника, **РАВНАЯ ПО БАЙТАМ** и внутри чанка (сдвинешь границы нарезки —
|
||
получишь `ghost` вместо `stale`, а в отчёте напишешь, что stale проверен) → `status --json` →
|
||
`build`. ⛔ Идёт ПЕРВОЙ: `staleUnits` под config drift возвращает «неизвестно» сразу, ничего не
|
||
считая, а любая правка конфига двигает снапшот ⇒ `drift=true` ⇒ ось `stale` для этой книги закрыта
|
||
НАВСЕГДА.
|
||
2. **Строка 238** — на тех же данных: `status --json` скажет, что пере-оплаты нет, а `build` скажет
|
||
`stale N`. **Расхождение двух $0-поверхностей и есть предъявление строки.**
|
||
3. **`--partial` / дыры** — с `--out` в отдельный путь (§5.1), и здесь же глазами найти русскую строку
|
||
маркера дыры — это второй шаг оси §1б.
|
||
4. **Второй `--verify-bank`** (§5.4).
|
||
5. **Второй `translate`** — строка бэклога **198**: юниты резолвятся бесплатно; посмотри, появились ли
|
||
ПОВТОРНЫЕ анонсы юнитов в `events.jsonl`. Ключ анонса — `unit:<bookID>:<wave>:<chapter>:<unit>`, без
|
||
метки нарезки; это первый настоящий аутбокс на схеме v15 и первая возможность увидеть механизм на
|
||
данных, а не в коде.
|
||
6. **ПОСЛЕДНЕЙ — строка 239:** снять edit-стадию в **КОПИИ** `pipeline.yaml` → `status --json` покажет
|
||
`config_drift=false` и черновики как полную книгу, а `export`/`build` на том же конфиге покажут
|
||
дрейф. ⛔ Эта проба двигает снапшот, поэтому она последняя.
|
||
|
||
### 5.7 Что закрывается ДАРОМ — из того, что ты и так сохраняешь
|
||
|
||
**Строки бэклога 154 и 157** гейчены именно этим прогоном и закрываются числами, которые уже печатаются:
|
||
из stderr терминолога выпиши `families` / `families_refused` / `families_held`; из `manifest --json` —
|
||
распределение размеров юнитов (минимум/медиана/максимум знаков) и `units_total` по главам. Это
|
||
единственный носитель замера, на который обе строки гейчены; без него они переезжают на следующий
|
||
платный прогон.
|
||
|
||
## 6. Мандат самопроверки ИСПОЛНЕНИЕМ
|
||
|
||
Самоотчёт «проверено» без исполнения регулярно оказывается ложным и здесь стоит ДЕНЕГ.
|
||
|
||
**Тебе ЯВНО разрешены субагенты.** Модель задавай ИМЕНЕМ и знай, сколько их у тебя работает.
|
||
По умолчанию для трудного суждения — **Fable 5**; обычно хватает одного-двух, веер под предмет
|
||
выбираешь ты.
|
||
|
||
1. **Записка-план ДО первой покупки** — что покупаешь, каким потолком защищено, чем докажешь; `N` для
|
||
обеих порций `--max-units` названы числом. Пишется в каталог прогона **и ДОСЛОВНО повторяется первой
|
||
секцией отчёта**: отчёт уезжает в репозиторий, каталог прогона нет. Записка, дожившая только до
|
||
конца сессии, приёмке не предъявляется.
|
||
2. **Сухой проход $0 ПЕРЕД покупкой:** `status` · `manifest` · `report` ключей не требуют. ⚠ Но
|
||
`status`/`manifest` на никогда-не-запускавшейся книге **СОЗДАЮТ и мигрируют БД**. ⚠ На ТВОЕЙ свежей
|
||
книге `tmctl migrate` напечатает `migrate: created <db> at schema v16` (или `already at schema v16`);
|
||
**`backups/` НЕ появится** — restore point на новой БД не берётся. Строка `pre-migrate: backed up …
|
||
at schema v14` — контракт СУЩЕСТВУЮЩЕЙ книги, и её ты не увидишь. Хочешь увидеть глазами — сделай на
|
||
СВОЕЙ КОПИИ чужого стенда вне `books/`, и так и запиши.
|
||
3. **Деньги — двумя независимыми путями.** Оба печатает ОДНА $0-команда
|
||
`tmctl report --config book.yaml`: строка `Book ledger: committed=… reserved=…` считает
|
||
`SUM(spend.committed_usd)`, а `ROUTING/MONEY: … spend by model:` собирается из `checkpoints`.
|
||
Сойдутся — приводишь обе; разойдутся — это НАХОДКА, а не помеха.
|
||
4. **Активная проверка живости.** Раз в пару часов сверяй рост числа вызовов и трат по леджеру ДВУМЯ
|
||
чтениями. Зависшая задача от идущей неотличима по молчанию.
|
||
5. **Адверсариальный проход по СВОЕЙ ГОТОВОЙ работе — ПЕРЕД сдачей.** Не перечтение: субагент получает
|
||
твой отчёт, твои команды и мандат «найди, где она выдаёт непроверенное за проверенное».
|
||
**Артефакт — секция отчёта «Адверсариальный проход»:** какой моделью, сколько агентов, что каждому
|
||
дано на вход, и КАЖДАЯ находка дословно + твоя диспозиция (принято и исправлено / отклонено с
|
||
доводом). Ноль находок — тоже запись, но тогда назови, что именно субагент проверял и какими
|
||
командами.
|
||
Оси, на которых пак уязвим **по моему суждению** — приор, не потолок: клеймы о деньгах · клеймы о
|
||
кодах выхода, которых ты не видела · клейм «EPUB валиден» · утверждение, что артефакт совпал с
|
||
ожиданием платформы. Считаешь, что уязвимо другое (тождество нарезки, честность `complete`) —
|
||
замени ось с доводом и скажи об этом.
|
||
6. **Перед отчётом сверь КАЖДЫЙ клейм с результатом инструмента ЭТОЙ сессии.**
|
||
7. **Последний абзац отчёта — план или обещание? Сделай сейчас.**
|
||
8. **Интервальная сверка с заказом.** На каждой естественной границе (после сухого $0-прохода · после
|
||
первой порции · после edit-волны) прогоняй по осям §5 короткую сверку «что уже предъявлено / что ещё
|
||
нет», и хотя бы одну отдай субагенту с явными критериями §7. Длинная сессия дрейфует от заказа
|
||
незаметно для себя.
|
||
|
||
⛔ **Тесты и гейты не подгонять под зелень.** Править или удалять тест/голден/гейт, чтобы он прошёл, —
|
||
НЕДОПУСТИМО. Несогласие с тестом — пинг, не правка.
|
||
|
||
## 7. Записка-план и комплектность
|
||
|
||
До первой покупки — записка-план (§6.1). Перед сдачей — механическая сверка отчёта против §5 по осям:
|
||
каждая ось получает вердикт **предъявлено / не предъявлено / опровергнуто**. Три исхода, не два:
|
||
«не проверено» ≠ «опровергнуто».
|
||
|
||
## 8. «Заявление = команда»
|
||
|
||
Каждое число и каждая категорика отчёта идут С КОМАНДОЙ, которой получены. Приёмка пере-ранит
|
||
выборочно. Клейм о рантайме без живого прогона = **PLAUSIBLE**, и так и помечается. Клейм без
|
||
ре-рана — «со слов сессии».
|
||
|
||
## 9. Эхо-протокол старта
|
||
|
||
**ДО первой правки и ДО первой покупки** — ≤10 строк: скоуп / инварианты / чего не делаешь.
|
||
Отправь первым действием по каналу (§12). Эхо служит и проверкой канала.
|
||
|
||
## 10. Obstacle reporting
|
||
|
||
Обязательная секция отчёта: **что НЕ удалось и что НЕ проверено**. Отсутствие инструмента, недостижимая
|
||
ось, непонятое поведение — сюда. Пустая секция при непустой работе читается как дефект отчёта.
|
||
Ты вправе сказать «этого делать не надо» с аргументом — это поощряется, а не штрафуется.
|
||
|
||
## 11. Канал вопросов
|
||
|
||
Конфликт промта с кодом или доками ⇒ **пинг, НЕ интерпретация**. Промт мог устареть между написанием и
|
||
исполнением; код первичен. Настоящую развилку неси быстро.
|
||
**Правь курс через оркестратора:** mid-flight правки доезжают ТОЛЬКО релеем — владелец пере-передаёт
|
||
правку отдельным сообщением, ты эхо-подтверждаешь, и она отдельным пунктом отчёта.
|
||
|
||
## 12. Прямой канал
|
||
|
||
Механизм — `CLAUDE.md` §«Связь между сессиями»; файл **`/tmp/textmachine-channel`**. Впиши туда СВОЙ
|
||
блок первым делом, дописывая в КОНЕЦ и не трогая чужие. Перед тем как писать кому-то — сверься с
|
||
`ListAgents`: файл переживает смерть сессии, `ListAgents` нет.
|
||
⚠ Дословно: **нужной роли нет, файла нет или имя не отвечает ⇒ КАНАЛА НЕТ, и это НОРМАЛЬНЫЙ случай: НЕ
|
||
опрашивай сессии подряд.** Вопрос — секцией в отчёт.
|
||
|
||
---
|
||
|
||
## Приложение А. Известные грабли прежних холодных прогонов
|
||
|
||
Промт на холодный прогон писался ДВАЖДЫ, оба отработаны (`docs/archive/prompts/`). Третий заход (работа
|
||
C промта `BACKEND_EFFORT_HANDLE`, 02.08) закрыт владельцем как неуспешный — и **прогон там не начался
|
||
вовсе**. Техническая причина: `DeepSeek-V4-Flash-0731` сменил веса под тем же слагом, а thinking у
|
||
вендора включён по умолчанию с эффортом high.
|
||
⇒ **Слаг живой ≠ модель та же.** Перед покупкой сверь ПОВЕДЕНИЕ модели, а не только доступность слага.
|
||
|
||
`coldrun-b` заморожен ЛЕГИТИМНО: фаза C остановлена чекпойнтом по букве промта (критерий «0 пустых»
|
||
нарушен 8 из 9). Его собственная база ПУСТА — деньги «coldrun-b» потрачены в подпроектах `reprobe/*`.
|
||
Оба каталога — улика, read-only.
|
||
|
||
## Приложение Б. Готовые команды (проверены на HEAD, но пере-проверь)
|
||
|
||
```
|
||
# бинарь из HEAD + его личность
|
||
cd /home/ubuntu/projects/textmachine-main/backend && go build -o <твой путь>/tmctl ./cmd/tmctl
|
||
sha256sum <твой путь>/tmctl
|
||
|
||
# $0-глаголы, ключей не требуют, безопасны в любом порядке:
|
||
tmctl <report|status|export|build|manifest|backup|migrate> --config book.yaml
|
||
tmctl bank-apply --config book.yaml --decisions decisions.json [--dry-run]
|
||
tmctl seed-lint --seed glossary.yaml
|
||
|
||
# ⛔ ПЛАТНЫЕ:
|
||
# translate — твой глагол, см. §1в
|
||
# redrive — этот пак его НЕ заказывает НИГДЕ. Не запускай: он и платит, и разрушительно
|
||
# сбрасывает флаговую телеметрию, и принимает голую форму без селектора.
|
||
|
||
# полная стоимость из сырья — ⛔ ВСЕГДА mode=ro (§2)
|
||
sqlite3 'file:<db>?mode=ro' "SELECT printf('%.6f',COALESCE(SUM(committed_usd),0)),
|
||
printf('%.6f',COALESCE(SUM(reserved_usd),0)) FROM spend WHERE book_id='<id>';"
|
||
```
|