Land stage 0 item 1: the bank holds its terms, and the audit found on disk a production-profile run, a July measurement of the same question, and a ratified editor-price input this phase never executed
This commit is contained in:
parent
62f8f6bef9
commit
cdc5a5f156
4 changed files with 626 additions and 1 deletions
|
|
@ -7534,3 +7534,177 @@ ln 38 = 3.64, то есть **примерно 3.1 sd — событие ред
|
|||
компонента одна — наклон раскладки: он в тексте не живёт по построению. Корреляция — справочно.
|
||||
* **Объём правки не предсказывает место `Z0` у читателя** (0.18, незначимо): «больше правил — лучше
|
||||
прочли» не наблюдается.
|
||||
|
||||
---
|
||||
|
||||
## Д50. Стадия 0 п.1 исполнена: банк держит термины — но главное найдено НЕ в замере, а на диске
|
||||
|
||||
**Дата:** 30.08.2026, полигон. **Стоимость: $0** (только артефакты на диске). Носитель прибора —
|
||||
`eval/dovodka/bank.py` (пре-регистрация в шапке файла, записана ДО первого числа).
|
||||
|
||||
### Д50.1. ⭐ Четыре вещи, которых консилиум не знал, и все они лежали на диске
|
||||
|
||||
Консилиум 30.08 назначил аудит прогона `acceptance`. Исполнение показало, что заказ был построен
|
||||
на неполной карте собственного архива:
|
||||
|
||||
1. **Рядом лежит более боевой прогон `rerun`** (11.07): промты `v1-reflow` вместо `v0-draft`,
|
||||
редактор БИЛИНГВ (D30.1), переведены 57/57 чанков против 54/57. Движковых промахов 27 против 55.
|
||||
2. **Лежит и сам БОЕВОЙ ПРОФИЛЬ — `rerun2-dspro`** (23.07, 5 глав): черновик `deepseek-v4-flash` +
|
||||
редактор **`deepseek-v4-pro`**, плюс арм `mistral-large-2512`, которого нет ни в одной нашей
|
||||
таблице моделей. ⇒ Утверждение фазы «боевой профиль недоступен без Шага 7 (~$2)» верно только
|
||||
про ОБЪЁМ (5 глав против 15), а не про наличие.
|
||||
3. **Эту работу уже делали в июле, и сильнее.** `docs/archive/PROGRESS-2026-07-10-13.md:149` — замер
|
||||
B5 D10 независимым скриптом: presence 91.0% (647/711), occurrence 95.8%, по типам (титулы —
|
||||
слабейший класс, 78.7%), классы промахов `decl_gap 0` · `inflection_gap 54` · `genuine_absent 10`,
|
||||
эффективная консистентность 98.6%.
|
||||
4. **Три редактора уже отсужены на боевой китайской паре** — `rerun2/RERUN_REPORT.md`: 56 игр на арм,
|
||||
судья `gemini-3.1-pro` + `grok-4.3`-фолбэк, шумовой пол замерен (14/14 tie на идентичном тексте).
|
||||
Ранг: **dspro 0.679 > glm-5 0.589 >> mistral 0.232**. ⇒ Оговорка консилиума §4 «вся наша фактура
|
||||
по дешёвым моделям АНГЛИЙСКАЯ» неверна для ВЫБОРА РЕДАКТОРА: он мерен на китайской паре.
|
||||
|
||||
⛔ **Класс ошибки один и он не про эти четыре пункта, а про фазу: «фаза не знала собственный архив».**
|
||||
Вчера тем же классом было «фаза не знала собственный бэкенд». Дешёвое лекарство очевидно и стоит $0:
|
||||
**прежде чем строить прибор — смотреть, не построен ли он.**
|
||||
|
||||
⛔ **ПЯТАЯ ТИХАЯ ПОЛОМКА ПЕРЕЕЗДА.** Июльские скрипты (`d10_consistency.py`, `audit.sh`, `reflow.py`,
|
||||
`extract.py`) НЕ ПЕРЕЖИЛИ переезд машины: `PROGRESS-2026-07-10-13.md:190` перечисляет их поимённо с
|
||||
пометкой «Всё ВНЕ git», и в каталоге остались только ДАННЫЕ. После путей `~/books`, обнулённых mtime
|
||||
и подчёркиваний в `.env` — четвёртая известная, а по счёту находок пятая. **Класс: что вне git, то
|
||||
переезд убивает молча.** `bank.py` заведён в git намеренно.
|
||||
|
||||
### Д50.2. Результат замера: гипотеза «банк держит» НЕ ОПРОВЕРГНУТА
|
||||
|
||||
Единица — пара (термин, чанк) со сработавшим ключом; принятое множество форм = `dst` ∪ `decl.forms`
|
||||
(ратифицированное D24.4). Эндпойнт — CONFIRMED (`approved`); с AMBIGUOUS спрашивать нельзя, движок
|
||||
её таковой не объявлял (`mempostcheck.go:52-64`).
|
||||
|
||||
| прогон / режим | пар | presence | взвешенная доля промахов | эффективная консистентность |
|
||||
|---|---|---|---|---|
|
||||
| `acceptance`, native | 375 | 98.9% | **0.23%** | 100.0% |
|
||||
| `acceptance`, substring | 390 | 98.5% | **0.62%** | 99.5% |
|
||||
| `rerun`, native | 531 | 97.4% | **0.91%** | 99.6% |
|
||||
| `rerun`, substring (методика июля) | 548 | 96.9% | **1.29%** | 99.3% |
|
||||
|
||||
⚠ Числа сняты с ФИНАЛЬНОЙ версии прибора. Промежуточная, до починки регистра, давала presence на
|
||||
0.5–0.9 пункта ниже; таблица едва не ушла в коммит с ними — см. Д50.4 п.4.
|
||||
|
||||
**Метрика A (порог 2%) — в пределах во всех четырёх сечениях.** Метрика B пробита в одном сечении
|
||||
единственным термином `炼化` и разобрана ниже как ЛОЖНАЯ.
|
||||
|
||||
⭐ **Взаимная верификация двух независимых реализаций через полтора месяца.** Мой прибор
|
||||
самостоятельно воспроизвёл июльские `decl_gap = 0`, `genuine_absent = 10` (до починки эвристики) и —
|
||||
поимённо — редчайший класс `古月 → Гуюэ` ровно в главах **18/0 и 20/1**, названных июльским отчётом.
|
||||
Совпадение поимённое, а не по величине.
|
||||
|
||||
### Д50.3. ⭐ Слепое пятно, которого не видит НИ ОДИН из двух приборов
|
||||
|
||||
Чтение кандидатов глазами дало находку, не сводимую к обоим счётчикам. Гл.18/ч0: оригинал
|
||||
`古月方源`, в переводе — **«Гу Юэ Фан Юань»**, тогда как канон банка — слитное «Гуюэ».
|
||||
|
||||
Почему молчат оба прибора: `古月方源` заведён **алиасом полного имени** (`glossary_aliases`,
|
||||
`alias_type=fullname`) к записи `方源 → Фан Юань`. Автомат движка берёт длиннейший ключ, ждёт в
|
||||
выходе «Фан Юань» — и находит его. Родовая приставка канону не соответствует, но её никто не
|
||||
проверяет: ожидаемая часть на месте. ⇒ **Дрейф ВНУТРИ составного имени не наблюдаем ни пост-чеком
|
||||
движка, ни `presence`-метрикой.** Дёшево чинится: проверять алиас-ключ на собственную канонную
|
||||
форму, а не только dst записи-хозяина.
|
||||
|
||||
### Д50.4. Четыре ложные тревоги МОЕГО прибора — все пойманы чтением, ни одна не опубликована
|
||||
|
||||
Прибор строился и правился в один заход, и каждая правка рождала новую ошибку — ровно вчерашний урок
|
||||
«правка правки не безопаснее правки», подтверждённый четырежды за один пункт плана:
|
||||
|
||||
1. ⛔ **Зелёный вердикт на ПУСТОМ знаменателе.** Парсер не понял формат `rerun` (там `--- чанк 0 ---`
|
||||
без флага), разобрал 0 чанков — и прибор напечатал «порог не пробит, гипотеза не опровергнута».
|
||||
Лечение — не только формат: заведён гейт `assert_measured`, отказывающий с кодом 2 при нулевом
|
||||
знаменателе. **Нулевой знаменатель — не «в пределах», а отсутствие замера.**
|
||||
2. ⛔ **Промахи на непереведённых чанках.** 4 чанка `acceptance` гейт покрытия не переводил вовсе;
|
||||
отсутствие термина там — дефект ПОКРЫТИЯ, не банка.
|
||||
3. ⛔ **Односимвольные ханьские ключи** `蛊`/`转`: `memory.go:319` удаляет такой ключ из автомата —
|
||||
записи не инжектировались НИКОГДА. Мой счёт спрашивал за них и дал ⛔ по метрике B.
|
||||
4. ⛔ **Регистр и чередование согласных.** `开窍 → «открытие апертуры»` считалось промахом при
|
||||
«Открытие апертуры удалось!» в тексте; `炼化 → «очистить и подчинить»` уезжало в кандидаты дрейфа,
|
||||
потому что «очистить»[:4] = «очис», а в тексте «очищает».
|
||||
|
||||
⚠ **Все семь «промахов» `炼化` — верный перевод** («очищает и подчиняет», «очистил и подчинил», «по
|
||||
очистке и подчинению») при **ПУСТОМ `decl.forms`**. Метрика B по нему пробита формально и по существу
|
||||
ложна: это дефект ЗАСЕВА глагольного термина, а не дрейф.
|
||||
|
||||
### Д50.5. ⛔ Что из этого — долг полигона (моя зона)
|
||||
|
||||
* **Глагольные и многословные термины засеяны без форм.** `炼化 → «очистить и подчинить»`,
|
||||
`forms=[]` — пост-чек по такому термину не может не врать. Требуется засев форм либо явное
|
||||
исключение класса из пост-чека.
|
||||
* **`inflection_gap` живёт** (16–17 CONFIRMED на `rerun`): мн.ч. дописано сидом v2 не всюду.
|
||||
* ⚠ **Осторожно, поправка к самому себе:** первая редакция этого разбора объявила июльскую задачу
|
||||
«дописать мн.ч.» НЕВЫПОЛНЕННОЙ — по чтению `books/gu-zhenren/guzhenren-seed.yaml`. Это неверно:
|
||||
рядом лежит **`guzhenren-seed-v2.yaml`**, и мн.ч. там есть («первобытные камни», «гу-мастеров»,
|
||||
«смертные»), плюс 8 новых записей. Класс ошибки: **вывод по первому найденному файлу без проверки,
|
||||
единственный ли он.** Поймано до публикации.
|
||||
|
||||
---
|
||||
|
||||
## Д51. ⭐⭐ Вход ратификации, висевший на фазе Д, исполнен: выбор редактора держится на цене, а цена перевернулась
|
||||
|
||||
**Дата:** 30.08.2026, полигон. **Стоимость: $0.** Носитель — пересчёт оплаченных клеток `rerun2`.
|
||||
|
||||
### Д51.1. Задача была поставлена ратифицированной нотой ЭТОЙ фазе и не исполнена
|
||||
|
||||
Цепочка, восстановленная по журналу решений (не по пересказу):
|
||||
|
||||
* **D39.22** (23.07): редактор = `deepseek-v4-pro`, интерим. Основания: судья №1 · лучшая проза и
|
||||
глоссарий · дефекты чинибельного класса · **«×2 дешевле glm»**.
|
||||
* **D39.117 п.3, строка 65 ЗАКРЫТА** (08.08): «движки dspro/glm-5 **неразличимы** (`A/B` +0.06
|
||||
p=0.95; `A_law/B` −0.69 порога не проходит) ⇒ **жилец редактора — вопрос ЦЕНЫ, то есть конфиг**».
|
||||
* **D39.137** (15.08): пере-пин вендора. «Посылка интерим-редактора D39.22 в ПИКЕ ПЕРЕВЁРНУТА —
|
||||
dspro пик ×1.26 ДОРОЖЕ glm-5… **Вход ратификации жильцов при фазе Д**» (`05-decisions-log.md:380`).
|
||||
|
||||
⇒ **Ратификация пере-выбора редактора формально висит на фазе Д с 15.08 и не исполнена.** Консилиум
|
||||
29–30.08 обсуждал «резать ли редакторскую стадию», не зная, что настоящий открытый вопрос —
|
||||
не «резать», а «кто в ней живёт по нынешней цене», и что он адресован именно нам.
|
||||
|
||||
### Д51.2. Замер: одна нагрузка, оба редактора, СОБСТВЕННЫЕ токены каждого
|
||||
|
||||
D39.137 считала контрфактику по оси цены **на токенах glm** и сама назвала это оговоркой. В `rerun2`
|
||||
есть лучшее: три арма редактора **на одном и том же оплаченном черновике**, каждый со своим расходом.
|
||||
|
||||
**Валидация метода — прежде результата:** пересчёт по СТАРОМУ прайсу воспроизводит записанный
|
||||
движком `cost_usd` **бит-в-бит на всех трёх армах** (glm $0.076583, dspro $0.040555, mistral
|
||||
$0.040093 — расхождение 0.0%). Значит прайс-таблица и формула те самые, которыми считал движок.
|
||||
|
||||
| редактор | prompt / cached / completion | нынешний прайс, 5 глав | книга 1500 глав | к glm |
|
||||
|---|---|---|---|---|
|
||||
| `glm-5` | 33 831 / 3 456 / 14 224 | $0.0766 | **$22.97** | — |
|
||||
| `deepseek-v4-pro`, пик | 39 795 / 8 192 / 30 779 | $0.1640 | **$49.19** | **×2.14** |
|
||||
| `deepseek-v4-pro`, офф-пик | те же | $0.0820 | $24.59 | ×1.07 |
|
||||
| `mistral-large-2512` | 39 119 / 1 232 / 13 689 | $0.0401 | $12.03 | ×0.52 ⛔ исключён D39.20 |
|
||||
|
||||
**Оговорка, снимающая часть разрыва:** из 11 записей арма dspro три — записи санитайзера по $0, а
|
||||
одна оборвалась по `finish=length` и пере-генерировалась. Обрыв — артефакт флора `min_max_tokens`
|
||||
8000, поднятого позже до 16000. Без него: пик $0.1238 → **книга $37.14 (×1.62)**, офф-пик $0.0619 →
|
||||
**$18.57 (×0.81)**.
|
||||
|
||||
### Д51.3. Что из этого следует и чего НЕ следует
|
||||
|
||||
* ⭐ **В ПИКЕ dspro дороже glm-5 при любом обращении с артефактом — в 1.6–2.1 раза.** Экономическое
|
||||
основание D39.22 в пиковые часы не просто ослабло, а сменило знак.
|
||||
* ⚠ **Уточнение к D39.137, и оно в сторону ХУДШЕГО для dspro.** Нота дала «офф-пик дешевле ×1.59»;
|
||||
на собственных токенах офф-пик даёт от ×1.07 ДОРОЖЕ до ×0.81 дешевле. Причина проста и видна в
|
||||
таблице: **dspro тратит вдвое больше completion-токенов** (30 779 против 14 224), чего контрфактика
|
||||
на чужих токенах увидеть не могла.
|
||||
* ⛔ **Из этого НЕ следует «менять редактора».** Три причины, и все три — не мои полномочия:
|
||||
(1) D39.117 закрыл строку 65 на «неразличимы», но неразличимость мерена ригом фазы, а судья
|
||||
`rerun2` ставил dspro первым (0.679 против 0.589) — приборы согласны лишь в том, что зазор мал;
|
||||
(2) пик у DeepSeek — только будни 01–04 и 06–10 UTC, то есть ответ зависит от РАСПИСАНИЯ прогона,
|
||||
а не только от модели; (3) выбор жильца — конфиг `backend/`, зона бэкенда и лендинг оркестратора.
|
||||
* ⛔ **Носитель решения врёт прямо сейчас.** `backend/configs/pipeline-c1.yaml:65` и
|
||||
`backend/configs/pipeline-arm-glm.yaml:6` до сих пор обосновывают выбор словами «×2 дешевле glm».
|
||||
Это устаревшее обоснование в БОЕВОМ конфиге. Правка — зона бэкенда; **пинг сдан этой секцией.**
|
||||
|
||||
### Д51.4. Дешёвый ход, который виден из этих же данных
|
||||
|
||||
Если жилец — вопрос цены (D39.117), то у вопроса есть ответ, не требующий смены модели:
|
||||
**гнать редакторскую волну в офф-пик.** Для DeepSeek офф-пик — это все выходные целиком и будни вне
|
||||
двух окон; скидка ровно ½ и не требует ни решения о модели, ни правки Go. На книге это разница
|
||||
между $49 и $25 у того же самого редактора, с которым фаза уже согласилась по качеству.
|
||||
⚠ Тарифная погода не климат: несущую архитектуру на скидочное окно не ставят, но ПЛАНИРОВЩИК волн —
|
||||
ровно то место, где расписание законно.
|
||||
|
|
|
|||
|
|
@ -6,6 +6,31 @@
|
|||
|
||||
# КОНСИЛИУМ 30.08 — АРХИТЕКТУРА ГЕНЕРАЦИИ, МОДЕЛИ, УБОРКА
|
||||
|
||||
> ⚠⚠ **ПОПРАВКИ ОТ 30.08 ПОСЛЕ ИСПОЛНЕНИЯ СТАДИИ 0 п.1 — ЧИТАТЬ ПРЕЖДЕ ТЕЛА.** Разбор — **Д50 и
|
||||
> Д51** отчёта `docs/experiments/23-editor-tier.md`. Консилиум строился на неполной карте
|
||||
> собственного архива, и четыре его положения этим затронуты:
|
||||
>
|
||||
> 1. ⛔ **§5 п.1 назначал аудит `acceptance`. Объект выбран неверно:** рядом лежит более боевой
|
||||
> `rerun` (11.07, промты `v1-reflow`, редактор-билингв, 57/57 чанков), а также **`rerun2-dspro`
|
||||
> (23.07) — настоящий БОЕВОЙ профиль с редактором `deepseek-v4-pro`** на 5 главах. «Боевого
|
||||
> профиля нет без Шага 7» верно про ОБЪЁМ, не про наличие.
|
||||
> 2. ✅ **Сам п.1 ИСПОЛНЕН, вывод: гипотеза «банк держит» в терминной половине НЕ ОПРОВЕРГНУТА** —
|
||||
> взвешенная доля промахов 0.23–1.29% при пороге 2%, эффективная консистентность 99.3–100%.
|
||||
> Прибор `eval/dovodka/bank.py` независимо воспроизвёл июльский замер, включая поимённое
|
||||
> совпадение редчайшего класса. **Работа уже делалась в июле; её скрипты погибли при переезде
|
||||
> (были вне git) — ПЯТАЯ тихая поломка того же класса.**
|
||||
> 3. ⛔ **§4 «вся наша фактура по дешёвым моделям АНГЛИЙСКАЯ» — неверно для ВЫБОРА РЕДАКТОРА.**
|
||||
> Три редактора отсужены на боевой китайской паре (`rerun2/RERUN_REPORT.md`, 56 игр на арм,
|
||||
> шумовой пол замерен): dspro 0.679 > glm-5 0.589 >> mistral 0.232.
|
||||
> 4. ⛔⛔ **§7 и §6 п.3 ставят вопрос не там.** Открытый вопрос не «резать ли редактора», а «кто в
|
||||
> нём живёт по нынешней цене» — и он адресован ФАЗЕ Д ратифицированной нотой **D39.137 от
|
||||
> 15.08** («вход ратификации жильцов при фазе Д»), не исполненной. Замер сделан (Д51):
|
||||
> **в пике `deepseek-v4-pro` дороже `glm-5` в 1.6–2.1 раза**, в офф-пик — от ×1.07 дороже до
|
||||
> ×0.81 дешевле. ⚠ Это ХУЖЕ для dspro, чем оценка самой D39.137 (×1.59 дешевле в офф-пик),
|
||||
> потому что та считала на чужих токенах, а dspro тратит вдвое больше своих.
|
||||
> ⛔ Боевой конфиг `backend/configs/pipeline-c1.yaml:65` до сих пор обосновывает выбор словами
|
||||
> «×2 дешевле glm» — устаревшее обоснование в живом файле; пинг бэкенду сдан в Д51.3.
|
||||
|
||||
**Заказ владельца дословно:** (1) насколько сложной делать архитектуру харнесса — качество без
|
||||
взлёта цены, с учётом банка памяти; что делает черновая модель; нет ли сдвигов в ландшафте;
|
||||
(2) на каких моделях выгодно ехать по цене/качеству; (3) нет ли ошибок в замерах и ошибок в выводах
|
||||
|
|
|
|||
|
|
@ -7,7 +7,36 @@
|
|||
> ⚠ Персист, не scratch (норма владельца 01.08): файл лежит в зоне и коммитится, потому что
|
||||
> эфемерный scratchpad умирает вместе с сессией.
|
||||
|
||||
## 0-БИС. ⭐⭐ ГЛАВНОЕ ПОСЛЕ КОНСИЛИУМА 30.08 — ЧИТАТЬ ПЕРВЫМ, ОСТАЛЬНОЕ НИЖЕ ИСТОРИЧНО
|
||||
## 0-ТРИ. ⭐⭐ СОСТОЯНИЕ НА ВЕЧЕР 30.08 — САМОЕ СВЕЖЕЕ, ЧИТАТЬ ПЕРВЫМ
|
||||
|
||||
**Стадия 0 п.1 ИСПОЛНЕНА.** Разбор — **Д50 и Д51** в `docs/experiments/23-editor-tier.md`, прибор —
|
||||
`eval/dovodka/bank.py` (в git намеренно), поправки к курсу — врезка в шапке `KONSILIUM-30-08.md`.
|
||||
|
||||
1. ✅ **Банк держит термины.** Взвешенная доля промахов CONFIRMED 0.23–1.29% при пороге 2%;
|
||||
эффективная консистентность 99.3–100%. Гипотеза в терминной половине НЕ ОПРОВЕРГНУТА.
|
||||
2. ⭐⭐ **Главное найдено не замером, а на диске.** Лежат: более боевой прогон `rerun`; **БОЕВОЙ
|
||||
профиль `rerun2-dspro` (редактор `deepseek-v4-pro`, 5 глав)**; июльский замер того же вопроса;
|
||||
**отсуженная на КИТАЙСКОЙ паре тройка редакторов** (dspro 0.679 > glm 0.589 >> mistral 0.232).
|
||||
3. ⭐⭐ **Ратифицированный вход фазы Д, висевший с 15.08, исполнен (Д51).** D39.117: жилец редактора —
|
||||
вопрос ЦЕНЫ. D39.137: посылка «dspro ×2 дешевле glm» перевёрнута. Замер на одной нагрузке
|
||||
собственными токенами: **в пике dspro дороже glm в 1.6–2.1×**, в офф-пик от ×1.07 дороже до ×0.81
|
||||
дешевле. Дешёвый ход без смены модели — **гнать редакторскую волну в офф-пик** (÷2).
|
||||
4. ⛔ **Пинги, сданные секцией (чужие зоны, сам не правил):** `pipeline-c1.yaml:65` и
|
||||
`pipeline-arm-glm.yaml:6` обосновывают выбор устаревшим «×2 дешевле glm»; `docs/PROGRESS.md:610`
|
||||
несёт снятую сильную форму «полей пола в банке нет вовсе, механизма не существовало».
|
||||
5. ⛔ **ПЯТАЯ тихая поломка переезда:** июльские скрипты замера (`d10_consistency.py` и др.) были ВНЕ
|
||||
git и погибли. Класс: **что вне git, то переезд убивает молча.**
|
||||
6. ⚠ **Четыре ложные тревоги собственного прибора, пойманные чтением, — Д50.4.** Из них главная:
|
||||
**прибор напечатал «гипотеза не опровергнута» на НУЛЕВОМ знаменателе**, когда парсер не понял
|
||||
формат. Заведён гейт `assert_measured` (код 2). Плюс: непереведённые чанки · односимвольные
|
||||
ханьские ключи вне автомата · регистр и чередование согласных.
|
||||
⚠ И поправка к себе: «долг полигона по мн.ч. не выполнен» — НЕВЕРНО, есть `guzhenren-seed-v2.yaml`;
|
||||
читал первый найденный файл, не проверив, единственный ли он.
|
||||
|
||||
**Остаток Стадии 0:** п.2 (разбор диффов по категориям) · п.3 (позиционный аудит панелей + латинский
|
||||
квадрат) · п.5 (базис Жаккара) · п.6 (уборка). П.4 — греп исполнен, находка в п.4 выше.
|
||||
|
||||
## 0-БИС. ⭐⭐ ГЛАВНОЕ ПОСЛЕ КОНСИЛИУМА 30.08 — ОСТАЛЬНОЕ НИЖЕ ИСТОРИЧНО
|
||||
|
||||
**Твой курс лежит в `eval/dovodka/KONSILIUM-30-08.md`.** Там итог шести раундов с архитектором,
|
||||
четырёх со скептиком и одного с разведкой: что установлено, что СНЯТО, план по стадиям, и что
|
||||
|
|
|
|||
397
eval/dovodka/bank.py
Normal file
397
eval/dovodka/bank.py
Normal file
|
|
@ -0,0 +1,397 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
bank.py — АУДИТ УДЕРЖАНИЯ БАНКА на движковых прогонах 蛊真人 (zh→ru, 25 глав).
|
||||
|
||||
Стадия 0 п.1 плана `eval/dovodka/KONSILIUM-30-08.md` §5. Стоимость $0: только артефакты на диске.
|
||||
|
||||
═══════════════════════════════════════════════════════════════════════════════════════════════
|
||||
⚠⚠ ПОПРАВКА КУРСА, НАЙДЕННАЯ ИСПОЛНЕНИЕМ 30.08 — ЧИТАТЬ ПРЕЖДЕ ЧИСЕЛ
|
||||
═══════════════════════════════════════════════════════════════════════════════════════════════
|
||||
Консилиум назначил аудит прогона `acceptance`, НЕ ЗНАЯ ДВУХ ВЕЩЕЙ:
|
||||
|
||||
1. ⭐ РЯДОМ ЛЕЖИТ БОЛЕЕ ПОЗДНИЙ И БОЛЕЕ БОЕВОЙ ПРОГОН `rerun` (11.07, `~/books/gu-zhenren/rerun/`).
|
||||
Он собран из боевого `pipeline-c1.yaml` post-D33 байт-в-байт: промты `v1-reflow` (не `v0-draft`),
|
||||
редактор БИЛИНГВ (D30.1), переведены все 57 чанков (у `acceptance` — 54 из 57). Движковых
|
||||
промахов там 27 против 55. ⇒ ОБЪЕКТ АУДИТА — ОБА, и `rerun` важнее.
|
||||
⚠ Боевым он всё равно НЕ является: редактор `glm-5`, а не `deepseek-v4-pro`.
|
||||
|
||||
2. ⛔ ЭТУ РАБОТУ УЖЕ ДЕЛАЛИ В ИЮЛЕ, и результат сильнее плановой заявки. `docs/archive/
|
||||
PROGRESS-2026-07-10-13.md:149` (замер B5 D10, независимый скрипт `rerun/d10_consistency.py`):
|
||||
presence 91.0% (647/711) · occurrence 95.8% (3072/3207)
|
||||
по типам: имена 98.6% · клички 100% · места 96.0% · термины 94.9% · ТИТУЛЫ 78.7%
|
||||
промахи: decl_gap 0 · inflection_gap 54 · genuine_absent 10 ⇒ эффективная 98.6%
|
||||
⛔ Сами СКРИПТЫ не пережили переезд машины — лежали ВНЕ git (`PROGRESS-2026-07-10-13.md:190`
|
||||
перечисляет их поимённо; в каталоге остались только данные). Это ЧЕТВЁРТАЯ тихая поломка
|
||||
переезда после путей `~/books`, обнулённых mtime и подчёркиваний в `.env`. Класс один:
|
||||
ЧТО ВНЕ GIT, ТО ПЕРЕЕЗД УБИВАЕТ МОЛЧА. Этот файл — в git намеренно.
|
||||
⇒ Июльские числа здесь не пересказываются как свои: они ЭТАЛОН СВЕРКИ. Совпадение = две
|
||||
независимые реализации через полтора месяца согласились. Расхождение = находка, а не шум.
|
||||
|
||||
═══════════════════════════════════════════════════════════════════════════════════════════════
|
||||
ПРЕ-РЕГИСТРАЦИЯ — ПРАВИЛО РЕШЕНИЯ ЗАПИСАНО ДО ПЕРВОГО ЧИСЛА
|
||||
═══════════════════════════════════════════════════════════════════════════════════════════════
|
||||
ЧТО МЕРЯЕМ. Вопрос 0 в его ТЕРМИННОЙ половине: удерживает ли банк канонные формы через 25 глав.
|
||||
Голосовая половина им НЕ закрывается ПО ПОСТРОЕНИЮ — колонки `first_person`/`speech` пусты 0/49
|
||||
(Д32.16, консилиум §5 п.1).
|
||||
|
||||
ЕДИНИЦА — пара (термин, чанк), в которой ключ термина СРАБОТАЛ в китайском оригинале чанка. Ровно
|
||||
это условие включает инжекцию записи в промт, поэтому только такие пары и подсудны.
|
||||
|
||||
ДИСПОЗИЦИИ (`backend/internal/membank/memory.go:121,650-663` — прочитано, не пересказано):
|
||||
approved → CONFIRMED (авторитетно) · auto/draft → AMBIGUOUS (кандидат, обязательности нет).
|
||||
Блок ограничений редактора — CONFIRMED-only (`memory.go:745-750`).
|
||||
⇒ ОСНОВНОЙ ЭНДПОЙНТ — CONFIRMED. С AMBIGUOUS-записи спрашивать соблюдения нельзя: движок её
|
||||
таковой не объявлял, и `mempostcheck.go:52-64` прямо зовёт наказание за неё инверсией контракта.
|
||||
|
||||
ПРИНЯТОЕ МНОЖЕСТВО ФОРМ = базовый `dst` ∪ `decl.forms`. Это РАТИФИЦИРОВАННОЕ D24.4, а не мой
|
||||
выбор: проверка одних косвенных давала 37 ложных промахов из 55 на этих же данных (nominative_gap).
|
||||
|
||||
ТРИ СТРУКТУРНЫХ ИСКЛЮЧЕНИЯ — каждое установлено кодом или данными, ни одно не «для красоты»:
|
||||
1. ЧАНКИ БЕЗ ПЕРЕВОДА. Гейт покрытия пометил их флагом и не переводил вовсе; в параллельном
|
||||
файле у них нет секции `[ПЕРЕВОД]`. Отсутствие термина там — дефект ПОКРЫТИЯ, не банка.
|
||||
⚠ Печатается отдельной строкой, а не заминается.
|
||||
2. ОДНОСИМВОЛЬНЫЕ ХАНЬСКИЕ КЛЮЧИ без `allow_short` (蛊, 转). `memory.go:319` УДАЛЯЕТ такой ключ
|
||||
из автомата — записи не инжектировались НИКОГДА, спрашивать за них нельзя. (В живом коде есть
|
||||
ещё и демот таких промахов, `mempostcheck.go:122`, но он от D39.39 — ПОЗЖЕ этих прогонов.)
|
||||
3. STICKY (scene-inertia, A5) — ключа в чанке нет по построению, `mempostcheck.go:31-33`
|
||||
исключает их сознательно. Тоже печатается числом.
|
||||
|
||||
ПРАВИЛО РЕШЕНИЯ (порог консилиума §5 п.1; двусмысленность его второй половины разрешена ЗДЕСЬ,
|
||||
до чисел, и разрешение объявлено явно):
|
||||
A. взвешенная доля промахов CONFIRMED > 2% ⇒ «банк держит» ложна в сильной форме;
|
||||
B. «любая сущность топ-50» двусмысленна — записей всего 49, и буквальное чтение убивает гипотезу
|
||||
одной случайной строкой. Читаю как проверку на СИСТЕМАТИЧЕСКИЙ провал ядра: термин из ТОП-10
|
||||
по весу ключа с долей промахнутых чанков >= 20%.
|
||||
⚠ Обе печатаются всегда и не пересматриваются после просмотра чисел.
|
||||
|
||||
КЛАССИФИКАЦИЯ ПРОМАХА (июльская номенклатура, чтобы числа были сравнимы):
|
||||
decl_gap — принятая форма есть, но её не увидели бы БЕЗ union D24.4 (контроль: должен быть 0);
|
||||
inflection_gap — основа dst присутствует в форме, которой в сиде НЕТ (обычно мн.ч.) ⇒ читатель
|
||||
видит верный термин, это дефект ЗАСЕВА, а не дрейф;
|
||||
genuine_absent — основы нет вовсе ⇒ КАНДИДАТ дрейфа, требующий чтения глазами. НЕ дрейф сам по себе.
|
||||
⚠ Граница признана честно: определитель основы здесь — ЭВРИСТИКА общего префикса, а не морфология
|
||||
(в движке стеммер настоящий). Поэтому `genuine_absent` объявляется КАНДИДАТОМ и подлежит чтению.
|
||||
|
||||
ДВА РЕЖИМА МАТЧИНГА, потому что эталоны построены по-разному:
|
||||
native — longest-match, как автомат движка (古月 внутри 古月漠北 не считается);
|
||||
substring — независимая подстрока на термин, как июльский скрипт: он этим и обошёл alias-слепое
|
||||
пятно D24.2, поймав 古月→Гуюэ ×2. Числа июля сравнивать нужно с ЭТИМ режимом.
|
||||
|
||||
ВТОРОЙ КОНТУР — СВЕРКА С ДВИЖКОВЫМ ПОСТ-ЧЕКОМ (`postcheck_gate: false` ⇒ флаггер пишет промахи в
|
||||
`retrieval_state`). Расхождение ЛЮБОГО знака — находка:
|
||||
движок нашёл, я нет ⇒ ложная тревога гейта (ожидаемо: базы писаны ДО фикса D24.4);
|
||||
я нашёл, движок нет ⇒ слепота гейта — то, чего он не смотрит.
|
||||
|
||||
ЧЕГО ПРИБОР НЕ УМЕЕТ: он не читает смысл — термин в правильной форме не на своём месте он засчитает.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import re
|
||||
import sqlite3
|
||||
import sys
|
||||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
|
||||
RUNS = {
|
||||
"acceptance": {
|
||||
"db": Path.home() / "books/gu-zhenren/acceptance/guzhenren-acc-a.db",
|
||||
"parallel": Path.home() / "books/gu-zhenren/acceptance/guzhenren-25ch-parallel.txt",
|
||||
"book_id": "guzhenren-acc-a",
|
||||
"note": "10.07, промты v0-draft, редактор glm-5 монолингв, 54/57 чанков переведены",
|
||||
},
|
||||
"rerun": {
|
||||
"db": Path.home() / "books/gu-zhenren/rerun/guzhenren-rerun.db",
|
||||
"parallel": Path.home() / "books/gu-zhenren/rerun/rerun-parallel.txt",
|
||||
"book_id": None, # берётся из базы: имя книги у пере-прогона своё
|
||||
"note": "11.07, промты v1-reflow, редактор glm-5 БИЛИНГВ, 57/57 чанков — ближе к боевому",
|
||||
},
|
||||
}
|
||||
|
||||
WEIGHTED_MISS_MAX = 0.02
|
||||
TOP_N = 10
|
||||
CORE_MISS_MAX = 0.20
|
||||
# Эвристика основы для КЛАССИФИКАЦИИ промаха (на сам вердикт не влияет — метрики A и B считают
|
||||
# промахи, а не классы, поэтому это число ничего подогнать не может).
|
||||
# ⚠ 4 знака ЛОМАЮТСЯ НА ЧЕРЕДОВАНИИ СОГЛАСНЫХ: «очистить»[:4] = «очис», а в тексте стоит «очищает» —
|
||||
# и верно переведённый термин уезжает в `genuine_absent`, то есть в кандидаты дрейфа. Поймано
|
||||
# чтением текста 30.08 на 炼化 → «очистить и подчинить»: все 7 его «промахов» суть верный перевод
|
||||
# при ПУСТОМ `decl.forms`. 3 знака чередование переживают; цена — более грубое сито.
|
||||
STEM_MIN = 3
|
||||
|
||||
CHAPTER_RE = re.compile(r"^【 Глава (\d+) 】", re.M)
|
||||
# ⚠ Флаг в скобках есть у `acceptance` и ОТСУТСТВУЕТ у `rerun` (`--- чанк 0 ---`). Первая редакция
|
||||
# требовала скобок — и на `rerun` разобрала НОЛЬ чанков, после чего прибор напечатал «порог не
|
||||
# пробит» и «гипотеза не опровергнута» НА ПУСТОМ ЗНАМЕНАТЕЛЕ. Отсюда же гейт `assert_measured`.
|
||||
CHUNK_RE = re.compile(r"^--- чанк (\d+)(?: \[([^\]]*)\])? ---$", re.M)
|
||||
HAN_RE = re.compile(r"[一-鿿]")
|
||||
|
||||
|
||||
def load_glossary(con, book_id):
|
||||
aliases = defaultdict(list)
|
||||
for term_id, alias in con.execute(
|
||||
"select term_id, alias from glossary_aliases where book_id=?", (book_id,)
|
||||
):
|
||||
aliases[term_id].append(alias)
|
||||
rows = []
|
||||
for (tid, src, dst, typ, status, gender, decl, allow_short) in con.execute(
|
||||
"select id, src, dst, type, status, gender, decl, allow_short "
|
||||
"from glossary where book_id=? order by id",
|
||||
(book_id,),
|
||||
):
|
||||
forms = []
|
||||
if decl:
|
||||
try:
|
||||
forms = [f for f in json.loads(decl).get("forms", []) if f]
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
keys = [src] + aliases[tid]
|
||||
# Структурное исключение 2: односимвольный ханьский ключ без allow_short в автомат не попал.
|
||||
eligible = [k for k in keys if allow_short or not (len(k) == 1 and HAN_RE.match(k))]
|
||||
rows.append(
|
||||
{
|
||||
"id": tid, "src": src, "dst": dst, "type": typ, "status": status,
|
||||
"gender": gender, "keys": eligible, "banned": [k for k in keys if k not in eligible],
|
||||
"decl_forms": forms, "accepted": sorted({dst, *forms}, key=len, reverse=True),
|
||||
"confirmed": status == "approved",
|
||||
"stem": dst[:STEM_MIN] if len(dst) >= STEM_MIN else dst,
|
||||
}
|
||||
)
|
||||
return rows
|
||||
|
||||
|
||||
def split_chunks(text):
|
||||
out = []
|
||||
chapters = list(CHAPTER_RE.finditer(text))
|
||||
for i, cm in enumerate(chapters):
|
||||
ch = int(cm.group(1))
|
||||
body = text[cm.end(): chapters[i + 1].start() if i + 1 < len(chapters) else len(text)]
|
||||
marks = list(CHUNK_RE.finditer(body))
|
||||
for j, km in enumerate(marks):
|
||||
seg = body[km.end(): marks[j + 1].start() if j + 1 < len(marks) else len(body)]
|
||||
translated = "[ПЕРЕВОД]" in seg
|
||||
zh, ru = (seg.split("[ПЕРЕВОД]", 1) if translated else (seg, ""))
|
||||
out.append((ch, int(km.group(1)), km.group(2) or "", zh.replace("[ОРИГ]", ""), ru,
|
||||
translated))
|
||||
return out
|
||||
|
||||
|
||||
def assert_measured(what, n, ctx):
|
||||
"""ГЕЙТ ПРОТИВ ЗЕЛЕНИ НА ПУСТОТЕ. Прибор, ничего не измеривший, обязан ОТКАЗАТЬ, а не напечатать
|
||||
«порог не пробит»: пустой знаменатель читается как успех и ровно так и был прочитан 30.08, когда
|
||||
парсер не понял формат `rerun` и вердикт «гипотеза не опровергнута» встал на нуле наблюдений."""
|
||||
if n <= 0:
|
||||
print(f"\n⛔⛔ ПРИБОР ОТКАЗЫВАЕТ: {what} = 0 ({ctx}). Вердикт НЕ выносится: "
|
||||
"нулевой знаменатель — это не «в пределах», это отсутствие замера.")
|
||||
sys.exit(2)
|
||||
|
||||
|
||||
def count_keys(zh, terms, mode):
|
||||
"""mode=native — longest-match (автомат движка); mode=substring — независимо на термин (июль)."""
|
||||
hits = {}
|
||||
if mode == "substring":
|
||||
for t in terms:
|
||||
n = sum(zh.count(k) for k in t["keys"])
|
||||
if n:
|
||||
hits[t["id"]] = n
|
||||
return hits
|
||||
occupied = bytearray(len(zh))
|
||||
ordered = sorted(
|
||||
(t for t in terms if t["keys"]),
|
||||
key=lambda t: max(len(k) for k in t["keys"]), reverse=True,
|
||||
)
|
||||
for t in ordered:
|
||||
n = 0
|
||||
for key in sorted(t["keys"], key=len, reverse=True):
|
||||
start = 0
|
||||
while (p := zh.find(key, start)) >= 0:
|
||||
if not any(occupied[p:p + len(key)]):
|
||||
occupied[p:p + len(key)] = b"\x01" * len(key)
|
||||
n += 1
|
||||
start = p + 1
|
||||
if n:
|
||||
hits[t["id"]] = n
|
||||
return hits
|
||||
|
||||
|
||||
def engine_state(con, book_id):
|
||||
st = {}
|
||||
for ch, idx, n_miss, detail, sticky, spoil, evict, exact in con.execute(
|
||||
"select chapter, chunk_idx, n_postcheck_miss, postcheck_detail, n_sticky, "
|
||||
"n_spoiler_blocked, n_evicted, n_exact_hits from retrieval_state where book_id=?",
|
||||
(book_id,),
|
||||
):
|
||||
items = json.loads(detail) if detail else []
|
||||
st[(ch, idx)] = {
|
||||
"confirmed_miss": {d["src"] for d in items if d.get("disp") == "confirmed"},
|
||||
"ambiguous_miss": {d["src"] for d in items if d.get("disp") == "ambiguous"},
|
||||
"n_miss": n_miss, "sticky": sticky, "spoiler": spoil,
|
||||
"evicted": evict, "exact": exact,
|
||||
}
|
||||
return st
|
||||
|
||||
|
||||
def classify(term, ru):
|
||||
"""Промах уже установлен: ни одной принятой формы нет. Чем он является?"""
|
||||
ru_low = ru.lower()
|
||||
if any(f and f.lower() in ru_low for f in term["decl_forms"]):
|
||||
return "decl_gap" # контроль: обязан быть 0 при union D24.4
|
||||
if term["stem"] and term["stem"].lower() in ru_low:
|
||||
return "inflection_gap" # основа есть, формы в сиде нет — дефект ЗАСЕВА
|
||||
return "genuine_absent" # КАНДИДАТ дрейфа, читать глазами
|
||||
|
||||
|
||||
def audit(run, mode, verbose):
|
||||
cfg = RUNS[run]
|
||||
con = sqlite3.connect(f"file:{cfg['db']}?mode=ro", uri=True)
|
||||
book_id = cfg["book_id"] or con.execute("select book_id from glossary limit 1").fetchone()[0]
|
||||
terms = load_glossary(con, book_id)
|
||||
by_id = {t["id"]: t for t in terms}
|
||||
chunks = split_chunks(cfg["parallel"].read_text(encoding="utf-8"))
|
||||
engine = engine_state(con, book_id)
|
||||
|
||||
print("=" * 98)
|
||||
print(f"АУДИТ УДЕРЖАНИЯ БАНКА — прогон `{run}` ({book_id}), режим матчинга: {mode}")
|
||||
print(f" {cfg['note']}")
|
||||
print(" правило решения — в шапке файла, записано ДО чисел")
|
||||
print("=" * 98)
|
||||
banned = sorted({k for t in terms for k in t["banned"]})
|
||||
print(f"записей {len(terms)}: confirmed {sum(t['confirmed'] for t in terms)}, "
|
||||
f"ambiguous {sum(not t['confirmed'] for t in terms)} | "
|
||||
f"ключей вне автомата (single-Han ban): {', '.join(banned) or '—'}")
|
||||
print(f"чанков {len(chunks)}, из них переведено {sum(c[5] for c in chunks)}; "
|
||||
f"строк retrieval_state {len(engine)}")
|
||||
assert_measured("разобрано чанков параллельного файла", len(chunks),
|
||||
f"формат {cfg['parallel'].name} не распознан")
|
||||
assert_measured("переведённых чанков", sum(c[5] for c in chunks), "нечего проверять")
|
||||
|
||||
fired, fired_w, miss_ch, miss_w = (defaultdict(int) for _ in range(4))
|
||||
klass = defaultdict(int)
|
||||
kandidaty, rows = [], []
|
||||
agree = only_engine = only_mine = 0
|
||||
|
||||
for ch, idx, flag, zh, ru, translated in chunks:
|
||||
if not translated:
|
||||
continue # структурное исключение 1
|
||||
hits = count_keys(zh, terms, mode)
|
||||
ru_low = ru.lower()
|
||||
eng = engine.get((ch, idx), {})
|
||||
eng_miss_all = eng.get("confirmed_miss", set()) | eng.get("ambiguous_miss", set())
|
||||
for tid, n in hits.items():
|
||||
t = by_id[tid]
|
||||
fired[tid] += 1
|
||||
fired_w[tid] += n
|
||||
# ⚠ РЕГИСТР: сравнение регистро-НЕчувствительное. Прямое `in` дало ложный промах на
|
||||
# 开窍 → «открытие апертуры» (гл.5/ч1): в тексте «Открытие апертуры удалось!» — термин
|
||||
# верен, заглавная лишь начинает предложение. Поймано чтением 30.08.
|
||||
held = any(f and f.lower() in ru_low for f in t["accepted"])
|
||||
if not held:
|
||||
miss_ch[tid] += 1
|
||||
miss_w[tid] += n
|
||||
k = classify(t, ru)
|
||||
klass[(k, t["confirmed"])] += 1
|
||||
if k == "genuine_absent" and t["confirmed"]:
|
||||
kandidaty.append((ch, idx, t["src"], t["dst"], t["type"], n))
|
||||
eng_miss = t["src"] in eng_miss_all
|
||||
if not held and eng_miss:
|
||||
agree += 1
|
||||
elif eng_miss and held:
|
||||
only_engine += 1
|
||||
rows.append(("ЛОЖНАЯ ТРЕВОГА ГЕЙТА", ch, idx, t["src"], t["dst"], t["status"], n))
|
||||
elif not held and not eng_miss:
|
||||
only_mine += 1
|
||||
rows.append(("СЛЕПОТА ГЕЙТА", ch, idx, t["src"], t["dst"], t["status"], n))
|
||||
|
||||
def block(conf, label):
|
||||
ids = [i for i in fired if by_id[i]["confirmed"] == conf]
|
||||
c_all, c_miss = sum(fired[i] for i in ids), sum(miss_ch[i] for i in ids)
|
||||
w_all, w_miss = sum(fired_w[i] for i in ids), sum(miss_w[i] for i in ids)
|
||||
print(f"\n--- {label} ---")
|
||||
print(f" пар (термин, чанк) со сработавшим ключом : {c_all}")
|
||||
print(f" из них промах (presence-провал) : {c_miss}"
|
||||
+ (f" ⇒ presence {1 - c_miss / c_all:.1%}" if c_all else ""))
|
||||
print(f" вхождений ключа всего / промахнуто : {w_all} / {w_miss}"
|
||||
+ (f" ⇒ occurrence {1 - w_miss / w_all:.1%}" if w_all else ""))
|
||||
return (w_miss / w_all) if w_all else 0.0, c_all, c_miss
|
||||
|
||||
weighted, conf_all, conf_miss = block(True, "CONFIRMED — ОСНОВНОЙ ЭНДПОЙНТ")
|
||||
assert_measured("пар CONFIRMED со сработавшим ключом", conf_all,
|
||||
"ни один подписанный ключ не сработал — матчер или данные не те")
|
||||
block(False, "AMBIGUOUS — справка: обязательности движок не объявлял")
|
||||
|
||||
print("\n--- классификация промахов (июльская номенклатура, для сверки) ---")
|
||||
for k in ("decl_gap", "inflection_gap", "genuine_absent"):
|
||||
c, a = klass[(k, True)], klass[(k, False)]
|
||||
note = {"decl_gap": "контроль union D24.4 — обязан быть 0",
|
||||
"inflection_gap": "дефект ЗАСЕВА (мн.ч.), не дрейф",
|
||||
"genuine_absent": "КАНДИДАТ дрейфа — читать глазами"}[k]
|
||||
print(f" {k:<16} confirmed {c:>4} ambiguous {a:>4} — {note}")
|
||||
eff_num = conf_all - klass[("genuine_absent", True)] - klass[("decl_gap", True)]
|
||||
if conf_all:
|
||||
print(f" эффективная консистентность CONFIRMED = {eff_num}/{conf_all} = {eff_num / conf_all:.1%}"
|
||||
" (читатель видит верный термин: инфлексия вне сида ему не мешает)")
|
||||
|
||||
print(f"\n--- метрика B: ядро (топ-{TOP_N} по весу ключа среди CONFIRMED) ---")
|
||||
core = sorted((i for i in fired if by_id[i]["confirmed"]),
|
||||
key=lambda i: fired_w[i], reverse=True)[:TOP_N]
|
||||
core_fail = []
|
||||
print(f" {'термин':<34}{'вес':>6}{'чанков':>8}{'промах':>8}{'доля':>7}")
|
||||
for i in core:
|
||||
share = miss_ch[i] / fired[i]
|
||||
if share >= CORE_MISS_MAX:
|
||||
core_fail.append(by_id[i]["src"])
|
||||
print(f" {by_id[i]['src'] + ' → ' + by_id[i]['dst']:<34}{fired_w[i]:>6}{fired[i]:>8}"
|
||||
f"{miss_ch[i]:>8}{share:>6.0%}{' ⛔' if share >= CORE_MISS_MAX else ''}")
|
||||
|
||||
print("\n--- ВТОРОЙ КОНТУР: сверка с движковым пост-чеком ---")
|
||||
print(f" согласие : {agree}")
|
||||
print(f" ⚠ ложная тревога гейта (форма В ТЕКСТЕ есть): {only_engine}"
|
||||
" ← ожидаемо: базы писаны ДО фикса D24.4")
|
||||
print(f" ⚠ слепота гейта (промах, гейт молчит) : {only_mine}")
|
||||
if verbose and rows:
|
||||
print(f" {'класс':<24}{'гл':>4}{'чанк':>6} {'src':<12}{'dst':<30}{'статус':<10}{'вес':>5}")
|
||||
for kind, ch, idx, src, dst, status, n in rows:
|
||||
print(f" {kind:<24}{ch:>4}{idx:>6} {src:<12}{dst:<30}{status:<10}{n:>5}")
|
||||
|
||||
if kandidaty:
|
||||
print(f"\n--- КАНДИДАТЫ ДРЕЙФА (genuine_absent, confirmed): {len(kandidaty)} — ЧИТАТЬ ГЛАЗАМИ ---")
|
||||
print(f" {'гл':>4}{'чанк':>6} {'src':<12}{'dst':<30}{'тип':<10}{'вес':>5}")
|
||||
for ch, idx, src, dst, typ, n in kandidaty:
|
||||
print(f" {ch:>4}{idx:>6} {src:<12}{dst:<30}{typ:<10}{n:>5}")
|
||||
|
||||
print("\n--- зоны, которые прибор НЕ судит (печатаются, а не заминаются) ---")
|
||||
print(f" чанков без перевода (гейт покрытия) : {sum(1 for c in chunks if not c[5])}")
|
||||
print(f" sticky-переносов (инерция сцены, A5) : {sum(e['sticky'] for e in engine.values())}")
|
||||
print(f" вытеснено бюджетом токенов : {sum(e['evicted'] for e in engine.values())}")
|
||||
print(f" спойлер-блокировок : {sum(e['spoiler'] for e in engine.values())}")
|
||||
|
||||
print("\n" + "=" * 98)
|
||||
a_fail = weighted > WEIGHTED_MISS_MAX
|
||||
print(f"МЕТРИКА A: взвешенная доля промахов CONFIRMED = {weighted:.2%} при пороге "
|
||||
f"{WEIGHTED_MISS_MAX:.0%} ⇒ {'⛔ ПОРОГ ПРОБИТ' if a_fail else 'в пределах'}")
|
||||
print(f"МЕТРИКА B: терминов ядра с долей промахов >= {CORE_MISS_MAX:.0%}: {len(core_fail)}"
|
||||
f"{' — ' + ', '.join(core_fail) if core_fail else ''} ⇒ "
|
||||
f"{'⛔ ПОРОГ ПРОБИТ' if core_fail else 'в пределах'}")
|
||||
print("ВЫВОД (строгий presence): гипотеза «банк держит» в СИЛЬНОЙ форме "
|
||||
+ ("⛔ ЛОЖНА" if (a_fail or core_fail) else "не опровергнута"))
|
||||
print("⚠ Границы: терминная половина Вопроса 0 · июльский профиль · редактор glm-5, не боевой "
|
||||
"deepseek-v4-pro.")
|
||||
print("=" * 98)
|
||||
|
||||
|
||||
def main():
|
||||
ap = argparse.ArgumentParser(description="аудит удержания банка, $0")
|
||||
ap.add_argument("--run", choices=[*RUNS, "both"], default="both")
|
||||
ap.add_argument("--match", choices=["native", "substring"], default="native",
|
||||
help="native — автомат движка; substring — как независимый июльский скрипт")
|
||||
ap.add_argument("--verbose", action="store_true", help="печатать построчную сверку с гейтом")
|
||||
a = ap.parse_args()
|
||||
for run in ([*RUNS] if a.run == "both" else [a.run]):
|
||||
audit(run, a.match, a.verbose)
|
||||
print()
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Loading…
Add table
Reference in a new issue