diff --git a/docs/PROGRESS.md b/docs/PROGRESS.md index 61703d8d..e876810a 100644 --- a/docs/PROGRESS.md +++ b/docs/PROGRESS.md @@ -619,6 +619,8 @@ * ⭐⛔ **30.08, ПОСЛЕ КОМПАКТА: КЛЮЧИ ПОЧИНЕНЫ ВЛАДЕЛЬЦЕМ, ПРОБНАЯ КЛЕТКА КУПЛЕНА ($0.038276) — И ГЛАВНОЕ ОНА ОТДАЛА БЕСПЛАТНО (Д45.5, Д46).** Несущая улика — не размер размышления, а **входные токены**: при побайтно одинаковых `messages` (sha256 сверен исполнением) вызов без параметра дал `prompt_tokens` **3270**, вызов с `reasoning_effort:"low"` — **3191**, то есть **−79**. **Два контроля детерминизма:** замер 05.08 (дефолт и `low` вернули ОДИНАКОВЫЕ 2124) и пред-полётные пробы самого рига (`84 · 84 · 84 · 84` на одном тривиальном запросе, четвёртая куплена 30.08 — то есть **дефолтный счёт входа не сдвинулся через смену вендорского сервинга**). ⇒ **параметр `low` на `deepseek-v4-pro` ТЕПЕРЬ ДОХОДИТ ДО МОДЕЛИ**, статус квирк-бюллетеня «НЕ УСТАНОВЛЕНО» закрыт в части «доходит ли» (новая запись **3г**). ⛔ **ВЕЛИЧИНА среза — НЕТ, и это находка против моего же пре-рега:** `RN` куплен 21.08, `RNL` — 30.08, а между блоками лежит **документированная смена вендорского сервинга** (её же зафиксировала вахта Д44) — сравнение приписывает ручке всё, что вендор поменял за девять дней; дрейф из §3б — второй конфаунд и слабее (у него есть знак, и он работает против нуля). Раздел Д45.3 «чего замер не закроет» не назвал НИ ОДНОГО — **дефект найден пере-чтением ПОСЛЕ фриза `87dd124`, печатаю против себя**. ⇒ ⭐ **Лечение одно: оба арма в ОДНОМ блоке вперемежку — и такой замер КУПИТЬ МОЖНО, вчетверо дешевле замороженного:** дизайн Д (интерливинг `RN2` против `RNL` на восьми дешёвых главах) стоит **$0.078–0.133** при свободных $0.2472, n=8 пар, минимальный двусторонний p = 0.0078; гард кассы его пропускает (проверено по коду, гард не тронут). **Пре-регистрация — Д47, заморожена коммитом, ⛔ НЕ КУПЛЕНО: санкция владельца была на ДРУГОЙ дизайн, переносить её я не вправе.** Рекомендация: пятнадцать клеток по фризу Д45 (дизайн А) **не покупать ни при каком ответе**; Д47 — по его слову. ⚠ **Первая редакция Д46 утверждала обратное — «ни один неконфаундированный дизайн не влезает» — и это было НЕВЕРНО** (пропущена дешёвая восьмёрка, при том что бимодальность нашла та же секция); сломал адверсариальный проход, разбор и цена ошибки — **Д46.6**, там же единственная находка прохода, которую я ОТКЛОНИЛ (корреляция по порядку вызовов: у всех 16 клеток `RN` один mtime, порядка не существует). Боевая ступень редактора **не тронута** (`eval/tenant_panel/roster.py` — правлен только комментарий, который до сегодня объяснял выбор снятой посылкой; гейт пака пере-снят, расхождение то же единственное mtime-шное). +* ⭐⭐ **30.08, Д47 ЗАПУЩЕН ПО САНКЦИИ ВЛАДЕЛЬЦА И ОСТАНОВЛЕН ГАРДОМ ПОСЛЕ ПЕРВОЙ ПАРЫ — А КУПЛЕННОЕ ОКАЗАЛОСЬ ЦЕННЕЕ ЭНДПОЙНТА (Д47.6).** Списано **$0.134804**, ФД-N 3.187585 из 3.30, потолок НЕ поднимался. **Побайтно один промт, одна глава `b065a92dc0`, `reasoning_effort` не слался НИ РАЗУ: 21.08 модель думала 466 токенов, 30.08 — 17 757. ×38.** Конфаунд, которым я двумя часами раньше обосновывал отказ от дизайна А, теперь ЗАМЕРЕН, а не выведен: пятнадцать клеток, сравнённых с августовским `RN`, дали бы число, целиком утонувшее в этом сдвиге. ⚠ При n=1 «сдвиг во времени» и «разброс розыгрыша на побайтно одном входе» (квирк п.2) неразличимы — и **второе чтение обвиняет уже МОЙ дизайн**: один розыгрыш на главу такого шума не переиграет. ⭐ Побочно Клейм 1 подтверждён на БОЕВОМ промте: `prompt_tokens` = **3256 и 21.08, и 30.08** (через девять дней и смену сервинга), а `low` двигает их ровно на **−79**; гейт провенанса пройден (Δpt=79, кириллица 1.000, латиница 0). **Эндпойнт по правилу: внутри блока ручка дала ×1.40** (меньше ×2.52, полученных через девять дней — конфаунд эффект РАЗДУВАЛ), годных пар 1 из 8, знаковый тест p=1.0 ⇒ ⛔ **«НЕ УСТАНОВЛЕНО»**, добор глав после чисел запрещён. Носитель — `eval/dovodka/stupen.py`, написан ДО прихода клеток, селфтест стережёт, что порог достижим только единогласием. ⛔ **Смета ошиблась на порядок, и это моя восьмая ошибка того же класса:** $0.078–0.133 объявлялись ценой ВОСЬМИ пар, одна пара стоила $0.1348 — **я оценил опыт по той самой базе, нестабильность которой опыт и должен был показать**. Доделать дизайн сегодня ≈$0.94 (подъём ФД-N на ~$0.85, резерв пака $1.09 покрывает) — **не рекомендую**, нужен пак с несколькими розыгрышами на главу. ⚠ Операционное для чужих циклов: отказ гарда возвращает код 1, но в ФОНОВОМ shell `set -e` цикл не остановил — семь итераций вхолостую, $0. + **📌 ПИНГ ПОЛИГОНУ от оркестратора №19 (28.08, D39.164) — вендор-вердикт по Gemini для `docs/experiments/00-provider-quirks.md`.** Материал добыт бэкенд-сессией (curl по вендор-доке, не пересказ), но файл — ВАША зона, поэтому вписываете вы, а не я. Строка 157 сегодня несёт три утверждения сильнее, чем даёт источник: diff --git a/docs/experiments/00-provider-quirks.md b/docs/experiments/00-provider-quirks.md index 9161014b..fc87630d 100644 --- a/docs/experiments/00-provider-quirks.md +++ b/docs/experiments/00-provider-quirks.md @@ -82,6 +82,8 @@ **3г. ⭐ ПОВЕДЕНЧЕСКАЯ ПРОБА 2026-08-30 (полигон, фаза Д, $0.038276): ПАРАМЕТР `low` НА `pro` ТЕПЕРЬ ДОХОДИТ ДО МОДЕЛИ.** Дока 3а требовала живой пробы перед денежным решением — вот она. **Несущая улика — не размер размышления, а `prompt_tokens`:** при **побайтно одинаковых** `messages` (sha256 `51e7f427940cae15`, проверено исполнением) вызов без параметра дал **3270** входных токенов, вызов с `reasoning_effort:"low"` — **3191**, то есть **−79**. Тело вызова различалось РОВНО одним полем (`eval/dovodka/rol.py:668`=`def call_kwargs`), исходник главы приколот манифестом с гейтом остановки (`eval/role_topology/pair_en.py:132`=`def units`), шаблон промта не менялся с 20.08, кэш смещения не даёт (две клетки с `cached_tokens=0` дали остатки −31.8 и +10.4 при разбросе ±20–44). **ДВА контроля детерминизма.** (1) Замер 05.08 ниже: при побайтно одинаковых `messages` дефолт и `low` вернули ОДИНАКОВЫЕ 2124 — провайдер повторяет `prompt_tokens` в точности, когда параметр не действует; ⚠ но он снят ДО смены сервинга и на другом промте. (2) **Межэпохальный контроль — пред-полётные пробы того же рига:** один и тот же тривиальный запрос БЕЗ ручки дал `prompt_tokens` = **84 · 84 · 84 · 84**, причём четвёртая куплена 30.08 за две минуты до испытуемого вызова ⇒ **дефолтный счёт входа не сдвинулся ни на токен через смену вендорского сервинга**, и −79 принадлежит параметру, а не эпохе. ⚠ **Регулярность без объяснения:** 2203 − 2124 = **79** (05.08, `xhigh` над дефолтом) и 3270 − 3191 = **79** (30.08, дефолт над `low`) на совершенно разных промтах — похоже на серверную вставку фиксированного размера, но это догадка. ⇒ **Статус `low` на `pro` закрыт В ЧАСТИ «доходит ли»: ДОХОДИТ.** ⛔ **ВЕЛИЧИНА среза размышления ПО-ПРЕЖНЕМУ НЕ УСТАНОВЛЕНА:** наблюдённые ×2.52 (19 559 → 7 748 токенов) сняты БЛОКАМИ, разнесёнными на 9 дней. ⛔ **Несущий конфаунд здесь — НЕ дрейф, а сама смена сервинга, зафиксированная выше в 3а:** вендор переписал маппинг между двумя блоками, и сравнение «арм 21.08 против арма 30.08» приписывает ручке всё, что он поменял. Дрейф (строка в 3б) — второй и более слабый: у него есть ЗНАК (все шесть розыгрышей монотонно РАСТУТ), и при его продолжении ×2.52 было бы нижней границей среза. Чтобы величина стала известной, нужен интерливинг обоих армов в ОДНОМ блоке; пре-регистрация и цены — `docs/experiments/23-editor-tier.md` §Д46.3 и §Д47 (дорогая восьмёрка $0.565–0.620, дешёвая — $0.078–0.133). ⚠ **Эхо на `low` у `pro`: одна английская клетка дала кириллицу 1.000 и ноль латиницы — это НЕ снимает предупреждение «Не бесплатно» ниже**, эхо-мина живёт на плотном CJK, а проба была на английской паре. + **3д. ⭐⭐ ЗАМЕРЕНО 30.08 ($0.134804, интерливинг Д47): ДЕФОЛТНЫЙ ПУТЬ `deepseek-v4-pro` СДВИНУЛСЯ ×38 ЗА ДЕВЯТЬ ДНЕЙ — ИЛИ РАЗБРОС РОЗЫГРЫША ТАКОВ.** Побайтно один промт (sha256 сверен), одна и та же глава, `reasoning_effort` НЕ слался ни разу: 21.08 модель думала **466** токенов, 30.08 — **17 757**. Цена той же клетки $0.005034 → $0.076893. ⚠ При n=1 «сдвиг во времени» и «разброс на побайтно одном входе» (п.2 выше) неразличимы — но для практики это одно и то же предупреждение: **любая смета DeepSeek, снятая с прошлого прогона, может ошибиться на порядок, и денежные планы на неё ставить нельзя**. Проверено на себе: пре-регистрация оценила восемь пар в $0.078–0.133, одна пара стоила $0.1348. ⭐ **Зато счёт ВХОДА через тот же разрыв стабилен до токена:** `prompt_tokens` = 3 256 и 21.08, и 30.08 при не-присланной ручке, а `low` сдвигает его ровно на −79 (3 177) — то есть провенанс параметра читается по входу даже там, где выход уехал ×38. ⚠ Наблюдённый ВНУТРИ ОДНОГО БЛОКА эффект ручки — ×1.40 (17 757 → 12 676), заметно меньше ×2.52, полученных сравнением через девять дней: конфаунд эффект РАЗДУВАЛ. n=1, знаковый тест p=1.0 ⇒ величина по-прежнему **НЕ УСТАНОВЛЕНА**; разбор — `docs/experiments/23-editor-tier.md` §Д47.6. + **3в. ВАХТА D39.92 ИСПОЛНЕНА ПОВТОРНО 2026-08-10 (полигон, фаза Д; $0, `curl` HTTP 200).** Таблица маппинга 3а на `guides/thinking_mode` **побайтно та же** (снята разбором ячеек ``: `low`→low/high · `high`→high/high · `xhigh`→high/**max** · `max`→max/max), и сноска (3) diff --git a/docs/experiments/23-editor-tier.md b/docs/experiments/23-editor-tier.md index 3638234a..6511cf15 100644 --- a/docs/experiments/23-editor-tier.md +++ b/docs/experiments/23-editor-tier.md @@ -6184,7 +6184,7 @@ n = 16 английских единиц = 7.89 главы Гу · k = 5 арм * **Находка 1 (декой) — диспозиция за приёмкой**, не за сессией. От неё зависит, считать ли Шаг 4 закрытым по букве или по цели. * **Находка 11** — пометы «контраст условный» на телах Д23/Д24 не поставлены. -* `docs/PROGRESS.md:673`=`ЖИВОЙ ДЕФЕКТ ДВИЖКА` — шапка пинга №19 теперь ложна дважды (дефект +* `docs/PROGRESS.md:675`=`ЖИВОЙ ДЕФЕКТ ДВИЖКА` — шапка пинга №19 теперь ложна дважды (дефект движка закрыт 28.08; терялся промт, а не глоссарий) и баннера не имеет. **Чужая зона, пинг дан.** --- @@ -7080,3 +7080,55 @@ RN» переносила отношение с САМОЙ ДУМАЮЩЕЙ гл ⇒ **Даже полный успех этого замера НЕ разрешает менять боевую ступень редактора.** Он двигает ровно одну клетку знания: «ручка режет» перестаёт быть вендорским заявлением и становится замером. + +### Д47.6 ⭐⭐ РЕЗУЛЬТАТ: КУПЛЕНА ОДНА ПАРА, ГАРД ОСТАНОВИЛ ОСТАЛЬНОЕ — И ЭТА ПАРА СТОИТ БОЛЬШЕ, ЧЕМ ЭНДПОЙНТ + +Санкция владельца 30.08 — дословно «Запускай». Прогон пошёл интерливингом, как заморожено: глава +`b065a92dc0`, сначала контроль `RN2` (ручка не шлётся), сразу за ним `RNL` на `low`. **Списано +$0.134804** (клетки $0.133588 + две пред-полётные пробы $0.001216). После первой же пары +**гард кассы отказал** — `потрачено $3.187585 + ожидание $0.131016 > потолок $3.30` — и семь +оставшихся пар не куплены. Потолок сессией не поднят. + +| клетка | когда | ручка | `prompt_tokens` | выход | **размышление** | цена | латентность | +|---|---|---|---|---|---|---|---| +| `RN` | 21.08 | не слалась | **3 256** | 1 052 | **466** | $0.005034 | 19.5 с | +| `RN2` | 30.08 | не слалась | **3 256** | 18 332 | **17 757** | $0.076893 | 260.8 с | +| `RNL` | 30.08 | `low` | **3 177** | 13 258 | **12 676** | $0.056695 | 173.0 с | + +⭐⭐ **ГЛАВНОЕ И НЕ ТО, ЗА ЧЕМ ШЛИ. Побайтно один промт, одна глава, ручка не слалась НИ РАЗУ — +и размышление 466 против 17 757, то есть ×38.** Конфаунд, названный в Д46.2 рассуждением, теперь +**замерен**, и он огромен. Это ретроспективно решает судьбу дизайна А: пятнадцать клеток `RNL`, +сравнённых с `RN` от 21.08, дали бы число, целиком утонувшее в этом сдвиге. + +⚠ **И приписать сдвиг нечему: при n=1 «время» и «разброс розыгрыша» неразличимы.** Квирк-бюллетень +п.2 давно печатает разброс на побайтно одном входе; сегодня он же мог сработать. **Оба чтения +обвиняют дизайн А — но второе обвиняет и МОЙ дизайн Д:** один розыгрыш на главу не переиграет шум +такого размера, каким бы ни было n. + +⭐ **Побочно — усиление Клейма 1 на БОЕВОМ промте, а не на тривиальной пробе.** `prompt_tokens` у +`RN` (21.08) и `RN2` (30.08) — **3 256 и 3 256, до токена**, через девять дней и смену вендорского +сервинга; а ручка `low` сдвигает их на **ровно 79** (3 177). Гейт провенанса Д47.3 пройден: +Δpt = 79 внутри полосы [60,100], кириллица 1.000, латиница 0, `finish=stop` у обеих клеток. + +**Эндпойнт — по правилу, а не по желанию.** Внутри блока `RNL` думал меньше `RN2` в **×1.40** +(17 757 → 12 676). Годных пар **1 из 8**, знаковый тест даёт **p = 1.0000** ⇒ ⛔ **«НЕ УСТАНОВЛЕНО»**, +и добор глав после взгляда на числа запрещён (Д47.3). Носитель вывода — `eval/dovodka/stupen.py`, +написан ДО прихода клеток. ⚠ Заметить стоит и то, что ×1.40 внутри блока **много меньше** ×2.52, +полученных сравнением через девять дней: конфаунд не просто мешал — он РАЗДУВАЛ видимый эффект. + +⛔ **МОЯ СМЕТА ОШИБЛАСЬ НА ПОРЯДОК, И ИРОНИЯ ТОЧНАЯ: я оценил опыт по той самой базе, нестабильность +которой опыт и должен был показать.** $0.078–0.133 объявлялись ценой ВОСЬМИ пар; одна пара стоила +$0.1348. Класс ошибки тот же, что у семи прежних: число взято из прошлого замера без вопроса, живо +ли оно. + +**Что стоило бы доделать дизайн сегодня:** семь пар по наблюдённой цене ≈ **$0.94**, то есть подъём +ФД-N примерно на $0.85 (резерв пака $1.090316 это покрывает). ⛔ **Не рекомендую.** Наблюдённый +внутриблочный эффект ×1.40 стоит против шума, который на соседней строке показал ×38; дизайн с +одним розыгрышем на главу против такого шума недомощен, и восемь пар этого не чинят. Вопрос +переносится в пак, который может позволить **несколько розыгрышей на главу на арм** — и цену +которого теперь считают по СЕГОДНЯШНЕЙ базе, а не по августовской. + +⚠ **Операционная заметка, чтобы не повторить:** отказ гарда возвращает код 1 (проверено), но в +фоновом shell `set -e` цикл не остановил — семь оставшихся итераций отработали вхолостую, печатая +тот же отказ. Денег это не стоило ($0: гард отклонил и пред-полётную пробу), но цикл на сотню клеток +в такой форме выглядел бы как прогон. Следующий цикл несёт `|| break` в теле, а не надежду на `set -e`. diff --git a/eval/dovodka/SESSION-30-08.md b/eval/dovodka/SESSION-30-08.md index 37a4e208..de10ea24 100644 --- a/eval/dovodka/SESSION-30-08.md +++ b/eval/dovodka/SESSION-30-08.md @@ -69,7 +69,21 @@ workaround, который канон запрещает («ошибка тих 3. ⭐ **Неконфаундированный замер КУПИТЬ МОЖНО, и он вчетверо дешевле замороженного** — дизайн Д: интерливинг `RN2` против `RNL` на восьми дешёвых главах, **$0.078–0.133** при свободных $0.2472, n=8, минимальный двусторонний p = 0.0078. Пре-регистрация — **Д47**, ⛔ **не куплено**. -⇒ **Вопрос владельцу: запускать ли Д47.** Рекомендация: (а) пятнадцать клеток по фризу Д45 — +⛔⛔ **Д47 ЗАПУЩЕН ПО СЛОВУ ВЛАДЕЛЬЦА («Запускай») И ОСТАНОВЛЕН ГАРДОМ ПОСЛЕ ПЕРВОЙ ЖЕ ПАРЫ.** +Списано **$0.134804**, ФД-N теперь 3.187585 из 3.30 (свободно $0.1124), потолок НЕ поднимался. +**Результат крупнее эндпойнта:** побайтно один промт, одна глава, ручка не слалась ни разу — 21.08 +модель думала **466** токенов, 30.08 — **17 757**, то есть **×38**. Конфаунд из Д46.2 замерен, а не +выведен. ⚠ При n=1 «время» и «разброс розыгрыша» неразличимы, и второе чтение обвиняет мой же +дизайн Д. Внутри блока ручка дала ×1.40 (меньше, чем ×2.52 через девять дней — конфаунд эффект +РАЗДУВАЛ); годных пар 1 из 8, p=1.0 ⇒ **величина НЕ УСТАНОВЛЕНА**, добор глав запрещён. ⭐ Побочно: +`prompt_tokens` = 3256 и 21.08, и 30.08, а `low` двигает их ровно на −79 — Клейм 1 подтверждён на +боевом промте. Доделать дизайн стоило бы ≈$0.94 (подъём ФД-N на ~$0.85) — **не рекомендую**: эффект +×1.40 против шума ×38, один розыгрыш на главу такого шума не переиграет. Разбор — **Д47.6**, +носитель вывода — `eval/dovodka/stupen.py` (написан ДО клеток). +⚠ **Операционное:** отказ гарда возвращает код 1, но в ФОНОВОМ shell `set -e` цикл не остановил — +семь итераций отработали вхолостую ($0). Следующий цикл покупок несёт `|| break` в теле. + +⇒ **Прежняя развилка (закрыта):** (а) пятнадцать клеток по фризу Д45 — **НЕ покупать** ни при каком ответе; (б) Д47 — по его слову. **Величина среза остаётся НЕ УСТАНОВЛЕННОЙ, и так и записана.** ⚠ **Первая редакция Д46 утверждала «ни один неконфаундированный дизайн не влезает» — ЭТО БЫЛО diff --git a/eval/dovodka/stupen.py b/eval/dovodka/stupen.py new file mode 100644 index 00000000..ea971844 --- /dev/null +++ b/eval/dovodka/stupen.py @@ -0,0 +1,155 @@ +#!/usr/bin/env python3 +"""ЭНДПОЙНТ ДИЗАЙНА Д (пре-рег Д47): РЕЖЕТ ЛИ `reasoning_effort:"low"` РАЗМЫШЛЕНИЕ У `pro`. $0. + +⚠ ЗАЧЕМ ОТДЕЛЬНЫЙ ФАЙЛ, а не счёт в уме отчёта. Правило решения Д47.3 написано ДО чисел, и оно +обязано применяться механически, иначе «правило до чисел» превращается в «правило под числа». +Файл написан ДО прихода клеток и коммитится вместе с ними: кто угодно пере-снимает вывод одной +командой и видит ровно то, что видел автор. + +ЧТО ЗДЕСЬ ЕСТЬ И ЧЕГО НЕТ: + * есть парный знаковый тест по восьми главам (`reasoning_tokens` у `RNL` против `RN2`); + * есть по-клеточный гейт годности В ТОЙ ФОРМЕ, В КАКОЙ ОН ЗАМОРОЖЕН, включая проверку + провенанса `Δprompt_tokens ∈ [60,100]` — она ловит клетку, до которой параметр НЕ доехал; + * НЕТ ни одной ручки, которой можно подвинуть порог: α, полосы и список глав — константы файла, + и селфтест стережёт, что они те же, что в отчёте. + +⛔ ОТНОШЕНИЯ (×N) ПЕЧАТАЮТСЯ КАК ОПИСАНИЕ, А НЕ КАК ВЫВОД. Дизайн Д стоит на восьми ДЕШЁВЫХ главах +(10.2% цены панели) — переносить их величины на дорогую моду запрещено там же, где выбраны главы. + +Запуск: eval/.venv/bin/python eval/dovodka/stupen.py [--selftest] +""" + +from __future__ import annotations + +import json +import math +import sys +from pathlib import Path + +ZONE = Path(__file__).resolve().parent +sys.path.insert(0, str(ZONE)) + +import rol # noqa: E402 + +OUT = Path.home() / "books" / "dovodka" + +# ── КОНСТАНТЫ ПРЕ-РЕГА Д47. Меняются только вместе с отчётом и только ДО покупок ─────────────── +CHAPTERS = ("b065a92dc0", "5a8f48d24a", "100b088f71", "49ca859c94", + "8e50448cea", "c3517980c7", "3bd6481182", "26c3bff1d4") +ARM_HIGH, ARM_LOW = "RN2", "RNL" # контроль (ручка не шлётся) и испытуемый (`low`) +ALPHA = 0.05 # двусторонний, Д47.3 +DPT_BAND = (60, 100) # провенанс параметра: ожидается 79 (Д46.1) +CYR_MIN = 0.99 # доля кириллицы среди букв +LAT_MAX = 0 # латиница-эхо + + +def _letters(t: str) -> tuple[int, int, int]: + """(букв всего, кириллических, латинских).""" + al = [c for c in t if c.isalpha()] + cyr = sum(1 for c in al if "а" <= c.lower() <= "я" or c.lower() == "ё") + lat = sum(1 for c in al if "a" <= c.lower() <= "z") + return len(al), cyr, lat + + +def _cell(arm: str, uid: str) -> dict | None: + f = OUT / f"{rol.tag('en', arm, uid)}.json" + return json.loads(f.read_text(encoding="utf-8")) if f.exists() else None + + +def sign_p(k: int, n: int) -> float: + """Точный двусторонний знаковый тест при p=0.5. k — сколько пар легли в ожидаемую сторону.""" + if n == 0: + return 1.0 + tail = sum(math.comb(n, i) for i in range(k, n + 1)) / 2 ** n + return min(1.0, 2 * tail) + + +def main() -> int: + rows, missing = [], [] + for uid in CHAPTERS: + hi, lo = _cell(ARM_HIGH, uid), _cell(ARM_LOW, uid) + if not hi or not lo: + missing.append(uid) + continue + n_al, cyr, lat = _letters(lo.get("content") or "") + share = cyr / n_al if n_al else 0.0 + dpt = hi["prompt_tokens"] - lo["prompt_tokens"] + bad = [] + if hi.get("finish") != "stop" or lo.get("finish") != "stop": + bad.append("finish≠stop") + if share < CYR_MIN: + bad.append(f"кириллица {share:.3f}") + if lat > LAT_MAX: + bad.append(f"латиница {lat}") + if not DPT_BAND[0] <= dpt <= DPT_BAND[1]: + bad.append(f"Δpt {dpt} вне [{DPT_BAND[0]},{DPT_BAND[1]}] — параметр не доехал") + rows.append(dict(uid=uid, hi=hi["reasoning_tokens"], lo=lo["reasoning_tokens"], + dpt=dpt, cyr=share, lat=lat, bad=bad, + cost=hi["cost_usd"] + lo["cost_usd"])) + + if missing: + print(f"⛔ клеток нет у глав: {' '.join(missing)} — эндпойнт неполон") + if not rows: + return 1 + + print(f"{'глава':12}{'RN2 дум':>9}{'RNL дум':>9}{'отнош':>8}{'Δpt':>6}{'кирилл':>8}" + f"{'лат':>5} гейт") + for r in rows: + ratio = r["hi"] / r["lo"] if r["lo"] else float("inf") + print(f"{r['uid']:12}{r['hi']:>9}{r['lo']:>9}{ratio:>8.2f}{r['dpt']:>6}" + f"{r['cyr']:>8.3f}{r['lat']:>5} " + f"{'OK' if not r['bad'] else '⛔ ' + ' · '.join(r['bad'])}") + + good = [r for r in rows if not r["bad"]] + n = len(good) + k = sum(1 for r in good if r["lo"] < r["hi"]) + p = sign_p(k, n) + ratios = sorted(r["hi"] / r["lo"] for r in good if r["lo"]) + med = ratios[len(ratios) // 2] if ratios else float("nan") + + print(f"\nгодных пар {n} из {len(CHAPTERS)} · размышление у `low` МЕНЬШЕ в {k} из {n}") + print(f"знаковый тест, двусторонний: p = {p:.4f} при пороге α = {ALPHA}") + print(f"цена прогона: ${sum(r['cost'] for r in rows):.6f}") + + # ── ПРАВИЛО Д47.3. Ветки написаны до чисел; ни одна из них ничего не «дозакупает» ────────── + print() + if n < len(CHAPTERS): + print("⚠ ПАР МЕНЬШЕ ВОСЬМИ: правило Д47.3 писалось на n=8. Вывод печатается по факту " + "годных пар и объявляется НЕПОЛНЫМ — добор до восьми ПОСЛЕ взгляда на числа запрещён.") + if k == n and p < ALPHA: + print(f"⭐ ЕДИНОГЛАСНО И ЗНАЧИМО: ручка РЕЖЕТ размышление. Медиана отношения ×{med:.2f} — " + "ОПИСАНИЕ этих восьми дешёвых глав, не перенос на дорогую моду и не на пару zh.") + elif p >= ALPHA: + print(f"⛔ НЕ ЗНАЧИМО (p = {p:.4f} ≥ {ALPHA}): «не установлено». Это РЕЗУЛЬТАТ, а не повод " + "докупать девятую главу — добор до значимости после чисел запрещён (Д47.3).") + else: + print(f"⛔ ЗНАЧИМО В ОБРАТНУЮ СТОРОНУ (k={k} из {n}): ручка размышление НЕ режет.") + return 0 + + +def selftest() -> int: + bad = 0 + + def ck(ok: bool, what: str) -> None: + nonlocal bad + print(f"[{'OK ' if ok else 'ПРОВАЛ'}] {what}") + bad += 0 if ok else 1 + + ck(len(CHAPTERS) == 8 and len(set(CHAPTERS)) == 8, "восемь глав пре-рега, без повторов") + rep = (ZONE.parents[1] / "docs" / "experiments" / "23-editor-tier.md").read_text(encoding="utf-8") + ck(all(u in rep for u in CHAPTERS), "все восемь глав названы в отчёте (пре-рег Д47.2)") + ck(ARM_HIGH in rol.ARMS and ARM_LOW in rol.ARMS, "оба арма есть в реестре покупок") + ck(rol.THINK_LEVEL.get(ARM_HIGH) is None and rol.THINK_LEVEL.get(ARM_LOW) == "low", + "контроль без ручки, испытуемый на `low`") + ck(rol.ARMS[ARM_HIGH][0] == rol.ARMS[ARM_LOW][0] == "deepseek-v4-pro", "модель у армов одна") + ck(rol.tag("en", ARM_HIGH, "x") != rol.tag("en", ARM_LOW, "x"), "теги армов не схлопываются") + # правило решения обязано быть НЕ достижимо ничем, кроме единогласия — это и есть цена n=8 + ck(sign_p(8, 8) < ALPHA <= sign_p(7, 8), "при n=8 значимость даёт ТОЛЬКО 8 из 8") + ck(abs(sign_p(8, 8) - 0.0078125) < 1e-9, "минимальный двусторонний p посчитан верно") + ck(sign_p(4, 8) == 1.0, "полный ноль эффекта даёт p = 1") + print(f"\n{'ПРИБОР ГОДЕН' if not bad else f'ПРОВАЛОВ: {bad}'}") + return bad + + +if __name__ == "__main__": + sys.exit(selftest() if "--selftest" in sys.argv else main())