78 KiB
Мини-прогон ~10 глав: сквозной тест построенного (гигиена → главный проход → проба банкноты → верификация)
Ревью-шапка оркестратора №8 (26.07, приёмка execute-first по СЫРЬЮ; ПРИНЯТ —
D39.37). 0 блокеров. Ре-ранено: build/vet/gofmt ·-race13/13 · ценз ИМЁН 475→492 (удалено 0) · парити EXACT · маскированный дифф golden против HEAD пуст вне трёх заявленных осей. Деньги сверены по сырым леджерам до цента: $0.114291 (проекция = списание ТОЧНО) + $0.021688 + $0.003081 (обе оплаты вspend) + $0.048855 + $0.046668 брака = $0.234583. Спот-чеки: банкнота 71/9из20/0 по БД · v11 реальна ·banknote_detailнесёт «学堂家老 → старейшина школы» ·RegressionGuardlive-срабатывание подтверждено МОИМ ре-раном (number_drift:[66]). Находка рубежа-2: моя мутация «отключить джойн WHAT в колл-сайте» ВЫЖИЛА по всей сьюте — фикс доказан прогоном, но не запинён тестом; фикс-лист №1 следующего касания. Оговорки хендоффа §2 ратифицированы как норма чтения этих чисел; хвосты §5 — в трекере с диспозициями (D39.37).
Сессия: бэкенд, одна сессия делает всё (решение владельца). Промт — docs/archive/prompts/BACKEND_MINIRUN_SESSION_PROMPT.md.
Дата: 2026-07-25. Книга: 蛊真人, главы 1–10, новый проект guzhenren-minirun (вне git).
⟶ ЧИТАТЬ ВМЕСТЕ С ХЕНДОФФОМ
MINIRUN_HANDOFF_2026-07-26.md. Там — вес каждого числа этого отчёта (что оно доказывает и чего НЕ доказывает), самооценка честности фиксов, методические ошибки сессии и 8 хвостов, увиденных но не чиненных. Отдельные выводы §6.2 хендофф уточняет: срабатывание dc2 — не дефект реализации, а принятая неоднозначность класса.
§0. ПРЕ-РЕГИСТРАЦИЯ (написана ДО первой траты; ниже НЕ переписывается)
Это первый раздел отчёта и он зафиксирован до единого платного вызова. Причина названа в промте прямо: принцип author ≠ reviewer снят, а по переписи инцидентов проекта самоотчёт — доминирующий канал ошибок (62 из 180). Прогон, у которого критерий успеха дописан после результата, ничего не доказывает, поэтому критерий провала назван здесь заранее.
0.1 Что меряем (M1–M8)
| # | Утверждение, которое прогон обязан подтвердить СЫРЬЁМ | Артефакт-носитель |
|---|---|---|
| M1 | Гейт согласия на пере-оплату (пак-18) отработал ЖИВЬЁМ: показал проекцию (N единиц, ~$X), отказал без флага ДО первой резервации, прошёл с флагом | лог отказа, chunk_status, SpentUSD до/после |
| M2 | Майнинг-стоп остановил прогон перед волной редактуры, записал подписную карту, очистился после подписи (промоушен + reject) | *.db.mined-signature.yaml, mined-delta.yaml, mined-rejects.yaml, логи |
| M3 | Чекеры и QualityReport дали ОСТАТОК ДЕФЕКТОВ по классам ($0 read-only скан) — главное измерение прогона |
tmctl report, repair_candidates |
| M4 | RegressionGuard ПОСЛЕ флипа даёт наблюдаемость (длина/числовой дрейф видны) |
retrieval_state.n_style_flags + style_detail |
| M5 | Лейбл-путь = no-op: резолвнутые модели тождественны конфиговым, ноль строк проблем маршрутизации | tmctl report/status --json, chunk_status.model_* |
| M6 | Деньги durable: доля finish=stop, эхо-класс, reserve→settle одной транзакцией, итог против потолка и против оценки |
request_log, checkpoints, ledger |
| M7 | escalation_model держит ОТВЕТИВШУЮ модель, а не попробованную |
chunk_status.escalation_model |
| M8 | Канал WHAT (банкнота) физически работает от промпта до парсера | сырые тела ответов (LOG_LLM_BODIES), retrieval_state банкнота-телеметрия |
0.2 Пороги и ожидания (названы заранее)
- Деньги главного прохода: ожидание $0.10–0.19 (драфт ≈$0.022 + редактура ≈$0.08–0.15; экстраполяция фактических цифр rerun2 на срез ровно вдвое больший). Потолки книги/дня — $1.00/$1.00, выставлены с 5–6× запасом, но конечны: гейт потолка обязан быть способен выстрелить.
- Проба банкноты: ожидание ≈$0.02 (только волна черновика).
- Проба гейта пере-оплаты (пас-лег): ожидание ≤$0.01 (отдельный микро-проект в одну главу, чтобы «проход с флагом» стоил центы, а не второй прогон).
- Судья НЕ вызывается. Петля ремонта остаётся
enabled: false. Второй арм (glm-5) НЕ гоняется без отдельного слова владельца.
0.3 ЧТО МЫ ЗАРАНЕЕ НАЗЫВАЕМ ПРОВАЛОМ
| # | Провал (заранее) |
|---|---|
| П1 | Фактическая стоимость главного прохода > $0.40 (вдвое выше верха оценки) — модель денег неверна |
| П2 | Пробит потолок книги/дня ИЛИ committed ≠ SUM(checkpoints) вне ратифицированного исключения redrive |
| П3 | Эхо-класс (cjk_artifact) на черновике > 0 — эхо-мина DeepSeek жива при thinking-ON |
| П4 | Гейт пере-оплаты НЕ отказал при проекции выше порога, ИЛИ отказал ПОСЛЕ резервации денег (сырьё: любая новая строка ledger/checkpoint на отказе) |
| П5 | Майнинг-стоп НЕ остановил прогон при непустой дельте, ИЛИ не очистился после того, как каждый терм промоутнут/отклонён |
| П6 | RegressionGuard после флипа молчит, а ручная проверка находит реальный обвал длины/числовой дрейф в отгруженном тексте. (Честный ноль при отсутствии дрейфа — НЕ провал.) |
| П7 | Хоть одна резолвнутая модель ≠ конфиговой ИЛИ есть хоть одна строка проблем маршрутизации на книге без лейблов |
| П8 | Банкнота: n_banknote_lines = 0 по ВСЕМ чанкам (модель не выдаёт блок) ИЛИ parse_fail > 0 (парсер не принимает то, что модель выдаёт) |
| П9 | Остаток дефектов отчитан СЫРЫМ счётчиком без ручного отделения ложняков — решение владельца о платной петле принимается по ЧИСТОМУ остатку |
| П10 | Потеря/порча данных: битая БД, рваное состояние после прерывания, утрата фактуры rerun2 |
0.4 Что заранее объявлено НЕ провалом (чтобы задним числом не переписать)
- Майнинг-стоп с нулём кандидатов — законный исход (сид уже покрывает главы 1–10). Тогда M2 остаётся НЕДОКАЗАННЫМ и отчитывается именно так, а не как успех.
- Эскалация не случилась — законный исход; M7 остаётся НЕДОКАЗАННЫМ.
- Термины приходят на подпись БЕЗ dst — это сегодняшнее ОЖИДАЕМОЕ поведение (D39.36), фиксируется как факт, а не как авария.
- Разрыв канона 元-семейства (元海/真元/元石 расщеплены, единый корень ждёт владельца), отсутствие
学堂家老в сиде,赤城только внутри古月赤城— ИЗВЕСТНЫЕ разрывы, объявленные ДО прогона; чтение результата не имеет права приписывать их качеству перевода. - Качество перевода как таковое НЕ измеряется (судья не зовётся); прогон отвечает на вопрос «работают ли узлы», а не «хорош ли текст».
0.5 Пре-регистрационные факты стенда (зафиксированы до трат)
- Бэкап
rerun2/*.dbсделан ДО первой write-команды:/home/ubuntu/books/gu-zhenren/backup-pre-minirun-2026-07-25/(3 БД + shm/wal). - Срез: строки 93–837 исходного
guzhenren-gb18030.txt= 10 глав, 57 838 байт GB18030. Метод среза проверен воспроизведением: строки 93–469 дают файл, байт-в-байт равныйrerun2/guzhenren-ch1-5.gb18030.txt(sha2568755afd3…d3d76f64). - Манифест до прогона: 10 глав, 14 edit-единиц (
tmctl status, $0). - Слаги живьём (правило двух направлений, до платных вызовов):
GET /v1/modelsDeepSeek →['deepseek-v4-flash', 'deepseek-v4-pro'], оба слага конфига живы.prices_checked: 2026-07-10(15 дней, порог 120). - Ре-чек ToS (D39.32 п.4): проверено, изменений нет. Триггеры не наступили: головной Google ToS — 30.07.2026 (впереди), правок
accepts_labelsв этой сессии не было, книга лейблов не несёт, Gemini в цепочке этого прогона не участвует.
§1. ШАГ 0 — ГИГИЕНА (исполнена ДО прогона, $0-код)
1.1 Обязательный флип Gates.RegressionGuard.Enabled (D38.4 п.5, невыполненное обязательство D39.34)
Включён во всех пяти шиппинг-конфигах: pipeline-c1.yaml · pipeline-c2.yaml · pipeline-arm-deepseek-pro.yaml · pipeline-arm-glm.yaml · pipeline-arm-mistral.yaml (grep -c regression_guard configs/*.yaml = 5). C2 включён осознанно: у него ЕСТЬ стадия edit, значит переход черновик→финал существует и гард не вырожден.
Флип НЕ двигает снапшот — проверено исполнением, а не рассуждением: в логах одного и того же прогона с гейтом и без него обе волны рендерят те же id (snapshot=2ab1b7578d40 драфт, 46e9bc2bcf5a эдит). Пороги гарда — код-консты, а его версия уже сидит в CheapGateVersion ⇒ пере-оплаты флип не стоит.
Покрыт тестом, что гейт РЕАЛЬНО стреляет — internal/pipeline/regressionguard_live_test.go, три теста через настоящий драйвер (норма 11):
TestRegressionGuardFiresLiveWhenEnabled— редактор возвращает текст вчетверо короче черновика и без двух многозначных чисел ⇒n_style_flags=3, вstyle_detail"length_collapse":1,"number_drift":2и сами человекочитаемые строки;TestRegressionGuardSilentWhenDisabled— тот же прогон без гейта ⇒ 0 (гейт opt-in, «выключён = байт-идентично»);TestRegressionGuardComparesDraftAgainstFinal— редактор возвращает черновик БЕЗ изменений ⇒ 0. Пинит, ЧТО именно волна подаёт гарду: разводка «финал против финала» (законная форма драфт-волны) отчитывалась бы чистой книгой вечно.
1.2 Два нита общности (условность снята D39.35)
| нит | было | стало |
|---|---|---|
| множитель DC1 | expectedHours := n * 2 в internal/checks/checkers.go |
n * c.dc1UnitHours, значение из dc_ratio dc1_unit_in_hours 2 в configs/langpacks/zh-ru/dc-checkers.txt |
| Detail-строки | Go-литералы с 时辰/千万/数十万/成 в generic-файле | шаблоны msg<TAB>key<TAB>template в пар-паке, подстановка {name} |
Форма выбрана fail-loud, без Go-дефолта: пак, который несёт детекцию, но не несёт шаблон/отношение, — корраптный, и CompileCheckers падает так же, как на битом регексе (mustPairRatio/mustPairMessages). Это снимает возражение D39.31 п.5 («дефолт шаблона обязан рендерить текущую строку, значит 时辰-литерал остаётся в Go») — дефолта просто нет.
Заодно из engine-файлов убраны ЦЕЛЕВЫЕ литералы, которые соврали бы второй паре/второму таргету, без всякой новой данных-механики: «万/億» и пример 三万→«три миллиона» из сообщения магнитудного гейта, «no valid Russian word» → «the target has no well-formed word», «Latin word … in the Russian output» → «in the target output».
Тесты (internal/checks/checkers_pairdata_test.go): синтетический «второй пар-пак» с отношением 1:1 МОЛЧИТ там, где 2:1 флагает (TestDC1UnitRatioIsPairData); каждая пар-строка рендерится из пакета, а не из Go (TestCheckerDetailTextComesFromPairData); корраптный пак падает с именем недостающего ключа (TestCorruptPairPackFailsLoud, 4 кейса); книга без пакета остаётся инертной (TestNoPackStaysInert).
Сдвинутая версионная ось — ровно одна, называю строкой (как требует промт): langpack_version langpack-v2-a7d4be2c0465 → langpack-v2-a28ed743c99c (замер: тот же пробный тест на HEAD-дереве и на рабочем). Двигает ОБА волновых снапшота для книг, ссылающихся на репозиторный каталог langpack. Для мини-прогона это бесплатно (новый проект), для стендовых книг rerun2 — часть уже состоявшегося расхождения D39.35. CheapGateVersion НЕ бампался осознанно: изменились ТЕКСТЫ строк, а не счётчики и не вердикты; пар-сообщения теперь данные, и их версия — это и есть хеш пакета.
1.3 Опциональное: проекция пере-оплаты в tmctl status (спека D15.2 §9)
Добавлены rebill_units/rebill_usd (оба omitempty) + строка в человекочитаемом рендере. Считает тот же projectRebill, на котором отказывает гейт, — одно определение числа, а не второе, дрейфующее. Булев ConfigDrift СОХРАНЁН (не заменён): его читает полигонная экстракция, а добавление чисел аддитивно. Тест TestStatusPricesTheDriftWithTheGatesOwnNumber пинит, что цифра статуса равна и фактически списанному, и той, что называет отказ гейта.
1.4 Приёмка гигиены исполнением
| проверка | результат |
|---|---|
go build ./... && go vet ./... |
чисто |
go test ./... -race |
15 пакетов ok, 0 FAIL |
| golden | 211c9013f5cfa31562857cc9518488393a647cce489d37113402b159089045d6 — байт-в-байт равен HEAD (git show HEAD:…| sha256sum), пере-капчера не было |
| ценз диффом ИМЁН тестов | 475 → 483, удалено 0 (8 добавленных перечислены выше) |
| мутации (самопроверка исполнением) | 5 мутаций — 5 красных: RegressionEnabled:false · RunCheapGates(…, finalText, finalText, …) · n * 2 вместо данных · renderMsg без подстановки · status не пишет проекцию |
§2. ГЛАВНЫЙ ПРОХОД — что произошло
| манифест | 10 глав → 20 драфт-чанков → 14 edit-единиц |
| прогон 1 | драфт-волна целиком, STOP на майнинг-стопе (exit 3), $0.022205 |
| подпись, раунд 1 | 学堂 → «школа» (владелец рассмотрел «академия», подписал «школа») |
| прогон 2 | драфт резюмнулся за $0.00, стоп СНОВА (exit 3) — расчехлился 学堂家老 |
| подпись, раунд 2 | 学堂家老 → «старейшина школы» |
| прогон 3 | «bank-mining: empty delta, auto-continuing», edit-волна 14/14 ok, $0.092086 |
| итог | 14/14 units done, 0 flagged, committed $0.114291, потолок $1.00 (11.4%) |
Эскалация случилась одна: ch3/chunk0 драфт flagged cjk_artifact → хоп deepseek-v4-pro → ok.
Два edit-юнита (ch5/0, ch6/0) упёрлись в max_tokens=8000, ретрай на 16000 вытащил оба.
§3. ПРОБА БАНКНОТЫ (отдельный проект, только волна черновика)
Проект minirun-banknote/: своя БД, свой book.yaml, КОПИЯ промпта переводчика с блоком ⟦TM-BANK-v1⟧ (шиппинг-файл не тронут), gates.banknote.enabled: true, LOG_LLM_BODIES=1 LOG_LEVEL=debug. $0.021688, 20/20 чанков ok.
| метрика | значение |
|---|---|
n_banknote_lines (сумма) |
71 строка на 9 из 20 чанков |
banknote_parse_fail |
1 чанк (ch3/chunk0) |
banknote_truncated |
0 |
производных чекпоинтов banknote_export |
9 |
| сепаратор в чистом экспорте | 0 вхождений (grep -c по export-banknote.txt), табличных строк-остатков — 0 |
§4. ПРОБА ГЕЙТА СОГЛАСИЯ НА ПЕРЕ-ОПЛАТУ
Гейт стрелял живьём дважды: на микро-проекте minirun-rebill/ (одна глава, чтобы «проход с флагом» стоил центы) и на ГЛАВНОМ проекте (только отказ — он бесплатен).
| лег | команда | исход |
|---|---|---|
| проекция | status |
⚠ RE-PAYMENT: 2 chunk×stage unit(s) … ~$0.001629 |
| отказ без флага | translate |
exit 1, «NOTHING was reserved and no row was touched» |
отказ на --resnapshot БЕЗ согласия |
translate --resnapshot |
exit 1 — ре-пин ≠ согласие на КОНКРЕТНУЮ сумму (развилка пака-18 подтверждена живьём) |
| отказ по потолку | --accept-rebill=0.0001 |
exit 1: «caps consent at $0.000100 — refusing» |
| проход с флагом | --resnapshot --accept-rebill |
WARN rebill_units=2 rebill_usd=0.001629 threshold_usd=0.000081, прогон пере-оплатил $0.001452 |
| главный проект (обе волны сдвинуты) | status + translate |
34 chunk×stage unit(s) … ~$0.114291, отказ; порог $0.005715 (5% от $0.114291) |
Деньги ДО и ПОСЛЕ трёх отказов побайтно те же: spend $0.0016289784 → $0.0016289784, checkpoints 2 → 2, request_log 2 → 2, snapshot_id в chunk_status не сдвинулся. Отказ происходит до резервации и до провайдерского вызова, а не после.
После возврата конфига в исходное состояние снапшот вернулся (2299964c3e56) и проекция замолчала — то есть отказ не оставил следа, а гейт есть чистая функция конфига.
§5. ВЕРДИКТЫ ПО ШАГУ 4 (каждый — с артефактом; проверял так, будто отчёт писал не я)
4.1 Гейт согласия на пере-оплату — ✅ ПОДТВЕРЖДЁН ЖИВЬЁМ (первое исполнение механизма)
Фактура — §4. Отказ ДО денег доказан сырьём, а не текстом сообщения: spend/checkpoints/request_log/snapshot_id побайтно те же после трёх отказов. Сверка проекции с фактической тратой: проекция главного проекта 34 единицы, ~$0.114291 точно равна spend.committed_usd = $0.11429117. Расхождение отсутствует, потому что проекция суммирует хранимые chunk_status.cost_usd — то есть буквально то, что уже было списано. На микро-проекте проекция $0.001629, а фактическая пере-оплата $0.001452 (−11%): это не ошибка проекции, а её семантика — она отвечает «сколько стоила эта работа В ПЕРВЫЙ РАЗ», а второй раз провайдер отдал часть промпта из кэша. Направление безопасное (перед фактом называется не-заниженное число).
4.2 Майнинг-стоп — ✅ ПОДТВЕРЖДЁН, с новым фактом о его форме
Остановился перед edit-волной (exit 3, WARN terms=1), записал подписную карту, после подписи дельта опустела («empty delta, auto-continuing to the edit wave») и стоп не повторился. Драфт-волна при этом резюмнулась за $0.00 (в request_log 40 строк tm_hit=1, cost 0) — «пере-оплачено ОДИН раз» держится.
Термы приходят БЕЗ dst — подтверждено, как ожидаемое поведение (D39.36), не как авария: в обеих подписных картах dst: "".
НОВОЕ (не предсказано ни промтом, ни D39.36): стоп очищается РАУНДАМИ, а не одним заходом. Промоушен 学堂 расчехлил 学堂家老, которого в первом раунде в карте не было (его перекрывала эмиссия). Владелец на первом стопе видит «1 терм» и не может знать, что подписей будет 2 (а на книге — неизвестно сколько). Это не дефект кода, но это свойство контракта, которое стоит назвать вслух рядом с «опциональным ОК» из D39.36.
4.3 Банк памяти — ✅ ПОДТВЕРЖДЁН, с независимой сверкой глазами
injections(exact)=268 · sticky=64 · ambiguous=5 · spoiler-blocked=0 · evicted=0 · post-check-misses=9 на 20 чанках (ориентир прошлого прогона — 107/3 на 10 чанков; здесь вдвое больше чанков и вдвое больше попаданий).
Независимая проверка (взял термины из глоссария, нашёл в исходнике, посмотрел финальный текст):
| терм (канон) | что в отгруженном тексте | вердикт |
|---|---|---|
| 蛊虫 «гу-червь» ×3 | «гу-червей», «гу-червям» | перевод ВЕРЕН; в decl.forms сида только ЕДИНСТВЕННОЕ число ⇒ промах записан честно, но это дыра в данных сида, не дефект перевода |
| 月兰花 «лунная орхидея» | «лунных орхидей» | то же — множественного числа в формах нет |
| 甲等/丙等 «класс А»/«класс В» | «талантом класса «А»», «класса «В»» | смысл верен, канон-форма не воспроизведена буквально: редактор добавил кавычки вокруг литеры |
| 开窍 «открытие апертуры» ×2 | «Церемония открытия апертур» | форма-дрейф (мн. ч. «апертур» вместо «апертуры») |
| 族长 «глава клана» | «Первый глава рода», «в нашем роду Гуюэ» | РЕАЛЬНЫЙ ДРЕЙФ КАНОНА — ровно тот, о котором предупреждает заметка самого сида («⚠ консистентность род/клан») |
Итого 9 промахов: 1 реальный дрейф канона · 4 формальных/косметических · 4 — отсутствие мн. ч. в сиде.
4.4 Чекеры и остаток дефектов — ГЛАВНОЕ ИЗМЕРЕНИЕ ⚠ см. §6
4.5 RegressionGuard после включения — ✅ ЧЕСТНЫЙ НОЛЬ (проверен независимо)
Гард зафиксировал 0 обвалов длины и 0 числовых дрейфов. Пре-регистрация требовала не поверить этому нулю на слово (П6), поэтому я пересчитал переход черновик→финал сам, по чекпоинтам и экспорту:
- отношение непробельных символов финал/черновик по 14 единицам: 0.90 … 1.06 (порог гарда — падение ниже 0.60);
- многозначных чисел ПОТЕРЯНО: 0 во всех 14 единицах;
- единственное «появившееся» число —
10в ch10/0, и это артефакт МОЕЙ сверки:ApplyHeadingдописывает «Глава 10» в экспорт ПОСЛЕ того, как гейты отработали (у глав 1–9 номера однозначные и правилом «≥2 цифр» отсекаются).
⇒ ноль гарда — правда, а не молчание. Наблюдаемость при этом работает: соседние классы в том же канале дали 11 флагов с деталями.
4.6 Путь content-лейблов = no-op — ✅ ПОДТВЕРЖДЁН
SELECT count(*) FROM checkpoints WHERE model_requested <> model_actual = 0. Резолвнутые модели тождественны конфиговым: draft/deepseek-v4-flash ×20, draft/deepseek-v4-pro ×1 (это сконфигурированный escalate_to), edit/deepseek-v4-pro ×16. В status --json полей маршрутизации/лейблов НЕТ ВООБЩЕ (все omitempty) ⇒ read-model книги без лейблов байт-идентичен до-паковому, строк проблем маршрутизации ноль.
4.7 Деньги durable — ✅ ПОДТВЕРЖДЁН (по строкам БД)
| проверка | значение |
|---|---|
spend.committed_usd |
0.11429117 |
SUM(checkpoints.cost_usd) |
0.11429117 (37 строк) |
SUM(chunk_status.cost_usd) |
0.11429117 |
reserved в покое |
0.0 |
jobs |
20/20 done |
доля finish=stop |
35/37 = 94.6% (2 × length, оба вытащены ретраем) |
| потолок | $0.114291 из $1.00 = 11.4% |
Инвариант committed == SUM(checkpoints) держится ТОЧНО, резервов в покое нет ⇒ на этом прогоне не осталось ни одной незакрытой резервации. Честная оговорка о границе доказательства: «reserve→settle одной транзакцией» этот прогон подтверждает КОСВЕННО (нет рваных состояний после 6 запусков процесса); прямое доказательство атомарности — kill9_test.go в CI, живого kill -9 в этом прогоне не делалось.
Эхо-класс — см. §7-Д1: сырой факт «1 эхо из 20», отчётная метрика — 0.0%.
4.8 Слаги и цены живые — ✅
GET /v1/models DeepSeek до платных вызовов: ['deepseek-v4-flash','deepseek-v4-pro'] — оба слага конфига живы, катовер deepseek-chat (24.07) нас не касается. prices_checked: 2026-07-10 (15 дней при пороге 120). Ре-чек ToS (D39.32): проверено, изменений нет (триггеры не наступили).
4.9 Канал WHAT — ✅ ФИЗИЧЕСКИ РАБОТАЕТ, с двумя поправками к тому, как его смотреть
n_banknote_lines= 71 > 0 ✔ ·truncated= 0 ✔ · сепаратор в чистом черновике отсутствует (срезался) ✔ ·parse_fail= 1 ✘ (диагноз ниже).- Диагноз единственного
parse_fail: модель выдала строкуБам, бам-бам → Тук, тук-тук— звукоподражание, вsrcНЕТ ни одного ханьца. Парсер отверг её по правилуhasBankSrcHan— то есть отработал КАК ЗАДУМАН, а негодную строку произвела модель. Флаг сделал свою работу; чинить парсер не надо.
Оценка предложений ГЛАЗАМИ (выборка — все 71 строка, ниже 15 характерных):
Годятся как основа канона: 力量蛊 «гу Силы» · 智慧蛊 «гу Мудрости» (обе — дословно то, что владелец подписал в rerun2 своими руками) · 古月方源 «Гуюэ Фан Юань» · 古月陈博 «Гуюэ Чэньбо» (совпало с подписью rerun2) · 沈嬷嬷 «матушка Шэнь» · 开窍大典 «Церемония открытия апертуры» (дважды одинаково) · 紫府 «Пурпурный дворец» · 华池 «Нефритовый пруд» · 青铜海 «Бронзовое море» · 元石碎块 «осколок первобытного камня» (согласовано с сидовым 元石) · 学堂家老 (три варианта — и это ПОЛЕЗНЫЙ сигнал: терм дрейфует, нужен канон; именно его владелец сегодня и подписал).
Шум, который пришлось бы отклонять: 少年/中年/老年 «юность/средний возраст/старость» · 无 «нет» · 十二分之一 «одна двенадцатая» · 雨声 «звук дождя» · 停息 «прекратиться» · строка-звукоподражание без ханьца.
Прямой ответ на вопрос промта: предложения годятся как основа канона, но не как автоматический канон. Полезная доля — примерно 40–45% строк (имена, титулы, гу-термины, топонимы); остальное — обиходная лексика и числовые выражения, которые владелец отклонял бы. Ценность в том, что предложение приходит ВМЕСТЕ с исходником, а альтернатива сегодня — придумывать русский вариант с нуля на голом терме. Починка шва работы стоит.
§6. ГЛАВНОЕ ИЗМЕРЕНИЕ: ОСТАТОК ДЕФЕКТОВ, ЛОЖНЯКИ ОТДЕЛЕНЫ
Read-only скан ($0) по отгруженному тексту 10 глав.
6.1 Остаток в классах, которые петля ремонта УМЕЕТ чинить
repair_candidates = 0. По классам — пусто: DC1 время 0 · латиница-остаток 0 · битая словоформа 0. (Строка в рендере печатается только при >0; проверено по коду render.go:277 и по --json-полю repair_candidates,omitempty.)
Вход в решение владельца о включении платной петли (D39.24): на этих 10 главах петля не нашла бы НИ ОДНОЙ работы. Она бы отработала вхолостую и стоила бы только денег на скан. Это аргумент НЕ включать её сейчас — но аргумент слабый по объёму выборки: 14 единиц, один арм, одна книга.
6.2 Сырой счётчик наблюдаемости — 11 флагов. Каждый разобран ГЛАЗАМИ
| класс | сырых | реальных | ложняков | почему |
|---|---|---|---|---|
dialogue_dash (смешение стилей речи) |
8 | 0 | 8 | «…»-строки — это ВНУТРЕННИЙ МОНОЛОГ («Становится всё интереснее», — усмехнулся про себя Фан Юань), а «—» — звучащая речь. Это НОРМА русской типографики, а не смешение стилей. Чекер бьёт по законному приёму |
percent_scale (成 как дробь) |
2 | 0 | 2 | «три десятых» = 30%, «сорок четыре сотых» = 44% — масштаб верен, отличается только ФОРМА. Заявленный класс («~100× ошибка масштаба») не реализовался |
dc2_magnitude (千万 как «тысячи») |
1 | 0 | 1 | 杀了千万人 — стоковая ГИПЕРБОЛА («погубил тысячи и тысячи людей»), о чём предупреждает комментарий самого чекера (§5-A4) |
| ИТОГО | 11 | 0 | 11 |
6.3 Остаток по каналу памяти (пост-чек)
9 подтверждённых промахов → после разбора глазами: 1 реальный дрейф канона (族长 «глава рода» вместо «глава клана») · 4 формальных (кавычки вокруг литеры класса ×2, «апертур» вместо «апертуры» ×2) · 4 — дыра в данных сида (нет форм мн. ч. у 蛊虫 и 月兰花).
6.4 ЧИСТЫЙ ОСТАТОК — то, по чему принимается решение
| адресуемых петлёй ремонта дефектов | 0 |
| реальных дефектов, найденных детерминированными чекерами | 0 из 11 сигналов (все 11 — ложняки) |
| реальных дефектов канона, найденных банком | 1 (族长 → род/клан) |
| дефектов, вызванных дырой в ДАННЫХ, а не кодом | 4 (мн. ч. в decl.forms сида) |
| структурный KPI | 3.20 предложения на нарративный абзац (обвала в «одно предложение — абзац» нет) |
| эхо / косметический стрип / вырожденные циклы | 0 / 0 / 0 |
Честный вывод: на этой выборке платить за петлю ремонта не за что, а деньги, которые стоило бы потратить, лежат в двух других местах — в чистке ЛОЖНЯКОВ чекеров (иначе цифра «11 флагов» будет вводить в заблуждение на каждом прогоне) и в ДАННЫХ сида (формы мн. ч.). Обе работы $0.
§7. ДЕНЬГИ: ФАКТ ПРОТИВ ОЦЕНКИ
| статья | оценка промта | факт | вердикт |
|---|---|---|---|
| главный проход (один арм) | $0.10–0.19 | $0.114291 | попал в вилку |
| — драфт | ≈$0.022 | $0.022205 | попал почти точно |
| — редактура | $0.08–0.15 | $0.092086 | попал |
| проба банкноты | ≈$0.02 | $0.021688 | попал |
| проба гейта пере-оплаты | ≤$0.01 (моя пре-рег) | $0.003081 | попал |
| ВСЕГО за сессию | — | $0.139060 |
Где оценка промта оказалась неточна (прямой ответ на вопрос «скажи, где я ошибся»): нигде по сумме — но вилка была построена как «удвоенный rerun2» и случайно совпала, погасив внутри себя 16% брака. Из $0.114291 главного прохода $0.018337 ушло в ПРОВАЛЬНЫЕ попытки: $0.000638 — эхо-черновик, $0.017699 — две обрезанные по max_tokens попытки редактора (см. §8-Д2). Без этого брака проход стоил бы ≈$0.096. То есть модель «драфт + редактура» верна, а вот статьи «брак» в ней нет вообще, и на этом прогоне она составила шестую часть счёта.
§8. НАЙДЕННЫЕ ДЕФЕКТЫ (то, ради чего прогон и затевался)
Д1 — MEDIUM, наблюдаемость: эхо, вылеченное эскалацией, отчитывается как «эха не было»
Сырьё: request_log 18:53:02 — ch3/chunk0 draft, ok=0, err=cjk_artifact, $0.000638. chunk_status той же строки: disposition=ok, escalated=1, escalation_model=deepseek-v4-pro. tmctl report: echo draft=0 (0.0%).
Корень (internal/pipeline/quality.go:245): draftEcho считает строки, у которых chunk_status.flag_reason == cjk_artifact. Успешная эскалация переписывает строку в ok с пустым flag_reason ⇒ эхо исчезает из метрики. Доккоммент честно перечисляет случай c-lite (упавший мембер), но случай «эскалация вылечила» в него не попал.
Почему это важно: эхо-рейт — единственный числовой сторож эхо-мины DeepSeek (D18/D19), и он показывает 0.0% там, где живьём было 5% (1 из 20). На книге в 2284 раздела так теряется весь класс.
Предлагаемый фикс (в пак-19 или отдельной мелочью): считать echo_draft по request_log (attempt-уровень, err=cjk_artifact), а не по финальной строке chunk_status; либо завести на chunk_status durable-флаг «первичная попытка эхнула». Первое дешевле и не трогает схему.
Д2 — MEDIUM, деньги: редактор упирается в max_tokens = флор модели, и это 15.5% счёта
Сырьё: ch5/0 (finish=length, классифицировано empty, $0.008706) и ch6/0 (finish=length, $0.008993) — оба на max_tokens=8000; WARN «stage flagged, regenerating with a larger budget … next_max_tokens=16000»; вторые попытки прошли (ch6/0 отдал 10 951 completion-токен).
Корень: у deepseek-v4-pro capabilities.min_max_tokens: 8000 (флор из D24.3, калиброванный под ЧЕРНОВИК), а max_output_ratio: 2.2 на edit-единице в 3200 ru-токенов даёт меньше флора ⇒ бюджет ВСЕГДА ровно 8000. При этом у DeepSeek thinking-токены входят в completion (reasoning: subset), то есть 8000 делятся между размышлением и текстом. Крупная единица не помещается — платим дважды.
Предлагаемый фикс: считать потолок редактора от РАЗМЕРА ЧЕРНОВИКА единицы (вход редактора), а не от исходника, и/или поднять флор редакторской роли. Дешёвая мера до дизайна — поднять min_max_tokens в конфиге арма. Не делал: это правка поведения вне скоупа промта, и она двигает снапшот.
Д3 — LOW, инструментальный: LOG_LLM_BODIES обрезает тела на 4096 БАЙТ — банкноту в логах не увидеть
internal/obs/logging.go:88: llmBodyLogMax = 4096. Кириллица — 2 байта на символ, перевод чанка — 4–8 КБ, а блок банкноты идёт В КОНЦЕ ответа ⇒ он гарантированно за отсечкой. Способ, предписанный промтом («единственный способ увидеть сами предложения — сырые тела»), физически не работает.
Д4 — ПОПРАВКА К D39.36 (хорошая новость, меняет цену починки шва)
D39.36 утверждает: «предложенный перевод не остаётся и в артефактах прогона». Это не так. Проверено: SELECT count(*) FROM checkpoints WHERE response_text LIKE '%⟦TM-BANK-v1⟧%' = 9 — первичный чекпоинт попытки хранит СЫРОЙ текст ответа вместе с блоком; чистится только ПРОИЗВОДНЫЙ чекпоинт banknote_export (9 строк, во всех блока нет), который и читают редактор с экспортом.
⇒ выбрасывается не текст, а распарсенная структура (_, flags = parseBanknote(...), banknote.go:177). Практическое следствие: чинить шов можно, не пере-прогоняя ничего — dst за любой уже сделанный прогон с включённым каналом восстановим из БД. Именно так я и достал 71 строку для оценки в §5-4.9.
Д5 — свойство контракта (не баг): майнинг-стоп очищается РАУНДАМИ
Подпись 学堂 расчехлила 学堂家老 (второй стоп, второй заход владельца). На книге число раундов заранее неизвестно. Ложится прямо в развилку D39.36 («опциональный ОК вместо жёсткого стопа») как дополнительный аргумент: сегодня цена стопа — не одна пауза, а неизвестное их число.
Д6 — данные, не код: в сиде нет форм МНОЖЕСТВЕННОГО числа
4 из 9 промахов пост-чека — «гу-червей», «гу-червям», «лунных орхидей»: перевод верен, а decl.forms перечисляет только единственное число. Дешёвая правка данных, которая уберёт треть шума пост-чека. Не делал: сид — зона владельца.
Д7 — качество чекеров: 11 сигналов из 11 — ложные (см. §6.2)
Самый крупный класс (dialogue_dash, 8 из 11) systematically бьёт по ЗАКОННОЙ русской типографике «мысль в «…» против речи в «—»». Пока это не исправлено, книжная цифра «N стилевых флагов» не является входом ни в какое решение.
§9. ПРЕ-РЕГИСТРАЦИОННЫЕ КРИТЕРИИ: ЧТО СРАБОТАЛО
Критерии из §0.3 применяю дословно, БЕЗ переопределения задним числом.
| # | статус | по факту |
|---|---|---|
| П1 стоимость > $0.40 | не сработал | $0.114291 |
П2 потолок / committed ≠ SUM(checkpoints) |
не сработал | равенство точное, потолок 11.4% |
| П3 эхо-класс на черновике > 0 | СРАБОТАЛ | 1 из 20 драфт-чанков (5%) отдал cjk_artifact при thinking-ON |
| П4 гейт не отказал / отказал после резервации | не сработал | отказал трижды, ничего не тронув |
| П5 стоп не остановил / не очистился | не сработал | остановился и очистился (за два раунда) |
| П6 гард молчит при реальном дрейфе | не сработал | ноль перепроверен независимо: дрейфа нет |
| П7 модель ≠ конфиговой / строки маршрутизации | не сработал | 0 расхождений, 0 строк |
П8 parse_fail > 0 |
СРАБОТАЛ | 1 чанк — строка без ханьца в src |
| П9 остаток без отделения ложняков | не сработал | ложняки отделены поимённо (§6.2) |
| П10 потеря/порча данных | не сработал | бэкап цел, БД мигрировала v9→v10 штатно, рваных состояний нет |
Разбор двух сработавших — без смягчения формулировки:
- П3 сработал, и я не переопределяю его задним числом. Эхо DeepSeek живо при thinking-ON: 5% на этом срезе (D18 мерил 25% на приёмочной книге — порядок тот же). Механизм ответа отработал ровно как ратифицирован: класс распознан, single-hop эскалация на
deepseek-v4-proвылечила чанк, книга не пострадала. Но факт остаётся фактом: эхо-мина не «закрыта», она компенсируется деньгами — и, как показывает Д1, компенсируется НЕВИДИМО для отчёта. - П8 сработал, и его диагноз меняет адресата, а не статус. Парсер отверг строку
Бам, бам-бам→Тук, тук-тук, у которой вsrcнет ни одного ханьца, — то есть исполнил свой контракт. Негодную строку выдала МОДЕЛЬ. Формулировка моего же критерия («парсер не принимает то, что модель выдаёт») оказалась неточной: она предполагала вину парсера. Критерий сработал, дефект — на стороне промпта/модели, и лечится строкой инструкции («src обязан быть исходным написанием»).
§10. ДЕВИАЦИИ ОТ ПРОМТА (отдельным разделом, как требует приёмка)
- Промт: «LOG_LLM_BODIES включить — записи парсера код выбрасывает, поэтому единственный способ увидеть САМИ предложения — сырые тела». Включил (
LOG_LLM_BODIES=1 LOG_LEVEL=debug), но метод не сработал: тела режутся на 4096 байт и банкнота в хвосте не попадает в лог (Д3). Девиация: предложения извлечены изcheckpoints.response_textпервичных попыток — сырьё более прямое, чем лог. Предпосылка промта заодно опровергнута (Д4). - Промт: «проба банкноты — ОТДЕЛЬНЫЙ проект, только волна черновика». Исполнено буквально. Дополнительно завёл третий микро-проект (
minirun-rebill/, одна глава, только драфт) — промт этого не предусматривал, но требовал «проход с флагом» у rebill-гейта, а на главном проекте это стоило бы второй оплаты всего прогона ($0.114). Микро-проект дал тот же лег за $0.003. - Пар-слой и промпты. rerun2 прописывал
prompt_overrideи inline-segmentation; я вместо этого положил в проект КОПИЮ ратифицированногоpairs/zh-ru.yamlс абсолютнымprompts_rootи гоню промпты КОНВЕНЦИЕЙ (prompts/<пара>/<роль>.md). Пар-данные сверены с репозиторным файлом: не-комментарные строки идентичны. Мотив — проверить штатный шов слоя 2, а не обходить его. escalation.budget_usd: 0.30(rerun2 держал 3.0). Осознанно: на 10 главах бюджет должен позволять эскалации, но не финансировать их десятками.- Второй арм (glm-5) НЕ гонялся — промт разрешает только по отдельному слову владельца. Не спрашивал.
- Владельцу задано ДВА вопроса вместо одного — майнинг-стоп очистился раундами (Д5). Первый: 学堂 (владелец рассмотрел «академию», подписал «школа» после того, как я принёс фактуру из исходника). Второй: 学堂家老 → «старейшина школы».
- Сессия НЕ коммитила — ни код, ни артефакты прогона (промт). Рабочее дерево бэкенда содержит гигиену ШАГА 0 незакоммиченной; книга и производные — вне git.
§11. ЧТО ПРОГОН НЕ ПРОВЕРИЛ (честнее списка успехов)
- Качество перевода. Судья не звался (D39.32). Всё, что сказано выше про текст, — детерминированные сигналы и мои глаза на выборке, а не вердикт о читаемости. Планка «≤2 претензии владельца» этим прогоном НЕ адресовалась.
- Масштаб. 10 глав из 2284 разделов. Ни каденс волн, ни поведение потолков/ETA на сотнях глав, ни деградация банка на длинной книге не проверялись. Цифра «остаток = 0» — про 14 единиц, а не про книгу.
- Второй арм и итерация №2. dspro-vs-glm не сравнивались; вопрос «кто редактор» этим прогоном не двигался.
- Петля ремонта. Осталась
enabled: false. Мы измерили, СКОЛЬКО работы она нашла бы (ноль), но не проверили, что она делает эту работу правильно. - Атомарность reserve→settle под падением. Живого
kill -9не делал; инвариант держится косвенно (нет рваных состояний) и прямо — только тестом в CI. - Лейбл-путь под ЛЕЙБЛОМ. Доказано, что книга БЕЗ лейблов идёт байт-идентично; путь помеченной книги (маршрутизация,
label_models, fail-closed) живьём не гонялся — помеченных книг нет. - Канал B / 18+. Не трогались (промт запрещает).
- Эскалация дальше первого хопа. Случился ровно один хоп и он ответил; поведение цепочки при отказе ПЕРВОГО хопа (
escalation_modelна отказавшем хопе — кейс, ради которого пере-капчерился golden в паке-18) живьём не воспроизводилось. - Резюм после падения посреди волны. Все три остановки были штатными (майнинг-стоп, отказ гейта). Аварийного прерывания не было.
- ja/en-пары. Инвариант общности §0 проверялся кодом и тестами (синтетический «второй пак»), но не живой книгой на другой паре.
- Банкнота в шиппинг-форме. Проверен канал, а не продукт: dst по-прежнему выбрасывается кодом, майнинг-стоп по-прежнему отдаёт голые термы. Проба доказала, что чинить есть что и есть из чего.
§12. ЧТО ЛОЖИТСЯ НА ВЛАДЕЛЬЦА / В ОЧЕРЕДЬ
- Решение о платной петле ремонта (D39.24): чистый остаток в её классах — 0. Моя рекомендация — НЕ включать сейчас; вернуться к вопросу, когда появится выборка больше 14 единиц или когда классы петли расширятся.
- Шов банкноты (развилка D39.36): проба говорит «канал работает, предложения годятся как основа канона (~40–45% полезных), и dst НЕ потерян — он в БД». Починка дешевле, чем считалось: пере-прогон не нужен.
- Д1 (эхо-метрика слепа к вылеченному эскалацией эху) — фикс дешёвый, но это правка кода: в пак-19 или отдельной мелочью.
- Д2 (редакторский
max_tokens= флор модели, 15.5% денег в брак) — требует решения о том, откуда считать потолок редактора; двигает снапшот, поэтому едет с ближайшим resnapshot. - Д6 (нет форм мн. ч. в сиде) и 族长 → род/клан — правки ДАННЫХ сида, зона владельца, $0.
- Д7 (11 ложняков из 11) — чистка чекеров:
dialogue_dashне должен считать «мысль в «…»» смешением стилей;percent_scaleне должен называть верный масштаб ошибкой масштаба. - Сдвинутая ось
langpack_version(a7d4be2c0465→a28ed743c99c) — при следующем прогоне СТЕНДОВЫХ книг это часть уже состоявшегося расхождения D39.35, отдельной оплаты не создаёт.
§13. АРТЕФАКТЫ (для приёмки по сырью и ре-рана манифеста)
| артефакт | путь |
|---|---|
| главный проект | /home/ubuntu/books/gu-zhenren/minirun/ — book.yaml, pipeline.yaml, pairs/zh-ru.yaml, guzhenren-minirun.db |
| логи главного прохода | run-01-draft.log (стоп 1) · run-02-edit.log (стоп 2) · run-03-edit.log (edit-волна) · run-04-rebill-refusal.log |
| подписи | mined-delta.yaml (2 терма) · mined-rejects.yaml (пусто) · guzhenren-minirun.db.mined-signature.yaml |
| проекции | status-final.txt · status-final.json · report-final.txt · export.json · export.txt |
| проба банкноты | /home/ubuntu/books/gu-zhenren/minirun-banknote/ — run-banknote.log, guzhenren-banknote.db, export-banknote.txt, prompts/zh-ru/translator.md (копия с блоком) |
| проба rebill-гейта | /home/ubuntu/books/gu-zhenren/minirun-rebill/ — run-01-baseline.log … run-05-accept.log, guzhenren-rebill.db |
| бэкап фактуры rerun2 | /home/ubuntu/books/gu-zhenren/backup-pre-minirun-2026-07-25/ |
| код гигиены (НЕ закоммичен) | backend/: configs/pipeline-*.yaml, configs/langpacks/zh-ru/dc-checkers.txt, internal/lang/langpack.go, internal/checks/{checkers.go,cheapgates.go}, internal/pipeline/status.go, cmd/tmctl/render.go + 3 новых тест-файла |
Ре-ран манифеста приёмки (всё $0):
cd backend && go build ./... && go vet ./... && go test ./... -race
sha256sum internal/pipeline/testdata/golden/capture.golden # 211c9013…089045d6 == HEAD
grep -rh '^func Test' --include=*_test.go . | wc -l # 483 (было 475, удалено 0)
tmctl status --config /home/ubuntu/books/gu-zhenren/minirun/book.yaml
tmctl report --config /home/ubuntu/books/gu-zhenren/minirun/book.yaml
tmctl export --config /home/ubuntu/books/gu-zhenren/minirun/book.yaml --plaintext
§14. ФИКС-ПАК ПО ИТОГАМ ПРОГОНА (та же сессия, санкция владельца: «исследование → правки → ревью»)
Четыре дефекта починены, два кандидата на починку сознательно ОТКЛОНЕНЫ по итогам исследования — и это главный результат раздела: правка, умершая о ратифицированную фикстуру, дешевле правки, которая её тихо переписала.
14.1 Что построено
| # | Фикс | Форма | Сдвигает снапшот? |
|---|---|---|---|
| Д1 | chunk_status.first_flag_reason (миграция v11) + echo_draft считает эхо, вылеченное эскалацией; новое поле echo_draft_recovered держит число честным в обе стороны |
код + схема | нет |
| Д4 | retrieval_state.banknote_detail (та же v11) — распарсенные записи банкноты durable; майнинг-стоп джойнит их в подписную карту: dst = самое частое предложение, альтернативы с весами в note, status: auto НЕ трогается |
код + схема | нет |
| Д7a | dialogue_dash больше не считает смешением стилей строку, чья атрибуция — глагол ВНУТРЕННЕЙ речи (данные таргета inner_speech) |
код + target-данные | да (CheapGateVersion v4→v5) |
| Д3 | LOG_LLM_BODIES: кап 4096→32768 байт и обрезка СЕРЕДИНЫ, а не хвоста — блок банкноты живёт в хвосте ответа |
код | нет |
| Д2 | флор deepseek-v4-pro 8000→16000 по замеру (перебор бюджета бесплатен, недобор стоит целой генерации) |
данные models.yaml |
да (max_tokens ∈ request_hash) |
Ключевая находка исследования, удешевившая Д4: сырой текст банкноты УЖЕ durable в чекпоинте, а resume его пере-парсит (stagerun.go resume-path) — поэтому новая таблица не нужна, хватило четвёртой *_detail-колонки рядом с тремя такими же.
Граница безопасности Д4 названа явно: предложенный dst приезжает как ЕВИДЕНС на терме status: auto. Trust-gate (D39.2) в инъекцию пускает только CONFIRMED, значит «модель предложила» не может само стать «книга использует». Развилки D39.36 п.2/п.3 (опциональный ОК, ослабление trust-gate) НЕ трогались — это продуктовое решение владельца.
14.2 Что ОТКЛОНЕНО и почему (обе правки были написаны, прогнаны и откачены)
percent_scale. Мой отчёт назвал 2 живых срабатывания ложняками (масштаб верен, форма — дробь). Правка «стрелять только на ЦИФРОВОЙ форме» уронила ратифицированную фикстуру«шесть и шесть десятых»= 6.6 для 六成六 — это НАСТОЯЩАЯ 100× ошибка, и она тоже прописана словами. То есть цифро-словесная граница не разделяет классы; разделяет ЗНАЧЕНИЕ, а для него нужен разбор числительных таргета в данные. Правка откачена, дизайн записан.dc2千万. Живое срабатывание (杀了千万人 → «тысячи и тысячи людей») шейпом тождественно ратифицированному ИСТИННОМУ (千万生灵 → «тысячи жизней»). Вето по коэффициенту убивало оба. Вывод, который правит мой же §6.2: это не дефект реализации, а принятая неоднозначность класса, о которой предупреждает его собственный комментарий (§5-A4). Правка откачена.
⇒ чистый остаток ложняков после фикс-пака: 8 из 11 закрыты (dialogue_dash), 3 остаются осознанно — 2 percent_scale (ждут числительных в данных) и 1 dc2 (offline неразделим).
14.3 Ревью исполнением
| проверка | результат |
|---|---|
| build / vet / gofmt | чисто (единственная жалоба internal/llm/llm.go воспроизводится на HEAD — файл не трогался) |
go test ./... -race |
15 пакетов green, 0 FAIL |
| golden | пере-капчер САНКЦИОНИРОВАННЫЙ и доказанный: 172 сырых строки сдвинулись, но МАСКИРОВАННЫЙ структурный дифф (хеши→<HASH>, версия→<CHEAPGATE_VERSION>) ПУСТ ⇒ двигались только версии и производные от них хеши, ни один вердикт/текст/стоимость не изменились. 211c9013…089045d6 → 1165e3a9…2132ea82 |
| ценз ИМЁН тестов | 483 → 491, удалено 0 |
| мутации | 6 мутаций — 6 красных: echo-метрика читает только вердикт · first_flag_reason пишется и когда он И ЕСТЬ вердикт (двойной счёт) · записи банкноты снова выбрасываются · подписная карта перестаёт нести dst · дискриминатор внутренней речи выключен · обрезка лога снова хвостовая |
| проверка на ЖИВЫХ данных прогона | реальные 9 блоков банкноты из БД пробы прогнаны через НОВЫЙ шов: 71 строка, 67 различных ключей, 2 терма с конкурирующими вариантами. Среди них — 学堂家老, тот самый, который владелец сегодня подписывал вслепую: под фиксом карта пришла бы с dst: «старейшина школы» (+ «старейшина-наставник», «учитель-старейшина» в note) — ровно тем вариантом, который владелец и выбрал |
Честная граница этой проверки: $0-реплей ПОЛНОГО прогона через новый код невозможен — правки Д7a/Д2 двигают снапшот, и job-пиннинг корректно отказал («already-paid checkpoints become invalid»). Это не дефект, а работающая дисциплина; поэтому живьём проверены ПУРЕ-функции нового шва на реальных ответах, а сквозняк — тремя тестами через настоящий драйвер.
14.3-bis МОЯ ОШИБКА В ХОДЕ РЕВЬЮ: непреднамеренная трата $0.046668
Проверяя, что миграция v9→v11 чисто ложится на БД стендовой схемы, я собрал book.yaml, указывающий на КОПИЮ rerun2-БД, но оставил в нём источник и пайплайн мини-прогона. Для движка это была НОВАЯ книга (строк guzhenren-minirun в той БД нет) — и он честно начал переводить. Прогон шёл ~5 минут до моего таймаута.
Точный счёт (по строкам БД-копии): guzhenren-minirun / 2026-07-25 → $0.046668, 31 живой вызов. Деньги потрачены зря.
Что НЕ пострадало (проверено): оригинальная rerun2/guzhenren-rerun2.db — схема по-прежнему v9, единственный book_id = guzhenren-rerun2, spend не изменился · бэкап 25.07 цел · БД мини-прогона и пробы банкноты нетронуты (v10, свои суммы). Трата целиком осталась на выбрасываемой копии в скретчпаде.
Что проверка всё же дала: миграция v9→v11 применилась чисто (schema_version 1…11, обе колонки на месте, старые строки целы) — ради этого она и затевалась; и в логе видно max_tokens=16000 на живом вызове редактора, то есть фикс Д2 подтверждён исполнением.
Правильный способ, которым надо было это делать: открывать стор на запись командой, которая гарантированно не доходит до провайдера (или на БД, где книга уже завершена), а не собирать конфиг «чужая БД + чужой источник».
Итог по деньгам сессии: $0.139060 (прогон + проба + гейт) + $0.046668 брака ревью = $0.185728.
14.4 Цена следующего прогона
Две оси версий сдвинуты осознанно: style_check_version (v4→v5) и max_tokens через флор dspro. Обе входят в снапшот ⇒ следующий платный прогон стендовой книги пере-оплачивается целиком и потребует --resnapshot --accept-rebill. На сегодня это ничего не стоит: мини-прогон закрыт, а стендовый снапшот и так разошёлся (D39.35). Экономия от Д2 (≈15% счёта на браке) окупает пере-пин на первом же прогоне.
§15. СКВОЗНАЯ ПРОВЕРКА БЭКЕНДА ПОСЛЕ ФИКС-ПАКА (26.07, по вопросу владельца «а ты протестировал?»)
Вопрос был законный: после фиксов я прогнал ТЕСТЫ, но не гонял БЭКЕНД. Прогнал — два проверочных прогона, $0.049, и они нашли то, чего тесты не могли.
15.1 Что проверено живьём
Проект minirun-verify (главы 1–2) и minirun-verify2 (главы 4–5, выбраны потому, что там ЕСТЬ майнинг-кандидат), оба с включённой банкнотой — иначе главный фикс не отрабатывает.
| узел | результат |
|---|---|
| миграция v11 на свежей БД | схема 1…11, обе новые колонки на месте |
| ingest → чанкер | 2 главы → 4 драфт-чанка → 3 edit-единицы |
| драфт-волна с банкнотой | n_banknote_lines 7 и 3, banknote_detail записан живьём (396 и 193 байта) |
| майнинг-стоп | выстрелил, 2 терма, подписная карта записана |
| подпись → резюм | стоп очистился, драфт резюмнулся за $0, edit-волна прошла 3/3 |
| санитайзер | поймал РЕАЛЬНЫЙ дефект: mixed Cyrillic and Latin in one word (homoglyph): лицó |
RegressionGuard |
ПЕРВОЕ ЖИВОЕ СРАБАТЫВАНИЕ: number_drift [66] — черновик писал «66%», редактор «шестьдесят шесть процентов». Значение цело, цифра ушла ⇒ это ровно тот ложняк, который предсказан в его собственной доке. Гейт, невключённый до 25.07, теперь даёт сигнал |
| банк памяти | 56 попаданий + 12 sticky, 2 промаха пост-чека |
| экспорт | 31 715 байт, сепаратор банкноты в отгруженном тексте 0 раз |
| деньги | $0.032764 из потолка $0.30, finish=stop на всех вызовах |
15.2 Что нашёл ТОЛЬКО сквозной прогон
(1) Поправка к тому, что я сказал владельцу вчера. Я утверждал: «под фиксом подписная карта пришла бы с dst «старейшина школы» — ровно тем, что владелец выбрал». Верно только для ВТОРОЙ подписи. Проверка по сырью пробы: банкнота НИКОГДА не предлагала 学堂 отдельно — только составной 学堂家老. Значит раунд 1 всё равно пришёл бы голым.
(2) Структурный разрыв, из-за которого фикс даёт меньше, чем кажется. На verify2 стоп выстрелил с terms_with_proposed_dst=0: майнер предложил 花海 и 陈博, банкнота — 古月方源, 学堂家老, 开窍大典, 力量蛊, 智慧蛊, 灵泉. Пересечение НУЛЕВОЕ. Механизм джойна исправен (ключи нормализуются верно), но два канала систематически выбирают РАЗНЫЕ популяции: майнер — частотные name/place/title (freq ≥ 5), банкнота — то, что модель считает новой терминологией. Итог: на 10 главах шов помог бы в 1 подписном раунде из 2, на 2 главах — в 0 из 1. Следующая работа по банкноте — не «замкнуть шов» (замкнут), а заставить WHAT покрывать кандидатов WHICH (например, инъекция списка mined-кандидатов в промпт переводчика).
(3) Полярность дискриминатора чекера была выбрана неверно — исправлено по живым данным. Первая версия спрашивала «это МЫСЛЬ?» по списку глаголов мысли. Живой прогон за минуты выдал «понимал» и «размышлял», которых в списке нет: список мыслей не имеет естественной границы, и каждый промах = ложный флаг на хорошей прозе. Перевернул: «это РЕЧЬ?» по закрытому списку речевых глаголов + вето про себя/мысленно (нашлось на «пробормотал про себя»). Промах теперь = МОЛЧАНИЕ, а не флаг — та ошибка, которую и требует ратифицированный уклон precision-over-recall.
Замер по реальным экспортам, по чанкам: мини-прогон 10 глав 8 → 0, проверка 2 глав 1 → 0, при этом настоящее смешение речи («…», — сказал он) по-прежнему флагается.
(4) Дыра в моих же тестах, вскрытая мутацией. Мутация «снять nil/no-data гард» ВЫЖИЛА: ветка «книга без данных таргета» была не покрыта, а без гарда там nil-разыменование. Закрыто тестом TestLintDialogueDashInertWithoutTargetData (nil-спека и спека без данных: правило молчит, но его data-independent половина — дефис вместо тире — продолжает работать). Пере-мутация после этого — красная с паникой.
15.3 Ревью финального состояния
build/vet/gofmt чисты · -race 15/15 · golden пере-капчен ВТОРОЙ раз (точное имя версии cheapgate-v5-chevron-speech-attribution), маскированный структурный дифф снова ПУСТ → 281d7025…dd9b99b4 · ценз ИМЁН 475 → 492, удалено 0 · 9 мутаций суммарно — 9 красных (три последние по новому правилу; одна выжила, вскрыла дыру, дыра закрыта, пере-мутация красная).
Деньги проверки: $0.032764 + $0.016091 = $0.048855. Итог сессии: $0.139060 (прогон) + $0.046668 (мой брак) + $0.048855 (сквозная проверка) = $0.234583.