# ПЛАН ФАЗЫ Д — РЕДАКЦИЯ 4: ПРЕ-РЕГ РАТИФИЦИРОВАННОЙ ПРОБЫ > Редакции 1–3 отвергнуты консилиумом; их разбор — §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` (4412–6946: там доминируют исходник и системное), **но сама длина черновика широка — 427–6171 знак, разброс ×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. **Интерливинг во времени** — пять клеток юнита в окне 10–20 минут, чтобы дрейф сервинга не разошёлся между руками. ⛔ **Останов цикла НЕ по коду выхода:** штатная остановка по объёму приходит **и как 0, и как 2**, различает её только строка `VOLUME CEILING:` в выводе. `|| break` (урок Д47.6) здесь либо рвёт цикл на первом штатном стопе, либо не рвёт никогда ⇒ **цикл разбирает вывод на `VOLUME CEILING:`**. ⚠ Окно 10–20 мин достижимо не всегда: латентности edit-вызовов 43–216 с, ретрай добавляет ~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 тоже одинаков. ⚠ Числа прежней редакции были не те: реальные черновики **427–6171 знак** (не «~7 тыс.»), а «4412–6946» — это `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`. А предмет замера — именно размышление (95–96% цены). **Лечение без правки Go, с замеренной точностью:** `R̂ = completion_tokens − 0.3644·len(response_text)`. Коэффициент — видимый выход pro-редактора на zh→ru; **пере-снят мной независимо: 0.3644 токена/знак, n=16, sd 0.0069**. Ошибка типично ~3% видимого выхода, **худшая клетка 5.3%**; пренебрежима при размышлении в тысячах и заметна лишь при малом размышлении. Коэффициент **пинится в пре-реге**. ⚠ **Границы формулы, названные до покупки** (проверено независимо на 185 клетках рига с отчётным `reasoning_tokens`: 0.367–0.369, sd 0.007–0.010): (1) **любой CJK в выходе** ломает оценку — иероглиф ≈1 токен, видимая часть недооценивается, `R̂` завышается; направление консервативно для E1, но раздувает клетки E5; (2) при `R̂ < ~700` относительная ошибка достигает 20–70% — у мелких клеток `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, на паре zh→ru, на нашей нарезке (~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, для эквивалентности нужно n≈117. **Решение:** `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**. ⚠ Оговорка: 2–4-я клетки юнита бьют префикс-кэш, вход дешевеет ~$0.006–0.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.02–2.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.004–0.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.05–0.065 ⇒ юнит 2·0.09 + 2·(0.05…0.065) = **$0.28–0.31** ⇒ 32 юнита = **$8.96–9.92 до запаса**. Сравнивать это надо со строкой ЮНИТОВ ($10.0), а не с полной суммой: база, эскалация и пред-полёт ($1.1) тратятся при любом срезе. **Зазор 0.8–10.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 | «канон мерен на 1–2 главах» | я сам намерил на 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`.** Промпт резолвится конвенцией `/<пара>/<роль>.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/.db cp $B/backups/.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; * рамка выборки — главы книги **26–42**, все юниты в порядке движка, без отбора; * сид рандомизации — **20260902**; * коэффициент восстановления размышления — **0.3644 токена/знак**; * область переноса §3-БИС и обязательный шаблон формулировки вывода. **Что фризом НЕ покрыто и остаётся работой исполнителя** (форма — на его усмотрение, требования — в §9.6 и в промте): скрипты `chetyre.py` и `poryadok.py` · сборка стенда · тексты конфигов. ⚠ **Известные шероховатости, названные при фризе, а не скрытые:** смета существует в двух структурах (обе ниже потолка, расхождение в базе $0.45 против $0.85 и в двойном счёте пред-полёта); в полировочных местах остались формулировки «четыре руки» там, где теперь пять. Ни то, ни другое не меняет дизайн, правило решения и потолок. **Отступление от замороженного = пинг владельцу, а не правка.** Если исполнение покажет, что что-то из замороженного неверно — это НАХОДКА, которая записывается и предъявляется, а не исправляется молча.