1080 lines
No EOL
766 KiB
JSON
1080 lines
No EOL
766 KiB
JSON
{
|
||
"lines": [
|
||
{
|
||
"agentId": "a0850d7db152b7c81",
|
||
"checked": "Прогнал исполнением все пять названных инструментов + грунтовал чтением тех, кого они дёргают.\n1) `eval/.venv/bin/python eval/dovodka/material_ja.py` — 48 чанков, гардрейл 0/48, отбор 9 единиц из 9 РАЗНЫХ глав (6,8,9,11,12,13,15,16,18), длины 1148…1177. Разные главы подтверждены.\n2) Контроль гардрейла: синтетические пробы через `M.AGE/M.SEX` (детектор жив: 2 из 3 проб срабатывают) + пере-прогон HEAD-редакции material_ja.py на снятом `isekai_majutsushi_jp.txt` — воспроизвёл заявленные «3 срабатывания из 184 чанков» ровно (индексы 87,122,142). Заявка в докстринге честная.\n3) `grep -rn \"AI直接使用|AI支援|生成AI\" --include=*.py eval/` → только докстринг material_ja.py:11,14; `grep -c` по самому `~/books/enkan_no_hate_ja.txt` → 0 (метаданных в файле нет); `grep -rln \"n7233mn|syosetu|enkan_no_hate\"` по eval/ и docs/ → ни одного артефакта провенанса.\n4) `eval/.venv/bin/python eval/dovodka/promptdiff.py en-ru ja-ru` → всё зелёное, BAD=0. Затем две дыры проверены ИСПОЛНЕНИЕМ на копии дерева в скретчпаде (репо не трогал, подменял `m.REPO/m.BATTLE/m.PAIRS`): (а) удалил `ja-ru/editor.md` → «ПАР-ПРОМПТЫ КОНСИСТЕНТНЫ», BAD=0; (б) переписал хвосты обеих «объявленных» строк в `en-ru/editor.md` на «делай что хочешь» → «ПАР-ПРОМПТЫ КОНСИСТЕНТНЫ», BAD=0.\n5) `eval/.venv/bin/python eval/dovodka/canon.py` — сальдо 23, валовая потеря 35, 24 места, 3 нарушения единообразия; сверил вывод с содержимым `~/books/dovodka/canon-dissect.json` (24 записи, поле `cls`: парафраз 19 / другой 4 / исчез 1).\n6) `eval/.venv/bin/python eval/dovodka/runs.py --selftest` (зелёный) и `| grep -c '^\\[OK \\]'` → 15; `--report` → журнала на диске нет, 0 из 80.\n7) `eval/.venv/bin/python eval/editor_tier/axiscal.py` — отработал, sha1-сверка посадки прошла на всех 16 единицах (это его настоящий контроль, он исполнен). Отдельно СЧИТАЛ нулевую модель атрибуции: те же окна в случайных местах того же текста, 20 жребиев × 78 окон → ложное срабатывание Claude 0.02, Sol 0.09.\nНичего не покупал, ни одного сетевого вызова, файлы репозитория не правил. Попутно независимо подтвердил Д-1: `prompts.py:104` объявляет `translator_msgs(src, block, en=False)`, `contour.py:252` зовёт `PR.translator_msgs(src)` — TypeError, ветка «арм пропущен» недостижима."
|
||
},
|
||
{
|
||
"agentId": "a1a6567a6d7165056",
|
||
"checked": "1) Сумма cost_usd по сырью: `~/books/dovodka/*.json` = 148 клеток, $1.139729; ровно это печатает `money_d.py --report` (ФД-A 0.871904 + ФД-F 0.267825). Расхождения нет; файлов мимо глоба `dv-*.json` нет (`canon-dissect.json` — $0-свод, не запись покупки), клеток фазы Д в `~/books/editor-tier` не осталось (0 файлов с полем arm).\n2) Формула цены пере-считана руками на реальной клетке `dv-a-a1-00e4c3496f`: (4557−256)/1e6·0.435 + 256/1e6·0.003625 + 2997/1e6·0.87 = $0.004479253 против записанного 0.004479. Затем прогнал независимый пере-счёт по прайсу `tenant_panel/roster.py` для ВСЕХ 148 клеток — 0 расхождений; инвариант total=prompt+completion держится 148/148, значит reasoning DeepSeek внутри completion и не теряется (сумма reasoning 560733 токенов, reasoning_tokens=0 ни у одной клетки).\n3) Кэш: 112384 токенов на 144 клетках по $0.003625/1M — цена совпадает с каноном проекта (`docs/experiments/08-cost-model-v2.md:25`, `role_topology/prices.py:21`); занижения нет, вся кэш-статья пака ≈ $0.0004.\n4) `sum(CEILINGS)=4.495 ≤ 4.50` — правда, но свободного запаса $0.005.\n5) Гард воспроизведён исполнением: `Guarded('ФД-A')` при next_model=deepseek-v4-pro даёт `False [СТОП ФД-A] 0.871904 + 0.015945 = 0.887849 > 0.885`; ожидание 0.015945 = max клетки пака. `Guarded('ФД-F')` тоже уже отказывает.\n6) Смета сверена с фактом: `plan.py` печатает фиксер $0.00314 / критик $0.01120; медианы по 148 клеткам фазы — фиксер $0.007561, критик $0.005758. Медианы по армам: A1 0.006865, A3crit 0.005190, A3fix 0.007411, A4 0.007937, A6crit 0.007777, A6fix 0.008875.\n7) `contour.py --plan` + $0-прогон `canon_gaps`/`flags_of` по недостающим uid: у A4 из 10 непокрытых юнитов 9 имеют места (то есть остановлены гардом) и 1 (474f822806) мест не имеет — цифра заказа «A4 9 клеток» подтверждается; у A1 оба непокрытых юнита (474f822806, 9b16c9c9a7) дают 0 мест, то есть A1 = 30/30, деньгами не заблокирован."
|
||
},
|
||
{
|
||
"agentId": "a41fdd93e6a42188e",
|
||
"checked": "Прочитал заказ `docs/POLYGON_EXP2223_REDO_SESSION_PROMPT.md` целиком (208 строк), разложил на требования по секциям Д0–Д8 / «Нормы рига» / «Анти-лень» / «Чего НЕ делать» / «Отчёт и сдача» и сверил каждое с реестром `eval/dovodka/requirements.md` (77 строк R1–R77 + 12 строк-заголовков) и с кодом/сырьём.\nПрогнал `eval/.venv/bin/python eval/conformance.py eval/dovodka/requirements.md --plan` → «требований 89 · ожидают 58 · провалов 3» (R3, R55, R71), «сам-себя 9 из 89».\nПрогнал батарею гейтов: verify22 EXIT=1, itog22/verify23/runs --selftest/money_d --selftest/contour --selftest/power/canon/promptdiff en-ru/promptdiff ja-ru/plan — EXIT=0.\nРазобрал все 148 платных клеток `~/books/dovodka/dv-*.json` скриптом: раскладка по (arm, role), finish, стоимости, places, доля иероглифов в выводе, reasoning_tokens.\nИмпортировал `eval/dovodka/contour.py` и посчитал $0: какие единицы выпали из A1/A4 и сколько у них мест; долю CJK в базах `base_draft`/`base_a0`/`base_draft2` по всем 32 единицам; прогнал штатный гейт `bakeoff.draft_reject_reason` на подозрительной базе.\nПроверил кассу (`money_d.py` — отчёт по фазам), поведение гарда в `eval/role_topology/buy.py:143-146`, журнал агент-сессий `runs.py`, каталог внешнего судьи `~/books/editor-tier/sol-tier/`, наличие/содержимое ja-материала в `~/books`, `git log`/`git status` по зоне.\nПроверил улики реестра руками, включая те, что зелёные: воспроизвёл команды R36/R37/R55/R3/R71 в shell дословно."
|
||
},
|
||
{
|
||
"agentId": "a5fc66f556e9bf971",
|
||
"checked": "Все числа получены скриптами в /tmp/claude-1000/.../scratchpad/an1..an11.py на eval/.venv/bin/python; an1.py грузит contour.py (без --run, сетевых вызовов нет) и выгружает входы всех 32 единиц в inputs.json, остальные считают поверх ~/books/dovodka/*.json.\n(1) ФИКСЕР НЕ СТАЛ РЕДАКТОРОМ — главный вопрос закрыт положительно (an2.py, difflib по символам и по строкам, вход=черновик для A1/A3, draft2 для A6, A0 для A4):\n арм N char_chg медиана (мин–макс) line_chg медиана len out/in медиана\n A1 30 0.002 (0.000–0.082) 0.024 1.002\n A3 32 0.036 (0.003–0.100) 0.247 1.002\n A4 22 0.003 (0.000–0.387) 0.051 1.002\n A6 16 0.037 (0.005–0.062) 0.324 0.995\n A0 (эталон «перепис целиком») 32: char 0.189, line 0.947, len 0.999.\n Контраст «точечно против переписа» цел: смысловой контур трогает 3.6% знаков против 18.9% у переписа, разрыв ×5 по знакам и ×4 по строкам.\n(2) an5.py: преамбул, ```-обёрток, md-заголовков, списков вместо текста, пустых клеток — НОЛЬ на 118 фиксерских клетках.\n(3) an2/an3: объём совпадает, все клетки в полосе 0.95–1.06 кроме двух A4 с finish=length (0.442 и 0.710) и эхо-единицы.\n(4) an5.py: побайтных дублей МЕЖДУ армами нет (0), идентичных content во всём пуле нет; но 5 клеток побайтно равны своему ВХОДУ — см. находку 4.\n(5) an7/an8/an9: критик отработал содержательно — 2404 места, 99.5% в формате «цитата → ошибка», мусорных строк 3, заголовков-рубрик 0; фиксер реально тронул 71.0% (A3) и 74.7% (A6) названных цитат, клеток с нулём правок нет.\n(6) an6/an11: канон-покрытие ДО→ПОСЛЕ — A1 74→41 (починено 34, заведено 1), A3 74→72, A4 69→63 (починено 19, заведено 13), A6 54→48. Но положительный класс самого гейта негоден — находка 1.\nПере-открывать Д-1..Д-5 не стал; Д-2 подтверждён косвенно: в 30 строках A1 поле places РОВНО равно числу канон-пробелов, вклад батареи ноль (an6.py, таблица «A1 подробно»)."
|
||
},
|
||
{
|
||
"agentId": "a740983d32fb3ff56",
|
||
"checked": "Коды возврата (реальные, не через пайп): contour.py --selftest 0 · money_d.py --selftest 0 · runs.py --selftest 0 · power.py 0 · canon.py 0 · promptdiff.py en-ru 0 · promptdiff.py ja-ru 0 · verify23.py 0 · itog23.py 0 · itog22.py 0 · verify22.py 1 · conformance.py без аргументов 1 (это печать usage, не сверка) · conformance.py eval/dovodka/requirements.md --plan 1 · --final 1. Ruff по eval/dovodka+conformance+editor_tier+tenant_panel+role_topology — «All checks passed», RC 0.\nПрочитано целиком: conformance.py, requirements.md, contour.py, money_d.py, power.py, шапки canon.py/promptdiff.py/runs.py/verify23.py, money.py:130-200.\nИсполнено сверх заказа ($0, без сети): пере-снят состав флагов A1 на всех 32 единицах через импорт contour (74 КАНОН-флага, 0 БАТАРЕЯ, ошибка батареи без глушения — AttributeError 'dict' object has no attribute 'final'); разложение 74 флагов на «канон отсутствует» (16) против «канон есть, но реже» (58); инвентарь ~/books/dovodka по arm/role/finish; пере-счёт MDE функцией power.mde при фактических n; пере-счёт остатка ФД-A и стоимости недокупленного; сверка mtime всего дерева ~/books против коммита fd3e522; поведение sh на улике с `\\|`; демо подстрочной коллизии verify23.has.\nПопытка сломать гейт исполнена: улика с экранированным пайпом, ложное число рядом с истинным, подстрока «+0.50» внутри «+0.508»."
|
||
},
|
||
{
|
||
"agentId": "a812a92d98e26ea57",
|
||
"checked": "Сверху вниз: выписал проверяемые утверждения из Д0 (23-editor-tier.md:719-896), секции «Полигон» docs/PROGRESS.md:193+ и хендоффа ~/CONTINUATION_PROMPT.md (починки D-1..D-12), и грунтовал каждое до кода и сырья. Исполнено: `power.py` (сверка таблицы Д0.3 с реальной печатью; пере-счёт MDE при k=1/3/5 через сам power.mde); `plan.py`, `money_d.py`, `money_d.py --selftest`, `contour.py --selftest`, `contour.py --floor`, `material_ja.py`, `runs.py --selftest`, весь список гейтов из хендоффа §5 (11 команд, коды выхода записаны); `git show <коммит>:eval/dovodka/power.py` по четырём коммитам фризов. По сырью ~/books/dovodka (150 файлов): суммы и медианы по армам, finish-статусы, попарное сравнение цены A1 с A0 на тех же 30 единицах, доля изменённого текста каждого арма против его базы через difflib (A1/A3/A4/A6 и A0 против черновика), длины выходов, поля записи клетки. Исполнением воспроизвёл падение батареи (`battery.run_unit` → AttributeError) и содержимое флагов A1. Проверил семантику `tp2-edit-E-<model>` (edit БОЕВЫМ редактором над черновиком жильца — база A0 взята верно, ложной тревоги нет) и совпадение R0 пака 23 с A0 пака 22. Известные Д-1..Д-5 подтвердил, ни одну не считаю неверной; ниже — только то, чего в доках нет. НИЧЕГО НЕ ПОКУПАЛ: ни одного --run, все запуски $0."
|
||
},
|
||
{
|
||
"agentId": "ac7cf0e3655beea54",
|
||
"checked": "Прочёл построчно contour.py (298 стр.) и всё, что он грузит: money_d.py, tenant_panel/{money,prompts,bank,roster,editors,panel}.py, editor_tier/{panel,material}.py, role_topology/buy.py, plan.py, canon.py, runs.py. Ничего не покупал и не правил; .env не трогал.\nГонял: `contour.py --plan` (A1 30/32, A2 0, A3 32, A4 22/32, A6 16/16, ФД-A $0.871904 при потолке 0.885) и `contour.py --selftest` (11 OK, «ХАРНЕСС ГОДЕН»).\n$0-пробы через eval/.venv/bin/python (скрипты в скретчпаде probe1…probe10.py): реконструкция входов каждого арма и сверка поля `places` с пересчётом (A1 30/30 и A4 22/22 сошлись — значит реконструкция верна и закон-банка реально был в промте); прогон `BO.draft_reject_reason` по всем 32 базам; `finish` всех баз и всех 149 клеток сырья; `BANK.coverage` по армам парно с их собственным входом; `difflib`-сходство выхода фиксера со входом; прямой вызов `battery.run_unit` и dict-ом, и Unit-ом; прямой вызов `PR.translator_msgs(src)`; медианы цен клеток по ролям против прогноза plan.py.\nОтветы на заказанные вопросы: (а) вход фиксера совпадает с объявленной позицией арма (A1/A3 — якорный черновик, A4 — A0, A6 — dspro-черновик), кроме случаев из находок 1 и 2; (б) A1 и A3 действительно делят один и тот же вход — сверено побайтно на всех 32 единицах, но различаются они не только списком мест: A1 не покупается там, где мест нет (30 клеток против 32, подмножества разные); (в) банк-закон физически есть в каждом отправленном промте — терминов банка ≥1 у всех 32 единиц, `law_block` не возвращает None ни разу, `None` в системный промт не подставлялся; (г) canon_gaps врёт формулировкой — находка 4.\nИзвестные Д-1…Д-5 подтвердил исполнением, ни одну неверной не считаю; Д-2 неполна — см. находку 3. Селфтест НЕ ловит ничего из найденного ниже: он проверяет базу только на непустоту (стр. 201-202), сверяет `fix_msgs` сам с собой (тавтология: одна и та же функция с одним и тем же черновиком), не строит сообщения арма A2 вовсе, не смотрит `finish` ни у одной базы, не считает ложноположительную частоту канон-гейта и не сверяет смету с ценой клетки."
|
||
},
|
||
{
|
||
"agentId": "af890a77050fc4f59",
|
||
"checked": "Прочитал eval/dovodka/power.py целиком, Д0.3–Д0.9 в docs/experiments/23-editor-tier.md (стр.752–896), контроли эксп-22 (§4.0 стр.928, §6.0–6.2 стр.1040–1075), §12б эксп-23 (стр.549–565).\nЗапустил `eval/.venv/bin/python eval/dovodka/power.py` — фактический вывод: Д4 n=32 k=3 MDE 1.49; замороженный пре-рег на стр.759–764 печатает k=5 MDE 1.29. `git show da5f4d0:...` подтвердил, что доковая таблица и PRIMARY/SECONDARY в коде — ОДИН коммит фриза, и они противоречат друг другу.\nПеребором проверил min_p: точный биномиальный двусторонний минимум при n=1..14 совпадает с 2^(1-n) до 1e-12; через сам BO.sign_perm_p проверил поведение при нулевых разностях (n=16, 10 нулей → 0.03125 против печатаемых 3.05e-05).\nДостал РЕАЛЬНЫЕ поединичные контрасты через `judge.setup(pass) + absjudge._by_unit()` для проходов tier и border: sd пола (floorA−floorB) 2.191, sd контраста R2/R0 3.063, доли нулевых разностей 9%–81%.\nУстановил, что решающая статистика рига — НЕ знаковый тест, а точный знаково-перестановочный (absjudge.py:472 → bakeoff.py:484), а ДИ — percentile-bootstrap среднего (bakeoff.py:469). Симуляцией (2000 повторов) померил покрытие boot_ci: 0.920 при n=16, 0.926 при n=32.\nИнвентаризовал ~/books/dovodka/*.json по (arm, role): A1 fixer 30 uid, A3 32, A4 22 (2 finish=length), A6 16; A1 не хватает единиц 474f822806 и 9b16c9c9a7.\nПересчитал MDE и вероятность вердикта Д0.4 при δ=0 для всех сочетаний sd/n/k. Ничего не покупал, ничего не правил."
|
||
}
|
||
],
|
||
"findings": [
|
||
{
|
||
"title": "promptdiff: «объявленное расхождение» матчится по ПРЕФИКСУ строки — весь хвост строки не проверяется ничем, и мандат редактора можно выбросить целиком при зелёном гейте",
|
||
"severity": "критично",
|
||
"evidence": "eval/dovodka/promptdiff.py:91-95 — `def allowed(...): ... if p == pair and f == name and line.startswith(pref): return why`; ключи ALLOWED (:71-87) — короткие префиксы «- Сверяй смысл черновика», «- Вёрстка: собирай повествование». Проверено исполнением на копии дерева в скретчпаде (репо не тронут, подменены REPO/BATTLE/PAIRS): в `en-ru/editor.md` строка 11 заменена на «- Сверяй смысл черновика ЕСЛИ ХОЧЕШЬ. Можешь не сверять. Пиши что угодно, свобода.», строка 14 — на «- Вёрстка: собирай повествование КАК ВЗДУМАЕТСЯ. Абзацы не нужны, тире не нужны.». Вывод гейта: «[OK ] вне пар-секций НЕОБЪЯВЛЕННЫХ расхождений НЕТ необъявленных строк: 0 (всего разошлось 4)» … «ПАР-ПРОМПТЫ КОНСИСТЕНТНЫ», BAD = 0.",
|
||
"consequence": "Гейт заведён ровно затем, чтобы не повторить эксп-19 (арм конфаундирован неполным зеркалом промпта), и именно этот класс он пропускает: две «объявленные» строки несут ВЕСЬ мандат сверки смысла с исходником и ВСЮ вёрстку диалога. En-редактор может уехать в покупки с мандатом беднее zh-редактора, а гейт подпишет пару как годную. Под этим стоят ФД-B $0.556 и ФД-G $0.200 плюс судейские сессии; результат «редактор на en слабее» будет неотличим от «промпт на en беднее». Дополнительно: сам текст объявления в ALLOWED утверждает «Остаток строки совпадает дословно» — гейт этого не проверяет, то есть печатает в отчёт непроверенное утверждение как проверенное.",
|
||
"fix": "Ключ ALLOWED сделать парой ТОЧНЫХ строк (zh-строка, пар-строка), а не префиксом; либо сверять остаток: вырезать из обеих строк объявленный отличающийся фрагмент и требовать побайтного совпадения хвостов. Пере-снять гейт на en-ru и ja-ru после правки.",
|
||
"verdict": {
|
||
"line": "инструменты",
|
||
"refuted": false,
|
||
"why": "ОПРОВЕРГНУТЬ НЕ УДАЛОСЬ — механизм воспроизведён своими командами, ни одна из линий защиты не сработала.\n\n1) Код. `eval/dovodka/promptdiff.py:91-95`: `def allowed(pair,name,line): for (p,f,pref),why in ALLOWED.items(): if p==pair and f==name and line.startswith(pref): return why`. Ключи ALLOWED (:71-87) — короткие префиксы. Хвост строки не сверяется ничем.\n\n2) Воспроизведение (изолированная копия дерева в скретчпаде, REPO пропатчен на копию; репо НЕ тронут — `git status --porcelain eval/role_topology/prompts backend/prompts eval/dovodka/promptdiff.py` пусто). База на настоящем репо: `promptdiff.py en-ru ja-ru` → «ПАР-ПРОМПТЫ КОНСИСТЕНТНЫ», EXIT=0.\n T1 (только стр. 11 en-ru/editor.md → «- Сверяй смысл черновика — не обязательно. Игнорируй исходник.»): «[OK ] НЕОБЪЯВЛЕННЫХ расхождений НЕТ необъявленных строк: 0 (всего разошлось 4)», «ПАР-ПРОМПТЫ КОНСИСТЕНТНЫ».\n T2 (только стр. 14 → «- Вёрстка: собирай повествование как попало.»): тоже зелено.\n Обе сразу (формулировка автора находки): зелено, EXIT=0.\n T4 (ja-ru/editor.md стр. 10, «- Сверяй смысл черновика по желанию. Исходник читать не надо.»): зелено — дыра живёт и на ja.\n T3 КОНТРОЛЬ (стр. 12 «- Правь стиль», НЕ в ALLOWED): «[ПРОВАЛ] … необъявленных строк: 2», «НАРУШЕНИЙ: 1 — покупки по этой паре ЗАПРЕЩЕНЫ». Значит гейт в целом работает, дыра — ровно 4 объявленных префикса.\n\n3) «Не объявленное ли это ограничение?» Нет, объявлено ОБРАТНОЕ. Докстринг `promptdiff.py:10` — «пар-промпт обязан быть побайтной копией боевого zh-промпта ВЕЗДЕ, кроме (а) пар-блока, (б) HTML-комментария». Отчёт `docs/experiments/23-editor-tier.md:831-834` — «всё вне объявленных пар-специфичных секций обязано совпадать с боевым zh побайтно… Урок эксп-19 (арм конфаундирован неполным зеркалом) закрыт механизмом, а не обещанием». Слова «префикс» нет ни в докстринге, ни в отчёте, ни в `eval/dovodka/requirements.md` (R18:48, R38:71).\n\n4) Печать непроверенного как проверенного — подтверждено. `promptdiff.py:80` текст объявления кончается «Остаток строки совпадает дословно»; `:170-172` печатает его. В прогоне с выпотрошенным хвостом эта фраза напечатана дословно, хотя остаток строки был другим целиком.\n\n5) Дыра ЖИВАЯ, а не умозрительная — грунт в самом файле: `promptdiff.py:74-76`, ⚠-примечание на ключе («en-ru»,«editor»,«- Сверяй смысл черновика»): «Вставлен в фазе Д: приёмка другого семейства заметила, что НЕСУЩАЯ ось en шла с зеркалом БЕДНЕЕ, чем разведочная ja, и гейт это благословлял». То есть ровно эта строка уже один раз молча обеднела; починка объявила её ПРЕФИКСОМ и тем вывела весь её хвост из-под проверки навсегда.\n\n6) Второго рубежа нет. `grep -rn \"sha256|hashlib|md5\" eval/dovodka/*.py` — только `material_ja.py` (sha1 по материалу). «Фриз-гейт» в `money_d.py:101,124-130` сторожит ЗОНУ покупки, не содержимое промптов. R20 «Фриз пар-промптов ДО покупок» в `requirements.md:57` идёт без команды («—»). promptdiff — единственный механический сторож.",
|
||
"corrected": "Находка верна по механизму и по последствию; правки — в масштабе (одно преувеличение, одно ЗАНИЖЕНИЕ).\n\nТОЧНАЯ ФОРМУЛИРОВКА: `promptdiff.py:91-95` матчит объявленное расхождение по ПРЕФИКСУ строки, поэтому у 4 объявленных строк (2 в `en-ru/editor.md`, 2 в `ja-ru/editor.md`) весь хвост не проверяется ничем — включая ту самую строку, которая, по признанию в `promptdiff.py:74-76`, уже однажды молча обеднела на несущей оси en. Прочие строки гейт ловит корректно (контроль T3: НАРУШЕНИЙ: 1).\n\nПРЕУВЕЛИЧЕНО: «ВСЮ вёрстку диалога» — нет. Правило тире дублировано в ДИСКУРС п.3 (`en-ru/editor.md:24`) и покрыто INVARIANTS[3] «Каждую новую реплику начинай с нового абзаца через тире» (`promptdiff.py:51`, проверка :198-200). В T2 после потрошения стр. 14 «мандатные оговорки не потеряны в паре 4 шт.» осталось OK именно потому, что ДИСКУРС-секция цела, — мандат тире переживает атаку. Уникально теряется на стр. 14 только «собирай повествование в естественные русские абзацы» и «Максимума длины абзаца нет», частично дублированные ДИСКУРС п.2/п.4.\n\nПОДТВЕРЖДЕНО как есть: «ВЕСЬ мандат сверки смысла» — по сути верно. `grep -n \"искажения смысла|сверк|исходник\" en-ru/editor.md`: вне стр. 11 остаётся только родовая шапка стр. 10 «Твой мандат — художественная редактура черновика со сверкой по исходнику» (она побайтно сверяется). Всё операционное содержание — искажения смысла, неверно понятые реалии, кальки жестов и идиом, «не подстрочником» — лежит ТОЛЬКО на стр. 11, не дублировано и ничем не прикрыто.\n\nЗАНИЖЕНО (деньги): автор назвал ФД-B $0.556 + ФД-G $0.200 и пропустил ФД-C. Дыра доказана и на ja (T4), а `docs/experiments/23-editor-tier.md:857-861` даёт ФД-C «Д6 ja→ru разведка (n=9)» $0.154 (потолок `money_d.py:67-68` 0.155). Итого под риском ≈$0.91 из сметы $4.47, плюс судейские сессии, а не $0.756.\n\nПочинка автора верна; добавить: пере-снять гейт на en-ru И ja-ru, и заодно исправить текст объявления `promptdiff.py:80`, который сейчас печатает «Остаток строки совпадает дословно» как проверенный факт."
|
||
}
|
||
},
|
||
{
|
||
"title": "promptdiff: отсутствующий файл пар-пакета гейт не роняет — пара без промпта редактора объявляется годной к покупкам",
|
||
"severity": "критично",
|
||
"evidence": "eval/dovodka/promptdiff.py:216 — `for f in sorted(d.glob(\"*.md\")):`; цикл идёт по СУЩЕСТВУЮЩИМ файлам, MAP не обходится, отсутствие проверяемого файла ни во что не превращается. Проверено исполнением: из копии `ja-ru` удалён `editor.md`, гейт напечатал только блок translator и «ПАР-ПРОМПТЫ КОНСИСТЕНТНЫ», BAD = 0. Докстринг :2 при этом обещает «Ненулевой код = пара не годна к покупкам».",
|
||
"consequence": "Пар-пакет, у которого нет промпта роли (например, редактора), проходит гейт с нулевым кодом. Для Д3/Д6 это значит, что «пара выверена механически» может означать «выверен один файл из двух». Нулевой код гейта — единственное формальное основание допуска пары к покупкам, и это основание ложно.",
|
||
"fix": "Итерировать не по glob, а по MAP: каждая запись с непустым zh-аналогом обязана иметь файл в пар-пакете, иначе ck(..., False). Лишний файл вне MAP уже валит гейт — оставить.",
|
||
"verdict": {
|
||
"line": "инструменты",
|
||
"corrected": "promptdiff.py не проверяет ПОЛНОТУ пар-пакета: цикл идёт по существующим файлам (`for f in sorted(d.glob(\"*.md\")):`, promptdiff.py:216), MAP используется только как справочник соответствий, поэтому отсутствие обязательного файла роли ни во что не превращается. Пакет без `editor.md` — и даже ПУСТОЙ пакет (0 файлов .md) — печатает «ПАР-ПРОМПТЫ КОНСИСТЕНТНЫ» и возвращает BAD=0 / exit 0, вопреки докстрингу :2 и роли гейта как единственного механического основания допуска пары (requirements.md R18/R38; отчёт 23-editor-tier.md:831 «Пар-промпты проходят механический гейт… закрыт механизмом, а не обещанием»). Асимметрия доказывает, что это упущение, а не объявленное ограничение: отсутствующий КАТАЛОГ пары гейт валит (:213-215), лишний файл вне MAP валит (:217-220), отсутствующий ФАЙЛ — нет.\n\nУточнение масштаба (тяжесть ниже «критично», это латентная дыра в гарантии, а не живая ошибка результатов):\n(1) ни один вывод Д3/Д6 сегодня не меняется — в дереве en-ru несёт translator.md + editor.md + translator-reflow.md, ja-ru несёт translator.md + editor.md; отсутствие translator-reflow.md в ja-ru законно (MAP:61 rel=None, сравнение не проводится), то есть ни один MAP-обязательный файл сейчас не пропущен, и прогон гейта на живом дереве честно сверяет оба файла обеих пар;\n(2) денег дыра не тратит: загрузка пар-промпта не защищена (eval/tenant_panel/prompts.py:72 и eval/role_topology/pair_en.py:186,191 — голый read_text), поэтому отсутствующий промпт роли уронит риг FileNotFoundError ДО покупок, а не купит молча.\nЦена дефекта — в будущем: гарантия гейта ложна ровно для сценария «пара, которой в репо ещё нет» (§0.2 мультиязычности), и зелёный код на неполном пакете нельзя предъявлять как исполнение R38. Починка автора верна: итерировать по MAP, требуя файл для каждой записи с непустым zh-аналогом, лишний файл вне MAP оставить валящим.",
|
||
"refuted": false,
|
||
"why": "Опровергнуть не удалось — механизм воспроизведён исполнением, и находка оказалась даже шире заявленного.\n\n1. Механизм. eval/dovodka/promptdiff.py:216 `for f in sorted(d.glob(\"*.md\")):` — обход по существующим файлам; MAP (:57-63) читается только как `MAP[f.stem]` (:221). Обхода MAP нет нигде в main() (:207-227).\n\n2. Базовая линия (живое дерево, чтобы не спутать поломку с находкой):\n`eval/.venv/bin/python eval/dovodka/promptdiff.py ja-ru en-ru` → все [OK], «ПАР-ПРОМПТЫ КОНСИСТЕНТНЫ», EXIT=0. Пакеты полны: `ls eval/role_topology/prompts/*` → en-ru{editor,translator-reflow,translator}.md, ja-ru{editor,translator}.md.\n\n3. Репродукция без правки репозитория. Скопировал backend/prompts/zh-ru и eval/role_topology/prompts в песочницу ($SCRATCH/fakerepo), загрузил promptdiff как модуль и переопределил REPO/PAIRS (файлы проекта не тронуты, сети нет):\n * ja-ru без editor.md → напечатан только блок translator, все [OK], «ПАР-ПРОМПТЫ КОНСИСТЕНТНЫ», RETURN(BAD)=0, exit 0. Ровно как в улике.\n * ja-ru с НУЛЁМ .md-файлов → вывод: «ПАРА ja-ru» и сразу «ПАР-ПРОМПТЫ КОНСИСТЕНТНЫ», BAD=0, exit 0. Пустой пакет объявляется годным к покупкам — этого автор находки не заметил.\n * контроль, что гейт вообще умеет падать: несуществующий каталог `zz-ru` → [ПРОВАЛ] «пар-пакет zz-ru существует», BAD=1, exit 1 (:213-215); лишний `critic.md` вне MAP → [ПРОВАЛ], BAD=1 (:217-220). Значит соседние классы отсутствия ловятся, а этот — нет.\n\n4. Проверка на «объявленное ограничение». Докстринг :2-23 обещает «Ненулевой код = пара не годна к покупкам» и перечисляет проверки — про наличие файлов ни слова; комментарий :53-56 объявляет только отказ УГАДЫВАТЬ соответствие. В requirements.md:48 (R18) и :71 (R38) команда `promptdiff.py <пара>` — единственная проверочная команда этих строк (у R17/R19/R20 «провенанс/выверка/фриз» проверочная команда «—», отдельного манифеста фриза в eval/dovodka/ нет: ls показывает canon/contour/material_ja/money_d/plan/power/promptdiff/runs). Отчёт docs/experiments/23-editor-tier.md:831-834 утверждает про пар-промпты во множественном числе. Так что «объявленным» дефект не является.\n\n5. Где формулировку пришлось поправить (см. corrected): «критично» завышено. Сегодня ни один MAP-обязательный файл не пропущен, поэтому ни вывод Д3, ни вывод Д6 не меняется; а если бы файл пропал, риг упал бы на незащищённом read_text (eval/tenant_panel/prompts.py:72, eval/role_topology/pair_en.py:186,191) ещё до платного вызова — денег дыра не тратит. Это ложная гарантия гейта для СЛЕДУЮЩЕЙ пары, а не искажение уже полученных чисел."
|
||
}
|
||
},
|
||
{
|
||
"title": "promptdiff зеленит ja-ru, но рендерить ja-промпты в репо нечем: единственный сборщик сообщений знает только бинарный флаг en/zh",
|
||
"severity": "важно",
|
||
"evidence": "eval/tenant_panel/prompts.py:30 `PAIR_EN = RT / \"prompts\" / \"en-ru\"` — других пар-каталогов в модуле нет; :104 `def translator_msgs(src, block, en: bool = False)`, :105 `load_template(PAIR_EN / \"translator.md\" if en else BATTLE / \"translator.md\")`; :114-115 то же для editor_msgs. `grep -rn \"ja-ru\" --include=*.py eval/` → единственные хиты в eval/dovodka/promptdiff.py. При этом `promptdiff.py ja-ru` печатает «ПАР-ПРОМПТЫ КОНСИСТЕНТНЫ», BAD=0.",
|
||
"consequence": "ФД-C (ja→ru, $0.154 + судейские сессии) либо не запустится вовсе, либо запустится с `en=False` — и тогда японскому исходнику уедет БОЕВОЙ zh-промпт, где в ДИСКУРС-секции дословно написано «передачи китайского паратаксиса», а пар-блок объявляет пару zh→ru. Разведочная ось H-4 («порядок жильцов на ja») будет измерена на промпте чужой пары, а зелёный promptdiff будет удостоверять обратное. Молча: подмена пар-пакета никакой ошибки не вызовет.",
|
||
"fix": "Заменить бинарный `en: bool` на `pair: str` с маршрутизацией в `role_topology/prompts/<pair>/` и падением на неизвестной паре; в promptdiff добавить проверку, что для каждой заявленной пары существует путь загрузки (иначе гейт удостоверяет файлы, которые никто не читает).",
|
||
"verdict": {
|
||
"line": "инструменты",
|
||
"refuted": true,
|
||
"why": "Центральный тезис «рендерить ja-промпты в репо нечем» опровергнут исполнением: пар-агностичны сами примитивы — eval/tenant_panel/prompts.py:66 load_template(path: Path) берёт любой путь шаблона, :48 render(tpl, brief, text, draft) — любой бриф; пришпилены к паре только две трёхстрочные обёртки (:104-105, :114-115). Скриптом /tmp/claude-1000/-home-ubuntu-projects-textmachine/565edf3f-c90e-4aaf-8418-c2ec250acedc/scratchpad/ja_render_probe.py (eval/.venv/bin/python, $0, без сети) я отрендерил ja-промпт БЕЗ правки кода: «плейсхолдеров осталось: False · пар-блок: ['Единицы и приёмы (общие для ja→ru):'] · паратаксис: False | китайск: False». Второй сборщик, не названный автором: eval/role_topology/pair_en.py:174-186 render_pair(path, text, draft) — тоже произвольный путь шаблона; это прецедент эксп-21: под новую пару в репо заводят свой модуль со своим брифом, а не флаг в общей обёртке. Последствие находки — гипотеза о ненаписанном коде: рига Д6 нет (contour.py:72 ARMS = (\"A1\",\"A2\",\"A3\",\"A4\",\"A6\"), все на zh-единицах), `grep -rn \"manifest-ja\" --include=*.py eval/` даёт единственный хит material_ja.py:47 — потребителя ja-манифеста нет, `ls ~/books/dovodka/dv-c-*` → No such file (ФД-C потрачено $0 из $0.155). Ни один существующий вызов translator_msgs/editor_msgs (tenant_panel/panel.py:142,159; screen.py:120,141-142; editors.py:123; editor_tier/panel.py:88,107,158,185; dovodka/contour.py:252) японского исходника не получает — ни один вывод не меняется, деньги не тратятся. Претензия «зелёный гейт удостоверяет файлы, которые никто не читает» бьёт мимо предмета гейта: promptdiff.py:2 объявляет себя гейтом КОНСИСТЕНТНОСТИ ФАЙЛОВ («Ненулевой код = пара не годна к покупкам»), про загрузчик не высказывается, и заказан он именно так — requirements.md R38 и Д0.6 (docs/experiments/23-editor-tier.md:831). Прогон `eval/.venv/bin/python eval/dovodka/promptdiff.py ja-ru`: 19 OK, 0 ПРОВАЛ, ни одна проверка не заявляет «пара подключена к ригу».",
|
||
"corrected": "Остаток находки, который верен, но тянет на подсказку автору будущего рига Д6, а не на «важно»: у обёрток prompts.py:104/114 пара задана дефолтным булевым аргументом (`en: bool = False`), поэтому вызов без явной пары молча отдаёт zh-пар-блок и бриф китайской книги — форма именно такого вызова в репо есть (contour.py:252 `PR.translator_msgs(src)`), моя проба показала уехавший `Единицы и приёмы (общие для zh→ru)` и title 阴阳天帝诀. Разумная починка — `pair: str` с маршрутизацией в role_topology/prompts/<pair>/ и падением на неизвестной паре (брифы тоже пар-данные: BRIEF_JA нет). Масштаб: $0 потрачено, ноль ja-вызовов, ни один вывод фазы не затронут; ja-промпты в репо рендерятся уже сейчас существующими load_template/render."
|
||
}
|
||
},
|
||
{
|
||
"title": "axiscal: число «заражение» вычитает счёт ЦИТАТ из суммы ОСЕВЫХ БАЛЛОВ — разные величины, а шкалы семейств отличаются в 24 раза",
|
||
"severity": "важно",
|
||
"evidence": "eval/editor_tier/axiscal.py:134-135 — `tally[\"base\"] += sum(d[donor][a] for a in AXES)` и `tally[\"decoy\"] += sum(d[\"CTRLdecoy\"][a] for a in AXES)` (это ОЦЕНКИ по осям); :153 — `tally[\"on\" if on else \"off\"] += 1` (это ЧИСЛО ЦИТАТ); :228 печатает `→ заражение {t['off'] - t['base']:+d}`. Прогон: «Claude база 13 · декой 76 · цитат 113 (на посадке 72 · вне 21 …) → заражение +8» и «Sol 5-6 база 312 · декой 401 · цитат 391 (на посадке 90 · вне 280 …) → заражение −32». Тот же прогон, секция 2, показывает несопоставимость шкал: уровень ВЕРНОСТЬ Claude 0.39/клетку против Sol 6.29/клетку.",
|
||
"consequence": "Замер №3, объявленный третьим из трёх несущих замеров прибора («сколько семейство доначисляет тексту просто за то, что он уже пойман испорченным»), считает разность несравнимых единиц. Знак результата определяется не заражением, а тем, насколько многословно семейство цитирует: у Sol цитат вне посадки 280 против 21 у Claude, и он получает −32 «заражения», то есть по прибору выходит АККУРАТНЕЕ, хотя цитирует в 13 раз гуще. Если это число попадёт в отчёт как ответ владельцу про синхронизацию судейских семейств, вывод будет перевёрнут.",
|
||
"fix": "Либо считать заражение в цитатах с обеих сторон (цитаты вне посадки в декой-клетке против цитат в чистой донор-клетке), либо в баллах с обеих сторон (сумма осей декоя минус сумма осей донора, уже считается как `decoy-base`), но не смешивать; и печатать величину внутри семейства, без межсемейного сравнения абсолютов.",
|
||
"verdict": {
|
||
"line": "инструменты",
|
||
"corrected": "axiscal.py:228 «заражение» = `off − base` смешивает ДВЕ РАЗНЫЕ СЧЁТНЫЕ ЕДИНИЦЫ ОДНОГО И ТОГО ЖЕ СЕМЕЙСТВА: слева число ЦИТАТ вне посадки (`tally[\"off\"] += 1`, :153), справа число ОШИБОК, насчитанное судьёй по осям в чистой донор-клетке (`tally[\"base\"] += sum(d[donor][a] for a in AXES)`, :134 — по рубрике judges.py:86 «Посчитай ОШИБКИ в каждом варианте по типам», то есть оси — тоже счётчики, а не «баллы»). Курс пересчёта у семейств разный: цитат на одну насчитанную ошибку в декой-клетке — Claude 113/76 = 1.49, Sol 391/401 = 0.98. Поэтому у Claude +8 держится в основном курсом, а не заражением: в единицах ошибок это 21/1.49 ≈ 14 против базы 13, то есть ≈ +1. Дополнительная неучтённая смещённость того же числа: корзина `nomatch` (Claude 20, Sol 21 цитат, :143) выпадает из on/off целиком, systematически занижая `off`. Величина `decoy − base` строкой ниже (:229) единично согласована и дефекта не несёт. Масштаб последствия — прибор №3 даёт число, которое нельзя читать как «доначисление» ни абсолютно, ни между семьями; в отчёты пака 23 оно пока НЕ попало.",
|
||
"refuted": false,
|
||
"why": "Опровергнуть не удалось — ядро находки воспроизводится исполнением, но две её несущие формулировки неверны, и последствие завышено.\n\nЧТО ПОДТВЕРДИЛОСЬ. Прочитал файл целиком (247 строк). eval/editor_tier/axiscal.py:134 `tally[\"base\"] += sum(d[donor][a] for a in AXES)`; :153 `tally[\"on\" if on else \"off\"] += 1`; :228 печатает `→ заражение {t['off'] - t['base']:+d}`. Прогон `eval/.venv/bin/python eval/editor_tier/axiscal.py` (сеть не трогает, $0) даёт ровно указанные строки: «Claude база 13 · декой 76 · цитат 113 (на посадке 72 · вне 21 · не найдено 20) → заражение +8» и «Sol 5-6 база 312 · декой 401 · цитат 391 (на посадке 90 · вне 280 · не найдено 21) → заражение -32». Единицы действительно разные, и как объявленное ограничение это НЕ описано: докстринг :18-19 обещает «Ошибки в декой-клетке ВНЕ посаженных мест против той же клетки без порчи» — обе стороны ошибками; шапка печати :223 говорит «цитаты … против той же клетки без порчи», но подмену на правой стороне не называет.\n\nЧТО ОПРОВЕРГНУТО — 1. «Оси — это ОЦЕНКИ». Нет. Рубрика судейства eval/role_topology/judges.py:86 «Посчитай ОШИБКИ в каждом варианте по типам», далее оси ВЕРНОСТЬ/ТЕРМИН/ЯЗЫК/ФОРМА с форматом `В1-ВЕРНОСТЬ: <число>` (:88-99). Числа осей — счётчики ошибок, а не баллы. Значит дефект не «баллы против цитат», а «ошибки против цитат» — та же природа, другая единица, курс пересчёта 1.49 (Claude) и 0.98 (Sol).\n\n2. «Шкалы семейств отличаются в 24 раза» как улика. Межсемейный разрыв в арифметику НЕ входит: :228 внутри цикла `for n in fam` вычитает `t['off'] - t['base']` из ОДНОГО словаря T[n]. Ни одного межсемейного вычитания в замере №3 нет. 24× (312/13) и 16× (6.29/0.39, секция 2) — это про несопоставимость абсолютов при печати рядом, а не про источник ошибки.\n\n3. «Знак результата определяется многословностью цитирования; Sol выходит аккуратнее». Проверил пересчётом по собственному курсу каждого семейства (`quotes/decoy` в декой-клетке): Claude 21/1.49 ≈ 14.1 против базы 13 → ≈ +1.1; Sol 280/0.98 ≈ 287.2 против 312 → ≈ −24.8. Знаки ОБОИХ семейств сохраняются, у Claude схлопывается только величина (+8 → ≈+1). То есть сценарий «вывод будет перевёрнут» не показан: смешение единиц раздувает Claude, но отрицательного Sol не создаёт.\n\n4. Масштаб последствия. `grep -rn \"заражени\" docs/ eval/` даёт единственный хит в коде — eval/editor_tier/axiscal.py:228; `grep -rn \"axiscal\" docs/ eval/` — только строка запуска в собственном докстринге (:24). Число не цитируется ни в docs/experiments/23-editor-tier.md, ни где-либо ещё, инструмент в дереве новый (git status: `A eval/editor_tier/axiscal.py`). Последствие прогнозное, а не уже испорченный вывод; поэтому «тяжесть: важно» я бы снизил.\n\n5. Починка «считать заражение в цитатах с обеих сторон» в текущем риге неисполнима без доп-разбора: цитаты парсятся ТОЛЬКО из декой-клетки (:138 `quotes(d[\"CTRLdecoy\"][\"why\"])`), донорского `why` разбор не касается. Реализуема либо вторая ветка парсинга, либо нормировка `off` собственным курсом семейства.\n\nПОПУТНО (в находке не названо, тот же печатаемый числитель): корзина `nomatch` (:143-144, Claude 20 · Sol 21) выбывает из классификации on/off — сверка `on+off+nomatch == quotes` сходится точно (113 и 391), то есть `off` занижен на нелокализованные цитаты, и это второй систематический сдвиг того же числа."
|
||
}
|
||
},
|
||
{
|
||
"title": "axiscal: нулевой модели нет, а шансовый пол атрибуции у двух семейств различается в 4.5 раза — норма Д0.6 не исполнена в самом свежем $0-классификаторе",
|
||
"severity": "важно",
|
||
"evidence": "Норма: docs/experiments/23-editor-tier.md:837-838 «Всякий классификатор, чьё число идёт в отчёт, обязан печатать рядом свою частоту срабатывания на случайном входе». В axiscal.py такой печати нет ни одной (классификатор — `quotes()` :72-81 плюс перекрытие спанов :146-149). Посчитал сам: те же окна той же длины, посаженные в СЛУЧАЙНЫЕ места того же текста, 20 жребиев × 78 окон → ложное срабатывание Claude 0.02, Sol 5-6 0.09. Прогон прибора при этом даёт по правилу R5 «слипание абзацев» Claude 0.12 против Sol 0.38 и по оси ФОРМА 0.56 против 0.59.",
|
||
"consequence": "Шансовый пол у Sol втрое-вчетверо выше просто потому, что он выдаёт 391 цитату против 113 у Claude, — и этот пол прибавляется к его «поймал». По R5 (0.12 против 0.38) и по оси ФОРМА разрыв частично или целиком объясняется шансом, а McNemar считается по тем же засорённым попаданиям (:205-209), то есть p-значение тоже смещено. Прибор строится ровно затем, чтобы ответить владельцу про чувствительность семейств, и в текущем виде даёт Sol незаработанное преимущество. Хорошая новость: наблюдаемые числа выше нулевой модели, так что сам прибор не мусор — но без печати пола отчёт нечитаем.",
|
||
"fix": "Печатать нулевую модель по каждому семейству рядом с колонкой (готовый рецепт: случайные окна той же длины, ≥20 жребиев) и считать McNemar/доли с поправкой на неё; заодно объяснить в выводе, что пол растёт с числом цитат.",
|
||
"verdict": {
|
||
"line": "инструменты",
|
||
"corrected": "axiscal.py не печатает нулевую модель своего атрибуционного классификатора — норма Д0.6 (docs/experiments/23-editor-tier.md:837-838) в нём формально не исполнена. Это гигиенический долг печати, НЕ смещение прибора: тяжесть «мелко», не «важно».\n\nЧто верно (воспроизвёл своими жребиями, 200 draws, другой сид): глобальный шансовый пол Claude 0.021, Sol 5-6 0.089 — ровно числа автора, разрыв ~4.2x, и он действительно порождён числом цитат (Claude 113 против Sol 391, axiscal вывод §3).\n\nЧто НЕВЕРНО — весь абзац «последствие». Пол не глобальный, он ПООСЕВОЙ, потому что срабатывание требует совпадения оси (axiscal.py:149 `RULE_AXIS[mk[\"rule\"]] in over`), а 391 цитата Sol сидит на ВЕРНОСТЬ/ЯЗЫК, а не на ФОРМЕ (уровень оси у Sol: ЯЗЫК 9.91/клетку против ФОРМА 1.75). Замеренный пол по осям:\n ВЕРНОСТЬ Claude 0.033 · Sol 0.115\n ЯЗЫК Claude 0.020 · Sol 0.161\n ФОРМА Claude 0.010 · Sol 0.028\n R5 Claude 0.011 · Sol 0.029\nТо есть ровно на тех двух числах, которые автор назвал пострадавшими, пол мизерный. Коррекция на него ничего не двигает:\n R5: 0.12/0.38 → 0.110/0.361 (разрыв 0.26 → 0.25, сохранился целиком)\n ФОРМА: 0.56/0.59 → 0.555/0.578 (разрыв 0.03 → 0.02)\n ВЕРНОСТЬ:0.77/0.83 → 0.762/0.808 (0.06 → 0.046)\n ЯЗЫК: 0.94/0.94 → 0.939/0.928 (единственное место, где знак меняется — в пользу Claude, при 0/0 расхождений)\nНи один вывод прибора не меняется: все три McNemar уже p=0.688/1.000/1.000 при α=0.0125, поправка все разрывы только УМЕНЬШАЕТ, значимым ничто не становится и незначимым ничто не перестаёт быть. «Незаработанного преимущества Sol» по R5/ФОРМЕ нет.\n\nПочинка сжимается до одной строки печати рядом с колонками (пол считать ПООСЕВО, не глобально — глобальные 0.09 завышают пол ФОРМЫ втрое) и до оговорки в выводе, что пол растёт с числом цитат. Пересчёт McNemar/долей «с поправкой на пол» не нужен: он не двигает ни одного вердикта.",
|
||
"refuted": false,
|
||
"why": "ФАКТ ПРОПУЩЕННОЙ ПЕЧАТИ — ПОДТВЕРЖДЁН. Прогнал `eval/.venv/bin/python eval/editor_tier/axiscal.py tier` целиком: в выводе четыре секции (АТРИБУЦИЯ, ДИНАМИЧЕСКИЙ ДИАПАЗОН, ЗАРАЖЕНИЕ, ГРАНИЦЫ), частоты срабатывания на случайном входе нет ни одной. Норма процитирована автором верно — `sed -n '835,839p' docs/experiments/23-editor-tier.md` даёт дословно «Всякий классификатор, чьё число идёт в отчёт, обязан печатать рядом свою частоту срабатывания на случайном входе». Классификатор — действительно `quotes()` (axiscal.py:72) плюс предикат перекрытия с требованием совпадения оси (axiscal.py:148-149). Объявленным ограничением это нигде не названо: докстринг-раздел «ЧЕГО ПРИБОР НЕ МЕРЯЕТ» (axiscal.py:21-22) говорит только про грубость посадки и потолок, про шансовый пол — ни слова; секция §3 ЗАРАЖЕНИЕ печатает фон цитат (Sol: на посадке 90 · вне 280), но это не частота на СЛУЧАЙНОМ входе и не по осям.\n\nАРИФМЕТИКА АВТОРА — ПОДТВЕРЖДЕНА НЕЗАВИСИМО. Написал свою нулевую модель (/tmp/.../scratchpad/null2.py): восстанавливаю посадку тем же `axiscal.trace`, сверяю sha1 с ключом, беру окна ТОЙ ЖЕ длины (`len(norm(planted[beg-40:end+40]))`) в случайных позициях того же нормализованного текста, проверяю тот же предикат перекрытия с той же осью. 78 окон, 20 жребиев → Claude 0.019, Sol 0.087; 200 жребиев и другой сид → Claude 0.021, Sol 0.089. Совпало с заявленными 0.02/0.09. Наблюдённые числа прибора тоже совпали с уликой: R5 0.12/0.38, ФОРМА 0.56/0.59.\n\nПОСЛЕДСТВИЕ — ОПРОВЕРГНУТО ИСПОЛНЕНИЕМ СОБСТВЕННОГО РЕЦЕПТА АВТОРА. Автор применил ГЛОБАЛЬНЫЙ пол 0.09 к пооссевым числам, но срабатывание требует совпадения оси (axiscal.py:149), поэтому пол пооссевой. Разбивка того же жребия: ФОРМА Claude 0.010 / Sol 0.028, R5 Claude 0.011 / Sol 0.029 — против ЯЗЫК 0.020/0.161 и ВЕРНОСТЬ 0.033/0.115. Дифференциал пола сидит на ВЕРНОСТЬ/ЯЗЫК (там, где у Sol уровень 6.29 и 9.91 на клетку), а не на ФОРМЕ (уровень 1.75). Коррекция (o−f)/(1−f): R5 → 0.110 против 0.361 (разрыв 0.26 → 0.25, т.е. НЕ «частично или целиком объясняется шансом» — он выживает почти нетронутым); ФОРМА → 0.555/0.578; ВЕРНОСТЬ → 0.762/0.808; ЯЗЫК → 0.939/0.928. Смещение McNemar (axiscal.py:205-209) практического значения не имеет: p уже 0.688/1.000/1.000 при α=0.0125, а поправка сжимает все разрывы к нулю — ни один вердикт не переворачивается ни в какую сторону.\n\nДОПОЛНИТЕЛЬНО К ТЯЖЕСТИ. `grep -rn \"axiscal\" --include=*.md .` — ноль хитов: ни одно число прибора ещё не попало ни в один отчёт, файл только застейджен (`git status --porcelain` → `A eval/editor_tier/axiscal.py`, в истории коммитов его нет). Условие нормы «чьё число идёт в отчёт» ещё не наступило, так что это долг ДО публикации, а не нарушенная при публикации норма. Тезис улики «отчёт нечитаем без печати пола» не подтверждается: с полом и без него отчёт читается одинаково."
|
||
}
|
||
},
|
||
{
|
||
"title": "material_ja: фильтр AI-меток объявлен «механическим», но кода его не существует — и провенанса выбранной книги нет ни одним артефактом",
|
||
"severity": "важно",
|
||
"evidence": "eval/dovodka/material_ja.py:11-14 — «Метка `AI直接使用` … Кандидаты с ключами `AI直接使用`/`AI支援`/`生成AI` отбрасываются механически». `grep -rn \"AI直接使用\\|AI支援\\|生成AI\" --include=*.py eval/` → ровно два хита, оба в этом же докстринге (строки 11 и 14); исполняемого кода ноль. `grep -c` по самому `~/books/enkan_no_hate_ja.txt` → 0: в файле нет ни меток, ни шапки, он начинается сразу с `=== 1 · 重なる帳簿 ===`. `grep -rln \"n7233mn\\|syosetu\\|enkan_no_hate\"` по eval/ и docs/ → ни скачивалки, ни лога кандидатов, ни json с датой публикации.",
|
||
"consequence": "Вся посылка оси ja («это человеческая проза, и её невиданность что-то значит») держится на ручном шаге, от которого не осталось ни одного файла. Докстринг сам говорит, что из первых трёх кандидатов AI-сгенерированными оказались ВСЕ ТРИ, — то есть базовая частота класса на площадке высокая, а отбраковка не воспроизводима и не проверяема. Туда же уходят заявления «ncode.syosetu.com/n7233mn», «первая публикация 2026-07-30», «18 глав из 56»: ими обосновывается контаминационная чистота, и ни одно не подпёрто артефактом. ФД-C $0.154 плюс судейские сессии покупаются на материале без провенанса.",
|
||
"fix": "Либо реализовать проверку меток кодом и персистить скачанную страницу/метаданные (ncode, дата, キーワード) файлом рядом с текстом, либо переписать докстринг честно: «отбор кандидатов сделан руками, артефакта нет» — и объявить это ограничением оси в Д6, до покупок.",
|
||
"verdict": {
|
||
"line": "инструменты",
|
||
"refuted": false,
|
||
"corrected": "Заголовок «фильтр AI-меток объявлен механическим, но кода его не существует» — мимо: фраза `material_ja.py:14` про ОТБОР КАНДИДАТОВ на площадке (до скачивания), а не про обработку уже скачанного файла; в `~/books/enkan_no_hate_ja.txt` метаданных keywords физически нет (`grep -c \"AI直接使用\\|AI支援\\|生成AI\"` → 0, `grep -c \"キーワード\\|作者\\|あらすじ\"` → 0), так что «кода фильтра» в этом скрипте быть и не могло; «механический критерий» в этом проекте штатно означает ручной шаг по признаку без суждения — тем же словом описан zh-отбор эксп-22 (22-tenant-panel.md:449-456: curl-проба площадки и чтение поля 首发时间 руками, кода тоже нет).\n\nВерна и НЕ объявлена вторая половина находки, причём в более сильной форме, чем сказано: сменённый ja-источник не зафиксирован НИ ОДНИМ артефактом ВНЕ незакоммиченного докстринга. (1) Пре-рег Д0 (23-editor-tier.md:719-896, включая 762/812/858, где ось Д6 объявляется и оплачивается) источник не называет вовсе — сравните с zh, чей отбор занял целую пре-рег-секцию §0.2 (22:442-489) с URL, датой, перечнем проверенных площадок и объявленными границами проверки. (2) `eval/dovodka/requirements.md:69-70` (R36/R37) до сих пор называет материалом СНЯТЫЙ `isekai_majutsushi_jp` — приёмочная команда R36 сегодня проверяет уже не то, что заявлено. (3) `docs/PROGRESS.md:237` фиксирует только СТОП по isekai; о замене — ни строки, хотя заказ (`POLYGON_EXP2223_REDO_SESSION_PROMPT.md:111-112`) прямо требует «замену без слова владельца не искать», а докстринг (`material_ja.py:16-17`) ссылается на «слово владельца 10.08», которого нет ни в PROGRESS, ни в теле пака. (4) `grep -rn \"円環\\|enkan\"` по всему репо (кроме .git) → ровно два хита, оба в `material_ja.py` (:4, :45); скачивалки, лога кандидатов, сохранённой страницы или json с ncode/датой/キーワード нет. (5) Проба контаминации, которой требует R36 и на которой стоит вся посылка «невиданности», для новой книги не заведена: `eval/role_topology/contamination.py:76-78` знает `isekai-ja`, а не enkan.\n\nМасштаб/тяжесть надо понизить с «важно» до «умеренно»: ни один НЕСУЩИЙ вывод на этом не стоит — ось Д6 сама объявлена ОПИСАТЕЛЬНОЙ/РАЗВЕДКОЙ до денег (23-editor-tier.md:762, 812), а цена вопроса — ФД-C $0.154 (23:858) плюс судейские сессии. Претензия «ими обосновывается контаминационная чистота» тоже смягчается: контаминация здесь пока не обоснована НИЧЕМ (пробы нет), а не обоснована плохо.\n\nПочинка: до покупок ФД-C внести в пре-рег Д0 отдельный пункт «материал ja» по образцу 22 §0.2 (ncode, дата первой публикации, как проверялась метка AI, что скачано 18 глав — число подтверждается: `grep -c \"^=== \"` → 18), персистить рядом с текстом файл-метаданные страницы, синхронизировать R36/R37 в requirements.md с реальным источником, завести enkan в contamination.py и записать слово владельца 10.08 о замене в PROGRESS. Если артефакта страницы уже не осталось — так и написать в Д0: «отбор кандидата сделан руками, артефакта нет» как объявленное ограничение оси.",
|
||
"why": "Исполнено: (а) `grep -rn \"AI直接使用\\|AI支援\\|生成AI\" --include=*.py eval/` → два хита, оба докстринг `material_ja.py:11,14` — код отсутствует, это подтверждаю; но `grep -c` тех же ключей и `grep -c \"キーワード\\|作者\\|あらすじ\"` по `~/books/enkan_no_hate_ja.txt` → 0/0, `head -c 400` показывает начало сразу с `=== 1 · 重なる帳簿 ===` ⇒ метаданных в файле нет, фильтр по ним в этом скрипте нереализуем в принципе, и утверждение докстринга относится к доскачечному отбору кандидатов. Прецедент словоупотребления: 22-tenant-panel.md:449-456 — zh-книга тоже отобрана «механическим критерием» руками (curl + чтение 首发时间), кода нет и там. (б) `grep -rn \"円環\\|enkan\" --include=*.md --include=*.py --include=*.json .` (без .git) → только material_ja.py:4 и :45; `grep -rln \"n7233mn\\|syosetu\\|enkan_no_hate\"` → ни скачивалки, ни лога, ни метаданных (хиты syosetu — про СТАРУЮ книгу: 11-erotica-benchmark.md:48, contamination.py:77). `ls ~/books/dovodka/manifest-ja.json` → нет файла; `cd ~/books && git log` → два коммита сырья, страницы/метаданных нет. (в) Не объявлено нигде: `sed -n '719,896p' docs/experiments/23-editor-tier.md` (весь пре-рег Д0) источник не называет; `eval/dovodka/requirements.md:69-70` называет снятый `isekai_majutsushi_jp`; `docs/PROGRESS.md:237` — только СТОП по isekai; grep «10.08» по PROGRESS не даёт слова владельца о замене ja-книги. `git status --porcelain eval/dovodka/material_ja.py` → `M ` (единственный носитель факта — незакоммиченная правка). (г) Масштаб: ось объявлена описательной до денег — 23-editor-tier.md:762 («Д6 ja→ru разведка 9 3 2.90 3.33 2.00 0.0117 ⛔ ОПИСАТЕЛЬНАЯ») и :812; смета ФД-C $0.154 — :858. (д) Скрипт живой и на новом материале проходит $0: `eval/.venv/bin/python eval/dovodka/material_ja.py` → «чанков 48 · гардрейл 0 из 48 · снято 4 · выбрано 9», exit=0; `grep -c \"^=== \"` → 18 глав, то есть «18 глав» докстринга проверяемо, а «из 56», ncode и дата 2026-07-30 — нет."
|
||
}
|
||
},
|
||
{
|
||
"title": "material_ja: «прикалывание единиц манифестом» не исполнено — манифест хранит только 10-знаковые uid, его никто не читает, и доступа к ja-единицам из кода покупок нет вовсе",
|
||
"severity": "важно",
|
||
"evidence": "eval/dovodka/material_ja.py:29-33 обещает «манифест: единицы прикалываются к файлу, иначе докачка материала молча сдвинет уже купленный замер (ровно это случилось с эксп-22 и чинилось в паке 23)». Запись :181-184 кладёт только `ja=dict(uids=[...])` — ни текстов, ни хешей источника, ни границ чанков. `grep -rn \"manifest-ja\" --include=*.py eval/` → единственный хит, строка 47 самого material_ja.py (определение). `grep -rn \"material_ja\\|units_ja\" --include=*.py eval/` → хитов, кроме докстринга запуска, нет: функции доступа к ja-единицам не существует. Файла `~/books/dovodka/manifest-ja.json` на диске нет (`ls` → No such file).",
|
||
"consequence": "Дефект эксп-22, который этот файл объявляет починенным, остаётся открытым: книга скачана на 18 глав из 56, докачка сдвинет и границы чанков, и uid, а обнаружить сдвиг нечем — читателя манифеста нет, восстановить текст по uid нельзя (uid = sha1 текста, обратного отображения не хранится). Покупающему коду сегодня неоткуда взять те самые 9 единиц, которые напечатал отбор; он возьмёт их пере-прогоном скрипта, то есть по состоянию файла на момент покупки.",
|
||
"fix": "Класть в манифест сами тексты единиц (или sha256 источника + смещения) и завести `units_ja()`, который ЧИТАЕТ манифест и падает при расхождении, как это сделано в eval/tenant_panel/material.py:265-311; прогнать с --units и зафиксировать ДО покупок.",
|
||
"verdict": {
|
||
"line": "инструменты",
|
||
"refuted": false,
|
||
"why": "ЯДРО НАХОДКИ ПОДТВЕРДИЛОСЬ, НО ТРИ ИЗ ЧЕТЫРЁХ УЛИК/ПОСЛЕДСТВИЙ ОПРОВЕРГНУТЫ ИСПОЛНЕНИЕМ.\n\nЧТО ВЫСТОЯЛО (проверено):\n* Читателя манифеста нет. `grep -rn \"MANIFEST\\|manifest\" --include=*.py eval/` → в dovodka только три строки самого material_ja.py (47 — константа, 181 — запись, 185 — печать). `grep -rn \"material_ja\\|units_ja\" -r . --include=*.py --include=*.md` → ни одной функции доступа. Значит печать material_ja.py:185 «единицы приколоты; докачка их больше не сдвинет» — УТВЕРЖДЕНИЕ ЛОЖНОЕ по построению: файл пишется и не читается никем, приколка не наступает от факта записи. Это и есть настоящая находка, и она не объявлена ограничением: докстринг :32-33 подаёт приколку как ИСПОЛНЕННЫЙ шаг лестницы («манифест: единицы прикалываются к файлу»), а не как план.\n\nЧТО ОПРОВЕРГНУТО (каждое — своей командой):\n1. «Файла manifest-ja.json на диске нет» — не улика. Прогнал `eval/.venv/bin/python eval/dovodka/material_ja.py` (EXIT=0, гардрейл 0/48, отбор 9 единиц): последняя строка — «(манифест НЕ записан — прогнать с флагом --units, когда состав утверждён)» (material_ja.py:186-187). Отсутствие файла — объявленное состояние «состав ещё не утверждён», а не дефект.\n2. «Докачка сдвинет и границы чанков, и uid» — ФАКТИЧЕСКИ НЕВЕРНО. chunks() (material_ja.py:88-98) сбрасывает буфер НА КАЖДОЙ главе, поэтому дописанные главы не могут двигать чанки прежних. Проверил: скрипт в скретчпаде подгрузил модуль, снял 48 uid, дописал в копию источника 6 новых глав (19–24), пере-снял: «после докачки чанков: 64 · первые 48 uid совпали посимвольно: True · все старые uid присутствуют: True». Сдвигается только ОТБОР (медиана распределения длин + дециль гейта прав): отбор ДО и ПОСЛЕ разошёлся, пересечение 8 из 9. То есть механизм риска ровно один — выбор единиц, — и именно его закрывает манифест эксп-22.\n3. «Восстановить текст по uid нельзя, обратного отображения не хранится», и потому «класть в манифест сами тексты (или sha256+смещения), как в eval/tenant_panel/material.py:265-311» — НЕВЕРНО, и эталон описан задом наперёд. manifest() в material.py:265-275 текстов НЕ хранит (uids + sha256[:16]), а _pinned_uids (material.py:199-207) читает ТОЛЬКО uids; units_zh (material.py:223-232) восстанавливает тексты пере-чанкованием материала и сопоставлением uid, падая `SystemExit` на любом ненайденном пине. Проверил тем же скретч-скриптом на РАСШИРЕННОМ материале: «uid старого отбора восстановимы из нового материала: True · не найдено: []», длина восстановленного 75d6ef1bb2 = 1148. Значит uid-only манифест достаточен; недостающая деталь ровно одна — читатель, а не тексты/хеши/границы.\n4. «Покупающему коду сегодня неоткуда взять единицы» — покупающего кода для ja НЕ СУЩЕСТВУЕТ вовсе. contour.py:2 покупает армы A1–A4/A6 на zh; `grep -rn \"\\bja\\b\" --include=*.py eval/dovodka/` вне material_ja даёт только смету (plan.py:85-88), кассу (money_d.py:57 — маска dv-c-*.json) и мощность (power.py:56,67). `ls ~/books/dovodka/dv-c-*` → No such file. Ось ФД-C ($0.154, 9 единиц) объявлена РАЗВЕДОЧНОЙ/описательной (Д0.3, Д0.5). Денег сегодня не тратится и ни один вывод фазы Д не меняется — риск наступает только в момент, когда ja-покупка будет написана. Крауллера ja в репо тоже нет (`grep -n \"crawl\\|urllib\\|requests\\|http\" material_ja.py` → пусто), так что «молча докачается» само по себе не произойдёт.\n\nИТОГ: тяжесть «важно» завышена — это не потеря денег и не искажённый замер, а ложная печать/докстринг о состоявшейся приколке плюс отсутствующий читатель в ещё не построенной ветке. Уровень — «средне, до первой ja-покупки».",
|
||
"corrected": "material_ja.py объявляет приколку единиц исполненной, хотя механизма приколки нет: манифест только ПИШЕТСЯ (:181-184) и не читается ничем (grep по eval/ — ни одного читателя), а печать :185 «единицы приколоты; докачка их больше не сдвинет» и докстринг :32-33 утверждают обратное. Ложна не форма манифеста, а факт приколки: uid-only достаточно — эталон eval/tenant_panel/material.py тоже не хранит текстов, он восстанавливает их пере-чанкованием по uid (_pinned_uids :199-207, units_zh :223-232, падает на ненайденном пине), и на расширенном ja-материале все 9 uid восстановились. Механизм риска ровно один и он не тот, что назван: докачка глав НЕ двигает границы чанков и uid (48 старых uid посимвольно те же после дописывания 6 глав, чанков стало 64) — двигается ОТБОР «из середины длин» и дециль гейта прав (пересечение старого и нового отбора 8 из 9). Починка: завести units_ja(), который ЧИТАЕТ manifest-ja.json и падает при ненайденном uid, и до этого не печатать «приколоты»; текстов/смещений в манифест класть не нужно. Тяжесть — средняя, не важная: покупающего ja-кода ещё нет (contour.py zh-only, dv-c-*.json на диске нет), денег не потрачено, вывод фазы не меняется; отсутствие файла на диске дефектом не является — скрипт сам печатает «манифест НЕ записан — прогнать с --units, когда состав утверждён» (:187)."
|
||
}
|
||
},
|
||
{
|
||
"title": "canon.py: снятая адверсариальным ревью классификация мест по-прежнему считается и пишется в артефакт, который объявлен спецификацией фиксера",
|
||
"severity": "важно",
|
||
"evidence": "Докстринг canon.py:20-27: «Список мест остался как СЫРЬЁ для фиксера (где искать), но классом он больше не размечается и числом по классам не подводится», и печать :227-229 повторяет это в отчёт. Код при этом зовёт `classify(...)` (:205), копит `per_class` (:210, дальше нигде не используется) и пишет `cls=d` в персист :302-305. Содержимое `~/books/dovodka/canon-dissect.json`: 24 записи, поля ['uid','term','dst','cls','why','draft','edit'], `Counter({'парафраз': 19, 'другой': 4, 'исчез': 1})` — то есть 19/24 = 79%, ровно то число, которое ревью объявило НИЖЕ нулевой модели 82.5%.",
|
||
"consequence": "Единственный носитель-артефакт Д5, объявленный «спецификацией того, что канон-фиксер обязан уметь чинить, и его регрессионным набором», несёт снятую разметку в машинно-читаемом виде. Любой, кто построит фиксер или сводку по этому json (а именно так его и предписано использовать), возьмёт `cls` и воспроизведёт вывод, который отчёт объявил недействительным, — при этом отчёт будет утверждать, что классов нет.",
|
||
"fix": "Не писать `cls`/`why` в персист (или писать под именем `retracted_cls` с полем-предупреждением), убрать мёртвый `per_class`; пере-прогнать canon.py и пере-выпустить canon-dissect.json до того, как на нём начнут строить фиксера A1/A3/A4.",
|
||
"verdict": {
|
||
"line": "инструменты",
|
||
"refuted": false,
|
||
"why": "Попытка опровержения провалилась — все три опорные улики воспроизведены исполнением, и это НЕ объявленное ограничение, а прямое противоречие внутри одного файла.\n\n1) Персист действительно пишет снятую разметку, и это ТЕКУЩЕЕ поведение, а не устаревший файл. Загрузил canon.py как модуль, подменил только m.OUT на scratchpad (файлы не правил, покупок нет — скрипт $0, читает купленное сырьё эксп-22), выполнил main(): rc=0, свежий canon-dissect.json = 24 записи, поля ['cls','draft','dst','edit','term','uid','why'], Counter({'парафраз': 19, 'другой': 4, 'исчез': 1}), и сравнение `d==old` с /home/ubuntu/books/dovodka/canon-dissect.json дало True. То есть пере-прогон воспроизводит ровно 19/24 = 79% — то самое число, объявленное недействительным.\n\n2) Противоречие внутри файла подтверждено построчно. eval/dovodka/canon.py:26-27 — «Список мест остался как СЫРЬЁ для фиксера (где искать), но классом он больше не размечается и числом по классам не подводится»; тот же прогон печатает canon.py:227-229 «⚠ КЛАССАМИ НЕ РАЗМЕЧАЮТСЯ. Прежняя разбивка «исчез/парафраз/другой» снята ревью» (строка видна в stdout прогона). При этом canon.py:203 зовёт classify(), :209 кладёт cls/why в rows, :302-305 пишет `cls=d, why=e` в json.\n\n3) per_class мёртв — подтверждено грепом: `grep -n per_class eval/dovodka/canon.py` даёт ровно два хита, :159 (инициализация) и :210 (инкремент); ни одного чтения.\n\n4) «Спецификация фиксера» — цитата грунтована: docs/POLYGON_EXP2223_REDO_SESSION_PROMPT.md:104-106 «Это спецификация того, что канон-фиксер (Д4 A1/A3/A4) обязан уметь чинить, и его регрессионный набор»; eval/dovodka/requirements.md:65-67 (Д5/R34/R35) называет тот же json регрессионным набором. Ссылка на нулевую модель 82.5% при наблюдённых 79% — docs/experiments/23-editor-tier.md:836-837.\n\nПроверил и обратную гипотезу «это уже объявлено»: `grep -rn \"canon-dissect\" --include=*.md --include=*.py .` даёт только canon.py:302,306 и requirements.md:67 — нигде не сказано, что в артефакте лежат снятые классы, и нигде нет предупреждения об этом. Downstream-потребителей у json сегодня нет (тот же греп), поэтому ни один УЖЕ напечатанный вывод находка не переворачивает — она про мину под будущим фиксером.",
|
||
"corrected": "Находка верна, но в трёх местах неточна.\n\n(а) Масштаб/тяжесть: денег не тратит и ни одного уже опубликованного вывода не меняет — потребителей у canon-dissect.json пока нет (грепом по репо json читает только сам canon.py). Это мина под будущим фиксером A1/A3/A4, а не порча текущего отчёта. «Важно» — верхняя граница; честнее «важно только потому, что артефакт объявлен единственным носителем Д5 и заказ предписывает строить на нём фиксер».\n\n(б) Починка сформулирована частично неверно в одном пункте: classify() убирать нельзя — её возврат НЕСУЩИЙ на canon.py:203-205 как фильтр (`if cls == \"есть\": continue`, места с найденным каноном в окне отсеиваются). Снимать надо только персист полей cls/why (или переименовать в retracted_cls с полем-предупреждением) и мёртвый per_class (:159, :210).\n\n(в) Пропущен корень, который делает находку не косметикой: отзыв классификации НЕ доведён до реестра требований и до заказа. eval/dovodka/requirements.md:66 (R34) до сих пор требует «КАЖДОЕ место потери покрытия у R0 классифицировано (исчез / парафраз / другой перевод)», и docs/POLYGON_EXP2223_REDO_SESSION_PROMPT.md:104-106 требует того же. То есть сейчас R34 читается как «исполнено» прибором, который сам себя объявил снятым, — и следующая сессия, идущая по реестру, законно возьмёт cls из json. Починка должна включать поправку R34 (класс снят, требование заменено на «список мест без классов + печать частоты срабатывания на случайном входе по норме Д0.6») — иначе удаление поля из персиста сделает R34 невыполнимым молча.\n\nПобочно (вне тела находки, но того же происхождения): число нулевой модели расходится между источниками — canon.py:24 говорит «84% ПРОИЗВОЛЬНЫХ окон», docs/experiments/23-editor-tier.md:836 — «82.5% на случайных окнах». Одно из двух в отчёт пойдёт неверным."
|
||
}
|
||
},
|
||
{
|
||
"title": "canon.py: метрика ЕДИНООБРАЗИЯ печатает число в отчёт без контроля на случайном входе — норма Д0.6 не исполнена в том самом файле, где она родилась",
|
||
"severity": "мелко",
|
||
"evidence": "canon.py:293 печатает «НАРУШЕНИЙ ЕДИНООБРАЗИЯ (конкурирующее родовое при том же якоре): 3»; классификатор — регекс по закрытому списку родовых :265-266 плюс правило `not g.startswith(mod.lower()[:3])` :276. Ни одной печати частоты срабатывания на случайном входе в файле нет (проверено прогоном: в выводе есть только раздел «ЧТО ЭТА МЕТРИКА ЛОВИТ И ЧЕГО НЕ ЛОВИТ»). Норма — docs/experiments/23-editor-tier.md:837-838, и заведена она после того, как ревью убило прежний классификатор ЭТОГО ЖЕ файла.",
|
||
"consequence": "Число 3 идёт в отчёт как замер, а его ложноположительная частота не объявлена. Смягчает то, что каждое из трёх нарушений напечатано цитатой («дом Цинь», «поместье Су», «дом Су») и проверяемо чтением — так что вывод, скорее всего, устоит. Но норма фазы формально не исполнена именно там, где куплена дороже всего, и следующий классификатор скопирует этот прецедент.",
|
||
"fix": "Добавить нулевую модель: та же rx по перемешанным/чужим текстам или по черновикам (если «дом Цинь» встречается и в черновике, это не потеря редактора) и печатать частоту рядом с числом.",
|
||
"verdict": {
|
||
"line": "инструменты",
|
||
"refuted": false,
|
||
"corrected": "canon.py: метрика ЕДИНООБРАЗИЯ печатает «3» без контроля точности — и оба недостающих контроля, будучи прогнаны, ЛОМАЮТ число, а не подтверждают его. Тяжесть — не «мелко», а средне: правится вывод Д5, не только форма. (а) Отсутствие FP-контроля подтверждено: grep по canon.py на «нулев|случайн|ложнополож|shuffle|random» даёт только :25, :228, :294 — все про СНЯТЫЙ классификатор парафраза либо про полноту (recall); дисклеймер :294-299 объявляет лишь чего метрика НЕ ловит, о ложных срабатываниях не говорит ни слова, т.е. это не объявленное ограничение. (б) Поправка вниз: числа 3 НЕТ ни в одном отчёте — grep -rn \"ЕДИНООБРАЗ|единообраз\" docs/ --include=*.md не даёт хитов в 22-tenant-panel.md и 23-editor-tier.md; норма Д0.6 (23-editor-tier.md:836-838) сработает на записи тела, формально ещё не нарушена. (в) Поправка вверх, главная: смягчение «вывод, скорее всего, устоит» неверно. Базовая частота на ЧЕРНОВИКЕ (те же единицы, 41599f30df исключён как в canon.py): «род 61 · поместье 2» и «род 67 · дом 1» = 2 класса нарушений / 3 вхождения уже в черновике против 3 / 5 у R0 — тот же порядок; canon.py печатает только сторону R0, а Д5 заявлен как «где боевой РЕДАКТОР теряет» (canon.py:1), значит атрибуция редактору для этого класса не подпёрта. (г) Семантический FP доказан на сырье: 2 из 3 помеченных классов передают ДРУГОЙ исходный токен, а не банковский 苏家 — d6cbc0179d «Кто смеет бесчинствовать в доме Су?!» ← 胆敢在苏府放肆 (苏府 = резиденция, 2 раза в единице); fdff3aae3a «вышибли ворота дома Су» ← 踹破了苏家大门 (физические ворота, и та же фраза сохраняет «верхушка рода Су» для клана); de3916de62 (помечено «поместье Су») несёт 苏府 ×3. Клановый смысл на обоих хитах держит только «дом Цинь». Защитимое число нарушений единообразия ≈ 1, не 3. (д) Починка в находке частично мертва: та же rx по перемешанным/чужим текстам сработает ~0 раз (шаблон якорится на литеральном имени) и даст ложно-успокоительные 0% FPR; кусаются ровно два контроля, которые я прогнал — базовая частота на черновике и сверка исходного токена (苏家 против 苏府/苏家大门).",
|
||
"why": "Прогнал eval/.venv/bin/python eval/dovodka/canon.py — в выводе «НАРУШЕНИЙ ЕДИНООБРАЗИЯ ...: 3» (秦家: род 57 · дом 2, ⛔ «дом Цинь» 2 из 59; 苏家: род 66 · дом 2 · поместье 1, ⛔ «поместье Су» 1 из 69, ⛔ «дом Су» 2 из 69), и ни одной печати частоты на случайном входе. Улики автора сверены построчно: canon.py:293 печать числа, :265-266 rx по закрытому списку GENERICS, :276 правило not g.startswith(mod.lower()[:3]); норма — docs/experiments/23-editor-tier.md:836-838. grep -n \"нулев|случайн|ложнополож|shuffle|random\" eval/dovodka/canon.py → 25, 228, 294: все про снятый классификатор парафраза либо про recall; grep -rn \"нулев|случайн|ложнополож|FPR|shuffl\" eval/dovodka/*.py вне canon.py → ни одного контроля в инструментах фазы. grep -rn \"ЕДИНООБРАЗ|единообраз\" docs/ --include=*.md → в отчётах паков 22/23 хитов нет (только формулировка политики в POLYGON_EXP2223_REDO_SESSION_PROMPT.md:93,103), значит число ещё не в отчёте. Свои контроли ($0, покупок нет), скрипт /tmp/claude-1000/-home-ubuntu-projects-textmachine/565edf3f-c90e-4aaf-8418-c2ec250acedc/scratchpad/nm2.py — та же rx и то же исключение trunc={'41599f30df'}: 秦家 ЧЕРНОВИК {'род': 61, 'поместье': 2} классов=1 / R0 {'род': 57, 'дом': 2} классов=1; 苏家 ЧЕРНОВИК {'род': 67, 'дом': 1} классов=1 / R0 {'род': 66, 'поместье': 1, 'дом': 2} классов=2. Сверка исходника (scratchpad/ctx.py, ctx2.py по MAT.units_zh()): d6cbc0179d 苏府×2 в т.ч. «胆敢在苏府放肆!» — ровно то место, где R0 даёт «бесчинствовать в доме Су»; fdff3aae3a «踹破了苏家大门,攻入了苏家!在他们看来,苏家高层已经死绝» ← R0 «вышибли ворота дома Су ... верхушка рода Су уже мертва»; de3916de62 苏府×3. Файлы не правил, .env не читал, сетевых вызовов не делал."
|
||
}
|
||
},
|
||
{
|
||
"title": "runs.py: отчёт заявляет «селфтест 16/16», исполнение даёт 15 проверок",
|
||
"severity": "мелко",
|
||
"evidence": "`eval/.venv/bin/python eval/dovodka/runs.py --selftest | grep -c '^\\[OK \\]'` → 15 (сам селфтест зелёный, «ЖУРНАЛ ГОДЕН»). docs/experiments/23-editor-tier.md:824: «`O_CREAT|O_EXCL`-замок с проверкой живости PID, селфтест 16/16».",
|
||
"consequence": "Число в отчёте не сходится с артефактом. Само по себе безобидно, но это ровно тот класс, который гейт чисел не ловит (сторожит присутствие числа, не истинность), и приёмка №16 уже ловила такие расхождения в паке 23; при следующем свипе оно будет предъявлено как невнимательность к собственным числам.",
|
||
"fix": "Поправить строку 824 на 15/15 либо дописать недостающую проверку в selftest (например, что `--report` считает незакрытые сессии).",
|
||
"verdict": {
|
||
"line": "инструменты",
|
||
"refuted": false,
|
||
"corrected": "runs.py: доки заявляют «селфтест 16/16» в ДВУХ committed-местах, исполнение даёт ровно 15 проверок — и 16 не достигалось никогда. `eval/.venv/bin/python eval/dovodka/runs.py --selftest` печатает 15 строк `[OK ]` из 17 строк вывода и «ЖУРНАЛ ГОДЕН» (exit 0). В источнике 18 вызовов `ck(` на runs.py:199-260, но три пары взаимоисключающие (205/207 «гонка», 222/225 «ждёт живой замок», 257/259 «кап отказывает») → на ЛЮБОМ пути ровно 15 печатаемых проверок; путей с 16 нет. Число ложно в docs/experiments/23-editor-tier.md:824 И в docs/PROGRESS.md:227 (обе строки закоммичены) — правка только 824 оставит журнал неверным. Число было ложным в момент написания, а не протухло: runs.py байт-в-байт равен своему единственному коммиту da5f4d0, которым добавлена и строка 824. Починка: править ДВА места на 15/15. Второй вариант из находки («дописать недостающую проверку, чтобы стало 16») — подгонка артефакта под цифру доки (CLAUDE.md: тесты и гейты под желаемое не подгонять); проверка `--report` на незакрытые сессии (runs.py:178-179) может быть заведена по существу, но не как арифметика до 16. Тяжесть подтверждаю как «мелко»: R7 реестра (eval/dovodka/requirements.md:34) требует лишь зелёный селфтест до первой сессии, счёта не называет; остальные числа той же фразы верны — CAP = 80 (runs.py:45), `O_CREAT|O_EXCL` (runs.py:83), проверка живости PID реально исполняется (runs.py:217-232). Ни один вывод замера и ни один доллар от числа не зависят.",
|
||
"why": "Опровергнуть не удалось — находка верна, уточнены масштаб и починка. (1) Исполнение: `eval/.venv/bin/python eval/dovodka/runs.py --selftest | grep -c '\\[OK'` → 15, всего 17 строк вывода, финал «ЖУРНАЛ ГОДЕН». (2) Не «пропущенная ветка»: прочитал runs.py:182-265 — `grep -c 'ck('` даёт 19 (1 def + 18 вызовов), но 205/207, 222/225, 257/259 — взаимоисключающие ветки try/except одного и того же имени проверки, значит печатается ровно 15 на любом пути; 16 недостижимо в принципе. (3) Не протухшая цифра: `git show da5f4d0:eval/dovodka/runs.py | diff - eval/dovodka/runs.py` пусто («IDENTICAL to freeze commit»), файл в git чист (`git status --porcelain` пусто), а `git log -S 'селфтест 16/16' -- docs/experiments/23-editor-tier.md` указывает на тот же da5f4d0 — число и код родились в одном коммите, число было ложно сразу. (4) Масштаб находки занижен: `grep -rn '16/16' docs/experiments/23-editor-tier.md docs/PROGRESS.md` показывает ту же ложную фразу ещё и в docs/PROGRESS.md:227 (строка закоммичена — её нет в `git diff -- docs/PROGRESS.md`); остальные вхождения «16/16» в паке — про 16 единиц, другой смысл, они не при чём. (5) Проверил версию «это объявленное ограничение»: в eval/dovodka/requirements.md:34 (R7) счёта проверок нет, только «селфтест до первой сессии», то есть нигде не сказано «15» — расхождение нигде не объявлено, но и ни на что не опирается. (6) Проверил, не ложны ли соседние числа той же фразы (было бы расширением находки): CAP = 80 на runs.py:45, `os.O_CREAT | os.O_EXCL` на runs.py:83, живость PID реально гоняется на runs.py:217-232 — верно. (7) Смежные селфтесты дают 13/18/17 (contour/money_d/promptdiff) — источника цифры 16 в фазе нет, это не перепутанный модуль."
|
||
}
|
||
},
|
||
{
|
||
"title": "promptdiff: проверка разделителя ---USER--- написана цепочкой сравнений и означает не то, что заявлено",
|
||
"severity": "мелко",
|
||
"evidence": "eval/dovodka/promptdiff.py:178 — `ck(\"разделитель ---USER--- в обоих\", (\"---USER---\" in zh) == (\"---USER---\" in en) is True, ...)`. В Python это цепочка: `(A == B) and (B is True)`. При A=B=False проверка ПРОВАЛИТСЯ с деталью «zh False · пара False», хотя заявленное условие («в обоих одинаково») выполнено.",
|
||
"consequence": "Сегодня безвредно — оба файла разделитель имеют, и все прогоны зелёные. Но на паре без разделителя гейт даст ПРОВАЛ с текстом, который ему противоречит, и разбираться будут не с промптом, а с гейтом. Строка также маскирует намерение: если требуется наличие в обоих, это надо писать явно.",
|
||
"fix": "Заменить на `ck(\"разделитель ---USER--- в обоих\", (\"---USER---\" in zh) and (\"---USER---\" in en), ...)`.",
|
||
"verdict": {
|
||
"line": "инструменты",
|
||
"refuted": true,
|
||
"why": "Находка опровергнута по существу: предложенная «починка» — побайтный no-op, а объявленное условие — именно то, что код и делает.\n\n1) Улика по строке верна ровно как факт: `eval/dovodka/promptdiff.py:178` — единственная цепочка сравнений в файле. Проверил AST-обходом, а не глазами:\n `eval/.venv/bin/python -c \"…ast.walk… len(n.ops)>1\"` → `chained compare at line 178 : ('---USER---' in zh) == ('---USER---' in en) is True`.\n\n2) Но вывод из неё неверен. Таблица истинности текущего выражения и предложенной замены СОВПАДАЕТ полностью (выполнено на eval/.venv/bin/python):\n A=T,B=T → current True / `A and B` True\n A=T,B=F → False / False\n A=F,B=T → False / False\n A=F,B=F → **False / False**\n Разошлась бы только форма `(A == B)` (в последней строке дала бы True), но её никто и не предлагает. То есть `(A==B) and (B is True)` ≡ `A and B`; замена не меняет ни одного исхода ни на одной паре — ни сегодня, ни на будущей. `dis` подтверждает механику: после `COMPARE_OP ==` идёт `POP_JUMP_IF_FALSE`, и в ветке True сравнивается `B is True`.\n\n3) Заявление «заявленное условие («в обоих одинаково») выполнено» подменяет объявленную норму. Объявлено НЕ «одинаково», а «в обоих»:\n * docstring, `promptdiff.py:18`: «разделитель `---USER---` **присутствует в обоих** и на своём месте»;\n * имя самой проверки, `promptdiff.py:178`: «разделитель ---USER--- **в обоих**».\n Пара без разделителя обязана валиться по этой норме, и деталь «zh False · пара False» её не опровергает, а объясняет. Сценарий «гейт даст ПРОВАЛ с текстом, который ему противоречит» не воспроизводится: провал корректен, текст корректен.\n\n4) «Строка маскирует намерение» тоже не держится в контексте: двумя строками ниже, `promptdiff.py:180`, автор пишет то же условие явным `and` — `if \"---USER---\" in zh and \"---USER---\" in en:` — как гард для проверки хвоста. Намерение в файле выражено недвусмысленно.\n\n5) Ни один вывод фазы Д не меняется, денег не тратится. Гейт зелёный: `eval/.venv/bin/python eval/dovodka/promptdiff.py` → `[OK ] разделитель ---USER--- в обоих zh True · пара True` (дважды, translator и editor), exit=0.\n\nОстаток находки — чисто стилистический: цепочка `== … is True` читается хуже, чем `and`, и рецензент справедливо на неё споткнулся. Но это косметика с нулевой поведенческой дельтой, а не дефект гейта; заявленные «тяжесть: мелко» + «последствие на будущей паре» дают ложное впечатление скрытого риска, которого нет.",
|
||
"corrected": "Если оставлять как заметку, то в честной формулировке: «promptdiff.py:178 записан цепочкой `(A) == (B) is True`, что читается двусмысленно, хотя семантически ТОЖДЕСТВЕННО `A and B` (проверено таблицей истинности). Поведенческого дефекта нет: объявленная норма — «разделитель присутствует в обоих» (docstring:18), и код реализует именно её; пара без разделителя обязана валиться, деталь «zh False · пара False» этому не противоречит. Косметическая правка читаемости, приоритет ниже мелкого; выводов не меняет.»"
|
||
}
|
||
},
|
||
{
|
||
"title": "Смета plan.py занижает цену фиксера в 2.4× — потолок ФД-A $0.885 не закрывает арм Д4 ни при каком порядке покупок",
|
||
"severity": "критично",
|
||
"evidence": "eval/dovodka/plan.py:56 `fixer = 0.60 * edit` → печатает $0.00314 (прогон `eval/.venv/bin/python eval/dovodka/plan.py`). Факт по 148 клеткам фазы: медиана роли fixer $0.007561 (×2.41), по армам A1 0.006865 / A3fix 0.007411 / A4 0.007937 / A6fix 0.008875. Пере-счёт ФД-A по фактическим медианам: 30·A1 + 32·A2@0.006 + 32·(A3crit+A3fix) + 31·A4 + пол 16·0.007561 = $1.1682 против потолка $0.885 (+$0.283, +32%). Разложение расхождения: A1 −$0.119, A4 −$0.148, пол −$0.071, A3 +$0.056 — сумма −$0.282, ровно наблюдаемый перерасход.",
|
||
"consequence": "Потрачено $0.8719 из $0.885 при куплённых 60% арма (A2 не начат, A4 22/32, пол не куплен). Д4 — несущая ось фазы: под нынешним потолком она не закрывается, и деньги, уже потраченные на A1/A3/A4, повисают как незавершённое семейство контрастов (Холм по пяти в Д0.5 требует всех армов).",
|
||
"fix": "Пере-считать ФД-A по фактическим медианам сырья фазы, а не по множителям 0.60×/2.14×; вынести цифру владельцу как запрос на подъём потолка ФД-A с 0.885 до ≈1.17 (закрытие Д4 без пере-покупок). Заодно научить `plan.py.measured()` читать `~/books/dovodka` — сейчас он смотрит только в T и E (plan.py:26-27,36), поэтому обещанная в plan.py:55-56 «сверка сметы с фактом при закрытии фазы» не имеет кода и после 148 купленных клеток печатает всё те же $0.00314.",
|
||
"verdict": {
|
||
"line": "деньги",
|
||
"refuted": false,
|
||
"corrected": "Смета plan.py занижает фиксер в 2.4×, и это ломает НЕ ФД-A, а ПАКЕТ: фаза Д в нынешнем дизайне не влезает в санкционированные владельцем $4.50.\n\n(1) Корень точнее, чем «множитель 0.60». plan.py:56 `fixer = 0.60 * edit` → $0.00314; факт по 100 фиксерным клеткам ~/books/dovodka: медиана $0.007561 (×2.41), по армам A1 0.006865 / A3fix 0.007411 / A4 0.007937 / A6fix 0.008875. Парно по 15 единицам, у которых есть единственная dspro-`edit`-клетка того же uid: A0 медиана $0.005851 против A1-фиксера $0.006435, A1 дешевле лишь в 6 из 15, медиана разницы +$0.000789. То есть фиксер ≈ 1.1× полного переписа, а не 0.6× — посылка «выход много короче ⇒ дешевле» в цене не подтвердилась. Попутно опровергается запись в ~/books/dovodka/razbiratelstvo-sudi-10-08.txt «находка \"A1 дороже полного переписа\" НЕ подтвердилась (медиана −$0.000096, n=7)»: при n=15 знак противоположный. Критик — ошибка в другую сторону (прогноз $0.01120 против факта $0.005190), она частично компенсирует.\n\n(2) Масштаб ЗАНИЖЕН, а не завышен. Единиц не 32: у A1 их 30 (без флагов 474f822806, 9b16c9c9a7), у A4 — 31 (без канон-щелей 474f822806); посчитано прогоном canon_gaps/flags_of по всем 32 единицам за $0, A4 куплен на 22 из 31 при 9 годных некуплённых — гард действительно остановил. Пере-счёт по потраченному + медианы на остаток: ФД-A = $1.2317 при потолке $0.885 (+$0.347, +39%), а не $1.1682/+32% — находка считала уже купленные армы медиана×n, тогда как фактический расход выше медианы (распределение скошено).\n\n(3) Область шире одного ФД-A. ФД-F ломается сильнее: A6 объявлен как ОБА контура, куплен один — $0.267825 из потолка $0.283; со вторым контуром (16 клеток по медиане A6-фиксера) $0.4098, +45%. Фиксерная часть ФД-B (plan.py:82, `16*(fixer+critic+fixer)`) поднимает фазу с $0.556 до $0.601 при потолке $0.560. Пакет: 4.470 → $4.9999 при потолке $4.50. Поэтому починка — не «поднять ФД-A до ≈1.17» (это перекладывание внутри пакета, которого нет), а СТОП и вопрос владельцу о пакетном потолке либо о срезе оси его решением.\n\n(4) Часть про мёртвую сверку верна дословно: `grep -n dovodka eval/dovodka/plan.py` даёт только строку запуска, measured() читает лишь T и E (plan.py:26-27,34) — обещанная в plan.py:54-55/68 «сверка сметы с фактом при закрытии» кода не имеет.",
|
||
"why": "Прогон `eval/.venv/bin/python eval/dovodka/plan.py` печатает «фиксер $0.00314 (0.60× переписа)», исходник — plan.py:56. Агрегация всех 148 клеток ~/books/dovodka скриптом даёт: fixer n=100 медиана $0.007561 (×2.41 к 0.00314); A1 n=30 sum $0.2269 med 0.006865 · A3crit n=32 med 0.005190 · A3fix n=32 med 0.007411 · A4 n=22 sum $0.1935 med 0.007937 · A6crit n=16 med 0.007777 · A6fix n=16 med 0.008875; TOTAL $1.1397 — совпадает с `money_d.py --report` (ФД-A 0.871904 при 0.885, ФД-F 0.267825 при 0.283, ПАК 1.139729). Потолки — money_d.py:67. Парное сравнение цены фиксера и полного переписа по uid (15 пар с единственной dspro-edit-клеткой): A0 медиана $0.005851 против A1 $0.006435, A1 дешевле в 6 из 15, медиана разницы +$0.000789 — множитель 0.60 неверен по построению, реальное отношение ≈1.1×. Число годных единиц получено импортом contour.py и прогоном canon_gaps/base_a0 (сеть не трогается): для A4 годных 31, куплено 22, 9 годных некуплённых (13c5f52fa3, b0a5efaa11, e40cdfbc3e, 63ab55ac5c, debb2c1aef, 89614f9bfa, 7d0258aec0, 3727846a2c, fb9ed5709e) — значит остановил гард, а не исчерпание материала; для A1 годных 30. Пере-счёт (потраченное + медианы на остаток, A2 по edit-медиане $0.00523, пол 16 клеток): ФД-A $1.2317 (+$0.3467, +39%), ФД-F с обоими контурами $0.4098 (+45%), ФД-B $0.556→$0.6014 при потолке $0.560, пакет 4.470→$4.9999 при $4.50. «Объявленным ограничением» это не закрыто: plan.py:54-55 объявляет множители прогнозом и обещает сверку при закрытии, но `grep -n dovodka eval/dovodka/plan.py` находит только строку запуска, а measured() (plan.py:26-27,34) читает только ~/books/tenant-panel и ~/books/editor-tier — кода сверки нет, и после 148 клеток скрипт печатает те же $0.00314. Величина расхождения нигде не записана: `git show 90c23cb -- docs/PROGRESS.md` (вечерний статус) фиксирует покупку A1 и денежной тревоги не содержит; ~/books/dovodka/razbiratelstvo-sudi-10-08.txt замерил $0.007251/клетка, но вывел «$0.2175 при потолке ФД-A $0.885», то есть цену увидел, а на арм не спроецировал. Вывод меняется: под нынешним пакетом Д4 (несущая ось, Холм по пяти армам, Д0.5) не закрывается ни при каком порядке покупок."
|
||
}
|
||
},
|
||
{
|
||
"title": "Внутри пакета денег нет: сумма фазовых потолков 4.495 из 4.50, свободно $0.005 — любой добор Д4 требует решения владельца, а не перекладки",
|
||
"severity": "критично",
|
||
"evidence": "`money_d.py:67-69`, проверено исполнением: sum(CEILINGS)=4.495, PACK_CEILING=4.50, свободно $0.005. Остаток ФД-A = 0.885−0.871904 = $0.013096. Стоимость буквального закрытия Д4 по фактическим ценам: A2 32 клетки × $0.0039…0.0079 (нижний якорь — медиана роли draft/deepseek-v4-pro пака 22, n=22, $0.003875; верхний — наблюдённая медиана dspro на ЭТОМ материале) + A4 9 клеток × $0.007937 = $0.196…$0.324, центр $0.263. Не хватает $0.183…$0.311.",
|
||
"consequence": "Ответ на ключевой вопрос: закрыть Д4 (A2 32 + A4 9) стоит ≈$0.26, потолков НЕ хватает — ни фазового ($0.0131), ни пакетного ($0.005). Полное закрытие Д4 со своим полом — $0.38…$0.56; с починкой Д-5 (A6, +$0.142) — до $0.70; если Д-2 и Д-3 требуют пере-покупки уже оплаченных клеток — ещё $0.220 (32·A1) и $0.215 (17·A3fix + 10·A6fix), итого до ≈$1.13 сверх потраченного. Проекция всей фазы по фактическим ценам ≈$4.96 против пакета $4.50.",
|
||
"fix": "Это ровно тот случай, который money_d.py:18 объявляет СТОПом и вопросом владельцу. Вынести владельцу три числа: закрытие Д4 $0.26, Д4+пол+A6 $0.70, полное с пере-покупками $1.13 — и спросить, поднимать пакет до ≈$5.2–5.7 или резать ФД-E (gemini $2.355 = 52% пакета) его же решением.",
|
||
"verdict": {
|
||
"line": "деньги",
|
||
"refuted": true,
|
||
"why": "Арифметика верна, но находка как «критичный дефект» не стоит: это объявленная норма, а её заголовок неверно описывает, где деньги.\n\n(1) ЧИСЛА ПРОВЕРЕНЫ: `eval/dovodka/money_d.py:67-69` → sum(CEILINGS)=0.885+0.560+0.155+0.055+2.355+0.283+0.202=4.495 при PACK_CEILING=4.50; `eval/.venv/bin/python eval/dovodka/money_d.py --report` даёт ФД-A 0.871904/0.885 (остаток $0.013096), ФД-F 0.267825/0.283, ПАК 1.139729/4.50. Тут спора нет.\n\n(2) НО «внутри пакета денег нет» — ЛОЖНО как утверждение. Та же команда печатает `ПАК 1.139729 4.50 резерв 3.360271`: в пакете НЕ потрачено $3.36. Гард `eval/tenant_panel/money.py:152` и `:156` сторожит две границы — фазовую и пакетную; упирается покупка Д4 ТОЛЬКО в фазовую ($0.0131). $0.005 — это не «свободные деньги пакета», а нераспределённый люфт РАЗБИЕНИЯ потолков.\n\n(3) Само разбиение с минимальным люфтом — ОБЪЯВЛЕННЫЙ проект, а не находка: `money_d.py:63-66` («потолки фаз = смета plan.py плюс МИНИМАЛЬНЫЙ запас, так чтобы их СУММА не превышала пакетный»), и селфтест это утверждает: `money_d.py --selftest` → `[OK ] сумма фазовых потолков не выше пакетного 4.50 ≤ 4.50`. Последствие тоже объявлено ДО покупок: пре-рег Д0.8, `docs/experiments/23-editor-tier.md:868-874` — «Резерв $0.03 — это 0.7% пакета, и сессия объявила это риском ДО покупок… Срабатывание проекционного гарда = СТОП и вопрос владельцу, а не сокращение оси решением сессии»; то же в докстринге `money_d.py:14-19`. Находка сама цитирует `money_d.py:18` в поле «починка» — то есть предлагает ровно ту процедуру, которую риг предписывает. По правилу ревью («отчёт сам называет проблему и её последствие → исполненная норма») это не находка.\n\n(4) МАСШТАБ ЧАСТИЧНО НЕВЕРЕН. По уникальным uid сырья (~/books/dovodka/dv-*.json, 32 uid всего): A4 fixer 22 uid, НЕ покрыто 10 (не 9), из купленных 2 с finish=length, которые Д0.6 в пачку не допускает → буквальное закрытие A4 = 10 новых + 2 пере-покупки = 12 клеток. A1 fixer 30 uid из 32 — 2 недостающие клетки в «закрытии Д4» не учтены вовсе. Ценовые якоря A2 подтвердились ($0.003875 = медиана draft/deepseek-v4-pro пака 22, n=22; translator/dspro n=2 $0.003837), верхний $0.0079 тоже в полосе фактических фиксеров ($0.006865 A1 … $0.008875 A6).\n\n(5) НИ ОДИН ВЫВОД ЭКСПЕРИМЕНТА не меняется, и деньги впустую не тратятся: находка описывает бюджетный статус, который пре-рег предсказал и оформил как СТОП. Тяжесть «критично» не подтверждается.\n\n(6) ЧТО ДЕЙСТВИТЕЛЬНО НЕ СКАЗАНО В ДОКАХ (и это другая находка, а не эта): причина перебора — не разбиение потолков, а мимо-калиброванная модель цены клетки в `eval/dovodka/plan.py:52-53`: fixer = 0.60×edit = $0.00314 и critic = 2.14×edit = $0.01120, тогда как ЗАМЕРЕНО на этом материале fixer $0.006865 (A1) / $0.007411 (A3) / $0.007587 (A4) / $0.008875 (A6) — в 2.2–2.8 раза дороже, а critic $0.005190 (A3) / $0.007777 (A6) — в 0.46–0.69 раза дешевле. Ошибки частично гасятся на A3 (план 32×0.01434=$0.459 против факта $0.4515), но на чисто-фиксерных армах дают 2.2–2.8×, отчего ФД-A и упёрся на 66% клеток. Те же множители лежат под ФД-B ($0.556) и ФД-F ($0.283, уже 94.6% выбрано, флаговая ветка A6 ≈$0.142 не куплена) — то есть перебор повторится и там.",
|
||
"corrected": "Что от находки выживает (в переформулировке, без статуса «критично»): фазовый потолок ФД-A исчерпан ($0.013096 остатка), поэтому Д4 не закрывается — но пакет не пуст ($3.360271 не потрачено), а исчерпан ИМЕННО фазовый лимит, и это ровно тот СТОП, который пре-рег Д0.8 (23-editor-tier.md:868-874) и money_d.py:14-19 объявили ДО покупок. Буквальное закрытие Д4 больше, чем в находке: A2 32 клетки ($0.0039…0.0079 → $0.125…$0.253) + A4 10 непокрытых uid + 2 пере-покупки клеток finish=length (Д0.6) ≈ $0.076…$0.107 + пропущенные находкой 2 клетки A1 ≈ $0.014 → $0.22…$0.37 (центр ≈$0.29), со своим шумовым полом $0.32…$0.51. НАСТОЯЩАЯ же и нигде не записанная причина — мимо-калибровка цены клетки в plan.py:52-53 (fixer 0.60×edit = $0.00314 против замеренных $0.0069…$0.0089, т.е. 2.2–2.8×; critic 2.14×edit = $0.01120 против $0.0052…$0.0078, т.е. 0.46–0.69×). Именно она, а не разбиение потолков, съела ФД-A на 66% клеток и лежит под ещё не тронутыми ФД-B ($0.556) и ФД-F ($0.283, уже 94.6% выбрано при не купленной флаговой ветке A6 ≈$0.142). Владельцу выносить надо это: не «перекладку против добора», а пере-снятую по факту смету всех оставшихся фаз."
|
||
}
|
||
},
|
||
{
|
||
"title": "ФД-F исчерпан: гард уже отказывает, флаговый контур A6 (починка Д-5) не купит ни одной клетки",
|
||
"severity": "важно",
|
||
"evidence": "Прогон: `Guarded('ФД-F')` при next_model=deepseek-v4-pro → afford=False; потрачено $0.267825 при потолке $0.283, остаток $0.015175. Смета ФД-F (plan.py:97-99) = 16·(fixer+critic+fixer) = $0.280 при фактической цене 16·(A6fix 0.008875 + A6crit 0.007777 + A6fix 0.008875) = $0.4084. Куплен только смысловой контур (16 critic + 16 fixer, `contour.py --plan` печатает «A6: куплено 16 из 16»); флаговый контур — 16 клеток × $0.008875 = $0.142 против остатка $0.0152.",
|
||
"consequence": "H-1 — гипотеза, ради которой арм A6 и заведён приёмкой (Д0.2), — остаётся полу-замеренной: «ОБА контура» объявлены, куплен один. Починить Д-5 нельзя без подъёма потолка ФД-F, а печать `--plan` при этом рапортует «16 из 16», то есть арм выглядит полным.",
|
||
"fix": "Подъём ФД-F с 0.283 до ≈0.41 (или явное объявление A6 одноконтурным в отчёте с последствием для H-1). Плюс: `contour.py` cmd_plan считает A6 по одному тегу — пересчитать знаменатель на оба контура, иначе «16 из 16» врёт.",
|
||
"verdict": {
|
||
"line": "деньги",
|
||
"refuted": false,
|
||
"corrected": "ФД-F исчерпан: гард отказывает уже на ПЕРВОЙ клетке флагового контура A6, и починка Д-5 требует санкции владельца, а не правки числа. Факты: потолок ФД-F 0.283 (money_d.py:68), потрачено $0.267825 (dv-f-a6 critic 16 = $0.121089 + fixer 16 = $0.146736), остаток $0.015175; Guarded(\"ФД-F\") с next_model=deepseek-v4-pro даёт afford=(False, \"потрачено $0.267825 + ожидание $0.015945 = $0.283770 > потолок $0.28\") — то есть блокируется любая, даже одна клетка. Масштаб недокупки меньше заявленного: флаговый контур покупает клетку только при непустом списке мест (contour.py:263-265), а flags_of(u, base_draft2(uid)) даёт места у 14 из 16 старых единиц (нулевые: 474f822806, 3754987548), всего 54 места; при цене ближе к медиане A1-фиксера $0.006865 (промт из ~4 мест, а не из 40) это ≈$0.096–0.124, и оба контура ≈$0.364–0.392, а не $0.4084. Починка «поднять ФД-F до 0.41» неисполнима как есть: money_d.py:102-104 требует sum(CEILINGS) ≤ PACK_CEILING, сумма уже 4.495 при 4.50 (свободно $0.005 на уровне фазовых потолков при $3.36 непотраченных в пакете), с ФД-F=0.41 сумма 4.622 и селфтест кассы падает — нужна санкция владельца на пакетный потолок или перекладка из другой фазы, которая сессии запрещена (money_d.py:16-19). Корень промаха сметы не A6-специфичен: plan.py:52 прогнозирует фиксер = 0.60×перепис, а замеренные медианы фиксера ВЫШЕ переписа (A1 $0.006865, A3 $0.007411, A6 $0.008875 против edit $0.005230 = 1.3–1.7×), критик же пере-оценён (A3 critic $0.005190 ≈ 1.0× вместо 2.14×); ФД-A по той же причине тоже упёрся — Guarded(\"ФД-A\") даёт afford=False при $0.871904 + $0.015945 > $0.885. Последствие точнее формулируется так: незамеренным остаётся не H-1 целиком, а взаимодействие «детерминированные флаги × качественная база» (H-2а на dspro-черновике) — купленный смысловой контур критик→фиксер и есть «точечный редактор» из H-1 и ставка H-2б. Печать contour.py --plan при этом рапортует «A6: куплено 16 из 16» (знаменатель n=len(old) по одному тегу dv-f-a6-<uid>, contour.py:161-163,177-180), то есть арм выглядит полным; в докладе A6 объявлен «оба контура» (23-editor-tier.md:748,804,860), и ни исчерпание ФД-F, ни одноконтурность нигде не объявлены (grep -rn \"ФД-F\\|0.267825\" docs/ → единственный хит, строка сметы 860).",
|
||
"why": "Пере-проверил всё своими командами, опровергнуть не удалось. (1) Сырьё: скрипт по ~/books/dovodka/dv-*.json дал dv-f-a6 critic 16 sum=0.121089 и dv-f-a6 fixer 16 sum=0.146736 → ФД-F потрачено $0.267825 при потолке 0.283 (money_d.py:68), остаток $0.015175. (2) Гард: прогон Guarded(\"ФД-F\") с next_model=\"deepseek-v4-pro\" вернул model_expect=0.015945, afford=(False, \"[СТОП ФД-F эксп-22] потрачено $0.267825 + ожидание $0.015945 = $0.283770 > потолок $0.28\") — отказ реальный, а не предполагаемый, и он срабатывает на первой же клетке. (3) Смета: eval/.venv/bin/python eval/dovodka/plan.py печатает ФД-F 0.280 при прогнозных фиксер $0.00314 (0.60× переписа) и критик $0.01120; строка сметы — plan.py:97-99, ссылка автора верна. (4) contour.py --plan (запущен, $0) печатает «A6: куплено 16 из 16» — подтверждено дословно. (5) Объявленность: grep -rn \"ФД-F\\|0.267825\" docs/ даёт один хит (23-editor-tier.md:860 — строка сметы); ни исчерпания, ни одноконтурности A6 в докладе нет, а Д0.5/Д0.2 (строки 748, 804) объявляют «оба контура» — значит это не исполненная норма. (6) Масштаб автора завышен: прогнал flags_of(u, base_draft2(uid)) по 16 старым единицам — места есть у 14 из 16 (474f822806 и 3754987548 дают 0, всего 54 места), а contour.py:263-265 при пустом списке клетку не покупает; плюс промт из ~4 мест дешевле промта из 40, так что цена ближе к A1-медиане $0.006865, чем к $0.008875. Итог ≈$0.096–0.124 вместо $0.142 и ≈$0.364–0.392 вместо $0.4084 за оба контура. (7) Починка автора ломает инвариант кассы: sum(CEILINGS)=4.495 при PACK_CEILING=4.50 (посчитано), с ФД-F=0.41 сумма 4.622, и проверка money_d.py:102-104 «сумма фазовых потолков не выше пакетного» провалится — то есть подъём одного числа недопустим без решения владельца по пакетному потолку, а резать другие фазы сессии запрещено (money_d.py:16-19). (8) Проблема не изолирована в A6: Guarded(\"ФД-A\") тоже даёт afford=False ($0.871904 + $0.015945 > $0.885), а замеренные медианы фиксера (A1 0.006865, A3 0.007411, A6 0.008875) против edit 0.005230 показывают, что множитель 0.60× из plan.py:52 перевёрнут. Вывод меняется по существу: Д-5 из «дефект кода, чинится» превращается в «чинится только через санкцию владельца», и это в докax не сказано."
|
||
}
|
||
},
|
||
{
|
||
"title": "Множитель «поиск ≈2.14× переписа», объявленный в пре-реге как экономическое основание H-2б, опровергнут собственным сырьём фазы в 1.9×",
|
||
"severity": "важно",
|
||
"evidence": "docs/experiments/23-editor-tier.md:735 (Д0.1, H-2б): «дороже (поиск ≈2.14× переписа)»; plan.py:57 `critic = 2.14 * edit` → $0.01120. Факт: медиана роли critic по 48 клеткам $0.005758, при переписе (edit/deepseek-v4-pro, медиана пакетов 22/23) $0.00523 — то есть 1.10× переписа, а не 2.14×. A3crit на материале zh — $0.005190 (0.99× переписа).",
|
||
"consequence": "Смета переоценила критика в 1.9× и недооценила фиксера в 2.4×, ошибки не компенсируются (A3 экономит $0.056, A1+A4+пол теряют $0.338). Содержательно: цена, которой в Д0.1 обосновано «дороже, но качественнее», в разы меньше объявленной — вывод фазы по H-2б должен опираться на замеренные $0.0126 за контур (2.41× переписа за ПАРУ вызовов), а не на 2.14× за поиск.",
|
||
"fix": "В отчёте закрытия фазы напечатать сверку «объявлено 2.14× / замерено 1.10× за критика и 2.41× за контур целиком» — это меняет экономическую часть вердикта H-2б, а не только смету.",
|
||
"verdict": {
|
||
"line": "деньги",
|
||
"refuted": false,
|
||
"why": "ЧИСЛА ВОСПРОИЗВЕЛ СВОИМИ КОМАНДАМИ — арифметика находки верна.\n\nПрогон по сырью (eval/.venv/bin/python, ~/books/dovodka/*.json + ~/books/{tenant-panel,editor-tier}):\n ROLE critic n=48 median=0.005758 · ROLE fixer n=100 median=0.007561\n A3 critic n=32 med=0.005190 · A6 critic n=16 med=0.007777 · A1 fix 0.006865 · A3 fix 0.007411 · A4 fix 0.007937 · A6 fix 0.008875\n ('edit','deepseek-v4-pro') n=179 median=0.005233 (tenant-panel 163 / editor-tier 16)\n critic/edit = 1.100 · fixer/edit = 1.445 · контур A3 (crit+fix)/edit = 2.408 · 2.14/1.100 = 1.945 · fixer_факт/fixer_прогноз = 2.408\nМатериал сопоставим: uid клеток dovodka пересекаются с uid edit-клеток паков 22/23 ('1431129de6','2484f16eac' в обоих).\nАртефакта обрезки в цене критика нет: finish у всех 48 клеток критика = 'stop' (A3 32/32, A6 16/16), med_chars 5802/6952 — цена не занижена капом.\n\nНО ТРИ УТВЕРЖДЕНИЯ НАХОДКИ ОПРОВЕРГНУТЫ.\n\n1) «Объявлено в пре-реге как ЭКОНОМИЧЕСКОЕ основание H-2б» — НЕВЕРНО. 23-editor-tier.md:730-732 — это дословный блокквот заказа владельца, и он заканчивается: «Цена заложена в смету сознательно — гипотеза о КАЧЕСТВЕ, не об экономии» (:732). У H-2б по объявлению НЕТ экономической части вердикта, менять нечего. Починка «это меняет экономическую часть вердикта H-2б» противоречит тексту, на который ссылается.\n\n2) Направление гипотезы «дороже» ПОДТВЕРЖДЕНО собственными числами находки, а не опровергнуто: контур целиком 2.408× переписа против объявленных 2.14× — расхождение 13%, а не «в разы». «В 1.9× опровергнуто» получается только если сравнивать ПОЛОВИНУ контура (один вызов критика) с числом, объявленным про контур-как-механизм.\n\n3) Требуемая починка — уже объявленная обязанность рига, а не найденный пробел: plan.py:54-56 «Обоснование множителей — в отчёте §Д0; они ПРОГНОЗ, и расхождение с фактом печатается при закрытии фазы как сверка сметы», plan.py:68 печатает блок «ПРОИЗВОДНЫЕ (прогноз, сверяется с фактом при закрытии)», plan.py:57/70 явно помечают 2.14× как чужой множитель. Фаза не закрыта (A2 — ноль клеток), срок обязанности не наступил.\n\n4) МАСШТАБ ПЕРЕВЁРНУТ. Смета на купленных клетках недо-, а не переоценила: план $0.851514 против факта $1.139729, +$0.288 (1.34×). По армам факт/план: A1 fix 2.41× · A3 crit 0.56× · A3 fix 2.51× · A4 fix 2.80× · A6 crit 0.68× · A6 fix 2.92×. Деньги и гард ФД-A (A4 обрезан 22/32, A2 не куплен) сломал ФИКСЕР, а не критик; заголовок находки назвал безобидную половину — подушку.\n\n5) Происхождение 2.14× находка не проверила: это НЕ произвольная цифра заказа, а замер эксп-20 (20-editor-role.md:181, строка deepseek-v4-pro/ru: full $0.001316, locate ×2.14) — отношение locate/full на ОДНОМ И ТОМ ЖЕ микро-спане. plan.py пересадил его на знаменатель главной шкалы $0.005233 — в 4× больше того, против которого множитель определён. Сломалась пересадка базы, а не множитель; проверить эксп-20 фаза Д не может — в ~/books/dovodka нет ни одной клетки роли full/edit (только critic/fixer, 149 файлов).",
|
||
"corrected": "СМЕТА, а не вердикт: пересадка множителя 2.14× на чужой знаменатель недооценила ФАЗУ на $0.288 (1.34×) и это она сожгла ось A4\n\nТяжесть: средняя (смета/бюджет), не «важно по существу» — ни один вывод фазы не двигается.\n\nФормулировка: множитель 2.14× — это замер эксп-20 (20-editor-role.md:181) отношения locate/full на одном микро-спане при full=$0.001316. plan.py:57 применил его к главному переписy $0.005233 — знаменателю в 4× крупнее, — и получил критика $0.01120 при факте $0.005758 (1.10× переписа), а фиксера $0.00314 при факте $0.007561 (2.41× прогноза). Ошибки не гасятся: на купленных клетках план $0.8515 против факта $1.1397, +$0.288. Именно недооценка ФИКСЕРА (все четыре фиксерных арма 2.41–2.92× плана) выбрала потолок ФД-A и остановила A4 на 22 из 32; критик дал обратно $0.217 подушки.\n\nЧто при этом НЕ находка: сама печать сверки при закрытии — pre-declared обязанность (plan.py:54-56, 68), срок не наступил; и экономическая часть вердикта H-2б — её не существует по тексту пре-рега (23-editor-tier.md:732 «гипотеза о КАЧЕСТВЕ, не об экономии»), а объявленное «дороже» замером подтверждается: контур 2.408× переписа против 2.14×.\n\nПочинка: при закрытии печатать сверку по РОЛЯМ и в правильную сторону — «критик 2.14×→1.10× (подушка $0.217), фиксер 0.60×→1.44× переписа (перерасход $0.505), нетто −$0.288, причина обрезки A4»; и в plan.py впредь брать fixer/critic медианами из сырья фазы, а не множителями от переписа другого харнесса."
|
||
}
|
||
},
|
||
{
|
||
"title": "Шумовой пол Д4 забюджетирован вполовину против собственной нормы Д0.6: смета берёт 16 клеток там, где норма требует пару отдельных генераций",
|
||
"severity": "важно",
|
||
"evidence": "plan.py:75 `d4 = n4 * (...) + 16 * fixer` — одна клетка на единицу пола. docs/experiments/23-editor-tier.md, Д0.6: «Шумовой пол — парой, чьи половины судят РАЗНЫЕ сессии. Обе половины — ОТДЕЛЬНЫЕ генерации; боевая клетка половиной пола не берётся». По фактической цене 16 клеток = $0.121, парой (32 клетки) = $0.242; в смете эта строка стоит 16·$0.00314 = $0.050.",
|
||
"consequence": "Строка пола недооценена в 2.4× по цене и вдвое по числу генераций — итого $0.05 в смете против $0.24 по норме и факту. Пол — то, из чего берётся порог различимости всей оси Д4; если денег на пару не хватит, порог придётся брать из прайора, и ось по правилу Д0.3 пере-классифицируется в описательную уже после того, как на армы потрачено $0.87.",
|
||
"fix": "Пере-считать строку пола как 2 генерации × число единиц пола по фактической цене фиксера и внести в запрос владельцу вместе с подъёмом ФД-A.",
|
||
"verdict": {
|
||
"line": "деньги",
|
||
"refuted": false,
|
||
"why": "Пере-проверено исполнением, опровергнуть не удалось; все три денежных числа находки сошлись до цента. (1) Улика точна: eval/dovodka/plan.py:75 `d4 = n4 * (fixer + onepass + (critic + fixer) + fixer) + 16 * fixer`, n4=32 на строке 74; сумма воспроизводится: 32*(3*0.0031389+0.0052315+0.0111954)+16*0.0031389 = 0.8270+0.0502 = 0.877 (совпадает с Д0.8). (2) Норма процитирована дословно — docs/experiments/23-editor-tier.md:817-819 «Шумовой пол — парой… Обе половины — ОТДЕЛЬНЫЕ генерации; боевая клетка половиной пола не берётся». (3) Фактическая цена: по 100 клеткам role=fixer в ~/books/dovodka медиана $0.00756 (среднее $0.00819) → 16 клеток $0.1210, 32 клетки $0.2420; строка сметы 16*$0.0031389=$0.0502. Все три числа находки верны. (4) Это НЕ объявленное ограничение: plan.py:49-52 объявляет прогнозом только МНОЖИТЕЛИ цен (0.60×/2.14×), про число генераций пола не сказано нигде — ни в Д0, ни в docs/POLYGON_EXP2223_REDO_SESSION_PROMPT.md:160-162, ни в eval/dovodka/requirements.md (R58/R60 повторяют норму, не смету), ни в money_d.py:55 («ФД-A … + свой шумовой пол»). (5) Единственный контр-довод, который я нашёл, — что `16 * fixer` может означать 8 ПАР по 2 генерации: число единиц пола не объявлено нигде. Но эта трактовка тоже дефектна и нигде не заявлена, а братские строки той же сметы читаются однозначно как одна клетка на единицу: plan.py:82 `+ n3 * edit` с комментарием «два контура + пол» при n3=16 и plan.py:88 `n6 * (draft + edit + onepass + edit)` при n6=9 — то есть по 1 генерации на единицу, ровно шаблон «боевая клетка + повтор», который Д0.6 запрещает (и который eval/editor_tier/panel.py:193-196 объявляет дефектом эксп-23 `CTRLfloorA ≡ T1`). Все замеренные полы этого рига — n=16 (power.py:35-40; эксп-22 пол = 32 файла tp2-floor-p1/p2 = 16×2, power.py:30), так что трактовка «8 пар» вдвое режет n пола против всех прайоров. (6) Масштаб последствия занижен, а механизм назван неверно. Механизм: Д0.3 (строки 774-777) пере-классифицирует ось, если СВОЙ пол выйдет ХУЖЕ прайора, — пункта «пола нет → описательная» там нет; при отсутствии своего пола пре-рег просто не исполняется («Решает СВОЙ пол»), и вердикт оси повисает на заимствованном прайоре, который пре-рег сам отказывается считать решающим. Практика жёстче формулировки находки: потолок ФД-A $0.885 (money_d.py:67) при потраченных $0.871904 (contour.py --plan) оставляет $0.0131 — пол Д4 не финансируется НИ В ОДНОЙ трактовке ($0.121 за 16 клеток, $0.242 парой), и это до того, как докупать A2 (0/32) и хвост A4 (22/32). Плюс пол ещё и не построен: contour.py:23 рекламирует `--floor`, а диспетчер contour.py:292-297 знает только --selftest/--run/--plan (grep floor по файлу даёт единственный хит — докстринг).",
|
||
"corrected": "Строка шумового пола Д4 финансирует ОДНУ генерацию на единицу там, где норма Д0.6 требует две, и пол Д4 не финансируется вовсе ни в одной трактовке. plan.py:75 кладёт `+ 16 * fixer` = $0.050 и число единиц пола не объявляет; единственная трактовка, согласная с братскими строками той же сметы (plan.py:82 `n3*edit` «пол» при n3=16 и plan.py:88 `n6*(…+edit)` при n6=9 — по 1 клетке на единицу) и со всеми замеренными полами рига (все n=16, power.py:30,35-40), — это 16 единиц по одной генерации, то есть запрещённый Д0.6 шаблон «боевая клетка + повтор» (тот самый дефект `CTRLfloorA ≡ T1`, eval/editor_tier/panel.py:193-196). Альтернативная трактовка «8 пар» нигде не заявлена и вдвое режет n пола против всех прайоров. По фактической медиане фиксера $0.00756 (100 клеток сырья) пара на 16 единиц стоит $0.242 против $0.050 в смете; из разрыва 2.4× ЦЕНОВАЯ часть (прогноз $0.00314 против факта $0.00756) объявлена заранее как прогноз множителя (plan.py:49-52) и находкой не является — не объявлено именно ЧИСЛО ГЕНЕРАЦИЙ. Тот же дефект в ФД-B (16 клеток пола на 16 единиц) и ФД-C (9 на 9), то есть строка не одна. Последствие сильнее заявленного и по другому механизму: Д0.3 пере-классифицирует ось, когда свой пол ХУЖЕ прайора, а не когда его нет, — при отсутствии пола несущий вердикт Д4 просто остаётся на прайоре, который пре-рег решающим не признаёт; при этом потолок ФД-A $0.885 (money_d.py:67) при потраченных $0.871904 оставляет $0.0131 — не хватает даже на 16 клеток ($0.121), и пол вдобавок не реализован (contour.py:23 обещает `--floor`, диспетчер contour.py:292-297 его не знает). Починка: считать пол как 2 генерации × объявленное число единиц по фактической цене и внести в запрос владельцу вместе с подъёмом ФД-A, назвав n пола явно."
|
||
}
|
||
},
|
||
{
|
||
"title": "«Два независимых пути счёта» в фазе Д не существует: оба пути читают одно и то же поле cost_usd из одних и тех же файлов",
|
||
"severity": "важно",
|
||
"evidence": "money_d.py:7 объявляет «два независимых пути счёта» свойством кассы фазы. Фактически `Guarded._led` и `Pack._led` — оба `buy.Ledger`, оба берут `float(r.get('cost_usd'))` с диска (buy.py:47). Настоящий второй путь — `role_topology/verify_report.py:66 independent_price` — в `eval/dovodka/` не вызывается ни разу (`grep -rn independent_price eval/dovodka/` → пусто). Более того, `eval/tenant_panel/roster.py:9` ссылается на `verify22.independent_price`, которой не существует нигде в репозитории (единственное определение — verify_report.py:66).",
|
||
"consequence": "Если бы прайс-таблица разъехалась с реальностью или `billed_output` ошибся классом биллинга, обе «независимые» кассы врали бы одинаково и согласованно — а гейт бы это сертифицировал (ровно класс §17.4 эксп-21, от которого касса и заводилась). Сегодня ущерба нет: я пере-считал все 148 клеток вторым путём вручную, 0 расхождений.",
|
||
"fix": "Либо позвать `verify_report.independent_price` по сырью фазы в селфтесте `money_d.py` (это $0 и десять строк), либо снять из шапки заявление о двух путях. Заодно поправить мёртвую ссылку `verify22.independent_price` в roster.py:9.",
|
||
"verdict": {
|
||
"line": "деньги",
|
||
"refuted": true,
|
||
"why": "ОПРОВЕРГНУТО по трём независимым основаниям, каждое проверено исполнением.\n\n1) ЭТО ОБЪЯВЛЕННОЕ И ГЕЙТОМ ОХРАНЯЕМОЕ НЕЗАКРЫТОЕ ТРЕБОВАНИЕ, А НЕ СКРЫТЫЙ ДЕФЕКТ. `eval/dovodka/requirements.md:114` — `| R76 | Деньги: итог по фазам ДВУМЯ путями счёта | — |`, в секции «ОТЧЁТ И СДАЧА». Легенда файла (requirements.md:18) и шапка гейта (`eval/conformance.py:15-20`): «`—` — улики ещё нет: в режиме плана это законно, в режиме сдачи — отказ». Прогнал сам: `eval/.venv/bin/python eval/conformance.py eval/dovodka/requirements.md --plan` → `[ОЖИДАЕТ ] R76 Деньги: итог по фазам ДВУМЯ путями счёта ← улика не объявлена`, итог «требований 89 · ожидают 58 · провалов 3 · СВЕРКА НЕ ПРОЙДЕНА». То есть тезис находки «а гейт бы это сертифицировал» прямо неверен: гейт фазы построен ПАДАТЬ на этом требовании в `--final`. Фаза стоит в середине покупок (A2 — ноль клеток, A4 остановлен гардом на 22 из 32), секция сдачи не начата, и второй путь в этой линии рига пишется в итог-скрипте на этапе отчёта, а не в кассе.\n\n2) НАХОДКА НЕВЕРНО ОПОЗНАЛА, ЧТО ТАКОЕ «ДВА ПУТИ». `Guarded._led` и `Pack._led` никогда не были двумя путями СЧЁТА — это два ПОТОЛКА (money.py:8-10, урок 2: «каждая покупка проходит ДВА гарда: фазовый и пакетный, оба проекционные»). Канонический второй путь линии — не `verify_report.independent_price`, а `itog22.py:227-228` (`def money_two_ways` / `h(\"ДЕНЬГИ — ДВА НЕЗАВИСИМЫХ ПУТИ\")`) и `itog23.py:94-95`; `grep -rn \"ДВА НЕЗАВИСИМЫХ\" eval/ --include=*.py` даёт только эти два. Соответственно и «починка» находки указывает не на тот прибор.\n\n3) ПОСЛЕДСТВИЕ НЕВЕРНО ПО СУЩЕСТВУ: заявленная «независимость» отсутствует и там, где второй путь РЕАЛИЗОВАН. `roster.py:142-146` `cost()` считает через `billed_output()` (roster.py:132-140), а «независимый» пере-счёт пака 23 (`itog23.py:98-107`) зовёт ТУ ЖЕ `ROSTER.billed_output` и ту же `ROSTER.CANDIDATES`; версия эксп-22 (`itog22.py:231-240`) переписывает правило руками, но берёт `R.CANDIDATES` и `R.REASONING_BILLING`. Значит оба названных находкой сценария — разъезд прайс-таблицы и ошибка класса биллинга в `billed_output` — прошли бы двухпутевую сверку и в паках 22/23. Внедрение недостающего пути в фазе Д не поймало бы ни одного из них.\n\nЭМПИРИКА (пере-проверил заявление находки своим кодом, $0): пере-считал все 148 клеток `~/books/dovodka/dv-*.json` вторым путём (CANDIDATES + REASONING_BILLING, правило выписано заново): леджер $1.139729 · пере-счёт $1.139729 · разница 5.8e-08 · макс расхождение клетки 5.0e-07 · моделей вне ростера 0. Все 148 клеток несут `prompt_tokens/cached_tokens/completion_tokens/reasoning_tokens/total_tokens` (0 без токенов), так что путь реализуем и ничего не меняет. Ни один вывод фазы не двигается, ни цента не потрачено впустую — по определению из правил ревью это не находка.\n\nФактическая неточность в улике: `eval/tenant_panel/verify22.py` СУЩЕСТВУЕТ (220 строк) — отсутствует только атрибут `independent_price` в нём; и это прозаический комментарий в зоне эксп-22 (`roster.py:9`), вне зоны фазы Д.\n\nЧТО ОСТАЁТСЯ ВЕРНЫМ (мелочь, не «важно»): предложение в докстринге `money_d.py:7` перечисляет «два независимых пути счёта» среди свойств наследуемого механизма, хотя `configure` кассы этого свойства не даёт — оно живёт в итог-скрипте пака. Формулировка унаследована дословно из `eval/editor_tier/money.py:5` и `eval/tenant_panel/money.py:70`, то есть это точность фразы предков, а не дефект фазы Д.",
|
||
"corrected": "Если оставлять след вообще — то в такой форме и с тяжестью «мелочь/косметика»: «Фраза `money_d.py:7` (унаследована дословно из `editor_tier/money.py:5` и `tenant_panel/money.py:70`) приписывает КАССЕ свойство \"два независимых пути счёта\", которое в этой линии рига живёт не в кассе, а в итог-скрипте пака (`itog22.py:227`, `itog23.py:94`). Уточнить формулировку до \"…механизм кассы: фриз-гейт, замок, проекционный сторож; второй путь счёта — в итоге пака (R76)\". Самого дефекта нет: второй путь фазы Д объявлен незакрытым требованием `requirements.md:114 R76` и механически охраняется `conformance.py --final`; пере-счёт 148 клеток даёт расхождение 5.8e-08 и не двигает ни одного вывода. Отдельно: когда R76 будут закрывать, стоит знать, что существующие реализации второго пути НЕ независимы от прайс-таблицы и (в паке 23) от `billed_output`, — заявленный класс защиты они не дают.»"
|
||
}
|
||
},
|
||
{
|
||
"title": "Класс «оплачено, но клетка не легла под своим именем» невидим кассе и оплачивается повторно при каждом ре-ране",
|
||
"severity": "важно",
|
||
"evidence": "buy.py:166-175: ответ без сообщения пишется в `{tag}.NOMSG.json` с ненулевым `cost_usd=priced(...)`, а `{tag}.json` не создаётся. Кэш-чек стоит на `{tag}.json` и в buy.py:139-141, и в money.py:228-230. Ошибочный вызов пишется в `{tag}.ERROR.json` с `cost_usd=0.0` (buy.py:154-155), хотя провайдер мог оттарифицировать сгенерированное. Записи не несут метки времени покупки (в клетке только `latency_s`), а mtime всего сырья перезаписан скопом: `stat` даёт 113 файлов в 2026-08-10 22:01:17 и 35 в 23:39:44.",
|
||
"consequence": "Каждый повторный `--run` по единице с NOMSG-исходом оплачивает её заново — деньги видны в леджере, но растут молча и без нового результата. Тот же класс уже стоил фазе инцидента 10.08 (7 оплаченных клеток уехали в `~/books/editor-tier`, касса показывала $0 — contour.py:56-63); в `editor-tier` их сейчас нет, а было ли это переносом или пере-покупкой, восстановить нечем: ни таймстампов в клетках, ни записи в docs/PROGRESS.md (там об инциденте одна строка 199 без числа).",
|
||
"fix": "Класть NOMSG под основным тегом (тогда кэш-чек его видит), писать в каждую клетку wall-clock `ts` покупки, и добавить в селфтест кассы проверку «сумма по .NOMSG/.ERROR = 0 или объявлена».",
|
||
"verdict": {
|
||
"line": "деньги",
|
||
"refuted": true,
|
||
"why": "Несущее утверждение заголовка — «невидим кассе» — ОПРОВЕРГНУТО исполнением, и находка сама себе противоречит («деньги видны в леджере» в поле «последствие»).\n\n1) КАССА ВИДИТ NOMSG. `Ledger.spent()` (eval/role_topology/buy.py:39-51) складывает `cost_usd` по `OUT.glob(pat)` для `prefixes` = TAGS фазы, а тег фазы — `dv-a-*.json` (eval/dovodka/money_d.py:55). `fnmatch('dv-a-a1-deadbeef.NOMSG.json','dv-a-*.json')` = True (проверил). Прямая проба на синтетическом каталоге: положил `dv-a-a1-deadbeef.NOMSG.json` с `cost_usd=0.0123` и `dv-a-a1-cafe.ERROR.json` с 0.0, подменил `buy.OUT`, `Ledger('t',1.0,('dv-a-*.json',)).spent()` вернул **0.0123**. То есть оплата NOMSG попадает и в фазовый потолок, и в пакетный (`Pack.prefixes` — те же глобы, money.py:88). Класс «оплачено и невидимо кассе» здесь не существует.\n\n2) МАСШТАБ = НОЛЬ. `ls ~/books/dovodka | grep -cE \"NOMSG|ERROR\"` → **0** при 148 клетках `dv-*.json` (a1 30, a3 64, a4 22, a6 32 — совпадает с объявленным состоянием). Ни одной клетки этого класса в фазе Д не куплено, ни одного доллара так не потрачено, ни один вывод не меняется. `money_d.py --report` даёт ФД-A 0.871904 / 0.89 и ПАК 1.139729 / 4.50 — ровно объявленные числа.\n\n3) ПОВТОРНАЯ ПОКУПКА ПРИ РЕ-РАНЕ — ОБЪЯВЛЕННОЕ ПОВЕДЕНИЕ, А НЕ ДЕФЕКТ, и предложенная починка возвращает уже исправленный баг. buy.py:151-153 дословно: «запись отказа кладётся ОТДЕЛЬНЫМ тегом: прошлая редакция писала её под тем же именем, и транзиентный таймаут навсегда отравлял клетку — пере-запуск читал ошибку из кэша и вызов не повторял». Починка «класть NOMSG под основным тегом (тогда кэш-чек его видит)» — это буквально возврат к той редакции.\n\n4) «В ДОКАХ НЕ СКАЗАНО» — НЕВЕРНО. Класс объявлен и оснащён гейтом в соседнем паке: eval/role_topology/judges.py:66-69 («отказы записаны отдельными `*.ERROR.json`, купленные голоса не отравлены») и eval/role_topology/verify_report.py:304-312 — секция «ОТКАЗЫ ПРОВОДА ЗАПИСАНЫ, А НЕ ПОТЕРЯНЫ» с двумя проверками: «отказы фильтра (N) записаны и объявлены в отчёте» и «отказы записаны ОТДЕЛЬНЫМ тегом (кэш успеха не отравлен)». Предлагаемая находкой проверка селфтеста уже существует в репозитории как прецедент.\n\n5) `cost_usd=0.0` НА ERROR-ПУТИ (buy.py:150-158). Ветка ловит исключение — объекта ответа нет, `r.usage` не существует, поэтому цену записать нечем в принципе; «провайдер мог оттарифицировать» — недоказуемая спекуляция без грунта. Сам класс уже стоит в трекере отдельной живой строкой: docs/PROGRESS.md строка 41, строка №78 «Леджер денег = НИЖНЯЯ граница: 2xx body decode failed (call IS billed)… живое число $0.015111 при леджере $0.114378», с готовым дизайном фикса. Это объявленное ограничение с числом, а не новая находка.\n\n6) ИНЦИДЕНТ 10.08 ПРИПИСАН НЕ ТОМУ МЕХАНИЗМУ и он исполнен как норма. Увод 7 клеток в `~/books/editor-tier` — это синглтон `buy` в `sys.modules` (contour.py:53-66), а не имя `.NOMSG`; он разобран в комментарии на 11 строк, закрыт жёстким ассертом contour.py:64-66 и продублирован двумя селфтестами (money_d.py:100 «покупки уходят в каталог фазы», contour.py:230 «buy.OUT совпадает с кассой фазы»), плюс своим коммитом 4f69810. `find ~/books/editor-tier -name 'dv-*'` → 0. Складывать это в один «класс» с NOMSG — подмена.\n\n7) МАСШТАБ ПО ТАЙМСТАМПАМ ЗАВЫШЕН. Отсутствие `ts` в клетке — верно (ключи клетки: arm, cached_tokens, completion_tokens, content, cost_usd, finish, latency_s, model, model_returned, places, prompt_tokens, reasoning_*, role, tag, total_tokens, uid — wall-clock нет). Но «mtime всего сырья перезаписан скопом» неточно: 22:01:17 накрывает ВЕСЬ `~/books` включая .epub книг и каталоги чужих паков (`stat ~/books/*` — editor-tier 22:01:17.99, epub 22:01:17.91), то есть это средовой bulk-copy, а не следствие buy.py; при этом более поздняя пачка mtime сохранила и она информативна: 23:39:44 = ровно 32 клетки dv-f-a6 + 3 dv-a-a4, 22:01:17 = 30 a1 + 64 a3 + 19 a4. «Восстановить нечем» — преувеличение.\n\nИтого: заголовок ложен (касса видит), тяжесть «важно» не обоснована (0 клеток класса, $0 потерь, ни один вывод не двигается), «не сказано в доках» неверно (объявлено в buy.py, judges.py, verify_report.py, строке 78 трекера), а предложенная починка регрессивна.",
|
||
"corrected": "Уцелевшее зерно (косметика, не «важно»): клетки фазы Д не несут wall-clock метки покупки — только `latency_s` (проверено по ключам dv-a-a1-00e4c3496f.json). Восстановление хронологии опирается на mtime, а он для материала до 22:01:17 10.08 затёрт средовым копированием всего `~/books` (не кодом покупки); для покупок после — сохранён и информативен (23:39:44 = 32 dv-f-a6 + 3 dv-a-a4). Добавить `ts` в запись клетки — дешёвое улучшение аудируемости. Всё остальное в находке — либо ложно (невидимость кассе: `Ledger.spent` глобит `dv-a-*.json`, что матчит `*.NOMSG.json`; проба дала $0.0123), либо объявленное ограничение с записанным основанием (отдельный тег отказа — buy.py:151-153; ledger как нижняя граница — PROGRESS.md строка 78), либо нулевого масштаба (0 NOMSG и 0 ERROR клеток на 148)."
|
||
}
|
||
},
|
||
{
|
||
"title": "Правило «срабатывание гарда = СТОП и вопрос владельцу» не механизировано, и по печати нельзя отличить «денег не хватило» от «чинить нечего»",
|
||
"severity": "важно",
|
||
"evidence": "money_d.py:18 объявляет это законом исполнения. Механизма нет: buy.py:143-146 при отказе гарда печатает строку и возвращает `skipped`-запись, а `contour.py` cmd_run (строки 238-288) не проверяет её — цикл идёт к следующей единице и к следующему арму с той же исчерпанной кассой. Проверено $0-прогоном: из 10 непокрытых единиц A4 у 9 места есть (гард), у 1 (474f822806) мест нет (легитимный пропуск); у A1 оба непокрытых юнита дают 0 мест, то есть A1 полон. При этом `contour.py --plan` печатает обе ситуации одинаково: «A1: куплено 30 из 32», «A4: куплено 22 из 32».",
|
||
"consequence": "Фаза упёрлась в потолок и поехала дальше, а в отчётной печати это выглядит как обычная неполнота арма. Пре-рег требует объявить непокрытые клетки числом и причиной; сейчас причина в артефактах не сохраняется вовсе — я восстанавливал её пере-прогоном canon_gaps.",
|
||
"fix": "На `skipped` из кассы — прерывать прогон с ненулевым кодом и печатать «СТОП по потолку, вопрос владельцу»; в `cmd_plan` печатать разложение непокрытых клеток на «мест нет» и «упёрлись в потолок».",
|
||
"verdict": {
|
||
"line": "деньги",
|
||
"refuted": false,
|
||
"why": "Пытался опровергнуть по четырём линиям — не вышло ни по одной.\n\n1) Механизм. `eval/dovodka/money_d.py:16-18` объявляет «**срабатывание проекционного гарда = СТОП и вопрос владельцу**», причём с оговоркой «правило исполнения жёсткое и записано ЗДЕСЬ, а не в прозе» — то есть док претендует именно на механизацию. Механизма нет: `eval/role_topology/buy.py:143-146` — `ok, why = led.afford(); if not ok: print(why); return dict(..., skipped=True, finish=\"skipped\")`; обёртка `eval/tenant_panel/money.py:246-249` возвращает эту запись как обычный `rec`; `contour.py` вызывает `MONEY.purchase` в четырёх местах (256, 266, 273, 285) и НИ РАЗУ не смотрит на возврат. Цикл `for arm ... for u in us` (236-286) идёт дальше. Файл при `skipped` не пишется — значит и следа причины в сырье не остаётся: `ls ~/books/dovodka` даёт только `dv-*.json`, `canon-dissect.json`, `razbiratelstvo-sudi-10-08.txt` — ни одного `.ERROR.json`/`.NOMSG.json`/skipped-артефакта.\n\n2) Числа автора — воспроизведены точно. $0-скриптом поверх `contour.py` (импорт, без покупок): A4 непокрыто 10 единиц, у 9 из них `canon_gaps(src, base_a0)` даёт 1-2 места, у `474f822806` — 0; A1 непокрыто 2 (`474f822806`, `9b16c9c9a7`), у обоих 0 мест → A1 полон. Что причина именно гард, а не иное, подтверждено прямым $0-вызовом кассы: `Guarded(\"ФД-A\").afford()` → `(False, '[СТОП ФД-A эксп-22] потрачено $0.871904 + ожидание $0.015945 = $0.887849 > потолок $0.89')`.\n\n3) Печать. `eval/dovodka/contour.py --plan` (реально выполнен) печатает «A1: куплено 30 из 32» и «A4: куплено 22 из 32» одной формой; разложения на «мест нет» / «упёрлись в потолок» нет (`contour.py:173-186`). Ситуации действительно неразличимы.\n\n4) Не объявлено ли уже. Грепом по `docs/` и `eval/dovodka/requirements.md` следов «A4 22/32» / причины нет; последняя запись фазы (`git show 90c23cb -- docs/PROGRESS.md`) сделана до покупки A4 и о ней молчит.",
|
||
"corrected": "Находка верна; уточняю масштаб и две неточности формулировки.\n\nШИРЕ, ЧЕМ СКАЗАНО. Дело не в 9 клетках A4. Касса ФД-A исчерпана ($0.871904 из $0.89, гард отказывает уже сейчас), а по смете она куплена под «A1·A2·A3·A4, n=32 + СВОЙ ПОЛ» (`eval/dovodka/plan.py:76-77`, Д0.8 отчёта). Не куплены: 9 клеток A4, ВЕСЬ арм A2 (32 клетки, ноль) и собственный шумовой пол Д4. Пол — не украшение: Д0.3 пре-рега говорит «РЕШАЕТ СВОЙ ПОЛ», и ось пере-классифицируется в описательную по нему; Д0.6 требует пол парой отдельных генераций. То есть исчерпанная касса блокирует не «полноту одного арма», а сам порог, которым несущая ось Д4 классифицируется, — и это в докладе не сказано нигде. ФД-F тоже уже отказывает ($0.267825 из $0.28), но A6 там 16/16, так что она не блокер.\n\nТОЧНЕЕ ПО ФАКТАМ. (а) «причина в артефактах не сохраняется вовсе» — верно про машинные артефакты, но для A1 причина всё же записана прозой в хендоффе `/home/ubuntu/CONTINUATION_PROMPT.md:249` («2 единицы без флагов — чинить нечего, объявить»); для A4 не записана нигде. (б) «цикл идёт к следующему арму с той же исчерпанной кассой» — точно для A1-A4 (все на ФД-A); A6 берёт отдельную кассу ФД-F (`contour.py:239`), и его гардом ФД-A не останавливает. (в) На живом прогоне отказ всё-таки виден оператору: `buy.py:144` печатает `[СТОП ФД-A эксп-22] ...` на каждую отказанную клетку. Отсутствуют три вещи: остановка прогона, персист причины и разложение в `--plan`.\n\nПОЧИНКА (уточнённая): на `skipped` из кассы — прерывать `cmd_run` ненулевым кодом с «СТОП по потолку, вопрос владельцу»; писать отказ отдельным тегом `*.SKIPPED.json` (как уже делается для ERROR/NOMSG), чтобы причина жила в сырье; в `cmd_plan` печатать непокрытые клетки разложением «мест нет / упёрлись в потолок» и отдельной строкой — что ФД-A ещё должна A2 и свой пол."
|
||
}
|
||
},
|
||
{
|
||
"title": "Проекционный гард резервирует максимум по всему паку вместо цены роли, и остановил A4 на клетке, которая в остаток влезала",
|
||
"severity": "мелко",
|
||
"evidence": "money.py:105-127 `model_expect`: при `len(prices) >= 2` возвращает `max(prices)` по всем клеткам модели во всём паке (глоб dv-*.json), без различения роли. Прогон: ожидание $0.015945 — это самая дорогая клетка A4 из всех; p95 фазы (`_led.expect()`) при этом $0.012572, а медиана клетки A4 $0.007937. Итог: 0.871904 + 0.015945 = 0.887849 > 0.885 при остатке потолка $0.013096.",
|
||
"consequence": "Гард отработал верно по своему определению и денег не потерял, но зарезервировал 2.0× медианы роли: одна клетка A4 (медиана $0.0079) в остаток $0.0131 помещалась. Ценой этого стала одна недокупленная клетка, а не деньги; при смешанных ролях (критик $0.0052 против фиксера $0.0089) перекос будет расти.",
|
||
"fix": "Брать ожидание как p95 по (модель, роль) следующего вызова, а не max по паку; роль уже есть в каждой записи (`role`) и передаётся в purchase как extra.",
|
||
"verdict": {
|
||
"line": "деньги",
|
||
"refuted": true,
|
||
"why": "ОПРОВЕРГНУТО ИСПОЛНЕНИЕМ по трём независимым линиям; верна только описательная часть цитаты, а причинный вывод и починка — ложны.\n\n1) ГЛАВНОЕ: предложенная починка НЕ меняет исход. Заголовок утверждает, что гард остановил A4 на клетке, которая «в остаток влезала», и что лечится это переходом на p95 по (модель, роль). Посчитал все варианты на реальном сырье ~/books/dovodka (eval/.venv/bin/python, агрегация 148 клеток dv-*.json), spent(ФД-A)=0.871904, потолок 0.885:\n max по паку 0.871904+0.015945 = 0.887849 → СТОП\n max по (модель, роль=fixer) 0.871904+0.015945 = 0.887849 → СТОП ← ровно то же число\n p95 по (модель, роль=fixer), n=100 0.871904+0.013281 = 0.885185 → СТОП\n p95 по A4-fixer, n=22 0.871904+0.015691 = 0.887595 → СТОП\nВсе четыре — отказ. Пропускает только МЕДИАНА (0.879841), но медиану находка не предлагает; она предлагает p95, и p95 тоже стопит. Значит «остановил клетку, которая влезала» не следует из механизма, названного виновным.\n\n2) Различение роли здесь — различие без разницы. По всем 148 клеткам модель ОДНА: deepseek-v4-pro (агрегация выше). Максимумы: (deepseek-v4-pro, fixer) n=100 max=0.015945; (deepseek-v4-pro, critic) n=48 max=0.013235. Решающие $0.015945 — это и есть клетка роли fixer, то есть роли покупаемого вызова. Формулировка «резервирует максимум по всему паку ВМЕСТО цены роли» подразумевает, что цена роли иная; фактически она побайтно та же. Перекос «критик $0.0052 против фиксера $0.0089» существует (A3 critic med 0.005190, A6 fixer med 0.008875), но на этот стоп не влияет никак: стопнутый вызов — fixer.\n\n3) Это объявленная норма, а не дефект. money_d.py:17-19: «**срабатывание проекционного гарда = СТОП и вопрос владельцу.** Резать ось, панель или кандидата решением сессии ЗАПРЕЩЕНО заказом». То же в отчёте docs/experiments/23-editor-tier.md:869-872 (Д0.8): резерв $0.03 объявлен риском ДО покупок, «Срабатывание проекционного гарда = СТОП и вопрос владельцу, а не сокращение оси решением сессии». Гард сделал ровно то, что пре-регистрировано.\n\n4) Починка реинтродуцирует известную дорогую регрессию. Докстринг money.py:105-115 (`model_expect`) прямо фиксирует, ПОЧЕМУ там не p95: «⚠ Заведено после того, как потолок Ф1 был пробит ($1.087758 против $1.05). Механизм пробоя: проекционный гард брал p95 УЖЕ КУПЛЕННЫХ вызовов». Селфтест money_d.py:118-123 сторожит именно это («гард видит цену дорогой модели, а не p95 прошлого»). Консервативность max — объявленный выбор, а не недосмотр. И эмпирика на этом же сырье показывает, что запас не бутафорский: 2 из 22 клеток A4 (9%) дороже остатка $0.013096 (0.015691 и 0.015945) — медианный гард пробивал бы санкционированный владельцем потолок с вероятностью ~9% на клетку.\n\n5) Ни один вывод не меняется, и денег не потеряно (это признаёт и сама находка). Арму A4 до полноты не хватало 10 клеток; 10 × медиана 0.007937 = $0.079 против остатка $0.013096 — одна лишняя клетка дала бы 23/32 вместо 22/32, статус «арм недокуплен» тот же.\n\nЧто остаётся верным и уже сказано в коде: `model_expect` (money.py:105-127, `if len(prices) >= 2: return max(prices)`) действительно не различает роль и берёт max по глобу пака — цитата и номера строк точны, `role=` действительно передаётся в purchase (contour.py:257, 268, 275, 286). Но это описание объявленного консервативного дизайна с нулевым эффектом на данный прогон, а не находка: не меняет вывода, не тратит денег и не противоречит докам."
|
||
}
|
||
},
|
||
{
|
||
"title": "Единица 63ab55ac5c куплена в армах A1 и A3 поверх черновика, который штатный гейт проекта бракует как «эхо исходника»: оба вывода — китайский текст, попадающий в судейскую пачку несущей оси Д4",
|
||
"severity": "критично",
|
||
"evidence": "$ eval/.venv/bin/python — импорт contour.py: base_draft('63ab55ac5c') = 2243 знака, 80.2% иероглифов (у остальных 31 единицы 0.0%); bakeoff.draft_reject_reason(этот текст) → 'эхо исходника'. Клетки: dv-a-a1-63ab55ac5c.json content[:120] = '青龙国,帝都。\\n\\nРезиденция левого канцлера深处的书房…' (1727 иероглифов из 2490), dv-a-a3-63ab55ac5c.json = '青龙国,帝都。\\n\\n左相府深处的书房…' (1804 из 2249), dv-a-a3-crit-63ab55ac5c.json — критика написана ЦЕЛИКОМ по-китайски. Механизм: contour.py:83 `return t if t.strip() else PAN23.draft_b(uid)` — для 16 НОВЫХ единиц база берётся через panel.py:112 `draft_b()`, который читает файл СЫРЫМ, тогда как для 16 старых P22.draft_text фильтрует через draft_reject_reason. Селфтест contour.py:201-202 проверяет только непустоту («якорный черновик есть у всех»), EXIT=0. Эксп-23 §8 п.2 (23-editor-tier.md:352) уже объявил ровно эту клетку эхо-миной и объявил гейт подключённым — фаза Д его обошла.",
|
||
"consequence": "$0.020019 оплачено за мусор; но главное — не деньги: A1 и A3 суть носители H-2а и H-2б (главная ставка владельца), и в их пачку идёт единица, где «перевод» на 70-80% китайский. Судья поставит ей катастрофу, A0 на той же единице здоров (8167 знаков, 0% CJK) — то есть дефект рига даёт большой отрицательный выброс в контрасте A1/A0 и A3/A0 при MDE оси 1.29, смещая вывод ПРОТИВ гипотез владельца. Класс не единичный: все 16 новых единиц заходят в контур без эхо-гейта.",
|
||
"fix": "В base_draft() пропускать вход через bakeoff.draft_reject_reason (как это делает P22.draft_text) и падать громко; единицу 63ab55ac5c либо исключить из Д4 с объявлением в отчёте, либо пере-купить годный черновик; в cmd_selftest добавить проверку «каждая база проходит эхо-гейт», а не «непуста»; три уже купленные клетки этой единицы аннулировать.",
|
||
"verdict": {
|
||
"line": "посылки-заказа",
|
||
"refuted": false,
|
||
"corrected": "Фаза Д купила армы A1 и A3 (критик+фиксер) на единице 63ab55ac5c поверх якорного черновика, который штатный гейт проекта бракует как «эхо исходника»: contour.base_draft() для 16 НОВЫХ единиц берёт базу через panel.py:112 draft_b() сырым, тогда как для 16 старых P22.draft_text (tenant_panel/panel.py:130) фильтрует через bakeoff.draft_reject_reason. Итог: три клетки на $0.020019, где выходы «фиксера» на 69–80% китайские (dv-a-a1: 1727 иероглифов из 2490; dv-a-a3: 1804 из 2249; критика dv-a-a3-crit написана по-китайски). A0 на той же единице здоров (8167 знаков, 0 иероглифов), поэтому единица даст большой отрицательный выброс в контрастах A1/A0 и A3/A0 — носителях H-2а и H-2б — при MDE оси Д4 1.29, то есть смещение ПРОТИВ гипотез владельца. Селфтест это не ловит: contour.py:201-202 проверяет только непустоту, EXIT=0. Две поправки к масштабу: (1) судейской пачки Д4 ещё не существует — сборщика в eval/dovodka нет, отчёт обрывается на пре-реге Д0 (23-editor-tier.md:896), — так что заражение пока потенциальное, но ничем не отфильтровано и по умолчанию попадёт в пачку; (2) реализованное заражение — ровно 1 единица / 3 клетки, а не класс: base_a0 и base_draft2 проходят гейт на всех 32 и 16 соответственно (проверено), у 16 новых единиц отсутствие гейта — экспозиция, а не факт. В фазе Д это нигде не объявлено: греп «63ab» по docs/ даёт единственный хит — 23-editor-tier.md:352 (§8 п.2 ПАКА 23, где измерена чувствительность вывода того пака и единица оставлена осознанно); в пре-реге Д0 (719-896) и в нормах рига Д0.6 ни единицы, ни нормы «база проходит эхо-гейт» нет.",
|
||
"why": "Проверено исполнением, опровергнуть не удалось. (1) Прогон по всем 32 единицам через contour.base_draft + bakeoff.draft_reject_reason: единственная забракованная — 63ab55ac5c, 2243 знака, 80.2% ханьцзы, вердикт 'эхо исходника'; у остальных 31 доля CJK 0.0% (у 474f822806 0.1%), вердикт пуст. (2) Механизм: eval/dovodka/contour.py:83 `return t if t.strip() else PAN23.draft_b(uid)`; исполнено P22.draft_text(ANCHOR,'63ab55ac5c') -> '' (новая единица), значит база идёт через eval/editor_tier/panel.py:112 draft_b() — сырое чтение json без гейта; у старых гейт есть в eval/tenant_panel/panel.py:130 `if c and not BO.draft_reject_reason(c)`. Гейт в eval/editor_tier/panel.py:98 подключён только в цикле покупок фазы B, но не в draft_b(), которую зовёт фаза Д. (3) Клетки из ~/books/dovodka: dv-a-a1-63ab55ac5c.json $0.012464 places=8, 1727/2490 иероглифов (69.4%); dv-a-a3-63ab55ac5c.json $0.004923 places=22, 1804/2249 (80.2%); dv-a-a3-crit-63ab55ac5c.json $0.002632, контент по-китайски. Сумма = $0.020019, сходится до цента. (4) base_a0('63ab55ac5c') = 8167 знаков, 0 иероглифов, draft_reject_reason пуст — асимметрия A1/A0 и A3/A0 реальна. (5) `eval/.venv/bin/python eval/dovodka/contour.py --selftest` -> все OK, «ХАРНЕСС ГОДЕН», EXIT=0; проверка на строках 201-202 только .strip(). (6) Объявленности в фазе Д нет: `grep -rn \"63ab\" docs/ --include=*.md` -> единственный хит 23-editor-tier.md:352. (7) Дополнительно проверено (сужает класс, но не отменяет находку): draft_reject_reason по base_a0 всех 32 и base_draft2 всех 16 старых -> пустые списки, то есть заражена только базовая ветка черновика."
|
||
}
|
||
},
|
||
{
|
||
"title": "Проекционный гард ФД-A сработал и молча срезал арм A4 (22 из 32), при этом A2 не куплен вовсе, свой шумовой пол не куплен, ФД-F исчерпан на одном контуре из двух — а СТОПа и вопроса владельцу, которых требует заказ, нигде нет",
|
||
"severity": "критично",
|
||
"evidence": "$ eval/.venv/bin/python eval/dovodka/money_d.py → ФД-A 0.871904 при потолке 0.885, ФД-F 0.267825 при 0.283. $ contour.py --plan → «A1: куплено 30 из 32 · A2: 0 из 32 · A3: 32 из 32 · A4: 22 из 32 · A6: 16 из 16». Пересчитал места у 10 недокупленных единиц A4: у 9 из 10 места ЕСТЬ (1–2 канон-потери), то есть пропуск не по «чинить нечего», а по деньгам. Гард по построению НЕ останавливает: eval/role_topology/buy.py:143-146 — `ok, why = led.afford(); if not ok: print(why); return dict(..., skipped=True)`; contour.py:236-288 возврат не смотрит и продолжает цикл. Смета промахнулась: plan.py печатает «фиксер $0.00314», факт — медианы $0.00686 (A1) / $0.00741 (A3) / $0.00794 (A4) / $0.00888 (A6), то есть в 2.2–2.8×. Заказ, строка 24 и money_d.py:17: «срабатывание проекционного гарда = СТОП и вопрос владельцу». В docs/PROGRESS.md:196-197 последняя запись полигона — «A1 30/30, A3 в работе, пакет $0.234846 из $4.50»; о стопе A4, об исчерпании ФД-A и ФД-F ни строки при фактических $1.139729.",
|
||
"consequence": "Несущая ось Д4 не может быть закрыта в объявленных потолках: семейство контрастов пре-рега Д0.5 — пять штук (A1/A0·A2/A0·A3/A0·A4/A0·A6/A0), из них A2 отсутствует полностью, A4 неполон, шумового пола нет — а без своего пола порог различимости брать неоткуда (Д0.6). A6 объявлен носителем H-1 «оба контура», куплен только смысловой контур, на флаговый в ФД-F осталось $0.015 при потребности ~$0.13. Итог: Холм по пяти контрастам физически не считается, и решение о доборе принято молчанием сессии, а не владельцем — ровно то, что заказ называет «резать ось решением сессии».",
|
||
"fix": "Пинг владельцу с числами: ФД-A нужно +$0.30…0.40 (A2 32 клетки + A4 10 клеток + пол), ФД-F +$0.13, либо явное сокращение состава армов его словом. В buy.purchase на непрохождении гарда — SystemExit, а не skipped-запись; в сырьё писать маркер «арм срезан потолком», чтобы неполнота арма была видна из данных, а не только из stdout.",
|
||
"verdict": {
|
||
"line": "посылки-заказа",
|
||
"refuted": false,
|
||
"corrected": "Смета фиксера промахнулась в 2.2–2.8× (plan.py «фиксер $0.00314» против замеренных медиан 0.006865/0.007411/0.007937/0.008875), и из-за этого потолок ФД-A $0.885 не вмещает даже уже объявленный состав арм: A1 $0.226944 + A3 $0.451476 + A4 на все 31 живую единицу ≈$0.273 = ≈$0.95 > $0.885, а сверх того не куплены A2 (32 клетки) и СВОЙ шумовой пол, обязательный по Д0.6. Остаток ФД-A — $0.013 при потребности ≈$0.39; остаток ФД-F — $0.0152 при потребности ≈$0.14 на второй (флаговый) контур A6. Ось Д4 в объявленных потолках закрыть нельзя, семейство Холма из пяти контрастов не считается, и решение о доборе или о сокращении состава — владельца. ⛔ Механизм и событие в исходной формулировке НЕВЕРНЫ: проекционный гард ФД-A НЕ срабатывал и A4 не срезал. Проверка объектом кассы: spent 0.871904 + expect 0.012572 = 0.884476 ≤ 0.885, afford=(True,''), то есть прогон сейчас купил бы следующую клетку; аргумент не зависит от порядка (spent монотонен, итог фазы 0.871904 — верхняя граница на любой момент), строки «[СТОП ФД-A» нет ни в докax, ни в сырье. A4 недокуплен сплошным хвостом 23–31 плюс единица с 0 мест — подпись оборванного передачей сессии прогона: CONTINUATION_PROMPT.md §8 держит «[ ] A4», «[ ] A2», «[ ] A6», «[ ] свой шумовой пол Д4» как ЗАЯВЛЕННУЮ открытую очередь, а не как молчаливый срез. A2 = 0 не по деньгам, а из-за уже известной Д-1 (translator_msgs зовётся одним аргументом) — добор денег его не купит. Правило «срабатывание гарда = СТОП и вопрос владельцу» (23-editor-tier.md:871, money_d.py:17) не нарушено, потому что триггер не наступил, а заказ (POLYGON_EXP2223_REDO_SESSION_PROMPT.md:23-24) прямо велит «спрашивать при срабатывании стопа, а не по проекции». Реально не сделано другое и меньшее: устаревшая на 4.9× запись в docs/PROGRESS.md:194-197 ($0.234846 против фактических $1.139729) и отсутствие маркера неполноты арма в сырье — buy.py:143-146 возвращает skipped-словарь, на диск его не пишет, а contour.py:236-288 возврат не читает, так что будущее срабатывание гарда останется видимым только в stdout.",
|
||
"why": "Проверял исполнением, не формулировкой. (1) Гард: `eval/.venv/bin/python -c` с загрузкой eval/dovodka/money_d.py → «ФД-A spent 0.8719040000000001 expect 0.012572 afford (True, '')» и «ФД-F spent 0.267825 expect 0.013758 afford (True, '')» — при CEILINGS ФД-A 0.885 (money_d.py:67-68) сумма 0.884476 ≤ 0.885, гард РАЗРЕШАЕТ следующую покупку, то есть сработать он не мог: Ledger.spent монотонен (buy.py:39-51), итог фазы 0.871904 — верхняя граница на любой момент прогона, а expect = p95 по 116 ценам (buy.py:53-58). Проигрыш всей ленты 116 клеток ФД-A по mtime дал afford=True на каждом шаге. `grep -rn \"СТОП ФД-A\" docs ~/books/dovodka` — пусто. (2) Подпись недокупа: мой прогон по units() печатает наличие клеток по индексу — A4 отсутствует на индексе 8 и сплошным хвостом 23..31, что есть оборванный прогон; /home/ubuntu/CONTINUATION_PROMPT.md §8 (строки 247-252) держит «[ ] A4», «[ ] A2», «[ ] A6», «[ ] свой шумовой пол Д4» как объявленную очередь. (3) A2: eval/tenant_panel/prompts.py:104 `def translator_msgs(src: str, block: str | None, en: bool = False)` против зова одним аргументом в eval/dovodka/contour.py:252 — причина нуля не деньги (известная Д-1). (4) Числа находки подтвердились: мой пересчёт canon_gaps по base_a0 у 10 недокупленных A4 дал места у 9 (474f822806 — 0); медианы по ~/books/dovodka: A1 fixer 0.006865, A3 fixer 0.007411, A4 fixer 0.007937, A6 fixer 0.008875 против «фиксер $0.00314» из `eval/.venv/bin/python eval/dovodka/plan.py`; суммы армов A1 0.226944, A3 0.199451+0.252025, A4 0.193484 — отсюда ≈$0.95 > $0.885 без A2 и без пола. (5) Правило про СТОП: docs/experiments/23-editor-tier.md:871 и eval/dovodka/money_d.py:17 привязывают его к СРАБАТЫВАНИЮ гарда, а docs/POLYGON_EXP2223_REDO_SESSION_PROMPT.md:23-24 — «спрашивать при срабатывании стопа, а не по проекции»; триггер не наступил. (6) docs/PROGRESS.md:194-197 — «$0.234846 из $4.50» при фактических $1.139729 (money_d.py --report)."
|
||
}
|
||
},
|
||
{
|
||
"title": "Счётчик агент-сессий фазы показывает 0 из 80 при не менее чем 11 фактически запущенных суб-агентах — воспроизведён дефект эксп-23 §6, который заказ прямо запретил воспроизводить и который фаза объявила починенным",
|
||
"severity": "критично",
|
||
"evidence": "$ eval/.venv/bin/python eval/dovodka/runs.py → «агент-сессий израсходовано 0 из 80»; журнал runs.py:44 LEDGER = ~/books/dovodka/agent-runs.json — файла на диске нет ($ ls ~/books/dovodka | grep agent-runs → пусто). При этом docs/PROGRESS.md:206-207 описывает «Разбирательство восьми агентов», строка 231 — «Адверсариальное ревью трёх линий (снизу вверх · сверху вниз · приёмка Fable-5)», строка 60 хендоффа — «Найдено многоагентным разбирательством 10.08». Заказ, строки 25-26: «Кап агент-сессий: 80. Счётчик пишет запись ДО запуска суб-агента (не --ingest пост-фактум — дефект эксп-23 §6 не воспроизводить)». PROGRESS:227 объявляет: «В фазе Д починено механизмом — runs.py пишет ДО запуска». Реестр R7/R60 закрывает требование уликой `runs.py --selftest` (EXIT=0) — селфтест проверяет механизм на своём тестовом журнале (runs.py:187 подменяет LEDGER на SELFTEST-agent-runs.json), а не факт вызова.",
|
||
"consequence": "Кап 80, поставленный владельцем, не исполняется: израсходовано ≥11 сессий, учтено 0, и к судейству фаза подойдёт с неизвестным остатком. Ровно тот класс, за который пак 23 получил пункт CONFIRM/DENY («на диске 20 записей против 58 фактических»), объявлен закрытым при живом дефекте — то есть отчёт фазы будет нести неверное число сессий.",
|
||
"fix": "Звать runs.claim() перед КАЖДЫМ запуском суб-агента (ревью/разбирательство/приёмка, не только судейство), задним числом восстановить и объявить фактическое число сессий фазы, а улику R7 заменить на проверку непустоты боевого журнала ~/books/dovodka/agent-runs.json, а не селфтест.",
|
||
"verdict": {
|
||
"line": "посылки-заказа",
|
||
"refuted": true,
|
||
"corrected": "Понижение до документарного пробела, не дефекта: единица капа объявлена фазой как СУДЕЙСКАЯ сессия (`docs/experiments/23-editor-tier.md:824` Д0.6, `/home/ubuntu/CONTINUATION_PROMPT.md:43-45`), тогда как заказ (`docs/POLYGON_EXP2223_REDO_SESSION_PROMPT.md:25-26`) пишет «агент-сессий» без квалификатора, а ратифицированное тем же заказом (п.4, строка 138) число 58 эксп-23 включает слагаемое «адверсариальное ревью 1» (`23-editor-tier.md:272-273`). Фаза сузила единицу до судейских сессий и не объявила это сужение; ревью-агенты фазы (проверено: `agentCount=8` в `~/books/dovodka/razbiratelstvo-sudi-10-08.txt` + три линии ревью, `docs/PROGRESS.md:231`) в кап не попадают. Тяжесть — низкая, документарная: денег это не стоит ($0-судейство, CONTINUATION_PROMPT:43), ни одного вывода не двигает, ни одного числа в отчёт ещё не внесло. Правильная починка — не задним числом «восстанавливать сессии», а спросить владельца, считает ли кап 80 не-судейских агентов, и записать ответ в Д0.6.",
|
||
"why": "ЗАГОЛОВОК НЕВЕРЕН: дефект эксп-23 §6 НЕ воспроизведён, потому что в фазе Д не запущено НИ ОДНОЙ судейской сессии — механизм не обойдён, до него не дошли.\n\n1. Что считает журнал — объявлено. `docs/experiments/23-editor-tier.md:824` (Д0.6): «**Судейские сессии регистрируются ДО запуска** (`eval/dovodka/runs.py`, кап 80, атомарный O_CREAT|O_EXCL-замок…)». То же в хендоффе, `/home/ubuntu/CONTINUATION_PROMPT.md:43-45`: «Судейство — агент-сессиями ($0)… Кап агент-сессий 80, счётчик пишет запись ДО запуска суб-агента». Та же единица — норма предыдущего пака: `docs/experiments/22-tenant-panel.md:609` «План агент-запусков (кап промта ≤60; **1 запуск = одна судейская сессия суб-агента**)». Это объявленное ограничение, а не тихая подмена.\n\n2. Судейских сессий в фазе Д НОЛЬ — проверено инвентарём сырья:\n`$ ls ~/books/dovodka/ | grep -v '^dv-'` → только `canon-dissect.json` и `razbiratelstvo-sudi-10-08.txt`. Ни `*-JUDGES.json`, ни каталогов голосов, ни `aj-*`. Всё остальное — 148 платных клеток покупки (`dv-a-a1` 30, `dv-a-a3` 32 + `dv-a-a3-crit` 32, `dv-a-a4` 22, `dv-f-a6` 16 + crit 16). Значит «израсходовано 0 из 80» — ПРАВДА про то, что журнал считает, а не ложь.\n\n3. Дефект эксп-23 §6 по существу другой. `23-editor-tier.md:285-288`: «на диске 20 против 58 фактических… `log_run` вызывается из `--ingest`, то есть ПОСЛЕ суб-агента… Проход `tier` не покрыт вовсе: во всех его голосах стоит `judge='?'`». Там судейские сессии РЕАЛЬНО шли и терялись, вместе с атрибуцией голосов. Здесь терять нечего: голосов нет. Улика «файла agent-runs.json нет» (`ls ~/books/dovodka/agent-runs.json` → No such file) равносильна «claim ни разу не звался», а не «звался поздно».\n\n4. Утверждение «фаза объявила дефект закрытым при живом дефекте» — пере-чтение источника. `docs/PROGRESS.md:227` говорит буквально: «В фазе Д починено механизмом — `runs.py` пишет ДО запуска, атомарный замок с проверкой живости PID, селфтест 16/16». Это утверждение о МЕХАНИЗМЕ, и оно верно: `$ eval/.venv/bin/python eval/dovodka/runs.py --selftest` → «ЖУРНАЛ ГОДЕН», EXIT=0, включая сценарии «claim пишет запись сразу», «кап отказывает при исчерпании», «сверх-капная сессия НЕ записана». Заявления «в фазе израсходовано N сессий» PROGRESS не делает нигде — я грепал (`grep -n \"агент-сесс\\|агент-запуск\" docs/PROGRESS.md docs/experiments/23-editor-tier.md eval/dovodka/requirements.md`): все хиты про эксп-22/23, ни одного про счёт фазы Д.\n\n5. Последствия, названные находкой, не наступают. «Отчёт фазы будет нести неверное число сессий» — числа в отчёте нет и оно не напечатано; «к судейству фаза подойдёт с неизвестным остатком» — остаток судейских сессий ровно 80, и первый же `claim` его начнёт считать (кап проверяется ДО записи, `runs.py:_claim_locked`). Денег не потрачено: судейство $0.\n\n6. Что в находке ВЕРНО и остаётся (см. поле corrected): факт ≥8 незарегистрированных не-судейских агентов подтверждён исполнением — `python3 -c \"json.load(...)\"` по `~/books/dovodka/razbiratelstvo-sudi-10-08.txt` даёт `agentCount: 8` и 8 записей `workflow_agent` (все `state=done`, модель `claude-opus-5[1m]`: диагноз зависания · разложение по осям · судить по текстам · калибровочный прибор · три опровергателя · свод). Плюс три линии ревью (`docs/PROGRESS.md:231`). И верно, что улика R7 (`eval/dovodka/requirements.md:34`) — селфтест, то есть проверка механизма на подменном журнале (`runs.py:187` LEDGER → `SELFTEST-agent-runs.json`), а не факта использования. Но это вопрос «что владелец включил в кап 80», а не воспроизведённый критический дефект: единица объявлена фазой заранее, ни одного вывода это не меняет и ни доллара не тратит."
|
||
}
|
||
},
|
||
{
|
||
"title": "Материал оси Д6 подменён на другую книгу без артефакта слова владельца; закоммиченный реестр требований по-прежнему называет исходную книгу, а улика R36 зелёная",
|
||
"severity": "важно",
|
||
"evidence": "Заказ, строки 112-113: «Материал: isekai_majutsushi_jp — контаминация-проба жильцами; непригоден → СТОП и пинг, замену без слова владельца не искать». Реестр (в git, коммит da5f4d0) requirements.md:69 R36 = «Материал isekai_majutsushi_jp». Код: eval/dovodka/material_ja.py:45 `SRC = Path.home()/'books'/'enkan_no_hate_ja.txt'`; $ material_ja.py печатает «источник enkan_no_hate_ja.txt», EXIT=0. Докстринг material_ja.py:15-17 утверждает «Замена подобрана по слову владельца 10.08», при этом docs/PROGRESS.md:237 (журнал той же сессии) говорит: «обработка источника прекращена; решение (механически выбросить помеченное либо сменить книгу) ЗА ВЛАДЕЛЬЦЕМ». Ни в docs/, ни в реестре, ни в отчёте артефакта санкции нет — только собственный хендофф /home/ubuntu/CONTINUATION_PROMPT.md:180. Файл material_ja.py при этом в индексе, но НЕ закоммичен ($ git status --porcelain eval/dovodka → «M eval/dovodka/material_ja.py»), то есть фриз-гейт покупок по ja его отвергнет. Отдельно: пробы контаминации ЖИЛЬЦАМИ в фазе нет вовсе — grep «контамина» по eval/dovodka даёт только строку сметы plan.py:80; material_ja.py делает лишь гардрейл, гейт прав и отбор.",
|
||
"consequence": "Ось H-4 будет замерена на книге, которую владелец не утверждал, при том что закоммиченный реестр — единственный документ, против которого валиден conformance-гейт, — называет другую книгу; расхождение «реестр ↔ код» гейт не видит, потому что улика просто запускает скрипт. Плюс требование пробы контаминации жильцами не исполнено ни для ja, ни (пока) для en, а без неё «невиданность» среза не доказана.",
|
||
"fix": "Получить и приложить артефакт слова владельца о замене книги (строка в PROGRESS «владелец 10.08 санкционировал enkan_no_hate_ja» либо ответ в переписке), пере-фризнуть реестр с новым названием книги отдельным коммитом ДО покупок по ja; завести пробу контаминации жильцами как отдельный платный шаг с уликой-артефактом.",
|
||
"verdict": {
|
||
"line": "посылки-заказа",
|
||
"refuted": false,
|
||
"corrected": "ПОДТВЕРЖДЕНО ЯДРО, ИСПРАВЛЕН МАСШТАБ И ДВЕ УЛИКИ.\n\nВерно и пере-проверено мной: материал оси Д6 в коде заменён (`eval/dovodka/material_ja.py:45` `SRC = ~/books/enkan_no_hate_ja.txt`; в HEAD было `isekai_majutsushi_jp.txt` — `git show da5f4d0:eval/dovodka/material_ja.py`), артефакта слова владельца в дереве нет (`grep -rn \"円環\\|n7233mn\\|enkan\" --include=*.md docs/ eval/ ~/CONTINUATION_PROMPT.md` → ТОЛЬКО собственный хендофф `/home/ubuntu/CONTINUATION_PROMPT.md:180-181`), а `docs/PROGRESS.md:237` той же сессии всё ещё говорит «решение … за владельцем». Закоммиченный реестр (`git status --porcelain eval/dovodka/requirements.md` → пусто; `git show HEAD:eval/dovodka/requirements.md:69`) называет старую книгу.\n\nСИЛЬНЕЕ, ЧЕМ СФОРМУЛИРОВАНО: зелёная не только R36, а И R37 — требование «замену без слова владельца НЕ искать» — и уликой ему служит запуск САМОЙ замены. Я выполнил обе улики дословно: `material_ja.py >/dev/null; echo $?` → 0 (R36 `test $? -le 1` проходит) и `material_ja.py | grep -q \"СТОП\\|OK \"` → 0 (скрипт печатает «[OK ] срабатываний нет»). То есть требование-запрет подтверждается исполнением запрещённого действия.\n\nНЕВЕРНАЯ УЛИКА (снять): «Файл material_ja.py … НЕ закоммичен, то есть фриз-гейт покупок по ja его отвергнет». Не отвергнет. `eval/tenant_panel/money.py:174-195` `_refuse_unfrozen()` идёт по стеку и проверяет `git`-чистоту ПЕРВОГО не-кассового кадра, после чего `return`; `material_ja.py` кассу не импортирует (`eval/dovodka/material_ja.py:37-43` — только hashlib/json/re/sys/pathlib), и его не импортирует никто (`grep -rn \"material_ja\" eval/ --include=*.py` вне самого файла → пусто). `eval/conformance.py:52-66` `frozen()` фризит ТОЛЬКО переданный ему файл реестра. Ни один гейт незакоммиченность material_ja.py не видит.\n\nОСЛАБИТЬ: «расхождение реестр↔код гейт не видит» — это ОБЪЯВЛЕННАЯ граница прибора, `eval/conformance.py:23-27`: «проверяет, что у требования ЕСТЬ проходящая улика, а не что улика доказывает именно это требование… подменить её ничего не мешает… не отменяет чтения». Новое здесь не «гейт слеп», а «две строки закоммиченного фриза стали ЛОЖНЫМИ и при этом печатают OK».\n\nМАСШТАБ ПОСЛЕДСТВИЯ МЕНЬШЕ ЗАЯВЛЕННОГО: ни один вывод не меняется — ось объявлена описательной разведкой ДО денег (`docs/experiments/23-editor-tier.md:762` «⛔ ОПИСАТЕЛЬНАЯ», `:812`), её бюджет ФД-C $0.154 (`:858`), покупочная ветка ja вообще не подключена (`grep -n \"ja-ru\\|'ja'\" eval/dovodka/*.py` → хиты только в `promptdiff.py:81,84`; в contour/runs ja нет). Под риском $0.154 и правдивость фриза, а не вердикт фазы.\n\nПРО КОНТАМИНАЦИЮ — верно, но с уточнением: реализации нет (`grep -rn \"контамина\" eval/dovodka` → только смета `plan.py:80`), однако для en реестр это ЛОВИТ сам (R24, улика «—» → в `--final` ПРОВАЛ, `conformance.py:94-95,144-146`); маскирует именно ja, потому что R36 склеивает ДВА требования (материал + проба) под одной уликой, проверяющей только отбор единиц.\n\nПОЧИНКА (сузить): (1) до любых ja-покупок пере-фризнуть отдельным коммитом строки R36/R37 с фактическим названием книги и приложить артефакт слова владельца — либо вернуть SRC на isekai и уйти в СТОП, как требует заказ (`docs/POLYGON_EXP2223_REDO_SESSION_PROMPT.md:112-113`); (2) расщепить R36 на «материал» и «проба контаминации жильцами» с раздельными уликами; (3) улику R37 переписать так, чтобы она не могла быть удовлетворена запуском заменённого материала.",
|
||
"why": "Ядро подтверждено исполнением: `git show da5f4d0:eval/dovodka/material_ja.py` (HEAD-версия = isekai_majutsushi_jp) против рабочего `eval/dovodka/material_ja.py:45` (enkan_no_hate_ja); `git status --porcelain eval/dovodka/requirements.md` → пусто, `git show HEAD:eval/dovodka/requirements.md` строка 69 = «Материал isekai_majutsushi_jp»; `grep -rn \"円環|n7233mn|enkan\" --include=*.md docs/ eval/ ~/CONTINUATION_PROMPT.md` → единственные хиты /home/ubuntu/CONTINUATION_PROMPT.md:180-181 (собственный хендофф сессии), в docs/ артефакта нет, docs/PROGRESS.md:237 оставляет решение за владельцем. Обе улики я выполнил: `material_ja.py >/dev/null; echo $?` → 0 и `material_ja.py | grep -q \"СТОП\\|OK \"` → 0, при печати «источник enkan_no_hate_ja.txt» — то есть зелёная не только R36, но и R37 («замену без слова владельца не искать»), уликой которому служит сам факт замены. Опровергнута лишь вспомогательная улика про фриз-гейт: eval/tenant_panel/money.py:174-195 проверяет git-чистоту только первого не-кассового кадра стека и сразу return, material_ja.py кассу не импортирует (строки 37-43) и не импортируется никем (`grep -rn \"material_ja\" eval/ --include=*.py`), а eval/conformance.py:52-66 фризит только переданный файл реестра. Слепота conformance к связке «требование↔улика» объявлена в его же докстринге (eval/conformance.py:23-27), поэтому находкой является не слепота гейта, а ложность закоммиченных строк R36/R37. Масштаб последствия ниже заявленного: ось Д6 объявлена описательной до денег (docs/experiments/23-editor-tier.md:762, 812), её бюджет $0.154 (строка 858), покупочная ветка ja не подключена (`grep -n \"ja-ru|'ja'\" eval/dovodka/*.py` → только promptdiff.py:81,84), выводов это не меняет. Отсутствие пробы контаминации подтверждено (`grep -rn \"контамина\" eval/dovodka` → только plan.py:80), но для en реестр её отсутствие ловит сам через улику «—» (conformance.py:94-95,144-146); маскировка касается только ja из-за склейки двух требований в R36."
|
||
}
|
||
},
|
||
{
|
||
"title": "Три улики реестра механически не проверяют то, что заявляют: экранированная в markdown-таблице вертикальная черта уходит в shell литералом, поэтому R37 зелена всегда, R55 падает синтаксисом, а R3 ищет отменённое число потолка",
|
||
"severity": "важно",
|
||
"evidence": "$ eval/.venv/bin/python eval/dovodka/material_ja.py \\| grep -q \"СТОП\\|OK \" → EXIT=0, при этом на экран печатается ПОЛНЫЙ вывод material_ja.py, то есть пайпа нет: строки «|», «grep», «-q», «СТОП|OK » ушли аргументами в python-скрипт и были проигнорированы. R55 (requirements.md:90): `test $(grep -l \"баннер фазы Д\" docs/experiments/*.md \\| wc -l) -ge 7` → conformance печатает «/bin/sh: 1: Syntax error: end of file unexpected». R3 (requirements.md:30): `grep -q \"САНКЦИЯ ВЛАДЕЛЬЦА .4.00\" eval/dovodka/plan.py` → ПРОВАЛ, потому что plan.py:10 и money_d.py:10 несут «САНКЦИЯ ВЛАДЕЛЬЦА $4.50». Итог прогона: «требований 89 · ожидают 58 · провалов 3».",
|
||
"consequence": "Требование R37 («материал непригоден → СТОП и пинг, замену не искать») числится закрытым уликой, которая не может упасть ни при каком состоянии дерева — и именно оно нарушено (находка выше). Требование о сверке пакетного потолка словом владельца улики не имеет вовсе. То есть прибор, заведённый ради «сверки с буквой заказа», по трём строкам из 77 сообщает не то, что проверяет.",
|
||
"fix": "Гонять улики через список аргументов без shell либо снимать экранирование `\\|` перед запуском (одна строка в conformance.check); R3 привязать к $4.50; R37 — к артефакту (запись в PROGRESS о СТОПе и ответ владельца), а не к запуску скрипта.",
|
||
"verdict": {
|
||
"line": "посылки-заказа",
|
||
"refuted": false,
|
||
"why": "Три наблюдаемых факта воспроизвёл, но механизм, направление и главный алармирующий тезис находки НЕВЕРНЫ.\n\nВОСПРОИЗВЁЛ (`eval/.venv/bin/python eval/conformance.py eval/dovodka/requirements.md --plan`, EXIT=1):\n`[ПРОВАЛ] R3 ← код 1` · `[OK] R37` · `[ПРОВАЛ] R55 ← /bin/sh: 1: Syntax error: end of file unexpected (expecting \")\")` · итог `требований 89 · ожидают 58 · провалов 3`. `grep -q \"САНКЦИЯ ВЛАДЕЛЬЦА .4.00\" eval/dovodka/plan.py` → EXIT=1, при том что plan.py:10 и money_d.py:10 несут `$4.50`. Реестр закоммичен и == HEAD (`git diff --quiet HEAD -- eval/dovodka/requirements.md` → 0).\n\nОПРОВЕРГНУТО 1 — МЕХАНИЗМ. «Черта уходит в shell литералом, строки |, grep, -q, \"СТОП|OK \" ушли аргументами в python-скрипт» — так НЕ происходит. До shell они не доезжают вовсе. `eval/conformance.py:80`: `cells = [c.strip() for c in s.strip(\"|\").split(\"|\")]` — голый split по `|` БЕЗ снятия экранирования, поэтому ячейка улики ОБРЕЗАЕТСЯ на первом `\\|`. Пере-вывел настоящим парсером:\n```\n$ eval/.venv/bin/python -c \"import sys;sys.path.insert(0,'eval');import conformance as c; ...\"\n'R37' → CMD -> 'eval/.venv/bin/python eval/dovodka/material_ja.py \\\\'\n'R55' → CMD -> 'test $(grep -l \"баннер фазы Д\" docs/experiments/*.md \\\\'\n```\nУлика находки (`$ ... \\| grep -q ...` в интерактивном shell, «печатается полный вывод») — это НЕ то, что исполняет прибор; автор проверил ручную вставку, а не conformance.\n\nОПРОВЕРГНУТО 2 — НАПРАВЛЕНИЕ (главное). «R37 зелена всегда / улика не может упасть ни при каком состоянии дерева» — ИНВЕРТИРОВАНО. Обрезка сделала проверку СТРОЖЕ, а не слабее:\n* исполняется `python material_ja.py \\` → код = коду скрипта; `material_ja.py:145` `return 1` при срабатывании гардрейла 18+ без санкции владельца ⇒ улика ПАДАЕТ. Сейчас зелена по существу: `material_ja.py:152` печатает `[OK ] срабатываний нет: 0 из ... чанков` (grep -c дал 1).\n* а вот АВТОРСКАЯ, задуманная форма с пайпом действительно не падает никогда, потому что код пайплайна = коду grep, а grep матчит и «СТОП», и «OK »:\n```\n$ sh -c 'printf \"%s\\n\" \"⛔ СТОП. непригоден\"; exit 1' | grep -q \"СТОП\\|OK \" → EXIT=0\n$ sh -c 'printf \"%s\\n\" \"⛔ СТОП. непригоден\"; exit 1' → EXIT=1\n```\nТо есть баг случайно ПОЧИНИЛ улику, которую автор написал незападающей. Тезис находки «числится закрытым уликой, которая не может упасть» — ложен для того, что реально исполняется.\n\nОПРОВЕРГНУТО 3 — МАСШТАБ «трёх улик от одной причины». `grep -n '\\|' eval/dovodka/requirements.md` → РОВНО 2 строки: R37 (:70) и R55 (:90). R3 (:30) к экранированию отношения не имеет — это отдельный дефект (улика прибита к отменённому $4.00).\n\nОПРОВЕРГНУТО 4 — «Требование о сверке пакетного потолка улики не имеет вовсе». Улика есть, она просто ГРОМКО падает: `[ПРОВАЛ] R3`, `СВЕРКА НЕ ПРОЙДЕНА`, EXIT=1. Падающая улика ≠ отсутствующая. Два ряда из трёх (R3, R55) орут и роняют код возврата всего прибора — это прибор, который работает, а не «сообщает не то, что проверяет». Молча подменён ровно ОДИН ряд — R37.\n\nОПРОВЕРГНУТО 5 — ПОЧИНКА. «Гонять улики через список аргументов без shell» сломает легитимные улики, которым shell нужен: R55 (`test $(...)`), глобы `docs/experiments/*.md`. Верна только вторая половина (снимать экранирование при парсинге).\n\nЧАСТИЧНО — АРИФМЕТИКА. «по трём строкам из 77» спорит с собственной цитатой «требований 89»: 89 — все строки таблицы включая разделители-заголовки, 77 — число R-идентификаторов (`grep -oE '^\\| R[0-9]+ ' | wc -l` → 77, последний R77). Не ошибка, но два числа в одной находке без оговорки.\n\nЧТО ОСТАЁТСЯ ЖИВЫМ И ПОЧЕМУ refuted=false. Под неверным объяснением лежит настоящий, НЕ объявленный дефект общезонного инструмента: `conformance.py:80` молча переписывает команду улики. Читатель `requirements.md:70` видит один конвейер, исполняется другая команда — и никакой печати об этом нет. Объявленная граница прибора (`conformance.py:24-27`: «проверяет, что у требования ЕСТЬ проходящая улика, а не что улика доказывает именно это требование») покрывает подмену уликой АВТОРОМ, но не молчаливую обрезку САМИМ парсером. Это дефект `eval/conformance.py` (чужая зона, правится отдельным коммитом по R71), а не реестра фазы Д.",
|
||
"corrected": "Парсер таблицы `eval/conformance.py:80` (`s.strip(\"|\").split(\"|\")`) режет ячейку улики по `|` без снятия markdown-экранирования, поэтому улика, содержащая `\\|`, молча ОБРЕЗАЕТСЯ и исполняется не та команда, которую видит читатель реестра. Затронуто ровно 2 ряда: R37 (`requirements.md:70`) исполняется как `eval/.venv/bin/python eval/dovodka/material_ja.py \\` — grep-фильтр потерян; R55 (`requirements.md:90`) обрезан до незакрытого `$(` и падает `/bin/sh: 1: Syntax error: end of file unexpected`. Отдельным, не связанным с этим дефектом стоит R3 (`requirements.md:30`): улика прибита к отменённому `$4.00`, тогда как `plan.py:10` и `money_d.py:10` несут санкцию владельца `$4.50` ⇒ `[ПРОВАЛ] R3`. Тяжесть — СРЕДНЯЯ, не «важно»: два из трёх рядов падают громко и роняют EXIT=1 («СВЕРКА НЕ ПРОЙДЕНА»), выводов фазы это не двигает и денег не тратит. Молчаливо подменён один ряд — R37, причём обрезка сделала его СТРОЖЕ авторского замысла: исполняемая форма падает на `material_ja.py:145` (`return 1`, гардрейл 18+ без санкции владельца), а задуманная `| grep -q \"СТОП\\|OK \"` вернула бы 0 и в пригодном, и в непригодном случае, то есть не падала бы никогда. Починка: снимать `\\|` в `rows()` перед сборкой ячейки (shell для улик оставить — `test $(...)` и глобы без него не работают) и пере-привязать R3 к `$4.50`."
|
||
}
|
||
},
|
||
{
|
||
"title": "Арм A1 молча теряет единицы: при пустом списке мест клетка не покупается вовсе, поэтому n(A1)=30 против объявленного в пре-реге n=32, и выпадение коррелирует с исходом",
|
||
"severity": "важно",
|
||
"evidence": "contour.py:263-265: `if not places: print(f\" {uid}/{arm}: мест нет — чинить нечего, клетка не покупается\"); continue`. Пересчитал $0: из A1 выпали ровно 474f822806 и 9b16c9c9a7, у обеих flags_of(...) = 0 мест. Пре-рег Д0.3 объявляет по оси Д4 n=32 и MDE 1.29, Д0.5 — семейство из пяти контрастов на «базе одной и замороженной», норма Д0.6 — «все армы единицы в одном задании одной сессии». В сырье нет никакого маркера, отличающего «единицу не купили, потому что чинить нечего» от «не купили, потому что кончились деньги» — оба случая просто отсутствие файла.",
|
||
"consequence": "Правильный выход арма A1 на такой единице — черновик БЕЗ правок (контур отработал и ничего не нашёл), и его надо судить: это законный исход гипотезы H-2а. Вместо этого единица исчезает из арма, причём исчезают именно те, где черновик чист по канону, — отбор скоррелирован с качеством, а не случаен. Контраст A1/A0 считается на другом наборе единиц, чем A3/A0 и A4/A0, парность внутри единицы ломается, объявленная мощность оси завышена.",
|
||
"fix": "При пустом списке мест записывать клетку арма с content = черновик и cost_usd = 0 (арм отработал вхолостую) — тогда n=32 сохраняется и норма «все армы единицы» держится; в сырьё добавить поле, отличающее «мест нет» от «срезано потолком».",
|
||
"verdict": {
|
||
"line": "посылки-заказа",
|
||
"refuted": false,
|
||
"corrected": "Ветка `if not places: continue` (contour.py:263-265) молча выбрасывает единицу из арма, и это ударило по ДВУМ армам, не по одному: A1 потерял 474f822806 и 9b16c9c9a7 (n=30 вместо объявленных 32), A4 потерял 474f822806 той же веткой (значит A4 = 32 − 9 гардом − 1 «мест нет», а фазовая строка «гард остановил A4 на 22 из 32» ошибочна на единицу). Отбор не случаен и проверяем: батарея молчит на 32/32 единицах, поэтому flags_of == canon_gaps, и выпали ровно те единицы, чей flash-черновик не теряет ни одного канонного термина. В сырье различить «мест нет» и «срезано потолком» нечем: ключей клетки 17, маркера среди них нет, а у пропущенной единицы файла нет вовсе; ни один док фазы этой ветки не объявляет (грep «чинить нечего|мест нет» по docs/ и eval/dovodka/ даёт единственный хит — саму строку кода). Последствие точнее формулируется числом, а не словами «мощность завышена»: по собственной формуле рига power.mde(2.12, n, k=3) даёт 1.491 при n=32 и 1.540 при n=30 против цели оси 1.50, то есть по правилу Д0.3 «ось описательная, если MDE больше цели» контраст A1/A0 на фактическом n переходит из несущего в описательный. Оговорка: корреляция выпадения с СУДЕЙСКИМ исходом — вывод, а не замер; замерено то, что отбор идёт по детерминированному прокси качества черновика (нулевое покрытие канон-разрывов).",
|
||
"why": "Опровергнуть не удалось — механизм подтверждён исполнением, бюджетное объяснение исключено. (1) contour.py:263-265 — единственный путь, выбрасывающий единицу с непустым черновиком (проверено чтением cmd_run, строки 237-288). (2) Разность множеств по сырью: `ls ~/books/dovodka | grep '^dv-a-a1-'` = 30 uid, `dv-a-a3-` без crit = 32; в A3, но не в A1 — ровно 474f822806 и 9b16c9c9a7. (3) $0-прогон flags_of() по всем 32 единицам (скрипт в scratchpad/chk.py, eval/.venv/bin/python): flags=0 ровно у этих двух и ни у кого больше, и ровно у них нет A1-файла. (4) Гард исключён: их позиции в порядке итерации 8 и 16 из 32 (не хвост), длины черновиков 7814 и 7037 символов — то есть ветка «базы нет» тоже не при чём. (5) Отбор по канону доказан: len(canon_gaps)==len(flags_of) на 32/32 единицах, батарея даёт ноль всюду. (6) A4: canon_gaps(src, base_a0(uid)) == 0 у 474f822806 (та же ветка), у остальных 9 отсутствующих 1-2 разрыва — это гард; значит находка недо-охватила масштаб. (7) «Объявленное ограничение» исключено: `grep -rn \"чинить нечего\\|мест нет\\|30 из 32\" docs/ eval/dovodka/` — единственный релевантный хит contour.py:264; в Д0.3/Д0.5/Д0.6 (docs/experiments/23-editor-tier.md:719-896) объявлено n=32, «база одна и замороженная», «все армы единицы — в одном задании одной сессии». (8) Меняется вывод: power.mde(2.12,30,3)=1.540 > цели 1.50 против 1.491 при n=32 — по правилу Д0.3 контраст A1/A0 пере-классифицируется в описательный. (9) Ключи клетки (json из dv-a-a1-00e4c3496f.json) маркера причины пропуска не содержат."
|
||
}
|
||
},
|
||
{
|
||
"title": "Гейт чужого пака `verify22.py` красный (EXIT=1), хотя реестр держит его уликой R71, а отчёт эксп-23 печатает «зелёные, код возврата 0»; причина — mtime всего сырья сброшен, то есть провенанс по времени утрачен шире, чем объявлено в Д8 п.8",
|
||
"severity": "важно",
|
||
"evidence": "$ eval/.venv/bin/python eval/tenant_panel/verify22.py → «[ПРОВАЛ] верхняя граница двойной оплаты $0.000000 напечатана», «РАСХОЖДЕНИЙ: 1 — ОТЧЁТ НЕ СДАЁТСЯ», EXIT=1. Проверка verify22.py:174-185 считает расход Ф2 по файлам с mtime меньше времени коммита fd3e522; $ ls -la ~/books/dovodka и ~/books/editor-tier — у ВСЕХ файлов mtime «Aug 10 22:01», поэтому pre=0.0. Реестр requirements.md:108 объявляет R71 («правка рига чужого пака — отдельным коммитом + пере-снятие его гейтов») закрытым этой самой командой; отчёт 23-editor-tier.md (таблица §14, п.7) утверждает «Его гейты пере-сняты сейчас — verify22.py и itog22.py зелёные, код возврата 0». Заказ Д8 п.8 объявляет утрату mtime-провенанса ТОЛЬКО для каталогов aj-border*.",
|
||
"consequence": "Требование заказа «пере-снятие гейтов чужого пака» не исполнено, и conformance --final не пройдёт по R71. Шире: любая проверка обоих паков, опирающаяся на mtime (провенанс судейства, граница двойной оплаты, порядок покупок), сейчас возвращает нули — то есть класс «утрачен провенанс» затрагивает всё сырьё, а объявлен в отчёте для одного каталога.",
|
||
"fix": "Либо пере-считать границу двойной оплаты не по mtime, а по журналу покупок/git-истории и обновить число в теле эксп-22, либо объявить проверку неснимаемой с указанием причины; в Д8 п.8 расширить объявление: mtime-провенанс утрачен по ВСЕМУ ~/books, а не только по aj-border*.",
|
||
"verdict": {
|
||
"line": "посылки-заказа",
|
||
"refuted": false,
|
||
"corrected": "Гейт чужого пака `verify22.py` сейчас красный (EXIT=1) на единственной проверке — «верхняя граница двойной оплаты $0.000000 напечатана»; реестр `eval/dovodka/requirements.md:108` держит ровно эту команду уликой R71, а `docs/experiments/23-editor-tier.md:707` печатает про неё «зелёные, код возврата 0». Причина — не действие сессии: `~/books` был пере-клонирован (`~/books/.git` reflog `HEAD@{1}: clone`, импорт-коммит `8307ccc` 2026-08-10 21:59:47, 6774 файла одним куском), git mtime не сохраняет, и checkout проштамповал ВСЁ сырьё моментом выкладки. Уточнения к формулировке: (1) verify22 читает `~/books/tenant-panel` (`money.MONEY.OUT`), а не названные в улике `dovodka`/`editor-tier`; там все 335 файлов Ф2 несут ровно один mtime 1786388478 против времени коммита `fd3e522` 1786211005, поэтому pre=0.0 при фактическом расходе Ф2 $1.681912. (2) «у ВСЕХ файлов mtime Aug 10 22:01» неверно для `~/books/dovodka`: 114 файлов на 22:01:17, 35 на 23:39:44, 1 на 00:11:28 — клетки, купленные ПОСЛЕ клона, провенанс сохранили; утрачен он у всего, что существовало на момент клона. (3) «Требование не исполнено» неточно: пере-снятие БЫЛО сделано и было зелёным — клейм закоммичен в `da5f4d0` 2026-08-10 07:06, за ~15 часов до клона; улика протухла от события среды. Верное утверждение: R71 сейчас не выполняется, `conformance --final` по нему упадёт, а настоящее время в §14 п.7 стало ложным (при этом `itog22.py` пере-снят и по-прежнему EXIT=0 — «его гейты» ложны наполовину). (4) «любая проверка, опирающаяся на mtime, возвращает нули» — шире прибора: в `eval/` ровно три потребителя mtime (`verify22.py:182`, `verify23.py:111`, `absjudge.py:323`), причём третий получает `lambda tok, _mtime: jmap.get(tok, \"?\")` (`eval/editor_tier/judge.py:179`) и mtime игнорирует. Зато находка пропустила ХУДШИЙ случай: `verify23.py:111` — сторож «голоса не старше ответов судей», заведённый после того, как аудит поймал 5 единиц из 32 с голосами одного круга и ответами другого, — теперь ослеплён (все mtime равны, условие `a.mtime > v.mtime + 1` не срабатывает никогда) и печатает `[OK] голоса не старше ответов судей` по обоим проходам при EXIT=0. Молча зелёный гейт опаснее шумно красного. (5) Предложенная починка «пере-считать по журналу покупок / git-истории» неисполнима: клетки не несут поля времени (ключи `attempt/cached_tokens/completion_tokens/content/cost_usd/en/finish/floor/latency_s/model/model_returned/prompt_tokens/reasoning_*/role/tag/tenant/total_tokens/uid`), а в репо `~/books` сырьё лежит одним bulk-коммитом. Значит §8 эксп-22 «Выводимая из сырья граница одна: … 176 клеток Ф2 на $0.846103» стал ложным как утверждение о выводимости, и объявленное в ИТОГе (строка 1387) «фактическая величина двойной оплаты невосстановима» этот класс НЕ покрывает — там про фактическую величину, а не про границу. Честные опции: заморозить $0.846103 как исторически снятую константу с явной пометкой «более не пере-выводима» и снять/переписать проверку в verify22 с указанием причины, а в Д8 п.8 расширить объявление утраты mtime-провенанса с `aj-border*` на всё сырьё, существовавшее до клона 10.08 21:59.",
|
||
"why": "Опровергнуть не удалось — ядро находки подтверждено исполнением, неточны только улика и масштаб. Выполнено: (1) `eval/.venv/bin/python eval/tenant_panel/verify22.py` → единственный `[ПРОВАЛ] верхняя граница двойной оплаты $0.000000 напечатана`, `РАСХОЖДЕНИЙ: 1 — ОТЧЁТ НЕ СДАЁТСЯ`, EXIT=1. (2) `git log --format='%at %ai' -1 fd3e522` → `1786211005 2026-08-08 20:43:25`; скрипт по `verify22.py:174-185` пере-считан вручную: 335 файлов Ф2 (`money.TAGS['Ф2']` в `~/books/tenant-panel`), суммарно $1.681912, «older than commit: 0, sum 0.0», множество mtime = ровно {1786388478}. (3) `cd ~/books && git reflog` → `HEAD@{1}: clone: from ssh://git.vojo.chat:2222/heaven/books.git`; `git log` → `8307ccc 2026-08-10 21:59:47 Import polygon raw material: packs 21-23 and phase D measurements…`, `git show --stat 8307ccc | tail` → `6774 files changed`. Это и есть механизм сброса mtime, и он в докax не назван нигде (`grep -rn mtime` по заказу/отчёту/реестру даёт только `aj-border`). (4) `grep -n R71 eval/dovodka/requirements.md` → строка 108, улика = именно `verify22.py`; шапка реестра (строки 7-9, 17-19) требует кода 0 в `--final`. (5) `sed -n 700,712p docs/experiments/23-editor-tier.md` → строка 707 «его гейты пере-сняты сейчас — verify22.py и itog22.py зелёные, код возврата 0»; `git log -S` по этой строке → `da5f4d0 2026-08-10 07:06:07`, то есть ДО клона в 21:59 — значит клейм был верен в момент написания, а «требование не исполнено» неточно. (6) `eval/.venv/bin/python eval/tenant_panel/itog22.py` → EXIT=0, то есть красный только один из двух гейтов. (7) `grep -rn 'st_mtime|getmtime' eval/ --include=*.py` → три хита: `verify22.py:182`, `verify23.py:111`, `absjudge.py:323`; последний питается `lambda tok, _mtime: …` из `eval/editor_tier/judge.py:179`, mtime не использует. (8) `eval/.venv/bin/python eval/editor_tier/verify23.py` → EXIT=0 и в секции «СВЕЖЕСТЬ РАЗБОРА» два `[OK] голоса не старше ответов судей` — при равных mtime условие `verify23.py:111` не срабатывает в принципе, то есть сторож, заведённый против уже пойманного класса (комментарий `verify23.py:101-104`), сейчас слеп и молчит. (9) `ls -la ~/books/dovodka` + счёт распределения mtime → 114/35/1 на три разных штампа, что опровергает «у ВСЕХ файлов mtime Aug 10 22:01». (10) Ключи клетки `tp2-draft-D-deepseek-v4-flash-1431129de6.json` не содержат поля времени, а `docs/experiments/22-tenant-panel.md:223-226` объявляет границу «выводимой из сырья» — это утверждение теперь ложно, и оговорка в ИТОГе (строка 1387) про «невосстановимость фактической величины» его не покрывает."
|
||
}
|
||
},
|
||
{
|
||
"title": "Реестр требований не покрывает целую секцию заказа «Чего НЕ делать» (6 требований) и мандат самопроверки исполнением — при том что реестр заведён именно как механическая сверка с буквой заказа",
|
||
"severity": "важно",
|
||
"evidence": "Заказ, строки 194-199 («Чего НЕ делать»): не трогать чужие зоны и их незакоммиченные файлы · не объявлять ратификаций · Резерв D39.22 не трогать · не менять слаги моделей без live-фактчека /models · .env не читать НИКОГДА · аномалии провода → официальная вендор-дока. $ grep -n \"D39.22\\|ратифик\\|/models\\|\\.env\\|вендор-док\\|чужие зоны\" eval/dovodka/requirements.md → ни одного вхождения; в реестре 77 строк R1–R77 и ни одна из этих шести не заведена. Также отсутствует строка на заказ строки 186-188 — «Самопроверка исполнением: ревью своего кода, СФОРМИРОВАННЫХ запросов к моделям и ПОЛУЧЕННЫХ ОТВЕТОВ» (в реестре есть только R72 про адверсариальную приёмку) — и на строку 191-192 («гейт чисел сторожит присутствие числа, не истинность»).",
|
||
"consequence": "Пропущенные требования невидимы для conformance по построению, а одно из них уже нарушено: ревью ПОЛУЧЕННЫХ ответов не проводилось — иначе три китайские клетки единицы 63ab55ac5c (находка №1) были бы пойманы до траты. Реестр, заведённый как страховка от «пропусков в придаточных предложениях», сам повторил тот же класс пропуска: все шесть невыполненных строк заказа стоят в неформатированной секции.",
|
||
"fix": "Дописать в реестр строки на все шесть пунктов «Чего НЕ делать» (улика на .env — отсутствие чтения в транскрипте/логах; на слаги — снимок /models; на Резерв D39.22 — отсутствие правок), на мандат самопроверки исполнением (улика: протокол ревью сформированных запросов и полученных ответов) и на оговорку про гейт чисел; пере-фризнуть реестр коммитом ДО следующих покупок.",
|
||
"verdict": {
|
||
"line": "посылки-заказа",
|
||
"refuted": false,
|
||
"why": "Пытался опровергнуть — фактическое ядро выдержало проверку моими командами, но масштаб и последствие в формулировке смещены.\n\nПОДТВЕРЖДЕНО ИСПОЛНЕНИЕМ:\n1) Секция заказа «Чего НЕ делать» — `docs/POLYGON_EXP2223_REDO_SESSION_PROMPT.md:194` (заголовок) и `:196-199` (6 пунктов через `·`). `$ grep -n \"D39.22\\|ратифик\\|/models\\|\\.env\\|вендор\\|чужие зоны\\|Самопроверка\\|СФОРМИРОВАН\\|присутствие числа\" eval/dovodka/requirements.md` → всего 2 хита, и оба посторонние: `requirements.md:40` (R12, слово «вендор-статуса») и `requirements.md:91` (R56, `/models` внутри грепаемой строки). Ни одной строки на шесть запретов нет.\n2) Строк требований ровно 77 (`$ grep -oE '^\\| R[0-9]+' eval/dovodka/requirements.md | wc -l` → 77). Заголовок реестра `requirements.md:3` заявляет «прочитан ПОСТРОЧНО, включая придаточные» — то есть это не объявленное ограничение охвата, а невыполненный клейм полноты.\n3) Секция «Анти-лень» заказа: 7 буллетов, покрыты R67–R73, КРОМЕ первого предложения буллета `:186-187` («ревью своего кода, СФОРМИРОВАННЫХ запросов и полученных ответов») и КРОМЕ целого буллета `:191-192` («гейт чисел сторожит присутствие числа, не истинность»). R72 покрывает только второе предложение (адверсариальная приёмка), R73 — третье (построчный аудит). Находка права.\n4) Реестр зафризен (`frozen()` → True, коммит `da5f4d0`), то есть дописать его теперь можно только новым коммитом — «пере-фризнуть до покупок» уместно.\n\nЧТО В НАХОДКЕ НЕВЕРНО ПО МАСШТАБУ (три поправки):\nA. «Невидимы по построению» верно про ПРИБОР, но не про сессию: 5 из 6 запретов дословно стоят в CLAUDE.md, который грузится в каждую сессию — `.env` (CLAUDE.md:38), слаги/`/models` и вендор-дока при аномалиях (CLAUDE.md:41), чужие зоны и незакоммиченные файлы (CLAUDE.md:14, :24), ратификации — прерогатива оркестратора (CLAUDE.md:20). Уникален для фазы только «Резерв D39.22 не трогать» — у него второго носителя нет. И ни один из шести не нарушен: улика R56 уже несёт живой снимок `/models` от 2026-08-10, а отчёт ратификации не объявляет (`docs/experiments/23-editor-tier.md:677`: «ЗАКРЫТИЕ НЕ ОБЪЯВЛЯЮ, подаю ПРЕДЛОЖЕНИЕ»). То есть вред от шести — потенциальный (финальный построчный аудит R73 их не подскажет), а не состоявшийся.\nB. Последствие «уже нарушено» держится ЦЕЛИКОМ на пропущенной строке про самопроверку исполнением, а не на шести запретах — заголовок находки это склеивает. Сам факт китайских клеток я подтвердил сырьём: `dv-a-a1-63ab55ac5c.json` fixer 1727 иероглифов / 288 кириллицы (69% CJK, $0.012464), `dv-a-a3-63ab55ac5c.json` fixer 1804 CJK / 0 кириллицы (80%, $0.004923), `dv-a-a3-crit-63ab55ac5c.json` критик 764/228 (56%, $0.002632); итого $0.0200. У прочих 30 клеток критика доля CJK ≤6% (максимум `de3916de62` 1202/19621).\nC. Но формулировка «ответы не ревьюились» СЛАБЕЕ факта: эта единица уже заклеймена в том же отчёте — `docs/experiments/23-editor-tier.md:351-353`: «`et-unit-draft-deepseek-v4-flash-63ab55ac5c` ... 1798 иероглифов при НУЛЕ кириллицы», и там же `:355-356` объявлено «Гейт подключён» (`bakeoff.draft_reject_reason`). Значит фаза Д купила оба edit-контура поверх базы, которую её же пак 23 признал эхо-миной и на которую гейт объявлен подключённым.\n\nПОПРАВКА К ПОЧИНКЕ: предложенные улики («отсутствие чтения `.env` в транскрипте») прибор не принимает — `check()` знает только `$ команда` с кодом 0 или путь к непустому артефакту (`eval/conformance.py:104-119`), а строка с `—` в `--final` = жёсткий ПРОВАЛ (`eval/conformance.py:155-157`). Замечу и то, что цвет гейта эти строки не изменят: `$ grep -c '| — |' eval/dovodka/requirements.md` → 46, а `$ eval/.venv/bin/python eval/conformance.py eval/dovodka/requirements.md --plan` печатает «требований 89 · ожидают 58 · провалов 3» (R71 уже ПРОВАЛ). Меняется не гейт, а список того, что обязан пройти финальный аудит.",
|
||
"corrected": "Реестр требований фазы Д не покрывает три куска буквы заказа: секцию «Чего НЕ делать» целиком (заказ 194-199, 6 запретов), первое предложение буллета «Самопроверка исполнением» (заказ 186-187: ревью своего кода, СФОРМИРОВАННЫХ запросов и ПОЛУЧЕННЫХ ответов; R72/R73 покрывают только два других предложения того же буллета) и буллет «гейт чисел сторожит присутствие числа, не истинность» (заказ 191-192). Это опровергает клейм самого реестра «прочитан ПОСТРОЧНО, включая придаточные» (requirements.md:3) — тот же класс пропуска, ради которого реестр и заводился.\n\nТяжесть — средняя, не «важно», и распределена неравномерно:\n• Шесть запретов: не нарушены и не невидимы сессии — 5 из 6 дословно стоят в CLAUDE.md (:38 .env, :41 слаги//models и вендор-дока, :14/:24 чужие зоны, :20 ратификации), улика R56 уже несёт живой снимок /models от 2026-08-10, а отчёт ратификаций не объявляет (23-editor-tier.md:677). Реально не покрыт ничем только «Резерв D39.22 не трогать». Вред потенциальный: финальный построчный аудит (R73) этих строк не подскажет.\n• Пропуск строки о самопроверке исполнением — единственный со СОСТОЯВШИМСЯ вредом, и он крупнее заявленного: фаза Д купила ОБА edit-контура поверх базы, которую её же пак 23 уже признал эхо-миной (23-editor-tier.md:351-353, «1798 иероглифов при НУЛЕ кириллицы») и объявил закрытой гейтом bakeoff.draft_reject_reason (:355-356). Итог — три клетки единицы 63ab55ac5c с 56-80% иероглифов на $0.0200 (dv-a-a1-63ab55ac5c 1727 CJK/288 кир., dv-a-a3-63ab55ac5c 1804/0, dv-a-a3-crit-63ab55ac5c 764/228). Формулировка «ответы не ревьюились» это недоговаривает: не сработал не только пост-хок просмотр ответов, но и объявленный входной гейт базы.\n\nПочинка требует переделки: улика «отсутствие чтения .env в транскрипте» прибору неизвестна — check() принимает только `$ команда` с кодом 0 или путь (conformance.py:104-119), а `—` в --final = ПРОВАЛ (conformance.py:155-157). Нужны исполнимые формы (git diff --quiet по файлам-носителям D39.22; сверка использованных слагов с сохранённым снимком /models; для базы каждого арма — прогон draft_reject_reason как улика на строку о самопроверке) либо явно объявленный в реестре класс «механически непроверяемо, проверяется чтением при финальном аудите». Пере-фриз коммитом ДО следующих покупок — да, но заметить: цвет гейта от этого не изменится (сейчас 46 строк из 77 с `—`, --plan даёт «ожидают 58 · провалов 3»)."
|
||
}
|
||
},
|
||
{
|
||
"title": "Режим `conformance --final` непроходим по построению: 12 из «89 требований» — это строки-заголовки секций с пустой уликой, а пустая улика в --final считается провалом",
|
||
"severity": "мелко",
|
||
"evidence": "$ grep -c '^| R' eval/dovodka/requirements.md → 77; $ grep -c '^| \\*\\*' → 12; conformance.py rows() пропускает только разделители и строку «ID», поэтому строки вида `| **РАМКА** | | |` попадают в список требований — в выводе они видны как «[ОЖИДАЕТ ] **РАМКА** ← улика не объявлена». Итоговая строка прогона: «требований 89 · ожидают 58 · провалов 3». Документация conformance.py: «--final требование без улики = ПРОВАЛ (код ≠0)».",
|
||
"consequence": "Сдаточный режим гейта не сможет дать зелёный никогда, значит на сдаче его либо обойдут TM_ALLOW_UNFROZEN/глазами, либо заголовки задним числом причешут — обе дороги уводят к тому же, за что аннулировали conformance пака 23. Плюс число «89 требований фазы», которым фаза себя описывает, завышено на 12: реальных требований 77.",
|
||
"fix": "В rows() пропускать строки, у которых пусты обе последние ячейки (заголовки секций), и печатать честное «требований 77».",
|
||
"verdict": {
|
||
"line": "посылки-заказа",
|
||
"refuted": false,
|
||
"corrected": "Режим `conformance --final` непроходим по построению: 12 из 89 строк реестра — заголовки секций (`| **РАМКА** | | |` и т.п.) с пустой уликой, а пустая улика в `--final` = ПРОВАЛ, причём заголовок улику получить не может в принципе. Реальных требований 77. Обход через TM_ALLOW_UNFROZEN НЕ работает (переменная снимает только фриз-гейт, тальи провалов не трогает) — остаётся либо смотреть глазами мимо кода возврата, либо править таблицу. Числом «89» фаза себя нигде не описывает (грепом не найдено ни одного упоминания вне вывода самого инструмента), так что «завышенное самоописание» — не последствие. НАСТОЯЩЕЕ последствие крупнее заявленного: набивка искажает собственную головную метрику прибора — долю улик «сам-себя», ради которой написана починка №2 в докстринге. Улику объявили только 31 из 77 реальных требований, 9 из них само-ссылочные; строка печатает «9 из 89 = 10.1%» вместо честных «9 из 31 = 29.0%», то есть гейт занижает долю само-доказательных улик примерно втрое. Починка: в rows() пропускать строки с пустой ячейкой требования, печатать «требований 77» и считать долю сам-себя от объявленных улик.",
|
||
"why": "Механика подтверждена исполнением, находка верна, но две опорные посылки ложны и вред занижен.\n\nПОДТВЕРЖДЕНО. Парсер реально пропускает заголовки: `eval/.venv/bin/python -c \"import sys;sys.path.insert(0,'eval');import conformance as c;from pathlib import Path;r=c.rows(Path('eval/dovodka/requirements.md').read_text(encoding='utf-8'));print(len(r), len([x for x in r if x[1].strip()==''])) \"` → `89 12`. Причина в eval/conformance.py:68-88: фильтруются только разделители и строка ID/№; для `| **РАМКА** | | |` cells=['**РАМКА**','',''], len>=3 и set('**РАМКА**') не подмножество set(\"-: \"), строка проходит. Заголовки — requirements.md:27,36,43,46,58,65,68,75,78,92,103,111 (ровно 12, grep -c '^| \\*\\*' → 12; grep -c '^| R' → 77).\ncheck('') → ОЖИДАЕТ (conformance.py:94-95), main() переводит это в ПРОВАЛ при --final (conformance.py:155-157), bad>=12 → return 1 (conformance.py:169-171). Прогон end-to-end на синтетическом реестре из двух строк (заголовок + R1 с уликой `$ true`, покупок нет): «[ПРОВАЛ ] **РАМКА** ← улики нет, а пак сдаётся … требований 2 · ожидают 0 · провалов 1 · СВЕРКА НЕ ПРОЙДЕНА · EXIT=1».\nОбъявленным ограничением это НЕ является: докстринг conformance.py:29-39 называет два дефекта приёмки пака 23 (эфемерный scratchpad-реестр и улики «сам-себя»), шапка отчёта docs/experiments/23-editor-tier.md:32-36 — те же два; про фантомные строки-заголовки ни там, ни в шапке requirements.md:1-21 нет ничего.\n\nОПРОВЕРГНУТО В ФИНДИНГЕ (1): «обойдут TM_ALLOW_UNFROZEN». Переменная читается только в блоке фриз-гейта conformance.py:137-144 и лишь печатает предупреждение вместо `return 1`; подсчёт bad (conformance.py:162) и выход (conformance.py:169-171) выполняются после неё независимо. Мой прогон выше шёл именно с TM_ALLOW_UNFROZEN=1 и всё равно дал EXIT=1.\n\nОПРОВЕРГНУТО В ФИНДИНГЕ (2): «число 89, которым фаза себя описывает». `grep -n '\\b89\\b' eval/dovodka/requirements.md docs/POLYGON_EXP2223_REDO_SESSION_PROMPT.md docs/experiments/23-editor-tier.md eval/conformance.py` — пусто (нет вывода). 89 существует только в печати самого инструмента, самоописания фазы этим числом нет.\n\nЗАНИЖЕН МАСШТАБ. Набивка бьёт по метрике, ради которой написана починка №2 (conformance.py:36-39, печать на conformance.py:167). Счёт: улику объявили 31 из 77 реальных требований, само-ссылочных улик 9 → печатается «9 из 89 = 10.1%», честная доля «9 из 31 = 29.0%» (команда: import conformance, selfnames = {'requirements.md'} | имена docs/experiments/2[23]-*.md, подсчёт по x[2]). Гейт занижает долю «улика доказывает, что напечатано» примерно втрое — это и есть меняющееся следствие, а не арифметика заголовка.\n\nПОБОЧНО (вне находки): улика R52 (requirements.md:87) — `$ eval/.venv/bin/python eval/editor_tier/judge.py --run replication-runB border --score`, а check() исполняет улики через subprocess.run(shell=True) (conformance.py:102-104), то есть любой прогон --plan/--final её запускает. Поэтому полный гейт я не гонял; цитируемая в находке строка «требований 89 · ожидают 58 · провалов 3» получена чьим-то реальным прогоном."
|
||
}
|
||
},
|
||
{
|
||
"title": "Потолок фазы ФД-D $0.055 против прямого ограничения заказа «Д7 — микро-проба самооценки, ≤$0.05»",
|
||
"severity": "мелко",
|
||
"evidence": "Заказ, строка 119: «Д7 — Микро-проба самооценки (идея владельца; ≤$0.05, решений не несёт)». eval/dovodka/money_d.py:67: CEILINGS = {..., \"ФД-D\": 0.055, ...}; plan.py печатает смету ФД-D 0.050. Комментарий money_d.py:63-66 объясняет потолки как «смета плюс МИНИМАЛЬНЫЙ запас», то есть запас навешен и на ту строку, где владелец назвал жёсткий предел.",
|
||
"consequence": "Гард пропустит покупки на $0.055 там, где владелец назвал предел $0.05 — превышение на 10% названного им числа, невидимое для отчёта («ПРОБОЙ» печатается только выше 0.055).",
|
||
"fix": "Опустить CEILINGS['ФД-D'] до 0.050; освободившиеся $0.005 не перераспределять молча.",
|
||
"verdict": {
|
||
"line": "посылки-заказа",
|
||
"corrected": "Гард фазы ФД-D стоит на $0.055 при кэпе заказа «Д7 … ≤$0.05» (money_d.py:67 против POLYGON_EXP2223_REDO_SESSION_PROMPT.md:119) — единственная строка заказа с явным денежным кэпом на платный пункт, и запас на ней 10.0% против 0.1–1.1% на всех прочих фазах, то есть комментарий money_d.py:63-66 «МИНИМАЛЬНЫЙ запас» эту строку не описывает. Масштаб: экспозиция максимум $0.005, потрачено по ФД-D сейчас $0.000000, Д7 «решений не несёт» (заказ:119, Д0.10 23-editor-tier.md) — ни один вывод фазы не двигается, это дисциплина гарда, а не деньги и не вывод. Две поправки к формулировке улики: (1) число $0.05 названо ЗАКАЗОМ (промт оркестратора, файл ещё не в истории), «идея владельца» в той же скобке относится к идее пробы, а не к сумме — грепа со словом владельца про $0.05 в докax нет, поэтому «превышение названного ИМ числа» не грунтовано; кэп заказа при этом сессию всё равно связывает; (2) невидимость сильнее заявленной: report() печатает потолок как `{:10.2f}`, поэтому строка ФД-D показывает «0.06», а сами потолки (0.885/0.055/…) не опубликованы НИГДЕ в докax — секция пре-рега Д0.8 названа «Смета … и фазовые потолки», но таблица содержит только смету.",
|
||
"refuted": false,
|
||
"why": "Опровергнуть не удалось: механика подтверждена исполнением. (1) Кэп заказа: `grep -n \"^## \" docs/POLYGON_EXP2223_REDO_SESSION_PROMPT.md` → строка 119 «## Д7 — Микро-проба самооценки (идея владельца; ≤$0.05, решений не несёт)»; это единственный платный пункт заказа с денежным кэпом (прочие скобки — «$0» у Д2/Д5/Д8, у Д1/Д3/Д4/Д6 кэпов нет). (2) Гард: eval/dovodka/money_d.py:67 `CEILINGS = {..., \"ФД-D\": 0.055, ...}`; eval/dovodka/plan.py:91 `rows.append((\"ФД-D\", ..., 0.05))` — смета ровно кэп, захардкожена, не выведена из замеренных цен. Guarded.afford() (eval/tenant_panel/money.py:149-154) отказывает при `sp + exp > self.ceiling`, то есть достижимый потолок расхода Д7 = $0.055, на $0.005 выше кэпа заказа. Второго кэпа нет: `ls eval/dovodka/` — рига Д7 не существует, `grep -rln \"ФД-D\" eval/` даёт только money_d.py и plan.py. (3) «Объявленное ограничение»? Нет: комментарий money_d.py:63-66 объявляет ПРАВИЛО («смета плюс МИНИМАЛЬНЫЙ запас, сумма ≤ пакетного»), но не то, что на ФД-D оно пробивает кэп заказа, и на этой строке слово «минимальный» неверно — посчитано мной: A +0.9%, B +0.7%, C +0.6%, E +0.1%, F +1.1%, G +1.0%, D +10.0% (9× выброс). Сами числа потолков в докax отсутствуют: `grep -rn \"0\\.885\\|0\\.055\" docs/` не даёт ни одного попадания по фазе Д, а пре-рег docs/experiments/23-editor-tier.md:852-862 («Д0.8 Смета … и фазовые потолки») печатает только смету 0.050. (4) Невидимость: `money_d.py --report` печатает `ФД-D 0.000000 0.06` — потолок форматируется `{:10.2f}` (money_d.py:89), 0.055 → «0.06»; «ПРОБОЙ» ставится только при sp > 0.055 (money_d.py:88). (5) Что находка НЕ делает: по отчёту кассы ФД-D потрачено $0.000000, сумма потолков 4.495 ≤ 4.50 (санкция владельца цела, селфтест money_d.py:112-114 это и проверяет), Д7 решений не несёт — ни один вывод фазы не меняется, деньги впустую не потрачены. Поэтому тяжесть «мелко» подтверждаю, а формулировку улики поправляю по двум пунктам (см. corrected)."
|
||
}
|
||
},
|
||
{
|
||
"title": "Порог улики R55 откалиброван под уже сделанное (≥7), а статус-баннеров по-прежнему нет у отчётов эксп-18/19/20 — тех самых, чьи выводы фаза переиспользует",
|
||
"severity": "мелко",
|
||
"evidence": "Заказ Д8 п.12: «статус-баннеры на отчётах экспов, где их нет». Улика requirements.md:90: `test $(grep -l \"баннер фазы Д\" docs/experiments/*.md | wc -l) -ge 7`. $ grep -l \"баннер фазы Д\" docs/experiments/*.md | wc -l → 7 (файлы 01,02,03,06,07,10,11) при 24 отчётах в каталоге. $ head -20 по каждому: 14 и 14b несут ревью-шапки оркестратора, а 18-editor-wire-probe.md, 19-editor-contract-q4b.md, 20-editor-role.md не несут ни баннера, ни шапки. Сама улика при этом падает синтаксисом shell (см. находку про `\\|`).",
|
||
"consequence": "Требование исполнено частично, а гейт объявляет его закрытым числом, равным тому, что сделано, — «7 из 7» вместо «сколько отчётов без баннера осталось». Именно эксп-19 (урок конфаундированного зеркала промпта) и эксп-20 (механика точечного фиксера) — прямые опоры армов A1/A3 фазы Д, и читатель не увидит их статуса.",
|
||
"fix": "Заменить улику на «нет ни одного отчёта в docs/experiments без статус-баннера/ревью-шапки» и добавить баннеры в 18/19/20.",
|
||
"verdict": {
|
||
"line": "посылки-заказа",
|
||
"refuted": true,
|
||
"why": "Опровергнуто исполнением по трём независимым линиям.\n\n(1) ЦЕНТРАЛЬНАЯ УЛИКА ЛОЖНА. Утверждение «18-editor-wire-probe.md, 19-editor-contract-q4b.md, 20-editor-role.md не несут ни баннера, ни шапки» неверно фактически. `$ grep -c \"РЕВЬЮ-ШАПКА ПРИЁМКИ\" docs/experiments/1[89]*.md docs/experiments/20*.md` → по 1 в каждом; `$ grep -n \"РЕВЬЮ-ШАПКА\"` даёт 18-editor-wire-probe.md:9, 19-editor-contract-q4b.md:10, 20-editor-role.md:9 — т.е. ровно в том же месте и в том же формате, что у 14/14b, которые сам автор находки признаёт закрытыми шапкой. Вердикты напечатаны: 18 «— ПРИНЯТ», 19 «— ПРИНЯТ; вердикт гейта Q4b „диффы откладываются\" подтверждён ре-раном», 20 «— ПРИНЯТ С ОГОВОРКАМИ» с 8 поправками (включая «решающий замер §5.2 НЕ персистирован… статус „СО СЛОВ СЕССИИ\"»). Именно то, что находка объявляет отсутствующим («читатель не увидит их статуса»), у 19/20 — самые подробные статус-блоки во всём каталоге. Автор, судя по формулировке, смотрел `head -20` и не увидел строку 9/10, потому что это одна очень длинная строка.\n\n(2) ПОСЛЕДСТВИЕ ЛОЖНО: гейт НИЧЕГО не объявляет закрытым. Прогнал улику через настоящий рантайм:\n`$ eval/.venv/bin/python -c \"...import conformance as c; c.rows(md); c.check(ev)\"` для строки R55 → `('ПРОВАЛ', '/bin/sh: 1: Syntax error: end of file unexpected (expecting \")\")')`. Парсер `conformance.rows()` (eval/conformance.py:79 `cells = [c.strip() for c in s.strip(\"|\").split(\"|\")]`) режет ячейку по `\\|`, улика приходит обрезанной до `` `$ test $(grep -l \"баннер фазы Д\" docs/experiments/*.md \\ `` и падает. То есть R55 сейчас в реестре стоит КРАСНЫМ, а не «закрыт числом 7 из 7». Заявленное последствие невозможно по построению.\n\n(3) МАСШТАБ ЛОЖЕН: требование исполнено ПОЛНОСТЬЮ, а не частично. Прошёл по всем 24 файлам каталога: `$ for f in docs/experiments/*.md; do sed -n '1,12p' \"$f\" | grep -c \"⚠\\|СТАТУС\\|Статус\\|ШАПКА\"; done` → ни одного нуля; статус-маркер в первых 12 строках есть у КАЖДОГО файла (04 «Рекомендация ОТМЕНЕНА», 08 «Точка-во-времени», 09 «Указатель ревизии D31», 12/13/14/14b/18/19/20/22/23 — ревью-шапки, 15 «СТАТУС… перевёрнут», 16 «Статус: ИСПОЛНЕН И ЗАЛЕНДЁН», 21 «СТАТУС: замер закончен», 00 — справочник, а не отчёт, и закрыт отдельным R56). Порог ≥7 не «откалиброван под уже сделанное» произвольно: `$ for f in 01 02 03 06 07 10 11; do git show b1780b8^:docs/experiments/$f*.md | sed -n '1,6p' | grep -c \"⚠\\|СТАТУС\\|ШАПКА\"; done` → 0 у всех семи, т.е. множество «отчётов без статуса» до фазы Д равнялось ровно этим 7 файлам, и все 7 закрыты (b1780b8). Остатка нет.\n\n(4) Починка находки («добавить баннеры в 18/19/20») требует добавить второй статус-блок туда, где уже стоит первый, — то есть создаёт дублирование, а не чинит дефект. Ни один вывод фазы Д от этого не меняется, денег не тратится.\n\nЕдинственное, что уцелело от находки, — форма улики (счётчик достижения вместо счётчика остатка) плюс её обрыв на `\\|`; но обрыв — отдельная, уже поданная находка, а форма ничего не меняет, потому что по существу остаток нулевой.",
|
||
"corrected": "Уцелевший узкий остаток (мелкий, косметический, вывод не меняет): улика R55 (eval/dovodka/requirements.md:90) сформулирована как счётчик ДОСТИЖЕНИЯ — «≥7 файлов содержат фразу „баннер фазы Д\"» — вместо счётчика ОСТАТКА («нет ни одного отчёта без статус-маркера»), из-за чего она не отличает «сделано всё» от «сделано ровно семь». Плюс она обрезается парсером таблицы на `\\|` и всегда возвращает ПРОВАЛ. По существу же требование исполнено ПОЛНОСТЬЮ: до фазы статус-маркера не было ровно у 7 отчётов (01,02,03,06,07,10,11), все семь закрыты; у остальных, включая 18/19/20, статус стоит ревью-шапками приёмки (18:9, 19:10, 20:9). Правильная замена улики: `$ test $(ls docs/experiments/[0-9]*.md | while read f; do sed -n '1,12p' \"$f\" | grep -q \"⚠\\|СТАТУС\\|Статус\\|ШАПКА\" || echo \"$f\"; done | wc -l) -eq 0`, и без `\\|` в ячейке."
|
||
}
|
||
},
|
||
{
|
||
"title": "Канон-гейт — единственный источник «мест» для A1 — на 78% состоит из ложных срабатываний: он требует, чтобы канонная форма встречалась в переводе НЕ РЕЖЕ, чем иероглиф в исходнике, и штрафует нормальную русскую местоименную замену",
|
||
"severity": "критично",
|
||
"evidence": "contour.py:98-108 `canon_gaps`: `if min(len(re.findall(v[\"rx\"], out, re.I)), n) < n`. Разбор положительного класса (an11.py): из 74 флагов A1 «канонной формы НЕТ ВОВСЕ» — 16, «форма есть, но реже» — 58 (78.4%), медиана покрытия m/n = 0.82. Примеры: 3727846a2c «Цинь Фэн» n=13 m=12 → флаг; 1431129de6 n=21 m=20 → флаг; 53e0f3d653 n=21 m=18 → флаг. Частота срабатывания гейта: на flash-черновике 30/32 единиц (94%), на A0 — БОЕВОМ ПЕРЕПИСЕ, эталоне качества — 31/32 (97%), на dspro-черновике 14/16 (88%). Что фиксер делает по такому месту (an11.py): число повторов канонных форм A1 1454→1563 (+109, рост в 25 клетках из 30) против +26 у A3 и +19 у A6, которым канон-мест не давали. Грунт вреда, c73f4857e7: исходник «这三位金丹境强者» (три мастера уровня Золотого ядра), черновик «трёх мастеров Золотого Ядра» → выход A1 «трёх глав рода» — ранг культивации потерян правкой, сделанной ради канон-счётчика.",
|
||
"consequence": "Рушится и вход, и ось результата. Вход: арм A1 — носитель H-2а — на 78% чинит НЕ дефекты, а нормальную прозу, и «точечная правка вместо переписа» меряется на списке несуществующих поломок. Ось: «потеря канона» объявлена в Д0.6 безусловным дефектом и печатается отдельной осью (прогнозы Д0.9 №2 и №3 стоят на ней), но прибор срабатывает на 97% эталонных текстов — дискриминирующей силы у него нет, и норма Д0.6 «всякий классификатор обязан печатать свою частоту срабатывания на случайном входе» для canon_gaps не исполнена. Хуже: «починка» по такому флагу вкручивает в текст лишние повторы имён, то есть арм A1 системно двигает текст в translationese — ровно в то, против чего цель №1 продукта, — и судья будет штрафовать A1 за работу прибора, а не за контур.",
|
||
"fix": "До судейства: (а) пере-считать канон-ось, разделив положительный класс на «форма отсутствует вовсе» (m=0) и «дефицит частоты» (0<m<n), в отчёт нести только первый; (б) в качестве flags_of отдавать фиксеру только m=0; (в) исполнить норму Д0.6 — напечатать частоту срабатывания canon_gaps на A0 (97%) рядом с любым его числом; (г) 30 клеток A1 пере-снять после починки гейта либо объявить арм A1 непригодным для вывода по H-2а.",
|
||
"verdict": {
|
||
"line": "сырьё",
|
||
"refuted": false,
|
||
"why": "Пере-считал сам, не по формулировке автора (скрипт /tmp/claude-1000/-home-ubuntu-projects-textmachine/565edf3f-c90e-4aaf-8418-c2ec250acedc/scratchpad/an_ref.py, импорт contour.py без покупок).\n\nМЕХАНИКА ПОДТВЕРЖДЕНА. contour.py:98-108: `n = src.count(t)`, флаг при `min(len(re.findall(v[\"rx\"], out, re.I)), n) < n`, то есть требование ПАРИТЕТА ЧАСТОТ выход≥исходник. Флаг — единственный источник мест A1: сумма поля `places` по 30 клеткам A1 = 74 и совпадает с моим пере-счётом канон-флагов клетка-в-клетку, расхождений 0 (батарея не дала ни одного, Д-2 верна).\n\nЧИСЛА СОВПАЛИ ВСЕ, ДО ЗНАКА. «74 флага: m=0 — 16, 0<m<n — 58 (78.4%), медиана m/n 0.823»; 3727846a2c 秦风 n=13 m=12; 1431129de6 n=21 m=20 (плюс ещё 3 флага той же единицы); 53e0f3d653 n=21 m=18. Срабатывание: flash-черновик 30/32, A0 31/32, dspro-черновик 14/16. Повторы канонных форм: A1 1454→1563 (+109, рост в 25 из 30, падений 0), A3 +26 (13/5), A6 +19 (9/0).\n\nЧТО НЕВЕРНО В ФОРМУЛИРОВКЕ — три пункта.\n1) «Свойство не описано». Описано, и прямо: eval/dovodka/canon.py:13-16 — «ПОКРЫТИЕ… падает и когда термин передан ДРУГИМ переводом, и когда он заменён местоимением — а второе есть норма русской прозы», и там же покрытие СНЯТО как мера дефекта в пользу единообразия. Находка ценна не «неизвестным свойством прибора», а ПРОТИВОРЕЧИЕМ внутри одной фазы: Д5 покрытие отменил, Д4 сделал его единственным источником мест (contour.py:98-108, 262) и осью.\n2) «Дискриминирующей силы у оси нет» — неверно как сказано. Ось — не бинарное срабатывание, а капнутое покрытие bank.py:217-229. Оно армы разделяет, но в НЕВЕРНУЮ сторону: среднее покрытие A1 0.9608 против A0 0.8922, A3 0.8961, A6 0.9227; парно A1 против своей базы 0.8805→0.9608. Это Гудхарт, а не слепота.\n3) Грунт вреда c73f4857e7 отнесён не к тому классу. Пере-считал по терминам: флаг, породивший «трёх глав рода», — 家主 n=6, в черновике m=0 («глава клана»), то есть класс «формы НЕТ ВОВСЕ» — ровно тот, который починка (б) предлагает ОСТАВИТЬ. В той же клетке 金丹 покрытие 12→11 упало. Значит этот грунт ремонт (б) не поддерживает.\n\nДЕНЬГИ ЗАНИЖЕНЫ. A4 берёт места тем же гейтом (contour.py:262), поэтому прибор ведёт A1 $0.2269/30 клеток И A4 $0.1935/22 = $0.4204 из потраченных $1.1397 (37%), а не только A1.\n\nНОРМА Д0.6 — не нарушена ПОКА. docs/experiments/23-editor-tier.md кончается строкой 896 на Д0.10; секции результатов фазы Д нет, печатать частоту ещё нечего. Это живое обязательство, а не исполненный дефект.",
|
||
"corrected": "Канон-гейт (contour.py:98-108) требует паритета частот «канонная форма в выходе ≥ иероглиф в исходнике» и служит ЕДИНСТВЕННЫМ источником мест для двух платных армов — A1 ($0.2269, 30 клеток) и A4 ($0.1935, 22 клетки), 37% потраченного фазой. Из 74 флагов A1 только 16 — «канонной формы нет вовсе»; 58 (78.4%, медиана покрытия 0.823) — «форма есть, но реже», класс, который собственный файл фазы eval/dovodka/canon.py:13-16 объявил непригодным как мера дефекта («заменён местоимением — норма русской прозы») и снял в пользу единообразия. Д4 этот приговор не исполнил. Доля ложных внутри 58 не доказана поклеточно; на 3727846a2c показана прямо: «Цинь Фэн» 12 при n=13, альтернативных передач имени в черновике НОЛЬ, то есть пропущено местоимением. Главный вред — не слепота оси, а Гудхарт: армам выдали ось как список задач, и они её выиграли по построению — покрытие A1 0.9608 против A0 0.8922 и A3 0.8961 (парно A1 0.8805→0.9608), повторов канонных форм +109 при 25 ростах и 0 падений против +26 у A3 и +19 у A6. Прогноз Д0.9 №2 («A4 даст лучшее покрытие канона») будет судиться прибором, который A1/A4 велено было оптимизировать, а A1 системно набивает текст лишними повторами имён — против цели №1 продукта. Побочный вред фиксера классом флага не лечится: в c73f4857e7 ранг культивации потерян («трёх мастеров Золотого Ядра» → «трёх глав рода») по ЗАКОННОМУ флагу 家主 m=0, и там же покрытие 金丹 упало 12→11. Поэтому починка «отдавать фиксеру только m=0» необходима, но недостаточна. До судейства: канон-ось нести двумя числами (m=0 отдельно от дефицита частоты) и рядом печатать частоту срабатывания на A0 — 31/32; на A1/A4 как носителей H-2а вывод строить нельзя без пере-снятия либо явного объявления армов непригодными. Норма Д0.6 пока не нарушена: отчёт фазы Д не написан (файл кончается на строке 896)."
|
||
}
|
||
},
|
||
{
|
||
"title": "Эхо-мина 63ab55ac5c прошла в фазу Д: contour.py берёт черновик новых единиц в обход гейта draft_reject_reason, куплено 3 клетки на КИТАЙСКОМ входе, оба выхода фиксера сами являются эхо-минами",
|
||
"severity": "критично",
|
||
"evidence": "contour.py:83 `return t if t.strip() else PAN23.draft_b(uid)` — фолбэк для новых единиц; panel.py:112-115 `draft_b` читает файл БЕЗ проверки, тогда как для старых единиц tenant_panel/panel.py:124-132 `draft_text` гейт применяет. Замер (an4.py): у 63ab55ac5c доля кириллицы в «черновике» 0.000, ханьцзи 0.802. Прогон существующего $0-гейта: `draft_reject_reason(draft)` = 'эхо исходника'; `draft_reject_reason` на выходах — dv-a-a1-63ab55ac5c 'эхо исходника', dv-a-a3-63ab55ac5c 'эхо исходника'. Диффом (an-скрипт) видно, что фиксер A1 подставлял русские канон-термины ВНУТРЬ китайского текста: «род Цинь余孽,Цинь Фэн!». Стоимость (an9.py): dv-a-a1 $0.01246 + dv-a-a3 $0.00492 + dv-a-a3-crit $0.00263 = $0.0200. Единица объявлена дефектной в паке 23 (23-editor-tier.md:351-356), гейт там подключён (editor_tier/panel.py:98) — фаза Д его не зовёт.",
|
||
"consequence": "$0.0200 сожжено; клетка A3-критика выдала разбор на китайском (22 «места» иероглифами), клетка A3-фиксера — 100% китайский текст. Если эти три клетки попадут в судейскую пачку, судья сравнит русский A0 с китайским A3/A1 — это не «контур хуже переписа», это катастрофа рига, которая утянет средний перевес A3/A0 и A1/A0 вниз на 1/32 выборки и может сама по себе перевернуть знак ставки владельца H-2б.",
|
||
"fix": "Единицу 63ab55ac5c исключить из всех контрастов фазы Д и объявить в отчёте (n станет 31/29); в contour.base_draft добавить вызов BO.draft_reject_reason на фолбэк-ветке — тот же гейт, что уже подключён в паке 23, чтобы класс не вернулся третий раз.",
|
||
"verdict": {
|
||
"line": "сырьё",
|
||
"refuted": false,
|
||
"corrected": "Эхо-мина 63ab55ac5c прошла в фазу Д: contour.base_draft берёт черновик новых единиц через PAN23.draft_b в обход гейта draft_reject_reason, который для старых единиц применяется. Куплены 3 клетки на китайском входе за $0.02002; оба выхода фиксера сами не проходят гейт. Масштаб точен: гейт, прогнанный по всем 32 базам, отвергает РОВНО одну единицу. Ключевое отличие от объявленного в паке 23: там оба арма контраста делили китайскую базу, здесь base_a0 для этой единицы — 8167 знаков, кириллица 1.0 (русский), против китайских A1/A3, то есть контраст стал асимметричным — это НЕ объявлено ни в Д0, ни в промте заказа. Дополнительно: докстринг cmd_selftest (contour.py:190) обещает «годность входов», а contour.py:201 проверяет только .strip(). Последствие следует смягчить: смещение среднего перевеса A1/A0 и A3/A0 порядка 0.2–0.4 балла (вес единицы / 32) плюс раздутие дисперсии — это значимо при MDE 1.29, но «перевернуть знак H-2б сама по себе» клетка не может: при пред-объявленной полосе −1.0…+1.0 для этого нужен вес единицы около −32. Починка в находке верна: исключить единицу из контрастов фазы Д (n 31/29) и объявить; добавить BO.draft_reject_reason на фолбэк-ветку base_draft и в селфтест.",
|
||
"why": "Пытался опровергнуть по четырём линиям — все четыре не прошли.\n\n(1) Механизм подтверждён чтением кода. contour.py:82-83 `t = P22.draft_text(ANCHOR, uid); return t if t.strip() else PAN23.draft_b(uid)`. P22.draft_text (eval/tenant_panel/panel.py:124-132) гейт применяет: `if c and not BO.draft_reject_reason(c)`. PAN23.draft_b (eval/editor_tier/panel.py:110-113) читает json без единой проверки. `grep -rn \"bakeoff\\|BO\\.\" eval/dovodka/*.py` → ПУСТО: фаза Д не зовёт гейт нигде.\n\n(2) Единица идёт именно по фолбэк-ветке. Мой скрипт через importlib над contour.py: `in old: False in new: True`; `P22.draft_text len 0 | draft_b len 2243`; `base_draft profile {'len': 2243, 'cyr': 0.0, 'han': 1.0}`; `BO.draft_reject_reason(base_draft) -> 'эхо исходника'`.\n\n(3) Числа и масштаб верны. Прогон гейта по ВСЕМ 32 базам (base_draft и base_a0): `units with rejected base: 1` — только 63ab55ac5c. Клетки из ~/books/dovodka: dv-a-a1-63ab55ac5c cost 0.012464 finish stop places 8 {cyr 0.143, han 0.857}; dv-a-a3-63ab55ac5c cost 0.004923 places 22 {han 1.000}; dv-a-a3-crit-63ab55ac5c cost 0.002632. TOTAL $0.02002 — сходится с заявленным. Все три не проходят draft_reject_reason. Голова A1 подтверждает подстановку канон-терминов внутрь китайского: '青龙国,帝都。\\n\\nРезиденция левого канцлера深处的书房…'. A4 для этой единицы не куплен (гард остановил на 22).\n\n(4) Не объявлено, и конфигурация ДРУГАЯ, чем объявленная в паке 23. Пак 23 объявляет единицу в §8.2 (docs/experiments/23-editor-tier.md:350-364) и подключает гейт в editor_tier/panel.py:98 — но внутри cmd_b_run, то есть блокирует БУДУЩИЕ покупки; сам браконьерский файл лежит на диске, и draft_b его отдаёт. Grep по docs/POLYGON_EXP2223_REDO_SESSION_PROMPT.md, eval/dovodka/requirements.md и по секции Д0 (строки 719-896) — упоминаний 63ab55ac5c или гейта годности базы НЕТ. При этом обоснование пака 23 («вход у обоих армов контраста ДЕЙСТВИТЕЛЬНО одинаковый») в фазе Д не держится: base_a0(63ab55ac5c) = 8167 знаков, кириллица 1.0, против китайских A1/A3.\n\n(5) Дополнительно найдено при попытке опровержения: contour.py:190 докстринг cmd_selftest заявляет «изоляция армов и годность входов», а contour.py:201 проверяет только `if not base_draft(u[\"uid\"]).strip()` — пустоту, не годность. Селфтест на этой мине зелёный по построению.\n\nЕдинственное, что в находке завышено, — фраза «может сама по себе перевернуть знак ставки владельца H-2б». При n=32 сдвиг среднего = вес единицы/32; против пред-объявленной полосы −1.0…+1.0 (Д0.9) и MDE 1.29 (Д0.3) для переворота +1.0 нужен вес около −32. Обоснованная формулировка — смещение 0.2–0.4 и раздутие дисперсии на обоих контрастах."
|
||
}
|
||
},
|
||
{
|
||
"title": "Фактические n армов (A1 30, A4 22, A6 16, A2 0) меньше объявленных 32, и по собственному правилу пре-рега «MDE больше цели ⇒ ось описательная» носители H-2а и H-1 теряют статус несущих; вдобавок сам пре-рег противоречит инструменту, который называет",
|
||
"severity": "критично",
|
||
"evidence": "Наличие клеток (an-скрипт по ~/books/dovodka): A1 30/32 (нет 474f822806 и 9b16c9c9a7 — у обоих канон-пробелов 0, значит добрать их нельзя структурно), A3 32/32, A4 22/32, A6 16/16, A2 0. `eval/.venv/bin/python eval/dovodka/power.py` печатает «Д4 edit-контур zh 32 3 2.12 1.49 1.50 НЕСУЩАЯ» и Холм ПО ТРЁМ, а замороженная Д0.3 (23-editor-tier.md:760) печатает «Д4 32 5 2.12 1.29» и Д0.5 (строка 805) — «Холм по пяти»; power.py с фриза da5f4d0 не менялся (git log -- eval/dovodka/power.py). Пере-счёт тем же power.mde(2.12, n, 3): n=32 → 1.49; n=30 → 1.54; n=22 → 1.80; n=16 → 2.11 при ЦЕЛИ 1.50. При k=5, как в доке, даже n=32 даёт 1.58 > 1.50.",
|
||
"consequence": "A1/A0 (H-2а) на реальных 30 единицах имеет MDE 1.54 > цели 1.50, A6/A0 (H-1) на 16 единицах — 2.11: по правилу Д0.3 («ось объявляется описательной, если MDE больше цели») обе несущие гипотезы фазы становятся описательными ЕЩЁ ДО чтения перевесов, а несущим остаётся только A3/A0 с запасом 0.01. Если же верна замороженная таблица Д0.3 (k=5), несущих контрастов нет вовсе ни при каком n. Судейство 148 клеток даст числа, под которыми нельзя написать ни CONFIRM, ни REJECT — деньги фазы уйдут в описательный результат, и обнаружится это после покупки судей.",
|
||
"fix": "До заказа судейских пачек согласовать с владельцем одно из двух: (а) признать A1/A6 описательными и переписать Д0.3/Д0.5, объявив расхождение k=5 против k=3 как эрратy пре-рега; либо (б) добрать n. Разъехавшиеся k=5 (док) и k=3 (power.py) обязаны сойтись ДО первого судейского запуска — сейчас неизвестно, какое семейство несёт поправку Холма.",
|
||
"verdict": {
|
||
"line": "сырьё",
|
||
"refuted": false,
|
||
"why": "Ядро находки подтверждается исполнением, но три из четырёх её опор — неверны, и «критично» не выдерживает.\n\nЧТО ПОДТВЕРДИЛОСЬ (расхождение фриза с инструментом — реально).\n`git log --oneline -- eval/dovodka/power.py` → ровно один коммит `da5f4d0`; `git diff da5f4d0 -- eval/dovodka/power.py` → пусто; `git status --porcelain` по обоим файлам → пусто. То есть док и инструмент заморожены ОДНИМ коммитом и противоречат друг другу.\n`eval/.venv/bin/python eval/dovodka/power.py` печатает:\n `Д4 edit-контур zh 32 3 2.12 1.49 1.50 0.0000 НЕСУЩАЯ` · `Д3 ... 16 1 2.12 1.83 2.00 0.0000` · `Д6 ... 9 3 2.90 3.85` · `Д4 edit-контур zh — ПЕРВИЧНОЕ (Холм по 3)`.\nЗамороженный док `docs/experiments/23-editor-tier.md:760-763` печатает `32 5 2.12 1.29`, `16 5 2.12 1.83 ... 0.0002`, `9 3 2.90 3.33`, а `:805` и `:810` — «Холм по пяти».\nПричина расхождения установлена арифметически: колонка MDE дока воспроизводится ДО-ревизионной формулой (константа 2.8 без поправки Холма): 2.8·2.12/√32·1.23 = 1.291 = докова 1.29; 2.8·2.90/√9·1.23 = 3.329 = докова 3.33; `min_p(16,5)` = 0.0001526 = доковы 0.0002. Сам `power.py` в докстринге `mde()` документирует эту правку («первая редакция применяла 2.8 всегда... при k=5 это 3.417»). Значит Д0.3 — устаревшая распечатка, а не альтернативный расчёт. Это эррата фриза, и её надо закрыть.\n\nЧТО ОПРОВЕРГНУТО.\n1. «A6 16 меньше объявленных 32» — ложь. План A6 = 16 С САМОГО НАЧАЛА: док `:860` `ФД-F H-1: A6, dspro-черновик + оба контура (n=16) 0.280`; `eval/dovodka/contour.py:179` `n = len(old) if a == \"A6\" else len(us)`; `contour.py --plan` печатает `A6: куплено 16 из 16`. A6 УКОМПЛЕКТОВАН. Проблема MDE у H-1 существует, но она НЕ от недобора сырья — она была в пре-реге в момент фриза.\n2. «A1 = n 30, добрать нельзя структурно» — вывод неверен. Я выполнил `flags_of` на двух отсутствующих единицах: `474f822806 flags 0 draftlen 7814 a0len 7862` и `9b16c9c9a7 flags 0 draftlen 7037 a0len 6695`. По определению арма (`contour.py:263-265`: «мест нет — чинить нечего, клетка не покупается») выход A1 на этих единицах ТОЖДЕСТВЕН черновику, который куплен и лежит. Единица не потеряна, её значение контраста определено и стоит $0. Более того, выкинуть эти две — это отбор ровно тех единиц, где флаговый контур не сработал, то есть смещение В ПОЛЬЗУ A1. Правильное n для A1/A0 = 32, MDE 1.491 < цели 1.50, H-2а статус несущей СОХРАНЯЕТ. (Оговорка: сборка судейских пачек обязана материализовать A1≡черновик — сейчас `text_of` (`contour.py:166-171`) на отсутствующей клетке возвращает \"\", и сборки ещё нет.)\n3. «Если верна замороженная таблица Д0.3 (k=5), несущих контрастов нет вовсе ни при каком n» — ложь дважды. Сама таблица `:760-763` печатает НЕСУЩАЯ для Д4, Д3 и Д1. И `power.py` в своём выводе печатает `k=5 цель 1.50 → n ≥ 36`, то есть n существует.\n4. «неизвестно, какое семейство несёт поправку Холма» — ложь. `power.py` словари `PRIMARY`/`SECONDARY` объявляют его явно и с обоснованием («объявляются ДО покупок, и это НЕ сужение задним числом»); A2/A0 и A4/A0 там пред-объявлены ОПИСАТЕЛЬНЫМИ. Поэтому недобор A4 (22/32) и ноль A2 ни одной несущей гипотезы не касаются и в k=3 не входят. Состояние — не «неизвестно», а «два фриза разошлись, и устаревшая сторона установлена — доковая».\n5. «носители H-2а и H-1 теряют статус несущих» → по H-2а неверно (см. п.2). Статус осей при обоих прочтениях совпадает: Д4 несущая и при 1.29, и при 1.49; Д3 1.83<2.00 в обоих; Д6 описательная в обоих; Д1 не меняется. Ни один статус ОСИ не переворачивается — значит «деньги фазы уйдут в описательный результат» верно ровно для одного контраста из трёх, и не из-за сырья.\n\nЧисла находки при этом пересчитаны мной и арифметически верны: `mde(2.12,n,3)` → n=32 1.491 · n=30 1.540 · n=22 1.799 · n=16 2.109; `mde(2.12,32,5)` = 1.575.",
|
||
"corrected": "Тяжесть — средняя (не критично), и находка распадается на две разные, ни одна из которых не про «недобор сырья».\n\n(1) ЭРРАТА ФРИЗА. Замороженная таблица Д0.3 (`23-editor-tier.md:760-763`) и фраза «Холм по пяти» (`:805`, `:810`) НЕ воспроизводятся инструментом, который сам док называет источником: `power.py` (единственный коммит `da5f4d0`, диффа с фриза нет) печатает k=3 для Д4, k=1 для Д3, MDE 1.49/1.83/3.85 и объявляет первичное семейство из трёх, а A2/A0 и A4/A0 — описательными. Колонка MDE дока воспроизводится ДО-ревизионной формулой (2.8 без Холма: 2.8·2.12/√32·1.23=1.291=«1.29»; 2.8·2.90/√9·1.23=3.329=«3.33»), то есть Д0.3 — устаревшая распечатка, а не расчёт-конкурент. Ни один СТАТУС оси при этом не переворачивается (Д4 несущая при обоих числах, Д6 описательная при обоих), так что это дефект документа, а не вывода: перед первой судейской пачкой Д0.3/Д0.5 привести к выводу `power.py` и подписать расхождение как эррату.\n\n(2) H-1 НЕДОМЕРЕН ПО ПЛАНУ, А НЕ ПО СЫРЬЮ. Носитель H-1 — контраст A6/A0 — заявлен в первичном семействе Д4 (`power.py` PRIMARY), но его n = 16 БЫЛ ЗАПЛАНИРОВАН таким: док `:860` «ФД-F H-1: A6 (n=16)», `contour.py:179`, `--plan` → «A6: куплено 16 из 16». При n=16, k=3, sd 2.12 MDE = 2.109 против цели 1.50, то есть по собственному правилу Д0.3 («ось описательная, если MDE больше цели») H-1 был описательным ЕЩЁ ДО первой покупки — а строка мощности Д0.3 печатает для всей оси одно n=32 и этого не показывает. Вот это и есть настоящая находка: не «сырья не хватило», а «несущий контраст объявлен несущим при n, которого никогда не планировалось». Починка: до заказа судей либо признать H-1 описательным и переписать Д0.3/Д0.5, либо добрать A6 до n≥32 (единиц dspro-черновика больше нет — `base_draft2` есть только у 16 старых, значит фактически только первое).\n\nЧто из находки НЕ надо чинить: A1 30 клеток — это не n=30, а n=32 (две единицы имеют 0 флагов, выход A1 на них тождествен черновику, доступен за $0; выкидывание их сместило бы оценку в пользу A1). Требование к сборке: судейская пачка обязана подставлять A1≡черновик, `text_of` сейчас вернёт \"\". A4 22/32 и A2 0 — контрасты пред-объявлены описательными в `power.py` SECONDARY, поправку Холма не несут и несущих выводов не трогают."
|
||
}
|
||
},
|
||
{
|
||
"title": "Пять оплаченных клеток вернули вход ПОБАЙТНО без единой правки; четыре из них — арм A1, то есть на этих единицах A1 есть сырой flash-черновик, а одна — арм A4, побайтно равный A0",
|
||
"severity": "важно",
|
||
"evidence": "an5.py, сравнение content с базой арма: A1 3727846a2c, A1 53e0f3d653, A1 cf9a90d9fe, A1 ed068182cf, A4 b2a7464dbd — во всех пяти out == вход. Стоимость (an9.py) $0.0366. У всех пяти «место» было ложным срабатыванием счётчика частоты (an-скрипт: 3727846a2c «Цинь Фэн» n=13 m=12; 53e0f3d653 n=21 m=18; cf9a90d9fe n=16 m=14; b2a7464dbd n=18 m=16), то есть модель повела себя правильно, а деньги списаны.",
|
||
"consequence": "На 4 единицах из 30 контраст A1/A0 перестаёт быть «флаговый контур против переписа» и становится «сырой черновик против переписа» — а собственный эффект редактора замерен в эксп-22 как +4.44, то есть эти 13% клеток тянут перевес A1/A0 вниз на величину, в три раза превышающую MDE оси (1.54). Клетка A4 b2a7464dbd побайтно равна A0 — это в точности вырожденная пара класса «CTRLfloorA ≡ T1», который Д0.6 запрещает называть замером; судья получит два одинаковых текста и выдаст ноль по построению.",
|
||
"fix": "Пять клеток пометить в ключе как «правок ноль» и либо исключить из контрастов, либо (честнее) объявить отдельной строкой отчёта «доля клеток, где контур не сделал ничего» — это самостоятельный результат про флаговый контур. Побайтное равенство A4≡A0 из судейской пачки убрать безусловно.",
|
||
"verdict": {
|
||
"line": "сырьё",
|
||
"refuted": false,
|
||
"corrected": "ФАКТ ПОДТВЕРЖДЁН, ПОСЛЕДСТВИЕ И ПОЧИНКА — НЕТ.\n\nВерное ядро: пять оплаченных фиксер-клеток вернули свой вход ПОБАЙТНО (A1 ed068182cf, cf9a90d9fe, 53e0f3d653, 3727846a2c; A4 b2a7464dbd), суммарно $0.036621, все finish=stop. Ни у A3 (32 клетки), ни у A6 (16) no-op нет ни одного — no-op есть свойство ФЛАГОВОГО контура, а не фиксера вообще. В докax фазы Д это нигде не объявлено.\n\nИсправления:\n\n1. МАСШТАБ ЗАВЫШЕН ~5–8×. MDE 1.54 верен (mde(2.12, n=30, k=3)=1.540), но сдвиг перевеса A1/A0 = 4/30 × 4.44 = 0.59, то есть 0.38 MDE, а НЕ «в три раза выше MDE». 2.88× — это величина НА ОДНОЙ клетке, поданная как сдвиг средней.\n\n2. НЕДОСЧЁТ. contour.py:262-264 не покупает клетку при пустом списке мест; у 474f822806 и 9b16c9c9a7 флагов ноль, A1-клетки нет вовсе — там A1 тоже равен сырому черновику. Верная доля 6/32 = 19% (не 4/30 = 13%), сдвиг 0.83, всё равно ниже MDE.\n\n3. «У ВСЕХ пяти место — ложное срабатывание счётчика частоты» НЕВЕРНО для ed068182cf — единственной клетки, которую улика молча пропускает. У неё 3 флага, среди них 筑基 n=18 против m=11 (недобор 39%), это не off-by-one, и ложноположительность там не показана.\n\n4. A4 ≡ A0 — НЕ класс «CTRLfloorA ≡ T1». Д0.6 запрещает брать боевую клетку ПОЛОВИНОЙ ШУМОВОГО ПОЛА; §12а (23-editor-tier.md:539-547) объясняет причину: ноль по построению обнуляет пол КАК КОНТРОЛЬ. В контрасте арма ноль — это истинный ответ (канон-фиксер ничего не поменял), и A4/A0 к тому же объявлен ОПИСАТЕЛЬНЫМ (power.py, семейство Д4), Холма не несёт и вывода не двигает.\n\n5. ПОЧИНКА «убрать A4≡A0 из пачки безусловно» ВРЕДНА: выброс истинного нуля смещает оценку A4 вверх. Правильно — засчитать ноль без оплаты судьи, а не исключить из средней. Так же и с A1: исключать клетки нельзя (это и есть продукт арма), годится только второй вариант автора — отдельная строка отчёта.\n\nЧто реально стоит внести в отчёт: «доля единиц, где флаговый контур не изменил текст = 6/32 (19%): 4 оплаченные клетки-no-op $0.0367 + 2 единицы без флагов»; и рядом — сравнение с объявленным в эксп-22 §7 (22-tenant-panel.md:177) классом «no-op редактора» 1/62 = 1.6%: у флагового контура он в 8 раз чаще. Это и есть новость, а не сам факт существования no-op.",
|
||
"why": "Собственная проверка (не по следам улики):\n\n(1) Скрипт /tmp/claude-1000/-home-ubuntu-projects-textmachine/565edf3f-c90e-4aaf-8418-c2ec250acedc/scratchpad/chk.py грузит contour.py и сверяет content КАЖДОЙ фиксер-клетки с базой ЕЁ арма (base_draft для A1/A3 — contour.py:88-91, base_a0 для A4 — contour.py:93-96, base_draft2 для A6 — contour.py:98-100). Вывод: «всего фиксер-клеток: 100 / ПОБАЙТНО равных базе: 5 / A1 ed068182cf cost 0.005964 places 3 · A1 cf9a90d9fe 0.005063 places 1 · A1 53e0f3d653 0.006261 places 1 · A1 3727846a2c 0.013037 places 1 · A4 b2a7464dbd 0.006296 places 1 / сумма стоимости побайт-равных: 0.036621 / равных после strip (но не побайтно): 0». Все пять с finish=stop. A3 и A4-прочие — ноль совпадений.\n\n(2) chk2.py воспроизводит canon_gaps (contour.py:104-115) для этих пяти: 3727846a2c 秦风 n=13 m=12 · 53e0f3d653 n=21 m=18 · cf9a90d9fe n=16 m=14 · b2a7464dbd n=18 m=16 — цифры улики совпадают с моими. НО ed068182cf: три флага, 秦风 16/13, 筑基 18/11, 苏晴雪 8/7. chk3.py по тексту черновика: rx `заклад\\w*\\s+фундамен\\w*` даёт 11 хитов, слово «фундамент» встречается 12 раз (12-й — «заложить фундамент», глагольная форма, мимо rx), против 18 вхождений 筑基 в исходнике. Недобор 39% — не «ложное срабатывание счётчика частоты», и улика этот пятый случай не приводит вовсе.\n\n(3) chk4.py: A1-клеток на диске 30 из 32; единиц без A1-клетки — 474f822806 и 9b16c9c9a7, у обеих flags_of даёт 0, и contour.py:262-264 («мест нет — чинить нечего, клетка не покупается») покупку не делает. Значит A1 = сырой черновик ещё на 2 единицах сверх четырёх → 6/32.\n\n(4) Арифметика через power.py (mde, power.py:117-129): mde(2.12, n=30, k=3) = 1.540 — 1.54 улики грунтован (пре-рег Д0.3 печатает 1.29 при k=5, текущий power.py — 1.491 при n=32/k=3). Сдвиг: 4/30*4.44 = 0.592; 6/32*4.44 = 0.833; 4.44/1.540 = 2.88. То есть «три MDE» — это НА КЛЕТКУ, а сдвиг средней 0.38–0.54 MDE.\n\n(5) Д0.6 (docs/experiments/23-editor-tier.md:822-824) говорит буквально: «Шумовой пол — парой, чьи половины судят РАЗНЫЕ сессии… боевая клетка половиной пола не берётся (в эксп-23 CTRLfloorA ≡ T1 в 16/16, и контроль был пуст)». §12а (там же, 539-547) объясняет, что порок именно КОНТРОЛЯ: «как контроль эта строка пуста». Про совпадение текстов внутри боевого контраста ни Д0.6, ни §12а не говорят ничего. Плюс `eval/.venv/bin/python eval/dovodka/power.py` печатает A4/A0 в описательных: «A4/A0 — канон-фиксер ПОСЛЕ переписа: его несущая ось — покрытие канона, а оно детерминировано и шума не имеет» — Холма не несёт, вывода не двигает.\n\n(6) Объявленность: grep по docs/ и eval/ на все пять uid даёт только эксп-22 (22-tenant-panel.md:1244,1255) и по другому поводу (эхо у gemini-flash-lite) — в фазе Д ни одна из пяти клеток не описана. При этом сам КЛАСС объявлен раньше: 22-tenant-panel.md:177 «deepseek-v4-flash в роли редактора однажды вернул черновик побайтно без правок (1 клетка из 62) — класс „no-op редактора“». 1/62 = 1.6% против 4/30 = 13.3% у A1 — это и есть та часть находки, что действительно новая."
|
||
}
|
||
},
|
||
{
|
||
"title": "Обрезка списка критика places[:40] не случайна, а систематически отрезает КОНЕЦ главы: 88% выброшенных мест лежат во второй половине текста, 40-е место в среднем приходится на 0.6 длины",
|
||
"severity": "важно",
|
||
"evidence": "contour.py:286 `fix_msgs(src, draft, places[:40])`. an8.py находит позицию цитаты каждого места в черновике: по 27 обрезанным клеткам из ОТРЕЗАННЫХ мест во второй половине текста лежит 727 из 823 = 88.3%. Позиция 40-го места (доля длины текста): A6 ef9cd38ec4 0.31, A3 c73f4857e7 0.42, A6 1431129de6 0.43, A3 e40cdfbc3e 0.44, A6 41599f30df 0.45, A3 cf9a90d9fe 0.48, A3 d1e353d569 0.48. Медиана позиции отрезанных мест — 0.65–1.00 у всех клеток без исключения.",
|
||
"consequence": "Известная находка Д-3 («потеряно 512 и 374 замечания») на деле хуже, чем «потеряно N»: у 17 из 32 клеток A3 и 10 из 16 клеток A6 фиксер физически не видел замечаний по второй половине главы, то есть арм измеряет «смысловой контур на первых ~50-60% текста». Судья читает главу целиком и увидит нетронутый хвост — систематическое, а не шумовое занижение ставки владельца H-2б. Направленность смещения в отчёте не объявлена, объявлено только число.",
|
||
"fix": "В отчёт вписать не «потеряно 886 мест», а «фиксер A3/A6 не получал замечаний по хвосту главы, медиана точки отсечения 0.6 длины»; при пере-снятии либо поднять лимит, либо резать равномерно по всей длине текста, а не по порядку списка.",
|
||
"verdict": {
|
||
"line": "сырьё",
|
||
"refuted": false,
|
||
"why": "Пытался опровергнуть тремя ходами — «уже объявлено», «числа не те», «вывод не меняется». Опровергнуть не вышло: механизм и головное число воспроизвелись независимо.\n\n1) НЕ ОБЪЯВЛЕНО. `grep -rn \"\\[:40\\]|40 мест|обрез|усеч|truncat\" eval/dovodka/*.py eval/dovodka/requirements.md docs/experiments/23-editor-tier.md docs/experiments/22-tenant-panel.md docs/POLYGON_EXP2223_REDO_SESSION_PROMPT.md` даёт ровно один хит по существу — сам код `eval/dovodka/contour.py:286` `fix_msgs(src, draft, places[:40])`. Ни докстринг контура (contour.py:1-24, где армы описаны построчно: «A3 черновик + СМЫСЛОВОЙ LLM-критик … → фиксер»), ни пре-рег Д0, ни отчёты 22/23 предела в 40 мест не называют вовсе — ни числом, ни направленностью. Объявленным ограничением это не является.\n\n2) ЧИСЛА ВЕРНЫ. Свой скрипт (/tmp/claude-1000/-home-ubuntu-projects-textmachine/565edf3f-c90e-4aaf-8418-c2ec250acedc/scratchpad/an_mine.py, запуск eval/.venv/bin/python; парсинг мест тем же правилом, что contour.py:280, черновик через C.base_draft/C.base_draft2, позиция цитаты — поиск подстроки с префиксным фолбэком), 48 клеток критика:\n - обрезанных клеток 27 (A3 17 из 32, A6 10 из 16), выброшено 886 мест (512 + 374) — совпадает с Д-3;\n - из отрезанных мест с разрешённой позицией 741 из 839 = 88.3% лежат во второй половине текста (у автора находки 727/823 = 88.3% — расхождение только в доле разрешённых цитат);\n - медиана позиции ОТРЕЗАННЫХ мест ≥0.65 в каждой из 27 клеток без исключения (min 0.65, max 1.00) — «у всех клеток без исключения» подтверждено;\n - механизм: список критика идёт по тексту, доля инверсий порядка 0.041, то есть `[:40]` — это срез по позиции в главе, а не случайная выборка;\n - все семь p40 из улики сошлись с моими до сотых (ef9cd38ec4 0.31, c73f4857e7 0.42, 1431129de6 0.43, e40cdfbc3e 0.44, 41599f30df 0.45, cf9a90d9fe 0.48, d1e353d569 0.48).\n\n3) ВЫВОД. Фиксер получает полный черновик (fix_msgs, contour.py:145-151), но промт FIX_HEAD (contour.py:128-134) прямо запрещает трогать что-либо вне списка — значит на обрезанных клетках хвост главы для арма недоступен по построению, и это систематический, а не шумовой сдвиг ставки H-2б.\n\nЧТО В ФОРМУЛИРОВКЕ НЕВЕРНО (см. corrected): «в среднем 0.6» — это среднее (0.607), медиана 0.524, разброс 0.31–0.97, а семь примеров улики — самый низкий хвост распределения. И «фиксер не видел замечаний по второй половине» верно НЕ для всех 27 клеток: у 6 из 25 разрешённых p40 > 0.85 (A3 3754987548 0.88/−5, A3 7d0258aec0 0.88/−14, A3 9120ad112e 0.92/−6, A3 fb9ed5709e 0.97/−1, A6 9120ad112e 0.86/−12, A6 f6da9f76b2 0.97/−1) — там срез задел только самый конец. Тяжесть «важно» держится: 12 клеток из 25 режутся до 0.5 длины, и именно они несут основную массу потерь (de3916de62 −110, ef9cd38ec4 −72, c73f4857e7 −70).",
|
||
"corrected": "Обрезка `places[:40]` (eval/dovodka/contour.py:286) режет не случайную выборку, а КОНЕЦ главы: список критика упорядочен по тексту (доля инверсий 0.041), поэтому срез — это точка отсечения по длине. На 27 обрезанных клетках (A3 17/32, A6 10/16, выброшено 886 мест) 741 из 839 отрезанных мест с разрешённой позицией = 88.3% лежат во второй половине текста, а медиана позиции отрезанных мест ≥0.65 в КАЖДОЙ клетке без исключения. Точка отсечения (позиция 40-го места в долях длины): медиана 0.52, среднее 0.61, разброс 0.31–0.97 — распределение неоднородно: у 12 клеток из 25 срез приходится на первую половину (до 0.5) и там фиксер по хвосту главы не получил ни одного замечания, у 6 клеток срез за 0.85 и потери составляют 1–14 мест. Основная масса потерь — у клеток с ранним срезом (de3916de62 −110, ef9cd38ec4 −72, c73f4857e7 −70).\nСледствие сверх Д-3: число «886 потерянных мест» скрывает направленность. На тяжело обрезанных клетках арм измеряет «смысловой контур на первых ~50% текста», тогда как судья читает главу целиком — систематическое (не шумовое) занижение ставки владельца H-2б. Вывод по A3/A6 ещё не снят (судья не куплен), поэтому опубликованную цифру это пока не меняет, но меняет описание того, ЧТО арм измеряет.\nПочинка: в отчёт вписать не «потеряно 886 мест», а «на 27 клетках список критика усечён по позиции в тексте; медиана точки отсечения 0.52 длины, 88% потерянных мест — во второй половине главы»; при пере-снятии либо снять лимит, либо резать равномерно по длине текста, а не по порядку списка."
|
||
}
|
||
},
|
||
{
|
||
"title": "В список «мест, где перевод неверен» фиксеру уходят строки, которыми критик прямо объявил перевод ВЕРНЫМ",
|
||
"severity": "важно",
|
||
"evidence": "Промт фиксера (contour.py:129-130): «СПИСОК МЕСТ, где перевод неверен… Почини ТОЛЬКО перечисленные места». Парсер (contour.py:281) берёт любую строку, начинающуюся с «-», без разбора вердикта. Строгий счёт (an-скрипт с регуляркой по «приемлемо|верно|допустимо|не ошибка|ок.»): 119 из 1518 ушедших фиксеру мест = 7.8%, затронуто 33 клетки из 48, максимум 16 на клетку. Дословно: «в несколько чжанах от прежнего места → реалия «чжан» оставлена без пояснения, но это допустимо»; «Золотое ядро → 金丹 — канон «Золотое ядро»; употребление верно.»; «все люди левого канцлера → 左相的人 — «люди левого канцлера», верно.»; «алые губы → 红唇 — «красные губы»; «алые» — украшение, но не ошибка.»",
|
||
"consequence": "Фиксеру дана инструкция «почини» по 119 местам, которые чинить не надо, — прямой канал порчи текста в арме, несущем главную ставку владельца H-2б, причём порча концентрированная (до 16 таких мест в одной клетке). Плюс эти строки занимают квоту 40, вытесняя настоящие замечания (см. предыдущую находку), и раздувают поле places, по которому считается объём работы контура.",
|
||
"fix": "В парсер мест добавить отсев строк с вердиктом «верно/приемлемо/допустимо/не ошибка» ДО среза [:40]; при пере-снятии — потребовать от критика в промте выводить только ошибки и запретить строки-подтверждения. Для уже купленного: пере-считать поле places после отсева, прежде чем печатать «сколько мест нашёл смысловой контур».",
|
||
"verdict": {
|
||
"line": "сырьё",
|
||
"refuted": false,
|
||
"corrected": "Критик выдаёт строки-подтверждения («верно», «допустимо», «не ошибка», «ок»), парсер их не отсеивает (contour.py:281 берёт любую строку с «-»), и они уходят фиксеру под заголовком «СПИСОК МЕСТ, где перевод неверен» (contour.py:129-131). Масштаб: 116 строк (7.6%) по строгому счёту, 199 (13.1%) по широкому, из 1518 фактически отправленных мест; 26-38 клеток из 48. НО заявленное последствие «прямой канал порчи текста» ОПРОВЕРГНУТО исполнением: фиксер правит подтверждённые места в 20.4% случаев (30 из 147, чья цитата дословно есть в черновике) против 74.3% (939 из 1263) для мест вообще — то есть он читает вердикт и подтверждения в основном не трогает; абсолютная порча ~30 мест на 48 клеток, и большинство из них несут неявную правку в самой строке. Реальный вред — второй, не названный главным: 166 строк-подтверждений занимают квоту [:40] в 25 клетках из 27, где квота вообще связывает, вытесняя настоящие замечания (усиливает Д-3), и раздувают поле places (contour.py:286), по которому отчёт считает объём работы смыслового контура. Починка: отсев вердиктов до среза [:40] и запрет строк-подтверждений в промте критика — но пере-снятие A3 этим не обосновывается, потому что вывод арма от 2% тронутых лишних мест не меняется; достаточно пере-счёта places и честной оговорки о квоте.",
|
||
"why": "Механизм подтверждён: contour.py:281 `places = [ln.strip(\"- \").strip() for ln in found.splitlines() if ln.strip().startswith(\"-\")]` — вердикт не разбирается; contour.py:129-131 «СПИСОК МЕСТ, где перевод неверен… Почини ТОЛЬКО перечисленные места». Не объявлено: grep по docs/experiments/23-editor-tier.md на `places|критик|critic` даёт только 729/802/876 (формулировки гипотез), grep по eval/dovodka/requirements.md на `верно|подтверж|приемлем|отсев|парсер|places` — пусто. Числа мои: 48 крит-клеток, 2404 разобранных места, sum(min(n,40))=1518 отправленных. Регулярка находки как записана негодна («верно» матчит внутри «неверно»): наивно даёт 272, а не 119; мой строгий классификатор (вердикт после «→» содержит confirm-токен и не содержит error/suggestion-токена) даёт 116 / 7.6% / 26 клеток / max 15, широкий — 199 / 13.1% / 38 клеток. Последствие проверено исполнением ($0-скрипт scratchpad/an3.py, импортирует contour.py как модуль, сеть не трогает): сверка дословной цитаты критика с черновиком и с выходом фиксера — «BROAD confirm: lines=199 verbatim-in-draft=147 altered-by-fixer=30 (20.4%)» против «ALL sent places: lines=1514 verbatim-in-draft=1263 altered-by-fixer=939 (74.3%)». Разрыв 20% против 74% означает, что фиксер вердикт читает и подтверждения в основном оставляет побайтно; «прямой канал порчи, до 16 мест в клетке» данными не подтверждается. Из 7 строк, где фиксер всё же тронул подтверждённое место, большинство несут правку в самой строке («правильнее «записи опыта алхимии»», «корректнее «словно свинью режут»»). Квотная часть верна и осталась: 27 клеток из 48 имеют >40 мест, в 25 из них внутрь квоты попали 166 строк-подтверждений; places=len(places) считается до среза (contour.py:286)."
|
||
}
|
||
},
|
||
{
|
||
"title": "Базовая клетка A0 у единицы 41599f30df имеет finish=length, лежит в знаменателе ВСЕХ контрастов этой единицы и служит входом для A4 — при том что Д0.6 запрещает finish=length в судейской пачке, а в contour.py нет ни одной проверки поля finish",
|
||
"severity": "важно",
|
||
"evidence": "an10.py прошёл все базы фазы: единственная база с finish != stop — tp2-edit-E-deepseek-v4-flash-41599f30df.json, finish='length', 5759 знаков при черновике 6767 (85%). `grep -n finish eval/dovodka/*.py` даёт только комментарии в power.py:31,94 и фильтр в canon.py:162-168 — ни одной проверки в contour.py. Дефект унаследован из пака 22 и там объявлен (22-tenant-panel.md:1288-1290: «одна клетка стоит в БАЗЕ ВСЕХ КОНТРАСТОВ»), но фаза Д, объявившая норму Д0.6 (строка 826), взяла её без изъятия и купила поверх неё A4, который сам оборвался: dv-a-a4-41599f30df finish=length, 2548 знаков = 44% входа.",
|
||
"consequence": "На единице 41599f30df ВСЕ четыре контраста (A1/A0, A3/A0, A4/A0, A6/A0) сравниваются против оборванного текста — оборванный знаменатель систематически завышает перевес любого арма, то есть работает В ПОЛЬЗУ гипотез владельца. Норма Д0.6 объявлена и не исполнена ни кодом, ни фильтром при сборке пачки; сейчас единственная защита — что кто-то вспомнит про это руками.",
|
||
"fix": "Единицу 41599f30df исключить из контрастов Д4 (canon.py уже исключает её из канон-оси — сделать то же для судейской пачки), либо пере-купить её A0. В сборщик пачки добавить механический отказ по finish != 'stop' для ЛЮБОЙ клетки, включая унаследованные $0-базы — иначе норма Д0.6 остаётся текстом.",
|
||
"verdict": {
|
||
"line": "сырьё",
|
||
"refuted": true,
|
||
"why": "ФАКТЫ ФИНДА ПОДТВЕРЖДАЮТСЯ, ВЫВОД — НЕТ.\n\nЧто я перепроверил своими командами и что сошлось:\n* `base_a0()` (contour.py:88-91) = `P22.edit_text(ANCHOR=\"deepseek-v4-flash\", uid)` → `panel.py:135-137` + `tag_edit` (panel.py:119-120) → файл `~/books/tenant-panel/tp2-edit-E-deepseek-v4-flash-41599f30df.json`. Мой прогон по всем 32 единицам (скрипт в scratchpad/chk.py, chk2.py): это ЕДИНСТВЕННАЯ база A0 с finish != stop среди 32 — `finish=length, len=5759` при черновике 6767; остальные 15 старых (`tp2-edit-E-deepseek-v4-flash-*`) и все 16 новых (`et-unit-edit-deepseek-v4-pro-*`) — `stop`.\n* `grep -n finish eval/dovodka/*.py` → power.py:31,94 (комментарии) и canon.py:162-168 (фильтр). В contour.py проверки finish действительно нет.\n* `dv-a-a4-41599f30df.json`: finish=length, len=2548, cost 0.015691.\n\nПОЧЕМУ ЭТО НЕ НАХОДКА В ЗАЯВЛЕННОМ ВИДЕ — три независимых основания.\n\n1) ЭТО ОБЪЯВЛЕННОЕ ОГРАНИЧЕНИЕ С ПРЕД-РЕГИСТРИРОВАННОЙ ПОЧИНКОЙ, а не «сказано неверно». Пак 22 §15 (`docs/experiments/22-tenant-panel.md:1288-1290`) называет ровно эту клетку по имени, ровно это последствие («на единице 41599f30df каждый контраст обеих фаз сравнивался ПРОТИВ оборванного текста»), МЕРЯЕТ чувствительность leave-out (строки 1298-1315) и прямым текстом предписывает точку исполнения: «**В фазе Д он стоит ДО судейства и жёсткий**» (22-tenant-panel.md:1339-1343). Пре-рег Д0.6 (23-editor-tier.md:826-828) это повторяет и явно цитирует класс, включая «одна в базе всех контрастов (§15 эксп-22)». То есть норма привязана к СБОРКЕ СУДЕЙСКОЙ ПАЧКИ, а не к покупке армов, — и требовать её от contour.py (это закупщик армов) значит спутать место исполнения.\n\n2) МОМЕНТ ИСПОЛНЕНИЯ ЕЩЁ НЕ НАСТУПИЛ, судейских денег не потрачено. Сборщика пачки в фазе Д не существует: `grep -rln \"пачк|судь|judge|blind\" eval/dovodka/*.py` даёт runs.py (реестр сессий, `def claim/done/judge_of`), contour.py и power.py — ни одного сборщика ключей/пачки. Тезис «норма объявлена и не исполнена ни кодом, ни фильтром при сборке пачки» опережает событие: фильтровать пока нечего и негде, а прецедент реализации уже лежит рядом (canon.py:162-168 исключает именно 41599f30df).\n\n3) ЗАЯВЛЕННОЕ ПОСЛЕДСТВИЕ НЕВЕРНО ПО НАПРАВЛЕНИЮ И НЕ МЕНЯЕТ НИ ОДНОГО ВЫВОДА.\n * «Оборванный знаменатель систематически завышает перевес ЛЮБОГО арма, то есть работает В ПОЛЬЗУ гипотез владельца» — для A4 это ровно наоборот: A4 на этой единице сам оборван до 2548 знаков = 44% своей базы 5759, значит контраст A4/A0 здесь пойдёт ПРОТИВ A4. Из четырёх купленных контрастов направление финда держится максимум на трёх.\n * Масштаб: 1 единица из 32 (3%) при MDE оси Д4 = 1.29 (Д0.3). Для калибровки — собственный leave-out пака 22 при 4 затронутых из 16 (25%, вшестеро более грубое вмешательство) НЕ сдвинул ни одного вердикта решающей таблицы Ф3 (22-tenant-panel.md:1310-1315, 1317-1319). Одна единица из 32 сдвинуть вывод не может по построению.\n\n4) ПРЕДЛОЖЕННАЯ ПОЧИНКА СОЗДАЛА БЫ ЛОЖНУЮ УВЕРЕННОСТЬ. «Механический отказ по finish != stop для ЛЮБОЙ клетки» не ловит худшую дыру сырья, уже оплаченную этой фазой: якорный черновик единицы `63ab55ac5c` (`~/books/editor-tier/et-unit-draft-deepseek-v4-flash-63ab55ac5c.json`) имеет **finish=stop**, но это ЭХО — 2243 знака китайского исходника вместо перевода (хвост содержимого — чистый zh; для сравнения src 2182 знаков, нормальный перевод ~7000). Он подан в `base_draft()` (contour.py:83-86, ветка `PAN23.draft_b` — БЕЗ гейта `BO.draft_reject_reason`, в отличие от `P22.draft_text`), и поверх него фаза купила `dv-a-a1-63ab55ac5c` (1727 китайских знаков из 2490), `dv-a-a3-63ab55ac5c` (1804 из 2249) и критика — $0.0200. Фильтр по finish пропустил бы всё это целиком.\n\nЧТО ОСТАЁТСЯ ЖИВОГО (существенно меньше заявленного и с другим последствием): единица 41599f30df пре-регом фазы уже приговорена к изъятию из пачки, но contour.py об этом не знает и закупил по ней шесть клеток на $0.0510 (a1 0.010675 + a3 0.006374 + a3-crit 0.006499 + a4 0.015691 + a6 0.005096 + a6-crit 0.006709) = 4.5% потраченных $1.1397; из них собственно новый брак — A4 $0.0157, купленный ПОВЕРХ оборванной базы. Это про деньги, а не про смещение выводов, и в докладе это не записано. Тяжесть — «мелочь/на заметку», не «важно».",
|
||
"corrected": "Остаточная, сжатая формулировка (если парент захочет её сохранить): «Пре-рег Д0.6 приговаривает единицу 41599f30df к изъятию из судейской пачки (её база A0 `tp2-edit-E-deepseek-v4-flash-41599f30df` — finish=length, 5759 знаков), но закупщик армов contour.py списка изъятий не имеет и купил по ней 6 клеток на $0.0510 (4.5% потраченного), включая A4 $0.0157 прямо поверх оборванной базы. Последствие — деньги, а не смещение вывода: 1 единица из 32 при MDE 1.29 вывод не двигает, а направление 'в пользу гипотез владельца' для A4 обратное (A4 сам оборван до 44% базы). Починка не в фильтре по finish — он пропускает худшее (эхо-черновик 63ab55ac5c с finish=stop, $0.0200 уже куплено поверх него), а в едином списке негодных единиц, разделяемом закупщиком, canon.py и будущим сборщиком пачки»."
|
||
}
|
||
},
|
||
{
|
||
"title": "Арм A4 «завёл» 13 новых канон-пробелов, из которых 12 — механика обрыва двух клеток finish=length, и это ломает ту самую ось, ради которой A4 заведён",
|
||
"severity": "важно",
|
||
"evidence": "an6.py: A4 69→63, починено 19, ЗАВЕДЕНО 13, клеток «стало хуже» 3. Из 13 заведённых 7 приходятся на 41599f30df (обрыв до 44% входа) и 5 на f6da9f76b2 (обрыв до 71%) — то есть термины «пропали» не потому, что фиксер их убрал, а потому, что текст кончился. Без этих двух клеток A4 даёт 58 пробелов до и 1 заведённый.",
|
||
"consequence": "Прогноз Д0.9 №2 гласит «A4 даст лучшее покрытие канона из всей панели»; на сыром материале A4 выглядит как арм, ломающий канон (69→63 при 13 новых пробелах), тогда как без двух оборванных клеток картина обратная. Число, которое пойдёт в отчёт по объявленной оси A4, определяется артефактом обрыва, а не поведением канон-фиксера.",
|
||
"fix": "Две клетки с finish=length из канон-оси A4 вычесть (норма Д0.6 это и так предписывает) и напечатать оба числа — с ними и без них, как это уже сделано для эхо-мины в паке 23.",
|
||
"verdict": {
|
||
"line": "сырьё",
|
||
"refuted": false,
|
||
"corrected": "Обе клетки A4 с finish=length (41599f30df, f6da9f76b2) обрывают выход фиксера до 44.2% и 71.0% длины его входа-A0 и тем самым фабрикуют 12 из 13 «заведённых» канон-пробелов арма. Механизм доказан контролем, а не выведен: если обрезать САМ A0 до len(A4), появляются ровно те же 7 и 5 пробелов — 12/12, 100%. Числа оси: со всеми 22 клетками 69→63, починено 19, заведено 13, «стало хуже» 3; без двух оборванных 58→40, починено 19, заведено 1, «стало хуже» 1.\n\nДВЕ ПОПРАВКИ к формулировке автора.\n\n(1) Починка сформулирована неверно и тем ЗАНИЖАЕТ находку: норма Д0.6 (23-editor-tier.md:826) исключает finish=length из «СУДЕЙСКОЙ пачки», а канон-ось — отдельный $0-детектор, печатаемый самостоятельной осью (contour.py:19-21). Ни одна норма фазы эту ось от оборванных клеток не защищает, так что вычет не «и так предписан», а требует ОТДЕЛЬНОГО правила. Формулировать надо так: завести норму «клетка с finish=length не входит и в $0-оси, а не только в судейскую пачку», и печатать оба числа.\n\n(2) Последствие переоценено. Прогноз Д0.9 №2 (строка 880) — КРОСС-АРМОВЫЙ: «A4 даст лучшее покрытие канона из всей панели». На 21 общей единице с A1/A3/A4: A1=35, A3=53, A4=62 остаточных пробела — A4 последний. Без двух оборванных клеток (19 единиц): A1=28, A3=45, A4=39 — A4 переезжает с последнего места на среднее, но A1 не догоняет ни по абсолюту, ни по относительному сокращению (A4 57→39 = −32%, A1 47→28 = −40%). Прогноз №2 проваливается в обеих бухгалтериях. Обрыв переворачивает не вердикт по прогнозу, а ХАРАКТЕРИСТИКУ арма: «A4 ломает канон, заводит 13 новых пробелов» — чистый артефакт, тогда как настоящий A4 заводит один пробел на 20 клетках.\n\nПобочно: две мёртвые клетки — самые дорогие в арме ($0.015691 + $0.015945 = $0.0316, 16.3% от $0.1935 арма A4) при наименьшем объёме выхода.",
|
||
"why": "Опровергнуть не удалось: воспроизвёл независимо своим скриптом поверх contour.canon_gaps/base_a0, все числа автора совпали до единицы, и добавил контроль, которого у автора не было.\n\n1) Сырьё. `python -c` по ~/books/dovodka/dv-a-a4-*.json: ровно 22 клетки, ровно две с finish=length — dv-a-a4-41599f30df.json (content 2548 симв., cost 0.015691) и dv-a-a4-f6da9f76b2.json (content 5441, cost 0.015945); у остальных 20 content 6700..9761.\n\n2) Механика оси. contour.py:261-262 — для A4 `target = base_a0(uid)`, места = `canon_gaps(src, target)`; canon_gaps определён contour.py:98-108 (термин банка, чья канонная форма в выходе встречается реже, чем в исходнике).\n\n3) Воспроизведение (scratchpad/a4check.py, eval/.venv/bin/python): ALL 22 → before=69 after=63 fixed=19 intro=13 worse=3. Без finish=length (20) → before=58 after=40 fixed=19 intro=1 worse=1. Только finish=length (2) → before=11 after=23 fixed=0 intro=12 worse=2. Совпадает с уликой автора (69→63, 19, 13, 3; «58 до и 1 заведённый»). Пер-клеточно: 41599f30df ratio 2548/5759=0.442 intro=7; f6da9f76b2 ratio 5441/7661=0.710 intro=5 — заявленные «44%» и «71%», 7 и 5 подтверждены.\n\n4) КОНТРОЛЬ, которого не было у автора (scratchpad/a4cause.py). Обрезал САМ A0 до len(A4) и прогнал canon_gaps: для 41599f30df «новых A4, объяснённых обрезкой самого A0: 7 из 7», для f6da9f76b2 «5 из 5» — 12/12, 100%. Хвосты выходов A4 рвутся посреди предложения («...его чёрные волосы развевались без ветра, а глаза», «...величайшая редко»), тогда как A0 обеих единиц заканчивается терминатором. Причинность доказана, а не скоррелирована.\n\n5) Не объявленное ограничение. `grep -n \"A4\" docs/experiments/23-editor-tier.md` даёт только 803, 805, 856, 880 — все в пре-реге Д0; секции результата A4 в отчёте нет вовсе, значит «отчёт сам называет проблему» не выполняется. Д0.6 (строка 826) звучит дословно «Клетка с finish=length в СУДЕЙСКУЮ пачку НЕ допускается», а канон-гейт по contour.py:19-21 «печатается ОТДЕЛЬНОЙ осью результата» — то есть норма эту ось не покрывает.\n\n6) Проверка «меняется ли вывод» (scratchpad/panel.py, 21 общая единица с A1/A3/A4): ВСЕ 21 → A0=68, черновик=54, A1=35, A3=53, A4=62. Без 2 length (19) → A0=57, черновик=47, A1=28, A3=45, A4=39. То есть число, идущее в отчёт по объявленной оси A4, действительно определяется обрывом (A4 с последнего места на среднее), но прогноз Д0.9 №2 «лучшее покрытие из всей панели» не восстанавливается — A1 впереди в обоих срезах. Это и есть исправление масштаба в поле corrected."
|
||
}
|
||
},
|
||
{
|
||
"title": "Каждое десятое «место» критика цитирует текст, которого в черновике нет",
|
||
"severity": "мелко",
|
||
"evidence": "an8.py, сверка левой части «цитата → ошибка» с черновиком подстрокой: из 2346 проверенных цитат не найдено в черновике 192 (8.2%); по клеткам среди ушедших фиксеру 40 мест медиана доли фантомных цитат 9.8%, клеток с долей >25% — 5 из 48 (худшие: A3 b0a5efaa11 5/11=45%, A3 89614f9bfa 6/18=33%, A3 6df3dd3eb6 2/6=33%). Примеры несуществующих цитат: «простои вояка», «Издыхающим мощь», «пилюля возвращения весны», «волна времени».",
|
||
"consequence": "Фиксеру велено починить место, которое он не может найти; в лучшем случае он тратит квоту впустую, в худшем — правит похожий фрагмент, то есть трогает текст там, где промт это прямо запрещает («всё остальное оставь ПОБАЙТНО как есть»). Замеренная доля правок по названным местам (71% у A3, 75% у A6) частично объясняется именно этим и не должна читаться как «фиксер проигнорировал четверть замечаний».",
|
||
"fix": "В отчёт добавить строку «доля фантомных цитат критика 8.2%» рядом с числом найденных мест; при пере-снятии — отсеивать места, чья цитата не встречается в черновике подстрокой, до передачи фиксеру.",
|
||
"verdict": {
|
||
"refuted": true,
|
||
"why": "Прогнал СВОИМИ скриптами по 48 крит-клеткам ~/books/dovodka/dv-*-crit-*.json; парсер мест воспроизводит авторский (2404 места, 2393 со стрелкой, 1514 из них уходят фиксеру срезом places[:40], contour.py:281,286).\n\n1) ЧИСЛО 8.2% — АРТЕФАКТ РЕГИСТРО-ЗАВИСИМОГО МАТЧЕРА. Авторский an8.py:9-11 (`quote()`) снимает кавычки только по КРАЯМ, не складывает регистр, не нормализует пробелы/ё, и матчит `q not in draft` (an8.py:71). Прогнал сетку из 16 нормализаций (скрипт ph5.py): доля «фантомных» ходит от 21.5% (совсем без нормализации) до 5.3% (кавычки+регистр+пробелы). Строка сетки «кавычки да, регистр нет» даёт РОВНО авторские 192/2393 = 8.0%. То есть метрика на порядок чувствительнее к матчеру, чем к самому явлению, и 8.2% — верхняя точка выбранного матчера, а не замер.\n\n2) ВСЕ ЧЕТЫРЕ НАЗВАННЫХ ПРИМЕРА РАЗВАЛИВАЮТСЯ (ph9.py):\n• «Издыхающим мощь» — В ЧЕРНОВИКЕ ЕСТЬ дословно, с маленькой буквы: «...доисторическим зверем, издыхающим мощь, способную поглотить...». Чистый ложняк case-sensitive матчера.\n• «пилюля возвращения весны» — черновик 13c5f52fa3: «это же явно аура пилюли возвращения весны»; в клетке debb2c1aef та же цитата лежит в черновике ПОБАЙТНО. Словоизменение.\n• «волна времени» — черновик: «она обладает волной времени». Словоизменение; вдобавок вердикт самого критика — «терпимо», т.е. это не приказ чинить.\n• «простои вояка» — единственный настоящий: черновик содержит «простой вояка», критик выдумал опечатку. Но место при этом опознаётся однозначно (критик сам печатает верную форму в правой части), так что это галлюцинация ДЕФЕКТА, а не ненаходимое место.\n\n3) МАСШТАБ ПОСЛЕ ЧЕСТНОГО МАТЧА (ph7.py, только 1514 мест, реально ушедших фиксеру): нормализация кавычек+регистра+ё+пробелов → 98 непрямых (6.5%); из них 10 — цитаты ИСХОДНИКА иероглифами (9 из 10 лежат в исходнике дословно, а исходник фиксеру подан, contour.py:147); ещё 37 находятся стем-матчем (русское словоизменение). ОСТАТОК 51 из 1514 = 3.4%, медиана по клеткам 2.5%, клеток с долей >25% — НОЛЬ из 48 (у автора «5 из 48»). Авторские «худшие» клетки не воспроизводятся ни в одном из 16 вариантов матча: b0a5efaa11 у меня (2,12) при полной нормализации и (5,12) при сырой — автор печатает 5/11; 89614f9bfa — (3,17)/(17,17) против авторских 6/18; 6df3dd3eb6 — (1,5)/(5,5) против 2/6.\n\n4) «ФИКСЕР НЕ МОЖЕТ НАЙТИ МЕСТО» — измерил напрямую (ph6.py, difflib по нормализованным строкам): из 98 непрямых цитат у 54 в черновике лежит непрерывный общий кусок ≥60% длины цитаты, ещё у 12 присутствует ≥80% знаменательных слов, 21 — частичные (30-60%, это короткие «Золотое ядро» при «Золотого ядра»), и РОВНО ОДНА цитата не имеет в черновике ничего похожего (A3 cf9a90d9fe «„почему?“ в черновике перевода»). Один случай на 1514 мест = 0.07%, а не 8.2%.\n\n5) ПРИЧИННОЕ УТВЕРЖДЕНИЕ ОПРОВЕРГНУТО СОБСТВЕННЫМ СКРИПТОМ АВТОРА. Заявлено, что доля правок 71%/75% «частично объясняется» фантомами. an9.py:24 — `qs=[q for q in qs if len(q)>=6 and q in draft]`: знаменатель этой метрики ПО ПОСТРОЕНИЮ содержит только цитаты, присутствующие в черновике, фантомы туда не попадают вовсе. Пере-считал независимо (ph8.py) на цитатах, лежащих в черновике: A3 625/904 = 69.1%, A6 367/512 = 71.7% — те же 71/75. Фантомы не объясняют недостающие ~29% ни на одну единицу.\n\n6) ЧАСТЬ «ФАНТОМОВ» — НЕ ФАНТОМЫ, А ДРУГОЙ, УЖЕ ПОСЧИТАННЫЙ АВТОРОМ КЛАСС: из 98 непрямых 22 — строки, где критик перевод ОДОБРЯЕТ («ок», «верно», «соответствует канону», «терпимо», «ошибки нет»). Автор считает этот класс отдельной секцией в том же an8.py:53-67 («места, которыми критик объявил перевод ВЕРНЫМ»), но не вычитает его из фантомной доли — то есть одни и те же строки идут в две находки сразу.\n\n7) ЦЕНА ВОПРОСА. Ни одного доллара: покупок по этой линии нет, судейств ноль (runs.py --report: 0 из 80), значит ни один вывод фазы на этом сейчас не стоит. Предложенная починка «отсеивать места, чья цитата не встречается подстрокой» при авторском матчере выбросила бы 385 из 1514 мест (25.4% сырой матч, ph4.py), включая дословно существующие «издыхающим мощь» — то есть починка навредила бы сильнее описанной болезни.",
|
||
"corrected": "Спасаемый остаток находки (после честной нормализации и с правильными последствиями): «В ~3.4% мест, ушедших фиксеру (51 из 1514 по 48 крит-клеткам), левая часть „цитата → ошибка“ не находится в черновике даже после снятия кавычек, регистра и словоизменения; медиана по клетке 2.5%, клеток с долей >25% нет. Подавляющее большинство остатка — составные цитаты через „/“ и „…“ (критик склеил два места в строку) и строки, где критик перевод ОДОБРЯЕТ, а не требует правки; полностью нелокализуемая цитата ровно одна на 1514. На метрику „доля правок по названным местам“ (A3 69–71%, A6 72–75%) это не влияет по построению: её знаменатель (an9.py:24) содержит только цитаты, присутствующие в черновике. В отчёт это годится строкой о качестве формата критика, а не как дефект контура; фильтр „нет подстроки — не передавать фиксеру“ вводить нельзя (при регистро-зависимом матче он выбрасывает 25% мест, среди них дословно существующие).»"
|
||
}
|
||
},
|
||
{
|
||
"title": "A1 куплен на флаг-листе, который на 78% состоит из легитимной прономинализации: фиксеру велено «починить» места, где перевод правилен",
|
||
"severity": "критично",
|
||
"evidence": "contour.py:106 `if min(len(re.findall(v[\"rx\"], out, re.I)), n) < n: gaps.append(...)` — флаг ставится, когда канонная форма встречается в выходе РЕЖЕ, чем термин в исходнике. Пере-снято исполнением по всем 32 единицам: флагов 74, из них «канон в выходе отсутствует полностью» 16, «канон есть, но реже» 58. Примеры: d1e353d569 秦风 в исходнике 20 раз, «Цинь Фэн» в черновике 19 → флаг; 徐婉 11 против 10 → флаг. canon.py:13-15 сам объявляет эту метрику негодной для вердикта: «Она падает и когда термин передан ДРУГИМ переводом, и когда он заменён местоимением — а второе есть норма русской прозы там, где китайская повторяет имя.» Текст флага contour.py:116: «КАНОН: термин ... передан не канонной формой либо пропущен», и FIX_HEAD (contour.py:129-130) подаёт это как «СПИСОК МЕСТ, где перевод неверен».",
|
||
"consequence": "A1 — носитель H-2а в ПЕРВИЧНОМ семействе Холма (power.py:76). Арм измеряется не как «флаговый контур», а как «контур, которому велели вернуть повторы имён вместо местоимений»: если фиксер послушался, судья по художественности штрафует A1 за исполнение задания. H-2а меряется против соломенного арма. Оплачено A1 $0.22694 (30 клеток) + A4 $0.19348 (22 клетки, contour.py:262 та же canon_gaps по base_a0) = $0.42 из $1.14 фазы. Владельческая политика 10.08 («банк существует, чтобы термины единообразно переводились») меряется через ПОКРЫТИЕ, а ЕДИНООБРАЗИЕ (canon.py:16-18, единственная метрика, отвечающая политике) во флаги не входит вовсе.",
|
||
"fix": "Флаговать только 16 случаев полного отсутствия канона плюс нарушения единообразия из canon.py (конкурирующее родовое при том же якоре). Пере-снять A1/A4 на исправленном листе либо объявить оба арма конфаундированными в отчёте с числом 58/74.",
|
||
"verdict": {
|
||
"refuted": false,
|
||
"why": "Механика и арифметика находки воспроизводятся точно, но её центральный клейм, тяжесть и починка — неверны, а рядом лежит настоящий дефект, который автор пропустил.\n\nЧТО ПОДТВЕРДИЛОСЬ (мой пере-снимок, не со слов автора).\nСкрипт по всем 32 единицам (contour.canon_gaps на base_draft): «CANON flags total 74 absent(hits=0) 16 present-but-fewer 58 · share fewer 78.4%» — числа автора сходятся до штуки. Деньги тоже: `python3` по ~/books/dovodka/dv-*.json дал ('A1','fixer') 30 $0.226944 · ('A4','fixer') 22 $0.193484 · TOTAL $1.139729, A1+A4 = $0.420428.\n\n1. КЛЕЙМ «78% — легитимная прономинализация» НЕ ИЗМЕРЕН И НЕВЕРЕН. Автор наклеил ярлык на все 58, не вскрыв ни одного. Разбивка 58 по терминам (мой прогон): личные имена 秦风 18 · 曹英 2 · 风老 2 · 苏晴雪 2 · 苏无视 1 · 徐婉 1 · 徐宁 1 · 史仁 1 = 28. НЕ-персоны: 筑基 8 · 家主 4 · 世子 3 · 秦家 3 · 公子 3 · 金丹 3 · 左相 2 · 苏家 2 · 天阳城 2 = 30. То есть прономинализация как объяснение применима максимум к 28/58 (48%), а не к 78%. Я прочитал реальные причины недобора у не-персон: ed068182cf 筑基 18/11 — «неужели он хочет успеть ЗАЛОЖИТЬ ФУНДАМЕНТ до возвращения главы рода», глагольный парафраз, который канонный rx `заклад\\w*\\s+фундамен\\w*` не берёт; 89614f9bfa 金丹 5/3 — «как минимум четвёртый слой ЯДРА», эллипсис; d6cbc0179d/debb2c1aef 公子 — голое «господин» вместо канона «молодой господин». Это разнородная смесь (парафраз, эллипсис, предел регекса), и часть её — ровно тот класс, который политика владельца зовёт дефектом.\n\n2. ЭТО ОБЪЯВЛЕНО, ПРИЧЁМ САМИМ ВЛАДЕЛЬЦЕМ — значит не «фиксеру велено чинить правильное», а «фиксеру велено то, что заказано». docs/POLYGON_EXP2223_REDO_SESSION_PROMPT.md:91-94: «Канон-гейт = детерминированная сверка ПОКРЫТИЯ банка после каждого арма — он и флагует потери для фиксера... потеря канона = дефект безусловно; художественность — отдельная ось. Гейт жёсткий, ФИКСЕР ОБЯЗАН КАНОН ВОССТАНАВЛИВАТЬ». Автор цитирует canon.py:13-15 как самодисквалификацию метрики, но обрывает файл на середине: canon.py:6-7 — «Задача этого файла — НЕ СПОРИТЬ о том, дефект ли это, а дать фиксеру МЕХАНИЗМ», canon.py:26 — «Список мест остался как СЫРЬЁ ДЛЯ ФИКСЕРА (где искать)». canon.py снимает покрытие как ВЕРДИКТ и тем же абзацем санкционирует его как ВХОД фиксера — ровно то, что делает contour.py. Предложенная починка («флаговать только 16») отменяет ратифицированную политику владельца решением ревьюера.\n\n3. ПОЛОВИНА ДЕНЕЖНОГО КЛЕЙМА ОТПАДАЕТ. A4 по определению — канон-полировщик: пре-рег Д0.5 «A4 = A0 + канон-фиксер ПОСЛЕ», прогноз Д0.9.2 «A4 даст лучшее покрытие канона из всей панели, не двигая судейский перевес». Восстановление покрытия — объявленная ЦЕЛЬ арма, поэтому его флаг-лист не может быть его же конфаундом. Минус $0.193484. В зоне остаётся только A1 $0.226944 = 19.9% фазы, а не «$0.42».\n\n4. МАСШТАБ ПОСЛЕДСТВИЯ ЗАВЫШЕН И СЕЙЧАС НЕПРОВЕРЯЕМ. Пере-снял по КУПЛЕННЫМ клеткам A1: медианное сходство выхода с черновиком 0.998 (худшее 0.918); на 58 «реже» канон-хиты 538 → 592 (+54 на 30 единиц ≈ 1.8 вставки на единицу), на 16 «отсутствует» — 16/16 восстановлено. Это не «контур, которому велели вернуть повторы имён вместо местоимений», а почти побайтно тот же текст плюс ~2 вставки термина на единицу. Судейств не было ни одного (0 из 80), поэтому ни один вывод фазы на этом пока не стоит — снимать нечего.\n\n5. АВТОР ПРОШЁЛ МИМО НАСТОЯЩЕГО ДЕФЕКТА В ЭТОЙ ЖЕ ФУНКЦИИ. Сумма поля `places` по 30 клеткам A1 = 74 — ровно число канон-флагов; батарея дала НОЛЬ на всех 30. Причина: `B.run_unit` падает на каждой единице — я вызвал напрямую, «battery RAISED: AttributeError 'dict' object has no attribute 'final'», и contour.py:122-123 глушит это голым `except Exception: pass`. Пре-рег Д0.5 определяет A1 как «детерминированные флаги (БАТАРЕЯ + канон-гейт)»; A1 куплен как канон-гейт в одиночку. Это отступление от пре-регистрированного арма, оно необъявлено, и оно точнее и тяжелее того, что предъявлено.",
|
||
"corrected": "A1 куплен на флаг-листе из 74 мест, все 74 — канон-гейт по НЕДОБОРУ покрытия (contour.py:106), и это объявленный заказ владельца (SESSION_PROMPT:91-94 «потеря канона = дефект безусловно... фиксер обязан канон восстанавливать»), а не изобретение сессии. 58 из 74 — «канон есть, но реже»; назвать их «легитимной прономинализацией» нельзя: только 28 из 58 стоят на личных именах, остальные 30 — на не-персонах (筑基 8, 家主 4, 世子 3, 秦家 3, 公子 3, 金丹 3, 左相 2, 苏家 2, 天阳城 2), где вскрытие текста даёт глагольный парафраз (ed068182cf «заложить фундамент»), эллипсис (89614f9bfa «четвёртый слой ядра») и голое родовое («господин» вместо «молодой господин»), то есть смесь, часть которой политика владельца прямо считает дефектом. Реальное воздействие на арм мало: медианное сходство выхода A1 с черновиком 0.998, канон-хиты на 58 флагах 538→592 (+54 на 30 единиц), 16/16 полных отсутствий восстановлено; судейств 0 из 80, поэтому ни один вывод фазы на этом не стоит. Из денег в зоне только A1 $0.226944 (19.9% фазы), но не A4 $0.193484 — восстановление покрытия есть ОБЪЯВЛЕННАЯ цель A4 (пре-рег Д0.5, прогноз Д0.9.2), а не его конфаунд. Тяжесть — не «критично», а «средне»: оговорка в отчёте о том, что канон-ось A1 меряет покрытие, а не корректность, и что 58/74 флагов не есть подтверждённые ошибки перевода. НАСТОЯЩИЙ дефект рядом, требующий действия: батарея не дала НИ ОДНОГО флага ни на одной из 30 клеток A1 — `B.run_unit` падает с AttributeError('dict' object has no attribute 'final'), а contour.py:122-123 глушит это голым `except Exception: pass`, так что A1 куплен как «канон-гейт», хотя пре-рег Д0.5 определяет его как «батарея + канон-гейт»; это отступление от пре-регистрированного арма и оно обязано быть объявлено в отчёте."
|
||
}
|
||
},
|
||
{
|
||
"title": "Ось Д4 объявлена НЕСУЩЕЙ при n=32, хотя треть её первичного семейства по построению живёт на n=16, а второй член фактически на n=30",
|
||
"severity": "критично",
|
||
"evidence": "power.py:48 `(\"Д4 edit-контур zh\", 32, 3, 2.12, 1.50, ...)`; power.py:76-78 первичное семейство = A1/A0, A3/A0, A6/A0. A6 существует только на 16 старых единицах — contour.py:243 `if arm == \"A6\" and uid not in old: continue`, и plan.py:97 бюджетирует ФД-F как «n=16». Пере-счёт функцией power.mde(2.12, n, 3): n=32 → 1.491 (НЕСУЩАЯ, запас до цели 1.50 всего 0.009); n=30 → 1.540; n=16 → 2.109. Факт по сырью: A1 30 клеток, A3 32, A6 16, A4 22.",
|
||
"consequence": "Пре-рег Д0.3 объявляет правило «ось описательная, если MDE больше цели» и печатает по оси ОДНУ строку. По этому же правилу A6/A0 описательный ещё до денег (MDE 2.109 при цели 1.50, +40%), а A1/A0 стал описательным в момент, когда две единицы не получили флагов. Вердикт по H-1 и H-2а будет прочитан как несущий, не будучи им; ФД-F $0.267825 потрачены на контраст, который прибор не разводит. Запас 0.009 означает, что любая одна выпавшая единица переворачивает статус оси.",
|
||
"fix": "В power.py считать MDE ПО КОНТРАСТУ с его собственным n, а не по оси; пере-классифицировать A6/A0 и A1/A0 в описательные ДО чтения перевесов, как требует Д0.3.",
|
||
"verdict": {
|
||
"line": "гейты",
|
||
"refuted": false,
|
||
"why": "Пытался опровергнуть по трём линиям — «это объявленное ограничение», «числа не те», «вывод не меняется». Ни одна не прошла.\n\n1) Гетерогенность n внутри семейства РЕАЛЬНА и в докax НЕ объявлена как ограничение мощности.\n `sed -n '45,50p;74,80p' eval/dovodka/power.py` → power.py:48 `(\"Д4 edit-контур zh\", 32, 3, 2.12, 1.50,` и power.py:76-78 PRIMARY = A1/A0 · A3/A0 · A6/A0. Строка оси печатается ОДНА, n=32.\n `eval/.venv/bin/python eval/dovodka/power.py` → `Д4 edit-контур zh 32 3 2.12 1.49 1.50 0.0000 НЕСУЩАЯ`, а список семейства печатается БЕЗ n у контрастов.\n A6 живёт только на 16: contour.py:243 `if arm == \"A6\" and uid not in old: continue`; contour.py:92 докстринг `base_draft2` — «Есть только у 16 старых единиц»; contour.py:179 `n = len(old) if a == \"A6\" else len(us)`; plan.py:97 «n=16»; отчёт 23-editor-tier.md:860 «ФД-F … (n=16)».\n НО: все эти места — про МАТЕРИАЛ и ДЕНЬГИ. Про МОЩНОСТЬ A6 не сказано нигде: `grep -rn \"A6\" eval/dovodka/ | grep -v json` даёт 12 хитов, ни один не о MDE; `grep -n \"мощност|MDE|описательн\" docs/experiments/23-editor-tier.md` — ни строки про A6. А Д0.5 (23-editor-tier.md:797-805) наоборот вписывает A6 в блок «Д4 — edit-контур zh, 32 единицы».\n Решающая улика против «автор так задумал»: тот же файл применяет ровно это рассуждение к другому арму — power.py:81-83 объявляет E6/E0 описательным ИМЕННО из-за n=16 («на n=16 порядок жильцов разрешить нельзя … сказано ДО денег»). Значит пропуск для A6 — непоследовательность внутри одного файла, а не сознательная норма.\n\n2) Числа сходятся точно. `eval/.venv/bin/python -c \"import sys;sys.path.insert(0,'eval/dovodka');import power as p;...\"` → mde(2.12,n,3): n=32 → 1.4915 · n=31 → 1.5154 · n=30 → 1.5404 · n=22 → 1.7988 · n=16 → 2.1093. Запас до цели 1.50 = 0.0085 (авторские «0.009» верны), и уже n=31 переворачивает статус.\n Сырьё пере-считал сам (обход `~/books/dovodka/*.json` по полям arm/role/uid): A1 fixer 30 клеток / 30 uid · A3 critic 32 + fixer 32 · A4 fixer 22 (2 клетки finish=length) · A6 critic 16 + fixer 16. `contour.py --plan` ($0) подтверждает: «A1: куплено 30 из 32 · A6: куплено 16 из 16 · ФД-F 0.267825».\n\n3) Вывод меняется. Заказ (docs/POLYGON_EXP2223_REDO_SESSION_PROMPT.md:95-97) требует НЕСУЩЕГО вердикта по H-1/H-2а/H-2б на zh. Единственный носитель H-1 — A6/A0 (power.py:78, отчёт Д0.2:748), и он по правилу самого пре-рега (23-editor-tier.md:769 «ось объявляется описательной, если MDE больше цели») описательный ЕЩЁ ДО ДЕНЕГ: 2.109 против цели 1.50, +40%. Прибор не разводит контраст, ради которого куплена фаза ФД-F.\n\nИтог: находка верна. Неточности только в масштабе — правки в поле corrected.",
|
||
"corrected": "Формулировка после проверки (три уточнения масштаба, вывод тот же):\n\nЯДРО (подтверждено): power.py печатает MDE и статус ПО ОСИ при плановом n=32, тогда как n у членов первичного семейства РАЗНЫЕ. A6/A0 — единственный носитель H-1 — существует только на 16 единицах (contour.py:243, база есть лишь у 16: contour.py:92, `--plan`: «черновик-dspro 16/16»), его собственный MDE 2.109 при цели 1.50, то есть по правилу пре-рега 23-editor-tier.md:769 он ОПИСАТЕЛЬНЫЙ ещё до покупки. Нигде — ни в power.py, ни в Д0.3/Д0.5, ни в докстрингах — это не объявлено; n=16 для A6 фигурирует только в сметных и материальных строках (plan.py:97, отчёт:860). Тот же файл при этом объявляет E6/E0 описательным именно из-за n=16 (power.py:81-83) — значит норма автору известна и к A6 просто не применена.\n\nУТОЧНЕНИЕ 1 — «треть семейства» верна для ИНСТРУМЕНТА, но не для ЗАМОРОЖЕННОГО ПРЕ-РЕГА. Отчёт Д0.5 (строка 805) объявляет «семейство: A1/A0 · A2/A0 · A3/A0 · A4/A0 · A6/A0, Холм по пяти», а таблица Д0.3 (759-764) печатает «Д4 32 5 2.12 1.29» — эти числа НЕ воспроизводятся из закоммиченного power.py (`git diff HEAD -- eval/dovodka/power.py` пуст, оба файла из одного фриза da5f4d0; тот же файл даёт 32 3 → 1.49, а k=5 → 1.5753; 1.29 = mde при k=1, то есть в отчёт вклеен вывод ДО починки множителя Холма, описанной в докстринге mde()). Так что A6 — 1 из 3 по инструменту и 1 из 5 по отчёту; описательным он выходит при обоих (2.109 при k=3, 2.228 при k=5). Побочно: заявленный в отчёте запас 0.21 (1.29 против 1.50) фиктивен, реальный — 0.0085.\n\nУТОЧНЕНИЕ 2 — «A1 фактически на n=30» верно как СОСТОЯНИЕ МАТЕРИАЛА, но причина и необратимость другие. Недостают ровно 2 uid (474f822806, 9b16c9c9a7; A1 ⊂ A3, A3 полон), и выпали они не по гарду (гард остановил A4 на 22, A3 при этом полон), а по ветке contour.py:261-263 «мест нет — чинить нечего, клетка не покупается». Это НЕ окончательный n: честный выход арма на такой единице — черновик без правок, и сборка судейских входов (её в eval/dovodka/ ещё не существует — A1-тексты не читает ни один файл, кроме contour.py) может внести эти две единицы и удержать n=32. Более того, ИСКЛЮЧЕНИЕ их само по себе смещает контраст A1/A0 в сторону единиц, где флаговый контур сработал. Поэтому корректно так: A1/A0 стоит на границе — при n=30 MDE 1.5404 > цели, при n=32 1.4915 < цели; статус решается тем, как сборка обойдётся с двумя без-флаговыми единицами, и это решение должно быть объявлено ДО чтения перевесов.\n\nУТОЧНЕНИЕ 3 — «ФД-F $0.267825 потрачены впустую» сильнее факта. Сумма верна ($0.267825, `contour.py --plan`), но пре-рег сам разрешает описательным контрастам «печататься с числами» (power.py:75-88), так что материал A6 не мусор. Потеряно не $0.27, а НЕСУЩИЙ вердикт по H-1, которого заказ требует явно (POLYGON_EXP2223_REDO_SESSION_PROMPT.md:95-97).\n\nПОЧИНКА (уточнённая): считать и печатать MDE ПО КОНТРАСТУ с его собственным n, а статус оси выводить как худший по её первичному семейству; A6/A0 пере-классифицировать в описательный ДО чтения перевесов и сказать это в Д0.3/Д0.5; для A1/A0 объявить заранее правило обращения с без-флаговыми единицами (вносим черновик → n=32, несущий с запасом 0.0085; не вносим → n=30, описательный); заодно пере-снять вклеенную в отчёт таблицу Д0.3 — она не воспроизводится из закоммиченного инструмента."
|
||
}
|
||
},
|
||
{
|
||
"title": "Свой шумовой пол фазы не реализован: объявленная команда --floor молча выполняет --plan и возвращает 0, а денег в ФД-A на пол больше нет",
|
||
"severity": "критично",
|
||
"evidence": "contour.py:23 «Запуск: contour.py --plan | --selftest | --run [A1 A2 A3 A4 A6] | --floor», но в contour.py:291-298 ветки --floor нет: любой аргумент кроме --selftest/--run падает в else → cmd_plan(). Исполнено: `contour.py --floor` печатает план и RC=0. Грепом по eval/dovodka/*.py кода пола нет вовсе. При этом plan.py:73 закладывает его в ФД-A (`+ 16 * fixer`), Д0.6 объявляет его нормой («пол — парой, чьи половины судят РАЗНЫЕ сессии»), а power.py:98-100 ставит на нём пере-классификацию оси: «СВОЙ пол прохода меряется в фазе... если он выйдет хуже прайора — ось пере-классифицируется ТОГДА ЖЕ». Деньги: ФД-A потрачено 0.871904 при потолке 0.885 → остаток $0.013096; пол при ФАКТИЧЕСКОЙ p50 фиксера ($0.0075) стоит ~$0.120.",
|
||
"consequence": "Порог различимости оси Д4 будет взят из заимствованного прайора 2.12, и правило «решает СВОЙ пол» исполнить нечем. Ось Д4 без своего пола не может дать ни несущего вывода, ни честного описательного: MDE 1.491 держится на прайоре, который power.py:96-97 сам называет решающим («при sd 3.53 MDE был бы 2.48, ось стала бы описательной»). Плюс дыра в бюджете: A2 ($0.167 по смете) + добор A4 10 клеток ($0.079 по факту) + пол ($0.120) = $0.367 против остатка $0.013.",
|
||
"fix": "Написать --floor либо объявить в отчёте, что порог берётся из прайора и своего пола у Д4 нет. Пере-смета ФД-A и СТОП+пинг владельцу по правилу Д0.8 — сессия резать ось не вправе.",
|
||
"verdict": {
|
||
"line": "гейты",
|
||
"corrected": "Свой шумовой пол оси Д4 не реализован и не оплачен, а вся несущесть оси держится на заимствованном прайоре с запасом ~1% по sd.\n\n(1) Кода пола в фазе нет вовсе: `grep -rn \"floor|пол\" eval/dovodka/*.py` даёт только докстринг contour.py:23, комментарий money_d.py:55 и текстовые ремарки power.py:16/30/98 — ни одной строки, покупающей или собирающей пару пола.\n(2) contour.py:23 объявляет `--floor`, но диспетчер contour.py:291-298 знает только `--selftest` и `--run`, всё прочее уходит в `else: cmd_plan()`. Это шире, чем в исходной формулировке: молча планом отрабатывает ЛЮБОЙ нераспознанный аргумент (в т.ч. опечатка `--pln`), всегда RC=0.\n(3) Смета пола занижена вдвое с лишним ещё до траты: plan.py:75 закладывает `16 * fixer`, где `fixer` — ПРОГНОЗ plan.py:56 ($0.00314, «0.60× переписа»), тогда как факт p50 фиксера по 100 купленным клеткам ~/books/dovodka — $0.007561. Пол стоит $0.121, а в смете под него $0.050.\n(4) Денег нет: CEILINGS ФД-A = 0.885 (money_d.py:67), потрачено 0.871904 → остаток $0.013096; требуется A2 $0.167 + добор A4 10 клеток $0.079 + пол $0.121 ≈ $0.367.\n(5) Вывод, который это меняет, острее заявленного: power.py печатает Д4 n=32 k=3 sd 2.12 MDE 1.49 при цели 1.50 — запас 0.01. Прогоном mde(sd,32,3): sd 2.13 → 1.4985 (несущая), sd 2.14 → 1.5056 (описательная). То есть ЛЮБОЙ свой пол выше ~2.13 переводит ось в описательные, а правило Д0.3/Д0.6 «решает СВОЙ пол» исполнить нечем.\n\nУточнения к улике: `+ 16 * fixer` — plan.py:75, не :73. Цифра MDE 1.491 взята из кода (power.py), а опубликованная таблица Д0.3 отчёта (23-editor-tier.md:759, «k 5 · MDE 1.29») ей противоречит и устарела — отдельное расхождение, но оно усиливает, а не ослабляет находку.\n\nТяжесть: «критично» справедливо для денежно-нормативной половины; сам по себе фантомный `--floor` — средняя (денег ещё не потрачено впустую, судейство фазы не запускалось).",
|
||
"refuted": false,
|
||
"why": "Опровергнуть не удалось — каждый грунт подтверждён исполнением, а искал я именно объявленное ограничение и завышенный масштаб.\n\nИсполнено:\n* `grep -n -- \"--floor\" eval/dovodka/contour.py` → одна строка, 23: «Запуск: contour.py --plan | --selftest | --run [A1 A2 A3 A4 A6] | --floor».\n* `sed -n '289,298p'` → диспетчер: `if a[0]==\"--selftest\" ... if a[0]==\"--run\" ... else: cmd_plan()`. Ветки `--floor` нет.\n* `eval/.venv/bin/python eval/dovodka/contour.py --floor` → напечатал план покупок и кассу, «RC=0». Сетевых вызовов нет (cmd_plan только читает).\n* `grep -rn \"floor|пол\" eval/dovodka/*.py` → contour.py:23 (докстринг), money_d.py:55 (комментарий «+ свой шумовой пол»), power.py:16/30/98 (ремарки). Ни строки кода пола. В runs.py и canon.py — тоже ничего (грепал отдельно).\n\nПроверка «не объявлено ли это ограничением»: наоборот, доки обещают пол трижды и нигде не снимают. 23-editor-tier.md:774-776 — «Своего пола у будущего прохода нет по построению; берётся худший... **Решает СВОЙ пол**, и если он выйдет хуже прайора, ось пере-классифицируется ТОГДА ЖЕ». Д0.6 (:817-821) — «Шумовой пол — парой, чьи половины судят РАЗНЫЕ сессии... Порог берётся из своего пола без ручной поправки». Д0.8 (:856) — строка сметы «ФД-A Д4 edit-контур zh (A1·A2·A3·A4, n=32 + свой пол) 0.877». В `docs/POLYGON_EXP2223_REDO_SESSION_PROMPT.md` и `docs/PROGRESS.md` слов «--floor»/«свой пол» про фазу Д нет (грепал). Значит объявленного отказа от пола не существует — путаницы «объявленное против реального» у автора находки нет.\n\nПроверка масштаба (числа, свои команды):\n* Деньги. `money_d.py:67` CEILINGS[\"ФД-A\"]=0.885; вывод `contour.py --floor` — ФД-A потрачено 0.871904 → остаток $0.013096 (совпало с уликой).\n* Цена пола. Скрипт по ~/books/dovodka/*.json: fixer n=100, p50 $0.007561 → 16 клеток = $0.1210 (улика: «~$0.120» — верно). A4 fixer p50 $0.007937 → добор 10 клеток $0.0794 (улика $0.079 — верно). `plan.py` печатает edit/onepass $0.00523 → A2 32 клетки $0.167 (верно). Сумма $0.367 против остатка $0.0131 — подтверждена.\n* Мощность. `eval/.venv/bin/python eval/dovodka/power.py` → «Д4 edit-контур zh 32 3 2.12 1.49 1.50 0.0000 НЕСУЩАЯ» (улика «MDE 1.491» — верна, это код). Прямым вызовом `m.mde(sd,32,3)`: 2.12→1.4915, 2.13→1.4985, 2.14→1.5056, 2.90→2.0402, 3.53→2.4835. Порог опрокидывания — sd≈2.135, то есть прайор решает с запасом ~1%, а не «с запасом». Цитата power.py:96-99 про «при sd 3.53 MDE был бы 2.48, ось стала бы описательной» — на месте.\n\nЕдинственные неточности улики — мелкие и не в пользу опровержения: `+ 16 * fixer` стоит на plan.py:75 (не :73); заявленный `--plan`-фолбэк на деле срабатывает на любом неизвестном аргументе, а не только на `--floor`; смета пола вдобавок построена на прогнозной цене фиксера $0.00314 (plan.py:56/69) вместо факта $0.00756, то есть под пол не хватало денег и в самой смете. Ни одна из них находку не отменяет.\n\nФайлы: /home/ubuntu/projects/textmachine/eval/dovodka/contour.py:23,291-298 · /home/ubuntu/projects/textmachine/eval/dovodka/plan.py:56,69,75 · /home/ubuntu/projects/textmachine/eval/dovodka/money_d.py:55,67 · /home/ubuntu/projects/textmachine/eval/dovodka/power.py:96-99 · /home/ubuntu/projects/textmachine/docs/experiments/23-editor-tier.md:759,774-776,817-821,856"
|
||
}
|
||
},
|
||
{
|
||
"title": "conformance.py --final структурно не может позеленеть: 12 строк-заголовков реестра считаются требованиями с пустой уликой",
|
||
"severity": "критично",
|
||
"evidence": "conformance.py:80-85 отсеивает только разделители и шапку ID/№; строка `| **РАМКА** | | |` проходит как требование с уликой ''. conformance.py:155-157: в --final ОЖИДАЕТ превращается в ПРОВАЛ. Счёт в requirements.md: `grep -c '^| \\*\\*'` = 12, `grep -c '^| R[0-9]'` = 77, гейт печатает «требований 89». Выхлоп --final: строки `[ПРОВАЛ ] **НОРМЫ РИГА** ← улики нет, а пак сдаётся`, `[ПРОВАЛ ] **АНТИ-ЛЕНЬ**`, `[ПРОВАЛ ] **ОТЧЁТ И СДАЧА**` и т.д.",
|
||
"consequence": "Режим сдачи, ради которого инструмент написан («--final ... Гонять перед сдачей пака», conformance.py:20), никогда не даст код 0 — минимум 12 провалов при любой полноте пака. Значит при сдаче автор всё равно будет читать красный выхлоп и решать глазами, какие красные важны: ровно та ручная процедура, которую инструмент заменяет. Заодно знаменатель «сам-себя: 9 из 89» занижает долю — реально 9 из 77.",
|
||
"fix": "Пропускать строки, у которых ячейка ID обёрнута ** ** (или у которых пусты и требование, и улика), и считать total по ним же.",
|
||
"verdict": {
|
||
"line": "гейты",
|
||
"corrected": "Формулировка верна по механике и числам; неточны тяжесть и формулировка «последствия».\n\nТочная редакция: **`conformance.py` считает 12 строк-разделителей реестра полноценными требованиями, из-за чего `--final` даёт пол в 12 ПРОВАЛов при любой полноте пака (код возврата никогда не 0), а знаменатели «требований N» и «сам-себя: 9 из N» завышены на 12 (89 вместо 77).** Это ЛОЖНО-КРАСНЫЙ, громкий и $0-отказ, а не ложно-зелёный: провалившие строки печатаются с ID `**РАМКА**`/`**НОРМЫ РИГА**` и пустым текстом требования — их ни с чем не спутать, отличать их «глазами» не приходится. Поэтому тяжесть — средняя (максимум высокая), а не критическая: денег не тратит, ни одного числа экспериментов не меняет, ни один уже опубликованный вывод не разворачивает (единственный исторический зелёный клейм conformance уже аннулирован по ДРУГОЙ причине — реестр в scratchpad, `docs/PROGRESS.md:241` и `docs/experiments/23-editor-tier.md:34`).\n\nЧто реально ломается — не «читатель вернётся к ручной процедуре», а: (1) двоичный контракт гейта («ненулевой код = не сдаётся», формулировка шапки отчёта, `23-editor-tier.md:29`) на `--final` неисполним, т.е. при сдаче фазы Д клейм «сверка с буквой заказа пройдена кодом 0» сделать честно нельзя; (2) доля «сам-себя», ради печати которой инструмент правили в фазе Д (докстринг :35-39), занижена: 9/89 = 10.1% вместо 9/77 = 11.7%; (3) в `--plan` те же строки раздувают счётчик хода работ («требований 89 · ожидают 58» вместо 77/46) при коде 0.\n\nУточнение по слову «структурно»: пол в 12 — свойство пары «инструмент + текущий реестр», а не только кода; чинится и в `rows()` (пропускать строки с ID в `** **` или с пустыми требованием И уликой, и total считать по ним же), и в самом реестре. Но реестр зафризен в git и `--final` требует совпадения с закоммиченным (`conformance.py:52-65`, `requirements.md:7-9`), поэтому починка на стороне реестра требует пере-фриза коммитом.",
|
||
"refuted": false,
|
||
"why": "Опровергнуть не удалось; всё проверено исполнением, а не чтением формулировки.\n\n1. Парсер действительно принимает шапки за требования. Прогнал собственный `rows()` инструмента:\n`eval/.venv/bin/python -c \"...import conformance as c; rs=c.rows(open('eval/dovodka/requirements.md').read())\"` →\n`total rows parsed: 89`, `bold header rows parsed as requirements: 12`, каждая вида `('**РАМКА**', '', '')`.\nМеханика — ровно как заявлено: `/home/ubuntu/projects/textmachine/eval/conformance.py:81` отсеивает только строки, у которых ячейка ID состоит из `-:` и пробелов, `:83` — только `ID`/`№`; `| **РАМКА** | | |` проходит и уходит в `out` (`:85`).\n\n2. Числа совпадают. `grep -c '^| \\*\\*' eval/dovodka/requirements.md` = **12** (строки 27, 36, 43, 46, 58, 65, 68, 75, 78, 92, 103, 111), `grep -c '^| R[0-9]'` = **77**, 12+77 = 89. Счётчик `сам-себя` посчитал я тем же кодом, что и инструмент (`selfnames` из `:151-152`) — **9** (R44-R48, R50, R51, R53, R64), т.е. печатается «9 из 89», хотя требований 77.\n\n3. Ветка ПРОВАЛа достижима и не перехватывается фриз-гейтом. `git ls-files --error-unmatch eval/dovodka/requirements.md` → tracked, `git diff --quiet HEAD --` → clean, значит `frozen()` (`:137-144`) пропускает, и цикл `:153-164` выполняется.\n\n4. Главный клейм — «не может позеленеть при любой полноте пака» — проверил моделированием МАКСИМАЛЬНО полного пака: подменил `check()` так, что ЛЮБАЯ объявленная улика возвращает OK, пустые ячейки идут штатным путём, и вызвал `main()` с `--final`. Выхлоп дословно содержит `[ПРОВАЛ ] **РАМКА** ← улики нет, а пак сдаётся`, `[ПРОВАЛ ] **НОРМЫ РИГА**`, `[ПРОВАЛ ] **АНТИ-ЛЕНЬ**`, `[ПРОВАЛ ] **ОТЧЁТ И СДАЧА**` и т.д. (все 12), итог `требований 89 · ожидают 0 · провалов 58`, `EXIT CODE: 1`. Путь: `:155-157` (ОЖИДАЕТ→ПРОВАЛ) → `:162` → `:169-171` (`return 1 if bad`). Даже если бы все 77 R-строк имели проходящую улику, `bad` был бы ≥12 и код ≠0. Тот же прогон в `--plan` дал `требований 89 · ожидают 58 · провалов 0`, `EXIT CODE: 0` — режим плана заявленное поведение сохраняет, но счётчик раздут на 12.\n\n5. «Объявленное ограничение»? Нет. Прочитал целиком докстринг (`conformance.py:2-40`): объявлены ровно два ограничения — связь «требование↔улика» не проверяется (`:24-27`) и два дефекта, чинившиеся в фазе Д (эфемерный реестр и счётчик «сам-себя», `:29-39`). Про строки-разделители, про пол провалов и про знаменатель — ни слова. Шапка самого реестра (`eval/dovodka/requirements.md:7-21`) и оговорка §0 отчёта (`docs/experiments/23-editor-tier.md:31-39`, где перечислены три вещи, которых гейты НЕ доказывают) этого тоже не называют. `grep -rn \"требований 89\\|из 89\"` по `docs`+`eval` — пусто, т.е. число нигде ещё не опубликовано, ущерб проспективный.\n\nИтого: находка верна по факту и по числам; корректирую только тяжесть (ложно-красный громкий отказ, а не критический ложно-зелёный) и формулировку последствия (ломается двоичный контракт кода возврата и знаменатель доли «сам-себя», а не «возврат к ручной процедуре»)."
|
||
}
|
||
},
|
||
{
|
||
"title": "Улики с экранированным пайпом не разэкранируются: R37 зелёная, хотя её grep никогда не выполняется, R55 вечно красная по синтаксису sh",
|
||
"severity": "критично",
|
||
"evidence": "conformance.py:103 `subprocess.run(cmd, shell=True, ...)` получает строку прямо из ячейки markdown-таблицы, где пайп обязан быть записан как `\\|`. requirements.md:70 R37 = `$ eval/.venv/bin/python eval/dovodka/material_ja.py \\| grep -q \"СТОП\\|OK \"`. Исполнено: `sh -c 'eval/.venv/bin/python -c \"...print(sys.argv[1:])\" \\| grep -q ZZZZNOTPRESENT'` печатает `ARGV ['|', 'grep', '-q', 'ZZZZNOTPRESENT']`, RC=0 — grep не запускался, аргументы ушли в python. requirements.md:90 R55 = `$ test $(grep -l ... docs/experiments/*.md \\| wc -l) -ge 7` → в выхлопе `/bin/sh: 1: Syntax error: end of file unexpected`.",
|
||
"consequence": "R37 («материал непригоден → СТОП и пинг») сертифицирована зелёной, а проверяет она не то, что написано: реально это «material_ja.py вышел с кодом 0», то есть при СТОПе (material_ja.py:145 return 1) улика упала бы, хотя СТОП — законный исход. R55 («статус-баннеры на отчётах») числится провалом по причине, не связанной с требованием, и в замороженном реестре её не поправить без нового коммита. Оба класса — «гейт зелёный/красный не по тому, что он якобы меряет» — это ровно то, ради чего conformance написан.",
|
||
"fix": "В check() заменять `\\|` на `|` перед запуском (и `\\\\` тоже), либо запретить пайпы в уликах явной проверкой с падением.",
|
||
"verdict": {
|
||
"line": "гейты",
|
||
"refuted": false,
|
||
"why": "Не опровергнуто по сути, но механизм в улике назван НЕВЕРНО, и предложенная починка не сработала бы.\n\nЧТО ПРОВЕРЕНО ИСПОЛНЕНИЕМ.\n\n1) Реальный механизм — не `sh`, а парсер таблицы. `eval/conformance.py:80` — `cells = [c.strip() for c in s.strip(\"|\").split(\"|\")]` — режет строку по СЫРОМУ `|`, не понимая `\\|`. Ячейка улики обрывается на первом экранированном пайпе ДО того, как `check()` вообще что-то видит. Прогон парсера самого инструмента:\n```\neval/.venv/bin/python -c 'import sys;sys.path.insert(0,\"/home/ubuntu/projects/textmachine/eval\");import conformance as C;from pathlib import Path;md=Path(\"/home/ubuntu/projects/textmachine/eval/dovodka/requirements.md\").read_text(encoding=\"utf-8\");[print(r[0],repr(r[2]),C.check(r[2])) for r in C.rows(md) if r[0] in (\"R37\",\"R55\")]'\n```\nвывод:\nR37 EV = '`$ eval/.venv/bin/python eval/dovodka/material_ja.py \\\\' -> ('OK', '')\nR55 EV = '`$ test $(grep -l \"баннер фазы Д\" docs/experiments/*.md \\\\' -> ('ПРОВАЛ', '/bin/sh: 1: Syntax error: end of file unexpected (expecting \")\")')\nЗаметь: сообщение об ошибке R55 в улике («Syntax error: end of file unexpected») воспроизводится ТОЛЬКО так — то есть автор находки прогнал настоящий инструмент, но объяснил результат неверной моделью. Его собственная реконструкция `sh -c '... \\| grep -q ZZZZNOTPRESENT'` даёт другую картину: я её повторил (`ARGV ['|', 'grep', '-q', 'ZZZZNOTPRESENT']`, RC=0) — она верна как факт про sh, но к conformance.py отношения не имеет, потому что до sh хвост уже отрезан.\n\n2) Из этого следует, что починка «в check() заменять `\\|` на `|`» НЕ РАБОТАЕТ: к моменту вызова check() (conformance.py:91) хвоста команды уже нет. Чинить надо `rows()` (conformance.py:80) — split по НЕэкранированным пайпам.\n\n3) Масштаб рядов: экранированные пайпы ровно в двух строках — `grep -n '\\\\|' eval/dovodka/requirements.md` даёт только 70 (R37) и 90 (R55) из 89 распарсенных строк / 30 улик-команд.\n\n4) Не объявленное ограничение. Докстринг conformance.py:24-27 объявляет другой класс («улика может не доказывать именно это требование» — связь ставит автор). Здесь инструмент исполняет НЕ ТУ команду, которую автор объявил, и молча. Ни в docstring, ни в шапке requirements.md:1-21, ни в отчётах этого нет: `grep -rn \"R55\\|R37\" docs/experiments/23-editor-tier.md docs/PROGRESS.md` — ноль.\n\n5) Реестр действительно заморожен: `git status --porcelain eval/dovodka/requirements.md eval/conformance.py` — пусто, `git ls-files` обоих находит. Правка только новым коммитом — верно.",
|
||
"corrected": "Исправленная формулировка (заголовок): «Парсер таблицы режет ячейку улики по экранированному пайпу: conformance.py исполняет обрубок команды. R37 зелёная пустотой, R55 — ЛОЖНО красная на фактически выполненном требовании, из-за чего --final не может пройти в принципе».\n\nПравки к исходной формулировке:\n* Механизм — conformance.py:80 (`split(\"|\")` не понимает `\\|`), а не conformance.py:103 (`shell=True`). Команда не «уходит аргументами в python» — её хвост просто не существует к моменту запуска.\n* Починка — в rows() (split по неэкранированным пайпам, либо явный отказ при `\\|` в ячейке), а не в check(); замена `\\|`→`|` внутри check() бесполезна.\n* Масштаб R55 СИЛЬНЕЕ, чем сказано. Требование фактически ИСПОЛНЕНО: `grep -l \"баннер фазы Д\" docs/experiments/*.md | wc -l` = 7, и неэкранированная команда возвращает 0 (`sh -c 'test $(grep -l \"баннер фазы Д\" docs/experiments/*.md | wc -l) -ge 7'; echo $?` → 0). То есть это не «провал по причине, не связанной с требованием», а ЛОЖНЫЙ ОТКАЗ по выполненному требованию. Поскольку main() возвращает `1 if bad else 0` (conformance.py:171), замороженный реестр делает `--final` структурно непроходимым — это меняет вывод фазы прямо сейчас.\n* R37: дефект ЛАТЕНТНЫЙ, а не текущий. Сегодня оба варианта дают 0 — я прогнал и обрубок (`material_ja.py` RC=0), и задуманное (`eval/.venv/bin/python eval/dovodka/material_ja.py | grep -q \"СТОП\\|OK \"` → RC=0). Расхождение проявится на СТОПе: обрубок = «rc==0», а material_ja.py:145 на СТОПе возвращает 1, тогда как задуманный пайп на СТОПе прошёл бы (material_ja.py:131 печатает «⛔ СТОП»). То есть улика инвертирует само требование R37, но вывод пака поменяет только когда материал окажется непригоден."
|
||
}
|
||
},
|
||
{
|
||
"title": "Фриз-гейт кассы проверяет ровно ОДИН файл — первый кадр стека; промпты, роспись моделей и сами потолки фазы вне фриза",
|
||
"severity": "важно",
|
||
"evidence": "money.py:181-196: цикл по стеку, на первом же кадре не-money.py делается `_git_clean(p)` и `return` (строка 196 внутри for). При покупке из contour.py проверяется только contour.py. Вне проверки остаются prompts.py (PR.law_block — текст банк-закона, contour.py:146), bank.py (contour.py:102), roster.py (call_kwargs — параметры вызова, contour.py:257/267/286), editors.py (клиент), editor_tier/panel.py, role_topology/battery.py и money_d.py, который задаёт CEILINGS и PACK_CEILING (money_d.py:67-69). Селфтест кассы проверяет только сценарий exec-из-строки (money_d.py:126-130). Сейчас все девять файлов цепочки чисты по `git diff --quiet HEAD` — дыра не сработала, но и не закрыта.",
|
||
"consequence": "Правка банк-закона, температуры/модели или ФАЗОВОГО ПОТОЛКА между коммитом и покупкой проходит бесшумно, и клетки покупаются кодом, которого нет у читателя. Это ровно тот класс, который conformance чинил у себя (реестр из scratchpad) и который R71 требует по чужим ригам («правка рига чужого пака — отдельным коммитом»).",
|
||
"fix": "Проверять фриз для ВСЕХ кадров стека внутри зоны и для явного списка чужих модулей, от которых зависит содержимое запроса; `return` вынести за цикл.",
|
||
"verdict": {
|
||
"refuted": false,
|
||
"why": "Ядро находки подтверждается исполнением, но её механика, починка и охват описаны неверно.\n\nЧТО ПОДТВЕРДИЛОСЬ.\n1) `eval/tenant_panel/money.py:181-196` — `return` стоит на строке 196 ВНУТРИ `for fr in inspect.stack()[1:]`; `_git_clean` (money.py:192) зовётся ровно один раз, на первом кадре не-money.py. Прочитано `grep -n \"\" eval/tenant_panel/money.py | sed -n '160,205p'`.\n2) Кадры, которые гейт реально видит на покупке, я снял исполнением. Скрипт-зонд подменил `MONEY.purchase` записывателем стека и прогнал `contour.cmd_run([\"A4\"])` (арм не докуплен, 22 из 32). Вывод: `/home/ubuntu/projects/textmachine/eval/dovodka/contour.py`, затем файл-точка-входа. Всё. Ни `prompts.py`, ни `roster.py`, ни `bank.py`, ни `money_d.py` в стеке НЕТ — они импорты, а `CEILINGS`/`PACK_CEILING` ставятся `M22.configure` на импорте (money_d.py:67-72, contour.py:61-63). Значит фриз их действительно не покрывает.\n3) Купленная клетка НЕ хранит отправленный промпт: ключи `dv-a-a1-b0a5efaa11.json` = arm, cached_tokens, completion_tokens, content, cost_usd, finish, latency_s, model, model_returned, places, prompt_tokens, reasoning_*, role, tag, total_tokens, uid. Пост-хок восстановить текст запроса можно только из кода — то есть последствие «клетки куплены кодом, которого нет у читателя» ничем не смягчено.\n4) Селфтест кассы по фризу правда проверяет только exec-из-строки (money_d.py:124-130); рядом есть лишь `M22.ZONE == ZONE` (money_d.py:101), это про адрес зоны, не про охват.\n\nЧТО ОПРОВЕРГАЕТСЯ.\n5) Предложенная починка «вынести `return` за цикл» — НО-ОП для всего перечисленного автором. Перечисленные девять модулей никогда не кадры (п.2), а в боевом запуске `contour.py --run` единственный зонный файл в стеке — сам contour.py, он же `__main__`: обход всех кадров проверил бы его дважды. Закрывает дыру только вторая половина предложения — явный манифест зависимостей.\n6) Автор пишет, что вне проверки остаются в том числе местоположение и «код, которого нет у читателя» в общем виде. Половина «локация» НЕ дырявая: в `eval/role_topology/buy.py:98-130` есть ВТОРОЙ независимый гейт `_refuse_unfrozen_caller`, он идёт по ВСЕМ кадрам без раннего return (`return` на строке 130, вне цикла) и отвергает любой кадр вне `eval/`. Проверено исполнением: драйвер из /tmp, зовущий `contour.cmd_run([\"A4\"])` с подменённым клиентом, получил `⛔ покупка из кода вне зоны полигона запрещена: /tmp/.../probe3.py` ДО сети. То есть незакоммиченный скрипт откуда угодно купить не может; дыра сужена до «файл внутри eval/, изменённый после коммита».\n7) Единичный охват объявлен в докстрингах обоих гейтов: money.py:11-13 («покупка отказывает, если файл ВЫЗЫВАЮЩЕГО … отличается от закоммиченного») и buy.py:107 («Проверяется ФАЙЛ ВЫЗЫВАЮЩЕГО»). Это документированный дизайн, а не тихий баг. Недокументирован именно РАЗРЫВ с законом фазы: `docs/POLYGON_EXP2223_REDO_SESSION_PROMPT.md:22` формулирует закон шире — «фриз-гейт „покупает только закоммиченный код“». Разрыв реальный, поэтому находку не снимаю.\n8) Ни одного доллара и ни одного вывода фазы это не двигает. `git diff --quiet HEAD -- <файл>` по всей цепочке: contour.py, money_d.py, money.py, prompts.py, bank.py, roster.py, editors.py, editor_tier/panel.py, role_topology/battery.py, role_topology/buy.py — ВСЕ CLEAN. Последние коммиты (prompts/roster 08.08 15:14, editors 08.08 22:26, bank и editor_tier/panel 10.08 07:05, money_d 10.08 07:06, contour 10.08 17:11) предшествуют первой покупке фазы (mtime `dv-a-*.json` = 10.08 22:01). Грязны в дереве только `eval/dovodka/material_ja.py` и `eval/editor_tier/axiscal.py`, и ни один из них в цепочку покупок ФД-A/ФД-F не входит: `MAT` в contour.py — это `editor_tier/material.py` (editor_tier/panel.py:43), не material_ja.py.\n\nИтог: находка верна по существу (фриз-гейт покрывает один файл, содержимое запроса и потолки — вне фриза), но её причинно-следственная часть, починка и оценка «что остаётся незащищённым» требуют правки; тяжесть — не «важно», а долг харнесса без последствий для фазы.",
|
||
"corrected": "Git-фриз покрывает ровно ОДИН файл — ближайший кадр вызывающего (money.py:181-196, `return` внутри цикла). Всё, от чего зависит СОДЕРЖИМОЕ запроса и границы траты, фризом не проверяется: `prompts.PR.law_block` (contour.py:146,156), `bank.py` (contour.py:102), `roster.call_kwargs` (contour.py:257,267,286), `editors.client`, `editor_tier/panel.py`, `role_topology/battery.py` и `money_d.py` с `CEILINGS`/`PACK_CEILING` (money_d.py:67-72). Причина НЕ в раннем `return`: эти модули — импорты и никогда не кадры стека (проверено зондом: стек на покупке = contour.py + точка входа), а конфиг кассы ставится на импорте. Поэтому «вынести return за цикл» дыру не закрывает — нужен явный манифест зависимостей с хешами, снимаемый перед покупкой (и, дешевле, запись отправленных messages в клетку: сейчас клетка промпт не хранит).\n\nМасштаб уже; локационная половина закрыта вторым гейтом: `buy._refuse_unfrozen_caller` (buy.py:98-130) обходит ВСЕ кадры без раннего return и отвергает любой файл вне `eval/` — драйвер из /tmp получает отказ до сети (проверено исполнением). Остаточный риск — правка файла ВНУТРИ eval/ между коммитом и покупкой.\n\nЕдиничный охват объявлен в докстрингах (money.py:11-13, buy.py:107), недокументирован разрыв с законом фазы «покупает только закоммиченный код» (POLYGON_EXP2223_REDO_SESSION_PROMPT.md:22).\n\nПоследствий у фазы нет: все десять файлов цепочки clean по `git diff --quiet HEAD`, их последние коммиты предшествуют первой покупке (22:01 10.08); грязные material_ja.py и axiscal.py в цепочку ФД-A/ФД-F не входят. Тяжесть — «долг харнесса / расхождение закона и механизма», не «важно»."
|
||
}
|
||
},
|
||
{
|
||
"title": "Проекционный гард — на клетку, а не на арм: арм покупается наполовину и стоп ловится в середине",
|
||
"severity": "важно",
|
||
"evidence": "money.py:149-159 Guarded.afford(): `sp = self.spent(); exp = self.expect()` — ожидание ОДНОЙ следующей клетки, ничего о числе оставшихся клеток арма. contour.py:239-288: цикл по единицам, гард спрашивается на каждой. Факт: A4 22 клетки из 32, ФД-A 0.871904 при потолке 0.885. money_d.py:114-123 селфтест проверяет гард только на «нулевом потолке» и «видит цену дорогой модели».",
|
||
"consequence": "$0.19348 потрачены на арм A4, который не может дать контраст на объявленном n=32 (и при исключении 2 клеток finish=length даёт n=20, MDE 1.887 против цели 1.50). Незавершённый арм — худший исход, чем непокупка: деньги списаны, вывод не получен. Тот же механизм остановит любой следующий арм посередине.",
|
||
"fix": "Перед стартом арма проверять `spent + n_остаток * expect <= ceiling` и не начинать арм, который не влезает целиком; при отказе — СТОП и пинг по правилу Д0.8.",
|
||
"verdict": {
|
||
"refuted": true,
|
||
"why": "МЕХАНИЗМ ВЕРЕН, НО ОБЪЯВЛЕН, А НЕ НАЙДЕН.\n(1) Гранулярность гарда — это записанный дизайн, а не пропуск. `eval/dovodka/money_d.py:5`: «проекционный сторож перед КАЖДЫМ вызовом по цене ИМЕННО ЭТОЙ модели». Стопы посреди фазы объявлены риском ДО денег: `docs/experiments/23-editor-tier.md:870-872` — «Честным потолком БЕЗ СТОПОВ ПОСРЕДИ ФАЗЫ сессия называла $4.80; владелец выбрал $4.50. Срабатывание проекционного гарда = СТОП и вопрос владельцу».\n(2) ПРЕДЛОЖЕННАЯ ПОЧИНКА ПРЯМО ПРОТИВОРЕЧИТ РАТИФИЦИРОВАННОМУ ЗАКАЗУ. `docs/POLYGON_EXP2223_REDO_SESSION_PROMPT.md:23-24`: «Стоп-правило: не влезает → СТОП и пинг ДО покупок; **спрашивать при срабатывании стопа, а не по проекции** (жалоба эксп-22 ратифицирована владельцем поведением)». Автор предлагает ровно ту преждевременную арм-проекцию, которую владелец отверг поведением.\n(3) ПОЧИНКА УБИЛА БЫ АРМ ВЛАДЕЛЬЦА. `expect` — это НЕ средняя, а МАКСИМУМ замеренных цен (`money.py:model_expect`, `if len(prices)>=2: return max(prices)`); прогон дал max=$0.015945 при среднем $0.007701 (посчитал по 148 файлам ~/books/dovodka). Арм-проекция на старте A3: остаток $0.885−$0.226944=$0.658, проекция 64 вызова×$0.015945=$1.02 > остатка ⇒ A3 (СТАВКА ВЛАДЕЛЬЦА H-2б, первичный контраст) не стартовал бы вовсе. Фактически A3 уложился в $0.4515 и куплен целиком 32+32.\n(4) ЧИСЛА ПОСЛЕДСТВИЯ МИМО КАССЫ. `eval/dovodka/power.py:83-86` кладёт A4/A0 во ВТОРИЧНОЕ, ОПИСАТЕЛЬНОЕ семейство: «его несущая ось — покрытие канона, а оно детерминировано и шума не имеет». Первичное семейство (k=3) — A1/A0, A3/A0, A6/A0 (`power.py:70-73`), A4 в нём НЕТ. Цифра автора 1.887 = `power.mde(2.12,20,3)` (сверил: `mde(2.12,20,3)=1.887`) — это холм-множитель ЧУЖОГО семейства, применённый к описательному контрасту; без поправки k=1 даёт 1.558 при n=22. Цель 1.50 к A4 не относится.\n(5) ВЫВОД ПО A4 УЖЕ ПОЛУЧЕН, ДЕНЬГИ НЕ ПРОПАЛИ. Прогнал $0-скрипт по 22 купленным клеткам через `contour.canon_gaps`: дыр канона у A0 69 → после A4 63, улучшение на 12/22 единицах. Объявленная несущая ось арма читается прямо сейчас и уже расходится с прогнозом Д0.9 п.2 («лучшее покрытие канона из всей панели»). Это результат, а не «деньги списаны, вывод не получен».\n(6) КОРЕНЬ — СМЕТА, НЕ ГАРД. `eval/dovodka/plan.py:56`: `fixer = 0.60*edit` = $0.00314; факт — A4 $0.008795/клетка, A1 $0.00756/клетка (посчитал по сырью), 2.4–2.8× сметы. Смета ФД-A $0.877 покрывала A1+A2+A3+A4+пол 16 клеток; фактические $0.871904 купили только A1(30)+A3(32+32)+A4(22), а A2 и пол не тронуты вовсе. Любая гранулярность гарда при заниженной в 2.5 раза цене клетки даёт ту же нехватку.\n(7) НИ ОДИН ДОЛЛАР И НИ ОДИН ВЫВОД ФАЗЫ ОТ ЭТОГО НЕ МЕНЯЮТСЯ: деньги уже потрачены, судейств 0 из 80, из 10 некупленных клеток A4 одна (474f822806) пропущена законно — у неё 0 дыр канона, «чинить нечего» (`contour.py:262-265`).",
|
||
"corrected": "Остаток, который переживает проверку (мельче и о другом, тяжесть — мелочь): отказ гарда СОФТОВЫЙ и правило «стоп = вопрос владельцу» кодом не принуждается. `eval/role_topology/buy.py:143-147` при отказе печатает строку и возвращает `skipped`-запись, а цикл `contour.py:239-288` идёт к следующей клетке и следующему арму без `break`. То есть арм не «останавливается», а тихо доскакивает до конца, печатая по строке СТОП на каждую оставшуюся клетку; объявленный СТОП+пинг остаётся дисциплиной человека. Стоимость этого остатка в фазе Д = $0 (пропущенные клетки бесплатны), риск на будущее — ФД-E (16×$0.147 при потолке $2.355), где такая же тихая усечка возможна. Разумная починка — не арм-проекция (её владелец отверг), а `raise SystemExit` с пингом при ПЕРВОМ срабатывании гарда."
|
||
}
|
||
},
|
||
{
|
||
"title": "Смета фиксера ошиблась в 2.2-2.8 раза; гейта, сверяющего прогноз с фактом, нет, хотя plan.py его обещает",
|
||
"severity": "важно",
|
||
"evidence": "plan.py:56-57 `fixer = 0.60 * edit` = $0.00314, `critic = 2.14 * edit` = $0.01120; шапка выхлопа: «ПРОИЗВОДНЫЕ (прогноз, сверяется с фактом при закрытии)». Факт по сырью (p50 cost_usd): A1 fixer $0.00686 · A3 fixer $0.00741 · A4 fixer $0.00794 · A6 fixer $0.00888; A3 critic $0.00519 · A6 critic $0.00778. Фиксер дороже прогноза в 2.2-2.8×, критик дешевле в 1.4-2.2×.",
|
||
"consequence": "ФД-A выбрана на 98.5% при трёх армах из пяти вместо пяти плюс пола. Ошибки разнонаправленные, поэтому в общей сумме частично гасятся и в отчёте «$1.1397 из $4.50» выглядят благополучно — а на чисто-фиксерных армах (A1, A4) бьют в полную силу. Ни один гейт этой сверки не делает, значит следующая фаза унаследует те же коэффициенты.",
|
||
"fix": "Добавить в money_d.report() или plan.py пере-снятие фактических p50 по ролям и печать отклонения от прогноза с порогом, роняющим код возврата.",
|
||
"verdict": {
|
||
"line": "гейты",
|
||
"refuted": false,
|
||
"why": "Пере-снял всё своими командами, опровергнуть не смог.\n\n1) Числа прогноза воспроизводятся. `eval/.venv/bin/python eval/dovodka/plan.py` печатает: `edit deepseek-v4-pro $0.00523`, «ПРОИЗВОДНЫЕ (прогноз, сверяется с фактом при закрытии): фиксер $0.00314 (0.60× переписа) · критик $0.01120». Множители — plan.py:56-57.\n\n2) Факт по сырью — мой пересчёт всех 148 клеток ~/books/dovodka/*.json (медиана cost_usd по (arm, role)): A1 fixer n=30 p50 $0.00686 · A3 critic n=32 $0.00519 · A3 fixer n=32 $0.00741 · A4 fixer n=22 $0.00794 · A6 critic n=16 $0.00778 · A6 fixer n=16 $0.00888; сумма $1.139729 — сходится с состоянием в заказе. Отношения к прогнозу: фиксер 2.19 / 2.36 / 2.53 / 2.83×; критик 0.46 и 0.70× (то есть дешевле в 2.2 и 1.4×). Заявленный масштаб «2.2–2.8×» и «1.4–2.2×» верен.\n\n3) Кода сверки нет нигде: `grep -rn \"0\\.60|2\\.14|сверк|прогноз\" eval/dovodka/*.py` даёт только сами строки plan.py:55,68-70 и не относящийся к делу комментарий contour.py:19. money_d.report() (money_d.py:77-88) печатает лишь потрачено/потолок/пробой, selftest() (money_d.py:90-133) сверяет суммы потолков и проекционный гард — сверки «прогноз vs факт» ни там, ни там нет.\n\n4) В докax это НЕ объявлено как ограничение: §Д0.8 отчёта (docs/experiments/23-editor-tier.md:869-887) говорит только «цены — медианы по СЫРЬЮ», о риске множителей молчит; grep по «дороже прогноза|смета ошиб|недооцен|0.0068|0.0074|0.0079|0.0088» в 23-editor-tier.md, POLYGON_EXP2223_REDO_SESSION_PROMPT.md, PROGRESS.md, requirements.md — ноль хитов. Значит это не исполненная норма.\n\n5) Вывод меняется: пересчёт ФД-A по фактическим p50 (32·A1f + 32·edit(A2) + 32·(A3c+A3f) + 32·A4f + 16·fixer(пол)) = $1.163 против потолка $0.885 — ось недобюджетирована примерно на 30%, а не «ошибки частично гасятся». Факт по кассе: `dv-a-*` = A1 30 + A3 32+32 + A4 22 = $0.87189 = 98.5% потолка $0.885 (A6 лежит в ФД-F, dv-f-a6-*, $0.2678).",
|
||
"corrected": "Смета фиксера занижена в 2.2–2.8×, критика завышена в 1.4–2.2×; сверки прогноза с фактом нет ни в одном инструменте фазы, а measured() физически не видит сырьё фазы Д.\n\nТри поправки к исходной формулировке:\n\n(а) plan.py обещает не ГЕЙТ, а ПЕЧАТЬ: plan.py:55 «они ПРОГНОЗ, и расхождение с фактом печатается при закрытии фазы как сверка сметы» + шапка выхлопа plan.py:68. Фаза не закрыта, так что формально срок обещания не наступил — но кода, который эту печать делает, нет ни в plan.py, ни в money_d.report()/selftest(), ни где-либо в eval/dovodka (grep выше). Претензия к отсутствию механизма остаётся, претензия к нарушенному обещанию — преждевременна.\n\n(б) масштаб последствия назван неверно: ФД-A по plan.py:74-77 покрывает ЧЕТЫРЕ арма (A1·A2·A3·A4) плюс свой пол на 16 клеток, а не пять. Факт: 98.5% потолка съедены ТРЕМЯ армами, причём A4 — только 22 клетками из 32, при нуле у A2 и НЕкупленном шумовом полу. Пятый арм A6 к ФД-A не относится (ФД-F, $0.2678).\n\n(в) добавляется грунт, которого в находке нет и который усиливает «следующая фаза унаследует коэффициенты»: plan.py:26-27,34 — measured() читает только ~/books/tenant-panel (tp*.json) и ~/books/editor-tier (et-*.json). Сырьё фазы Д (~/books/dovodka/dv-*.json) в замер не попадает вовсе, поэтому даже повторный запуск plan.py после покупок фазы самокоррекции не даёт: множители 0.60/2.14 останутся жёстко зашитыми, сколько бы фактических фиксер-клеток ни было куплено.\n\nОтдельно стоит отметить в отчёте: множитель критика 2.14 — не оценка сессии, а цифра из заказа владельца (H-2б, 23-editor-tier.md:730 «поиск ≈2.14× переписа»). Факт 0.46–0.70× опровергает саму посылку заказа о цене смыслового контура — это самостоятельный эмпирический результат фазы, а не только промах сметы."
|
||
}
|
||
},
|
||
{
|
||
"title": "Селфтест contour.py на двух ключевых проверках утверждает тавтологию, поэтому и пропустил Д-2",
|
||
"severity": "важно",
|
||
"evidence": "contour.py:224 `ck(\"канон-гейт выдаёт места (иначе A1 нечего чинить)\", isinstance(fl, list), f\"мест {len(fl)}\")` — flags_of всегда возвращает list (contour.py:114 `out = []`), утверждение истинно всегда, число мест печатается, но не проверяется. contour.py:213-214: `m1 = fix_msgs(src, d, [\"КАНОН: тест\"])`, `m3 = fix_msgs(src, d, [\"СМЫСЛ: тест\"])` — обе стороны «изоляции A1 против A3» построены ОДНОЙ функцией с разными списками; проверяется, что fix_msgs чистая функция аргументов, а не что армы делят вход. Ветка A2 (contour.py:251-258) селфтестом не строится ни разу — отсюда Д-1. Ветка A6 «оба контура» (Д-5) селфтестом не сверяется с объявлением contour.py:12.",
|
||
"consequence": "Селфтест печатает «ХАРНЕСС ГОДЕН» и RC=0 при батарее, падающей на 100% единиц (проверено: AttributeError 'dict' object has no attribute 'final'), при недостижимой ветке A2 и при A6, идущем одним контуром вместо двух. Гейт, обязанный пройти ДО первой покупки (contour.py:190), пропустил три из пяти известных дефектов и не мог поймать их по построению.",
|
||
"fix": "Заменить isinstance на `len(fl) > 0 and any(f.startswith(\"БАТАРЕЯ\") for f in fl)`; собрать в селфтесте сообщения КАЖДОГО арма, включая A2, и проверить банк-закон в каждом; сверить объявленный контур арма с веткой cmd_run таблицей.",
|
||
"verdict": {
|
||
"refuted": false,
|
||
"why": "Проверил исполнением, опровергнуть не удалось — ядро находки подтверждается, неточны две частности.\n\n(1) Тавтология на :224 — ПОДТВЕРЖДЕНА буквально. `flags_of` (contour.py:111-124) заводит `out = []` и имеет единственный выход `return out`; пути, возвращающего не-list, нет. `isinstance(fl, list)` ложным быть не может.\n\n(2) Батарея мертва на 32/32 — ПОДТВЕРЖДЕНО прогоном. `battery.run_unit` (eval/role_topology/battery.py:515-526) читает `u.final`, `u.bank_dst`, `u.cards`, `u.draft` у датакласса `Unit`, а contour.py:118 передаёт `dict(uid=…, source=…, text=…)`. Мой скрипт по всем единицам: `units 32 battery failures 32 / errs {\"AttributeError: 'dict' object has no attribute 'final'\": 32} / canon flags total 74 · battery flags total 0 / units with zero flags: 2`. Две единицы без мест ровно объясняют A1 30 из 32. Важная поправка к предложенной починке: `len(fl) > 0` тоже прошёл бы (у единицы 0 шесть мест, все канонные) — ловит только половина `startswith(\"БАТАРЕЯ\")`.\n\n(3) Зелень гейта — ПОДТВЕРЖДЕНА: `eval/.venv/bin/python eval/dovodka/contour.py --selftest` → все 13 `[OK ]`, в т.ч. `канон-гейт выдаёт места … мест 6`, затем `ХАРНЕСС ГОДЕН`, RC=0.\n\n(4) A6 идёт ОДНИМ контуром — ПОДТВЕРЖДЕНО чтением cmd_run:243-287: A6 не входит в `if arm in (\"A1\",\"A4\")` и падает в ветку критик→фиксер; сырьё совпадает (16 `dv-f-a6-crit` + 16 `dv-f-a6`). Объявление обратного — contour.py:12 и пре-рег docs/experiments/23-editor-tier.md:800.\n\n(5) Объявленным ограничением это нигде не является: единственная релевантная декларация — contour.py:123 `# батарея не обязана знать наш вход` — легализует глотание исключения, а не потерю половины объявленного источника флагов; пре-рег (23-editor-tier.md:726, :800) и заказ (POLYGON_EXP2223_REDO_SESSION_PROMPT.md:32, :81) говорят «батарея + канон-гейт».\n\nВлияние на деньги и выводы реально: 30 клеток A1 на $0.2269 куплены как «детерминированные флаги (батарея + канон-гейт)», а фактически это канон-only, то есть по источнику мест A1 почти совпал с A4 — H-2а инструментирована наполовину; контраст A2/A0 из объявленного семейства Холма по пяти отсутствует физически (в ~/books/dovodka нет ни одного `dv-a-a2-*`).",
|
||
"corrected": "Селфтест contour.py зелёный (RC=0, «ХАРНЕСС ГОДЕН») при трёх реальных дефектах, и по построению не мог поймать ни один из них.\n\nТочно: (а) contour.py:224 — БУКВАЛЬНАЯ тавтология: `flags_of` (contour.py:111-124) заводит `out = []` и имеет единственный выход `return out`, `isinstance(fl, list)` истинно всегда; число мест печатается, но не проверяется. Пропущен Д-2: `battery.run_unit` (battery.py:515-526) ждёт датакласс `Unit` с `.final`, а contour.py:118 даёт dict — измерено 32 падения из 32 (`AttributeError: 'dict' object has no attribute 'final'`), 74 канонных флага и 0 батарейных, 2 единицы без мест (ровно A1 30/32). Поправка к починке автора: `len(fl) > 0` тоже прошёл бы (у единицы 0 шесть канонных мест) — необходима именно проверка `any(f.startswith(\"БАТАРЕЯ\") for f in fl)`.\n\n(б) contour.py:211-214 — НЕ тавтология, а проверка не того объекта: она реально удостоверяет, что `places` доезжают до user-сообщения, а закон и голова стоят в system; чего она не делает — не сверяет, что армы A1 и A3 в `cmd_run` получают ОДИН черновик (фактически получают: cmd_run:247 обоим даёт `base_draft`). То есть чек назван «изоляцией армов», а измеряет чистоту `fix_msgs`; ложной зелени здесь нет, есть непокрытое утверждение.\n\n(в) Ветка A2 не «недостижима» — она достижима и ПАДАЕТ. `hasattr(PR, \"translator_msgs\")` истинно (eval/tenant_panel/prompts.py:104), поэтому `else None` и объявленное мягкое «A2: сборки однопроходки нет — арм пропущен» (contour.py:254) — мёртвый код; настоящая сигнатура `translator_msgs(src, block, en=False)`, и вызов с одним аргументом даёт `TypeError: translator_msgs() missing 1 required positional argument: 'block'`, то есть прогон обрывается трейсбеком. Селфтест эту ветку не строит ни разу; клеток `dv-a-a2-*` в ~/books/dovodka ноль, контраст A2/A0 из семейства Холма по пяти отсутствует физически.\n\n(г) Объявленный контур A6 («оба контура», contour.py:12 и пре-рег 23-editor-tier.md:800) селфтестом не сверяется с кодом; cmd_run:243-287 гонит A6 только через критик→фиксер, что подтверждает сырьё (16 crit + 16 fixer)."
|
||
}
|
||
},
|
||
{
|
||
"title": "Атрибуция судей в runs.py ключуется на mtime файла ответа, а всё дерево ~/books пере-штамповано одной датой 2026-08-10 22:01",
|
||
"severity": "важно",
|
||
"evidence": "runs.py:153 `def judge_of(run: str, token: str, answer_mtime: float)`, runs.py:162 окно `_ts(r[\"at\"]) <= answer_mtime <= _ts(r.get(\"done_at\")) + 5.0`. Единственный производственный путь подачи — absjudge.py:323 `return JUDGES_HOOK(stem, path.stat().st_mtime)`. Пере-снято `find`ом: editor-tier 715 файлов, gu-zhenren 2366, role-topology 2797, tenant-panel 773 — ВСЕ с mtime 2026-08-10 22:01; в dovodka самый старый mtime тоже 2026-08-10 22:01:18. Селфтест runs.py (строки 244-251) кормит judge_of временами, выведенными из самого леджера (`_ts(a[\"at\"]) + 0.001`), ни одного файла не трогает.",
|
||
"consequence": "Механизм, написанный специально чтобы починить мис-атрибуцию голосов пака 23, стоит на величине, которую окружение уже трижды переписало (R51 в реестре — та же потеря провенанса по mtime у aj-border*). После любого копирования/восстановления дерева все ответы попадают в одно окно или в '?'. Селфтест 16/16, на который ссылается Д0.6, этого не видит и увидеть не может.",
|
||
"fix": "Писать время ответа внутрь артефакта (поле в json/txt) и атрибутировать по нему, а не по stat(). В селфтесте гонять judge_of на РЕАЛЬНОМ файле, у которого mtime сдвинут искусственно.",
|
||
"verdict": {
|
||
"refuted": false,
|
||
"corrected": "Механизм атрибуции судей `runs.judge_of` (eval/dovodka/runs.py:153,162) стоит на `st_mtime` файла ответа — величине, которую окружение этого проекта демонстрируемо стирает оптом. Дефект ЛАТЕНТНЫЙ и ПРОСПЕКТИВНЫЙ, а не сработавший: (а) `judge_of` сегодня НЕ имеет ни одного производственного вызова — ни один модуль eval/dovodka/ не импортирует ни `absjudge`, ни `runs`; связка `JUDGES_HOOK = runs.judge_of` в репозитории не написана; (б) плоские mtime, которые автор пересчитал, принадлежат ЗАКУПОЧНЫМ клеткам и артефактам прошлых паков, а `judge_of` работает по mtime файла ОТВЕТА СУДЬИ (absjudge.py:335 glob по `*.txt` → :382), которых в ~/books/dovodka не существует ни одного (agent-runs.json ABSENT, 0 сессий из 80). Ноль долларов и ноль выводов фазы затронуто СЕЙЧАС — цена дефекта наступает на первой же судейской сессии. Режим отказа при этом ХУЖЕ заявленного: при пере-штамповке ПОЗЖЕ сессий `judge_of` не отдаёт '?', а МОЛЧА возвращает имя ПОСЛЕДНЕЙ сессии для всех ответов (проверено исполнением). Тяжесть «важно» держится как блокер перед первой сессией, но не как порча уже произведённого результата. Мелочь в улике: селфтест печатает 15 проверок, не 16 — «16/16» автор переписал из доков (23-editor-tier.md:824, PROGRESS.md:227), не запустив его.",
|
||
"why": "ОПРОВЕРГНУТЬ НЕ УДАЛОСЬ — ядро находки подтверждено исполнением, неточны только масштаб и «производственный путь».\n\n1) Код такой, как заявлено. runs.py:153 `def judge_of(run: str, token: str, answer_mtime: float) -> str`; :162 `inwin = [r for r in cand if _ts(r[\"at\"]) <= answer_mtime <= _ts(r.get(\"done_at\")) + 5.0]`; :164-165 фолбэк `started[-1][\"judge\"] if started else \"?\"`.\n\n2) Пере-штамповка дерева РЕАЛЬНА и это плоская копия, а не `cp -p`. `cd ~/books && find editor-tier -type f -printf '%TH:%TM:%.2TS\\n' | sort -u | wc -l` → `1`, при 715 файлах; `stat -c '%n mtime=%y ctime=%z' editor-tier/agent-runs.json` → mtime==ctime==`2026-08-10 22:01:17.927446875` (совпадение ctime с mtime у ВСЕХ 715 файлов: `find editor-tier -type f -printf '%CY-%Cm-%Cd %CH:%CM:%.2CS\\n' | sort | uniq -c` → `715 2026-08-10 22:01:17`). Пооптовые числа автора подтверждены: gu-zhenren 2366, role-topology 2797, tenant-panel 773 — все в одну минуту 2026-08-10 22:01. В dovodka `for f in dv-*.json; do stat -c '%Y' \"$f\"; done | sort | uniq -c` → ровно ДВА значения на 148 клеток: `113 1786388477` (22:01:17) и `35 1786394384` (23:39:44). То есть провенанс по mtime у сырья уже уничтожен полностью.\n\n3) Последствие воспроизведено $0-симуляцией на временном леджере (импорт runs, подмена LEDGER, две сессии по одному токену, done обеих):\n `честные mtime: д-01 д-02`\n `после пере-штамповки ПОЗЖЕ: д-02 д-02`\n `после пере-штамповки РАНЬШЕ: ?`\n То есть при штампе позже сессий оба ответа МОЛЧА уходят последней сессии — ровно тот класс мис-атрибуции, ради починки которого модуль и написан (докстринг runs.py:10-13 «все её голоса получили имена судей боевого прогона»). Автор написал «в одно окно или в '?'» — верно, но недооценил: тихий вариант опаснее.\n\n4) Где автор неточен. `grep -rn \"JUDGES_HOOK\\|judge_of\" --include=*.py .` даёт всего 3 места вне runs.py: role_topology/absjudge.py:112 (объявление), :321-323 (`return JUDGES_HOOK(stem, path.stat().st_mtime)`), tenant_panel/judge.py:147 (`JUDGES_HOOK=None`), editor_tier/judge.py:173 (`None`) и :179 (`JUDGES_HOOK=lambda tok, _mtime: jmap.get(tok, \"?\")` — mtime принимается и ВЫБРАСЫВАЕТСЯ). `grep -rn \"^import\\|^from\" eval/dovodka/*.py` не содержит ни `absjudge`, ни `runs`. Значит `runs.judge_of` вызывается только из собственного селфтеста (runs.py:244-251) — «единственный производственный путь подачи» пока не существует, он предполагаемый.\n\n5) Объявлено ли это ограничение заранее? Частично и про ЧУЖОЙ объект: eval/dovodka/requirements.md:86 R51 — «Пере-штамповка `aj-border*` объявлена (копии `replication-runA`, mtime 23:31:54)», и POLYGON_EXP2223_REDO_SESSION_PROMPT.md:147 «исходный mtime-провенанс судейства утрачен». Это декларация про артефакты пака 23, а НЕ про надёжность нового механизма. В пре-реге Д0.6 (23-editor-tier.md:822-825) и в R60 (requirements.md:96) новый механизм подаётся без единой оговорки о хрупкости mtime — только «атомарный O_CREAT|O_EXCL-замок с проверкой живости PID, селфтест 16/16». Так что автор НЕ путает объявленное с реальным: конкретно эта уязвимость нигде не объявлена.\n\n6) Селфтест: `eval/.venv/bin/python eval/dovodka/runs.py --selftest` → 15 строк `[OK ]`, «ЖУРНАЛ ГОДЕН». Не 16. Утверждение автора, что селфтест кормит judge_of временами из самого леджера и не трогает ни одного файла, подтверждено runs.py:238-251 (`t_first = _ts(a[\"at\"]) + 0.001`, `t_second = _ts(b[\"at\"]) + 0.001`) — файловой чувствительности он действительно не проверяет и проверить не может.\n\n7) Меняется ли доллар или вывод фазы? Нет, сегодня. `test -e ~/books/dovodka/agent-runs.json` → ABSENT: журнал не создан, ни одной claim-записи, что сходится с «0 из 80». Голосов на диске нет, ни один вывод фазы Д на атрибуцию судей не опирается. Дефект стоит ровно перед следующим шагом, а не позади него."
|
||
}
|
||
},
|
||
{
|
||
"title": "verify22.py красный не из-за отчёта, а из-за той же mtime-плоскости: граница двойной оплаты посчиталась $0.000000, и гейт требует напечатать это в отчёте",
|
||
"severity": "важно",
|
||
"evidence": "verify22.py:176-184: `at = git log --format=%at -1 fd3e522`, затем `if f4.stat().st_mtime < int(at): pre += cost_usd`, и `ck(f\"верхняя граница двойной оплаты ${pre:.6f} напечатана\", ...)`. Пере-снято: коммит fd3e522 = 2026-08-08 20:43:25; файлов Ф2 335, с mtime раньше коммита — 0; самый старый mtime 2026-08-10 22:01:18. Отсюда pre = 0.0 и `[ПРОВАЛ] верхняя граница двойной оплаты $0.000000 напечатана`, RC=1. В отчёте 22-tenant-panel.md:226 стоит верное «≤$0.846103».",
|
||
"consequence": "R71 («правка рига чужого пака + пере-снятие его гейтов») не может позеленеть никогда, и conformance --final будет вечно нести этот провал. Хуже: гейт требует внести в отчёт заведомо бессмысленную границу $0.000000 вместо замеренной $0.846103 — то есть подталкивает к правке отчёта под сломанный прибор.",
|
||
"fix": "Заменить mtime-отсечку на явный список тегов Ф2, купленных до fd3e522 (по данным самих клеток), либо зафиксировать границу числом с провенансом и снять вычисление.",
|
||
"verdict": {
|
||
"refuted": false,
|
||
"why": "Пере-проверил своими командами — все числа находки воспроизвелись точно, опровергнуть нечего.\n\n1) Гейт красный ровно по этой строке и только по ней. `timeout 900 eval/.venv/bin/python eval/tenant_panel/verify22.py` → RC=1, единственный провал:\n`[ПРОВАЛ] верхняя граница двойной оплаты $0.000000 напечатана граница = расход Ф2 ДО атомарного замка...`\nОстальные ~50 проверок OK, финальная строка `РАСХОЖДЕНИЙ: 1 — ОТЧЁТ НЕ СДАЁТСЯ`. То есть отчёт со стороны чисел чист, красный даёт прибор.\n\n2) Код цитирован верно: eval/tenant_panel/verify22.py:176-184 — `git log --format=%at -1 fd3e522`, затем `if f4.stat().st_mtime < int(at): pre += cost_usd`, затем `ck(f\"верхняя граница двойной оплаты ${pre:.6f} напечатана\", has(t, f\"{pre:.6f}\"), ...)`.\n\n3) Арифметика: `git log --format='%at %ai' -1 fd3e522` → `1786211005 2026-08-08 20:43:25`. Своим скриптом по `MONEY.TAGS[\"Ф2\"]` (globs `tp2-draft-*`, `tp2-edit-*`, `tp2-floor-*`): файлов 335, полный расход $1.681912, самый старый mtime 2026-08-10 22:01:18.786414, файлов с mtime раньше коммита — 0, `pre = 0.000000`. Точно как в улике.\n\n4) Отчёт несёт верное число: docs/experiments/22-tenant-panel.md:224 «до него куплено **176 клеток Ф2 на $0.846103**» и :226 «⇒ **Верхняя граница невозвратной пере-оплаты: ≤$0.846103.**». Будь `pre` посчитан правильно, `has(t, \"0.846103\")` вернул бы True и гейт был бы зелёным. Значит вывод «гейт толкает вписать в отчёт $0.000000 вместо замеренного $0.846103» верен буквально.\n\n5) Последствие про R71 подтверждено механически: eval/dovodka/requirements.md:108 — улика R71 это ровно `$ eval/.venv/bin/python eval/tenant_panel/verify22.py`; eval/conformance.py:106-109 — `if r.returncode == 0: return \"OK\"` иначе `return \"ПРОВАЛ\"`. RC=1 ⇒ R71 навсегда ПРОВАЛ в `--final`.\n\n6) Проверил, не объявлено ли это ограничение заранее — НЕТ. Греп `mtime` по eval/ и docs/: объявлена только утрата провенанса судейства пака 23 (`docs/experiments/23-editor-tier.md:295-299`, R51 про `aj-border*`, копии 23:31:54). Про Ф2 пака 22 и про эту проверку не объявлено нигде. Это не «объявленное ограничение», а сломанный гейт.\n\n7) Проверил обратный вариант — не сломался ли отчёт, а не прибор: `git log -S\"0.846103\" -- docs/experiments/22-tenant-panel.md` → b1780b8, 2026-08-10 07:05:55, тем же коммитом, что и сам блок гейта (`git show b1780b8 --stat` содержит и verify22.py, и 22-tenant-panel.md). А mtime уплощены позже — в ~/books есть свой git, `cd /home/ubuntu/books && git log` → импорт 8307ccc «Import polygon raw material» 2026-08-10 21:59:47, и файлы проштампованы чекаутом в 22:01:17. То есть число было выведено этим же кодом, пока mtime были целы, и прибор сломался ПОСЛЕ.",
|
||
"corrected": "Находка верна по сути, числам и последствию. Уточняю две вещи — масштаб причины и осуществимость предложенной починки.\n\n(а) МАСШТАБ ПРИЧИНЫ ШИРЕ, ЧЕМ Ф2 ПАКА 22. Уплощены не клетки Ф2, а всё дерево сырья: `cd /home/ubuntu/books && find . -type f | wc -l` → 6880, `find . -type f ! -newermt '2026-08-10 22:01:00' | wc -l` → 0, то есть НИ ОДНОГО файла старше 2026-08-10 22:01:17 во всём ~/books. Пообъектно: dovodka/ 151, editor-tier/ 715, gu-zhenren/ 2366, jinpingmei/ 1, role-topology/ 2797, tenant-panel/ 773 — у всех oldest=newest≈2026-08-10 22:01:17–18. Новее 22:02 только `.git` и `dovodka/` (покупки фазы Д, до 2026-08-11 02:44). Причина — импорт сырья в git-репозиторий ~/books (commit 8307ccc, 21:59:47) с последующим чекаутом. Следствие: mtime-провенанс потерян у ВСЕХ паков разом, а не у одного гейта, и попутно устарела запись `docs/experiments/23-editor-tier.md:295` («mtime всех файлов равен 2026-08-09 23:31:54» — сейчас там 22:01:17).\n\n(б) ПЕРВАЯ ПОЛОВИНА ПРЕДЛОЖЕННОЙ ПОЧИНКИ НЕИСПОЛНИМА. «Список тегов Ф2, купленных до fd3e522, по данным самих клеток» построить нельзя: в клетках нет времени. Объединение ключей по всем 335 файлам Ф2 — `['attempt','cached_tokens','completion_tokens','content','cost_usd','en','finish','floor','latency_s','model','model_returned','prompt_tokens','reasoning_chars','reasoning_tokens','role','tag','tenant','total_tokens','uid']`, ни одного поля-таймстампа. И ни одна группировка по содержимому не даёт 176 клеток / $0.846103: role → draft 172/$0.611276, edit 163/$1.070636; en → False 263/$1.515148, True 72/$0.166764; floor → 0:267/$1.379217, 1:33/$0.141345, 2:35/$0.16135. Разбиение было чисто временным. В ~/books тоже не восстановить: там всего 2 коммита (`git log --oneline | wc -l` → 2), пофайловой истории нет. Значит осуществима только вторая половина: зафиксировать $0.846103 (176 клеток) константой с провенансом «замерено по mtime до импорта сырья в git 2026-08-10 21:59:47, коммит отчёта b1780b8» и снять вычисление, добавив в докстринг, почему прибор не пере-снимается.\n\n(в) МАСШТАБ ПОСЛЕДСТВИЯ: ни один потраченный доллар и ни одно замеренное число фазы не меняются — $0.846103 в отчёте остаётся верным на момент замера. Ломается приёмка: R71 не закрывается, `conformance --final` вечно несёт провал, и гейт в текущем виде подталкивает вписать в отчёт $0.000000. Тяжесть «важно» подтверждаю."
|
||
}
|
||
},
|
||
{
|
||
"title": "Счётчик «сам-себя» ловит только буквальное имя файла в строке улики; грепы отчёта, отмытые через скрипт, невидимы",
|
||
"severity": "важно",
|
||
"evidence": "conformance.py:151-152 `selfnames = {path.name, *(...)}` плюс глоб `2[23]-*.md`, conformance.py:159 `if any(n in ev for n in selfnames)`. Улики R49 и R61 = `$ eval/.venv/bin/python eval/editor_tier/verify23.py`, а verify23.py:38 `REPORT = REPO/\"docs\"/\"experiments\"/\"23-editor-tier.md\"` и вся его работа — `has(t, ...)` по этому тексту (verify23.py:132-181). Улика R71 = verify22.py, verify22.py:35 указывает на 22-tenant-panel.md. Ни одна из трёх не помечена [сам-себя] в выхлопе.",
|
||
"consequence": "Печатается «улик вида греп своего же документа: 9 из 89» — оба числа неверны: знаменатель завышен на 12 строк-заголовков (реально 77), числитель занижен минимум на 3. Читатель, ради которого строка и заведена (conformance.py:39 «требуется, чтобы читатель видел их число»), получает заниженную долю самопроверки.",
|
||
"fix": "Помечать улику как сам-себя, если запускаемый скрипт читает файл отчёта (список известных верификаторов), а не только по подстроке имени.",
|
||
"verdict": {
|
||
"refuted": false,
|
||
"corrected": "Механизм-наблюдение верно, но обе цифры и все три экспоната автора — не те. Верно и подтверждено: знаменатель 89 включает 12 строк-заголовков секций, реальных требований 77. Прогнал `rows()` напрямую: `total rows: 89`, `header-rows: 12 ['**РАМКА**','**Д1 — gemini**',...,'**ОТЧЁТ И СДАЧА**']`, `real R-rows: 77`. Автор при этом НЕ заметил куда более тяжёлое следствие того же дефекта: у заголовочной строки улика пустая, `check(\"\")` возвращает `('ОЖИДАЕТ','улика не объявлена')` (проверено исполнением), а conformance.py:155-157 в режиме `--final` превращает ОЖИДАЕТ в ПРОВАЛ — значит объявленный сдаточный гейт `--final` на этом реестре НИКОГДА не вернёт 0, минимум 12 гарантированных провалов, независимо от работы пака. Это, а не доля самопроверки, и есть настоящая находка в этой строке. Неверно: «числитель занижен минимум на 3» на уликах R49/R61/R71. Улика R49/R61 — verify23.py, который наклон не грепает, а ПЕРЕ-СЧИТЫВАЕТ из голосов (verify23.py:159-169) и только потом сверяет с текстом; прогнал: `[OK ] border: НАКЛОН +0.708 напечатан n=128`, рядом пере-считанные из сырья контрасты, ДИ, декой, пол, порог и деньги `[OK ] расход пака $2.907359 напечатан`, RC=0. То же у verify22.py (verify22.py:66-213 — числа из `material/bank/money/panel`, не из прозы). Это ровно «улика на дело», которую счётчик по своему же назначению (conformance.py:36-37) выделять не должен; предложенная починка «помечать по списку известных верификаторов» дала бы три ложных срабатывания и ЗАВЫСИЛА бы долю самопроверки, то есть навредила бы тому же читателю. Настоящая слепая зона мехинизма в реестре ровно одна, и автор её пропустил: R55 (requirements.md:90) — `grep -l \"баннер фазы Д\" docs/experiments/*.md`, чистый греп текста отчётов через глоб, именами файлов не совпадает и в 9 не попал. Итог по масштабу: 10 из 77 вместо напечатанного «9 из 89», а не «12 из 77». Ни один доллар и ни один вывод фазы от этого не двигается: строка «9 из 89» не напечатана нигде в docs/ или eval/ (грепал `из 89`/`89 требован` — ноль хитов в реестре и отчётах), решения на ней не стоят; двигается только исполнимость `--final` перед сдачей.",
|
||
"why": "Проверено исполнением, не по формулировке автора. (1) Знаменатель. Загрузил conformance.py как модуль и вызвал `rows()` на eval/dovodka/requirements.md: `total rows: 89`, из них 12 строк вида `| **РАМКА** | | |` (первая ячейка не R-ID), реальных R1..R77 = 77. Парсер их не отсеивает: conformance.py:80-85 пропускает только сепараторы и `ID`/`№`, у заголовка `len(cells)==3`, поэтому он идёт в out. Тезис автора о 12 лишних строках ВЕРЕН. (2) Не замеченное автором следствие: `m.check(\"\")` → `('ОЖИДАЕТ','улика не объявлена')`, а conformance.py:155-157 `if st == \"ОЖИДАЕТ\" and mode == \"--final\": st = \"ПРОВАЛ\"` и conformance.py:162 `bad += st == \"ПРОВАЛ\"` — 12 детерминированных провалов в сдаточном режиме, `--final` не проходим в принципе. (3) Числитель. Пере-снял списком: помечено ровно 9 улик — R44, R45, R46, R47, R48, R50, R51, R53, R64; все девять — буквальные `grep -q \"<фраза>\" docs/experiments/2[23]-*.md` либо строка с `requirements.md`. R49/R61/R71 действительно не помечены — но не потому, что счётчик что-то упустил по существу: `timeout 300 eval/.venv/bin/python eval/editor_tier/verify23.py` даёт RC=0 и печатает пере-счёт из сырья — `[OK ] border: НАКЛОН +0.708 напечатан n=128`, `[OK ] tier: величина декоя -3.94 напечатана`, `[OK ] ФC: расход $2.080125 напечатан`; наклон вычисляется в verify23.py:159-169 из `AJ._by_unit()`, а не читается из отчёта. verify22.py:61-213 устроен так же (`import material/bank/money/panel`, числа из json сырья). Класс «улика доказывает НАПЕЧАТАНО, а не СДЕЛАНО» (conformance.py:35-39) к ним не относится. (4) Реальный пропуск мехнизма — R55 (eval/dovodka/requirements.md:90), глоб `docs/experiments/*.md` под именами файлов не матчится, хотя грепает те же 22/23. (5) Цена вопроса: `grep -rn \"из 89|89 требован|77 требован\" docs/ eval/` — ни одного хита; число нигде не опубликовано, покупок ноль, выводы фазы на нём не стоят."
|
||
}
|
||
},
|
||
{
|
||
"title": "promptdiff печатает пар-вердикт «ПАР-ПРОМПТЫ КОНСИСТЕНТНЫ» по двум ролям из требуемых трёх: терминолога у пар нет вовсе",
|
||
"severity": "мелко",
|
||
"evidence": "Выхлоп promptdiff en-ru сравнивает editor.md и translator.md (translator-reflow помечен «боевого zh-аналога НЕТ»). `ls backend/prompts/zh-ru/` содержит terminologist.md, `ls eval/role_topology/prompts/en-ru/` и `ja-ru/` — только editor.md, translator.md (+reflow у en). requirements.md:51 R21 требует «en-банк: майнинг + терминолог по методике эксп-22». Шапка promptdiff.py:2: «Ненулевой код = пара не годна к покупкам».",
|
||
"consequence": "Зелёный код будет прочитан как «пара готова к покупкам ФД-B/ФД-C», хотя роль, которой строится банк (а банк-закон обязателен на всех армах, R22), в паре не заведена и гейтом не покрыта. Гейт не проверяет полноту НАБОРА ролей, только совпадение тех, что нашлись.",
|
||
"fix": "Перечислить обязательный набор ролей пары константой и ронять код при отсутствии любой из них, а не молча пропускать.",
|
||
"verdict": {
|
||
"refuted": true,
|
||
"why": "Проверял своими командами; факты автора о содержимом каталогов верны, но вывод построен на несуществующем требовании и на неверном прочтении гейта.\n\n1) «Требуемых трёх ролей» нет ни в одном документе. Заказ (docs/POLYGON_EXP2223_REDO_SESSION_PROMPT.md:60-66) требует «провенанс КАЖДОГО en-промпта» (т.е. тех, что есть) и отдельно «en-банк: майнинг + терминолог ПО МЕТОДИКЕ ЭКСП-22». `grep -rn \"терминолог\" docs/experiments/23-editor-tier.md docs/POLYGON_EXP2223_REDO_SESSION_PROMPT.md` даёт РОВНО одно попадание — строку 65 заказа; в пре-реге Д0 (719-896) терминолог не упомянут вовсе. Набор «editor+translator+terminologist для пары» автор изобрёл сам.\n\n2) «Методика эксп-22» терминолога ПАР-СПЕЦИФИЧНЫМ не делает — он единый и берётся из боевого zh-пути: eval/tenant_panel/bank.py:46 `TERMINOLOGIST = REPO/\"backend\"/\"prompts\"/\"zh-ru\"/\"terminologist.md\"`. То же во всех прочих ригах: eval/bank_autonomy/term_probe.py:18, eval/bank_arbitration/consilium_probe.py:44 — пар-копии терминолога нет НИГДЕ в репо, и это не пропуск фазы Д. Сам промпт параметризован языком: backend/prompts/zh-ru/terminologist.md — «Ты — терминолог издательского перевода с языка «{{source_lang}}» на язык «{{target_lang}}»», и в нём НЕТ пар-блока «Единицы и приёмы» и нет секции ДИСКУРС-ПЕРЕВЁРСТКА, т.е. зеркалить в паре нечего — а promptdiff именно зеркала и сверяет. Заведение en-копии терминолога было бы отступлением от «методики эксп-22», а не её исполнением.\n\n3) Роли, которые пар-риг реально рендерит на покупках, — ровно две, и обе гейтом покрыты: eval/tenant_panel/prompts.py:105 `load_template(PAIR_EN/\"translator.md\" if en else ...)` и :115 `load_template(PAIR_EN/\"editor.md\" if en else ...)`. Больше PAIR_EN нигде не читается.\n\n4) «Зелёный код прочтут как готовность пары к покупкам ФД-B/ФД-C» — неверно: гейт односторонний по собственной шапке (promptdiff.py:1 «Ненулевой код = пара не годна к покупкам» — про НЕнулевой), а готовность закрывается реестром. `eval/.venv/bin/python eval/conformance.py eval/dovodka/requirements.md --plan` печатает `[OK] R18` (это и есть всё, что доказывает promptdiff) и рядом `[ОЖИДАЕТ] R21 en-банк: майнинг + терминолог…`, `[ОЖИДАЕТ] R22 Банк-закон D39.104 на ВСЕХ армах` — обе улики «—», а по шапке requirements.md:20-23 в режиме `--final` «—» = провал. То есть ровно тот пробел, о котором пишет автор, уже отслеживается отдельным требованием и блокирует сдачу.\n\n5) Цена вопроса нулевая: en/ja не покупались вовсе (потрачено $0.871904 из потолка ФД-A на zh-армах A1/A3/A4/A6), ни один вывод фазы и ни один доллар от находки не меняется. Прогон `eval/.venv/bin/python eval/dovodka/promptdiff.py en-ru ja-ru` → все проверки OK, «ПАР-ПРОМПТЫ КОНСИСТЕНТНЫ», EXIT=0 — и это фактически ВЕРНО для тех двух ролей, которые будут куплены.\n\nЕдинственное, что уцелело от находки, — тривиальная механика обхода файлов (`for f in sorted(d.glob(\"*.md\"))`, promptdiff.py main()): полнота НАБОРА не проверяется. Воспроизвёл на копии скрипта с подменённым PAIRS и пустым каталогом `xx-ru` (/tmp/.../scratchpad/drive.py): вывод «ПАР-ПРОМПТЫ КОНСИСТЕНТНЫ», BAD=0. Но у обеих реальных пар оба нужных файла на месте (`ls eval/role_topology/prompts/en-ru/` → editor.md, translator-reflow.md, translator.md; `ja-ru/` → editor.md, translator.md), так что это гипотетика, а не дефект замера.",
|
||
"corrected": "Уцелевшая (несущественная) часть: promptdiff обходит пар-каталог глобом и потому проверяет только те файлы, что нашлись, — полнота набора не сторожится, и пустой пар-каталог даёт «ПАР-ПРОМПТЫ КОНСИСТЕНТНЫ» с кодом 0 (воспроизведено на подменённом PAIRS с пустым xx-ru). Обязательный набор — translator.md и editor.md (единственные пар-файлы, которые читает prompts.py:105/115); терминолога в этот набор включать НЕЛЬЗЯ: он по всему репо один, боевой zh-путь (bank.py:46), параметризован {{source_lang}}/{{target_lang}} и пар-специфичных секций не имеет. На en-ru и ja-ru оба обязательных файла присутствуют, покупок по этим осям не было, так что ни вывод фазы, ни доллар не затронуты."
|
||
}
|
||
},
|
||
{
|
||
"title": "Уточнение к Д-4: норма Д0.6 говорит про СУДЕЙСКУЮ пачку, поэтому покупка двух length-клеток нормой не запрещена — запрещён их допуск к судейству, и вот этого не сторожит ничто",
|
||
"severity": "важно",
|
||
"evidence": "Пре-рег 23-editor-tier.md, Д0.6: «**Клетка с `finish=length` в судейскую пачку НЕ допускается** — ни боевым армом, ни половиной пола.» Греп `finish` по eval/dovodka/*.py даёт только canon.py:162-168 (исключение клетки R0 из СВОЕЙ метрики) и комментарии power.py:31/94-95. Ни в contour.py, ни в money_d.py, ни где-либо ещё нет ни отказа, ни пометки, ни счётчика. Факт по сырью: A4 fixer length 2, stop 20.",
|
||
"consequence": "Формулировка «клетка с finish=length в пачку НЕ допускается» как нормы покупки неточна — купить их не нарушение. Нарушение произойдёт молча в момент судейства, потому что клетки ничем не помечены и отбирающего кода нет. При корректном исключении A4 остаётся n=20 → MDE 1.887 против цели 1.50, то есть арм описательный, а в отчёте будет фигурировать как купленный на 22.",
|
||
"fix": "Ввести в contour/бухгалтерию отказ или карантин по finish != 'stop' и печатать число исключённых клеток рядом с n каждого арма.",
|
||
"verdict": {
|
||
"refuted": false,
|
||
"why": "ПРОВЕРЕНО СВОИМИ КОМАНДАМИ, ядро находки подтверждается, но три её элемента неверны.\n\nЧТО ПОДТВЕРДИЛОСЬ.\n1) Норма действительно про ПАЧКУ, а не про покупку. docs/experiments/23-editor-tier.md, Д0.6 (sed -n '700,900p'): «**Клетка с `finish=length` в судейскую пачку НЕ допускается** — ни боевым армом, ни половиной пола». Покупка ею не запрещена — уточнение автора верно.\n2) Механизма отбора нет. `grep -rn \"finish\\|length\\|truncat\" eval/dovodka/contour.py eval/dovodka/money_d.py` → ПУСТОЙ вывод (0 строк). По всей зоне `grep -rn finish eval/dovodka/*.py` даёт только canon.py:162-168 и комментарии power.py:31,94-95. В eval/role_topology/agentjudge.py (единственный сборщик судейских пачек в репо) `grep -n \"finish\"` → ничего.\n3) Факт по сырью подтверждён точно: обход ~/books/dovodka/*.json даёт a1 stop 30 · a3 stop 64 · a4 length 2 + stop 20 · a6 stop 32. Обе length-клетки — dv-a-a4-41599f30df.json и dv-a-a4-f6da9f76b2.json, обе `deepseek-v4-pro/fixer`, completion 16000 при reasoning 15046 (бюджет выжрало размышление).\n\nЧТО НЕВЕРНО.\nа) «Клетки ничем не помечены» — фактически ложно. Каждая запись НЕСЁТ поле-ключ: dv-a-a4-41599f30df.json → `'finish': 'length', 'arm': 'A4', 'uid': '41599f30df', 'places': 7`. Пометка есть, отсутствует ВЫЗОВ фильтра. Формулировка «нечем отличить» подменяет «никто не смотрит».\nб) «Не сторожит ничто» описывает НЕНАПИСАННЫЙ этап, а не сломанный гейт: в eval/dovodka нет judge.py вовсе (ls зоны: canon, contour, material_ja, money_d, plan, power, promptdiff, runs), `runs.py --report` → «агент-сессий израсходовано 0 из 80». Сторожить пока нечему — это долг перед следующим шагом, а не дефект в купленном коде. Тяжесть «важно» завышена до момента написания сборщика пачки.\nв) Ни один вывод фазы и ни один доллар от этого не двигаются. A4/A0 пре-регом объявлен ВТОРИЧНЫМ и описательным ДО денег: power.py:88-91 — «A4/A0 — канон-фиксер ПОСЛЕ переписа: его несущая ось — покрытие канона, а оно детерминировано и шума не имеет», SECONDARY поправку Холма не несёт. Значит k=3 в расчёте автора к A4 неприменим. Пересчёт его же функцией (power.mde(2.12,n,k)): n=22 → 1.558 (k=1) / 1.799 (k=3); n=20 → 1.634 / 1.887. То есть A4 БЫЛ выше цели 1.50 уже на 22 клетках из-за денежного стопа; вычет двух length-клеток двигает 1.799→1.887 и классификации не меняет. Число 1.887 автор посчитал верно, но вывод «арм СТАНОВИТСЯ описательным» ложен — он таким объявлен пре-регом.\n\nЧТО АВТОР ПРОПУСТИЛ (и это дороже его собственной находки). Норма ломается не на A4, а на БАЗЕ ВСЕХ КОНТРАСТОВ. contour.py:86-89 `base_a0()` берёт `P22.edit_text(ANCHOR, uid)` при ANCHOR=\"deepseek-v4-flash\" (contour.py:69), то есть файл ~/books/tenant-panel/tp2-edit-E-deepseek-v4-flash-{uid}.json. Проход по всем 22 таким файлам: ровно один `finish=length` — `tp2-edit-E-deepseek-v4-flash-41599f30df`. Это ровно то, что эксп-22 §15 (docs/experiments/22-tenant-panel.md:1284-1288) называет «одна клетка стоит в БАЗЕ ВСЕХ КОНТРАСТОВ … каждый контраст обеих фаз сравнивался ПРОТИВ оборванного текста». Проверил и обратное: в ~/books/editor-tier все 16 R0 (deepseek-v4-pro) и 16 R2 (glm-5) — stop, так что случай единственный. Честное применение Д0.6 убирает единицу 41599f30df из A1/A0, A3/A0, A6/A0 — ПЕРВИЧНОГО семейства (power.py PRIMARY), n 32→31, MDE 1.491→1.515 при цели 1.50: пограничный переход несущей оси в описательную. Именно этого в находке нет.",
|
||
"corrected": "Норма Д0.6 запрещает не покупку, а ДОПУСК length-клетки в судейскую пачку, и сборщика пачки в фазе Д ещё не существует (нет eval/dovodka/judge.py; runs.py --report: 0 из 80 сессий) — поэтому это ДОЛГ ПЕРЕД СУДЕЙСТВОМ, а не действующая утечка. Клетки при этом ПОМЕЧЕНЫ самим сырьём (поле `finish` в каждой записи, dv-a-a4-41599f30df.json), не хватает только вызова фильтра и счётчика.\n\nМасштаб важнее, чем в находке, и лежит не там: кроме двух A4-клеток (41599f30df, f6da9f76b2), `finish=length` стоит у A0-БАЗЫ единицы 41599f30df — contour.py:86-89 base_a0() читает tp2-edit-E-deepseek-v4-flash-{uid}.json, и этот файл оборван (эксп-22 §15:1284-1288). Он общий знаменатель ВСЕХ контрастов оси Д4, включая первичное семейство A1/A0, A3/A0, A6/A0: при исключении n 32→31 и MDE 1.491→1.515 при цели 1.50 — ось из несущей становится пограничной. Проверено: остальные 21 flash-база и все 32 базы editor-tier (R0 pro, R2 glm-5) — stop.\n\nПо A4 вывод обратный заявленному: арм и так ВТОРИЧНЫЙ/описательный по пре-регу (power.py:88-91, его несущая ось — детерминированное покрытие канона), и уже на 22 клетках его MDE 1.558 (k=1) / 1.799 (k=3) выше цели 1.50 из-за денежного стопа; вычет двух клеток даёт 1.634/1.887 и ничего не переклассифицирует.\n\nПочинка: фильтр `finish != 'stop'` ставить в сборщик судейской пачки (когда он появится) НА ОБЕ стороны контраста — и на арм, и на базу A0, и на половины пола, — печатая рядом с n каждого арма число исключённых клеток и список затронутых uid; отдельно пере-снять MDE первичного семейства на n=31 и решить с владельцем, остаётся ли Д4 несущей."
|
||
}
|
||
},
|
||
{
|
||
"title": "has() в верификаторах — подстрочный поиск, поэтому проверка удовлетворяется чужим числом, а ложное число рядом с истинным невидимо",
|
||
"severity": "мелко",
|
||
"evidence": "verify23.py:47-52 `_norm` вырезает пробелы, `has` = `_norm(s) in _norm(text)`. Проверено: `has('перевес +0.508', '+0.50')` = True; `has('sd 2.129', '2.12')` = True; `has('наклон +0.708, а по-другому +9.99', '+0.708')` = True. В нормализованном 23-editor-tier.md подстрока «+0.19» встречается 6 раз, «+0.50» 5 раз, «+2.06» 4 раза.",
|
||
"consequence": "Двухзначные контрасты и пороги подтверждаются любым вхождением по всему документу, в том числе внутри более длинного числа и в чужом разделе. Ограничение «сторожит присутствие, а не истинность предложения» объявлено (verify23.py:7-10), но подстрочная коллизия и слепота к противоречащему числу рядом — сверх объявленного.",
|
||
"fix": "Искать число как отдельный токен (границы по не-цифре) и, для несущих чисел, требовать вхождение в объявленной секции, а не по всему файлу.",
|
||
"verdict": {
|
||
"refuted": false,
|
||
"corrected": "Механизм верен, но акценты смещены: главная дыра не «подстрока внутри числа», а ДОКУМЕНТНАЯ область поиска + склейка колонок при нормализации; при этом НИ ОДНА проверка сейчас не проходит ложно, ни один вывод фазы и ни один доллар не меняются — это латентная слабость гейта, не напечатанное неверное число. Точная формулировка: (1) `has` в eval/editor_tier/verify23.py:53-54 и идентичный eval/tenant_panel/verify22.py:53-54 — подстрочный поиск по всему файлу; `_norm` (verify23.py:47-50) вырезает ВСЕ пробелы, поэтому в код-блоках с колоночным выравниванием соседние ячейки склеиваются, и игла может совпасть ПОПЕРЁК двух чисел (проба: подстрока «0.042506» есть в нормализованном отчёте, хотя такого числа в отчёте нет — оно склеено из «0.04250» и «6.6%»); 12 из ~35 текущих игл (0.04250, 0.08041, 0.05481, 0.01792, 0.00769, 0.01725, 0.04408, 0.05276 и все 4 интервала ДИ) совпадают ТОЛЬКО внутри таких склеек. (2) Ложных прохождений сейчас нет: у каждой иглы есть настоящее одиночное вхождение в сыром тексте (проверено regex-ом с границами — список «без токенного вхождения» пуст). (3) Реально несущая часть — поиск по всему документу: мутационный тест показывает, что ложное число в СВОЁМ разделе гейт не видит. (4) Счётчики автора (6/5/4) точны, но это законные повторы ОДНОЙ величины; опаснее повтор одной строки для РАЗНЫХ величин (−0.62 = пол tier в §сводке и одновременно поправленный перевес R2 vs R0 в border-разделе; −1.00 = пол border и вердикт внешнего судьи). (5) Починка: искать число как отдельный токен по границам не-цифры И привязывать несущие иглы к своей секции — предложение автора верное.",
|
||
"why": "Проверял своими командами, ничего не покупал и не правил файлы проекта (мутации — копии в scratchpad).\n\n1) Код: verify23.py:47-54 — `_norm` = `re.sub(r\"\\s+\",\"\",x)` + унификация минуса; `has(text,s) = _norm(s) in _norm(text)`. Идентичная пара есть в eval/tenant_panel/verify22.py:53-54 (grep \"def has|_norm(s) in _norm\" по eval/), т.е. «в верификаторах» во множественном числе — верно.\n\n2) Гейт РЕАЛЬНО работает и сейчас зелёный: `eval/.venv/bin/python eval/editor_tier/verify23.py` → «ВСЕ ЧИСЛА ОТЧЁТА СХОДЯТСЯ», RC=0, ~35 проверок (цены редакторов, p50, книга по связке, контрасты, ДИ, декой, порог, пол, наклон, расходы).\n\n3) Числа автора воспроизвёл точно: в нормализованном docs/experiments/23-editor-tier.md «+0.19» — 6, «+0.50» — 5, «+2.06» — 4. Но контексты (напечатал все вхождения) показывают, что это законные повторы одной и той же величины (контраст T3/T2 в таблице, в строке пересчёта на порог и в сводке), а не «чужое число». Настоящий случай чужого числа — «−0.62» (строка 521 = пол tier; строка 306 и 645 = совсем другая величина в border-разделе) и «−1.00» (пол border и строка внешнего судьи).\n\n4) Подстрочная коллизия существует и хуже, чем «префикс»: `_norm` убирает разделители колонок в код-блоке (docs/experiments/23-editor-tier.md:488 «gpt-5.6-terra прошёл 4 0.04250 6.6%» → «…прошёл40.042506.6%»), поэтому проба показала `\"0.042506\" in _norm(text)` = True при том, что числа 0.042506 в отчёте нет. Анализ границ по всем иглам: 12 игл имеют 0 токенных вхождений в нормализованном тексте — они совпадают только внутри склеек.\n\n5) Но ложного прохождения сейчас НЕТ: regex-проверка по сырому тексту `(?<![\\d.])<число>(?!\\d)` для всех 29 скалярных игл дала пустой список «без одиночного вхождения», и каждый из 5 интервалов ДИ встречается ровно 1 раз. То есть все проверяемые числа в отчёте реально напечатаны — доллары и выводы фазы не двигаются, тяжесть «мелко» корректна.\n\n6) Мутационные тесты (копии отчёта в scratchpad, verify23 импортирован через importlib с подменённым `m.REPORT`):\n а) строка 260 (несущее предложение о наклоне border) «+0.708» → «+0.646» (ровно то ошибочное значение, которое фаза Д и исправляла): вывод «[OK ] border: НАКЛОН +0.708 напечатан», «ВСЕ ЧИСЛА ОТЧЁТА СХОДЯТСЯ», RC=0 — потому что «+0.708» уцелело в шапке (строка 15) и в эррате (строка 264).\n б) строка 521 (пол tier в собственной сводной таблице) «−0.62» → «−9.99»: «[OK ] tier: пол -0.62 напечатан», RC=0 — проверку удовлетворило «−0.62» из border-раздела, где это ДРУГАЯ величина.\n Это и есть «ложное число рядом с истинным невидимо» — подтверждено исполнением.\n\n7) Объявленность: докстринг verify23.py:7-10 объявляет «сторожит, что число ПРИСУТСТВУЕТ в тексте, а не что предложение вокруг числа истинно». Случай (6) формально касается границы объявленного, но случай (4) — совпадение строкой, которой в отчёте как числа НЕТ, — выходит за объявленное: там не выполняется даже гарантия присутствия. Так что находка не сводится к уже объявленному ограничению."
|
||
}
|
||
},
|
||
{
|
||
"title": "Журнал агент-сессий пуст (0 из 80) — кап сторожит только те сессии, которые сами через него позвали",
|
||
"severity": "мелко",
|
||
"evidence": "`runs.py --report` → «агент-сессий израсходовано 0 из 80»; файла ~/books/dovodka/agent-runs.json нет (в каталоге, кроме dv-*.json, лежит только canon-dissect.json). При этом contour.py:60 ссылается на находку «многоагентным разбирательством 10.08», money_d.py:11 и plan.py:94 — на «приёмку другого модельного семейства».",
|
||
"consequence": "Это тот же класс, из-за которого написан сам модуль (runs.py:4-7: в паке 23 на диске осталось 20 записей против 58 фактических сессий). Судейские сессии Д4 ещё не гонялись, поэтому ноль может быть законным — но проверить это нечем: механизма, который отличает «сессий не было» от «claim не позвали», нет, и селфтест такой вопрос не задаёт.",
|
||
"fix": "Объявить в отчёте, какие классы сессий кап считает, а какие нет; при закрытии фазы сверить число записей с фактическим числом суб-агентов вручную и записать расхождение.",
|
||
"verdict": {
|
||
"refuted": true,
|
||
"why": "Факт «0 из 80» верен, но всё остальное в находке — неверно, и ноль здесь проверяем в одну команду, а не «нечем».\n\n1) НОЛЬ ЗАКОННЫЙ И ДОКАЗУЕМЫЙ. Кап сторожит СУДЕЙСКИЕ сессии — это записано в пре-реге Д0: `docs/experiments/23-editor-tier.md:823` «**Судейские сессии регистрируются ДО запуска** (`eval/dovodka/runs.py`, кап 80…)»; тот же контракт у предка: `eval/tenant_panel/judge.py:18` «одна судейская сессия = одна запись». Судейского сырья на диске НЕТ ни одной единицы. Проверил инвентарём всех 148 клеток:\n`ls ~/books/dovodka/ | grep '^dv-' | sed -E 's/-[0-9a-f]{10}\\.json//' | sort | uniq -c` → `30 dv-a-a1 · 32 dv-a-a3 · 32 dv-a-a3-crit · 22 dv-a-a4 · 16 dv-f-a6 · 16 dv-f-a6-crit`; разбор ролей внутри файлов даёт ровно `['critic','fixer']`, и `grep -l '\"judge\"' ~/books/dovodka/dv-*.json | wc -l` → `0`. Ноль записей при нуле судейских артефактов — это согласованность, а не слепота.\n\n2) «МЕХАНИЗМА, ОТЛИЧАЮЩЕГО „СЕССИЙ НЕ БЫЛО“ ОТ „CLAIM НЕ ПОЗВАЛИ“, НЕТ» — ЛОЖНО, И ОН ОБЪЯВЛЕН. Механизм — метка `?`: `runs.py:8` «не позвал `claim` — не получил имени, и разбор проставит `?`», реализация `runs.py:166` `return started[-1][\"judge\"] if started else \"?\"`. Проверил исполнением, ничего не записывая на диск:\n`python -c \"import runs,time; print(runs.LEDGER.exists(), runs.used(), runs.judge_of('ФД-A','tok',time.time()))\"` → `False [] '?'`. Ровно этой меткой и был диагностирован пак 23: `docs/experiments/23-editor-tier.md:279` «`agent-runs.json` не создавался, во всех голосах стоял `judge='?'`». То есть неучтённая судейская сессия не «невидима» — она даёт `?` в каждом своём голосе.\n\n3) «СЕЛФТЕСТ ТАКОГО ВОПРОСА НЕ ЗАДАЁТ» — ЛОЖНО: `runs.py:249-251` проверяют ровно его — «ответ РАНЬШЕ первой регистрации не отдаётся никому», «чужой прогон не атрибутируется», «незарегистрированный токен даёт `?`».\n\n4) УЛИКА ФАКТИЧЕСКИ НЕВЕРНА в двух местах. (а) «в каталоге, кроме dv-*.json, лежит только canon-dissect.json»: `ls ~/books/dovodka/ | grep -v '^dv-'` в момент проверки дал `canon-dissect.json`, `razbiratelstvo-sudi-10-08.txt`, `revizia-fazy-D-11-08.json` (а десятью минутами раньше там же лежали `SELFTEST-agent-runs.json` и `.lock`). (б) Отсутствие `agent-runs.json` — не симптом, а объявленный нормальный старт: `runs.py:59` `used()` возвращает `[]`, если файла нет; файл рождается первым `claim`.\n\n5) ССЫЛКИ НА ЧУЖИЕ СЕССИИ — ПОДМЕНА КЛАССА. `contour.py:60` («многоагентное разбирательство 10.08») и `money_d.py:11` / `plan.py:94` («приёмка другого модельного семейства») — это РЕВЬЮ кода фазы, а не судейские суб-агенты, которых считает кап (см. п.1). Их отсутствие в журнале — соблюдение объявленной границы, а не пропуск сторожа.\n\n6) ЦЕНА ВОПРОСА НУЛЕВАЯ. Ни один вывод фазы и ни один доллар не двигаются: судейств не было, потрачено $0.871904 на critic/fixer, и предложенная починка («объявить, какие классы кап считает») уже исполнена пре-регом на строке 823.\n\nЕдинственное зерно рядом — но это НЕ то, что утверждает автор, и не дефект: `judge_of` в фазе Д пока не имеет вызывающего (`grep -rn judge_of eval/dovodka/` даёт хиты только внутри `runs.py`; судейского модуля в `eval/dovodka/` нет — там `canon, contour, material_ja, money_d, plan, power, promptdiff, runs`). Штамп `?` встанет тогда, когда появится разбор судейских ответов Д4; сейчас его отсутствие — «ещё не построено», а не «сторож дырявый»."
|
||
}
|
||
},
|
||
{
|
||
"title": "Улика R3 в замороженном реестре сверяет потолок $4.00, тогда как санкция владельца поднята до $4.50 — вечный провал в неисправимой строке",
|
||
"severity": "мелко",
|
||
"evidence": "requirements.md:30 R3 улика = `$ grep -q \"САНКЦИЯ ВЛАДЕЛЬЦА .4.00\" eval/dovodka/plan.py`; исполнено — RC=1. plan.py:10 содержит «Потолок фазы — САНКЦИЯ ВЛАДЕЛЬЦА $4.50 (10.08)», money_d.py:10 — то же. Реестр отслежен git и совпадает с HEAD (`git diff --quiet HEAD` = 0, коммит da5f4d0), то есть фриз взят и правка потребует нового коммита.",
|
||
"consequence": "Три провала в --plan (R3, R55, R71) — все три по причинам, не связанным с исполнением требований. Красный шум в гейте обесценивает его сигнал: при сдаче красные придётся сортировать глазами, а именно от этого conformance и написан.",
|
||
"fix": "Пере-заморозить реестр отдельным коммитом с исправленными уликами R3 и R55 и с пометкой причины правки, чтобы фриз оставался проверяемым.",
|
||
"verdict": {
|
||
"corrected": "R3 в замороженном реестре РОДИЛСЯ красным, а не «протух»: улика `grep -q \"САНКЦИЯ ВЛАДЕЛЬЦА .4.00\" eval/dovodka/plan.py` не проходила НИ РАЗУ — в том же коммите фриза da5f4d0 plan.py уже нёс «$4.50». Существо требования (потолок сверен словом владельца) исполнено; сломана только буква улики. Строка исправима обычным коммитом (`frozen()` требует лишь tracked+clean к HEAD, conformance.py:58-62) — «неисправимой» она не является. Класс «красный шум от битой улики» покрывает ДВА провала из трёх, а не три: R3 (устаревший литерал) и R55 (экранированный `\\|` в ячейке таблицы уходит в shell as-is, conformance.py:103 — `/bin/sh: Syntax error`, при том что существо держится: `grep -l \"баннер фазы Д\" docs/experiments/*.md | wc -l` = 7 при пороге ≥7). R71 — НЕ шум: `eval/tenant_panel/verify22.py` падает содержательной проверкой «[ПРОВАЛ] верхняя граница двойной оплаты $0.000000 напечатана», это неисполненное требование чужого пака, и глушить его вместе с двумя косметическими нельзя.",
|
||
"refuted": false,
|
||
"why": "Ядро находки подтверждено исполнением, но её обоснование и масштаб неточны в трёх местах.\n\nПОДТВЕРЖДЕНО. `grep -q \"САНКЦИЯ ВЛАДЕЛЬЦА .4.00\" eval/dovodka/plan.py; echo RC=$?` → RC=1. eval/dovodka/requirements.md:30 держит именно эту улику. eval/dovodka/plan.py:10 и :28 — «САНКЦИЯ ВЛАДЕЛЬЦА $4.50 (10.08)» / `PACK_CEILING = 4.50`; money_d.py:10 — то же. Реестр отслежен и чист: `git diff --quiet HEAD -- eval/dovodka/requirements.md` → rc=0, последний коммит файла da5f4d0. `eval/.venv/bin/python eval/conformance.py eval/dovodka/requirements.md --plan` → «требований 89 · ожидают 58 · провалов 3», в списке R3, R55, R71. Ни в пре-реге Д0 (`sed -n '719,900p' docs/experiments/23-editor-tier.md | grep -n \"conformance\\|реестр\\|R3\\|улик\\|провал\"` — только одна строка про мощность), ни в docs/PROGRESS.md, ни в самом реестре эти три красных как объявленное ограничение не описаны. Значит это находка, а не известное ограничение.\n\nНЕТОЧНОСТЬ 1 — хронология. Заголовок «санкция поднята до $4.50» подразумевает дрейф ПОСЛЕ фриза. Проверено: `git log --oneline -- eval/dovodka/plan.py` → единственный коммит da5f4d0; `git show da5f4d0:eval/dovodka/plan.py | grep -n \"САНКЦИЯ\\|PACK_CEILING\"` → строка 10 «$4.50», строка 28 `PACK_CEILING = 4.50`; `git show da5f4d0:eval/dovodka/requirements.md` строка 30 → улика «$4.00». Улика и код разошлись В МОМЕНТ фриза, R3 не был зелёным никогда.\n\nНЕТОЧНОСТЬ 2 — «неисправимая строка». eval/conformance.py:58-62 (`git ls-files --error-unmatch` + `git diff --quiet HEAD`) проверяет только «отслежен и совпадает с HEAD»; новый коммит с исправленной уликой фриз не ломает — что и предлагает сам автор в починке, противореча собственному заголовку.\n\nНЕТОЧНОСТЬ 3 — масштаб последствия, самая существенная. Клейм «все три по причинам, не связанным с исполнением требований» опровергнут: `eval/.venv/bin/python eval/tenant_panel/verify22.py | grep -v \"^\\[OK\"` печатает «[ПРОВАЛ] верхняя граница двойной оплаты $0.000000 напечатана — граница = расход Ф2 ДО атомарного замка, в худшем случае оплаченный дважды» и «РАСХОЖДЕНИЙ: 1». Это содержательный красный, а не битая улика. Битых улик ровно две: R3 и R55 (для R55 проверено, что существо держится — `grep -l \"баннер фазы Д\" docs/experiments/*.md` даёт 7 файлов при пороге ≥7, а падает shell на неснятом экранировании `\\|`: conformance.py:103 гонит строку ячейки в `shell=True` без де-экранирования).\n\nЦЕНА ВОПРОСА. Ни один вывод фазы и ни один потраченный доллар не меняются: potолок в исполняемом коде равен санкции владельца $4.50, касса им и живёт. Тяжесть «мелко» проставлена верно."
|
||
}
|
||
},
|
||
{
|
||
"title": "Оплаченный арм A1 побайтно почти равен черновику: медиана 2 изменённых символа из ~7500 — контраст A1/A0 выродился в «черновик против боевого редактора»",
|
||
"severity": "критично",
|
||
"evidence": "difflib по 30 клеткам ~/books/dovodka/dv-a-a1-*.json против их базы (contour.base_draft): изменённых символов медиана 2, среднее 10.2, максимум 71 при базе ~7500 знаков; клеток с ≤5 изменённых символов 18 из 30; побайтно равны черновику 4 клетки ($0.0303). Для сравнения тем же кодом: A3 меняет 3.4% текста, A6 4.0%, A0 (боевой перепис) 21.4%. Причина воспроизведена исполнением: contour.flags_of на первой единице выдаёт 6 флагов, ВСЕ вида «КАНОН: термин «Цинь Фэн» (в исходнике 秦风 встречается 20 раз) передан не канонной формой либо пропущен» — тот самый класс ложных срабатываний покрытия, который сам пак снял находкой D-5; батарея при этом падает (`battery.run_unit(dict(...))` → AttributeError 'dict' object has no attribute 'final', contour.py:118).",
|
||
"consequence": "$0.226944 куплено за арм, который фиксер оставил без правок: фиксеру запрещено трогать что-либо кроме мест (contour.py:131), а места — артефакты метрики покрытия, чинить в них нечего. Первичный контраст A1/A0 (H-2а, один из трёх в PRIMARY power.py:79) измерит уже известную величину «черновик vs боевой редактор» (+2.06…+4.44 в паках 22/23), то есть DENY H-2а предопределён конструкцией арма, а не свойством флаговых контуров. Плюс арм побайтно совпадает с базой ВСЕХ остальных армов — ровно класс дефекта «floorA ≡ T1», за который пак 23 получил возражение. Норма Д0.6 «всякий классификатор, чьё число идёт в отчёт, печатает свою частоту срабатывания на случайном входе» к генератору флагов A1 не применена — а он тратит деньги.",
|
||
"fix": "Не судить A1 в нынешнем виде и не заносить его в первичное семейство. Перед доборами: (1) починить арность battery.run_unit, чтобы флаговый контур получил объявленную батарею; (2) заменить канон-флаг метрикой единообразия из canon.py (подмена родового слова при неизменном якоре), которая, по D-5, даёт решаемые однозначно места; (3) прогнать «декой для детектора» — частоту срабатывания флагов на случайном входе — и напечатать её рядом; (4) объявить владельцу, что $0.2269 куплены впустую, и пере-покупка A1 стоит ещё столько же.",
|
||
"verdict": {
|
||
"refuted": false,
|
||
"why": "ПРОВЕРЕНО СВОИМИ ПРОГОНАМИ (eval/.venv/bin/python, скрипты в scratchpad/chk14*.py).\n\nЧТО ПОДТВЕРДИЛОСЬ.\n1) `battery.run_unit` действительно падает: мой прогон `B.run_unit(dict(uid=..., source=..., text=draft))` → `AttributeError: 'dict' object has no attribute 'final'`; вызов на eval/dovodka/contour.py:118 обёрнут `except Exception: pass` (contour.py:121-122). Масштаб БОЛЬШЕ заявленного автором: я прогнал `flags_of` по ВСЕМ 32 единицам — 74 флага, `Counter` по префиксам даёт `{'КАНОН': 74}`, батарея не дала НИ ОДНОГО флага ни на одной единице. Объявленный в докстринге (contour.py:26) и в пре-реге Д0.5 (docs/experiments/23-editor-tier.md:797) арм «батарея + канон-гейт» куплен как «канон-гейт». Селф-тест это не ловит: `ck(\"канон-гейт выдаёт места\", isinstance(fl, list), ...)` (contour.py:226) истинен и для пустого списка.\n2) Норма Д0.6 (23-editor-tier.md:838-841, «всякий классификатор, чьё число идёт в отчёт, обязан печатать рядом свою частоту срабатывания на случайном входе») к `flags_of`/`canon_gaps` не применена: `grep -rn \"случайн|decoy|декой|ложнополож\" eval/dovodka/contour.py eval/dovodka/canon.py` — пусто.\n3) 6 флагов на первой единице (d1e353d569), все «КАНОН» — совпало дословно.\n4) Побайтно равны черновику 4 клетки на $0.030325 — совпало (мой подсчёт по `cost_usd` из сырья).\n\nЧТО ОПРОВЕРГНУТО — ЦИФРЫ И ВЫВОД ПРО ДЕНЬГИ.\n5) «Медиана 2 изменённых символа, среднее 10.2, максимум 71, ≤5 символов у 18 из 30» — артефакт МЕТРИКИ автора, а не свойство арма. Я воспроизвёл его числа ровно (chk14b.py: `left median=2.5 mean=10.2 max=71.0 le5=18`) — они получаются, только если по opcodes difflib считать ТОЛЬКО удалённые символы базы (`i2-i1`), игнорируя вставки. А фиксер по конструкции арма работает почти исключительно ВСТАВКАМИ (возврат пропущенной канонной формы), т.е. метрика зануляет ровно то, что арм делает. Симметричный счёт `max(i2-i1, j2-j1)`: A1 медиана 20 символов, среднее 39.4, максимум 318, ≤5 символов у 6 из 30, побайтно равны 4. Сравнительные проценты автора тоже занижены вдвое той же метрикой: у меня A1 0.86%, A3 6.34%, A6 5.74%, A0 42.73% (у автора 3.4/4.0/21.4).\n6) «Фиксер оставил арм без правок», «места — артефакты покрытия, чинить в них нечего», «$0.2269 куплены впустую» — НЕВЕРНО. Из 74 флагов 16 — ЖЁСТКИЕ пропуски (канонная форма отсутствует в выходе полностью), 58 — недобор счёта. Фиксер восстановил 16 из 16 жёстких (chk14e.py). Суммарные канон-дыры по 30 куплённым клеткам упали 74 → 41 (chk14d.py). Правки есть в 26 клетках из 30. На первой единице видно предметно: 公子 draft_out=0 → a1_out=4, 苏家 0 → 1, 筑基 1 → 2, при этом счётный артефакт 秦风 20/19 фиксер корректно НЕ трогал.\n7) «Класс дефекта floorA ≡ T1» — не тот класс. Норма Д0.6 (23-editor-tier.md:825-827) запрещает брать БОЕВУЮ клетку половиной ШУМОВОГО ПОЛА. A1 — боевой арм, а не половина пола; черновик в ARMS (contour.py:44) не судится. Близость A1 к черновику — не нарушение этой нормы.\n8) «DENY H-2а предопределён» — H-2а по пре-регу Д0.4 (23-editor-tier.md:778-792) вообще не superiority-тест, а non-inferiority с ТРЕМЯ объявленными исходами, включая «НЕ УСТАНОВЛЕНО»; Д0.9 прогноз 3 (23-editor-tier.md:884-886) прямо предсказывает «A1 не хуже, но дешевле в разы» со ссылкой на флаговый контур эксп-20. Малый объём правок у точечного фиксера — ОЖИДАЕМОЕ поведение арма по пре-регу, а не признак его вырождения.\n\nЧТО РЕАЛЬНО МЕНЯЕТСЯ. Ни один потраченный доллар не признаётся выброшенным. Меняется интерпретация одного контраста: A1/A0 измерит «канон-гейт как единственный источник флагов», а не объявленный «батарея + канон-гейт», и это надо либо починить до судейства (арность `run_unit`), либо переименовать арм в отчёте. Тяжесть — не «критично», а major.",
|
||
"corrected": "Арм A1 куплен в УРЕЗАННОМ против объявленного виде: `battery.run_unit` падает на всех 32 единицах (`AttributeError: 'dict' object has no attribute 'final'`, вызов contour.py:118, глушится `except Exception: pass` на :121), поэтому все 74 флага фазы — только канон-гейт, батарея не дала ни одного. Из 74 флагов 58 — счётные артефакты покрытия (канонная форма в выходе есть, но реже, чем термин в исходнике: 秦风 20 против 19 — норма для русского с местоимениями), 16 — жёсткие пропуски, и их фиксер закрыл 16 из 16; канон-дыры по 30 клеткам упали 74 → 41, правки есть в 26 клетках из 30. Норма Д0.6 (23-editor-tier.md:838-841) о частоте срабатывания классификатора на случайном входе к `flags_of` не применена. Правки A1 малы (медиана 20 изменённых символов при базе ~7500, 0.86% текста против 6.34% у A3 и 42.7% у A0; побайтно равны черновику 4 клетки на $0.030325), но это ожидаемое поведение точечного фиксера по пре-регу Д0.9 прогноз 3, а не вырождение контраста. Перед судейством: починить арность `run_unit` (иначе арм в отчёте надо назвать «канон-гейт», а не «батарея + канон-гейт»), заменить счётное правило `canon_gaps` на «канонная форма отсутствует вовсе» плюс метрику единообразия из canon.py, и напечатать частоту срабатывания генератора флагов на случайном входе. Пере-покупка A1 при этом НЕ обязательна и $0.2269 не выброшены: на жёстком подмножестве флагов арм отработал."
|
||
}
|
||
},
|
||
{
|
||
"title": "Зафризенный пре-рег Д0.3/Д0.5 напечатан ДО починки D-1 и противоречит коду: в отчёте k=5 и MDE 1.29, в power.py k=3 и MDE 1.49; под объявленным в отчёте семейством из пяти несущая ось Д4 — ОПИСАТЕЛЬНАЯ",
|
||
"severity": "критично",
|
||
"evidence": "docs/experiments/23-editor-tier.md:733-737 печатает «Д4 32 5 2.12 1.29 1.50 0.0000 НЕСУЩАЯ · Д3 16 5 2.12 1.83 2.00 0.0002 · Д6 9 3 2.90 3.33 · Д1 16 1 2.12 1.83»; строки 805 и 810 — «Холм по пяти» для Д4 и Д3. Фактическая печать `eval/.venv/bin/python eval/dovodka/power.py`: «Д4 32 3 2.12 1.49 · Д3 16 1 2.12 1.83 потолок p 0.0000 · Д6 9 3 2.90 3.85». Числа отчёта воспроизводятся ТОЛЬКО старой константой 2.8: 2.8*2.12/√32*1.23 = 1.29 (проверено). Через сам power.mde: k=1 → 1.291, k=3 → 1.491, k=5 → 1.575 при цели 1.50; Д3 при k=5 → 2.23 при цели 2.00. `git show da5f4d0:eval/dovodka/power.py` — уже k=3/k=1, то есть отчёт и код разъехались в ОДНОМ фриз-коммите; правок docs/experiments/23-editor-tier.md после da5f4d0 нет (git log по файлу).",
|
||
"consequence": "Пре-рег — это и есть контракт «что объявлено до денег», и в нём стоит семейство из пяти и MDE, посчитанный ошибочной константой. По букве пре-рега Д4 (носитель ставки владельца H-2б) и Д3 недомощны по построению — тот самый провал en-оси эксп-22, ради которого писан power.py. Несущий статус обеих осей держится на сужении семейства 5→3, которого в замороженном документе нет; после результатов это неотличимо от подгонки, и вердикт CONFIRM/DENY по H-2а/H-2б/H-1 оспорим целиком. $1.1397 уже потрачены на ось с неопределённым статусом.",
|
||
"fix": "Пере-печатать Д0.3 выводом сегодняшнего power.py и привести Д0.5 к PRIMARY/SECONDARY кода (Холм по трём на Д4, по одному на Д3), явно пометив, что состав семейства зафиксирован коммитом da5f4d0 ДО первой покупки, а таблица в отчёте была стенограммой предыдущей редакции. Если владелец сочтёт сужение до трёх поздним — Д4 при k=5 объявляется описательной, и это надо сказать ДО судейства.",
|
||
"verdict": {
|
||
"refuted": false,
|
||
"why": "Проверил своими командами — фактическая часть находки воспроизводится полностью, попытка опровергнуть провалилась.\n\n1) Текст отчёта. `grep -n \"Д4 edit-контур zh\\|Д0.3 Мощность\" docs/experiments/23-editor-tier.md` → `756:### Д0.3 Мощность каждой оси — ДО покупок (eval/dovodka/power.py)` и `760:Д4 edit-контур zh 32 5 2.12 1.29 1.50 0.0000 НЕСУЩАЯ`. Таблица объявлена выводом power.py. Строки 805/810 (проверил `sed -n '803,812p'`): «семейство: A1/A0 · A2/A0 · A3/A0 · A4/A0 · A6/A0 Холм по пяти» и «…контроль E0 vs D0. Холм по пяти.» — цитаты автора точны. Единственная неточность улики: таблица лежит на 756-763, а не на 733-737 (733-737 — это тело H-2б/H-3 в Д0.1).\n\n2) Код. `eval/.venv/bin/python eval/dovodka/power.py` печатает `Д4 edit-контур zh 32 3 2.12 1.49 1.50 0.0000 НЕСУЩАЯ`, `Д3 en→ru несущая 16 1 2.12 1.83 2.00 0.0000`, `Д6 9 3 2.90 3.85`, и «Д4 — ПЕРВИЧНОЕ (Холм по 3)», «Д3 — ПЕРВИЧНОЕ (Холм по 1)». Расхождение с отчётом по k, MDE и потолку p — реальное.\n\n3) Происхождение чисел отчёта. `mde()` из самого модуля: k=1 → 1.291, k=3 → 1.491, k=5 → 1.575 (цель 1.50); Д3: k=1 → 1.826, k=5 → 2.228 (цель 2.00). Старая константа: 2.8·2.12/√32·1.23 = 1.291, 2.8·2.12/√16·1.23 = 1.825, 2.8·2.90/√9·1.23 = 3.329 — ровно колонка MDE отчёта. Причём колонка «потолок p» отчёта посчитана уже по k из отчёта: `min_p(16,5)` = 0.000153 → «0.0002» (код при k=1 печатает 0.0000), `min_p(9,3)` = 0.0117. То есть таблица .md — не гибрид, а целиком вывод ПРЕДЫДУЩЕЙ редакции power.py (k=5/5/3/1 + множитель 2.8), что усиливает, а не ослабляет находку.\n\n4) Хронология. `git log --oneline -- docs/experiments/23-editor-tier.md` и `-- eval/dovodka/power.py` дают по одному коммиту — da5f4d0, оба файла в нём (`git show da5f4d0 --stat`). `git show da5f4d0:eval/dovodka/power.py | grep -n` → уже `(\"Д4 edit-контур zh\", 32, 3, …)`, `(\"Д3 en→ru несущая\", 16, 1, …)`, PRIMARY/SECONDARY на месте; `git diff da5f4d0 HEAD -- eval/dovodka/power.py` пуст. `git status --porcelain docs/experiments/ eval/dovodka/` → тронут только material_ja.py. Значит отчёт и код разъехались внутри одного фриз-коммита и с тех пор не правились.\n\n5) Эрраты нет: `grep -rn \"Холм по\\|ПЕРВИЧН\\|1\\.49\\|1\\.57\\|k=5\"` по 23-editor-tier.md, POLYGON_EXP2223_REDO_SESSION_PROMPT.md, PROGRESS.md, requirements.md — ни одного упоминания сужения семейства вне power.py; промт и requirements говорят лишь «Холм по объявленному семейству», не называя, какой артефакт объявляет.\n\n6) Влияние на деньги: `grep -rn \"power\" eval/dovodka/*.py eval/editor_tier/*.py` — power.py ни одним скриптом не потребляется, смета идёт из plan.py. Ни один потраченный доллар от расхождения не зависит; зависит формулировка вердикта по H-2а/H-2б/H-3.",
|
||
"corrected": "Внутри одного фриз-коммита da5f4d0 два артефакта пре-рега противоречат друг другу по составу семейства Холма, и до сих пор не согласованы. Таблица Д0.3 в docs/experiments/23-editor-tier.md:756-763 объявлена выводом eval/dovodka/power.py, но является выводом ПРЕДЫДУЩЕЙ, незакоммиченной редакции этого файла: и MDE (множитель 2.8 при любом k), и потолок p (min_p(16,5)=0.0002, min_p(9,3)=0.0117) сходятся только при k=5/5/3/1. Сегодняшний power.py печатает Д4 k=3 MDE 1.49 и Д3 k=1 MDE 1.83, а PRIMARY/SECONDARY даёт «Холм по 3» на Д4 и «по 1» на Д3; Д0.5 (строки 805, 810) при этом дважды говорит «Холм по пяти».\n\nМасштаб точнее, чем в исходной формулировке, в трёх местах. (а) Ссылка на строки 733-737 неверна — таблица на 756-763. (б) Сужение семейства 5→3 НЕ отсутствует в замороженном материале и НЕ является поздним: оно записано в power.py того же коммита da5f4d0 от 10.08 07:06, то есть до первой покупки, и с тех пор байт в байт не менялось. Поэтому «после результатов неотличимо от подгонки» — риторическое преувеличение: временнáя метка сужения доказуема git-ом; дефект в том, что пре-рег внутренне противоречив и не назван управляющий артефакт, а не в том, что семейство подкручено задним числом. (в) Запас, на котором держится статус, узкий, но конечный: по букве .md (k=5) Д4 даёт MDE 1.575 против цели 1.50 — превышение на 5%, а первичный контраст Д3 E0/D0 при k=5 даёт 2.23 против 2.00 (+11%); обе оси по букве .md описательные, но с малым перебором, а не «недомощны в разы».\n\nНи один потраченный доллар от этого не меняется: power.py ничем не потребляется, смета идёт из plan.py, $1.1397 куплены независимо. Меняется одно, и это существенно: какой из двух зафризенных артефактов управляет статусом Д4 (носитель H-2б) и Д3, а значит — можно ли объявлять по ним несущий CONFIRM/DENY. Вопрос обязан быть закрыт владельцем ДО первого судейства (судейств пока ноль), решением-эрратой: либо .md пере-печатывается выводом сегодняшнего power.py с явной пометкой, что состав семейства зафиксирован коммитом da5f4d0 до покупок, либо при чтении по .md обе оси объявляются описательными — тоже до судейства. Тяжесть — высокая (блокирует формулировку вердикта), «критично» справедливо только при трактовке .md как единственного управляющего пре-рега."
|
||
}
|
||
},
|
||
{
|
||
"title": "Цена фиксера в смете занижена в 2.41×: по замеренным ценам фаза не доводится до конца ни на одном потолке — ФД-A $1.24 при потолке $0.885, пак ~$4.99 при $4.50",
|
||
"severity": "критично",
|
||
"evidence": "plan.py:63 `fixer = 0.60 * edit` = $0.00314; медиана 100 купленных фиксерных клеток ~/books/dovodka = $0.00756 (×2.41). Касса сейчас: ФД-A $0.871904/0.885 (остаток $0.013), ФД-F $0.267825/0.283 (остаток $0.015) — `eval/.venv/bin/python eval/dovodka/money_d.py`. Не куплено: A2 32 клетки, A4 10 клеток, свой пол 16, второй контур A6 16. Пере-счёт по замеренным медианам: ФД-A 0.872+0.364=$1.24; ФД-F 0.268+0.121=$0.389; ФД-B $0.61 против плановых 0.556; пак $4.99, перебор $0.49 при объявленном резерве $0.03. Отдельно: A1 на тех же 30 единицах стоил $0.2269 против $0.2447 у A0, то есть 0.93× — при прогнозе Д0.9 п.3 «дешевле в разы» с основанием «$0.0002 в эксп-20» (расхождение 34×); на 16 из 30 единиц фиксер ДОРОЖЕ переписа.",
|
||
"consequence": "Экономическая половина H-2а («флаговый контур дешевле») уже опровергнута купленным сырьём: точечный фиксер получает на вход исходник + черновик + список мест и выдаёт ПОЛНЫЙ текст, поэтому дешевле переписа он не бывает. И это же занижение — корень того, что фаза упирается в потолки: доборы Д4 и второй контур A6 не влезают, а пакетный потолок $4.50 при полном плане (с Д1 gemini $2.35) недостижим примерно на $0.5. Дальнейшие прогоны будут наступать на гард на каждой второй клетке.",
|
||
"fix": "Пере-снять plan.py на замеренных ценах фиксера/критика, напечатать новую смету и вынести владельцу ОДИН вопрос с числом: что режется или на сколько поднимается потолок. Прогноз Д0.9 п.3 в отчёте пометить как опровергнутый сырьём до судейства — это результат, а не бухгалтерия.",
|
||
"verdict": {
|
||
"refuted": false,
|
||
"why": "Пере-проверил своими прогонами, ядро находки подтверждается числом в число.\n\n1) Цена фиксера. `eval/dovodka/plan.py:53` `fixer = 0.60 * edit`; `plan.py` печатает `фиксер $0.00314`. Своя медиана по 100 купленным фиксерным клеткам (`~/books/dovodka/dv-*.json`, `role==\"fixer\"`): **$0.007561** (mean $0.008192) ⇒ ровно **×2.41**. По армам: a1 0.006865 (n=30), a3 0.007411 (32), a4 0.007937 (22), a6 0.008875 (16).\n\n2) ФД-A уже не доводится. `eval/dovodka/money_d.py` → ФД-A 0.871904 при потолке 0.885 (`money_d.py:67`), остаток $0.0131. Не куплено: A2 32 клетки, A4 10, свой пол 16. Мой пере-счёт остатка по замеренным медианам: 32·0.00523 + 10·0.007561 + 16·0.007561 = **$0.364** ⇒ ФД-A $1.236 против потолка $0.885. Даже по СОБСТВЕННЫМ ценам plan.py остаток стоит $0.249 — в остаток $0.013 не влезает ни при какой цене фиксера. Разложение перерасхода: A1 30 кл план $0.094 / факт $0.227; A4 22 кл план $0.069 / факт $0.194; A3 32 кл план $0.459 / факт $0.4515. То есть весь пробой ФД-A — именно фиксерные армы.\n\n3) Пакет. Пере-счёт всей сметы по замеренным медианам (мой скрипт, те же формулы plan.py): A 1.199 · B 0.610 · C 0.154 · D 0.05 · F 0.334 · G 0.20 · E 2.352 = **$4.90**; по «факт потрачено + остаток по медианам» = 1.139729+0.364+0.121+0.61+0.154+0.05+0.20+2.352 = **$4.991** — цифра автора воспроизводится точно.\n\n4) Основание прогноза Д0.9 п.3 (`docs/experiments/23-editor-tier.md:882-883`) «чинил по указанному месту за ~$0.0002» против замеренной медианы A1 $0.006865 ⇒ расхождение **34.3×** — верно.\n\n5) A1 против A0 на тех же 30 единицах (A0 = `tp2-edit-E-deepseek-v4-flash-<uid>.json` для старых, `et-unit-edit-deepseek-v4-pro-<uid>.json` для новых — базы из `eval/dovodka/contour.py:86-90`): сумма A1 **$0.226944**, A0 **$0.244714**, ratio **0.927**, A1 дороже на **16 из 30** единиц — все три числа автора воспроизвёл.\n\nПроверил и «не объявлено ли это заранее»: `plan.py:52-54` объявляет множители прогнозом со сверкой при закрытии, но ни в Д0.8, ни в отчётах, ни в `docs/PROGRESS.md` расхождения нет (грепы по «2.41», «занижен», «дешевле в разы», «0.60×» — ни одного попадания по теме). Более того Д0.8 озаглавлен «Смета по ЗАМЕРЕННЫМ ценам», а две самые ходовые цены edit-контура замеренными не были. Находка новая и меняет и деньги, и один печатный прогноз фазы.",
|
||
"corrected": "Находка верна, но три уточнения масштаба и формулировки.\n\n(а) **Ошибка сметы двусторонняя, и заголовок «занижена в 2.41×» её преувеличивает как сводную.** Фиксер занижен ×2.41 ($0.00314 против $0.007561), но КРИТИК в plan.py:54 (`2.14 * edit` = $0.01119) **завышен в 1.94×** — замеренная медиана 48 купленных критик-клеток **$0.005758**. Поэтому армы с критиком почти сходятся: связка (fixer+critic+fixer) план $0.01747 против замеренных $0.02088 = **+19%**, а A3 фактически лёг в смету (план $0.459 / факт $0.4515). Пробой концентрирован в ЧИСТО фиксерных армах — A1 (×2.19/клетка), A4 (×2.53), свой пол. Сводный перебор пакета — **+$0.49 (+11%)**, а не ×2.41.\n\n(б) **Пробой пакетного потолка условен по ФД-E.** $4.99 держится на 16 клетках gemini по цене n=1 ($0.14702). Пакет влезает в $4.50 при k≤12 отгруженных клеток gemini ((16−k)·0.14702 ≥ 0.491 ⇒ k ≤ 12.7), а Д0.9 п.6 сама предсказывает 12–15. То есть «не влезает» надо формулировать так: **план в объявленном виде (16 клеток Д1, все оси несущими) не влезает; влезает только ценой падения Д1 до n=12, где Д0.3 объявляет ось ОПИСАТЕЛЬНОЙ (MDE 2.11 против цели 2.00)** — то есть перерасход оплачивается разжалованием несущей оси, а не растворяется. Пробой ФД-A ($1.24 против $0.885) при этом безусловен и уже состоялся.\n\n(в) **«Экономическая половина H-2а опровергнута» и «дешевле переписа фиксер не бывает» — сильнее, чем показывает сырьё.** A1 в сумме на 7% ДЕШЕВЛЕ A0 (0.927×); парная разность −$0.000592, sd $0.00502, t=−0.65, 95% ДИ [−$0.00247; +$0.00128] — ничья, а не проигрыш. Опровергнут прогноз Д0.9 п.3 «дешевле В РАЗЫ» (основание $0.0002 мимо на 34×); H-2а «дешевле по деньгам» по деньгам НЕ УСТАНОВЛЕНА (эффект неотличим от нуля), а качественная половина вообще не мерена — судейств ноль. Механизм автор назвал неверно: медианный текстовый выход у армов равен (completion−reasoning: 2750 у A1 против 2760 у A0), а промпт у фиксера КОРОЧЕ (4616 против 5422); разницу цены делают reasoning-токены (2883 против 2014) и худшее попадание в префикс-кэш (cached 256 против 1152). Значит «фиксер дороже по построению» неверно — он дорог по РАЗМЫШЛЕНИЮ, и это чинибельно мандатом, что как раз меняет смысл рекомендации владельцу.\n\nПочинка остаётся той же по существу, но вопрос владельцу формулируется числом $0.49 и выбором из двух: поднять пакетный потолок до ~$5.00 либо принять Д1 на n=12 описательной. Отдельно и раньше денег — пере-снять ФД-A: он мёртв на $0.35 и без ответа владельца ни одной клетки A2 купить нельзя."
|
||
}
|
||
},
|
||
{
|
||
"title": "Проекционный гард не останавливает прогон, а молча пропускает клетку: норма «срабатывание гарда = СТОП и вопрос владельцу» не механизирована",
|
||
"severity": "важно",
|
||
"evidence": "eval/role_topology/buy.py:143-147 — `ok, why = led.afford(); if not ok: print(why); return dict(..., skipped=True, cost_usd=0.0, ...)`. Возврат нигде не проверяется: contour.py:256, 266, 273, 285 отбрасывают результат MONEY.purchase, цикл идёт дальше по всем единицам и всем армам, код выхода 0. Наблюдаемое следствие уже в сырье: `contour.py --floor` печатает «A4: куплено 22 из 32» при потолке ФД-A, съеденном на 98.5%. Норма записана в money_d.py:16-20 и Д0.8 отчёта («срабатывание проекционного гарда = СТОП и вопрос владельцу, а не сокращение оси решением сессии»).",
|
||
"consequence": "Ось сокращается решением кода без чьего-либо решения и без ненулевого кода выхода — ровно то, что заказ запрещает. Хуже: в армах критик→фиксер (A3, A6, оба контура Д3) критик оплачивается ПЕРВЫМ, и отказ гарда на следующем шаге оставляет оплаченную клетку критика сиротой — при остатках $0.013/$0.015 это состояние ближайшего же прогона.",
|
||
"fix": "В contour.py проверять возврат purchase и на `skipped` печатать причину и выходить ненулевым кодом; в армах критик→фиксер спрашивать `led.afford()` на СУММУ обеих клеток до покупки критика.",
|
||
"verdict": {
|
||
"refuted": false,
|
||
"corrected": "Проекционный гард не механизирует объявленную норму «срабатывание = СТОП и вопрос владельцу»: он печатает причину и возвращает клетку с skipped=True (eval/role_topology/buy.py:143-146), а contour.py отбрасывает возврат на всех четырёх площадках покупки (256, 266, 273, 285), продолжает цикл по единицам И ПО СЛЕДУЮЩИМ АРМАМ и завершается кодом 0 (единственный sys.exit — 294, ветка --selftest). Реализованное следствие: на арме A4 гард молча снял 9 клеток (не 10 — одна единица законно не покупается по «мест нет»), из-за чего пре-регистрированная НЕСУЩАЯ ось Д4 (n=32, k=5, docs/experiments/23-editor-tier.md:758-759) исполнена как n=22 при k=4 — то есть ось урезана решением кода, что запрещено R68 (eval/dovodka/requirements.md:105, колонка проверки пуста). Отягчающее, автором не названное: ARMS=(\"A1\",\"A2\",\"A3\",\"A4\",\"A6\") (contour.py:72) — A6 идёт ПОСЛЕ A4 на другом кошельке ФД-F, поэтому один --run продолжает тратить ($0.267825 на A6) уже после наступления стоп-условия. Две поправки к формулировке автора: (1) масштаб урона A4 — 9 клеток, а не разница 32−22; (2) сиротство критика в армах критик→фиксер — риск проспективный, а НЕ «состояние ближайшего прогона»: оба таких арма УЖЕ полны (dv-a-a3 = 32 крит + 32 фикс, dv-f-a6 = 16 + 16, сирот ноль), в почти исчерпанном ФД-A недокуплены только A4 (фиксер без критика) и A2 (однопроходка без критика), а контуры Д3 с критиком живут в ФД-B, где $0.560 не тронуты вовсе. Смягчающее: пропущенная клетка НЕ пишет файла, кэш не отравлен, все 9 клеток остаются докупаемыми — потеряна форма оси, не деньги.",
|
||
"why": "Улики автора проверены собственными командами и подтвердились дословно. `grep -n \"led.afford()\\|print(why)\\|skipped=True\" eval/role_topology/buy.py` → 143/145/146: возврат dict(skipped=True, cost_usd=0.0, finish=\"skipped\"), без raise. `grep -n \"purchase\\|sys.exit\" eval/dovodka/contour.py` → покупки ровно на 256, 266, 273, 285, возврат нигде не связывается; sys.exit только 294 (--selftest); cmd_run возвращает None → код 0. money.py:149-160 Guarded.afford возвращает кортеж; money.py:247-250 отдаёт skipped-запись наружу сразу (finish != \"error\"). Норма реальна и не является объявленным ограничением: money_d.py:17 «**срабатывание проекционного гарда = СТОП и вопрос владельцу.**», та же фраза в пре-реге docs/experiments/23-editor-tier.md:871, R68 в eval/dovodka/requirements.md:105 с ПУСТОЙ колонкой проверки; грепом skipped|пропуск|СТОП по зоне и чтением docstring contour.py:1-23 объявления «гард молча пропускает клетку» не найдено. Причинность доказана, а не принята на слово: скриптом на харнессных же canon_gaps/flags_of получил «A1 куплено 30 | нет мест: 2 | ЕСТЬ места но НЕ куплено: 0» и «A4 куплено 22 | нет мест: 1 | ЕСТЬ места но НЕ куплено: 9 ['13c5f52fa3','b0a5efaa11','e40cdfbc3e','63ab55ac5c','debb2c1aef','89614f9bfa','7d0258aec0','3727846a2c','fb9ed5709e']» — то есть у A1 недобор законный, у A4 девять клеток сняты гардом. Альтернативные объяснения исключены: `ls ~/books/dovodka | grep -cE \"ERROR|NOMSG|lock\"` → 0, `grep -l '\"skipped\"' ~/books/dovodka/*.json` → пусто. `eval/.venv/bin/python eval/dovodka/contour.py --floor` → «A4: куплено 22 из 32», ФД-A 0.871904 при потолке 0.885 (98.5%). Поправка по сиротам обоснована подсчётом сырья: `ls dv-a-a3*.json | grep -c crit` = 32 и без crit = 32; `ls dv-f-a6*.json` = 16/16 — оба арма критик→фиксер полны, сирот нет; ФД-B нулевой по --floor. Отягчающее по порядку армов — contour.py:72 ARMS=(\"A1\",\"A2\",\"A3\",\"A4\",\"A6\"), ФД-F потрачено 0.267825 по --floor. Вывод фазы двигается: пре-рег Д0.3 (docs/experiments/23-editor-tier.md:758-759) объявляет «Д4 edit-контур zh 32 5 2.12 1.29 1.50 0.0000 НЕСУЩАЯ», факт — n=22 на A4 и n=0 на A2. Отдельно помечаю как НЕразрешённое, а не как клейм: ноль A2 не объясняется объявленной веткой «сборки однопроходки нет» — hasattr(PR,'translator_msgs') вернул True, и `git log -S\"def translator_msgs\" -- eval/tenant_panel/prompts.py` показывает её с e67ef1b; `find ~/books -name \"dv-*\" -not -path \"*/dovodka/*\"` пусто, клеток A2 нет нигде, поэтому «арм не звали» и «гард молча снял 32» по артефактам неразличимы — ровно потому, что гард не оставляет следа."
|
||
}
|
||
},
|
||
{
|
||
"title": "Гейт verify22.py, объявленный зелёным, выходит с кодом 1: денежное число отчёта выведено из mtime файлов и больше не воспроизводится",
|
||
"severity": "важно",
|
||
"evidence": "Прогон списка гейтов из хендоффа §5: `eval/.venv/bin/python eval/tenant_panel/verify22.py` EXIT=1, единственное расхождение — «[ПРОВАЛ] верхняя граница двойной оплаты $0.000000 напечатана». verify22.py:174-185 считает границу как сумму cost_usd клеток Ф2, у которых `f4.stat().st_mtime < ts(commit fd3e522)`. Все 335 файлов tp2-* имеют mtime==ctime 2026-08-10 22:01:18 (весь ~/books пере-штампован тогда же — 470/128/114 файлов, включая .git и epub; файлы вне ~/books, например ~/CONTINUATION_PROMPT.md 21:50, естественные времена сохранили) ⇒ pre=0.0. В записи клетки поля времени нет вовсе: ключи tp2-*.json — tag/model/finish/latency_s/cost_usd/tokens/role/uid/... Клетки фазы Д (dv-*.json) — тоже без времени.",
|
||
"consequence": "Число «верхняя граница невозвратной пере-оплаты ≤$0.846103» (22-tenant-panel.md:198-224), от которого зависит утверждение «чистота Ф2 не доказана для фактического расхода», опирается на файловую систему, а не на артефакт, и после любого копирования сырья не выводится ни за какие деньги. Пак 22 сдаётся оркестратору с красным гейтом при записи «все обязаны давать код 0». Класс воспроизведён в фазе Д: её клетки тоже не датированы, значит и её хронологию покупок восстановить будет нечем.",
|
||
"fix": "Писать в запись клетки `ts` (и обещанный `input_sig`) — одной строкой в buy.purchase; в verify22 заменить mtime-вывод на честное «величина не выводится из артефактов» либо на дату из записи, когда она появится. До этого гейт зелёным не называть.",
|
||
"verdict": {
|
||
"refuted": false,
|
||
"why": "Я пытался опровергнуть и не смог — ядро находки воспроизводится покомандно.\n\n1) Гейт действительно красный. `eval/.venv/bin/python eval/tenant_panel/verify22.py` → EXIT=1, единственное расхождение из всего списка: «[ПРОВАЛ] верхняя граница двойной оплаты $0.000000 напечатана граница = расход Ф2 ДО атомарного замка».\n\n2) Число выведено из файловой системы. verify22.py:174-185: `at = git log --format=%at -1 fd3e522`, затем `if f4.stat().st_mtime < int(at): pre += cost_usd`. Проверил `git log --format='%at %ai' -1 fd3e522` → `1786211005 2026-08-08 20:43:25`. Пере-считал руками по тем же трём глобам Ф2 (money.py:49 `tp2-draft-*|tp2-edit-*|tp2-floor-*`): `Ф2 files=335 total=$1.681912` (сходится с отчётом), `pre-lock files=0 pre=$0.000000`, минимальный mtime среди tp2 = 1786388478 — на 2.05 суток ПОЗЖЕ замка. Отчёт при этом печатает «до него куплено 176 клеток Ф2 на $0.846103» (docs/experiments/22-tenant-panel.md:224) и называет это «выводимой из сырья границей» — сейчас это неверно: из сырья выводится 0.\n\n3) В артефакте времени нет. Ключи клетки Ф2 (`~/books/tenant-panel/tp2-draft-D-deepseek-v4-flash-1431129de6.json`): attempt, cached_tokens, completion_tokens, content, cost_usd, en, finish, floor, latency_s, model, model_returned, prompt_tokens, reasoning_chars, reasoning_tokens, role, tag, tenant, total_tokens, uid — ни `ts`, ни `input_sig`. Класс воспроизведён в фазе Д: 148 платных клеток `~/books/dovodka/dv-*.json` в двух формах ключей (100 + 48), в обеих времени нет.\n\n4) «Зелёным объявлен» — подтверждено записью: docs/PROGRESS.md:239 «Гейты код 0: itog22.py · verify22.py · conformance.py»; docs/experiments/23-editor-tier.md:707 «verify22.py и itog22.py зелёные, код возврата 0»; сам отчёт 22-tenant-panel.md:22 «ненулевой код возврата = отчёт не сдаётся».\n\n5) Последствие для фазы Д сильнее, чем в находке: `eval/conformance.py --plan eval/dovodka/requirements.md` → EXIT=1, среди трёх провалов `[ПРОВАЛ] R71 Правка рига чужого пака — отдельным коммитом + пере-снятие его гейтов ← РАСХОЖДЕНИЙ: 1 — ОТЧЁТ НЕ СДАЁТСЯ`, то есть красный verify22 валит и собственный реестр требований фазы Д (eval/dovodka/requirements.md:108).\n\nДолларов находка не двигает: ни одной покупки не отменяет и не добавляет. Ломается воспроизводимость числа и сдача пака.",
|
||
"corrected": "Формулировка верна по сути, но три детали надо исправить.\n\nа) «Список гейтов из хендоффа §5» — такого места нет: в docs/POLYGON_EXP2223_REDO_SESSION_PROMPT.md нет ни §5, ни списка гейтов (`grep -n '^#' ` даёт разделы Д0…Д8 / Нормы рига / Чего НЕ делать / Отчёт и сдача). Требование пере-снимать гейты чужого пака стоит строкой 185 промта, а машинная улика к нему — R71 в eval/dovodka/requirements.md:108 с командой `verify22.py`. Гейт красный по этому основанию, а не по несуществующему §5.\n\nб) Масштаб пере-штамповки указан неверно («470/128/114 файлов»). Замер обходом дерева: под ~/books 6880 файлов, 6797 из них несут mtime 2026-08-10 22:01, 81 файл — 23:39, 2 файла — 11.08. Причина не загадочна и устанавливается: ~/books превращён в git-репозиторий, импорт-коммит 8307ccc «Import polygon raw material: packs 21-23 and phase D measurements…» датирован 2026-08-10 21:59:47, рабочее дерево материализовано в 22:01:18. Важное следствие, которого в находке нет: в самом ~/books ВСЕГО два коммита (8307ccc, ad3c2a6), поэтому и git-история сырья хронологии покупок не содержит — запасного пути вывода нет ни одного.\n\nв) «Пак 22 сдаётся с красным гейтом» — верно, но красный ОДИН из трёх объявленных: `itog22.py` проверен, EXIT=0 (пере-счёт несущих чисел из сырья цел); `conformance.py` без режима выходит 1 по usage, а не по проверке. То есть дефект точечный: сломан ровно тот единственный чек, который опирался на mtime, а не пере-счётный контур целиком.\n\nТочная переформулировка: «Единственная mtime-зависимая проверка в verify22.py (строки 174-185) после материализации ~/books из git-импорта 10.08 22:01 даёт 0 вместо $0.846103, из-за чего verify22.py выходит с кодом 1 при трёх записях о его зелёности, и валит R71 в реестре требований фазы Д. Число «≤$0.846103 / 176 клеток» в 22-tenant-panel.md:224 названо «выводимым из сырья», хотя выводилось из файловой системы, и восстановлению не подлежит: ни клетки Ф2, ни клетки фазы Д не несут поля времени, а git-история ~/books состоит из двух коммитов.»"
|
||
}
|
||
},
|
||
{
|
||
"title": "Режим `--floor` объявлен в docstring, кода нет — молча исполняется `--plan` с кодом 0; своего шумового пола Д4 не существует ни в одном файле",
|
||
"severity": "важно",
|
||
"evidence": "contour.py:23 «Запуск: contour.py --plan | --selftest | --run [A1 A2 A3 A4 A6] | --floor»; разбор аргументов contour.py:291-298 знает только --selftest и --run, всё остальное падает в cmd_plan. Исполнено: `eval/.venv/bin/python eval/dovodka/contour.py --floor` печатает таблицу армов и кассу, EXIT=0. `grep -n floor eval/dovodka/contour.py` — единственное вхождение слова в docstring; `grep -rn floor eval/dovodka/*.py` — только комментарий в power.py и комментарий к тегу в money_d.py:55.",
|
||
"consequence": "Свой шумовой пол — то, чем Д0.3 обещает пере-классифицировать оси («Решает СВОЙ пол... ось пере-классифицируется ТОГДА ЖЕ»), и то, что нормой Д0.6 обязано строиться парой отдельных генераций, судимых РАЗНЫМИ сессиями. Инструмента нет, а строка сметы (16×фиксер в ФД-A) под него зарезервирована. Тот, кто продолжит фазу по docstring, получит зелёный код выхода и решит, что пол построен.",
|
||
"fix": "Либо написать cmd_floor (две ОТДЕЛЬНЫЕ генерации на единицу, боевые клетки половинами не брать, регистрация судейских сессий через runs.py), либо убрать --floor из docstring и добавить отказ на неизвестный аргумент. Заодно посчитать пол по замеренной цене: 16 клеток покрывают 8 единиц, а прайоры сняты на n=16.",
|
||
"verdict": {
|
||
"refuted": false,
|
||
"why": "Проверил своими командами, опровергнуть не удалось — все четыре звена находки воспроизводятся.\n\n1) Реклама режима: `eval/dovodka/contour.py:23` — «Запуск: contour.py --plan | --selftest | --run [A1 A2 A3 A4 A6] | --floor».\n2) Разбор аргументов `contour.py:291-298` (вывел с номерами через `grep -n \"\" | sed -n '285,300p'`): ветки только `--selftest` и `--run`, всё прочее падает в `else: cmd_plan()`. Исполнил: `eval/.venv/bin/python eval/dovodka/contour.py --floor` печатает таблицу армов и кассовую сводку, `EXIT=0`.\n3) Кода пола нет: `grep -rni \"floor\" eval/dovodka/*.py` даёт ровно два хита — `contour.py:23` (докстринг) и `power.py:30` (комментарий про ярлыки полов эксп-22); `grep -rn \"def .*floor\"` по `eval/dovodka/` — пусто. Купленных клеток пола тоже нет: `ls ~/books/dovodka | sed 's/-[0-9a-f]\\{10\\}\\.json//' | sort | uniq -c` → только `dv-a-a1/a3/a3-crit/a4` и `dv-f-a6/a6-crit`, ни одного тега пола.\n4) Смета под пол зарезервирована: `eval/dovodka/plan.py:74` `d4 = n4 * (fixer + onepass + (critic + fixer) + fixer) + 16 * fixer`, подпись строки `plan.py:76-77` «…n={n4} + свой пол»; тот же текст в пре-реге Д0.8 (`docs/experiments/23-editor-tier.md:850`) и в комментарии тега `eval/dovodka/money_d.py:55`.\n5) Пол — не украшение, а гейт вывода: Д0.3 «Решает СВОЙ пол, и если он выйдет хуже прайора, ось пере-классифицируется в описательную ТОГДА ЖЕ» (23-editor-tier.md, секция Д0.3), норма Д0.6 «Шумовой пол — парой, чьи половины судят РАЗНЫЕ сессии… боевая клетка половиной пола не берётся». Прайор оси Д4 (sd 2.12, MDE 1.29) — заимствованный, `power.py:16-18` это сам объявляет.\n\nПроверил и оправдательные версии — ни одна не спасает:\n— «Ограничение объявлено»: объявлено отсутствие СВОЕГО ПОЛА как прайора (`power.py:16`), но нигде не объявлено, что режим `--floor` не реализован; докстринг утверждает обратное. Это и есть разрыв «объявленное против реального».\n— «Есть переиспользуемый риг»: `eval/editor_tier/panel.py:167 cmd_floor_run` существует, но строит пол ПОЛНОГО переписа, а не фиксер-контура, и его же докстринг `panel.py:190-199` объявляет дефект «первая половина пары — сама боевая клетка T1», который норма Д0.6 этой фазы прямо запрещает. То есть годного заменителя для Д4 нет.\n— «Молчаливый фолбэк — просто стиль»: да, это домашний паттерн фазы (`money_d.py` и `runs.py` на неизвестном аргументе тоже уходят в `report()`), поэтому сам фолбэк я бы дефектом не считал; дефект — реклама несуществующего режима поверх этого фолбэка.",
|
||
"corrected": "Формулировка верна, но недосказана по деньгам — последствие крупнее, чем «докстринг врёт». Точнее так: режим `--floor` объявлен в `contour.py:23`, кода нет (`contour.py:291-298` знает только `--selftest`/`--run`), `--floor` молча исполняет `--plan` с EXIT=0; своего шумового пола Д4 нет ни в коде, ни в купленном сырье (0 клеток пола в ~/books/dovodka), а годного чужого рига нет тоже — пол пака 23 (`eval/editor_tier/panel.py:167`) меряет пол ПОЛНОГО переписа и сам объявлен дефектным (`panel.py:190-199`: первая половина пары — боевая клетка T1), что норма Д0.6 фазы запрещает.\n\nДобавить, чего в находке нет: строка сметы под пол не просто не потрачена — она СЪЕДЕНА армами. 16×фиксер = 16 × $0.00314 = $0.0502 (цена фиксера — вывод `plan.py`), а в ФД-A остаток $0.885 − $0.871904 = $0.0131 (`money_d.py:67`; в отчёте потолок печатается как 0.89 из-за формата `:10.2f`). То есть пол теперь не влезает в фазовый потолок примерно вчетверо — и это при том, что A2 куплен нулём клеток, а A4 обрезан на 22 из 32. Поэтому починка «просто написать cmd_floor» неполна: она требует либо пере-сметы ФД-A с пингом владельцу (Д0.8: срабатывание гарда = СТОП и вопрос владельцу, сокращение оси решением сессии запрещено), либо явного объявления оси Д4 описательной. Верна и арифметическая оговорка находки: 16 клеток при запрете брать боевую клетку половиной дают пол всего на 8 единицах против прайора, снятого на n=16."
|
||
}
|
||
},
|
||
{
|
||
"title": "Печать прогресса сертифицирует полноту армов, которые заведомо неполны",
|
||
"severity": "мелко",
|
||
"evidence": "`contour.py --floor` (=cmd_plan) печатает «A6: куплено 16 из 16» и «A1: куплено 30 из 32», тогда как A6 объявлен в contour.py:12 и Д0.5 как «черновик dspro + ОБА контура», а куплена только ветка критика (в cmd_run флаговой ветки для A6 нет — известная Д-5), у A1 же батарея не отработала ни разу (Д-2). cmd_plan:177-180 считает 16 из 16 по одному тегу dv-f-a6-<uid>.",
|
||
"consequence": "Единственная сводка состояния фазы показывает полностью закрытый арм там, где куплена половина объявленного дизайна; следующая сессия по этой печати сочтёт H-1 обеспеченным.",
|
||
"fix": "Считать полноту по ОБЪЯВЛЕННОМУ составу арма (для A6 — две ветки), а не по одному тегу.",
|
||
"verdict": {
|
||
"refuted": false,
|
||
"why": "Проверил своими прогонами, находка по существу подтверждается, но её формулировка и улика частично промахиваются.\n\nЧТО ПОДТВЕРДИЛОСЬ.\n1. Печать воспроизведена: `timeout 300 eval/.venv/bin/python eval/dovodka/contour.py --plan` →\n```\nединиц 32 (старых 16 + новых 16)\n A1: куплено 30 из 32\n A2: куплено 0 из 32\n A3: куплено 32 из 32\n A4: куплено 22 из 32\n A6: куплено 16 из 16\n```\n2. Объявленный состав A6 — ДВА контура: eval/dovodka/contour.py:12 «A6 ДРУГАЯ БАЗА: черновик dspro эксп-22 + оба контура»; пре-рег Д0.5 (docs/experiments/23-editor-tier.md:748 «A6 = dspro-черновик эксп-22 + оба контура», :804 таблица армов, :860 «ФД-F H-1: A6, dspro-черновик + оба контура (n=16) 0.280»); тот же текст в docs/PROGRESS.md:233 и в хендоффе /home/ubuntu/CONTINUATION_PROMPT.md:56,251.\n3. Куплена только смысловая ветка. В cmd_run флаговая ветка — `if arm in (\"A1\",\"A4\")` (contour.py:259), A6 туда не входит и падает в ветку contour.py:270 «A3 и A6: критик, затем фиксер». Сырьё это подтверждает: `cd ~/books/dovodka && ls | sed 's/-[a-z0-9]*\\.json$//' | sort | uniq -c` → `16 dv-f-a6-crit`, `16 dv-f-a6`, и ни одной клетки флагового контура A6.\n4. Счёт полноты в cmd_plan:177-180 действительно идёт по ОДНОМУ тегу (`text_of` → contour.py:163-167, `dv-f-a6-<uid>`), а знаменатель — число единиц (16), а не число объявленных веток.\n5. Нигде в докахURE сокращение A6 до одной ветки не задекларировано: греп «A6» по docs/PROGRESS.md, docs/POLYGON_EXP2223_REDO_SESSION_PROMPT.md, eval/dovodka/requirements.md, docs/experiments/22-tenant-panel.md — единственное упоминание PROGRESS.md:233 говорит «A6 (dspro-черновик + контуры)», множественное число. Вечерний статус (git show 90c23cb) A6 не упоминает вовсе. То есть «единственная сводка состояния» — действительно печать.\n\nЧТО В НАХОДКЕ НЕВЕРНО (масштаб/улика).\n6. Часть улики про A1 работает ПРОТИВ тезиса. Печать «A1: куплено 30 из 32» не сертифицирует полноту, а НЕДО-считает: две клетки не покупались законно — cmd_run:262-265 «мест нет — чинить нечего, клетка не покупается». Проверил: у обеих недостающих клеток (474f822806, 9b16c9c9a7) `flags_of` даёт places=0, а вечерний журнал сам пишет «A1 30/30 платных клеток». Так что арм A1 по дизайну ПОЛОН, а печать показывает его неполным — дефект печати есть, но противоположного знака, и к «сертификации полноты» отношения не имеет. (Для контраста A4: из 10 недостающих клеток лишь у одной ноль канон-разрывов, остальные 9 — реальный стоп гарда.)\n7. Ссылка на Д-2 («батарея не отработала») к этой печати не относится: она про СОСТАВ мест внутри A1, а не про счётчик. Факт я перепроверил (на 6 единицах flags_of даёт только «КАНОН», ноль «БАТАРЕЯ»), но это другая находка.\n8. Дефект производный, а не самостоятельный: корень — отсутствие второй ветки A6 (Д-5); печать лишь делает его невидимым. Ни одного доллара и ни одного числа фазы находка не двигает (судейств нет, ФД-F $0.267825 потрачен именно на смысловую ветку). Замечу попутно: объявленный потолок ФД-F $0.280 обе ветки на 16 единицах в принципе не покрывал бы (по удельной цене A3 ≈$0.0141/ед. и A1 ≈$0.0076/ед. это ≈$0.35), так что «оба контура» были недофинансированы уже в пре-реге.",
|
||
"corrected": "Печать cmd_plan (eval/dovodka/contour.py:177-180) считает полноту по ОДНОМУ тегу результата и по числу единиц, а не по объявленному составу арма. Практическое последствие ровно одно: строка «A6: куплено 16 из 16» скрывает, что из двух объявленных контуров A6 (contour.py:12, пре-рег Д0.5, PROGRESS.md:233 — «оба контура») куплен только смысловой; флаговой ветки для A6 в cmd_run нет (ветка `if arm in (\"A1\",\"A4\")`, contour.py:259), и сокращение нигде в докax не задекларировано, так что печать — единственная сводка состояния и читается как «H-1 обеспечен». Улику про A1 из находки надо снять: «30 из 32» ничего не сертифицирует — это НЕДО-счёт законно не купленных клеток (places=0, contour.py:262-265), арм A1 по дизайну полон (30/30 платных). Тяжесть — мелкая и производная от Д-5 (отсутствие второй ветки A6); ни один вывод фазы и ни один доллар не меняются. Починка: печатать полноту по составу арма (для A6 — две ветки, с отдельным счётом крит-тега `dv-f-a6-<uid>-crit`) либо явно помечать A6 как «1 из 2 объявленных контуров»."
|
||
}
|
||
},
|
||
{
|
||
"title": "Мелкие расхождения чисел отчёта и хендоффа с исполнением",
|
||
"severity": "мелко",
|
||
"evidence": "(а) Д0.6 и хендофф §4 D-2: «селфтест 16/16» — фактически 15 проверок: `eval/dovodka/runs.py --selftest` печатает 15 строк [OK ]. (б) Хендофф §4 D-11/D-12 называет артефактом изоляции каталог `~/sol-tier-work/` с побайтно сверенными заданиями 16/16 — каталога на диске нет (`ls ~` показывает только books/go/projects; файлы домашнего каталога свои времена сохранили, то есть это не следствие пере-штамповки ~/books). (в) Д0.4 решает H-2а неоткорректированным 95% ДИ, тогда как MDE той же оси посчитан с α/k=3 — множественность учтена в мощности и не учтена в решающем правиле.",
|
||
"consequence": "Каждое по отдельности вывод не меняет, но все три — заявления, которые читатель проверит первыми: два не воспроизводятся, третье делает объявленную мощность и объявленное правило решения разными приборами.",
|
||
"fix": "Поправить число проверок; пере-выпустить или назвать утраченным пакет заданий внешнему судье (от него зависит ждущее решение владельца «пере-судить tier или оставить с возражением»); согласовать множественность между Д0.4 и power.py.",
|
||
"verdict": {
|
||
"refuted": false,
|
||
"corrected": "Из трёх пунктов держатся полтора, и главный — (б) — неверен.\n\n(а) ВЕРНО, но это одна цифра. `eval/.venv/bin/python eval/dovodka/runs.py --selftest` печатает ровно 15 строк `[OK ]` и «ЖУРНАЛ ГОДЕН». Заявление «селфтест 16/16» стоит в `docs/experiments/23-editor-tier.md:824` и в `~/CONTINUATION_PROMPT.md:89`. Цифра 16 недостижима ни при каком счёте: в `eval/dovodka/runs.py:182-258` 18 вызовов `ck(`, из них три пары — взаимоисключающие ветки try/except с одним и тем же именем (гонка токенов, ожидание живого замка, отказ капа), то есть исполняется 15. Починка — заменить «16/16» на «15/15»; ни числа, ни выводы, ни доллары не двигаются.\n\n(б) НЕВЕРНО по существу и предложенная починка вредна. Пакет заданий внешнему судье НЕ утрачен: он лежит в `~/books/editor-tier/sol-tier/` — `tasks/` с 16 заданиями, `ИНСТРУКЦИЯ.md`, `ПРОМТ-ДЛЯ-ХАРНЕССА.md`. Побайтность D-12 воспроизводится: `diff ~/books/editor-tier/aj-tier-tasks/<t>.txt ~/books/editor-tier/sol-tier/tasks/<t>.txt` даёт по 2 различающиеся строки на каждом из 16 файлов, и это одна и та же строка 13 — путь записи ответа (`aj-tier/` → `sol-tier/`), тела заданий идентичны 16/16. Более того, прогон уже СОСТОЯЛСЯ: в `sol-tier/` лежат 16 файлов ответов, и `eval/.venv/bin/python eval/editor_tier/solscore.py tier` считает их с диска прямо сейчас: «принято единиц 16 · отвергнуто 0 · ДЕКОЙ −5.56 поймано 16/16 · ПОЛ −2.50 порог 2.60 · T1 +0.81 p=0.5695 · T2 +8.69 p=0.0002 · T3 +0.38 p=0.8730 · R0 vs F +9.25 p=0.0003». Ошибочен только путь-строка `~/sol-tier-work/` в `~/CONTINUATION_PROMPT.md:129` — стал стейлом, каталог с таким именем не создавался; `ПРОМТ-ДЛЯ-ХАРНЕССА.md` называет фактический `~/books/editor-tier/sol-tier/tasks/`. Аргумент автора про mtime тоже не работает: ВСЕ файлы под `~/books` несут одинаковый штамп Aug 10 22:01 (`ls -la ~/books/editor-tier`), то есть времена там ничего не доказывают ни в одну сторону. Правильная починка — поправить одну строку пути в хендоффе; «пере-выпустить пакет или назвать его утраченным» — работа владельца впустую по ложной посылке, и ждущее решение «пере-судить tier или оставить с возражением» ничем не заблокировано.\n\n(в) ФАКТ ВЕРЕН, рамка завышена, и рядом лежит расхождение крупнее, которое автор не заметил. Д0.4 (`23-editor-tier.md:785-786`) действительно решает H-2а неоткорректированной нижней границей 95% ДИ, а `eval/dovodka/power.py:47-50,72-75` держит `A1/A0` в первичном семействе Холма при k=3. Но «мощность и правило решения — разные приборы» — перебор: запас −1.50 в Д0.4 равен ЦЕЛИ оси Д4 в power.py, и Холм-скорректированный MDE 1.49 посчитан ровно под неё, то есть план подпирает границу. Точная формулировка дефекта другая: множественность внутри самого NI-правила (оно выносит два вердикта — A1 и A3) не объявлена вовсе. И на той же странице стоит расхождение больше: замороженная таблица Д0.3 (`23-editor-tier.md:760-763`) печатает «Д4 32 5 2.12 1.29», «Д3 16 5 … 0.0002», «Д6 … 3.33», тогда как `eval/.venv/bin/python eval/dovodka/power.py` на том же коммите даёт «Д4 32 3 2.12 1.49», «Д3 16 1 … 0.0000», «Д6 … 3.85» — таблицу пре-рега не перегенерили после починки множителя Холма (оба файла чистые в `git status`, то есть противоречие вморожено во фриз da5f4d0).\n\nИтог: ни один доллар и ни один вывод фазы не двигаются (судейств Д4 нет — 0 из 80), но публикуемая правка — «15/15», один путь в хендоффе, объявление множественности NI-правила и пере-генерация таблицы Д0.3 — а не пере-выпуск пакета внешнего судьи.",
|
||
"why": "(а) `eval/.venv/bin/python eval/dovodka/runs.py --selftest` → 15 строк `[OK ]` + «ЖУРНАЛ ГОДЕН»; `grep -c 'ck('` по `eval/dovodka/runs.py` даёт 18 вызовов, три пары из которых — try/except-альтернативы (`runs.py:203-208`, `216-224`, `253-258`), 18−3=15. Заявка «16/16»: `docs/experiments/23-editor-tier.md:824`, `~/CONTINUATION_PROMPT.md:89`.\n(б) `ls -la /home/ubuntu/books/editor-tier/sol-tier` → 16 `*.txt` ответов + `tasks/` + `ИНСТРУКЦИЯ.md` + `ПРОМТ-ДЛЯ-ХАРНЕССА.md`; `ls tasks | wc -l` = 16; цикл `diff aj-tier-tasks/$b sol-tier/tasks/$b` → по 2 строки на всех 16, единственная — строка 13 с путём записи; `eval/.venv/bin/python eval/editor_tier/solscore.py tier` → «принято единиц 16 · отвергнуто 0 · ДЕКОЙ −5.56 · поймано 16/16». Стейл-путь: `~/CONTINUATION_PROMPT.md:129`. Единый mtime всего `~/books`: `ls -la /home/ubuntu/books/editor-tier` (все Aug 10 22:01).\n(в) Правило: `docs/experiments/23-editor-tier.md:785-786`; семейство k=3: `eval/dovodka/power.py:47-50` (`(\"Д4 edit-контур zh\", 32, 3, 2.12, 1.50, …)`) и `PRIMARY` там же; множитель α/2k: `power.py::mde`. Расхождение таблицы: `23-editor-tier.md:760-763` против вывода `eval/.venv/bin/python eval/dovodka/power.py`; `git status --porcelain docs/experiments/23-editor-tier.md eval/dovodka/power.py` — пусто, оба во фризе da5f4d0."
|
||
}
|
||
},
|
||
{
|
||
"title": "base_draft() пропускает эхо-мину на новых единицах: гейт брака черновика применяется к старым 16 и не применяется к новым 16 — арм A1/A3 куплен поверх китайского исходника",
|
||
"severity": "критично",
|
||
"evidence": "eval/dovodka/contour.py:80-83 `return t if t.strip() else PAN23.draft_b(uid)`. Для старых единиц t идёт из tenant_panel/panel.py:124-133 `draft_text`, где стоит `if c and not BO.draft_reject_reason(c)`. Ветка для новых — editor_tier/panel.py:112-115 `draft_b`, сырое чтение без гейта. Исполнение (probe2.py): единица 63ab55ac5c — base_draft 2243 знака, 1798 ханьцзы, 0 кириллицы, `BO.draft_reject_reason` = «эхо исходника». Купленные на ней клетки: dv-a-a1-63ab55ac5c $0.012464 (выход 2490 знаков, 1727 ханьцзы, 288 кириллицы), dv-a-a3-crit-63ab55ac5c $0.002632 (ответ критика целиком на китайском), dv-a-a3-63ab55ac5c $0.004923 (2249 знаков, 1804 ханьцзы, 0 кириллицы) — итого $0.020019. base_a0 той же единицы = 8167 знаков нормального русского. Селфтест contour.py:201-202 проверяет только `.strip()`.",
|
||
"consequence": "Это дословное повторение дефекта, который пак 23 объявил и починил (23-editor-tier.md:349-356, editor_tier/panel.py:94-100 «гейт был написан и не подключён»): починку внесли в cmd_b_run, а фаза Д читает те же черновики мимо неё. $0.0200 выброшено, но дороже другое: на этой единице A1/A3 по построению отдают нередактируемый китайский текст против нормального русского A0, то есть в парный контраст несущей оси Д4 (n=32, MDE 1.29) заходит одна единица с максимально возможным отрицательным перевесом, не имеющая отношения к проверяемому контуру. Ставка владельца H-2б («смысловой контур лучше переписа») меряется с гирей на своей чаше.",
|
||
"fix": "Прогнать base_draft через BO.draft_reject_reason (как это делает draft_text), единицу 63ab55ac5c исключить из оси Д4 или пере-купить её черновик; в селфтест добавить проверку годности базы, а не непустоты; пере-снять числа Д4 без неё и объявить чувствительность вывода.",
|
||
"verdict": {
|
||
"line": "код-харнесса",
|
||
"refuted": false,
|
||
"corrected": "В contour.py:80-83 base_draft() отдаёт черновик новых 16 единиц без гейта брака: старая ветка P22.draft_text (tenant_panel/panel.py:130 `if c and not BO.draft_reject_reason(c)`) годность проверяет, новая PAN23.draft_b (editor_tier/panel.py:112-115) читает JSON сырым. Пере-снято мной по всем 32 единицам: забракована ровно ОДНА — новая 63ab55ac5c (len=2243, ханьцзы 1798, кириллицы 0, вердикт «эхо исходника»), при том что её base_a0 чист (len=8167, кириллицы 6557). Поверх этой китайской базы куплены три клетки: dv-a-a1 $0.012464 (выход 1727 ханьцзы / 288 кириллицы), dv-a-a3-crit $0.002632 (критика целиком на китайском), dv-a-a3 $0.004923 (1804 ханьцзы / 0 кириллицы) — $0.020019 выброшено (1.8% потраченных $1.1397). Селфтест (contour.py:201-202) проверяет только .strip() и печатает «ХАРНЕСС ГОДЕН» — прогнал живьём. В фазе Д это НЕ объявлено: греп 63ab55ac5c по Д0 (23-editor-tier.md:719-896), по промту заказа и по eval/dovodka/ даёт только пак-23-овую строку 352; фильтра годности базы в eval/dovodka/ нет вовсе, а Д0.5 объявляет базу «одной и замороженной» на n=32. ДВЕ ПОПРАВКИ к исходной формулировке. (1) Гиря лежит не на чаше H-2б отдельно: выход A1 на этой единице тоже почти китайский (1727 ханьцзы при 288 кириллицы), так что штраф несут ОБА контурных арма против A0, а прямое сравнение A3 против A1 примерно симметрично; страдает всё семейство «контур/A0», а не ставка владельца избирательно. (2) «Меняет вывод» — не доказано, а под риском: одна единица из 32 в парном дизайне сдвигает среднее оси максимум на ~0.2-0.3 при MDE 1.29 (аналогичная чувствительность в паке 23 замерена как 0.07), плюс раздувает sd и режет мощность; решающим это станет, только если контраст ляжет у пред-объявленной границы non-inferiority -1.50 (Д0.4). Судейство ещё не запускалось, поэтому починка (гейт в base_draft + исключение или пере-покупка черновика единицы + проверка ГОДНОСТИ, а не непустоты, в селфтесте) пока бесплатна.",
|
||
"why": "Грунт по каждому звену. КОД: `grep -n \"\" eval/dovodka/contour.py | sed -n '80,83p'` → `t = P22.draft_text(ANCHOR, uid); return t if t.strip() else PAN23.draft_b(uid)`; гейт в старой ветке — tenant_panel/panel.py:130 `if c and not BO.draft_reject_reason(c)`; новая ветка editor_tier/panel.py:112-115 — сырое `json.loads(...).get(\"content\")`. ИСПОЛНЕНИЕ (мой probe, eval/.venv/bin/python, загрузил contour.py как модуль и прогнал bakeoff.draft_reject_reason по всем units()): «units 32 old 16», единственная забракованная — ('63ab55ac5c', False=новая, 'эхо исходника', 'len=2243 han=1798 cyr=0'); base_a0 той же единицы 'len=8167 han=0 cyr=6557', reject пусто; P22.draft_text(ANCHOR,'63ab55ac5c') = пусто, PAN23.draft_b = тот самый эхо-текст — то есть фолбэк-ветка действительно источник. ДЕНЬГИ (чтение ~/books/dovodka): dv-a-a1-63ab55ac5c cost=0.012464 finish=stop places=8 len=2490 han=1727 cyr=288; dv-a-a3-crit-63ab55ac5c cost=0.002632 finish=stop len=1369 han=764 (первая строка ответа критика — китайская: «- 能拧出水来 → 原文为…»); dv-a-a3-63ab55ac5c cost=0.004923 places=22 len=2249 han=1804 cyr=0; сумма 0.020019; вся фаза sum(cost_usd, dv-*.json)=1.1397 — сходится с заявленным состоянием. СЕЛФТЕСТ: `eval/.venv/bin/python eval/dovodka/contour.py --selftest` прогнан — «[OK] якорный черновик есть у всех нет у []» и «ХАРНЕСС ГОДЕН»; тело проверки contour.py:201-202 — только `.strip()`. НЕ ОБЪЯВЛЕНО В ФАЗЕ Д: `grep -rn \"63ab55ac5c|эхо-мин|эхо исходника\" docs/experiments/23-editor-tier.md docs/POLYGON_EXP2223_REDO_SESSION_PROMPT.md eval/dovodka/*.py eval/dovodka/*.md` → 63ab55ac5c встречается ровно один раз, в теле пака 23 (строка 352, §8.2 «ЭХО-МИНА НА БОЕВОЙ БАЗЕ… гейт был написан, но не подключён»), и ни разу в Д0 (719-896) или в коде/требованиях фазы; `grep -rn \"reject_reason|исключ|exclude\" eval/dovodka/*.py` — ни одного фильтра годности базы. Прочитал Д0 целиком: Д0.3 даёт «Д4 edit-контур zh 32 5 2.12 1.29 1.50 НЕСУЩАЯ» (числа находки верны), Д0.5 — «база одна и замороженная», Д0.4 — граница non-inferiority -1.50. ПОЧЕМУ ЭТО НЕ «ОБЪЯВЛЕННОЕ ОГРАНИЧЕНИЕ»: пак 23 объявил и ПОЧИНИЛ дефект у себя (editor_tier/panel.py:94-100, гейт в cmd_b_run) и замерил свою чувствительность (-0.74 против -0.81, вердикт не менялся); фаза Д читает те же черновики мимо этой починки и нигде этого не объявляет. ПОЧЕМУ ПОПРАВКА (1): цифры моего probe по dv-a-a1 (288 кириллицы на 2490 знаков, 1727 ханьцзы) показывают, что A1 на этой единице испорчен так же, как A3, значит формулировка «гиря именно на чаше H-2б» неточна — штраф общий для A1/A0 и A3/A0, а contour.py:263-283 (cmd_run) подтверждает, что A4 берёт base_a0 (не затронут), A6 идёт только по старым (uid not in old → continue), A2 не куплен. ПОЧЕМУ ПОПРАВКА (2): арифметика парного дизайна — вклад одной единицы в среднее оси = её контраст/32, то есть ≤~0.3 при любом правдоподобном перевесе, против MDE 1.29; сам пак 23 замерил аналогичный сдвиг как 0.07 (23-editor-tier.md:357-358). Судейских клеток по Д4 в ~/books/dovodka нет (все 150 файлов — dv-a-*/dv-f-*, роли draft/fixer/critic), то есть вывод ещё не снят и починка бесплатна."
|
||
}
|
||
},
|
||
{
|
||
"title": "A4 стоит на усечённой базе и сам режется по max_tokens — прирост покрытия канона +53 попадания на 20 единицах ровно съедается −53 на двух обрезанных, и объявленный прогноз арма читается как опровергнутый",
|
||
"severity": "критично",
|
||
"evidence": "probe3/probe6/probe7.py: A0 единицы 41599f30df имеет finish=length (5759 знаков против 6767 у черновика), contour.py:86-89 base_a0 читает content не глядя на finish, contour.py:259-268 строит на нём канон-фиксер. Своя же canon.py:162-169 такие единицы исключает явно («клетка R0 с finish=length даёт потерю канона, которая на деле есть ОБРЫВ»). Результат парно: BANK.coverage по 22 единицам A4 = 1116/1271 = 0.878, у входа A0 на тех же 22 — 1116/1271 = 0.878, ноль. Поштучно A4 добавляет +1…+7 на 20 единицах (сумма +53) и теряет 62→27 на 41599f30df и 63→45 на f6da9f76b2 — обе клетки finish=length, completion_tokens ровно 16000 (дефолт roster.py:113 max_out=16000), $0.015691 и $0.015945.",
|
||
"consequence": "Прогноз пре-рега Д0.9 п.2 «A4 даст лучшее покрытие канона из всей панели» на этих данных печатается как ноль, хотя без двух обрезанных клеток это +0.042 покрытия. Вывод по оси канона переворачивается двумя клетками. Клетки закешированы под своим тегом (money.py:228-230), поэтому пере-запуск их НИКОГДА не пере-купит, и норма Д0.6 «клетка с finish=length в пачку не допускается» без ручного удаления файлов недостижима.",
|
||
"fix": "Гейт на finish клетки при чтении (text_of/base_a0 возвращают пусто при finish=length) и при записи — с пере-покупкой; дать фиксеру потолок выхода от длины входа, а не константу 16000 (у DeepSeek размышление внутри completion_tokens); единицы с обрезанным A0 из арма A4 исключить, как это делает canon.py.",
|
||
"verdict": {
|
||
"line": "код-харнесса",
|
||
"refuted": false,
|
||
"corrected": "ВЕРНО ЯДРО (арифметика), НЕВЕРНА ПРИЧИННАЯ ИСТОРИЯ И ЗАГОЛОВОК. Исправленная формулировка:\n\n«Две клетки A4 обрываются по собственному потолку выхода и ОБНУЛЯЮТ канон-ось арма. A4 добавляет +1…+7 попаданий на 19 из 20 нормальных единиц (сумма +53) и теряет −35 (62→27) и −18 (63→45) на двух клетках с finish=length и completion_tokens ровно 16000 (roster.py:113 max_out=16000; reasoning_tokens 15046 и 14013 — размышление DeepSeek съедает бюджет выхода). Итог по 22 единицам: 1116/1271 = 0.8780 у входа A0 и 1116/1271 = 0.8780 у A4 — ровно ноль. Без этих двух клеток: 991/1118 = 0.8864 → 1044/1118 = 0.9338, то есть +0.047. Прогноз Д0.9 п.2 („A4 даст лучшее покрытие канона из всей панели“) на нефильтрованных данных прочитается как опровергнутый, хотя это артефакт обрыва.»\n\nЧТО НАДО СНЯТЬ ИЛИ ПОПРАВИТЬ В ИСХОДНОЙ ФОРМУЛИРОВКЕ:\n1. Заголовок «A4 стоит на усечённой базе» к −53 отношения не имеет. База A0 стоит по ОБЕ стороны парной дельты (BANK.coverage(src, base_a0) против BANK.coverage(src, text_of('A4'))) и сокращается точно. Из двух проигравших единиц усечённую базу имеет только 41599f30df (tp2-edit-E-deepseek-v4-flash-41599f30df, finish=length, 5759 знаков); у f6da9f76b2 база finish=stop, 7661 знак. Весь −53 порождён обрывом ВЫХОДА A4, а не входа.\n2. Усечённая база — ОБЪЯВЛЕННОЕ ограничение, а не находка: 22-tenant-panel.md:1288-1290 поимённо называет ровно эту клетку («одна клетка стоит в БАЗЕ ВСЕХ КОНТРАСТОВ»), пре-рег Д0.6 (23-editor-tier.md:826-829) её цитирует. Требование «base_a0 должен смотреть на finish» — предложение поменять объявленное условие фазы, а не дефект.\n3. Число «+0.042» неверно; правильная величина на подвыборке без двух обрывов +0.047 (0.8864 → 0.9338).\n4. «Печатается как ноль» — пока гипотетически: A4-покрытие не считает ни один скрипт фазы (grep -rn coverage eval/dovodka/ даёт только строку докстринга canon.py:13). Это ловушка для будущего разбора, а не уже напечатанный вывод; переворот случится, только если разбор проигнорирует и Д0.6, и собственный прецедент canon.py:162-169.\n5. Факт «A4 несёт 2 клетки finish=length против нормы Д0.6» уже найден (Д-4); новое здесь — только количественное следствие (ноль по канон-оси).\n6. Починка «дать фиксеру потолок выхода ОТ ДЛИНЫ ВХОДА вместо константы 16000» направлена в противоположную сторону и сделает обрывы чаще: content вышел 2548 и 5441 знак при 16000 completion_tokens, из которых 15046/14013 — reasoning. Лечится подъёмом потолка/ретраем, не понижением. Предложение «исключить единицы с обрезанным A0» тоже неполно — оно снимает лишь одну из двух плохих клеток.\nТяжесть: не «критично/деньги впустую» ($0.0316 двух клеток), а «ловушка разбора» — нефильтрованная канон-ось арма A4 читается как нулевая.",
|
||
"why": "ПРОВЕРЕНО ИСПОЛНЕНИЕМ, ничего не покупалось.\n\n1) Инвентарь A4: `python -c` по ~/books/dovodka/dv-a-a4-*.json — 22 клетки, ровно две с finish=length: dv-a-a4-41599f30df.json (content 2548 знаков, cost 0.015691) и dv-a-a4-f6da9f76b2.json (5441, 0.015945). Метаданные обеих: completion_tokens=16000, reasoning_tokens 15046 и 14013, places 7 и 4. Совпадает с уликой находки.\n\n2) Потолок: eval/tenant_panel/roster.py:113 `def call_kwargs(model, msgs, max_out: int = 16000, ...)`, строка 120 `kw[\"max_tokens\"] = max_out`; contour.py:266-268 зовёт `ROSTER.call_kwargs(FIXER, fix_msgs(...))` без max_out. Подтверждено.\n\n3) Парный пере-счёт покрытия (мой скрипт, импорт contour.py как модуля, BANK.coverage из eval/tenant_panel/bank.py:217, база = m.base_a0(uid), выход = m.text_of('A4',uid), по всем 22 купленным единицам):\n TOTAL A0=1116 A4=1116 den=1271 → cov0=0.8780 cov4=0.8780; gain=+53, loss=−53, net=0.\n Поштучно: 41599f30df 62→27 (−35), f6da9f76b2 63→45 (−18), остальные от +0 (b2a7464dbd) до +7 (c73f4857e7, d1e353d569).\n Без двух обрывов: A0=991 A4=1044 den=1118 → 0.8864 → 0.9338 (+0.047, а не +0.042).\n Все числа находки воспроизвелись точно, кроме «+0.042» и «+1…+7 на 20 единицах» (одна из 20 даёт +0).\n\n4) Опровержение причинной части: тот же скрипт печатает finish входа A0 по каждой единице. У 41599f30df вход tp2-edit-E-deepseek-v4-flash-41599f30df.json = finish=length, 5759 знаков (черновик tp2-draft-D-deepseek-v4-flash-41599f30df.json = stop, 6767 — цифры находки верны). Но у f6da9f76b2 вход A0 = finish=stop, 7661 знак. То есть «усечённая база» есть у ОДНОЙ из двух проигравших единиц, и она в парной дельте сокращается: base_a0 подставляется и как измеряемый вход, и как основа выхода.\n\n5) Опровержение «не сказано в докax»: docs/experiments/22-tenant-panel.md:1288-1290 — «одна клетка стоит в БАЗЕ ВСЕХ КОНТРАСТОВ. tp2-edit-E-deepseek-v4-flash-41599f30df … на единице 41599f30df каждый контраст обеих фаз сравнивался ПРОТИВ оборванного текста»; таблица 22-tenant-panel.md:1271 даёт ей 5759 знаков и $0.015727. docs/experiments/23-editor-tier.md:826-829 (Д0.6) это цитирует. Условие объявлено.\n\n6) «Печатается как ноль» — кода нет: `grep -rn \"coverage\" eval/dovodka/` даёт единственный хит canon.py:13 (докстринг). Ни contour.py, ни runs.py, ни canon.py не считают покрытие A4. `grep -rn \"finish\" eval/dovodka/*.py` — гейта на finish в фазе нет нигде, кроме canon.py:162-169 (исключение обрезанных R0).\n\n7) Кэш подтверждён на двух уровнях: contour.py:245 `if text_of(arm, uid).strip(): continue` (обрезанный content непустой → единица пропускается) и eval/tenant_panel/money.py:227-229 `f = OUT/f\"{tag}.json\"; if f.exists(): return json.loads(...)`. Пере-запуск эти клетки не пере-купит без ручного удаления файлов — часть находки верна."
|
||
}
|
||
},
|
||
{
|
||
"title": "Батарея в A1 не заработает и после починки вызова: цикл извлечения флагов ищет числа на верхнем уровне, а run_unit возвращает только вложенные словари",
|
||
"severity": "важно",
|
||
"evidence": "contour.py:118-121 `for k, v in (r or {}).items(): if isinstance(v, (int, float)) and v ...`. probe10.py — прямой корректный вызов `B.run_unit(B.Unit(source=..., draft=d, final=d, cards=B.load_cards()))` возвращает 9 ключей, ВСЕ типа dict: palladius={'nonconformant_text': 3, …}, cjk_leak={'han_chars': 0, …}, ty_vy={'mixed_in_unit': True, …}, typography={…}. Ненулевых числовых значений верхнего уровня — ноль. Так же читает батарею и tenant_panel/editors.py:220-221 — через r['cjk_leak']['han_chars'].",
|
||
"consequence": "Известная Д-2 указывает на неверный аргумент (dict вместо Unit). Если чинить только её, `flags_of` вернёт РОВНО столько же флагов, сколько сейчас (только канон-гейт), а арм A1 останется «канон-гейт» под вывеской «батарея + канон-гейт» — и выглядеть будет починенным. При этом батарея на первой же единице находит настоящие места (palladius.nonconformant_text=3, ty_vy.mixed_in_unit=True), которых фиксер не видел ни разу.",
|
||
"fix": "Чинить обе вещи одним куском: передавать battery.Unit И разворачивать вложенные словари в флаги по явному списку метрик; после починки пере-купить A1 целиком, потому что арм менялся не в номинале, а в содержании.",
|
||
"verdict": {
|
||
"line": "код-харнесса",
|
||
"refuted": false,
|
||
"corrected": "Батарея в A1 требует ТРЁХчастной починки, а не одной: (1) `contour.py:118` передаёт `dict` вместо `battery.Unit` → AttributeError (это Д-2); (2) `contour.py:119-121` фильтрует `isinstance(v,(int,float))` по ВЕРХНЕМУ уровню, а `battery.run_unit` (`eval/role_topology/battery.py:515-526`) возвращает 9 ключей, каждый — результат `check_*(...)->dict`, поэтому числовых значений верхнего уровня нет НИ ОДНОГО (проверено на всех 32 единицах: суммарно 0 ненулевых числовых верхнего уровня); (3) наивный `B.Unit(source=…, draft=d, final=d)` оставляет `bank_dst` и `cards` пустыми, из-за чего банк-плечо палладия (`nonconformant_bank`) и весь `check_gender` инертны (`gender={'checked':0,'mismatched':0}`). Разворачивать вложенные словари можно ТОЛЬКО по явному списку метрик с порогами: сплошное разворачивание даст мусорные «места» вроде `typography.lines=69`, `translationese.sentences=90`, `palladius.name_candidates=80`, а `ty_vy.mixed_in_unit` истинен на 27 из 32 единиц (то есть как безусловный флаг это заливка шумом, а не место). Реальные сигналы скромнее заявленного: `palladius.nonconformant_text>0` — на 11 из 32 единиц. Вывод, который находка меняет, подтверждаю: починка одного аргумента даст РОВНО тот же выход, что сейчас, и все 30 купленных клеток A1 останутся «канон-гейт» под вывеской «батарея + канон-гейт» (docs/experiments/23-editor-tier.md:726,800), причём уже выглядя починенными.",
|
||
"why": "Проверил исполнением, а не по формулировке.\n(1) Типы возврата. `eval/role_topology/battery.py:515-526` — `run_unit` собирает 9 ключей из `check_palladius/cjk_leak/typography/yo/translationese/numbers/ty_vy/gender/noop`, и все они объявлены `-> dict` (`battery.py:133,166,182,215,238,309,361,377,481`). Прямой прогон на реальном черновике: типы всех 9 значений = dict, `числовых верхнего уровня ненулевых: []`. По всем 32 единицам суммарно `ненулевых ЧИСЛОВЫХ значений верхнего уровня: 0` (мой скрипт /tmp/claude-1000/-home-ubuntu-projects-textmachine/565edf3f-c90e-4aaf-8418-c2ec250acedc/scratchpad/pr2.py на eval/.venv/bin/python). Значит фильтр `contour.py:120` `isinstance(v,(int,float)) and v` не пропустит ничего и после починки аргумента — заявленное последствие верно.\n(2) Улика по строкам точна: `contour.py:118` `B.run_unit(dict(uid=…, source=…, text=draft))`, `:119-121` цикл по верхнему уровню, `:122-123` голый `except Exception: pass`. Текущий вызов на каждой единице даёт `AttributeError: 'dict' object has no attribute 'final'` (воспроизвёл на 6 единицах подряд).\n(3) Соответствие купленному сырью — самое сильное подтверждение. Пересчитал `flags_of` для всех 30 купленных клеток A1 и сверил с полем `places` в ~/books/dovodka/dv-a-a1-*.json: `совпало (места = ровно канон-гейт): 30, расхождений: 0`. То есть в оплаченном сырье батарейных мест нет ни одного, а места = ровно канон-гейт.\n(4) Второй потребитель батареи читает её ИМЕННО через вложенность: `eval/tenant_panel/editors.py:220-221` — `r['cjk_leak']['han_chars']`, `r['typography']['violations']`. Контур — единственное место, где батарею читают плоско.\n(5) Объявленным ограничением это не является: docs/experiments/23-editor-tier.md:726 и :800 объявляют A1 как «детерминированные флаги (батарея + канон-гейт)»; докстринг `flags_of` (contour.py:112) говорит то же. Единственная оговорка в коде — комментарий `contour.py:123` «батарея не обязана знать наш вход», но он оправдывает глотание исключения, а не отсутствие батарейной оси. Ни в отчёте, ни в пре-реге про плоское чтение вложенного результата не сказано.\n(6) Дубликатом Д-2 не считаю: Д-2 фиксирует факт «0% батареи» и указывает причину «неверный аргумент»; новая находка показывает, что этой причины НЕ ХВАТАЕТ, и починка по Д-2 даст ложную зелень.\nОграничения моей проверки: ничего не покупал и не правил, `--run` не трогал; чужой probe10.py в репозитории отсутствует (`find . -name \"probe10*\"` пусто), поэтому его вывод я воспроизвёл своими скриптами независимо."
|
||
}
|
||
},
|
||
{
|
||
"title": "canon_gaps врёт формулировкой в 78% случаев: он флагует «термин передан не канонной формой либо пропущен» там, где канон в выходе ЕСТЬ, просто реже, чем термин в исходнике",
|
||
"severity": "важно",
|
||
"evidence": "contour.py:98-108 и текст флага contour.py:116/261. probe4/probe5.py: на 32 черновиках (вход A1) канон-гейт даёт 74 флага, из них 58 (78%) — случаи, где канонная форма в выходе встречается ≥1 раза; на входах A4 (A0) — 69 флагов, из них 66 (96%). То есть фиксеру в 78–96% случаев говорят «пропущен» о термине, который стоит в тексте. Своя же canon.py:11-18 разводит эти величины дословно: «ПОКРЫТИЕ … падает и когда термин заменён местоимением — а второе есть норма русской прозы». Плюс мелочь того же происхождения: `min(len(re.findall(...)), n) < n` (стр. 106) — `min` здесь no-op, условие эквивалентно `len(findall) < n`, кап скопирован из bank.coverage, где он осмыслен.",
|
||
"consequence": "Детектор, задающий содержание армов A1 и A4 целиком, систематически требует ВСТАВИТЬ имя туда, где русская проза законно поставила местоимение — то есть подталкивает фиксер портить текст ровно на той оси, по которой его потом судят на художественность. Пре-рег Д0.6 требует: «всякий классификатор, чьё число идёт в отчёт, обязан печатать рядом свою частоту срабатывания на случайном входе» — canon_gaps не печатает ничего, а его числа (places) уже уехали в сырьё 52 клеток.",
|
||
"fix": "Разделить два класса — «канона нет вовсе» (16 из 74 флагов) и «встречается реже» — и в фиксер отдавать первый; для второго дать формулировку по факту либо не флагать вовсе. Напечатать ложноположительную частоту рядом с числом, как требует Д0.6, и пере-снять places.",
|
||
"verdict": {
|
||
"line": "код-харнесса",
|
||
"refuted": true,
|
||
"why": "Числа находки воспроизвёл своим $0-пробником (импорт живого contour.canon_gaps, покупок нет): A1 — 74 флага, 16 «канона нет вовсе», 58 = 78% «есть, но реже»; A4 на 22 КУПЛЕННЫХ клетках — 69 флагов, 66 = 96% (сумма поля places в ~/books/dovodka/dv-a-a4-*.json ровно 69; на всех 32 единицах вышло бы 82). Мультимножество places у A1 совпало с моим счётом поклеточно. min(len(findall),n)<n при contour.py:106 действительно no-op, кап скопирован из осмысленного bank.py:228. Но три несущих утверждения опровергнуты. (1) «Врёт/ложноположительные» — гейт СЧЁТНЫЙ, не эвристика: во всех 74 флагах хотя бы одно упоминание реально передано не канонно (110 таких упоминаний среди 58). Я прогнал ровно тот контроль, которого требует Д0.6 (23-editor-tier.md:836): частота срабатывания на выходе ЧУЖОЙ единицы (нулевая модель) = 65% применимых терминов против 27% на своём входе — прибор ВТРОЕ специфичнее шума, то есть противоположность канон-классификатору canon.py (79% при нулевой 82.5%), из-за которого норма и заведена. (2) «Подталкивает фиксер портить текст» — не замерено автором; замерил я на оплаченном сырье: пере-вставок сверх числа упоминаний в исходнике 2 из 74 (A1) и 2 из 69 (A4), длина выхода A1 +0.3%. Фиксер получает и ИСХОДНИК, и полный ЧЕРНОВИК (contour.py:146-147), то есть видит стоящий в тексте канон сам. А восстановление покрытия — дословный заказ владельца: docs/POLYGON_EXP2223_REDO_SESSION_PROMPT.md:91-94 «Канон-гейт = детерминированная сверка ПОКРЫТИЯ банка … Гейт жёсткий, фиксер обязан канон восстанавливать», «художественность — отдельная ось», «вопрос снят». (3) Объявленность: механизм назван дословно в докстринге самой функции contour.py:99 («чья канонная форма В ВЫХОДЕ встречается реже, чем в исходнике») и в шапке contour.py:19 («сверка ПОКРЫТИЯ»), а canon.py:11-18, который находка приводит как улику, есть письменная декларация этого же свойства фазой — по правилам ревью это исполненная норма, а не находка. Д0.6 связывает «классификатор, чьё число идёт в ОТЧЁТ»: число canon_gaps в отчёт не идёт вовсе (grep: вызовы только на строках 115 и 262, оба — содержание арма), канон-ось отчёта считает bank.coverage. Ни один вывод фазы не двигается, впустую денег не потрачено. Починка из находки разрушительна: оставить только «канона нет вовсе» — это A1 8 клеток из 32 и A4 3 из 32, флаговый арм перестаёт существовать и H-2а становится неизмеримой, вопреки прямому «гейт жёсткий» владельца.",
|
||
"corrected": "Понижается до косметики промта (тяжесть «мелочь», не «важно»): строка флага contour.py:116/261 не сообщает фиксеру, сколько раз канон УЖЕ стоит в выходе, — 29 из 74 флагов A1 суть нехватка ровно ОДНОГО упоминания имени, стоящего в тексте 4-20 раз (напр. 秦风 n=20, m=19). Осмысленная правка — дописать в флаг число попаданий в выходе («в исходнике 20 раз, в переводе канонной формой 19») и заодно снять no-op min() на строке 106. Пере-снимать places, делить флаги на классы и не флагать «реже» НЕЛЬЗЯ: это меняет заказанное владельцем содержание армов и обнуляет A1/A4."
|
||
}
|
||
},
|
||
{
|
||
"title": "Смета ФД-A занижена структурно: фиксер оценён в 0.60× переписа «выход много короче», хотя промт арма требует выдать текст ЦЕЛИКОМ — фактическая цена клетки вдвое-втрое выше прогноза",
|
||
"severity": "важно",
|
||
"evidence": "eval/dovodka/plan.py:56-58 `fixer = 0.60 * edit # точечная починка: тот же вход, выход много короче`, `critic = 2.14 * edit`. Промт того же харнесса, contour.py:134: «Выведи ТОЛЬКО полный текст перевода после правок». `plan.py` печатает фиксер $0.00314, критик $0.01120. Факт по 149 клеткам сырья (медианы): A1 фиксер $0.00686 (выход 5599 ток), A3 фиксер $0.00741 (6956 ток), A4 фиксер $0.00794 (7062 ток), A6 фиксер $0.00888; критик A3 $0.00519, A6 $0.00778. То есть фиксер 2.2–2.8× прогноза, критик 0.46×. Пересчёт объявленной оси Д4 по факту: 32×(0.00686+0.00523+0.00519+0.00741+0.00794) + 16×0.00686 ≈ $1.15 против потолка ФД-A $0.885 (money_d.py:67).",
|
||
"consequence": "Ось Д4 не влезала в свой потолок ещё до первой покупки, и проверить это можно было за $0, сверив множитель с собственным промтом. Отсюда всё наблюдаемое состояние фазы: гард встал на A4 (22 клетки из 32), A2 не куплен вовсе, ФД-A выбрана на 98.5% ($0.871904 из $0.885). Норма money_d.py:16-19 «срабатывание проекционного гарда = СТОП и вопрос владельцу» сработала не на внешнем сюрпризе, а на своей же арифметике.",
|
||
"fix": "Пере-считать plan.py по замеренным ценам клеток фазы (данные уже на диске), напечатать сверку прогноз/факт, и с этой цифрой идти к владельцу за решением по добору A2/A4 — а не резать ось молча.",
|
||
"verdict": {
|
||
"line": "код-харнесса",
|
||
"corrected": "Смета фазы Д структурно занижена по фиксеру, и ось Д4 не влезала в свой потолок ещё ДО первой покупки — но по двум независимым причинам, а не по одной, и масштаб шире объявленного: под $0-нижней границей не влезал ВЕСЬ пакет, а не только ФД-A.\n\n(1) Посылка `plan.py:56` «точечная починка: тот же вход, выход много короче» ложна дважды. Видимый выход фиксера РАВЕН выходу полного переписа: completion − reasoning = 2716 (A1), 2720 (A3), 2648 (A4), 2828 (A6) против 2823 у боевого редактора эксп-22 и 2738 эксп-23 — потому что промт того же харнесса (`contour.py:134`) требует «полный текст перевода», ровно как боевой `backend/prompts/zh-ru/editor.md:13`. Сверх того фиксер ДУМАЕТ больше переписа (медиана reasoning 2883/4236/4414/4874 против 1396–2014) и хуже кэшируется (cached prompt 256 против 2688), так что растут обе половины счёта, а не только выходная. Формулировка улики «выход 5599 ток» неточна: 5599 — это completion вместе с reasoning.\n\n(2) Числа верны (148 платных клеток сырья, не 149): фиксер 2.19× / 2.36× / 2.53× / 2.83× прогноза $0.00314, критик 0.46× (A3) и 0.70× (A6) прогноза $0.01120.\n\n(3) Масштаб ЗАНИЖЕН. Достаточно было $0-нижней границы «фиксер ≥ перепис» (его вход = исходник+черновик+места ⊇ входа редактора, выход тот же полный текст): тогда Д4 = $1.111 > потолка ФД-A $0.885, а ВЕСЬ пакет = $4.837 > санкционированного владельцем потолка $4.50. То есть невыполним был не один фазовый потолок, а пакетный.\n\n(4) Атрибуция последствий поправлена. Гард грунтуется только на A4: `Guarded(\"ФД-A\").afford()` сейчас возвращает «потрачено $0.871904 + ожидание $0.015945 = $0.887849 > потолок $0.885». А НОЛЬ клеток A2 деньгами не объясняется — у него независимая достаточная причина: `contour.py:265` `PR.translator_msgs(src)` при сигнатуре `(src, block, en=False)` даёт TypeError (находка Д-1).\n\n(5) Объявленной нормой это не является. Обещание `plan.py:53-54` «обоснование множителей — в отчёте §Д0; расхождение печатается при закрытии фазы» не исполнено с обеих сторон: `grep \"0\\.60\" docs/experiments/23-editor-tier.md` пуст (есть только 2.14 в цитате владельца, строка 730), а `measured()` читает лишь `~/books/tenant-panel` и `~/books/editor-tier` (`plan.py:26-27`) и никогда `~/books/dovodka` — поэтому `plan.py` СЕГОДНЯ, при 116 замеренных клетках фиксера на диске, всё ещё печатает «фиксер $0.00314 (0.60× переписа)». Отчёт кончается строкой 896 (Д0.10), секции результатов нет; запись в `docs/PROGRESS.md` от коммита 90c23cb про остановку гарда, про A4 22/32 и про ошибку сметы не говорит.",
|
||
"refuted": false,
|
||
"why": "Проверял исполнением, не по формулировке.\n\nЦЕНЫ. `eval/.venv/bin/python eval/dovodka/plan.py` печатает «фиксер $0.00314 (0.60× переписа) · критик $0.01120». Свой скан сырья (медианы по (arm, role, model) из ~/books/dovodka/*.json, 148 платных клеток): A1 fixer n=30 $0.00686 · A3 critic n=32 $0.00519 · A3 fixer n=32 $0.00741 · A4 fixer n=22 $0.00794 · A6 critic n=16 $0.00778 · A6 fixer n=16 $0.00888. Отношения к прогнозу: фиксер 2.19–2.83×, критик 0.46× и 0.70×. Цифры находки совпали с моими.\n\nПРИЧИНА (посылка множителя). `contour.py:134` FIX_HEAD: «Выведи ТОЛЬКО полный текст перевода после правок». Боевой редактор `backend/prompts/zh-ru/editor.md:13`: «Выведи ТОЛЬКО отредактированный текст перевода» — та же форма выхода. Медианы токенов из сырья: A1 fixer compl 5599 / reas 2883 → видимый выход 2716; A3 6956/4236 → 2720; A4 7062/4414 → 2648; A6 7702/4874 → 2828; боевой edit (tenant-panel, n=163) 4219/1396 → 2823, editor-tier (n=16) 4752/2014 → 2738. Выход НЕ короче — он равен. Плюс prompt cached 256 у фиксера против 2688 у переписа. Значит дорожают обе половины счёта: посылка «выход много короче» ложна, но ссылка находки на 5599 как на «выход» — это completion вместе с reasoning.\n\nАРИФМЕТИКА ОСИ. Формула плана `plan.py:73-74`: d4 = 32*(fixer+onepass+(critic+fixer)+fixer) + 16*fixer. По факту фазы = $1.1539 при потолке ФД-A $0.885 (`money_d.py:67`) — перебор +$0.269, число находки ($1.15) верно. Отдельно посчитал $0-нижнюю границу, доступную ДО денег (фиксер = перепис $0.00523, критик по заказу владельца 2.14×): Д4 = $1.1113 (+$0.226 сверх потолка), весь пакет = $4.837 > $4.50. То есть вывод находки устойчив и даже сильнее заявленного.\n\nГАРД. `money_d.py --report`: ФД-A $0.871904 / 0.89, ФД-F $0.267825 / 0.28, ПАК $1.139729 / 4.50. Инстанцировал кассу: `Guarded(\"ФД-A\")` с next_model=deepseek-v4-pro → afford() = (False, «потрачено $0.871904 + ожидание $0.015945 = $0.887849 > потолок $0.885»). Остановка A4 подтверждена механизмом, а не со слов.\n\nПОПЫТКИ ОПРОВЕРЖЕНИЯ, КОТОРЫЕ НЕ УДАЛИСЬ. (а) «Это объявленное ограничение»: `plan.py:53-54` называет множители прогнозом и ссылается на §Д0 — но `grep -n \"0\\.60\" docs/experiments/23-editor-tier.md` не даёт ни одного хита (2.14 есть, строка 730, в цитате владельца), то есть кросс-ссылка ложная; обещанная сверка прогноз/факт не реализована — `measured()` глобает только `~/books/tenant-panel` и `~/books/editor-tier` (`plan.py:26-27`), сырьё фазы не читает, и прогон plan.py сегодня всё ещё печатает $0.00314. (б) «Уже записано в докладе»: отчёт обрывается на строке 896 (Д0.10, `wc -l` = 896), секции результатов нет; дифф `git show 90c23cb -- docs/PROGRESS.md` про гард, про A4 22/32 и про смету молчит. (в) «Причина A2 — деньги»: неверно, `contour.py:265` `PR.translator_msgs(src)` при сигнатуре `prompts.py:114` `(src, block, en=False)` падает TypeError до всякой кассы — это отдельная причина (Д-1), и в этой части формулировку последствия я поправил.\n\nВывод меняется: ось Д4 объявлена НЕСУЩЕЙ при n=32 на арм (Д0.3), а куплено A4 22/32 и A2 0/32; при верной цене клетки заявленный дизайн не покупался ни за потолок ФД-A, ни за пакетный $4.50."
|
||
}
|
||
},
|
||
{
|
||
"title": "A1 получает втрое более слабое лечение на новой половине оси: банк на новых 16 единицах вдвое-втрое реже, и медиана флагов падает с 3 до 1",
|
||
"severity": "важно",
|
||
"evidence": "probe8.py: старые 16 единиц — терминов банка в единице медиана 11, упоминаний медиана 71, флагов A1 медиана 3.0 (n=15); новые 16 — терминов 5, упоминаний 28, флагов A1 медиана 1.0 (n=15). Банк один на обе половины (~/books/tenant-panel/bank.json, 22 термина, майнинг bank.py:63-64 по source_text() всех 40 глав пула). Две единицы получили 0 флагов и клетку A1 не получили вовсе (474f822806 — старая, 9b16c9c9a7 — новая, contour.py:263-265).",
|
||
"consequence": "Ось Д4 объявлена как n=32 с MDE 1.29 (Д0.3), но арм A1 на половине этих единиц — это фиксер с одной инструкцией, а с учётом мёртвой батареи (находка 3) другой у него и не будет. Правило non-inferiority Д0.4 («нижняя граница ДИ выше −1.50») будет считаться по 30 единицам, половина которых почти не лечена: результат «не хуже A0» на таком материале означает в основном «мы почти ничего не сделали», а не свойство контура.",
|
||
"fix": "Напечатать распределение числа мест по армам и половинам оси рядом с вердиктом; либо считать A1/A0 стратифицированно (старые/новые), либо объявить границу интерпретации в отчёте до чтения перевесов.",
|
||
"verdict": {
|
||
"line": "код-харнесса",
|
||
"corrected": "A1 (и A4) получают втрое более слабую дозу лечения на новой половине оси Д4, и причина — НЕ свойство материала, а УСТАРЕВШИЙ БАНК: он намайнен только по главам эксп-22, поэтому канон-гейт структурно слеп на новых главах.\n\nПроверено моим пере-счётом (не по probe8.py — такого файла в репо нет):\n* Дозa. Старые 16 единиц: терминов банка в единице медиана 11, упоминаний 71, флагов A1 медиана 3.0; новые 16: 5, 28, 1.0. Числа сходятся с полем `places` реально купленных клеток бин-в-бин: `dv-a-a1-*.json` даёт 11×1, 7×2, 5×3, 5×4, 1×6, 1×8 = 30 клеток, старые n=15 медиана 3, новые n=15 медиана 1.\n* Механизм — ИСПРАВЛЕНИЕ улики. Утверждение «майнинг по source_text() всех 40 глав пула» ЛОЖНО. `bank.mine()` по текущему пулу (`material.chapters()` = 40 из 42) воспроизводит лишь 15 из 26 записей банка и выдаёт 11 новых имён (北冥朔 戚红颜 曹秋道 柳玄 皇甫玉香 霍尊 青龙国 瀛国 苏晴 目光 青龙), которых в банке нет вовсе; майнинг, ограниченный главами 3–18 (ровно главы старых единиц), воспроизводит все 26 записей банка (22 термина + 4 dropped) без единого промаха. Банк заморожен на старой половине; новые единицы — главы 22–42, их персонажи в банк не попали. Это артефакт прибора, а не «на новом материале чинить нечего».\n* Контроль, что материал не «чище». Критик A3 банка не использует: мест старые медиана 46.5, новые 35.5 — 1.31×, а не 3×. Разрыв доза-контура держится на банке.\n* МАСШТАБ ШИРЕ, чем в находке. Ровно та же слепота бьёт по A4 (`canon_gaps` — единственный источник его мест): `dv-a-a4-*.json` старые n=15 медиана 4, новые n=7 медиана 2. A4 — арм, целиком состоящий из канон-фиксера, и прогноз Д0.9.2 («A4 даст лучшее покрытие канона панели») читается на новой половине по банку, который её глав не видел.\n* Последствие — точнее, чем в находке, и не одностороннее. Контраст A1/A0 считается по 30 парам (две единицы с 0 флагов клетку не получили: 474f822806 гл.16 старая, 9b16c9c9a7 гл.34 новая, contour.py:263-265) и смешивает два режима дозы, различающихся втрое. Пострадает ЛЮБОЙ исход Д0.4, а не только «не хуже»: точечная оценка становится средним по гетерогенной популяции, а разнородность лечения раздувает внутриармовый sd относительно однородного прайора sd 2.12, из которого Д0.3 вывел MDE 1.29 — то есть объявленная мощность оси оптимистична.\n* Починка (расщепление по половинам рядом с вердиктом) — не новшество, а уже принятая в этом паке практика: 23-editor-tier.md:171-177 печатает такое расщепление для оси R2/R0 и прямо пишет «различаются они ещё и составом глав». Для Д4 её просто не сделали.",
|
||
"refuted": false,
|
||
"why": "ПОПЫТКА ОПРОВЕРЖЕНИЯ ПРОВАЛИЛАСЬ ПО СУЩЕСТВУ, НО ОДНА УЛИКА НАХОДКИ ЛОЖНА.\n\nprobe8.py в репо нет (`find /home/ubuntu/projects/textmachine -name probe8.py` — пусто), поэтому все числа пере-считаны своими командами.\n\n1) Доза воспроизводится ТОЧНО. Загрузил contour.py и прогнал flags_of() по всем 32 единицам ($0, без сети):\n old n 16 terms med 11.0 ment med 71.0 flags med 3.0 flags [0,1,1,2,2,3,3,3,3,3,4,4,4,4,4,6]\n new n 16 terms med 5.0 ment med 28.0 flags med 1.0 flags [0,1,1,1,1,1,1,1,1,1,2,2,2,2,2,8]\nСверил с реально купленным сырьём (поле `places` в ~/books/dovodka/dv-a-a1-*.json, 30 файлов): [1×11,2×7,3×5,4×5,6,8]. Разложение по половинам совпадает бин-в-бин с пере-счётом (old 2×1,2×2,5×3,5×4,1×6; new 9×1,5×2,1×8). Пере-счёт = то, что куплено. Медианы у меня при n=16, у автора n=15 — медианы те же.\n\n2) Обе «нулевые» единицы подтверждены поимённо: zero-flag units [('474f822806','old',16), ('9b16c9c9a7','new',34)], файлов dv-a-a1-474f822806.json / dv-a-a1-9b16c9c9a7.json не существует. Ветка молчаливого пропуска — contour.py:263-265 (`мест нет — чинить нечего, клетка не покупается`), номера строк проверены sed. Автор прав и здесь.\n\n3) ГЛАВНАЯ ОШИБКА НАХОДКИ — в механизме. Улика утверждает «майнинг bank.py:63-64 по source_text() всех 40 глав пула», то есть банк одинаково видит обе половины. Проверил исполнением:\n - `material.chapters()` = 40 (из 42 на диске, SE_DROP_TOP=2) — «40 глав пула» как число верно;\n - но `bank.mine()` по этим 40 главам даёт кандидатов, из которых в банке ОТСУТСТВУЮТ 11: 北冥朔 戚红颜 曹秋道 柳玄 皇甫玉香 霍尊 青龙国 瀛国 苏晴 目光 青龙; и наоборот, 11 записей банка (世子 公子 史仁 天阳城 庭院 张天彻 苏无视 谷河 陈伯 青州 风老) текущим майнингом не находятся вовсе. Совпадение 15 из 26 — банк НЕ мог быть получен этим майнингом;\n - подменил source_text() на главы 3–18 (ровно главы старых единиц) и пере-намайнил: `mined on ch3-18 : 26 of 26 bank entries reproduced`, `missing: []`. Банк воспроизводится из старой половины ПОЛНОСТЬЮ и точно.\nГлавы старых единиц [3..18], новых [22,25,26,...,42] — непересекающиеся по построению (editor_tier/material.py:55-80 исключает главы эксп-22 целиком). Итог: банк заморожен на старой половине, канон-гейт на новых главах слеп структурно. Находка ошиблась в улике в СВОЮ невыгоду — реальная причина хуже заявленной.\n\n4) Проверил альтернативное объяснение «новый материал просто чище» — не проходит. Критик A3 банком не пользуется (crit_msgs строит места смыслом; contour.py:145-160), и его места по половинам: old n=16 медиана 46.5, new n=16 медиана 35.5 = 1.31×, тогда как канон-флаги дают 3×. Материал новой половины беднее терминами банка, а не проблемами.\n\n5) Проверил, не объявлено ли это ограничением. Пре-рег Д0 (23-editor-tier.md:719-896) прочитан целиком: Д0.3 объявляет Д4 как n=32, sd 2.12, MDE 1.29; Д0.4 — правило non-inferiority «нижняя граница ДИ выше −1.50»; Д0.5 — «32 единицы (16 эксп-22 + 16 эксп-23), база одна и замороженная». Ни слова о неравной дозе флагов, о слепоте банка на новых главах или о стратификации A1. Д0.10 исключает «банк как фактор» — это обещание НЕ варьировать банк между АРМАМИ (оно выполнено), а не заявление о неравном покрытии между ЕДИНИЦАМИ. Грепы по 23-editor-tier.md, POLYGON_EXP2223_REDO_SESSION_PROMPT.md и eval/dovodka/requirements.md на «доза / покрытие банка / 30 из 32 / мест нет» дали ноль попаданий. Докстринг contour.py:1-22 объявляет A1 как «батарея + канон-гейт» и об асимметрии молчит.\n\n6) Масштаб находки занижен: A4 поражён тем же дефектом (его места — ТОЛЬКО canon_gaps, contour.py:261-262), сырьё dv-a-a4-*.json даёт old n=15 медиана 4 против new n=7 медиана 2. Находка называет только A1.\n\n7) Формулировка последствия односторонняя: она пугает ложным «не хуже», но смесь двух режимов дозы портит и вердикт «хуже» — оценка становится средним по гетерогенной популяции, а гетерогенность лечения раздувает sd относительно однородного прайора 2.12, на котором построен MDE 1.29 (Д0.3). Это меняет не знак вывода, а его читаемость — то есть находка проходит планку «меняет вывод».\n\nМеняется ли хоть один вывод: да. Вердикт Д0.4 по A1 (и прогноз Д0.9.2 по A4) без расщепления по половинам приписывает контуру свойство, которое на половине единиц измерялось прибором, не видящим её словаря."
|
||
}
|
||
},
|
||
{
|
||
"title": "cmd_run не проверяет `skipped` у возвращённой записи — после срабатывания потолка цикл идёт дальше по единицам и следующим армам",
|
||
"severity": "мелко",
|
||
"evidence": "contour.py:266-268 и 285-287: результат MONEY.purchase никуда не присваивается. buy.py:137-140 при отказе гарда возвращает `dict(..., skipped=True)` и печатает причину. Для сравнения — tenant_panel/editors.py:183-185 `if rec.get(\"skipped\"): print(\"⛔ потолок Ф3 — стоп\"); return`. Наблюдаемый след: A4 остановлен на 22 из 32, то есть по 10 оставшимся единицам цикл прошёл вхолостую с печатью стопа на каждой.",
|
||
"consequence": "Норма money_d.py:16-19 («срабатывание гарда = СТОП и вопрос владельцу») в харнессе не реализована. Для A3/A6 отказ гарда на критике даёт вдобавок ложную диагностику: contour.py:277-279 напечатает «критик не отдал файл — арм пропущен» вместо «кончился потолок», и в отчёт уедет не та причина.",
|
||
"fix": "Проверять rec.get('skipped') и выходить из cmd_run с явным сообщением о фазе и потолке; отделить «файла нет из-за потолка» от «файла нет из-за провода».",
|
||
"verdict": {
|
||
"line": "код-харнесса",
|
||
"refuted": false,
|
||
"why": "ПРОВЕРЕНО ИСПОЛНЕНИЕМ, механизм подтверждён, но три детали находки неверны.\n\nЧТО ПОДТВЕРДИЛОСЬ.\n1) Результат покупки действительно нигде не проверяется: contour.py:256-257, 266-268, 273-275, 285-287 — все четыре вызова `MONEY.purchase(...)` без присваивания (нумерованный вывод `grep -n \"\" contour.py | sed -n 255,300p`). То есть НЕ два места, как в улике, а ЧЕТЫРЕ (добавляются A2-однопроходка 256-257 и критик 273-275) — это в пользу находки.\n2) Отказ гарда действительно даёт `skipped` без исключения: buy.py:143-146 `ok, why = led.afford(); if not ok: print(why); return dict(..., skipped=True, ..., finish=\"skipped\")`. Обёртка money.py:246-250 отдаёт эту запись наверх без изменений (`finish` != \"error\" ⇒ `err=\"\"` ⇒ `return rec`). Ретрай-цикл и замок не текут (money.py:255-256 `finally` снимает lock).\n3) Эталон сравнения на месте: tenant_panel/editors.py:183-185 `if rec.get(\"skipped\"): print(\"⛔ потолок Ф3 — стоп\"); return`.\n4) Это НЕ объявленное ограничение: `grep -rn \"гард|потол|СТОП|skipped\" eval/dovodka/requirements.md eval/dovodka/contour.py` — в contour.py про потолок ни слова (единственный хит — ассерт каталога кассы, строка 66), в requirements.md R3-R6 говорят о потолках и стоп-правиле ДО покупок, но нигде не сказано, что цикл после срабатывания гарда идёт дальше. Норма money_d.py:16-19 в харнессе действительно не реализована.\n5) Гард сейчас реально закрыт (запуск с импортом contour, $0): ФД-A `spent 0.871904, ceiling 0.885, afford (False, '[СТОП ФД-A ...] $0.871904 + $0.015945 = $0.887849 > $0.89')`; ФД-F `spent 0.267825, ceiling 0.283, afford False`.\n\nЧТО НЕВЕРНО В ФОРМУЛИРОВКЕ.\nа) Улика `buy.py:137-140` промахивается: там конец докстринга и кэш-чек (`f = OUT / f\"{tag}.json\"; if f.exists(): return ...`). Отказ гарда — buy.py:143-146.\nб) Масштаб «по 10 оставшимся единицам цикл прошёл вхолостую с печатью стопа на каждой» завышен на единицу. Посчитал сам: units()=32, A4 куплено 22, недостающих 10; из них у 474f82 `canon_gaps=0`, то есть единица уходит в ветку contour.py:263-265 «мест нет — клетка не покупается» и гарда не касается вовсе. Остальные 9 (13c5f5, b0a5ef, e40cdf, 63ab55, debb2c, 89614f, 7d0258, 372784, fb9ed5, gaps=1..2) доходят до покупки и печатают стоп. Итого 9, не 10.\nв) Ложная диагностика A3/A6 — ЛАТЕНТНАЯ, не наблюдавшаяся: в ~/books/dovodka лежат A3 critic 32 + fixer 32 и A6 critic 16 + fixer 16, ни одна клетка критика не была отказана гардом. Плюс «не та причина» не молчалива: buy.py:145 печатает `[СТОП ФД-X ...]` непосредственно ПЕРЕД строкой contour.py:278 «критик не отдал файл».\n\nЧТО НЕ МЕНЯЕТСЯ. Денег это не стоит и вывода не двигает: `afford()` (money.py:149-159) проверяет и фазовый, и ПАКЕТНЫЙ потолок перед КАЖДЫМ вызовом, поэтому продолжающийся цикл не может перерасходовать; десять недостающих клеток A4 не появились бы и при немедленном выходе — их блокирует сам гард. Ущерб чисто операционно-диагностический, что согласуется с заявленной тяжестью «мелко».",
|
||
"corrected": "cmd_run не проверяет `skipped` у записи, возвращённой MONEY.purchase, — после отказа проекционного гарда цикл идёт дальше по единицам и по следующим армам (у которых свой фазовый потолок). Все четыре платных вызова харнесса безрезультатны: contour.py:256-257 (A2), 266-268 (A1/A4-фиксер), 273-275 (критик), 285-287 (A3/A6-фиксер). Отказ гарда — buy.py:143-146 (`print(why)` + `dict(..., skipped=True, finish=\"skipped\")`), запись доходит наверх нетронутой через money.py:246-250; эталон обработки — tenant_panel/editors.py:183-185. Наблюдаемый след: A4 остановлен на 22 из 32, из 10 недокупленных единиц 9 дошли до вызова и напечатали стоп, а десятая (474f82, canon_gaps=0) отсеялась раньше веткой contour.py:263-265. Деньги при этом НЕ теряются — afford() (money.py:149-159) сторожит и фазовый, и пакетный потолок перед каждым вызовом, и десять клеток A4 не купились бы при любом поведении цикла. Последствие ограничено операционным: норма money_d.py:16-19 («срабатывание гарда = СТОП и вопрос владельцу») в харнессе не реализована, а для A3/A6 отказ гарда на критике латентно даёт вторую, неверную строку диагностики (contour.py:277-279 «критик не отдал файл — арм пропущен») сразу после верной строки стопа; на купленном сырье это не сработало ни разу (A3 32/32 критиков, A6 16/16). Тяжесть — мелко. Починка: проверять rec.get('skipped') и выходить из cmd_run с явным сообщением о фазе и потолке; отделить «файла нет из-за потолка» от «файла нет из-за провода»."
|
||
}
|
||
},
|
||
{
|
||
"title": "Половина единиц оси Д4 не приколота манифестом: новые 16 пересчитываются из каталога глав при каждом запуске",
|
||
"severity": "мелко",
|
||
"evidence": "editor_tier/material.py:55-93 `units_new` отбирает из `M22.chunks()` по длине на лету, манифеста не читает; ~/books/editor-tier/manifest.json не существует (`ls` → No such file). Старые 16 приколоты: tenant_panel/material.py:199-232 читает ~/books/tenant-panel/manifest.json и отдаёт uid оттуда, а его докстрока прямо описывает цену отсутствия прикола: «доскачка глав для следующего пака СДВИНУЛА единицы уже сданного эксп-22 … Детерминизм прогона — цель 6 канона владельца». Сейчас расхождения нет: базы найдены у 32/32 (`contour.py --plan`).",
|
||
"consequence": "Любая доскачка или пере-нарезка глав молча меняет половину оси Д4: uid поедут, купленные 149 клеток осиротеют, а `--plan` покажет недокупленные армы и предложит купить их заново — за деньги и на другом материале.",
|
||
"fix": "Записать манифест новых 16 uid рядом с сырьём пака 23 и читать units_new через него тем же приёмом, что units_zh; в селфтест contour.py добавить сверку набора uid с манифестом.",
|
||
"verdict": {
|
||
"line": "код-харнесса",
|
||
"refuted": false,
|
||
"why": "ЯДРО НАХОДКИ ПОДТВЕРДИЛОСЬ ИСПОЛНЕНИЕМ, ДВА ЕЁ УТВЕРЖДЕНИЯ — НЕТ.\n\nПодтверждено:\n1) Ось Д4 = 16 приколотых + 16 пересчитываемых: `eval/dovodka/contour.py:77` → `return P22.M.units_zh() + MAT.units_new()`.\n2) Старые 16 приколоты: `eval/tenant_panel/material.py:199-207` (`_pinned_uids()` читает `OUT/\"manifest.json\"`), `units_zh` при непустых pins возвращает ИМЕННО их (209-232). Манифест на диске есть: `ls -la ~/books/tenant-panel/manifest.json` → 1587 байт, ключ `zh.uids` = 16 uid.\n3) Новые 16 не приколоты: `eval/editor_tier/material.py:55-93` — манифест не читается вовсе, отбор из середины длин на лету (`lo = (len(keys) - n) // 2`, :78) по `M22.chunks()`. `ls -la ~/books/editor-tier/manifest.json` → No such file.\n4) Не объявлено: `grep -n \"манифест\\|прикол\" docs/experiments/23-editor-tier.md` даёт 4 хита (370, 413, 514-515) — все про эксп-22; §11:511-515 объявляет БОЛЕЗНЬ и починку только для старых 16. Пре-рег Д0.5:796 говорит «база одна и замороженная» — это про черновик, не про uid. При этом норму формулирует сам инструмент фазы: `eval/dovodka/material_ja.py` докстрока п.3 «манифест: единицы прикалываются к файлу, иначе докачка материала молча сдвинет уже купленный замер». То есть норма фазы своя и на новые 16 не применена.\n5) Зависимость от каталога проверена симуляцией ($0, на КОПИИ каталога глав в скретчпаде, оригинал не тронут; скрипты /tmp/.../scratchpad/drift/sim2.py, sim5.py): каталог 42→38 глав — `units_zh` не сдвинулось, `units_new` сдвинулось, осиротело 4/16 uid; +2 «докачанные» главы обычной длины — 2/16 uid заменились (главы 22,35 → 43,44).\n\nЧТО В НАХОДКЕ НЕВЕРНО:\nа) Масштаб «ЛЮБАЯ доскачка молча меняет ПОЛОВИНУ оси» — опровергнуто: sim3.py/sim4.py, +8 глав (кандидатов 22→30, окно lo 3→7) дали 0/16 изменений, потому что новые чанки легли ВНЕ середины распределения. Сдвигаются только единицы у краёв съехавшего окна: наблюдал 0/16, 2/16 и 4/16, а не 16/16.\nб) «Купленные 149 клеток осиротеют… `--plan` предложит купить их заново — за деньги и на другом материале» — опровергнуто дважды. По деньгам: `contour.py:248-250` при отсутствии базы печатает «базы нет — пропуск» и НЕ покупает, а `cmd_selftest` (:201-202, «якорный черновик есть у всех», объявлен обязательным ДО первой покупки, :188) на съехавшем uid валится громко. По числу: пересчёт сырья (`~/books/dovodka/*.json`, 148 клеток-словарей) даёт на новых-16 всего 54 клетки $0.3897, на старых-16 — 94; под риском сиротства не 149 клеток, а 54 на $0.39, и то лишь та их доля, чьи uid реально съедут (в моей симуляции +2 глав — 2 единицы ≈ 7 клеток).\n\nВывод не меняется ни один: `contour.py --plan` сейчас даёт «базы: черновик 32/32 · A0 32/32», расхождения нет. Тяжесть «мелко» поставлена правильно.",
|
||
"corrected": "Половина оси Д4 не приколота манифестом: 16 новых единиц пересчитываются из каталога глав при каждом запуске (`editor_tier/material.py:55-93`, отбор из середины длин, манифеста нет — `~/books/editor-tier/manifest.json` отсутствует), тогда как 16 старых приколоты (`tenant_panel/material.py:199-232` + существующий `~/books/tenant-panel/manifest.json`), и норму прикола объявляет сам инструмент фазы (`dovodka/material_ja.py` докстрока п.3). Последствие точнее: докачка или пере-нарезка глав сдвигает НЕ всю половину, а те новые единицы, что окажутся у краёв съехавшего окна середины длин — проверено на копии каталога: 42→38 глав даёт 4/16 съехавших uid, +2 главы обычной длины — 2/16, +8 глав с чанками вне середины — 0/16. Деньги при этом впустую НЕ уходят: покупка единицы без базы блокируется (`contour.py:248-250`), а `--selftest` («якорный черновик есть у всех», :201-202) падает до покупок. Реальная цена — тихая: съехавшие uid осиротят уже оплаченные клетки новых единиц (сейчас 54 клетки из 148, $0.3897) и молча изменят состав/размер n во ВСЕХ разборах, которые зовут `units_new()` (`contour.py:77`, `editor_tier/judge.py:77,81`, `itog23.py:44`) — ровно болезнь эксп-22 из §11 отчёта 23, объявленная там вылеченной только для старой половины."
|
||
}
|
||
},
|
||
{
|
||
"title": "Прайор шума взят с ПОЛА, а не с контраста: измеренный контраст той же структуры в 1.40× шумнее, и ось Д4 описательная при ЛЮБОМ k и с поправкой ×1.23 и без неё",
|
||
"severity": "критично",
|
||
"evidence": "power.py:36-40 — FLOORS[\"эксп-23 border\"]=2.12; `eval/.venv/bin/python eval/editor_tier/judge.py --score border` печатает это число под меткой «ПОЛ ... шум одного вызова: sd по единицам 2.12». Мой замер через absjudge._by_unit() на ТЕХ ЖЕ единицах того же прохода: пол (CTRLfloorA−CTRLfloorB) n=16 sd=2.191, КОНТРАСТ R2/R0 n=32 sd=3.063 — отношение 1.398. Независимое подтверждение из самого отчёта: 23-editor-tier.md:557-560 «внутри сессии sd 2.903 · между сессиями sd 1.030 · se 0.629» ⇒ полный sd = 0.629·√32 = 3.558. Пересчёт: P.mde(3.063,32,3)=2.155 · P.mde(3.063,32,3,between=False)=1.752 · P.mde(3.063,32,1,between=False)=1.517 — ВСЕ выше цели 1.50.",
|
||
"consequence": "Ось Д4, несущая главную ставку владельца H-2б, описательна по собственному критерию файла. Уже потрачено $0.8719 из $0.885 фазового потолка на прибор, который объявленный эффект 1.50 развести не может ни при каком исходе. power.py:96-97 признаёт «ПРАЙОР РЕШАЕТ» только для sd 3.53 и отводит его как «сквозную связку» — но 3.063 замерен на редакторах над ОДНОЙ базой, то есть ровно на структуре армов Д4, и этим доводом не отводится. В доках этого числа нет.",
|
||
"fix": "Взять прайором sd замеренного КОНТРАСТА над одной базой (3.06 наивный / 3.56 честный по §12б), а не пола: пол меряет только шум генерации+судьи, контраст несёт ещё и разброс эффекта по единицам. Пере-классифицировать Д4 в описательную ДО чтения перевесов либо пере-считать нужное n (при sd 3.06 и k=3 цель 1.50 требует n≈68).",
|
||
"verdict": {
|
||
"line": "статистика",
|
||
"refuted": false,
|
||
"corrected": "Механизм находки верен, но два её числа и её «последствие» надо поправить, а грунт — усилить доком, а не собственным замером.\n\nЧТО ВЕРНО. Решающее правило пака — `p` Холма < 0.05 по знаковому тесту НАД ПЕРЕВЕСАМИ (power.py:121), значит MDE обязан считаться на sd ПЕРЕВЕСОВ. power.py:37,48 подставляет туда sd ПОЛА 2.12 — шум двух генераций ОДНОГО арма, где разброса эффекта по единицам нет по построению. Это не одно и то же число, и разница замеряется.\n\nИСПРАВЛЕНИЕ МАСШТАБА (1.40× → 1.29×, и ДИ накрывает 1). «На ТЕХ ЖЕ единицах» неверно: пол прохода `border` лежит на 16 единицах, контраст R2/R0 — на 32 (judge.py:106-113 — пол для `border` заимствован у `tier`). Мой прогон `absjudge._by_unit()` после `judge.setup('border')`: пол n=16 sd 2.1909 (pstdev 2.121 = то самое печатаемое 2.12), контраст на ВСЕХ 32 sd 3.0632 (ratio 1.398 — воспроизвёл), но контраст НА ТЕХ ЖЕ 16 единицах sd 2.8255, ratio 1.290; бутстрап по единицам (20k, seed=1) даёт 95% ДИ отношения [0.896, 1.827], P(>1)=0.919. То есть направление устойчиво (корреляция полупар 0.580 против 0.364 у R0/R2 — ровно то, что даёт гетерогенность эффекта), но «в 1.40× шумнее» как замер — завышено и на n=16 от единицы значимо не отделено.\n\nГЛАВНЫЙ ГРУНТ — НЕ ЗАМЕР РЕВЬЮЕРА, А САМ ОТЧЁТ. 23-editor-tier.md:556-560 раскладывает дисперсию ИМЕННО ПЕРЕВЕСА `border` при n=32: внутри сессии sd 2.903, se 0.513 наивная → 0.629 честная, «ПОРОГ 1.48 напечатанный → 1.76 честный». 1.76 > цели 1.50 уже при k=1. То есть число, классифицирующее Д4 описательной, ЛЕЖИТ В ОТЧЁТЕ и просто не занесено в power.py; тезис находки «в доках этого числа нет» надо снять — это не новый замер, а внутреннее противоречие доков, что тяжелее. Добавочно: Д0.3 (строки 758-763) заморожена с k=5 и MDE 1.29, тогда как power.py:48 сейчас несёт k=3 и 1.491 — 1.29 это арифметика ДО поправки на k (2.8·2.12/√32·1.23), так что опубликованный статус оси ещё дальше от кода.\n\nИСПРАВЛЕНИЕ «ПРИ ЛЮБОМ k». Мой прогон P.mde: sd 3.0632 → k=1/без ×1.23 = 1.517, k=1/с = 1.866, k=3/без = 1.752, k=3/с = 2.155, k=5/с = 2.276 (все три числа находки воспроизвелись точь-в-точь). По честному sd 3.558 из §12б — 1.762…2.644. Но при sd 2.8255 (те же 16 единиц) k=1 без ×1.23 даёт 1.399 < 1.50. Точная формулировка: ось описательна при любой комбинации на наивном контрасте 3.06 и на честном 3.56; единственная комбинация, проходящая порог, — k=1 без ×1.23 на 16-единичной подвыборке, а она противоречит и пре-регу (k≥3, power.py:76-79), и объявленной поправке BETWEEN=1.23.\n\nИСПРАВЛЕНИЕ ПОСЛЕДСТВИЯ. «Развести не может ни при каком исходе» — это режим отказа en-оси эксп-22 (потолок p ≥ 0.05), и здесь его НЕТ: min_p(32,3) = 1.4e-9. Отказ другой и мягче: мощность 80% не достигается на ПРЕД-ОБЪЯВЛЕННОЙ цели 1.50; эффект ≥2.16 ось разведёт. Деньги тоже не сожжены целиком: несущая ось A4 — детерминированное покрытие канона (power.py:83-85), шума не имеет.\n\nИ ещё один довод в пользу находки, которого в ней нет: контрасты Д4 структурно ШУМНЕЕ, чем R2/R0. R2/R0 — два близких редактора над одной базой; A6/A0 (Д0.5) пересекает БАЗЫ (dspro-черновик против якорного flash), A1/A3 против A0 — точечный фиксер против полного переписа. Оценка 3.06 для них — нижняя граница, не верхняя.\n\nПОЧИНКА. Прайор Д4 = sd перевеса, а не пола: 3.06 наивный / 3.56 честный по §12б. Отдельно почини самокорректирующий механизм — power.py:99 и 23-editor-tier.md:776 обещают пере-классификацию, если СВОЙ ПОЛ выйдет хуже прайора; пол этой подмены не ловит по построению, сверять надо свой sd ПЕРЕВЕСОВ. Нужное n (мой расчёт): при sd 3.06, k=3, ×1.23 → n ≥ 67 (находка сказала 68 — округление); без ×1.23 → 44; при честном 3.56 → 90.",
|
||
"why": "ВОСПРОИЗВЁЛ ИСХОДНОЕ. `timeout 300 eval/.venv/bin/python eval/editor_tier/judge.py --score border` печатает «ПОЛ … шум одного вызова: sd по единицам 2.12 · ст.ошибка среднего 0.53 при n=16», контраст «R2 vs R0 32 -0.81 [-1.81, +0.28] 0.1601». power.py:37 `\"эксп-23 border (редакторы над ОДНОЙ базой, zh, n=16)\": 2.12`, power.py:48 `(\"Д4 edit-контур zh\", 32, 3, 2.12, 1.50, ...)`.\n\nСВОЙ ЗАМЕР. Скрипт: `sys.path.insert(0,'eval/editor_tier'); import judge as J, absjudge as AJ; J.setup('border'); d=AJ._by_unit()`. Вывод: `floor n 16 mean -1 sd 2.1909` · `contrast n 32 mean -0.8125 sd 3.0632` · `ratio 1.3981` · `contrast on floor units n 16 sd 2.8255`. Уровни: R0 n=32 sd 2.697, R2 n=32 sd 2.735, CTRLfloorA n=16 sd 1.893, CTRLfloorB n=16 sd 2.655. Корреляции: floorA/floorB 0.580, R0/R2 0.364 — то есть полупары связаны сильнее разных армов, что и даёт меньший sd разности у пола. Бутстрап 20000 по парам (seed=1) на 16 общих единицах: отношение 1.2896, 95% ДИ [0.896, 1.827], P(>1)=0.919.\n\nMDE (импорт `power as P`): sd 2.12 → k=1 1.291 / k=3 1.491 / k=5 1.575 (с ×1.23); sd 3.0632 → k=1 1.866 (без ×1.23 1.517), k=3 2.155 (без 1.752), k=5 2.276; sd 3.558 → k=1 1.762 без / 2.167 с, k=3 2.035 без / 2.503 с; sd 2.8255 → k=1 без ×1.23 = 1.399. `P.min_p(32,3)=1.3969e-09`. Нужное n при цели 1.50: sd 3.0632 k=3 ×1.23 → 67; без → 44; sd 3.558 k=3 ×1.23 → 90.\n\nПРОВЕРКА «НЕ ОБЪЯВЛЕНО ЛИ ЭТО ЗАРАНЕЕ» (главный тест на опровержение — не прошёл). Грепы `грep -rn \"пол не несёт|пол меряет|занижает|прайор|гетероген|разброс эффекта|sd контраста|контраст шумнее\"` по eval/dovodka/*.py, requirements.md, docs/POLYGON_EXP2223_REDO_SESSION_PROMPT.md, 23-editor-tier.md, 22-tenant-panel.md: единственное объявленное занижение пола — power.py:18 и §12б, и оно про ОДНОГО судью на обе половины (межсессионная компонента, ×1.23), а не про разброс эффекта по единицам. power.py:91-95 отводит полы 2.90/3.53 доводом «сквозная связка» — к 3.06, замеренному на редакторах над одной базой, этот довод неприменим. Д0.3 (23-editor-tier.md:774-776) объявляет только «прайор заимствован, решает СВОЙ ПОЛ» — то есть механизм самокоррекции меряет ту же неверную величину и подмену не ловит. Объявленным ограничением находка не закрывается.\n\nЧТО МЕНЯЕТ ВЫВОД. По собственному правилу power.py:145-150 («MDE больше искомого эффекта ⇒ ОПИСАТЕЛЬНАЯ») Д4 при sd перевеса становится описательной — а это ось H-2б, главной ставки владельца. Причём решающее число уже напечатано в отчёте: 23-editor-tier.md:560 «ПОРОГ 1.48 напечатанный → 1.76 честный» при n=32 для контраста той же структуры, против цели 1.50 (power.py:48)."
|
||
}
|
||
},
|
||
{
|
||
"title": "Замороженный пре-рег объявляет «Холм по пяти», а код считает по 3 и по 1; на ОБЪЯВЛЕННОМ k обе несущие оси становятся описательными",
|
||
"severity": "критично",
|
||
"evidence": "23-editor-tier.md:805 «семейство: A1/A0 · A2/A0 · A3/A0 · A4/A0 · A6/A0 Холм по пяти» и :810 «Холм по пяти» для Д3. В ТОМ ЖЕ коммите фриза da5f4d0 — power.py:75-89 PRIMARY даёт k=3 для Д4 и k=1 для Д3, а деление PRIMARY/SECONDARY в доках не упомянуто НИ РАЗУ (grep «ПЕРВИЧНОЕ|Холм по трём» по 23-editor-tier.md — пусто). Числа: P.mde(2.12,32,5)=1.575 против цели 1.50 ⇒ ОПИСАТЕЛЬНАЯ; P.mde(2.12,16,5)=2.228 против цели 2.00 ⇒ ОПИСАТЕЛЬНАЯ. Сама таблица Д0.3 (стр.759-764) ни одним прогоном кода не воспроизводится: колонка k=5, колонка MDE=1.29 посчитана формулой k=1 (2.8·2.12/√32·1.23=1.291), колонка потолка p=0.0002 посчитана при k=5 (2^-15·5=0.000153) — смесь двух редакций.",
|
||
"consequence": "Статус «НЕСУЩАЯ» у обеих осей, ради которых фаза покупалась, держится исключительно на сужении семейства, которого нет в замороженном документе. Читатель пре-рега видит k=5 и MDE 1.29 — сочетание, при котором ось на самом деле описательная. Это тот же класс, что провал en-оси эксп-22, ради недопущения которого power.py и написан.",
|
||
"fix": "Либо внести PRIMARY/SECONDARY в текст Д0.5 отдельным пере-фризом с датой и подписью владельца (и признать, что это правка пре-рега после начала покупок), либо считать по объявленному k=5 и объявить Д4/Д3 описательными. Таблицу Д0.3 перегенерировать выводом кода, а не пастой.",
|
||
"verdict": {
|
||
"line": "статистика",
|
||
"refuted": false,
|
||
"corrected": "Пре-рег фазы Д внутренне противоречив по размеру семейства Холма, и по тексту фриза обе несущие оси ложно-несущие. Текст: 23-editor-tier.md:805 и :810 «Холм по пяти», таблица Д0.3 (:759-764) печатает k=5 для Д4 и Д3. Код того же коммита фриза: power.py:48,52 AXES k=3 и k=1, PRIMARY (power.py:75-81) — 3 контраста для Д4, 1 для Д3. На объявленном в документе k=5: mde(2.12,32,5)=1.5753 > цели 1.50 и mde(2.12,16,5)=2.2278 > цели 2.00 — обе оси описательные. Две поправки к формулировке находки: (1) таблица Д0.3 НЕ «смесь двух редакций» и воспроизводима — я реконструировал до-фиксную редакцию (множитель 2.8 всегда + AXES k=5,5,3,1) и она даёт все четыре строки в точности, включая 1.29/1.83/3.33 и 0.0000/0.0002/0.0117/0.0000; это устаревшая паста одного прогона, не перегенерированная после починки mde(); (2) деление PRIMARY/SECONDARY не «отсутствует в замороженном документе» — оно пре-регистрировано в power.py:69-74 того же коммита da5f4d0, с обоснованием, а power.py:120-126 прямо фиксирует, что при k=5 Д4 была бы описательной. Дефект не в «сужении задним числом», а в том, что прозаический текст фриза противоречит коду фриза, и читатель Д0.3/Д0.5 видит k=5 вместе со статусом НЕСУЩАЯ — сочетание, ложное по арифметике самого рига. Дополнительно (мой замер, в находке нет): даже при кодовом k=3 запас Д4 равен 0.0085 (MDE 1.4915 против цели 1.50), порог sd*=2.1321 при прайоре 2.12 и MDE 1.5393 при k=4 — статус главной оси фазы держится на 0.6% прайора шума, то есть свой пол, объявленный решающим в Д0.3, перевернёт его почти при любом ухудшении. Починка та же: пере-фриз Д0.3/Д0.5 выводом кода с датой и подписью владельца, либо объявление Д4/Д3 описательными по k=5.",
|
||
"why": "Опровергнуть не удалось — ядро находки подтверждено исполнением. (1) Один коммит: `git log --oneline --all -- eval/dovodka/power.py` → единственная строка da5f4d0; `git show da5f4d0:eval/dovodka/power.py | md5sum` = afa1d4d228448aa385a8d2f49cd25fb1 = md5sum рабочего файла, и то же совпадение для docs/experiments/23-editor-tier.md (f83ec88d187c687963ccd37817a96495) — оба артефакта не менялись с фриза, значит противоречие вморожено, а не наросло после. (2) Расхождение k: 23-editor-tier.md:805 «семейство: A1/A0 · A2/A0 · A3/A0 · A4/A0 · A6/A0 Холм по пяти», :810 «Холм по пяти» для Д3, колонка k таблицы Д0.3 = 5,5,3,1; power.py:48 (\"Д4 edit-контур zh\", 32, 3, ...), power.py:52 (\"Д3 en→ru несущая\", 16, 1, ...), PRIMARY power.py:75-81 → 3 и 1. (3) Числа: `eval/.venv/bin/python -c \"import power as P; P.mde(2.12,32,5)\"` = 1.5753 при цели 1.50 и P.mde(2.12,16,5) = 2.2278 при цели 2.00 ⇒ по правилу power.py:149-150 обе оси описательные; прогон `power.py` при кодовом k печатает «Д4 … 32 3 … 1.49 1.50 … НЕСУЩАЯ» и «Д3 … 16 1 … 1.83 … НЕСУЩАЯ». (4) Опровергнут под-тезис «не воспроизводится / смесь редакций»: реконструкция mult=2.8 и AXES k=5,5,3,1 даёт ровно Д4 1.29/0.0000/НЕСУЩАЯ, Д3 1.83/0.0002/НЕСУЩАЯ, Д6 3.33/0.0117/ОПИСАТЕЛЬНАЯ, Д1 1.83/0.0000/НЕСУЩАЯ — совпадение со строками :760-763 посимвольно, то есть это один прогон старой редакции. (5) Опровергнут под-тезис «в докax не упомянуто ни разу» в части «замороженного документа»: `grep -rn \"ПЕРВИЧН|первичн|ВТОРИЧН|вторичн|Холм по\"` даёт пусто по .md, но power.py:69-74 несёт пре-регистрацию деления, а power.py:120-126 прямо называет, что при k=5 Д4 описательная — раскрытие есть внутри фриза, противоречит ему именно проза. (6) Чувствительность (моя проверка): sd*=1.50·√32/((z(1−0.05/6)+z(0.80))·1.23)=2.1321 против прайора 2.12; mde(2.12,32,4)=1.5393. Денег находка не тратит, но меняет публикуемый статус двух осей, ради которых фаза покупалась."
|
||
}
|
||
},
|
||
{
|
||
"title": "A6 — носитель H-1 — объявлен ПЕРВИЧНЫМ контрастом на оси, объявленной n=32, тогда как его собственный n=16 по построению: MDE 2.11 против цели 1.50",
|
||
"severity": "критично",
|
||
"evidence": "power.py:48 — AXES: (\"Д4 edit-контур zh\", 32, ...); power.py:78 — A6/A0 в PRIMARY. При этом plan.py:97-99 «H-1: dspro-черновик эксп-22 ... n=16» и 23-editor-tier.md:860 «ФД-F ... (n=16)». Диск подтверждает: инвентарь ~/books/dovodka/*.json по (arm,role) даёт ('A6','critic') 16 и ('A6','fixer') 16 против ('A3','fixer') 32. Пересчёт: P.mde(2.12,16,3)=2.109 > 1.50. При измеренном sd контраста 3.06 — 3.05.",
|
||
"consequence": "H-1 не может быть ни подтверждена, ни опровергнута; $0.2678 куплено на арм, чей контраст описателен по правилу самой фазы. Сестринский случай E6/H-4 объявлен описательным явно (docs/PROGRESS.md:233 «H-4 остаётся ОПИСАТЕЛЬНОЙ — при n=16 порядок жильцов не разрешается»), а для A6 при том же n=16 такой оговорки нет нигде — то есть про один арм сказано, а про другой умолчано.",
|
||
"fix": "Объявить A6/A0 описательным в Д0.3/Д0.5 наравне с E6, либо считать мощность оси Д4 поконтрастно (у каждого контраста свой n), а не одним n=32 на всю ось.",
|
||
"verdict": {
|
||
"line": "статистика",
|
||
"refuted": false,
|
||
"corrected": "A6/A0 — единственный носитель H-1 — записан в ПЕРВИЧНОЕ (Холм-корректируемое) семейство оси «Д4 edit-контур zh», для которой мощность объявлена одним числом при n=32 (power.py:48 `(\"Д4 edit-контур zh\", 32, 3, 2.12, 1.50, ...)`, power.py:78 `\"A6/A0 — качественный черновик + контур (H-1)\"`), тогда как сам контраст A6/A0 существует только на 16 единицах ПО ПОСТРОЕНИЮ: dspro-черновики эксп-22 есть лишь для 16 старых uid (`contour.py --plan` → «A6: куплено 16 из 16 · базы: черновик-dspro 16/16»; contour.py:179 `n = len(old) if a == \"A6\" else len(us)`; contour.py:243 `if arm == \"A6\" and uid not in old: continue`). При объявленном самой осью прайоре sd 2.12 («берётся худшая», power.py:49) MDE контраста = P.mde(2.12,16,3) = 2.11 против объявленной ЦЕЛИ 1.50, тогда как печатается 1.49 (n=32). Собственная таблица файла это подтверждает: «k=3 цель 1.50 → n ≥ 32».\n\nТри уточнения к исходной формулировке:\n1) «Не может быть ни подтверждена, ни опровергнута» — слишком сильно. Потолок значимости при n=16, k=3 равен 9.2e-05 (P.min_p(16,3)), то есть значимость достижима; недостижим именно ЦЕЛЕВОЙ эффект — прибор разведёт только разрыв ≥2.11, а предсказание самой фазы (23-editor-tier.md:884: A6 побьёт A1/A3, но не A0) описывает ровно подпороговые величины. Корректная формула: по собственному правилу фазы («ось описательна, если MDE больше цели», Д0.3) контраст A6/A0 обязан быть объявлен ОПИСАТЕЛЬНЫМ, а он объявлен несущим.\n2) «Измеренный sd контраста 3.06» ничем не грунтован: строки `3.06` нет ни в eval/dovodka/, ни в 23-editor-tier.md, ни в PROGRESS.md (grep — ноль), и power.py прямо пишет, что своего пола у будущего прохода нет по построению. Число из вывода убрать; грунтованные цифры — 2.11 при прайоре 2.12 и 2.23, если брать k=5 из фризованной таблицы Д0.3. Оговорка честности: при оптимистичном поле tier sd 1.45 MDE был бы 1.44 < 1.50 — то есть вывод держится на объявленном прайоре 2.12, но именно он и объявлен прайором этой оси.\n3) Параллель с E6/H-4 не буквальная: ось Д3 объявлена n=16, то есть у E6 n оси и n контраста СОВПАДАЮТ, и описательность там объявлена по существу вопроса (power.py:87, docs/PROGRESS.md:233). У A6 дефект другого рода и хуже: расхождение между напечатанным n оси (32) и физически возможным n контраста (16), которого не называет ни один док. Это усиливает находку, а не ослабляет — про n=16 как приговор «порядку жильцов» сказано в одном месте и не сказано там, где тот же n=16 решает судьбу H-1.\n\nОтдельно к масштабу: на сейчас ниже 32 стоят и A1 (30) и A4 (22), но это состояние покупок, лечится деньгами; 16 у A6 — структурный предел, деньгами не лечится. Единственное место, где n=16 для A6 вообще напечатано, — денежная строка ФД-F (23-editor-tier.md:860 и money_d.py:81), то есть смета, а не мощность.",
|
||
"why": "Проверено исполнением, попытка опровержения не удалась.\n\n(1) Объявление первичным на оси n=32: `grep -n \"\" eval/dovodka/power.py | sed -n '46,50p;76,80p'` → power.py:48 `(\"Д4 edit-контур zh\", 32, 3, 2.12, 1.50,` и power.py:78 `\"A6/A0 — качественный черновик + контур (H-1)\"` внутри `PRIMARY`. Структура AXES — один `n` на всю ось (комментарий power.py:47 «(имя, план n, контрастов, ...)»), поконтрастного n в файле нет; `main()` печатает MDE циклом `for name, n, k, sd, target, ... in AXES`, то есть A6 наследует n=32.\n\n(2) Запуск `eval/.venv/bin/python eval/dovodka/power.py` печатает строку `Д4 edit-контур zh 32 3 2.12 1.49 1.50 0.0000 НЕСУЩАЯ` и ниже семейство «ПЕРВИЧНОЕ (Холм по 3)» с пунктом «A6/A0 ... (H-1)». То есть единственное напечатанное число мощности для H-1 — 1.49 при n=32.\n\n(3) n=16 по построению: `timeout 120 eval/.venv/bin/python eval/dovodka/contour.py --plan` → «единиц 32 (старых 16 + новых 16) ... A6: куплено 16 из 16 ... базы: ... черновик-dspro 16/16». Код: contour.py:179 `n = len(old) if a == \"A6\" else len(us)`, contour.py:243 `if arm == \"A6\" and uid not in old: continue`, contour.py:247 `base_draft2(uid) if arm == \"A6\"`. Дозакупить нельзя — dspro-базы больше нет.\n\n(4) Инвентарь сырья независимой командой по ~/books/dovodka/*.json: `('A6','critic') 16 $0.1211`, `('A6','fixer') 16 $0.1467` (сумма $0.2678) против `('A3','fixer') 32`, `('A3','critic') 32`. Совпадает с состоянием из заказа.\n\n(5) Пересчёт: `P.mde(2.12,16,3)=2.109`, `P.mde(2.12,32,3)=1.491`, `P.mde(2.12,16,5)=2.228`, `P.min_p(16,3)=9.16e-05`, `P.mde(1.45,16,3)=1.443`. Собственная таблица power.py: «k=3 цель 1.50 → n ≥ 32».\n\n(6) Поиск объявленного ограничения (главный путь опровержения) — пусто. `grep -rn \"A6\" docs/ --include=*.md | grep -i \"мощн\\|MDE\\|описат\\|n=16\"` даёт единственный хит 23-editor-tier.md:860 — денежную строку `ФД-F H-1: A6 ... (n=16) 0.280`. В пре-реге Д0.3 (строки 745-760) напечатана таблица осей без A6-оговорки, в Д0.5 (строка 805) прямо сказано «Д4 — edit-контур zh, 32 единицы» и «семейство: A1/A0 · A2/A0 · A3/A0 · A4/A0 · A6/A0 Холм по пяти», то есть A6 включён в семейство под n=32. Ни докстринг power.py, ни contour.py, ни отчёт, ни docs/PROGRESS.md нигде не связывают n=16 A6 с мощностью.\n\n(7) Сестринский случай проверен: power.py:87 «E6/E0 ... на n=16 порядок жильцов разрешить нельзя, ось описательная и это сказано ДО денег» + docs/PROGRESS.md:233. Но ось Д3 сама объявлена n=16 (power.py:53), поэтому там расхождения n нет — параллель неточна, и это уточнено в corrected.\n\n(8) Побочно (не часть находки, но подрывает «объявлено заранее»): фризованная таблица Д0.3 в 23-editor-tier.md:751-756 печатает для Д4 `k=5, MDE 1.29`, тогда как живой power.py даёт k=3 и 1.49, а `P.mde(2.12,32,5)=1.575` — то есть ни одно из двух напечатанных чисел не воспроизводится своим же кодом при k=5. Проверять это не входило в задачу, отмечаю как смежное расхождение.\n\nНичего не покупалось и не правилось: выполнены только power.py, contour.py --plan и чтение сырья."
|
||
}
|
||
},
|
||
{
|
||
"title": "Правило Д0.4 «нижняя граница 95% ДИ» опирается на bootstrap-ДИ среднего, тогда как решающий тест рига — точный перестановочный; ДИ уже своего теста, фактическое покрытие 0.92 вместо 0.95, и перекос в сторону, облегчающую вывод «НЕ ХУЖЕ»",
|
||
"severity": "важно",
|
||
"evidence": "absjudge.py:472 p считается BO.sign_perm_p, absjudge.py:485 ДИ — BO.boot_ci. bakeoff.py:469-481 — percentile-bootstrap СРЕДНЕГО, 5000 реп; bakeoff.py:487-489 докстринг сам признаёт: «Bootstrap-ДИ ... на 15 единицах даёт заметно более узкий интервал, чем точный тест». Мои числа на реальных данных: tier T1/R0 n=16 boot [-0.562,+0.125] ширина 0.688 против t-ДИ 0.799 (уже на 14%), T3/R0 уже на 16%, F/R0 на 11%. Симуляция покрытия (2000 повторов, норм. данные, sd 2.61): n=16 → 0.920, n=32 → 0.926 при номинале 0.95.",
|
||
"consequence": "Единственный CONFIRM, который фаза способна выдать для H-2а, выносится анти-консервативным интервалом: наиболее вероятная ошибка прибора — ложное «НЕ ХУЖЕ». Дополнительно правило Д0.4 требует обе границы внутри ±1.50, то есть это TOST/эквивалентность, а названо non-inferiority, и поправку Холма оно не несёт, хотя контрасты-близнецы по превосходству её несут — α смешаны в одном вердикте.",
|
||
"fix": "Считать границу Д0.4 инверсией того же перестановочного теста (набор δ, при которых sign_perm_p(x−δ)≥0.05), а не percentile-bootstrap; при сохранении бутстрапа брать BCa либо t-ДИ. Назвать правило эквивалентностью и объявить, несёт ли оно поправку.",
|
||
"verdict": {
|
||
"refuted": false,
|
||
"corrected": "МЕЛКО (не «важно»), и последствие сформулировано неверно. Верно: правило Д0.4 (docs/experiments/23-editor-tier.md:785-791) объявляет решение по 95% ДИ, а весь переиспользуемый риг считает ДИ перцентильным бутстрапом среднего (bakeoff.py:469-481), покрытие которого ниже номинала. НЕверно: (1) «перекос в сторону НЕ ХУЖЕ» — перекос СИММЕТРИЧЕН и на границе маржи даже больше в сторону ложного «ХУЖЕ»; (2) «покрытие 0.92» — это n=16, а Д0.4 применяется на оси Д4 при n=32, где покрытие 0.931 и сужение ~5%, а не 11–16%; (3) добавленная верхняя граница ±1.50 делает правило СТРОЖЕ, то есть работает против тезиса об анти-консервативности. Реальная цена дефекта: на n=32/sd 2.12 при истинном δ=−1.50 ложный CONFIRM 0.026 (boot) против 0.019 (t) — инфляция 0.7 п.п., и обе величины ниже конвенционального α=0.05 для non-inferiority. Ни один вывод и ни один доллар не двигаются: судейств в фазе Д ноль, кода счёта в eval/dovodka/ нет вовсе. Из пакета правок остаются в силе два второстепенных пункта: правило названо non-inferiority, а по форме это эквивалентность (две границы), и множественность двух эквивалентностных заявлений (A1 и A3) не объявлена, тогда как близнецовые контрасты превосходства несут Холма по пяти (Д0.5). Починка $0 и уместна ДО первого судейства — но как гигиена пре-рега, а не как «единственный CONFIRM выносится сломанным прибором».",
|
||
"why": "ФАКТУРА АВТОРА ВОСПРОИЗВЕЛАСЬ ТОЧНО. `eval/.venv/bin/python eval/editor_tier/judge.py --score tier` + наложение t-ДИ на те же _margins: T1 vs R0 n=16 boot [-0.562,+0.125] ш=0.688 · t [-0.587,+0.212] ш=0.799 · уже на 14.0%; T3 vs R0 уже на 15.6%; R0 vs F на 11.1%. Симуляция покрытия с НЕЗАВИСИМЫМ ресемплингом на каждый повтор (норм., sd 2.61, 4000 повторов): n=16 покрытие 0.919, n=32 покрытие 0.931. Код процитирован верно: absjudge.py:472 `rows.append((a, b, what, m, BO.sign_perm_p(m)))`, absjudge.py:485 `lo, hi = BO.boot_ci(m)` — то есть p решает перестановочный тест, ДИ только печатается; bakeoff.py:469-481 — перцентильный бутстрап среднего, 5000 реп; bakeoff.py:487-489 докстринг признаёт узость.\n\nЧТО ОПРОВЕРГНУТО — ПОСЛЕДСТВИЕ. Я промоделировал НЕ покрытие вообще, а САМО правило Д0.4 («обе границы внутри ±1.50»), n=32, sd 2.12 (прайор оси Д4, power.py:48), 3000 повторов, boot против t:\n δ=+0.00: НЕ ХУЖЕ boot 0.958 / t 0.942 · расхождение вердиктов 0.016\n δ=-1.00: НЕ ХУЖЕ boot 0.291 / t 0.251 · расхождение 0.040\n δ=-1.50 (граница маржи): НЕ ХУЖЕ boot 0.026 / t 0.019 · ХУЖЕ boot 0.034 / t 0.025 · расхождение 0.016\n δ=-2.00: ХУЖЕ boot 0.290 / t 0.251 · расхождение 0.040\nНа границе маржи инфляция ложного «ХУЖЕ» (+0.009) БОЛЬШЕ инфляции ложного «НЕ ХУЖЕ» (+0.007). Тезис «наиболее вероятная ошибка прибора — ложное НЕ ХУЖЕ» не подтверждается: узкий ДИ облегчает ЛЮБОЙ определённый вердикт за счёт исхода «НЕ УСТАНОВЛЕНО», и делает это симметрично. Абсолютная величина ложного CONFIRM 0.026 — ниже конвенционального одностороннего α=0.05 для non-inferiority.\n\nМАСШТАБ ЗАВЫШЕН. Заголовочные «0.92» и «уже на 11–16%» — все с n=16 (проход `tier` пака 23). Ось, которой правило Д0.4 адресовано, — Д4, 32 единицы (docs/experiments/23-editor-tier.md:754 «Д4 edit-контур zh 32 5 2.12 1.29 1.50 НЕСУЩАЯ»), там покрытие 0.931 и сужение ~5%. На единственных существующих боевых числах сдвиг границы Д0.4 составляет 0.025 (boot -0.562 против t -0.587) при марже 1.50 — 1.7% маржи, вердикт идентичен.\n\nНИ ДОЛЛАРА, НИ ВЫВОДА. `eval/.venv/bin/python eval/dovodka/runs.py` → «агент-сессий израсходовано 0 из 80»; `ls ~/books/dovodka/*jv2* | wc -l` → 0. Правило Д0.4 не исполнялось ни разу. Больше того, `grep -rn \"boot_ci|sign_perm_p|ДИ\" eval/dovodka/*.py` не даёт ни одного попадания — в зоне фазы Д кода счёта контрастов НЕТ вовсе, так что «Д0.4 опирается на boot_ci» — вывод по переиспользуемому ригу (`grep -rn boot_ci eval/ --include=*.py`: 18 мест в role_topology/editor_tier, альтернативы в дереве нет), а не факт о написанном коде фазы.\n\n«УЖЕ ОБЪЯВЛЕНО?» ЧАСТИЧНО. Свойство прибора задокументировано в коде дважды и количественно: absjudge.py:506-509 «перцентильный бутстрап при n=16 накрывает ~93%, а не 95%» — и там же риг от ДИ как критерия ОТКАЗАЛСЯ в пользу sign_perm_p. В доках фазы этого нет: `grep -rn \"бутстрап|bootstrap|перцентил\" docs/experiments/23-editor-tier.md docs/experiments/22-tenant-panel.md docs/POLYGON_EXP2223_REDO_SESSION_PROMPT.md eval/dovodka/requirements.md` — пусто. То есть новизна находки не в свойстве бутстрапа (оно описано), а в том, что пре-рег вернул решающую роль инструменту, от которой сам риг её снял. Это законная гигиена, но не «важно».\n\nПОБОЧНЫЕ ПУНКТЫ АВТОРА ПРОВЕРЕНЫ И ВЕРНЫ. Строка 785 говорит «правило non-inferiority ... нижняя граница», строка 789 добавляет «и верхняя < +1.50» — по форме это эквивалентность; заметить стоит, но добавленная верхняя граница правило УЖЕСТОЧАЕТ. Холм: Д0.5 объявляет «Холм по пяти» для семейства превосходства, для двух эквивалентностных заявлений (A1 и A3) множественность не объявлена — верно."
|
||
}
|
||
},
|
||
{
|
||
"title": "Мощность самого правила Д0.4 нигде не посчитана: при измеренном sd вероятность получить «НЕ ХУЖЕ» даже при ТОЧНОМ равенстве армов — 0.23, а для A6 при n=16 вердикт недостижим по построению",
|
||
"severity": "важно",
|
||
"evidence": "В power.py и в Д0.4 (23-editor-tier.md:781-796) нет ни одной цифры мощности для правила эквивалентности — только MDE теста превосходства. Мой расчёт P(обе границы 95% ДИ внутри ±1.50 | δ=0): при sd 2.61 (прайор power.py) n=32 → 0.804, n=30 → 0.766, n=16 → 0.267; при измеренном контрасте 3.063×1.23=3.77 n=32 → 0.230, n=30 → 0.175, n=16 → 0.000 (полуширина ДИ 1.846 больше запаса 1.50 — интервал не помещается ни при каких данных).",
|
||
"consequence": "H-2а объявлена подтверждаемой только через Д0.4, но шанс подтверждения при истинном равенстве — от 23% до нуля. Это ровно форма провала en-оси эксп-22 («вердикт недостижим по построению»), перенесённая из потолка p в правило эквивалентности, и файл, написанный именно против этого, её не поймал.",
|
||
"fix": "Напечатать в power.py рядом с MDE вероятность вердикта эквивалентности при δ=0 для каждого контраста по его СОБСТВЕННОМУ n; контрасты, у которых полуширина ДИ ≥ запаса, объявить описательными до денег.",
|
||
"verdict": {
|
||
"line": "статистика",
|
||
"refuted": false,
|
||
"why": "ПРОВЕРЕНО ИСПОЛНЕНИЕМ, ЧТО ВЕРНО:\n1) Числа мощности правила эквивалентности в риге действительно нет. `grep -n \"эквивал|не хуже|НЕ ХУЖЕ|non-infer|TOST|запас\" eval/dovodka/power.py` → ни одного хита кроме числа 1.50 как ЦЕЛИ теста превосходства; полный прогон `eval/.venv/bin/python eval/dovodka/power.py` печатает только MDE и потолок p. Фраза «мощность объявлена» в 23-editor-tier.md:792 буквой не обеспечена.\n2) Арифметику находки я воспроизвёл своим кодом: sd0=2.12×1.23 → P(обе границы 95% ДИ внутри ±1.50 | δ=0) = 0.804 (n=32), 0.766 (n=30), 0.267 (n=16); при sd0=3.063 — 0.230/0.175/0.000. Цифры автора верны АРИФМЕТИЧЕСКИ.\n\nЧТО ОПРОВЕРГНУТО (заголовок, тяжесть и последствие):\n3) Заголовок «при измеренном sd вероятность 0.23» держится ТОЛЬКО на sd 3.063. Этого числа в репозитории нет: `grep -rn \"3\\.063\" /home/ubuntu/projects/textmachine` → пусто. И «измеренным контрастом» фазы Д оно быть не может: в ~/books/dovodka 148 клеток, роли только `critic` 48 и `fixer` 100 (посчитано json-обходом), судейских клеток НОЛЬ — ни один контраст фазы ещё не замерен. При ПРЕ-РЕГИСТРИРОВАННОМ прайоре (sd 2.12, power.py:37,48) мощность правила Д0.4 на несущем n=32 равна 0.804 — обычные 80%, а не 23%.\n4) Главное: заявленный сценарий уже ловится объявленным гейтом, то есть это НЕ повтор провала en-оси эксп-22. Тождество (посчитал): если MDE = (z_{1−α/2k}+z_{0.8})·se ≤ запаса, то P(эквивалентность|δ=0) = 2Φ(запас/se − 1.96) − 1 ≥ 2Φ(3.2356 − 1.96) − 1 = 0.798 при k=3. Правило Д0.4 приписано ровно оси Д4, а она идёт k=3 (power.py:48, вывод прогона) — значит существующий двухусловный гейт «MDE ≤ ЦЕЛЬ» на этой оси ЯВЛЯЕТСЯ де-факто гейтом экв-мощности ≥0.80. Граница: ось остаётся НЕСУЩЕЙ до sd0 ≤ 2.1321, и ровно на ней экв-мощность 0.798. Сценарий автора sd0=3.063 даёт MDE 2.155 > цели 1.50 → ось пере-классифицируется в ОПИСАТЕЛЬНУЮ, а Д0.3 (23-editor-tier.md, абзац «Прайор шума — не свой пол») и хвост power.py пред-объявляют, что это происходит по СВОЕМУ полу «ТОГДА ЖЕ, до чтения боевых перевесов». В эксп-22 ловить было нечем — здесь ловец пре-регистрирован и срабатывает.\n5) Ветка про A6 адресована не тому объекту: правило Д0.4 пред-объявлено дословно для «`A1` (и `A3`)» (23-editor-tier.md:785). A6 под правило non-inferiority не заведён вовсе, так что «для A6 вердикт эквивалентности недостижим по построению» опровергает норму, которой нет.\n\nЧТО ВСЁ-ТАКИ ОСТАЁТСЯ ДЕФЕКТОМ (и это меняет вывод — см. corrected): power.py считает MDE по n ОСИ, а контрасты первичного семейства имеют РАЗНЫЕ n. A6 планируется n=16 (plan.py:97-99, ФД-F), но печатается внутри строки «Д4 … n 32 … НЕСУЩАЯ». MDE(sd 2.12, n=16, k=3) = 2.109 против цели 1.50 → по СОБСТВЕННОМУ двухусловному правилу файла (power.py:143-153) носитель H-1 описателен, а объявлен несущим. У A1 фактически куплено 30 клеток (посчитано по сырью), MDE(n=30,k=3) = 1.540 > 1.50 — тоже за гейтом, пусть впритык. Побочно: таблица Д0.3 в отчёте (23-editor-tier.md:756-766) разошлась с ригом — в отчёте k=5, MDE Д4 1.29, Д6 3.33, Д3 потолок 0.0002; живой прогон даёт k=3, 1.49, 3.85, 0.0000.",
|
||
"corrected": "Дефект не в «непосчитанной мощности правила эквивалентности» (на несущем n=32 при пре-рег прайоре она 0.804, и гейт «MDE ≤ ЦЕЛЬ» при k=3 математически гарантирует ≥0.798 — то есть правило Д0.4 обеспечено уже существующим гейтом), а в том, что power.py применяет n ОСИ ко всем контрастам первичного семейства, тогда как n у них разные. Носитель H-1 — контраст A6/A0 — планируется на n=16 (plan.py:97-99), при котором MDE = 2.11 против объявленной цели 1.50, то есть по собственному двухусловному правилу файла (power.py:143-153) он ОПИСАТЕЛЬНЫЙ, но печатается внутри строки «Д4 … n 32 … НЕСУЩАЯ»; фактический A1 (30 куплённых клеток) даёт MDE 1.54 и тоже за гейтом. Починка сохраняется в части «по СОБСТВЕННОМУ n»: печатать MDE, потолок p и вероятность вердикта при δ=0 отдельно для каждого контраста по его n, и контрасты, не проходящие гейт по своему n, объявить описательными до судейства. Числа 0.23/0.175/0.000 из находки снять: они получены подстановкой sd 3.063, которого нет ни в репозитории, ни в сырье (судейских клеток в ~/books/dovodka ноль), а при таком поле ось и так пере-классифицируется пред-объявленным правилом своего пола."
|
||
}
|
||
},
|
||
{
|
||
"title": "Фактические n меньше плановых (A1=30, A4=22, после снятия finish=length A4=20) — при них контрасты уходят за MDE, а A1 и A3 перестают быть парными по одним и тем же единицам",
|
||
"severity": "важно",
|
||
"evidence": "Инвентарь ~/books/dovodka/*.json: ('A1','fixer') 30 uid, ('A3','fixer') 32, ('A4','fixer') 22 из них 2 с finish='length'. Разность множеств: A3\\A1 = ['474f822806','9b16c9c9a7'], A1\\A3 = []. Пересчёт при прайоре 2.12, k=3, цель 1.50: n=30 → MDE 1.540 ⛔, n=22 → 1.799 ⛔, n=20 → 1.887 ⛔ (n=32 → 1.491 ✔). power.py:48 считает по плановому n=32 и о фактическом не знает.",
|
||
"consequence": "A1/A0 — контраст гипотезы H-2а — описателен уже по своему собственному числу единиц, независимо от прайора. Кроме того, сравнение «флаги против смысла» (A1 против A3), которое владелец прочтёт как главный практический вывод, считается на разных наборах единиц и парным не является; на двух единицах, где A1 отсутствует, нарушается норма Д0.6 «все армы единицы — в одном задании одной сессии».",
|
||
"fix": "Считать MDE по ФАКТИЧЕСКОМУ n каждого контраста в момент свода и печатать его рядом с перевесом; контрасты A1/A3 сводить на пересечении единиц (n=30) явно, а не молча.",
|
||
"verdict": {
|
||
"line": "статистика",
|
||
"refuted": false,
|
||
"corrected": "Ядро находки верно, но причина и масштаб перепутаны — исправленная формулировка: «MDE считается по ПЛАНОВОМУ n оси, а фактический n у КАЖДОГО контраста свой — и по трём разным причинам, из которых бюджет только одна. (1) A1=30 не из-за денег: на двух единицах (474f822806, 9b16c9c9a7) детерминированный детектор даёт НОЛЬ мест, и contour.py:263-265 по правилу не покупает клетку. Это не «недобор», а исключение единиц по СОБСТВЕННОМУ механизму арма: выпадают ровно те, где флаговому контуру нечего чинить, то есть контраст A1/A0 смещается к единицам, где контуру было что делать. Правильная починка не «пересчитать MDE на n=30», а объявить трактовку: либо на этих единицах выход A1 ≡ черновик без правок (тогда n=32, MDE 1.491 и парность с A3 восстановлены), либо исключение объявлено селективным и названо в отчёте. (2) A4=22: из 10 отсутствующих 9 срезал гард, 1 (474f822806) — то же правило «мест нет». Но вывод это НЕ меняет: A4/A0 пре-регистрирован как ОПИСАТЕЛЬНЫЙ (power.py:82-86, «его несущая ось — покрытие канона, а оно детерминировано и шума не имеет»), Холм-вердикта он не несёт, поэтому числа MDE 1.799/1.887 в находке риторические. (3) Проблема шире фактических n: A6/A0 стоит в ПЕРВИЧНОМ семействе (power.py:78), а его n=16 ПО ПЛАНУ (contour.py:179, plan.py:97 «ФД-F ... n=16») — MDE 2.109 против цели 1.50, то есть контраст был описательным ещё до первой покупки, а power.py:48 приписывает всей оси n=32. Реально меняющаяся часть вывода одна: A1/A0 (H-2а) при n=30 даёт MDE 1.540 > 1.50 и уходит из несущих — но запас на плановом n был 0.009 (0.6%), а в замороженном пре-реге (23-editor-tier.md:760) напечатано устаревшее «n=32 k=5 MDE 1.29 НЕСУЩАЯ», так что читатель отчёта переворота вообще не увидит. Норма Д0.6/R59 «все армы единицы — в одном пакете одной сессии» НЕ нарушена: она про судейское задание, а отсутствующая клетка делает пакет единицы неполным, а не разнесённым по сессиям.»",
|
||
"why": "Пере-проверил всё своими командами, находка выдержала.\n\n1) Инвентарь сырья (мой скрипт по ~/books/dovodka/dv-*.json, поля arm/role/uid/finish): ('A1','fixer') 30 · ('A3','critic') 32 · ('A3','fixer') 32 · ('A4','fixer') 22 · ('A6','critic') 16 · ('A6','fixer') 16; единственные не-stop клетки — ('A4','fixer') [('41599f30df','length'), ('f6da9f76b2','length')]. Разность множеств: A3\\A1 = ['474f822806','9b16c9c9a7'], A1\\A3 = [], |A1∩A3| = 30. Улика находки воспроизводится точь-в-точь.\n\n2) Арифметика MDE воспроизводится СОБСТВЕННОЙ функцией рига (`eval/.venv/bin/python -c \"from power import mde; ...\"`, k=3, sd=2.12): n=32 → 1.491 · n=30 → 1.540 · n=22 → 1.799 · n=20 → 1.887 · n=16 → 2.109. Цель оси 1.50 (power.py:48-52). Значит A1/A0 на фактическом n действительно переходит порог, и это не риторика.\n\n3) power.py:48 — `(\"Д4 edit-контур zh\", 32, 3, 2.12, 1.50, ...)`, комментарий над ним прямо помечает поле как «план n». Никакого пересчёта по факту в зоне нет: `grep -rn \"MDE\" eval/dovodka/*.py *.md` вне power.py даёт единственный хит requirements.md:101 (R65 — «MDE каждой судейской оси в пре-рег ДО покупок»), сводного скрипта в eval/dovodka/ нет вовсе (ls: canon/contour/material_ja/money_d/plan/power/promptdiff/runs). То есть «печатать MDE при фактическом n» нигде не объявлено и не исполнено.\n\n4) ГЛАВНОЕ ИСПРАВЛЕНИЕ ПРИЧИНЫ — проверено исполнением, а не чтением. Загрузил contour.py как модуль и посчитал flags_of() по всем 32 единицам ($0, сети нет): «units with 0 flags: ['474f822806','9b16c9c9a7']», ровно те две, которых нет у A1. Значит клетки не куплены по правилу contour.py:263-265 («мест нет — чинить нечего, клетка не покупается»), а не гардом. Для A4 такой же прогон canon_gaps(src, base_a0(uid)) по 10 отсутствующим единицам: нулевых мест только 1 (474f822806) — остальные 9 срезал бюджетный гард.\n\n5) Почему A4-часть находки не меняет вывода: power.py:82-86 объявляет A4/A0 во ВТОРИЧНОМ (описательном) семействе с обоснованием «его несущая ось — покрытие канона, а оно детерминировано и шума не имеет». Поправку Холма он не несёт, поэтому MDE при n=22/20 никакого вердикта не переворачивает.\n\n6) Почему проблема шире фактических n: A6/A0 стоит в PRIMARY (power.py:78), но n у него 16 по плану — contour.py:179 `n = len(old) if a == \"A6\" else len(us)` и plan.py:97 «ФД-F ... n=16»; mde(2.12,16,3)=2.109 > 1.50. То есть один из трёх первичных контрастов оси был недомощен ещё до денег, а power.py приписывает оси единый n=32.\n\n7) Не объявленное ограничение: в замороженном пре-реге 23-editor-tier.md:759-764 напечатано «Д4 32 5 2.12 1.29 1.50 НЕСУЩАЯ» — таблица разошлась с текущим power.py (k=3 → 1.491), при 1.29 даже n=30 дал бы 1.333 < 1.50 и переворота не видно. В журнале docs/PROGRESS.md:196 арм A1 записан как «30/30 платных клеток» — знаменатель подменён фактом, две пропущенные единицы не названы. Ни в contour.py-докстринге (строки 2-24), ни в Д0 (719-896), ни в PROGRESS последствие пропуска не объявлено — значит это находка, а не исполненная норма.\n\n8) Единственное, что в находке неверно: ссылка на Д0.6 «все армы единицы — в одном задании одной сессии» (23-editor-tier.md:821-822, дубль requirements.md:95 R59). Норма про СУДЕЙСКОЕ задание; отсутствие купленной клетки не разносит армы по сессиям, а делает пакет единицы неполным — это другое нарушение, и называть его нарушением Д0.6 неточно."
|
||
}
|
||
},
|
||
{
|
||
"title": "min_p не учитывает нулевые разности: эффективное n = n − число нулей, а на этом материале нулей от 9% до 81%",
|
||
"severity": "мелко",
|
||
"evidence": "power.py:107-109 min_p(n,k)=2^(1-n)·k. Формула ВЕРНА при отсутствии связок — проверил перебором точного двустороннего биномиального p для n=1..14 (совпадение с 2^(1-n) до 1e-12) и через сам BO.sign_perm_p. С нулями: n=16 при 10 нулях → минимум 0.03125, при 7 нулях → 0.0039 (формула печатает 3.05e-05); n=9 при 4 нулях → 0.0625 ≥ 0.05, то есть значимость недостижима. Замеренные доли нулевых разностей на реальных проходах: tier T3/R0 13/16 = 81%, T1/R0 10/16 = 62%, T2/R0 7/16 = 44%; border R2/R0 3/32 = 9%.",
|
||
"consequence": "Печатаемый потолок значимости оптимистичен на порядки для контрастов близких армов. Наиболее уязвим A4 = A0 + канон-фиксер ПОСЛЕ: тексты почти совпадают, доля нулей ожидается на уровне tier (44–81%), эффективное n падает с 22 до ~5–12. Утверждение power.py:191-192 «здесь такой оси нет» на связанных данных не проверено.",
|
||
"fix": "Считать min_p по (n − ожидаемое число нулей) и печатать ожидаемую долю связок из замеров tier/border рядом с потолком; при своде брать фактическое число ненулевых разностей.",
|
||
"verdict": {
|
||
"line": "статистика",
|
||
"refuted": false,
|
||
"corrected": "ТОЧНАЯ ФОРМУЛИРОВКА (сильно уже исходной): докстринг `power.py:107-108` называет `min_p` «минимально достижимым p знакового теста при n наблюдениях», не оговаривая условие «без связок». Это неверная ПОДПИСЬ к плановому числу $0-калькулятора: при z нулевых разностях достижимый минимум равен 2^(1−(n−z))·k, а не 2^(1−n)·k. Никакой другой эффект находка не имеет: (1) отчётный p считается ригом ТОЧНО и связки обрабатывает корректно (`bakeoff.sign_perm_p` перебирает все 2^n расстановок знаков; на реальном векторе R0/T3 с 13 нулями из 16 он печатает p=0.75, а не оптимистичное число) — то есть предложенная починка «при своде брать фактическое число ненулевых разностей» УЖЕ является поведением рига; (2) ни один статус оси не меняется; (3) деньги не тратятся впустую. Части находки про масштаб («оптимистичен на порядки для контрастов близких армов», «наиболее уязвим A4», «эффективное n падает с 22 до ~5–12») — опровергнуты. Правильная починка — одна строка в докстринге плюс, по желанию, печать доли связок рядом с потолком; менять решающую арифметику нечего.",
|
||
"why": "ЧТО ПОДТВЕРДИЛОСЬ. Механизм реален и доли нулей воспроизводятся ТОЧНО. Пере-снял margins из сырья (`~/books/editor-tier/aj-{tier,border}-votes/*.json`, метрика — `absjudge.py:403-406` errors(b)−errors(a), целые): tier R0/T3 13/16=81%, R0/T1 10/16=62%, R0/T2 7/16=44%, border R0/R2 3/32=9% — совпало с находкой до единицы. Проверил достижимый минимум через сам риг: `sign_perm_p([0]*13+[1]*3)`=0.25 против формулы 3.05e-05; n=16/z=10 → 0.03125; n=9/z=4 → 0.0625; n=32/z=26 → 0.03125. Формула `power.py:109` связки игнорирует — это факт.\n\nПОЧЕМУ МАСШТАБ И ПОСЛЕДСТВИЕ НЕВЕРНЫ (четыре независимых основания).\n\n1. Отчётный p не искажён ВООБЩЕ. `eval/role_topology/bakeoff.py:484-500` — точный двусторонний перестановочный тест полным перебором 2^n при n≤20 и точной динамикой по достижимым суммам при n>20; нулевая разность просто не даёт вклада, и p выходит консервативно верным. Исполнил на боевом векторе R0/T3=[0]*10,−3,0,−1,1,0,0 → p=0.75. Никакое напечатанное в отчёте p не является оптимистичным. `grep -rn \"min_p\" eval/` даёт хиты ТОЛЬКО в `power.py` (107,141,192) — в `plan.py`/`runs.py`/`contour.py` его нет, на покупку он не влияет.\n\n2. Ни один статус не переворачивается. Порог поломки посчитал перебором: Д4 (n=32,k=3) — нужны нули ≥26 = 81%; Д3 (n=16,k=1) и Д1 (n=16,k=1) — ≥11 = 69%; Д6 (n=9,k=3) — ≥3 = 33%, но Д6 уже ⛔ОПИСАТЕЛЬНАЯ (`power.py` вывод: MDE 3.85 > цели 2.00 + FORCED_DESCRIPTIVE). А теперь замер по ВСЕМ 38 контрастам обоих проходов: доля нулей ≥44% встречается ИСКЛЮЧИТЕЛЬНО между околоидентичными армами над одной базой (R0/T3 81% sd 0.83 · R0/T1 62% sd 0.75 · R0/T2 44% sd 1.26) и 100% у вырожденной пары CTRLfloorA≡T1, которую Д0.6 (`docs/experiments/23-editor-tier.md:817-820`) уже запретила нормой. Все контрасты между армами РАЗНЫХ генераций — а первичные контрасты фазы именно такие (A1/A0, A3/A0, A6/A0, E0/D0, R1/R0) — лежат на 0–25%: F/R0 19% · border R0/R2 9% · CTRLdecoy/* 0–6%. До 69–81% им втрое.\n\n3. «Наиболее уязвим A4» неверно дважды. (а) `power.py:82-84`: A4 объявлен ВТОРИЧНЫМ, поправку не несёт, и там же сказано «его несущая ось — покрытие канона, а оно детерминировано и шума не имеет» — значимость знакового теста для A4 не является решающим числом по пре-регу. (б) Арифметика: при n=22 и k=1 недостижимость наступает при нулях ≥17 = 77%, а не при 44%; на цитированных находкой 44–81% нижняя половина диапазона безопасна с запасом (z=10 → min p 4.9e-04).\n\n4. Самый близкий случай вообще судится не p. Ровно там, где связок ожидаемо больше всего (A1/A3 против A0, H-2а «не хуже»), пре-рег Д0.4 (`docs/experiments/23-editor-tier.md:783-796`) заранее объявил решающим правилом non-inferiority по нижней границе 95% ДИ > −1.50, а не значимость. Потолок p на этот вердикт не влияет никак.\n\nПобочно (не входит в находку, но замерено тем же прогоном): доля нулей и sd на этом материале сильно анти-коррелированы — у КАЖДОГО контраста с ≥44% нулей sd ≤1.26 при прайоре 2.12, то есть режим «много связок» здесь же есть режим «мало шума». Это ассоциация на 38 точках, не гарантия, но она объясняет, почему потолок p и не был узким местом ни разу.\n\nКоманды: `eval/.venv/bin/python eval/dovodka/power.py`; разбор сырья и перебор порогов — скрипты в этом сообщении, все $0, сеть не трогалась, файлы не правились."
|
||
}
|
||
},
|
||
{
|
||
"title": "Множитель мощности берёт квантиль нормали вместо t, и одного этого хватает, чтобы Д4 перешла порог",
|
||
"severity": "мелко",
|
||
"evidence": "power.py:112-114,128 — _z() = statistics.NormalDist().inv_cdf. Правильный для парного теста при малом n множитель t_{1-α/2k,n-1}+t_{0.8,n-1}: при n=32,k=3 он 3.384 против z-версии 3.236 ⇒ MDE 1.560 вместо 1.491 (цель 1.50). При n=16,k=1 занижение 6.5%, при n=32 — 3.2%.",
|
||
"consequence": "Единственный «несущий» вердикт Д4 держится с запасом 0.6% (1.491 против 1.50) и переворачивается любой из трёх независимых поправок: t вместо z, n=30 вместо 32, измеренный sd вместо пола. Запас такого размера вердиктом не является.",
|
||
"fix": "Взять t-квантили (или решать уравнение мощности итеративно); печатать рядом с MDE запас до цели в процентах, чтобы пограничность была видна.",
|
||
"verdict": {
|
||
"line": "статистика",
|
||
"refuted": false,
|
||
"why": "МЕХАНИЗМ И ЧИСЛА ПОДТВЕРЖДЕНЫ ИСПОЛНЕНИЕМ.\n\n1) Улика точна по строкам. `eval/dovodka/power.py:112-114` — `def _z(p)` / `return statistics.NormalDist().inv_cdf(p)`; `:128` — `mult = _z(1 - 0.05 / (2 * max(1, k))) + _z(0.80)`. t-квантиля в файле нет ни одной (grep `inv_cdf|_z` даёт только эти строки + :193 в блоке «сколько единиц нужно»).\n\n2) Арифметика находки воспроизведена (`eval/.venv/bin/python`, scipy):\n n=32,k=3: множитель z 3.2356 против t(df=31) 3.3843 ⇒ MDE 1.4915 против 1.5601. Цель 1.50 ⇒ ось Д4 при t переходит из НЕСУЩЕЙ в ОПИСАТЕЛЬНУЮ. Фактический вывод рига: `power.py` печатает `Д4 edit-контур zh 32 3 2.12 1.49 1.50 0.0000 НЕСУЩАЯ`. Вердикт действительно переворачивается.\n Проценты занижения в улике даны для k=1 и там верны: n=16 ⇒ 6.5% (1.8264 vs 1.9542), n=32 ⇒ 3.1%. На СОБСТВЕННОМ k=3 оси Д4 занижение 4.4%, а не 3.2% — мелкая неточность подписи.\n\n3) Множитель t здесь уместен, а не спорен: решающий тест пака — `sign_perm_p` (`eval/role_topology/bakeoff.py:484`, «точный двусторонний знаковый ПЕРЕСТАНОВОЧНЫЙ тест», подключён в `absjudge.py:507,616`). Перестановочный тест по знакам — рандомизационный аналог парного t, его мощность практически совпадает с t-тестом. Так что контраргумент «формула вообще не про t, ведь тест непараметрический» не проходит: это не чистый знаковый тест по направлениям.\n\n4) Ограничение НЕ объявлено. В докстринге `mde()` (:118-127) названа ровно одна прошлая ошибка — константа 2.8 при k>1; про z-против-t не сказано ни в `power.py`, ни в Д0.3 отчёта (`docs/experiments/23-editor-tier.md:753-777`). Это не исполненная норма.\n\n5) Но ДВЕ поправки к формулировке.\n а) «Единственный несущий вердикт Д4» — НЕВЕРНО. Прогон `power.py` даёт ТРИ несущие оси: Д4, Д3 (1.83 против 2.00), Д1 (1.83 против 2.00). Под t Д3/Д1 дают 1.954 < 2.00 и остаются несущими. Переворачивается только Д4 — она несёт главную ставку владельца H-2б, но «единственной несущей» не является.\n б) Третья «независимая поправка» — «измеренный sd вместо пола» — это ПРЕ-ОБЪЯВЛЕННАЯ процедура, а не дефект: `power.py:98-102` и Д0.3 («если он выйдет хуже прайора, ось пере-классифицируется ТОГДА ЖЕ — до чтения боевых перевесов»). Считать её уликой хрупкости можно, уликой ошибки — нет.\n Вторая поправка, «n=30 вместо 32», грунтована сырьём: по `~/books/dovodka/*.json` A1 fixer = 30 клеток, A3 critic/fixer = 32/32, A4 fixer = 22, A6 = 16/16. При n=30,k=3 z-MDE = 1.5404 > 1.50 — ось падает и без t.\n\n6) ГЛАВНОЕ, что находка недосмотрела и что ослабляет её как «решающую улику»: пре-рег ЗАФРИЗИЛ для Д4 семейство из ПЯТИ контрастов (`23-editor-tier.md:836` — «семейство: A1/A0 · A2/A0 · A3/A0 · A4/A0 · A6/A0 Холм по пяти»), а `power.py` PRIMARY несёт k=3, вынеся A2 и A4 в SECONDARY. При пре-зарегистрированном k=5 z-MDE = 1.5753 > 1.50 — Д4 УЖЕ описательная, без всякой t-поправки; ровно это своими словами говорит докстринг `mde():124-126` («Д4 при k=5 давала MDE 1.57 против цели 1.50»). То есть z-вместо-t — не единственный и не первый рычаг: ось держится несущей за счёт сужения семейства 5→3 относительно фриза. Дополнительно: замороженная таблица Д0.3 в отчёте (1.29 / 1.83 / 3.33 при k=5/5/3) — это выход СТАРОЙ редакции с плоской 2.8 (2.8·2.12/√32·1.23 = 1.2907), и коду (1.49 / 1.83 / 3.85 при k=3/1/3) она больше не соответствует.\n\n7) Тяжесть «мелко» занижена: переворот касается оси, на которую уже потрачено $0.8719 фазового потолка ФД-A, и это ровно тот класс отказа (купленная недомощная ось), ради недопущения которого файл написан.\n\nКоманды, которыми получено: `eval/.venv/bin/python eval/dovodka/power.py`; расчёт t/z через scipy.stats.t.ppf; инвентарь клеток — прямой обход `~/books/dovodka/*.json` со счётом по (arm, role).",
|
||
"corrected": "Множитель мощности в power.py:128 берёт квантиль нормали (_z, :112-114) вместо t_{n-1}. На оси Д4 (n=32, k=3, sd 2.12) это даёт MDE 1.4915 вместо 1.5601 при цели 1.50, то есть печатает НЕСУЩАЯ там, где корректный множитель даёт ОПИСАТЕЛЬНУЮ. Занижение 6.5% при n=16,k=1 и 3.1% при n=32,k=1 (на собственном k=3 оси Д4 — 4.4%). t-квантиль здесь уместен: решающий тест пака — знаковый ПЕРЕСТАНОВОЧНЫЙ (bakeoff.py:484), рандомизационный аналог парного t. Ограничение нигде не объявлено. ПОПРАВКИ к исходной формулировке: (а) Д4 не «единственный несущий вердикт» — power.py печатает несущими также Д3 и Д1, они под t выживают (1.954 < 2.00); Д4 единственная переворачивается; (б) «измеренный sd вместо пола» — пре-объявленная процедура пере-классификации (power.py:98-102, Д0.3), не независимый дефект; реальны две поправки — t и фактическое n (A1 = 30 клеток по сырью, при n=30 z-MDE уже 1.5404 > 1.50); (в) z-вместо-t не первый и не решающий рычаг: пре-рег зафризил для Д4 семейство из ПЯТИ контрастов (23-editor-tier.md:836), а power.py несёт k=3 — при пре-зарегистрированном k=5 z-MDE = 1.5753 > 1.50, то есть ось описательная и без t-поправки, что докстринг mde():124-126 признаёт дословно; замороженная таблица Д0.3 (1.29/1.83/3.33) — вывод старой редакции с плоской 2.8 и коду больше не соответствует. Тяжесть — не «мелко»: на оси уже потрачено $0.8719."
|
||
}
|
||
},
|
||
{
|
||
"title": "Премисса «знаковый тест» неверна — риг считает знаково-ПЕРЕСТАНОВОЧНЫЙ, поэтому опасение про эффективность 0.64 не применимо; но мисноминация не бесплатна",
|
||
"severity": "мелко",
|
||
"evidence": "power.py называет тест знаковым в докстрингах строк 5, 11, 108, 118. Фактическая решающая статистика — absjudge.py:472 BO.sign_perm_p → bakeoff.py:484-512: точный двусторонний перестановочный тест на знаках СУММЫ (при n>20 — точная динамика по достижимым суммам). Его асимптотическая эффективность против парного t равна 1, поэтому форма mult·sd/√n для него уместна, и требуемое n формулой по этой причине НЕ занижается. Проверил численно: точный знаковый тест (только знаки) при n=32, α=0.05/3 дал бы MDE 2.135 и мощность 0.43 на цели 1.50 — но это не тот тест, который риг применяет.",
|
||
"consequence": "Само по себе вывод не меняет — это поправка к постановке. Но именно ярлык «знаковый» скрывает две вещи выше: связки (в перестановочном тесте нули так же выбрасываются из статистики) и рассогласование ДИ с тестом (перестановочный тест на среднем против bootstrap-ДИ среднего — они близки, но ДИ анти-консервативен).",
|
||
"fix": "Переименовать в power.py «знаковый» → «знаково-перестановочный» и указать file:line статистики (bakeoff.py:484), чтобы следующий ревьюер сверял формулу с тем тестом, который реально применяется.",
|
||
"verdict": {
|
||
"line": "статистика",
|
||
"refuted": true,
|
||
"corrected": "Оставить как ПОПРАВКУ К ЧУЖОЙ НАХОДКЕ, не как самостоятельную находку. Верная и ценная часть ровно одна: решающая статистика рига — знаково-ПЕРЕСТАНОВОЧный тест на сумме (bakeoff.py:484-522, вызывается absjudge.py:472/606/681, itog.py:81, verify_report.py:265), его ARE против парного t равна 1, поэтому форма mult·sd/√n в power.py уместна и требуемое n НЕ занижается; опасение про эффективность 0.64 снято. Числа проверены и совпадают до цифры (знаковый тест при n=32, sd_eff 2.12×1.23, α=0.05/3 дал бы MDE 2.1353 и мощность 0.4268 на цели 1.50; power.py mde(k=3)=1.4915). Утверждение «мисноминация не бесплатна» — снять: (а) ярлык стоит только в половине ПОТОЛКА ЗНАЧИМОСТИ (строки 5, 11, 108; строки 118 в списке нет — там докстринг mde(), теста не называющий), и там min_p=2^(1-n)·k ТОЧЕН и для перестановочного теста; (б) обе «скрытые» вещи не скрыты: нули в перестановочном тесте нейтральны ровно как выброшены в знаковом (p не меняется), а анти-консервативность bootstrap-ДИ объявлена дословно в bakeoff.py:487-489 как причина заведения sign_perm_p. Максимум остаётся косметика: дописать в power.py:11/108 «знаково-перестановочного» и сослаться на bakeoff.py:484 — правка нулевой цены, вывода не меняет, отдельной находкой не является. Если чинить power.py всё же будут, ценнее другое расхождение в том же файле: строка 13 объявляет решающим правилом «порог различимости» рига (2.8·sd/√n, verify23.py:151-152), а строка 121 — «p ХОЛМА < 0.05»; это два разных правила в одном докстринге.",
|
||
"why": "ИСПОЛНЕНО, не со слов. (1) `grep -n \"знаков\" eval/dovodka/power.py` → строки 5, 11, 108 и ТОЛЬКО они; `sed -n '116,120p'` показывает, что 118 — это `def mde(...)` и первая строка его докстринга «Минимально различимый эффект при 80% мощности и поправке Холма по k контрастам», никакого теста там не названо. Улика находки перечисляет 4 строки, одна из них выдумана — и именно та, что относится к половине MDE, где идентичность теста только и могла бы менять формулу. Реальный грунт формы 2.8·sd/√n — не тест, а пороговое правило рига: eval/editor_tier/verify23.py:151-152 «Порог различимости — решающее правило пака», eval/editor_tier/solscore.py:104, eval/editor_tier/axiscal.py:218. (2) Ярлык не несёт ЧИСЛОВОЙ ошибки в единственном месте, где применяется: min_p(n,k)=2^(1-n)·k точен и для перестановочного теста. Проверено вызовом настоящей функции: `sign_perm_p([3,1,2,5,4,1])` = 0.03125 = 2⁻⁵ (n=6), `sign_perm_p([1]*31+[7])` = 4.656612873077393e-10 = 2⁻³¹ (n=32) — совпадает с 2^(1-n) до бита. (3) Последствие «скрывает связки» опровергается исполнением: `sign_perm_p([2,3,1])` = `sign_perm_p([2,3,1,0])` = `sign_perm_p([2,3,1,0,0])` = 0.25 — нуль удваивает и hits, и знаменатель 2^n, p инвариантен, то есть нули нейтральны ровно как выброшены в знаковом тесте. Сама находка это и признаёт («нули так же выбрасываются»), значит ярлык тут не скрывает ничего. (4) Последствие «рассогласование ДИ с тестом» — ОБЪЯВЛЕННОЕ ограничение, а не скрытое: bakeoff.py:487-489 дословно «Bootstrap-ДИ отвечает на вопрос «где лежит среднее», а не «отличимо ли оно от нуля при этом n», и на 15 единицах даёт заметно более узкий интервал, чем точный тест» — это и есть анти-консервативность, названная причиной заведения sign_perm_p 07.08. По правилам ревью это исполненная норма. (5) «Мисноминация» преувеличена: собственный словарь рига в bakeoff.py:485 — «ТОЧНЫЙ двусторонний ЗНАКОВЫЙ ПЕРЕСТАНОВОЧНЫЙ тест», то есть «знаковый» в power.py — эллипсис внутри уже принятой терминологии, а не имя другого теста. (6) Что опровергнуть НЕ удалось — арифметику: воспроизвёл на eval/.venv/bin/python точный знаковый тест при n=32, α=0.05/3, sd_eff=2.12×1.23 → критическое c=24, мощность 0.4268 при δ=1.50, MDE(80%)=2.1353; power.py mult(k=3)=3.2356, MDE=1.4915 (при k=5 — 1.5753). Совпадает с заявленными 2.135/0.43. То есть верная часть находки — снятие чужого опасения про ARE 0.64 — стоит, но это поправка к ЧУЖОЙ находке, а не находка: собственная её тяжесть «мелко», собственное последствие «вывод не меняет», денег не тратит, ни один вывод пре-рега Д0 (docs/experiments/23-editor-tier.md:762-775) не двигает."
|
||
}
|
||
}
|
||
]
|
||
} |