textmachine/eval/dovodka/PLAN-01-09.md

540 lines
56 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ПЛАН ФАЗЫ Д — РЕДАКЦИЯ 4: ПРЕ-РЕГ РАТИФИЦИРОВАННОЙ ПРОБЫ
> Редакции 13 отвергнуты консилиумом; их разбор — §8, сохранён как класс ошибок фазы.
> Редакция 4 собрана с постоянным консилиумом (архитектор замера · скептик · казначей) и несёт
> ПРЕ-РЕГИСТРАЦИЮ, а не намерения. Платные замеры санкционированы владельцем 01.09 — ⚠ **без числа,
> и число нужно до фриза** (§6).
## 1. ЧТО ЭТО ЗА ЗАМЕР И ПОЧЕМУ ИМЕННО ОН
**Носитель:** D39.184 п.5 — «Следующий платный замер — контролируемая проба редактора по ЧЕТЫРЁМ
осям (§14 отчёта холодного прогона): трудность чанка БЛОКИРОВАТЬ, длину входа КОНТРОЛИРОВАТЬ,
промпт по SHA, эффорт `off` против `low`». ⚠ Ноты нет в ветке `polygon` (реестр обрывается на
D39.170) — она в `main`; это следствие расхождения веток, а не отсутствия решения.
**Вопрос:** ПОЧЕМУ редактор дорог. Не «кто лучше» (мерено) и не «сколько продавать» (гейчено
отдельно, §7).
## 2. ДИЗАЙН — КРЕСТ 2×2 ВНУТРИ ЮНИТА
| рука | промпт | `stages[edit].reasoning` | что уходит на провод |
|---|---|---|---|
| P₇·E∅ | `editor.md` из `e89874b^` | `"off"` | ключа `reasoning_effort` НЕТ ⇒ вендор-дефолт `high` |
| P₇·E_low | тот же | `"low"` | `reasoning_effort:"low"` |
| P₉·E∅ | `editor.md` HEAD | `"off"` | ключа нет |
| P₉·E_low | тот же | `"low"` | `low` |
Промпты различаются одной строкой; **метка `v3-discourse-reflow` у обоих одна**, поэтому берём по
SHA — снапшот их различает (`snapshot.go:288`=`prompt_sha256`).
**МОДЕЛИ (их не было ни в одной прошлой редакции — поймано владельцем 02.09):**
редактор — **`deepseek-v4-pro`** (он и есть предмет: `off` против `low`) · **референс — `glm-5`** (`thinking` выключен, `few_shot: false`, не фактор) · черновик —
`deepseek-v4-flash` с `low` · хоп эскалации черновика — `deepseek-v4-pro`, наследует эффорт стадии ·
терминолог и классификатор — `deepseek-v4-flash` с `low` · **судья не вызывается вовсе**.
Состав снят с отработавшего `coldrun-v16` и менять его нельзя: смета и сопоставимость стоят на нём.
* **БЛОКИРУЕТСЯ трудность:** каждая рука видит ВСЕ юниты. Реализация: один базовый прогон (черновая
волна + майнинг + терминолог), затем БД копируется **×5** (четыре руки креста + референс `glm`).
**Черновики выживают за $0 НЕ ре-пином** (`repin.go` — механизм смены БАНКА, при смене
промпта/эффорта он даёт «Nothing is re-pinnable»), **а потому, что снапшот ПЕР-ВОЛНОВЫЙ**
(`snapshot.go:225-231`=`waveDraft`): правка edit-стадии draft-снапшот не двигает, и черновики
идут обычным resume.
**Базовый прогон ОБЯЗАН остановиться ДО edit-волны, и это делает только `--verify-bank`.**
Без флага движок авто-продолжает с неподписанным банком и покупает edit-юнит в том же процессе —
тогда каждая копия потребует `--resnapshot` и перекупит базовые edit-юниты ×4.
**Условия копирования:** движок остановлен (WAL закрыт), `book_id` тот же (он входит в
`request_hash`), в `book.yaml` меняются ТРИ поля — `project_db`, `pipeline` и `ceilings` (последнее — потому что касса наследует базовый расход, §5.4).
* **КОНТРОЛИРУЕТСЯ длина входа:** `len(draft)` и `prompt_tokens` — ковариата. ⚠ Честно: чанки движка
узки по `prompt_tokens` (44126946: там доминируют исходник и системное), **но сама длина черновика
широка — 4276171 знак, разброс ×14**, и она входит в модель ковариатой (§4). Прежняя формулировка
«контролируется, а не измеряется» снята как противоречащая §4.
* **ФИКСИРУЕТСЯ:** модель и дата вендор-доки · бинарь `tmctl` по sha · `models.yaml` по sha ·
потолок вывода · `temperature 0.4` · `few_shot: false` · санитайзер ON ·
`escalation.budget_usd: 0` **ТОЛЬКО в ПЯТИ конфигах рук** (четыре креста + референс). ⛔ **В БАЗОВОМ прогоне он обязан быть
> 0**, иначе эхо-черновики останутся флагнутыми: в холодном прогоне 5 хопов на 25 вызовов,
$0.103 на 10 глав ⇒ **≈$0.25 на 24 главы, и это отдельная строка сметы**.
⚠ **обоснование прежней редакции («иначе флагнутый юнит уйдёт хопом»)
ЛОЖНО и снято: редактор эскалировать не может по построению** (`pipeline.go:1012`=`escalate_to is
only allowed on a translator role`). Настройка инертна для edit-волны; держим её как гигиену, а не
как защиту.
* **РАНДОМИЗИРУЕТСЯ** порядок ЧЕТЫРЁХ рук креста внутри юнита. ⭐ **Контракт `poryadok.py`, дословно:
четыре руки креста — перестановкой от сида, `glm-off` — ВСЕГДА последним пятым.** ⭐ **референс `glm` идёт ПЯТЫМ,
фиксированно последним** — тогда при срабатывании денежного гарда теряется референс, а не пара,
на которой стоит E1. **Интерливинг во времени** — пять клеток юнита в
окне 1020 минут, чтобы дрейф сервинга не разошёлся между руками.
**Останов цикла НЕ по коду выхода:** штатная остановка по объёму приходит **и как 0, и как 2**,
различает её только строка `VOLUME CEILING:` в выводе. `|| break` (урок Д47.6) здесь либо рвёт
цикл на первом штатном стопе, либо не рвёт никогда ⇒ **цикл разбирает вывод на `VOLUME CEILING:`**.
⚠ Окно 1020 мин достижимо не всегда: латентности edit-вызовов 43216 с, ретрай добавляет ~200 с
юнит с обрывом в обеих `∅`-руках упирается в верх окна.
⭐ **ПЯТАЯ, РЕФЕРЕНСНАЯ КЛЕТКА НА ЮНИТ: `glm-5` в БОЕВОЙ форме (размышление выключено) ×
сегодняшний промпт.** Не фактор креста — **ценовой контроль**: тот же черновик, тот же банк, тот же
день. ~$0.02 за клетку, **≈$0.5 на 24 юнита**.
**Зачем:** без неё вывод звучит «pro стал дешевле на ×N», а с ней — «цена доставленного знака у
pro@low против glm@off СЕГОДНЯ». Это ровно та таблица, которой не хватает Д51: там pro посчитан на
ИЮЛЬСКИХ токенах (2 798 на вызов), а сегодня один вызов даёт 12 203 — отношение ×2.14 занижено.
**Почему `glm` НЕ вводится третьей осью:** её «low» в движке не ступень — `on_extra_body` у неё не
объявлен, при `low` мержится пустое и едет вендор-дефолт. Значит ось на `glm` = «выкл/вкл», а на
`pro` = «уровень» — **фактор означал бы РАЗНОЕ на разных уровнях**, и крест 2×2×2 не дал бы чистого
взаимодействия. Плюс удвоение рук (считано при прежнем потолке $8.6) срезало бы n до ~12 и MDE до ×2.7 — проба
перестала бы видеть даже ×2.5.
**ЧЕТЫРЕ ОГОВОРКИ РЕФЕРЕНСА, без которых он даст ложное число** (найдены скептиком 02.09):
1. **Его потолок вывода НЕ 16000.** У `glm-5` в реестре нет флора `min_max_tokens` («0 = no floor»
для моделей с выключаемым размышлением) ⇒ потолок = `EstimateTokens(draft)·2.2` ≈ 4.5 тыс.
Для E1 неважно (референс в него не входит), но для E0/E2 «равный потолок» на него НЕ
распространяется — и это записывается рядом с числом.
2.**`R̂` для референса обязан быть 0 ПО ПОСТРОЕНИЮ, а не по формуле:** у него другой токенизатор,
и формула напечатала бы «думает ±300 токенов» на модели с выключенным размышлением. Статья
«размышление» = 0, «видимый выход» = весь `completion_tokens`.
3.**`few_shot: false` — РЕШЕНО, развилка закрыта** (нельзя фризить документ с открытой развилкой:
этот флаг меняет байты конфига, его sha256 и статью «вход» в E0). Боевой резервный арм держит
few-shot включённым, поэтому слово «боевая форма» из описания референса **снято**: референс
отличается от `P₉·E∅` **ровно моделью**, и только так он остаётся чистым ценовым контролем.
4.**Референс на билингвальном входе — зона эха.** Его эхо-клетки дадут `delivered = 0` и раздуют
цену знака не из-за цены. **E5 считается по референсу ОТДЕЛЬНО.**
**Единица наблюдения** — клетка (юнит × рука); **единица анализа** — юнит.
**Требование §14 «потолок вывода одинаков во всех руках» выполняется само:** `stagerun.go:109-125`
даёт `base = max(EstimateTokens(draft)·2.2, min_max_tokens)`; при МАКСИМАЛЬНОМ черновике 6171 знак это
≈4.5 тыс. < 16000 **16000 у всех юнитов во всех ЧЕТЫРЁХ РУКАХ КРЕСТА по построению** (референс своя история, §2), ретрай 32000 тоже одинаков.
Числа прежней редакции были не те: реальные черновики **4276171 знак** (не «~7 тыс.»), а
«44126946» это `prompt_tokens` трёх edit-вызовов (исходник + черновик + системное), не длина
черновика. Механизм ломается только выше ~21 800 русских знаков или ~7 300 CJK-знаков эха.
## 3. ⛔ ДВЕ ДЫРЫ ПРИБОРА — БЕЗ НИХ ЗАМЕР НЕ ИЗМЕРИТ СВОЙ ПРЕДМЕТ
**Дыра 1. Движок НЕ ВИДИТ размышление DeepSeek по построению.** `provider_openai.go:23`
=`ReasoningTokens stays 0 to avoid double-billing`: у subset-провайдеров размышление считается
ВНУТРИ `completion_tokens`, и поле остаётся нулём. Проверено: во всех движковых базах
`sum(reasoning_tokens>0) = 0`. А предмет замера именно размышление (9596% цены).
**Лечение без правки Go, с замеренной точностью:** `R̂ = completion_tokens 0.3644·len(response_text)`.
Коэффициент видимый выход pro-редактора на zhru; **пере-снят мной независимо: 0.3644 токена/знак,
n=16, sd 0.0069**. Ошибка типично ~3% видимого выхода, **худшая клетка 5.3%**; пренебрежима при размышлении в тысячах и заметна
лишь при малом размышлении. Коэффициент **пинится в пре-реге**.
**Границы формулы, названные до покупки** (проверено независимо на 185 клетках рига с отчётным
`reasoning_tokens`: 0.3670.369, sd 0.0070.010): (1) **любой CJK в выходе** ломает оценку иероглиф
1 токен, видимая часть недооценивается, `R̂` завышается; направление консервативно для E1, но
раздувает клетки E5; (2) при `R̂ < ~700` относительная ошибка достигает 2070% у мелких клеток
`low` вывод о величине не делается; (3) брать сырую строку попытки, **не `sanitized_export`** та
несёт обрезанный текст и пустой `usage_json`; (4) типичная ошибка ~3%, худшая клетка **5.3%**.
**Дыра 2. У движка нет проводного артефакта** стадийный лог эффорт не печатает. Лечение:
(а) снапшот фолдит `Reasoning` и `PromptSHA256` **у пяти рук пять разных `snapshot_id`**, это
запись в БД, что конфиг был в силе; (б) сигнатура `prompt_tokens(∅) prompt_tokens(low)` по юнитам
(на en дважды ровно **79**). Оба косвенные; побайтной улики у движка нет.
## 3-БИС. ⭐ ОБЛАСТЬ ПЕРЕНОСА — ПИШЕТСЯ ДО ЗАМЕРА, ЧТОБЫ ВЫВОД НЕ РАСШИРИЛИ МОЛЧА
**Повод: владелец 02.09 «мы фактически измеряем, как ведёт себя дипсик; исследование однобокое».
Он прав, и лечится это не расширением креста 7), а честной границей вывода.**
**УСТАНАВЛИВАЕТСЯ** на одной модели `deepseek-v4-pro` **в тех весах, что сервятся в дни прогона**
(вендор объявил новые веса 13.08 при неизменном слаге), при маппинге эффорта от 30.08, на паре
zhru, на нашей нарезке (~2 тыс. знаков исходника на юнит), с нашей инъекцией банка, на двух
конкретных SHA `editor.md`:
1. эффект ОТПРАВКИ `reasoning_effort:"low"` против неотправки ключа на объём размышления и на цену
доставленного знака;
2. эффект одной строки промпта;
3. **разложение цены по статьям** (E0 ниже) у ЭТОЙ модели.
**НЕ УСТАНАВЛИВАЕТСЯ, и это пишется тем же абзацем:**
* «размышление вообще» — в реестре **четыре разных механизма**: у DeepSeek уровень без выключения,
у GLM тумблер, у grok явное «none», у Gemini выключить нельзя;
* «семейство DeepSeek» у `flash` другие веса и своя эхо-статистика; общее у них лишь таблица
маппинга и сигнатура входа;
* перенос на английскую пару размышление на плотном китайском идёт в разы больше.
**СРОК ГОДНОСТИ.** Вендор за месяц сменил дефолт эффорта (31.07), веса (13.08) и таблицу маппинга
(30.08). **вывод действителен до следующего изменения вахты и ПЕРЕ-СНИМАЕТСЯ пред-полётной парой
(~$0.25), а не цитируется.**
**ШАБЛОН КЛЕЙМА, обязательный для любого, кто будет ссылаться на результат:**
> «у `deepseek-v4-pro` (веса 0813) на zh→ru при нашей нарезке ручка `low` даёт ×N [ДИ] —
> на N-й день после смены маппинга 30.08»
**Число без этого квалификатора — ошибка класса Д52.5** (вендор-факт принят за свойство системы).
## 4. ПРАВИЛО РЕШЕНИЯ — ЗАПИСАНО ДО ЧИСЕЛ
**Метрики клетки:** `R̂` · `completion_tokens` · `cost_usd` (сумма ВСЕХ строк юнита в руке, ретраи
включены) · `delivered` = знаки отгружаемого текста при годной диспозиции, иначе **0** ·
`cost/delivered` · `finish` попытки 0 · `flag_reason`.
* **E0 (ответ на вопрос «ПОЧЕМУ дорого», $0, на тех же данных).** Для каждой руки на каждом юните
цена раскладывается по статьям: вход · кэш · видимый выход · размышление · ретраи, сложенные по
ВСЕМ попыткам. Печатаются доли и их сдвиг между руками.
**Зачем он введён:** ратифицированные оси меряют «сколько режет ручка», а заказ владельца был
«почему редактор дорог» это шире. Разложение и есть ответ: «у пары без ручки размышление = X%
цены знака, ретраи = Y%; на `low` X/Y; промпт даёт Z». Одна статья невосстановима никакой
пробой и объявляется заранее: **что из подорожания дали новые веса и смена дефолта вендором**
июльское состояние сервинга не вернуть.
* **E1 (главный):** по-юнитный контраст `log R̂(low) log R̂(∅)`; **Вилкоксон знаково-ранговый**,
α=0.05 двусторонне; медиана и 95% ДИ ХоджесаЛемана печатаются как ВЕЛИЧИНА.
**Исходов ДВА, а не три** прежняя редакция обещала третий и была неправа: ветвь
«эквивалентность» (ДИ целиком внутри полосы) при наших n **недостижима** полуширина ДИ в
логарифме 0.43 при n=32 против полуширины полосы 0.22, для эквивалентности нужно n117.
**Решение:** `p<0.05` эффект есть, величина = медиана с ДИ. Иначе **«НИЖЕ РАЗРЕШЕНИЯ
ЗАМЕРА»**, и это НЕ «эффекта нет».
Критерий **только `p<0.05`**: со-условие «ДИ вне [0.8;1.25 снято, потому что оно строже
таблицы мощности (требовало бы истинного эффекта ≈×2.3 против заявленных ×1.84) и потому что сама
полоса заимствованная конвенция биоэквивалентности, к объёму размышления не обоснованная.
Полоса остаётся **описательной**: попадание в неё печатается, решения не несёт.
**Цензура на потолке — правило записано до чисел, СИММЕТРИЧНО.** В холодном прогоне 1 из 4
`∅`-строк вернула `length` ровно на 16000 при непустом тексте: там `R̂` **нижняя граница**, а
ретрай на 32000 есть ДРУГОЙ розыгрыш. **E1 считается по попытке 0**; клетка с `length` входит
правой цензурой (`R̂ ≥` наблюдённого). Знак пары определяется так:
* цензурирована `∅` знак достоверен, пока цензурированная `∅` `low`; иначе **ничья**;
* цензурирована `low` знак достоверен, только если `∅` наблюдённой границы `low`; иначе **ничья**;
* цензурированы обе **ничья**.
**«Ничья» «выброшено», и это надо задать в коде явно:** стандартный знаково-ранговый Вилкоксон
нули по умолчанию ВЫБРАСЫВАЕТ; сохраняет их вариант Пратта. **Скрипт эндпойнта обязан назвать
метод обработки нулей**, иначе правило плана и тест разойдутся молча. Проверено на машине
01.09: `scipy 1.18.0`, у `wilcoxon` умолчание `zero_method='wilcox'` (нули ВЫБРАСЫВАЮТСЯ), вариант
Пратта поддержан **в скрипте пинится `zero_method='pratt'`**.
**Величина под цензурой — НИЖНЯЯ ГРАНИЦА:** медиана и ДИ ХоджесаЛемана при цензурированных
клетках занижают эффект, поэтому величина печатается со знаком **«≥»**. Иначе `p<0.05` при малой
медиане прочтётся как «эффект мал», когда он может быть велик.
* **E2:** то же для `log(cost/delivered)` отдельно по попытке 0 (равный потолок) и по итогу юнита
(боевая цена). Средний член цены за знак константа, поэтому разница рук сидит в
**ρ = R̂/delivered**. Оговорка: 24-я клетки юнита бьют префикс-кэш, вход дешевеет ~$0.0060.009;
рандомизация порядка это усредняет, но добавляет ~10% шума на клетку.
* **E3:** ось промпта те же тесты. Прогноз, калибрующий удивление: |эффект| < ×1.25.
* **E4 (восстановлен без него крест не даёт ничего сверх двух пар):** взаимодействие промпт×эффорт,
контраст `(P₉E_low P₉E∅) (P₇E_low P₇E∅)`. sd контраста вдвое больше MDE ×3.3 при n=32:
**эндпойнт описательный, выводов не несёт** но печатается, иначе крест не отличим от двух пар.
* **E5 (безопасность, блокирует любую рекомендацию):** доля клеток с эхом/`cjk_artifact` и с
`length` по рукам. Если у `low` эхо-клеток 3 сверх `∅` **«риск эха на low» независимо от цены**.
* **Ковариата длины входа** требование §14, которое Вилкоксон принять не может. Восстановлено
ОТДЕЛЬНОЙ моделью: `log R̂ ~ effort + prompt + log(len_draft) + (1|unit)`, **как проверка
устойчивости E1/E3**, не как решающий тест.
* **Провал прибора:** сигнатура Δ`prompt_tokens` вне полосы у >20% юнитов ⇒ проба аннулируется,
деньги называются. ⛔ **Полоса НЕ задана заранее и не может быть**: единственное известное число
(79) снято на en и на риге. ⇒ **Пред-полёт ЗАМЕРЯЕТ сигнатуру и пинит её коммитом**, и лишь
после этого она становится гейтом.
**Но «полосу» из пред-полёта не вывести:** один юнит даёт две сигнатуры (P₇ и P₉), разброса в
них нет. Поэтому правило допуска объявляется ЗДЕСЬ, до замера, и опирается на контроль 05.08:
при побайтно одинаковых `messages` провайдер повторяет `prompt_tokens` **в точности** ⇒ сигнатура
ожидается КОНСТАНТОЙ. **Допуск: ±2 токена** от значения, снятого пред-полётом (запас на неучтённую
серверную вставку, не на шум). Клетка вне допуска — «сигнатура не воспроизвелась»; >20% таких
юнитов ⇒ проба аннулируется.
**Мощность.** В кресте 2×2 контраст главного эффекта на юните имеет sd = σ (не σ√2) — поэтому n
вдвое меньше, чем в простой паре. Источник σ: **эррата Д47.7** (`23-editor-tier.md:7201`=`sd одного розыгрыша = 1.02`, 16 пар
`e0`/`zf`, побайтно один вход) — ⚠ **на английской паре и роли редактора; на zh не переносится**,
поэтому планируем σ=1.2 с чувствительностью 1.0/1.4.
**Плановое число — ×2.0 при σ=1.2** (z-аппроксимация с поправкой на ранговый тест). ⚠ Три версии,
гулявшие по документам, суть одна формула в разных конвенциях: ×1.82 при σ=1.02 · ×1.88 при σ=1.056
(несмещённая sd, t-квантили без поправки) · ×2.022.08 при σ=1.2. t-квантили при n=24 добавляют ~3%.
Решение владельца ни одна из трёх не двигает.
| σ | ×2.5 | ×2.0 | ×1.5 | MDE при n=24 | MDE при n=32 |
|---|---|---|---|---|---|
| 1.02 | 11 | 18 | 51 | ×1.82 | ×1.68 |
| 1.2 | 15 | 25 | 70 | ×2.02 | ×1.84 |
| 1.4 | 20 | 34 | 95 | ×2.27 | ×2.03 |
⛔ **Эффект ×1.40 (наблюдённый внутри блока в Д47) при любом n ≤ 32 ниже разрешения — записано
ДО покупки.**
## 5. ГАРДЫ
0.**РАМКА ВЫБОРКИ — пинится ДО всего остального, иначе «24 юнита» читаются как ОТБОР.**
В пре-рег заносится: срез исходника (диапазон глав, файл, его sha256) · **новый каталог книги**
⚠ не `coldrun-v16`, где три оплаченных edit-юнита заставят `--resnapshot` на каждой из четырёх
копий · **все юниты этих глав в порядке движка, без выбора** · `n` = сколько их получится
(ориентир холодного прогона: 14 юнитов на 10 глав) · и **входит ли юнит пред-полёта в `n`**
(решение: **входит** — это первый юнит в порядке движка, прогоняемый во всех четырёх руках).
1. **Пред-полёт: один юнит × ПЯТЬ клеток** (четыре руки креста + референс, ~$0.27) → сигнатура
Δ`prompt_tokens` СНЯТА и запинена коммитом (по одной на P₇ и P₉; полосой она станет только после
этого) · **пять разных `snapshot_id`** · ⭐ **референс проходит свои гейты именно здесь**: эхо,
`R̂ = 0`, потолок ≈4.5 тыс. — иначе его первая клетка выстрелит в пачке мимо всех проверок · кириллица ≥0.99 · эхо 0. Только потом пачка.
2. **Зелень на пустоте:** `delivered = 0` ⇒ клетка идёт в E5 и исключается из E2; если таких >20% в
руке — **прибор ОТКАЗЫВАЕТ**, а не печатает «в пределах».
**Правило действует ТОЛЬКО на четыре руки креста.** Референс `glm@off` работает на
билингвальном входе — это зона эха с НЕИЗМЕРЕННОЙ экспозицией, и правдоподобная доля пустых у
него обнулила бы E1, в который он не входит вовсе. **Референс с >20% пустых просто не печатается
в E0**, а его доля идёт в E5 отдельной строкой.
3. **Эхо-гейт включён во всех руках.**`low` ≠ выключение: мина вооружается ТУМБЛЕРОМ, а уровни
эффорта едут с размышлением включённым. Гейт всё равно остаётся.
4. **Касса — и здесь ловушка, которую видно только в коде.** `ledger.go:58`=`FROM spend WHERE book_id`
считает потолок по `book_id`, а **копия БД несёт базовый расход под тем же `book_id`** (в холодном
прогоне это $0.4361). ⇒ `ceilings.book_usd` каждой копии = **база + доля руки + запас**, то есть в
`book.yaml` меняются ТРИ поля (`project_db`, `pipeline`, `ceilings`), либо потолок задаётся
`--ceiling-usd` на каждый запуск. И **число владельцу подаётся ОДНОЙ суммой**: база + пред-полёт +
N юнитов × 4 руки креста + референс — иначе базовый расход посчитается четырежды или не посчитается вовсе.
Отказ леджера = **СТОП и вопрос владельцу**; добор после чисел запрещён; потолок сессия не поднимает.
5. **Фриз — и он обязан лежать в зоне полигона.** Пре-рег и скрипт эндпойнта коммитятся в
`eval/dovodka/`. ⚠ ПЯТЬ `pipeline.yaml` и два `editor.md` физически живут в каталоге книги —
это ОТДЕЛЬНЫЙ репозиторий с открытым вопросом «кто коммитит книги», поэтому в зону полигона
кладутся **их замороженные копии вместе с sha256**; иначе «коммитами ДО первой клетки» не
исполнимо по канону. Всё — ДО первой платной клетки.
## 6. ⚠ ДЕНЬГИ — И ЗДЕСЬ НУЖНО ЧИСЛО ВЛАДЕЛЬЦА
**Все числа ниже — в ПИКОВЫХ терминах, и иначе быть не может:** леджер движка букирует пик всегда
(`models.yaml:180`=`держим пик`). Потолок кассы, `--ceiling-usd` и число владельца — тоже пиковые;
офф-пик — это счёт вендора по факту, а не потолок.
По леджеру холодного прогона: клетка `∅`**$0.054** (среднее четырёх ненулевых edit-строк, включая
ретрай на 32000; попытка 0 — $0.048 при n=3); обрыв случился у **1 строки из 4**.
**Клетка `low` ≈ $0.04 — ИСТОЧНИКА НЕТ:** движковых edit-вызовов на `low` не существует вовсе, а
хопы на `low` — роль переводчика ($0.0040.040). Это **предположение, а не замер**, и его проверяет
пред-полёт.
**Арифметика юнита, по шагам (её пропуск в прошлой редакции ломал все производные):** попытка 0
у `∅` = $0.048; обрыв на 16000 случается у ~25% и добавляет ретрай на 32000 (+$0.070) ⇒
**эффективная `∅` ≈ $0.048 + 0.25·0.070 ≈ $0.066**, с запасом на разброс — **$0.09**.
Юнит (2 × `∅` + 2 × `low`) ≈ 2·0.09 + 2·0.04 = **$0.26**.
| строка сметы | клеток | расчётно, ПИК |
|---|---|---|
| базовый прогон (черновая волна + майнинг + терминолог) | — | ≈ $0.6 |
| эскалация эхо-черновиков в базовом прогоне (`budget_usd` > 0) | ~12 хопов | ≈ $0.25 |
| пред-полёт (1 юнит × 5 клеток) | 5 | ≈ **$0.27** |
| **вариант A:** 24 юнита × 4 руки креста (+20% запаса) | 96 | ≈ $7.5 |
| ⭐ референс `glm-5@off`, 24 клетки (+20%) | 24 | ≈ **$0.6** |
| **вариант B:** 32 юнита × 4 руки (+20% запаса) | 128 | ≈ $10.0 |
**ОДНОЙ СУММОЙ, как и надо просить у владельца** (иначе база посчитается четырежды или ни разу —
леджер считает потолок по `book_id`, а его несут все четыре копии):
* **вариант A (~17 глав, ожидаемо ~24 юнита): $8.6 — ⚠ ЭТО ИСТОРИЯ, потолок поднят до $9.5 ниже** — разрешающая способность ×2.02;
* **вариант B (~24 главы, ожидаемо ~32 юнита): $11.1** — разрешающая способность ×1.84.
**Вариант задаётся ДИАПАЗОНОМ ГЛАВ, а не числом юнитов.** «24» и «32» — ожидание по пропорции
холодного прогона (14 юнитов на 10 глав), а не цель: юниты не добираются и не обрезаются. Прогон
идёт до конца диапазона либо до срабатывания денежного гарда — что наступит раньше.
**Чувствительность, названная до покупки и выведенная из своих же клеток:** если `low` на zh режет
размышление слабо (×1.4, как внутри блока Д47), клетка `low` дорожает до $0.050.065 ⇒ юнит
2·0.09 + 2·(0.05…0.065) = **$0.280.31** ⇒ 32 юнита = **$8.969.92 до запаса**. Сравнивать это надо
со строкой ЮНИТОВ ($10.0), а не с полной суммой: база, эскалация и пред-полёт ($1.1) тратятся при
любом срезе. **Зазор 0.810.4%** ⇒ гард с заметной вероятностью остановит раньше 32-го юнита.
Это штатный исход: **стоп и вопрос владельцу, добор после чисел запрещён.**
**Мои прежние сметы ($1.7 и $2.50) занижены втрое** и снимаются: они считали «выход» как видимый
текст, тогда как размышление у DeepSeek сидит ВНУТРИ `completion_tokens`. Это тот же класс, что
«смета ×10» редакции 1.
**РЕШЕНИЕ ВЛАДЕЛЬЦА: ВАРИАНТ A — 17 глав. ПОТОЛОК $9.5** (01.09 — «17 глав разрешаю», $8.6;
02.09 поднят до **$9.5** словом «да, можно поднять» после того, как в дизайн вошла референсная
клетка). Вариант B (~24 главы) не берётся.
**Почему именно $9.5 — посчитано, а не округлено:** база 17 глав $0.45 + четыре руки креста
(24 юнита × 2×$0.09 + 2×`low`) + референс 24×$0.02, всё с 20% на ретраи.
| сценарий цены клетки `low` | сырое | с запасом | влезает юнитов |
|---|---|---|---|
| центральный $0.04 | $7.17 | **$8.60** | 24 из 24 |
| пессимистичный $0.05 | $7.65 | **$9.18** | 24 из 24 |
| худший $0.065 | $8.37 | $10.04 | **22 из 24** (MDE ×2.02 → ×2.06) |
⇒ $9.5 покрывает два сценария из трёх целиком; в худшем теряются два юнита, и это штатный исход —
референс идёт последним, поэтому теряется он, а не пара, на которой стоит вывод.
**Потолок $9.5 — В ПИКОВЫХ ТЕРМИНАХ и СЕССИЕЙ НЕ ПОДНИМАЕТСЯ.** Срабатывание гарда = стоп и
вопрос владельцу; добор после просмотра чисел запрещён.
Прежняя развилка (снята решением): вариант A $8.6 (MDE ×2.02) или вариант B $11.1 (MDE ×1.84). Обе суммы — из таблицы выше и больше нигде в этом
файле не повторяются. Санкция «платные замеры разрешаю» числа не содержит, а по канону потолок
сессия не поднимает.
## 7. ЧЕГО В ЗАМЕРЕ НЕТ НАМЕРЕННО
Калибровки ставки платформы (гейчено, §14 прямо) · судейства качества — качество `low` вне скоупа,
только $0-гейты и E5 · правок `models.yaml`, capabilities, Go · смены модели, черновика,
дифф-контракта · креста «размышление вкл/выкл» пилота · сравнения с июльским базлайном как
каузального: между июлем и сегодня сменились веса модели, дефолт, маппинг и потолок — проба
разделяет рычаги СЕГОДНЯ.
**И отдельно: из этой пробы НЕ следует рекомендация менять боевой `pipeline-c1.yaml`.** Флип там
пинит тест (`echo_mine_test.go:217`, `TestBoevoyConfigEditorDsproAndGrokReasoning`) и двигает
снапшот edit-волны ⇒ `--resnapshot` и перекупка волны.
## 8. РЕЕСТР ОШИБОК ЧЕТЫРЁХ РЕДАКЦИЙ — сохранено, потому что класс один
| # | что утверждал | чем опровергнуто |
|---|---|---|
| 1 | «прибор верности нужен первым» | вопрос закрыт замером: редакторы не дописывают (рост знаков 0.4% и 0.6%) |
| 2 | «проба единицы выдачи» | гипотезу опровергают наши же данные; арм запрещён; смета ×10 |
| 3 | «контур ни разу не ездил целиком» | `coldrun-v16` прошёл НАКАНУНЕ |
| 4 | «канон мерен на 12 главах» | я сам намерил на 25 главах подряд сутками ранее |
| 5 | «засеять `first_person`/`speech`» | поля мёртвые: не копируются в рендер, не входят в хеш |
| 6 | «движок ручку не шлёт вообще» | `capability.go:236` шлёт `low|medium|high`; доказано на проводе |
| 7 | «гейт запретит» | гейт в другом тесте и пинит только шиппинг-конфиги |
| 8 | «риг потерял бы роль редактора» | `tenant_panel/prompts.py:141`=`def editor_msgs` грузит боевой `editor.md` |
| 9 | «эхо на `pro`@`low` не мерено» | 5 хопов в `coldrun-v16`, эхо 0 — ⚠ но роль переводчика, не редактора |
| 10 | сметы $1.7 / $2.50 | занижены втрое: размышление внутри `completion_tokens` |
**Сквозной класс — один:** показания инструмента, собственной памяти или своей ветки приняты за
факт о мире. Лечение, выведенное из десяти случаев: **отрицательный результат предъявляется с
положительным контролем**, а прежде «этого нет» — смотреть каталог артефактов, а не только доки
своей ветки.
---
# 9. ПРОЦЕДУРА — КОМАНДЫ, А НЕ АРГУМЕНТЫ
> ⚠ **Этот раздел дописан 02.09 после проверки исполнимости свежей сессией.** Её вердикт был:
> «план написан как аргумент, а не как процедура — из него нельзя набрать ни одной команды», и
> объём домысливания оказался больше, чем то, что план задаёт. Все якоря при этом были верны:
> дефект был не в фактуре, а в форме. Ниже — то, чего не хватало.
## 9.0 ⛔ ТРИ МЕСТА, ГДЕ ДОМЫСЛИВАНИЕ СТОИТ ДЕНЕГ ИЛИ ЗАМЕРА
Прочти их ПЕРВЫМИ; каждое проверено исполнением.
1. **`--verify-bank` НЕ ГАРАНТИРУЕТ останова.** Флаг единственный, кто вообще может остановить
прогон до редакторской волны, но при ПУСТОЙ дельте майнинга движок авто-продолжает
(`mining.go:152-164`, флаг лишь повышает уровень лога). Если это случится, базовый прогон купит
редакторские юниты, и каждая из четырёх копий потребует пересборки снапшота с перекупкой.
**ПОЯС:** базовому прогону ставится `--ceiling-usd` чуть выше ожидания ЧЕРНОВОЙ волны, чтобы
редакторская покупка упёрлась в денежный отказ (код 4), а не прошла молча.
2. **Ось промпта реализуется ТОЛЬКО через `stages[edit].prompt_override`.** Промпт резолвится
конвенцией `<prompts_root>/<пара>/<роль>.md`, а `prompts_root` живёт в `pairs/zh-ru.yaml`,
общем для всех конфигов каталога. ⇒ без `prompt_override` четыре руки схлопнутся в две:
**платишь за четыре, меришь две**. Ловится гардом «четыре разных `snapshot_id`» — снимать его
запросом к `snapshots` каждой из четырёх баз.
3. **Потолка $9.5 не существует как механизма.** Леджер считает по `book_id`, а таблица `spend`
лежит ВНУТРИ проектной базы: четыре копии сторожат каждая себя и каждая уже несёт базовый
расход. ⇒ **агрегат ведётся вручную** (§9.5), и санкционированную сумму держит только он.
## 9.1 СТЕНД
**Образец — `~/books/gu-zhenren/coldrun-v16/`** (его `book.yaml`, `pipeline.yaml`, `pairs/zh-ru.yaml`).
⚠ Каталог берётся как ОБРАЗЕЦ, но не как рабочее место: в нём три оплаченных редакторских юнита,
которые заставят пересборку снапшота на каждой копии.
⛔ **Пути на `models`, `langpack_root`, `prompts_root` обязаны смотреть в
`/home/ubuntu/projects/textmachine-main/`**, а не в своё дерево: **в `polygon` нет
`backend/configs/langpacks/ru`** (проверено: там только `zh`, `zh-ru`), а загрузчик на отсутствующий
каталог молча возвращает умолчания — русский слой читателя потеряется во всех четырёх руках тихо.
`backend/prompts` и `models.yaml` в двух деревьях побайтно совпадают, расходится только `langpacks`.
```bash
B=~/books/gu-zhenren/probe-4axes # новый каталог, не coldrun-v16
mkdir -p $B/{bin,logs,arms}
cp ~/books/gu-zhenren/coldrun-v16/{book.yaml,pipeline.yaml} $B/
cp -r ~/books/gu-zhenren/coldrun-v16/pairs $B/
# исходник: 17 глав, вариант A
eval/.venv/bin/python eval/dovodka/narezka.py --from 26 --to 42 --out $B/guzhenren-ch26-42.gb18030.txt
# бинарь — из main-дерева, sha пинится в пре-рег
cd /home/ubuntu/projects/textmachine-main/backend && go build -o $B/bin/tmctl ./cmd/tmctl
sha256sum $B/bin/tmctl
```
## 9.2 ЧЕТЫРЕ РУКИ
Четыре копии `pipeline.yaml` в `$B/arms/`, различающиеся РОВНО двумя строками стадии `edit`:
| файл | `prompt_override` | `reasoning` |
|---|---|---|
| `p7-off.yaml` | `$B/editor-p7.md` | `"off"` |
| `p7-low.yaml` | `$B/editor-p7.md` | `"low"` |
| `p9-off.yaml` | `$B/editor-p9.md` | `"off"` |
| `p9-low.yaml` | `$B/editor-p9.md` | `"low"` |
| ⭐ `glm-off.yaml` (**референс, не рука креста**) | `$B/editor-p9.md` | `"off"`, модель **`glm-5`** |
```bash
cd /home/ubuntu/projects/textmachine
git show e89874b^:backend/prompts/zh-ru/editor.md > $B/editor-p7.md # июльский
git show HEAD:backend/prompts/zh-ru/editor.md > $B/editor-p9.md # сегодняшний
sha256sum $B/editor-p7.md $B/editor-p9.md # ОБА в пре-рег
```
⚠ **В образце `coldrun-v16/pipeline.yaml` комментарий утверждает, что у `pro` ручки эффорта нет
вовсе** — это протухло. Копируя файл, комментарий поправить или удалить, иначе следующий читатель
получит противоречие своему же плану.
## 9.3 ПОРЯДОК
**Коды выхода, без которых штатный стоп читается как падение:** `0` — чисто · `2` — завершено с
флагами · **`3` — стоп подписи банка** (`WaveSignatureStop`) · **`4` — денежный отказ**
(`CeilingHalt`). Объёмный стоп приходит и как `0`, и как `2`; различает только строка
`VOLUME CEILING:` в выводе.
```bash
# 1. БАЗОВЫЙ ПРОГОН: черновая волна + майнинг + терминолог, стоп ДО редактуры
$B/bin/tmctl translate --config $B/book.yaml --verify-bank --ceiling-usd 1.20 2>&1 | tee $B/logs/base.log
# ожидаемый код 3 (стоп подписи). Код 0/2 ⇒ ⛔ СТОП: дельта была пуста, редактура куплена —
# к владельцу, не продолжать.
# 2. КОПИИ — только через backup, не cp (живые -wal/-shm теряют данные)
$B/bin/tmctl backup --config $B/book.yaml # ⚠ флага --out НЕТ: пишет в $B/backups/<ts>.db
cp $B/backups/<ts>.db $B/arms/p7-off.db # …и так все ПЯТЬ копий
# в каждой копии свой project_db, pipeline и ceilings
# ⛔ если project_db копии не существует, движок заведёт ПУСТУЮ базу и купит черновую волну заново
# 3. ИНТЕРЛИВИНГ: юнит за юнитом, руки в порядке из сида
for u in $(seq 1 $N); do
for arm in $(eval/.venv/bin/python eval/dovodka/poryadok.py --unit $u --seed 20260902); do
$B/bin/tmctl translate --config $B/arms/$arm.yaml --max-units 1 --ceiling-usd <своя> \
2>&1 | tee -a $B/logs/$arm.log
rc=$?; grep -q 'VOLUME CEILING:' $B/logs/$arm.log && break 2
[ $rc -eq 4 ] && { echo "⛔ ПОТОЛОК — СТОП, вопрос владельцу"; exit 4; }
done
done
```
**Увидел требование `--resnapshot` — СТОП, не давать флаг.** Он перекупит все уже оплаченные
клетки. ⚠ Предупреждение планировщика о будущем `--resnapshot` на майнящей книге печатается на
КАЖДОМ ограниченном прогоне (десятки раз) — оно ожидаемо и не есть требование.
## 9.4 РАНДОМИЗАЦИЯ
Порядок рук внутри юнита — детерминированная перестановка от сида; **сид объявляется в пре-реге**
(`20260902`), выпавший порядок пишется в манифест. Без запиненного сида пре-рег не является
пре-регом.
## 9.5 АГРЕГАТ ПОТОЛКА — ВРУЧНУЮ, ПОТОМУ ЧТО МЕХАНИЗМА НЕТ
```bash
for db in $B/arms/*.db $B/*.db; do
echo -n "$(basename $db): "; sqlite3 "$db" "select round(sum(committed_usd+reserved_usd),4) from spend;"
done
```
База считается ОДИН раз (она в каждой копии), поэтому: **израсходовано = база + Σ(копия база)**.
Санкция владельца — **$9.5 в пиковых терминах**; при достижении — стоп и вопрос, добор запрещён.
## 9.6 ЧЕГО ЕЩЁ НЕТ И ЧТО ПИСАТЬ ПЕРЕД ФРИЗОМ
* **скрипт эндпойнта** (`chetyre.py`): ключ юнита, реконструкция попытки 0 (в `request_log` нет
колонки `attempt` — она в `checkpoints`), определение `delivered`, восстановление размышления,
правило цензуры, Вилкоксон с `zero_method='pratt'`;
* ⚠ **медиану и доверительный интервал Ходжеса–Лемана придётся писать руками**: `scipy 1.18.0`
установлен и `pratt` поддерживает, но интервала у `wilcoxon` не отдаёт (проверено);
* ⚠ **ковариатная модель не запустится**: `statsmodels` в `eval/.venv` не установлен;
* `poryadok.py` — генератор порядка рук от сида.
---
# 10. ⛔ ФРИЗ ПРЕ-РЕГИСТРАЦИИ
**Настоящим коммитом пре-регистрация ЗАМОРОЖЕНА.** Дата: 02.09.2026. Объявлено владельцу вслух.
**Что заморожено и после этого коммита НЕ ПРАВИТСЯ:**
* дизайн — крест 2×2 внутри юнита + референсная клетка пятой, фиксированно последней;
* модели — редактор `deepseek-v4-pro`, референс `glm-5` (`thinking` выключен, `few_shot: false`),
черновик и терминолог `deepseek-v4-flash`, судья не вызывается;
* правило решения §4 — эндпойнты E0/E1/E2/E3/E4/E5, критерий `p<0.05`, два исхода, правило цензуры,
метод обработки ничьих, порог «ниже разрешения замера»;
* мощность и её конвенция — плановое **×2.0 при σ=1.2**;
* потолок — **$9.5 в пиковых терминах**, санкция владельца 02.09;
* рамка выборки — главы книги **2642**, все юниты в порядке движка, без отбора;
* сид рандомизации — **20260902**;
* коэффициент восстановления размышления — **0.3644 токена/знак**;
* область переноса §3-БИС и обязательный шаблон формулировки вывода.
**Что фризом НЕ покрыто и остаётся работой исполнителя** (форма — на его усмотрение, требования —
в §9.6 и в промте): скрипты `chetyre.py` и `poryadok.py` · сборка стенда · тексты конфигов.
**Известные шероховатости, названные при фризе, а не скрытые:** смета существует в двух
структурах (обе ниже потолка, расхождение в базе $0.45 против $0.85 и в двойном счёте пред-полёта);
в полировочных местах остались формулировки «четыре руки» там, где теперь пять. Ни то, ни другое не
меняет дизайн, правило решения и потолок.
**Отступление от замороженного = пинг владельцу, а не правка.** Если исполнение покажет, что
что-то из замороженного неверно — это НАХОДКА, которая записывается и предъявляется, а не
исправляется молча.