Issue the cold-run prompt under the owner's sanctioned budget and repair the money doc, whose fifty-one pointers were re-checked and whose form now survives drift
This commit is contained in:
parent
c14083ea66
commit
8e475fa2eb
6 changed files with 603 additions and 33 deletions
550
docs/BACKEND_COLDRUN_V16_SESSION_PROMPT.md
Normal file
550
docs/BACKEND_COLDRUN_V16_SESSION_PROMPT.md
Normal file
|
|
@ -0,0 +1,550 @@
|
|||
# Промт: ХОЛОДНЫЙ ПРОГОН ДВИЖКА на схеме 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>';"
|
||||
```
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -22,7 +22,7 @@
|
|||
| Роль | Активный промт | Статус |
|
||||
|---|---|---|
|
||||
| Оркестратор | [ORCHESTRATOR_SESSION_PROMPT.md](ORCHESTRATOR_SESSION_PROMPT.md) | роль и нормы; счётчик роли — CURRENT-STATE |
|
||||
| Бэкенд | активного НЕТ | пак «писатель книги» **ПРИНЯТ И ЗАЛЕНДЖЕН 30.08** (**D39.175**, `8adcb86`): `tmctl build` — EPUB 3 + чистый txt из `BookExport`, шесть состояний честности, отказ exit 16 / `--partial`, пути в `StatusArtifacts.book_files`. Слово владельца: drift — НЕ дыра файла, дверь выдачи обязана сверять `BuildReport`. Приёмка: 4 линзы + верификатор на каждую находку, два дофикса до лендинга. Промт отработан — `archive/prompts/`. Открыто строками **238/239**; вопросы владельцу (лестница D25.1 · лейбл К-3 · RTL) — CURRENT-STATE |
|
||||
| Бэкенд | [BACKEND_COLDRUN_V16_SESSION_PROMPT.md](BACKEND_COLDRUN_V16_SESSION_PROMPT.md) | **ВЫДАН 31.08** (**D39.179**): холодный прогон движка на схеме v16 — ПЕРВЫЙ ПЛАТНЫЙ сквозной прогон на текущем HEAD. Санкция владельца: ≈$0.60, потолок $0.80, десять глав ПОЛНОЙ цепью включая редакторскую волну; прежняя «≈$0.05» снята как протухшая. Гейт строк **16·154·157·160·198·202·216**. Оба рубежа пройдены: механическая сверка 12 блоков + опровергатель в четыре линзы — **53 находки, 8 блокеров**, все применены. Прежний пак «писатель книги» ПРИНЯТ И ЗАЛЕНДЖЕН 30.08 (**D39.175**, `8adcb86`): `tmctl build` — EPUB 3 + чистый txt, шесть состояний честности, отказ exit 16 / `--partial`. Открыто строками **238/239**; вопросы владельцу (лестница D25.1 · лейбл К-3 · RTL) — CURRENT-STATE |
|
||||
| Платформа | [PLATFORM_P12_SESSION_PROMPT.md](PLATFORM_P12_SESSION_PROMPT.md) | **ВЫДАН 30.08** сессии `textmachine-main-b5` (эхо принято; имя не переживает рестарт — адрес сверять `ListAgents`). Пак P12 «долги под ногами»: 7 открытых major (PD-425 деньги · PD-402/405 ложь экрана · PD-403/404 повторная продажа глав — решение владельца D39.165 §2 релеем · PD-424 замороженный холд) + снятие обхода `--verify-bank` (обязательство D39.158) + PD-369/431/432 + гигиена регистра. Оба рубежа пройдены: опровергатель (3 линзы + верификаторы) дал **21 удержанную находку**, все применены. Прежний пак `sqlc` — D39.172, промт в архиве: 40 запросов на типизированный слой, пин 1.31.1, `sqlc diff` в `make check`. ⚠ Решение принято НЕ доводом покрытия (3 из 42), а шестью ВЫЖИВШИМИ мутациями: `sqlgate` не видит Go-сторону вызова. Промт отработан — `archive/prompts/`. Открыто строками: `Touch` без проверки затронутых строк · `observe.go` неконвертируем |
|
||||
| Полигон | [POLYGON_EXP2223_REDO_SESSION_PROMPT.md](POLYGON_EXP2223_REDO_SESSION_PROMPT.md) (отложенный — [POLYGON_PACKAGE4_SESSION_PROMPT.md](POLYGON_PACKAGE4_SESSION_PROMPT.md), строка 85) | фаза Д ИДЁТ; ⚠ живой носитель курса — в `eval/dovodka/`, какой именно называет зона (⚠ [POLYGON_PHASE_D_HANDOFF.md](POLYGON_PHASE_D_HANDOFF.md) — перекрытый снимок, читать не как курс) |
|
||||
| Фронт | активного НЕТ | **ЗОНА ЗАМОРОЖЕНА** (D39.136 п.2 + D39.147: разморозка отдельным словом владельца, не привязана к P7); перечень первого касания — в зонном журнале |
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Реестр D-нот — карта актуальности v2 (D1–D39.178;
|
||||
# Реестр D-нот — карта актуальности v2 (D1–D39.179;
|
||||
|
||||
> ⚠ **СЛАБОЕ МЕСТО, КОТОРОЕ БЫЛО ЗДЕСЬ (вписано 22.08, ЗАКРЫТО 24.08 — D39.157 п.6).** Колонка ТЕЛА
|
||||
> у нот D39.107…D39.123 говорила «жив», хотя тела уехали в слайс подрезкой D39.139; семнадцать строк
|
||||
|
|
@ -240,3 +240,4 @@
|
|||
| D39.176 | 30.08 | **Пакет слов владельца по платформе**: продуктовых КВОТ НЕТ (живём на покупке API, бонусы из админки — `П-12`/`PD-175` сняты как продуктовая развилка, техническая гигиена остаётся инженерной) · продажа ПЛАНИРУЕТСЯ, но не в бете (`П-7` отложен, не отменён) · после пополнения баланса прогон возобновляется ЯВНЫМ действием (пункт снят с листа) · фразы пользователя ДЕЛЕГИРОВАНЫ проекту с требованием ИНТЕРНАЦИОНАЛЬНОСТИ — не литерал, а данные по коду причины и локали (гейт `PD-246`/строка 204). Ключи: движок берёт `--keys-file` ИЛИ конвенционный `.env`; холодный прогон разблокирован, живой через API — нет (платформа читает свой путь). | жив | ЖИВОЕ: на владельце остался ОДИН платформенный пункт — `PD-421` (держит ли открытый поток сессию живой), переформулирован | платформа продукт владелец квоты фразы |
|
||||
| D39.177 | 31.08 | **Передача роли оркестратора №20 → №21.** Смена приняла пак «писатель книги» (D39.175) и закрыла продуктовый лист платформы (D39.176), выдала промт P12 и ратифицировала минор 0.9.0 по пингу сессии. Три урока: опровергатель промта окупился в третий и четвёртый раз (62 находки; самая дорогая — «копия книги» через симлинк мигрировала бы ОРИГИНАЛ) · долг без носителя переживает приёмки (две находки ревью P9 прожили двое суток без строки) · якорь по номеру в файл живой сессии заведомо мёртв. Четыре ошибки названы; ТРИ из них поймал ВЛАДЕЛЕЦ вопросами «ты уверен / ты дочитал / почему не закрыл». Аудит всех живых доков: 57 находок, 55 применены. | жив | ЖИВОЕ: очередь №21 в CURRENT-STATE; пять обязательств переходят; незакоммиченное дерево пака P12 — норма, лендить при приёмке | передача процесс нормы аудит |
|
||||
| D39.178 | 30.08 (записано 31.08) | **Слово владельца о двери выдачи**: дверь `createExport` ВСЕГДА строит файл, отказ пользователю не отдаётся — неполная книга уходит с пометкой (`tmctl build --partial`), отказ exit 16 остаётся операторской ручкой CLI; D29.1(б) fail-closed читать как «никогда МОЛЧА»; дверь сверяет `BuildReport` — предупреждение оператору, не читателю. Ратификация жила в CURRENT-STATE без грепаемого носителя — пробел закрыт аудитом доков. | жив | ЖИВОЕ: лестница D25.1 (ступень копии без пометки) не решена, ждёт владельца перед дверью | контракт продукт выдача |
|
||||
| D39.179 | 31.08 | **Слово владельца о цене холодного прогона**: ≈$0.60, потолок $0.80, десять глав ПОЛНОЙ цепью включая редакторскую волну; прежняя санкция «≈$0.05» снята как протухшая (пере-пин DeepSeek, множитель 4.47). Промт `BACKEND_COLDRUN_V16_SESSION_PROMPT.md` выдан — 53 находки двух рубежей применены. Норма формы указателей заострена: стабильна не ЗОНА, а ЧИСТЫЙ ФАЙЛ. `arch-3` закрыт: 51 якорь пере-проверен, 34 уехали, сверяемых по содержимому 89→127 | жив | ЖИВОЕ: прогон не начат; строки 16·154·157·160·198·202·216 гейчены им | деньги прогон доки якоря |
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# Журнал решений оркестратора — контракт D1–D39.178 (живой файл: карта · эрраты · живые тела · голова D39.124+ (подрезка D39.139); тела закрытых эр — в слайсах `docs/archive/architecture/`, указатель ниже; реестр всех нот — `05-decisions-index.md`)
|
||||
# Журнал решений оркестратора — контракт D1–D39.179 (живой файл: карта · эрраты · живые тела · голова D39.124+ (подрезка D39.139); тела закрытых эр — в слайсах `docs/archive/architecture/`, указатель ниже; реестр всех нот — `05-decisions-index.md`)
|
||||
|
||||
> **⟶ КАРТА АКТУАЛЬНОСТИ (ревизия D31, продлена до D38.2 [12.07]; исторические записи ниже НЕ переписываются — дисциплина D23.3).** Работая с контрактом (греп номера: живой файл → слайсы, целиком НЕ читать — D39.125), держи под рукой, что чем перекрыто:
|
||||
> ⚠ **Эррата 09.08 (D39.125):** D39.111 п.1 предписывал промту S3 «максимум = баланс МИНУС открытые холды» — формула ОШИБОЧНА (вычитание дважды), исправлена D39.115 п.2(а): максимум = Balance КАК ЕСТЬ; тело D39.111 живёт ниже в этом файле (голова D39.106+).
|
||||
|
|
@ -1661,3 +1661,15 @@ head-1 это семнадцать бюджетируемых операций,
|
|||
2. **D29.1(б) «reader-facing выдача fail-closed» читать как «никогда МОЛЧА»,** а не «никогда не отдавать»: честность несут пометка на титуле и маркер на месте каждой дыры (D39.175), а не отказ. Молчаливый полный файл на книге с дырой по-прежнему запрещён.
|
||||
3. **Дверь дополнительно сверяет `BuildReport`** (`config_drift`/`stale_unknown`) — это предупреждение ОПЕРАТОРУ и интерфейсу, не читателю (D39.175 п.2).
|
||||
4. ⚠ **Граница осталась:** лестница D25.1 — какая ступень даёт читателю копию БЕЗ пометки и что печатать на титуле/в имени файла — НЕ решена и ждёт владельца между этим паком и дверью. Пока её нет, дверь строит по пп. 1–3.
|
||||
|
||||
## D39.179 — СЛОВО ВЛАДЕЛЬЦА 31.08 О ЦЕНЕ ХОЛОДНОГО ПРОГОНА + ВЫДАН ПРОМТ; норма формы указателей заострена (оркестратор №21). ✅
|
||||
|
||||
1. **Санкция владельца 31.08: ≈$0.60, потолок $0.80, ДЕСЯТЬ глав ПОЛНОЙ ЦЕПЬЮ включая редакторскую волну.** Из трёх предложенных вариантов владелец выбрал самый полный. **Прежняя цифра очереди «≈$0.05» СНЯТА как протухшая:** DeepSeek пере-пинен коммитом 15.08 (`76049bb`, D39.137) под цены, вступившие в силу 16.08 16:00 UTC; заход `bank-low` ($0.045095 в июльских деньгах) по ним стоит $0.2017 — множитель 4.47, пере-считан из его же токенов.
|
||||
|
||||
2. **Промт ВЫДАН** — `BACKEND_COLDRUN_V16_SESSION_PROMPT.md`. Оба рубежа пройдены: механическая сверка 12 блоков + опровергатель в четыре линзы дали **53 находки, 8 блокеров**, все применены. Механика — в самом промте, здесь не дублируется.
|
||||
|
||||
3. ⚠ **Эррата к п.1, названная перед владельцем:** санкция получена под формулировкой «редакторского вызова нет ни одного за всю историю проекта» — она ЛОЖНА и воспроизводила абсолют, уже исправленный №19 в строке бэклога 16. Верно: `judge` не вызывался НИ РАЗУ нигде, а редакторская волна гонялась и оплачена на 19 стендах; НЕ мерена **полная цепь ОДНИМ заходом на холодном старте** — у `coldrun-a` и всей семьи `coldrun-b` ноль редакторских вызовов. Смета от этого стала ТОЧНЕЕ, а не больше: стенд `minirun` гонял edit на побайтно ТОМ ЖЕ исходнике (sha256 `0b5f9b02…`) за $0.092086 июльскими, что и даёт ≈$0.38–0.40 сегодня. Число не пересматривалось.
|
||||
|
||||
4. **Норма формы указателей заострена (уточняет D39.177 §2в): стабильна не ЗОНА, а ЧИСТЫЙ ФАЙЛ.** Номер строки ставится только туда, где `git status <цель>` показывает файл чистым; файл с незакоммиченной правкой — чей угодно, включая `docs/` — получает греп-указатель без номера. Ось «зона» была НЕВЕРНА и поймана опровергателем на моей же правке: `14-api-contract/openapi.yaml` лежит в зоне оркестратора и при этом двигается паком контракта 0.9.0. Носитель нормы — шапка `15-money-path.md`.
|
||||
|
||||
5. **`arch-3` (major остатка аудита, строка 243) ЗАКРЫТ, и он был вдвое больше заявленного.** Аудит 30–31.08 называл «13 якорей, 9 не в тот код»; пере-проверка панелью нашла **51 указатель: 34 уехали, 1 мёртв, 16 верны**. Дороже адресов оказались КЛЕЙМЫ: дословная цитата контракта, которой в контракте нет; потерянный третий обязательный член `Usage`; живой К-13 при закрытом D39.132; метод `Settle`, которого у движкового `Store` нет; «смена потолка не двигает снапшот» без оговорки про `edit_ceiling_out`. **Корень механический:** 9 якорей из 12 РОДИЛИСЬ верными (`085dbb9`) и сгнили дрейфом, а гейт молчал по построению — по содержимому сверялись 89 якорей из ~818. Поэтому чинилась ФОРМА, не номера: сверяемых по содержимому стало **127**.
|
||||
|
|
|
|||
|
|
@ -1,60 +1,67 @@
|
|||
# Путь денег — от гранта до settle (топикальный вход, строка 167)
|
||||
|
||||
> **Статус: топикальный ВХОД, НЕ источник истины.** Док собирает денежную тему, размазанную по D-нотам, реестру дефектов платформы, глоссарию и бэклогу, в один маршрут чтения. При конфликте с чем угодно побеждает `docs/architecture/05-decisions-log.md` (правило чтения — диета D39.125: живой файл + слайсы). Каждое утверждение здесь снабжено указателем на первичный носитель; формулы — дословно оттуда. Словарь терминов (холд · прирост · аргумент потолка · baseline · settle · leftover-reserved · SpendBound) — `docs/glossary.md` §«Деньги платформы» (`glossary.md:50`).
|
||||
> **Статус: топикальный ВХОД, НЕ источник истины.** Док собирает денежную тему, размазанную по D-нотам, реестру дефектов платформы, глоссарию и бэклогу, в один маршрут чтения. При конфликте с чем угодно побеждает `docs/architecture/05-decisions-log.md` (правило чтения — диета D39.125: живой файл + слайсы). Каждое утверждение здесь снабжено указателем на первичный носитель; формулы — дословно оттуда. Словарь терминов (холд · прирост · аргумент потолка · baseline · settle · leftover-reserved · SpendBound) — `docs/glossary.md` §«Деньги платформы» (`docs/glossary.md:55`=`**Деньги платформы:**`).
|
||||
>
|
||||
> ⚠ **Форма указателей — норма этого дока (31.08, пере-проверены ВСЕ указатели: 34 уехали, 1 мёртв, 16 верны).**
|
||||
> **Стабильна не ЗОНА, а ЧИСТЫЙ ФАЙЛ.** Номер строки ставится только туда, где `git status <цель>` показывает файл чистым; файл с незакоммиченной правкой — чей угодно, включая `docs/` — получает греп-указатель без номера. Ось именно такая (D39.177 §2в), и зонная ось её НЕ заменяет: `docs/architecture/14-api-contract/openapi.yaml` лежит в «своей» зоне и при этом двигается прямо сейчас паком контракта 0.9.0.
|
||||
> Токен-форма — `` `путь:N`=`ожидаемая подстрока` ``; её гейт `docs/scripts/counts.py --lint` сверяет ПО СОДЕРЖИМОМУ и краснеет, когда цель уезжает.
|
||||
> ⚠ **Что гейт берёт с якоря БЕЗ токена:** существование файла и что номер не больше длины файла; у голого имени журнала решений — ещё и структуру (владелец строки обязан совпасть с названной рядом нотой). НЕ проверяется только СОДЕРЖИМОЕ — вот почему 34 якоря уехали молча. Голое имя без «/» не судится вовсе.
|
||||
> ⚠ **Греп-форма не проверяется гейтом никак** (регексп якоря требует `:номер`) — осознанный размен: переживает чужой WIP, но молчит.
|
||||
> ⚠ **Токен НЕ должен содержать бэктик:** регексп берёт токен как «всё до следующего бэктика» и обрезает хвост, а необрезанная часть не проверяется вовсе.
|
||||
|
||||
## 1. Канон одним абзацем
|
||||
|
||||
Деньги видимы с первого вызова: телеметрия, потолки, явное согласие на пере-оплату (CLAUDE.md, цель 5). Леджер без потолка запрещён — Р7: книга обязана нести хотя бы один из `book_usd`/`day_usd` (`backend/internal/config/book.go:250-251`, текст валидатора: «a ledger with no ceiling is forbidden, Р7»). Суммы на пользовательский экран НЕ выходят — запрет D39.84, подтверждён D39.100/К-8 («страница лимитов = СТАТУС, не суммы», D-лог `:196`) и держится в контракте (`14-api-contract/openapi.yaml:1152`: «No window, no `resets_at`, no sums»). Защита от перерасхода двойная и не зависит от событий: холд платформы делает кредит недоступным следующему прогону, а движок сам останавливается на потолке — «an overspend is impossible even while the platform is blind. The event stream is freshness only» (док-коммент `Hold`, `platform/internal/pgstore/credits.go:148-151`).
|
||||
Деньги видимы с первого вызова: телеметрия, потолки, явное согласие на пере-оплату (CLAUDE.md, цель 5). Леджер без потолка запрещён — Р7: книга обязана нести хотя бы один из `book_usd`/`day_usd` (`backend/internal/config/book.go:321`=`a ledger with no ceiling is forbidden`, текст валидатора: «a ledger with no ceiling is forbidden, Р7»). Суммы на пользовательский экран НЕ выходят — запрет D39.84, подтверждён D39.100/К-8 (дословно: «страница лимитов/использования в настройках (СТАТУС, не суммы — запрет денег на экране D39.84 в силе и НЕ superseded)» — `docs/architecture/05-decisions-log.md:232`=`СТАТУС, не суммы — запрет денег на экране`) и держится в контракте (`docs/architecture/14-api-contract/openapi.yaml`, греп `State of the credit balance. No window` — ⚠ номер не ставим: файл двигает пак контракта 0.9.0). Защита от перерасхода двойная и не зависит от событий: холд платформы делает кредит недоступным следующему прогону, а движок сам останавливается на потолке — «an overspend is impossible even while the platform is blind. The event stream is freshness only» (док-коммент `Hold` — `platform/internal/pgstore/credits.go`, греп `an overspend is impossible even`).
|
||||
|
||||
## 2. Деньги ДВИЖКА (зона `backend/`)
|
||||
|
||||
- **Леджер SQLite.** Таблица `spend`, две фигуры: `committed_usd` (потрачено, с сырым ответом провайдера) и `reserved_usd` (зарезервировано под летящий вызов). `Reserve` перед каждым платным вызовом сверяет `SUM(committed_usd + reserved_usd)` книги и дня с потолками (`backend/internal/store/ledger.go:44,58,63`; Р7 — коммент `:12`); `Settle` конвертирует резервацию в committed и персистит ответ (`ledger.go:162,199-210`). Суммарно по книге — `SpentUSD` (`ledger.go:314-320`).
|
||||
- **Леджер SQLite.** Таблица `spend`, две фигуры: `committed_usd` (потрачено, с сырым ответом провайдера) и `reserved_usd` (зарезервировано под летящий вызов). `Reserve` перед каждым платным вызовом сверяет `SUM(committed_usd + reserved_usd)` книги и дня с потолками (`backend/internal/store/ledger.go:44,58,63`=`func (s *Store) Reserve(`; Р7 — коммент `backend/internal/store/ledger.go:12`=`per-day (Р7); checked against`); `SettleWithCheckpoint` одной транзакцией конвертирует резервацию в committed и персистит ответ (`backend/internal/store/ledger.go:178`=`func (s *Store) SettleWithCheckpoint(`). ⚠ У ДВИЖКОВОГО `store.Store` метода `Settle` нет — он называется `SettleWithCheckpoint`; голое `Settle` пришло в прежнюю редакцию из словаря самого кода (`backend/internal/store/ledger.go:11`=`Reserve/Settle/ReleaseReservation semantics`). ⚠ Не спутать с ПЛАТФОРМЕННЫМ `credits.Settle` (§3 п.8) — это другой `Store`. ⚠ И прежний диапазон `199-210` — **ДРЕЙФ ЦЕЛИ, а не ошибка автора:** в `ledger.go` коммита `085dbb9`, где якорь ставился, строки 206-210 были ровно UPSERT настоящего settle (`committed_usd = committed_usd + excluded.committed_usd`), то есть якорь ПОДТВЕРЖДАЛ соседнее утверждение; сегодня тот же диапазон целиком лежит в ветке повторного settle («release the reservation, book no new spend»). Ровно этот дрейф и лечит токен-форма. Суммарно по книге — `SpentUSD` (`backend/internal/store/ledger.go:381`=`SpentUSD reports (committed, reserved)`).
|
||||
- **Гейт потолков — ПЕР-ВЫЗОВНЫЙ, и был им до эмиттер-пака** (`Reserve` на каждый свежий attempt; прежняя формулировка «на границе юнита» была неверна по отношению к потолкам — опровергнута приёмкой D39.131). На границе юнита сидел РЕПЭЙР-суб-бюджет — ужесточён до пер-вызовного с ценой вызова (строка 135 закрыта D39.131); эскалационный кап хоп НЕ прицениваает — перелёт ≤1 хопа, задокументирован и запинен (диспозиция D39.131 п.2д, реопен — живой инцидент).
|
||||
- **leftover-reserved зануляется write-open.** `store.Open` (путь записи, каждый `translate`) выполняет `recoverReservations` (`backend/internal/store/store.go:88`, функция `:218`: `UPDATE spend SET reserved_usd = 0 WHERE reserved_usd > 0`) — файл владеется одним процессом, значит любой reserved на открытии принадлежит несеттлённому прогону. `OpenReadOnly` этого прохода намеренно НЕ делает (`store.go:95-104`) ⇒ **reserved из read-only `status` — всегда остаток мёртвого процесса** (несущий факт формулы PD-158, см. §3).
|
||||
- **`--max-units` — ОБЪЁМНЫЙ потолок прогона, ортогональный денежному** (D39.165 §1б, принят D39.170). Ограничивает не деньги, а РАБОТУ: не больше N выходных ЮНИТОВ (гранулярность `units_total` манифеста — та же, в которой платформа продаёт главы) будет ОПЛАЧЕНО этим прогоном; юниты, отданные за $0 (резюм, ре-пин), ретраи и эскалации внутри юнита потолок не тратят. Принимает только `translate`. **Остановка по объёму — ЗАВЕРШЕНИЕ (exit 0), не пауза:** словарь кодов выхода не расширялся, различение живёт в отчёте прогона и в логе; отчёт разводит ДОСТАВКУ и ПЕРЕ-ДЕЛКУ. Носитель — `backend/internal/pipeline/volume.go`. ⚠ Проводка в платформу ГЕЙЧЕНА (`PD-422`): единственный писатель признака движения банка — дверь правок, рост АВТО-банка от майнинга флага не ставит.
|
||||
- **`--ceiling-usd` — КНИЖНЫЙ потолок, не бюджет прогона.** Дословно из флага: «the book USD ceiling in force for THIS RUN ONLY — it OVERRIDES book.yaml `ceilings.book_usd` and is never written back. It caps the book's CUMULATIVE committed+reserved spend, not this run's increment» (`backend/cmd/tmctl/invocation.go:114`; ⚠-коммент `main.go:110`). Ратификация — D39.122 п.2(в): пересчёт «пользовательский прирост → абсолют» — обязанность ПЛАТФОРМЫ, вторая денежная ось не заводится. День-потолок флаг НЕ перекрывает (PD-157). Проводка внутри: `Ceilings.BookUSD` в `Reserve` и именование сработавшего потолка в ошибке — `backend/internal/pipeline/stagerun.go:479-480,505-511` (стоп = `errReserveCeiling`).
|
||||
- **Потолки — wiring, не семантика:** `Ceilings` намеренно исключены из `BriefHash` («Wiring fields (paths, ceilings, db) deliberately excluded», `book.go:262-265`, канон `:267+`) ⇒ смена потолка не двигает ни снапшот, ни ре-билл (D39.110 п.2б).
|
||||
- **`status --json` отдаёт фигуры платформе:** `committed_usd`, `reserved_usd`, `book_ceiling_usd`, `ceiling_pct` = 100·(committed+reserved)/book_ceiling (`backend/internal/pipeline/status.go:155-158`). Дневной фигуры в status нет (PD-157).
|
||||
- **Леджер = НИЖНЯЯ граница** (строка 78 бэклога, `docs/PROGRESS.md:41`): «2xx body decode failed (call IS billed)» — провайдер списал, попытка в `request_log` не попадает; живой замер D39.86 — 3 вызова из 14, неизвестность $0.015111 при леджере $0.114378; движок сеттлит оценку и печатает `estimated-cost rows: 3`. Канал виден, фикс — money-паком (дизайн GENERALITY_PHASE2 §5.6).
|
||||
- **leftover-reserved зануляется write-open.** `store.Open` (путь записи, каждый `translate`) выполняет `recoverReservations` (`backend/internal/store/store.go:110`=`s.recoverReservations(ctx)`; сама функция — `backend/internal/store/store.go:278-279`=`UPDATE spend SET reserved_usd = 0`) — файл владеется одним процессом, значит любой reserved на открытии принадлежит несеттлённому прогону. `OpenReadOnly` этого прохода намеренно НЕ делает (`backend/internal/store/store.go:124`=`does not run that pass`) ⇒ **reserved, увиденный read-only `status` В МОМЕНТ СПАВНА, — остаток мёртвого процесса** (несущий факт формулы PD-158, см. §3). ⚠ Прежняя редакция писала «ВСЕГДА остаток мёртвого процесса» — это ШИРЕ кода и снято 31.08: `OpenReadOnly` построен ровно затем, чтобы `status` работал ВО ВРЕМЯ живого прогона (`backend/internal/store/store.go:122`=`allows concurrent readers while a writer is live`), и конкурентный `status` покажет ЖИВУЮ резервацию между `Reserve` и settle. Узко формулирует и сам код: «after a run crashes, reserved_usd stays non-zero until the next WRITE command» (`backend/internal/store/store.go:130`=`after a run crashes, reserved_usd stays non-zero`), и платформа — «at spawn there is no other writer … so anything reserved is by construction a leftover, never a live promise» (`platform/internal/runs/spawn.go`, греп `never a live promise`).
|
||||
- **`--max-units` — ОБЪЁМНЫЙ потолок прогона, ортогональный денежному** (D39.165 §1б, принят D39.170). Ограничивает не деньги, а РАБОТУ: не больше N выходных ЮНИТОВ (гранулярность `units_total` манифеста — та же, в которой платформа продаёт главы) будет ОПЛАЧЕНО этим прогоном; юниты, отданные за $0 (резюм, ре-пин), ретраи и эскалации внутри юнита потолок не тратят. Принимает только `translate`. **Остановка по объёму — ЗАВЕРШЕНИЕ (exit 0), не пауза:** словарь кодов выхода не расширялся, различение живёт в отчёте прогона и в логе; отчёт разводит ДОСТАВКУ и ПЕРЕ-ДЕЛКУ. Носитель — `backend/internal/pipeline/volume.go:12`=`the VOLUME ceiling — the run's second stop`; словарь флага дословно — `backend/cmd/tmctl/invocation.go:143`=`Stopping on it is a COMPLETION (exit 0), not a pause`. ⚠ Проводка в платформу ГЕЙЧЕНА (`PD-422`): единственный писатель признака движения банка — дверь правок, рост АВТО-банка от майнинга флага не ставит.
|
||||
- **`--ceiling-usd` — КНИЖНЫЙ потолок, не бюджет прогона.** Дословно из флага: «the book USD ceiling in force for THIS RUN ONLY — it OVERRIDES book.yaml `ceilings.book_usd` and is never written back. It caps the book's CUMULATIVE committed+reserved spend, not this run's increment…» (`backend/cmd/tmctl/invocation.go:142`=`the book USD ceiling in force for THIS RUN ONLY`; ⚠-коммент `backend/cmd/tmctl/main.go:260`=`--ceiling-usd is NOT a per-run budget`; многоточие закрывает обрыв цитаты — во флаге дальше стоит «, and must be > 0»). Ратификация — D39.122 п.2(в): пересчёт «пользовательский прирост → абсолют» — обязанность ПЛАТФОРМЫ, вторая денежная ось не заводится. День-потолок флаг НЕ перекрывает (PD-157). Проводка внутри: `Ceilings.BookUSD` в `Reserve` и именование сработавшего потолка в ошибке — `backend/internal/pipeline/stagerun.go:492`=`BookUSD: r.bookCeilingUSD()` и `backend/internal/pipeline/stagerun.go:521-523`=`overrides the book's ceilings.book_usd` (стоп = `errReserveCeiling`, `backend/internal/pipeline/escalation.go:49`=`var errReserveCeiling`).
|
||||
- **Потолки — wiring, не семантика:** `Ceilings` намеренно исключены из `BriefHash` («Wiring fields (paths, ceilings, db) deliberately excluded», `backend/internal/config/book.go:334`=`Wiring fields (paths, ceilings, db) deliberately excluded`; канон — `backend/internal/config/book.go:350`=`canon := struct {`) ⇒ смена ДЕНЕЖНОГО потолка не двигает ни снапшот, ни ре-билл (D39.110 п.2б). ⚠ Уточнено 31.08: это верно ровно про деньги. Потолок СЕГМЕНТАЦИИ `edit_ceiling_out` в снапшот ВХОДИТ и меняет границы чанков (`backend/internal/pipeline/snapshot.go:34`=`EditCeilingOut int`) — прежняя безоговорочная формулировка читалась как «любой потолок безопасен».
|
||||
- **`status --json` отдаёт фигуры платформе:** `committed_usd`, `reserved_usd`, `book_ceiling_usd`, `ceiling_pct` = 100·(committed+reserved)/book_ceiling (`backend/internal/pipeline/status.go:285`=`book_ceiling_usd,omitempty`; арифметика `ceiling_pct` — `backend/internal/pipeline/status.go:749`=`100 * (committed + reserved)`). Дневной фигуры в status нет (PD-157 — `platform/docs/DEFECT_REGISTER.md`, греп `PD-157`).
|
||||
- **Леджер = НИЖНЯЯ граница** (строка 78 бэклога, `docs/PROGRESS.md:84`=`Леджер денег = НИЖНЯЯ граница`): «2xx body decode failed (call IS billed)» — провайдер списал, попытка в `request_log` не попадает; живой замер D39.86 — 3 вызова из 14, неизвестность $0.015111 при леджере $0.114378; движок сеттлит оценку и печатает `estimated-cost rows: 3`. Канал виден, фикс — money-паком (дизайн GENERALITY_PHASE2 §5.6).
|
||||
|
||||
## 3. Деньги ПЛАТФОРМЫ по шагам (зона `platform/`)
|
||||
|
||||
1. **Грант.** `Grant` — строка леджера `kind='grant'`, идемпотентная по `(аккаунт, source, source_id)`: `on conflict (user_id, source, source_id) do nothing` (`platform/internal/pgstore/credits.go:38-49,357-362`). Фри-тир — тот же механизм в ТОЙ ЖЕ транзакции, что создание аккаунта (`pgstore/identity.go:86-88,153-155`; ⚠ **дефолт `SignupGrantMicroUSD` — НОЛЬ** (`platform/internal/config/config.go:262`), а не «5 × 1_000_000», как утверждала прежняя редакция: предложение «на бете дефолт в НОЛЬ» (D39.110 п.3) ИСПОЛНЕНО, `PD-104` в регистре стоит `fixed(P7)`. ⚠ Испр. аудитом доков 28.08 (D39.167) — ложная сумма стояла в ЕДИНСТВЕННОМ месте, куда идут за деньгами.
|
||||
2. **Выбор потолка — шкала в ГЛАВАХ** (D39.110: от 1 до максимума, ноль не выбираем; потолок принадлежит ПРОГОНУ, в `book.yaml` не пишется). **Максимум = Balance КАК ЕСТЬ** (D39.115 п.2а; эррата в шапке D-лога `:4`): `Hold` — дебет в момент взятия, баланс уже не содержит открытых холдов, повторное вычитание вдвое укорачивает шкалу. Реализация: `pricing.Model.Scale` — `affordable = balance / PerChapter`, кламп по остатку глав, дефолт = верх шкалы (ратифицировано D39.123 п.2е; компромисс «весь баланс под одну книгу» принят осознанно) — `platform/internal/pricing/pricing.go:75-98`.
|
||||
3. **Ставка $0.03/глава — конфиг-константа платформы:** `DefaultPerChapter = 30_000` micro-USD (`pricing.go:33`), переопределяется `PerChapterMicroUSD` (`config.go:90-93,194,229`). ⚠ **Провенанс ниже — ИСТОРИЯ, а не действующее обоснование (D39.165 §1, 28.08):** реальная цена главы замерена по движковым леджерам — средняя **$0.0115–$0.0190**, максимум одной главы $0.0375, то есть константа завышена в **1.6–2.6×**, и «купить 10 глав» отдаёт движку $0.30, покупающий ~16–26 глав («денежная ручка с подписью „главы"», `PD-410`). РЕШЕНО: цена — от ОБЪЁМА ИСХОДНИКА (носитель `chapters.units_total`, пишется интейком за $0), настоящий стоп — объёмный потолок В ДВИЖКЕ (см. §2). ⛔ Константу по сегодняшним числам НЕ калибровать (D39.165 ⛔г) — гейт строка 202. Исторический провенанс: exp08 v2 $0.0219/глава → ревизия D30.4 +15–25% → округление ВВЕРХ (низкая ставка опаснее высокой — прогон встанет на потолке посреди книги; `pricing.go:19-33`). Временная мера беты — честная оценка движковая (строка 166).
|
||||
4. **Холд прироста ДО спавна.** `holdTx` пишет отрицательную строку `('hold', -amount)` и тем же знаком двигает кэш баланса (`credits.go:163-206,375-385`); нехватка — `ErrInsufficientCredit`. Холд + прогон + попытка + очередь — одна транзакция (`pgstore/runs.go:104` StartRun, `:338` рестарт; форма D39.123 п.2д).
|
||||
5. **Аргумент движку: `bookCap = committed + прирост×ставка`, БЕЗ reserved — PD-158, дословно из кода: `return m.committed + increment`** (`platform/internal/runs/spawn.go:195-196`). Обе фигуры читаются ОДНИМ вызовом `status --json` перед стартом (`bookMeter`, `spawn.go:206-223`); отсутствие любой из них = отказ спавна («absent is not zero», PD-40). Почему без reserved: write-open движка занулит leftover до первой резервации, значит цифра из read-only status к моменту сравнения уже мертва; ратифицированная ранее формула с reserved переплачивала запасом ровно на leftover сверх холда — исполнено обеими формулами против гейта (D39.123 п.2б, поправка к D39.122(в)). Аргумент ≠ холд: он больше холда на committed (глоссарий `:50`). Фактически ушедшее значение хранится в `run_attempts.ceiling_arg_micro_usd` (PD-144, миграция 00011); потолок уходит argv-шаблоном `{{usd}}` (`config.go` `CeilingArg`, `spawn.go:132-150`); строка 145 закрыта D39.122.
|
||||
6. **Baseline и списание.** `baseline = committed` книги на старте попытки (`platform/internal/runs/spawn.go:82`=`baseline, bookCap := m.committed`); списание попытки = разница счётчика с baseline; счётчик ниже baseline = подменённая БД, сеттлится в ноль с WARN — сами цифры в лог не идут (D39.84; `reconcile.go:308-316`).
|
||||
1. **Грант.** `Grant` — строка леджера `kind='grant'`, идемпотентная по `(аккаунт, source, source_id)`: `on conflict (user_id, source, source_id) do nothing` (`platform/internal/pgstore/credits.go`, греп `func (s *Store) Grant(`; сама идемпотентность после пака sqlc уехала В ЗАПРОС — `platform/internal/pgstore/queries/credits.sql`, греп `on conflict (user_id, source, source_id) do nothing`). Фри-тир — тот же механизм в ТОЙ ЖЕ транзакции, что создание аккаунта (`platform/internal/pgstore/identity.go`, греп `appendLedger(ctx, tx, userID, "grant"`; ⚠ **дефолт `SignupGrantMicroUSD` — НОЛЬ** (`platform/internal/config/config.go`, греп `SignupGrantMicroUSD:`), а не «5 × 1_000_000», как утверждала прежняя редакция: предложение «на бете дефолт в НОЛЬ» (D39.110 п.3) ИСПОЛНЕНО, `PD-104` в регистре стоит `fixed(P7, дерево сессии)`). ⚠ Испр. аудитом доков 28.08 (D39.167) — ложная сумма стояла в ЕДИНСТВЕННОМ месте, куда идут за деньгами; якоря переведены на греп-форму и закрыта висевшая скобка — 31.08.
|
||||
2. **Выбор потолка — шкала в ГЛАВАХ** (D39.110: от 1 до максимума, ноль не выбираем; потолок принадлежит ПРОГОНУ, в `book.yaml` не пишется). **Максимум = Balance КАК ЕСТЬ** (D39.115 п.2а; эррата в шапке D-лога — `docs/architecture/05-decisions-log.md:4`=`Balance КАК ЕСТЬ`): `Hold` — дебет в момент взятия, баланс уже не содержит открытых холдов, повторное вычитание вдвое укорачивает шкалу. Реализация: `pricing.Model.Scale` — `affordable = balance / PerChapter`, кламп по остатку глав, дефолт = верх шкалы (ратифицировано D39.123 п.2е; компромисс «весь баланс под одну книгу» принят осознанно) — `platform/internal/pricing/pricing.go`, греп `func (m Model) Scale(`.
|
||||
3. **Ставка $0.03/глава — конфиг-константа платформы:** `DefaultPerChapter = 30_000` micro-USD (`platform/internal/pricing/pricing.go`, греп `DefaultPerChapter`), переопределяется `PerChapterMicroUSD` (`platform/internal/config/config.go`, греп `PerChapterMicroUSD`). ⚠ **Провенанс ниже — ИСТОРИЯ, а не действующее обоснование (D39.165 §1, 28.08):** реальная цена главы замерена по движковым леджерам — средняя **$0.0115–$0.0190**, максимум одной главы $0.0375, то есть константа завышена в **1.6–2.6×** — ⚠ но НЕ покрывает максимум: источник (D39.165 §1) добавляет «и отдельные главы её уже пробивают» ($0.0375 против $0.03 = ×1.25), и прежняя редакция это теряла, и «купить 10 глав» отдаёт движку $0.30, покупающий ~16–26 глав («денежная ручка с подписью „главы"», `PD-410`). РЕШЕНО: цена — от ОБЪЁМА ИСХОДНИКА (носитель `chapters.units_total`, пишется интейком за $0), настоящий стоп — объёмный потолок В ДВИЖКЕ (см. §2). ⛔ Константу по сегодняшним числам НЕ калибровать (D39.165 ⛔г) — гейт строка 202 бэклога (`docs/PROGRESS.md:182`=`Живой перевод книги НАСКВОЗЬ через API платформы`). Исторический провенанс: exp08 v2 $0.0219/глава → ревизия D30.4 +15–25% → округление ВВЕРХ (низкая ставка опаснее высокой — прогон встанет на потолке посреди книги; `platform/internal/pricing/pricing.go`, греп `Provenance, so the number is auditable`). Временная мера беты — честная оценка движковая (строка 166 бэклога, `docs/PROGRESS.md:154`=`Движковая поверхность оценки`).
|
||||
4. **Холд прироста ДО спавна.** `holdTx` пишет отрицательную строку `('hold', -amount)` и тем же знаком двигает кэш баланса (`platform/internal/pgstore/credits.go`, греп `func holdTx(` — строку леджера пишет `appendLedger(… "hold", -amount …)`, кэш баланса двигает `MoveBalance` внутри неё); нехватка — `ErrInsufficientCredit`. Холд + прогон + попытка + очередь — одна транзакция (`platform/internal/pgstore/runs.go`, греп `func (s *Store) StartRun(`; рестарт — греп `func (s *Store) RestartRun(`; форма D39.123 п.2д).
|
||||
5. **Аргумент движку: `bookCap = committed + прирост×ставка`, БЕЗ reserved — PD-158, дословно из кода: `return m.committed + increment`** (`platform/internal/runs/spawn.go`, греп `return m.committed + increment`). Обе фигуры читаются ОДНИМ вызовом `status --json` перед стартом (`bookMeter` — `platform/internal/runs/spawn.go`, греп `func (s *Service) bookMeter(`; отказы — греп `Absent is not zero`); отсутствие любой из них = отказ спавна («absent is not zero», PD-40). Почему без reserved: write-open движка занулит leftover до первой резервации, значит цифра из read-only status к моменту сравнения уже мертва; ратифицированная ранее формула с reserved переплачивала запасом ровно на leftover сверх холда — исполнено обеими формулами против гейта (D39.123 п.2б, поправка к D39.122(в)). Аргумент ≠ холд: он больше холда на committed (`docs/glossary.md:55`=`ЭТО НЕ ХОЛД`). Фактически ушедшее значение хранится в `run_attempts.ceiling_arg_micro_usd` (PD-144, миграция 00011); потолок уходит argv-шаблоном `{{usd}}` (шаблон — `platform/internal/config/config.go`, греп `CeilingArg`; подстановку делает `platform/internal/runner/engine.go`, греп `{{usd}}`; подстановку и рендер argv делает `platform/internal/runner/engine.go`, греп `func (t CeilingTemplate) Args(`; `platform/internal/runs/runs.go`, греп `func (s *Service) ceilingFor(` — однострочная делегация к нему — ⚠ прежняя редакция называла здесь `spawn.go`, который потолок только передаёт); строка 145 закрыта D39.122.
|
||||
6. **Baseline и списание.** `baseline = committed` книги на старте попытки (`platform/internal/runs/spawn.go`, греп `baseline, bookCap := m.committed`); списание попытки = разница счётчика с baseline; счётчик ниже baseline = подменённая БД, сеттлится в ноль с WARN — сами цифры в лог не идут (D39.84; `platform/internal/runs/reconcile.go`, греп `the book's meter reads below`).
|
||||
7. ⚠ **Терминальный вердикт ОПЕРАТОРА — путь холда мимо settle (добавлено 22.08, P8-FIX/D39.154).** Прогон, чей движок не ответит уже никогда, закрывает человек: `tmplatformctl run abandon --run <id> --reason <текст> [--release-hold]`. Команда ОТКАЗЫВАЕТ, если попытка ещё называет юнит или несёт базовую линию траты — над живым движком прогон не закрывают. Холд возвращается ЦЕЛИКОМ в обоих случаях (к abandon допускается только попытка, не дошедшая до движка, значит она ничего не потратила), а флаг решает лишь КОГДА — сразу или на ближайшем свипе. До этого пака такого пути не было вовсе: холд чужого аккаунта висел, пока кто-нибудь не залезет в БД руками.
|
||||
|
||||
8. **Settle по фигуре движка.** `reconcile.settle` (`platform/internal/runs/reconcile.go`, греп `func (s *Service) settle(` — ⚠ номера строк в файлы живой зоны не ставим, пока её сессия работает) читает committed из status; `credits.Settle` одной транзакцией закрывает резервацию, возвращает холд и списывает spent; **spent > холда — капится холдом** с явной пометкой «capped at the hold; the engine reported …» (`credits.go:214-234`), перерасход движка счётом не абсорбируется.
|
||||
9. **SpendBound (PD-159).** Отложенный settle читает пожизненный счётчик КНИГИ и без границы оплатил бы работу прогона-преемника (замер: $2.10 за прогон ценой $0.10, и преемник платил снова). Граница = наименьший baseline попыток той же книги, стартовавших ПОЗЖЕ: `committed = min(счётчик сейчас, SpendBound)` (`reconcile.go:293-307`; `pgstore/runs.go:268`).
|
||||
10. **Открытое — эскроу/intent (строка 136, `docs/PROGRESS.md:85`):** write-ahead intent + состояние `uncertain`-эскроу + `closing`; холд НЕ освобождается по выходу юнита (сигнал обгоняет денежные события); spend не постится без свидетельства провайдера; расход сверх холда — полной суммой, превышение явной строкой убытка. Стройка по research/25, «скоро». До эмиттера (строка 103) платформа между спавном и settle слепа — защита держится холдом и потолком движка (§1).
|
||||
8. **Settle по фигуре движка.** `reconcile.settle` (`platform/internal/runs/reconcile.go`, греп `func (s *Service) settle(` — ⚠ номера строк в файлы живой зоны не ставим, пока её сессия работает) читает committed из status; `credits.Settle` одной транзакцией закрывает резервацию, возвращает холд и списывает spent; **spent > холда — капится холдом** с явной пометкой «capped at the hold; the engine reported …» (`platform/internal/pgstore/credits.go`, греп `capped at the hold; the engine reported`), перерасход движка счётом не абсорбируется.
|
||||
9. **SpendBound (PD-159).** Отложенный settle читает пожизненный счётчик КНИГИ и без границы оплатил бы работу прогона-преемника (замер: $2.10 за прогон ценой $0.10, и преемник платил снова). Граница = наименьший baseline попыток той же книги, стартовавших ПОЗЖЕ: `committed = min(счётчик сейчас, SpendBound)` (`platform/internal/runs/reconcile.go`, греп `bound != nil`; `platform/internal/pgstore/runs.go`, греп `func (s *Store) SpendBound(`).
|
||||
10. **Открытое — эскроу/intent (строка 136 бэклога, `docs/PROGRESS.md:127`=`Write-ahead intent`):** write-ahead intent + состояние `uncertain`-эскроу + `closing`; холд НЕ освобождается по выходу юнита (сигнал обгоняет денежные события); spend не постится без свидетельства провайдера; расход сверх холда — полной суммой, превышение явной строкой убытка. Стройка по research/25, «скоро». ⚠ **«Строка 103» — ФАНТОМ, снят 31.08:** такой строки в бэклоге нет (закрыта D39.131), а эмиттер шва ПОСТРОЕН с обеих сторон — платформа тейлит `events.jsonl` и принимает кадр `spend` (`platform/internal/ingest/events.go`, греп `TypeSpend Type`). Денежной слепоты это НЕ снимает по построению: поток событий — только свежесть. Платформа между спавном и settle слепа — защита держится холдом и потолком движка (§1).
|
||||
|
||||
## 4. Фронт (зона `frontend/`)
|
||||
|
||||
Максимум шкалы — `Balance` КАК ЕСТЬ (D39.115 п.2а); `Reserved` — справочная величина, `ReadAccount` отдаёт обе раздельно (`pgstore/credits.go:99`). Шкала — в ГЛАВАХ: `CeilingBounds` — «in CHAPTERS. The chapters → money conversion lives on the platform and is not exposed here in any form»; клиенту запрещено клампить повторно; `max_chapters: 0` = состояние «исчерпано» вместо шкалы (`openapi.yaml:1116-1147`). Суммы на экран не идут: `Usage` = `state` (ok/low/exhausted) + `remaining_percent`, без окон и сумм (`openapi.yaml:1149-1165`); продуктовый носитель — ПТ-35 (`docs/product-requirements.md:62`): стоп по потолку = `paused` + оповещение «перевод остановлен: лимиты исчерпаны»; остаток — страница лимитов (S4+), слово владельца В-3, К-13 (`paused_reason` не различает «свой потолок» и «нет кредита»).
|
||||
Максимум шкалы — `Balance` КАК ЕСТЬ (D39.115 п.2а); `Reserved` — справочная величина, `ReadAccount` отдаёт обе раздельно (`platform/internal/pgstore/credits.go`, греп `func (s *Store) ReadAccount(`). Шкала — в ГЛАВАХ: `CeilingBounds` — «in CHAPTERS. The conversion to money lives on the platform and is not exposed here in any form» (`docs/architecture/14-api-contract/openapi.yaml`, греп `The conversion to money lives on the platform`); клиенту запрещено клампить повторно; `max_chapters: 0` = состояние «исчерпано» вместо шкалы. ⚠ Прежняя цитата «The chapters → money conversion …» УСТАРЕЛА ВМЕСТЕ С КОНТРАКТОМ, а не была ошибкой автора: контракт пере-сверстал её в «The conversion to money …», а «run-ceiling scale» — в «run-limit scale». Сегодня `grep -c 'chapters → money'` = 0. Испр. 31.08 — и это цена дословной цитаты без токена, а не небрежность. Суммы на экран не идут: `Usage` несёт ТРИ обязательных члена — `state` (ok/low/exhausted), `remaining_percent` и `halt_reason` — и ни окон, ни сумм (`docs/architecture/14-api-contract/openapi.yaml`, греп `required: [state, remaining_percent, halt_reason]`; ⚠ третий член `halt_reason` добавлен контрактом ПОЗЖЕ этой строки дока — знак равенства устарел вместе с ним, испр. 31.08); продуктовый носитель — ПТ-35 (`docs/product-requirements.md:63`=`ПТ-35`): стоп по потолку = `paused` + оповещение «перевод остановлен: лимиты исчерпаны»; остаток — страница лимитов (S4+), слово владельца В-3. ⚠ **К-13 ЗАКРЫТ** (D39.132 п.2а: `null` на проводе; пере-суждён ревью 28 §4 №9 и НЕ опрокинут — с уходом дневной оси различие перестало быть продуктовым): прежняя редакция держала его живым различением «свой потолок / нет кредита», испр. 31.08 по ПТ-35.
|
||||
|
||||
## 5. Открытые дыры и их носители
|
||||
|
||||
| Дыра | Носитель |
|
||||
|---|---|
|
||||
| ~~PD-113 (major)~~ **ЗАКРЫТ P6/D39.132** (испр. оркестратором 15.08): обе половины построены — событие `ceiling{scope}` + exit 4 (движок, D39.131) и потребитель (платформа, П-15): потолочный стоп = `paused` двумя независимыми каналами, причина пишется одним оператором со статусом и перечитывается после drain. ⚠ **Хвост «открытых major в регистре платформы 0» СНЯТ 22.08 — он протух:** ⚠ **прежняя редакция называла открытым мажором `PD-370` — он ЗАКРЫТ** (обе половины: зонная 22.08, контрактная минором 0.5.0 D39.161; регистр переведён 28.08 аудитом доков D39.167), и держать счёт чужого регистра здесь — лишний носитель, который протухает молча; счёт печатает `python3 docs/scripts/counts.py` | `platform/docs/DEFECT_REGISTER.md` (эра P6), D39.132 |
|
||||
| ~~Строка 165~~ **ЗАКРЫТА D39.131** (испр. оркестратором 14.08): exit 4 = потолок · 5 = graceful stop · 10–19 полоса отказов; потребительская половина построена P6 (D39.132) — шов закрыт с обеих сторон; ⚠ exit 13 (`schema_mismatch`) едет паком migrate, ратификация направления — D39.132 | D39.131, D39.132 |
|
||||
| **Строка 166** — движковая поверхность оценки $/глава; $0.03 — временная мера беты (П-10 зоны) | `docs/PROGRESS.md:114` |
|
||||
| ~~**PD-104**~~ **ЗАКРЫТА** (`fixed(P7)`; дефолт гранта в коде — ноль, испр. 28.08 D39.167) — фри-тир: док↔код закрыто, продуктовая половина (ноль на бете · агрегатный потолок · счётчик) на владельце | `DEFECT_REGISTER.md:115`, D39.110 п.3 |
|
||||
| **Строка 78** — леджер = нижняя граница (биллящийся decode-fail мимо request_log, ≤13% захода на ре-пробе) | `docs/PROGRESS.md:41` |
|
||||
| **Строка 136** — эскроу/intent (см. §3 п.10) | `docs/PROGRESS.md:85` |
|
||||
| *(добавка сборщика)* **PD-157 (minor)** — `day_usd` книги флагом не перекрывается, платформой не виден и не задаётся; в `status --json` дневной фигуры нет | `DEFECT_REGISTER.md:168` |
|
||||
| ~~Строка 165~~ **ЗАКРЫТА D39.131** (испр. оркестратором 14.08): exit 4 = потолок · 5 = graceful stop · 10–19 полоса отказов; потребительская половина построена P6 (D39.132) — шов закрыт с обеих сторон; ⚠ exit 13 (`schema_mismatch`) ПОСТРОЕН паком migrate (D39.134; `backend/cmd/tmctl/main.go:72`=`exitSchemaMismatch = 13`), ратификация направления — D39.132 | D39.131, D39.132 |
|
||||
| **Строка 166** — движковая поверхность оценки $/глава; $0.03 — временная мера беты (П-10 зоны) | `docs/PROGRESS.md:154`=`Движковая поверхность оценки` |
|
||||
| ~~**PD-104**~~ **ЗАКРЫТА** (`fixed(P7, дерево сессии)`; дефолт гранта в коде — ноль, испр. 28.08 D39.167) — фри-тир: док↔код закрыто, продуктовая половина (ноль на бете · агрегатный потолок · счётчик) на владельце | `platform/docs/DEFECT_REGISTER.md`, греп `PD-104`, D39.110 п.3 |
|
||||
| **Строка 78** — леджер = нижняя граница (биллящийся decode-fail мимо request_log, ≤13% захода на ре-пробе) | `docs/PROGRESS.md:84`=`Леджер денег = НИЖНЯЯ граница` |
|
||||
| **Строка 136** — эскроу/intent (см. §3 п.10) | `docs/PROGRESS.md:127`=`Write-ahead intent` |
|
||||
| *(добавка сборщика)* **PD-157 (minor)** — `day_usd` книги флагом не перекрывается, платформой не виден и не задаётся; в `status --json` дневной фигуры нет | `platform/docs/DEFECT_REGISTER.md`, греп `PD-157` |
|
||||
|
||||
## 6. Карта носителей темы
|
||||
|
||||
| Вопрос | Где живёт |
|
||||
|---|---|
|
||||
| Словарь терминов | `docs/glossary.md:50` §«Деньги платформы» |
|
||||
| Словарь терминов | `docs/glossary.md:55`=`**Деньги платформы:**` |
|
||||
| Управляемый потолок: решение и форма | D39.110 (+поправка D39.112 п.3: п.1 — пересказ, не цитата) |
|
||||
| Максимум шкалы = Balance как есть | D39.115 п.2а; эррата — шапка D-лога `:4` |
|
||||
| Семантика `--ceiling-usd` | D39.122 п.2в; `tmctl/invocation.go:114`, `main.go:110` |
|
||||
| Максимум шкалы = Balance как есть | D39.115 п.2а; эррата — шапка D-лога, `docs/architecture/05-decisions-log.md:4`=`Balance КАК ЕСТЬ` |
|
||||
| Семантика `--ceiling-usd` | D39.122 п.2в; `backend/cmd/tmctl/invocation.go:142`=`the book USD ceiling in force for THIS RUN ONLY`, `backend/cmd/tmctl/main.go:260`=`--ceiling-usd is NOT a per-run budget` |
|
||||
| Формула аргумента потолка (без reserved) · ставка · settle-формы | D39.123 п.2б/г/д; PD-158/PD-159/PD-144 в реестре |
|
||||
| Код денег платформы | `platform/internal/pgstore/credits.go` · `pgstore/runs.go` · `runs/spawn.go` · `runs/reconcile.go` · `pricing/pricing.go` |
|
||||
| Код денег движка | `backend/internal/store/ledger.go` · `store/store.go` · `pipeline/stagerun.go` · `pipeline/status.go` · `config/book.go` |
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue