Freeze the pre-registration of both second readings: name the baked-in answer path trap, the twelve-chapter subsample and the four metrics before any reader runs

This commit is contained in:
heaven 2026-08-23 02:02:05 +03:00
parent a1ce42200c
commit 03f585755a
2 changed files with 88 additions and 4 deletions

View file

@ -4558,3 +4558,78 @@ n = 16 английских единиц = 7.89 главы Гу · k = 4 арм
⇒ Шаг 7 («засеять характер-листы ПЕРЕД прогоном, иначе прибор консистентности померяет пайплайн
без носителя консистентности») перестал быть предосторожностью и стал требованием с числом.
---
## Д33 — ВТОРЫЕ ЧТЕНИЯ `vendor2` И `arch2` (Шаги 2 и 3 плана). ПРЕ-РЕГ, ЗАПИСАН ДО ЗАПУСКА
**Зачем.** Без второго чтения **ни одно наше «неразличимо» не имеет паспорта разрешения**: мы не
знаем, сколько в пороге прибора от текста, а сколько от читателя. Панель `vendor2` дополнительно
БЛОКИРУЕТ вердикт по вендорам (Д31 не печатается до метрики (ii) этой секции).
### Д33.0 ⛔ БЛОКЕР ПРОЦЕДУРЫ И ЕДИНСТВЕННЫЙ ПРАВИЛЬНЫЙ ОБХОД
**Путь файла ответа ВПЕЧАТАН В САМ ПАКЕТ** (`Что записать — в файл /home/ubuntu/books/chtenie-rol/
ОТВЕТ-en-vendor2-<uid8>.md`). Отсюда две мины сразу:
* «пусть второй пишет в другой каталог» невозможно **без правки пакета**, а правка пакета
превращает замер разброса ПРИБОРА в замер разницы ПРОМТОВ;
* если пакет не трогать и просто запустить второго — он получит путь к ответу первого,
**перезапишет его либо увидит**, и согласие читателей окажется сфабрикованным молча.
**Процедура, которая обходит обе:** ответы первого круга ПЕРЕНОСЯТСЯ в подкаталог `r1/` ДО запуска;
пакеты не трогаются вовсе; второй читатель пишет по прежнему впечатанному пути в пустой каталог;
после прогона его ответы уезжают в `r2/`. Ключи НЕ пере-эмитируются. Промт чтения — тот же байт в
байт, потому что это ТОТ ЖЕ ФАЙЛ. Счёт файлов до и после переноса печатается: ни один не потерян.
⚠ Инструмент: `rol.py --score-arch … --answers=r1|r2`. Параметр заведён только под это и умеет
ровно одно — читать ответы из подкаталога; логика свода не тронута.
### Д33.1 ПОДВЫБОРКА: 12 ГЛАВ, И ОНА ОБЪЯВЛЕНА ДО ЧТЕНИЯ
Решение владельца 22.08 — **стандарт панели 6 глав Гу**, то есть 12 английских единиц; план прямо
говорит «вторые чтения гнать на подвыборке, не на всей панели». Обе панели несут ОДНИ И ТЕ ЖЕ
15 глав, поэтому подвыборка у них общая. Правило отбора — **порядок захода Д17** (соль
`zakhod-d17-2026-08-16`, зафризена 16.08 ДО всех покупок; отбор по хешу не коррелирует с
содержанием):
```
ВХОДЯТ (12): f2274720 53f1a12d b065a92d 26c3bff1 49ca859c 197f98eb
d3237e1d eefdade2 27cb3a7e 3bd64811 8e50448c 90a20cb4
НЕ ВХОДЯТ (3): 001e6ac4 5a8f48d2 c3517980
```
**Оговорка, которую надо сделать до чисел:** три невошедшие главы — ровно те, где панель-0 нашла
дефекты рода. Это совпадение хеш-порядка, а не отбор: подвыборка выбрана правилом, замороженным
16.08, задолго до того, как класс «род» вообще появился. Но знать об этом надо, и на класс «род»
второе чтение по этой причине сказать ничего не сможет.
**Сравнение кругов идёт на ОДНИХ И ТЕХ ЖЕ 12 главах.** Первый круг пере-считывается на этой же
подвыборке (`--drop=001e6ac4,5a8f48d2,c3517980`), иначе разница кругов смешалась бы с разницей
выборок. Опубликованные вердикты на 15 главах остаются как есть и печатаются рядом.
### Д33.2 МЕТРИКИ, ОБЪЯВЛЕННЫЕ ДО ЗАПУСКА
1. **(i) Согласие порядков.** Спирмен между порядком читателя-1 и читателя-2 по каждой главе,
медиана и разброс по главам.
2. **(ii) Пере-счёт ВСЕХ контрастов на втором круге** и **счёт перевёрнутых вердиктов** («различим»
↔ «в пределах»), отдельной строкой — маржевые `RK` (порог пройден, знаковый p=0.1185) и `RE`
(порог не пройден, p=0.0352).
3. **(iii) Доля дисперсии РАЗНОСТЕЙ ЧИТАТЕЛЕЙ в дисперсии парной разности армов** — это и есть
ответ на «сколько в пороге от прибора, а сколько от текста».
4. **(iv) Держится ли знаковый p у `RKT`** (единственный вендор-вердикт, прошедший конъюнкцию).
**Правило чтения результата, объявленное ДО:**
* вердикт, перевернувшийся на втором круге, объявляется **читательским, а не текстовым** — и
снимается из живых, а не «уточняется»;
* если доля (iii) велика, все пороги фазы — это в основном шум прибора, и любое «неразличимо»
обязано печататься с этой долей рядом;
* ⛔ **одно семейство читателей меряет ШУМ, а не ВКУС.** Согласие двух чтений `fable-5` не говорит
ничего о том, согласился бы владелец: ось ВЕРНОСТИ у него разошлась с прибором радикально
(Д30, Шаг 8). Второе чтение закрывает разброс, а не правоту.
### Д33.3 ДИСЦИПЛИНА ПРОГОНА
Новые сессии, занятые `runs.py --claim` ДО запуска и закрытые после · один читатель на главу ·
читателю закрыты ключи, чужие пакеты, чужие ответы, код и отчёт · после прогона — аудит слепоты
грепом по всем ответам (упоминания вендоров и моделей обязаны быть НУЛЁМ).

View file

@ -1266,9 +1266,16 @@ def verify_read(tag_: str, p: str) -> int:
return 1 if bad else 0
def score_arch(tag_: str = "arch2", p: str = "en", drop: tuple = (), anchor: str = "") -> int:
def score_arch(tag_: str = "arch2", p: str = "en", drop: tuple = (), anchor: str = "",
ansdir: str = "") -> int:
"""`drop` — РЫЧАГ ЧУВСТВИТЕЛЬНОСТИ, не способ получить нужный ответ. Печатается в шапке свода,
и вывод, который живёт только при выброшенной главе, обязан называться вместе с ней."""
и вывод, который живёт только при выброшенной главе, обязан называться вместе с ней.
`ansdir` ПОДКАТАЛОГ ОТВЕТОВ, и он заведён под ВТОРОЕ ЧТЕНИЕ (Шаги 23 плана 22.08). Путь
файла ответа ВПЕЧАТАН В САМ ПАКЕТ, поэтому второй читатель обязан писать по тому же пути, что
первый; развести круги можно только ПЕРЕНОСОМ уже готовых ответов в свой подкаталог. Править
пакет ради нового пути НЕЛЬЗЯ: тогда замер сравнил бы разницу промтов, а не разброс прибора.
"""
keys = sorted((OUT / "blind-keys-rol").glob(f"rol-KEY-{tag_}-*.json"))
keys = [k for k in keys if k.stem.split(f"{tag_}-")[1] not in drop]
if not keys:
@ -1281,7 +1288,7 @@ def score_arch(tag_: str = "arch2", p: str = "en", drop: tuple = (), anchor: str
if p not in key: # ключ другой пары под тем же тегом — не наш
continue
lay = key[p]["1"]["метки"]
af = READ_DIR / f"ОТВЕТ-{p}-{tag_}-{uid8}.md"
af = (READ_DIR / ansdir) / f"ОТВЕТ-{p}-{tag_}-{uid8}.md"
if not af.exists():
bad.append((uid8, "ответа нет"))
continue
@ -1304,6 +1311,7 @@ def score_arch(tag_: str = "arch2", p: str = "en", drop: tuple = (), anchor: str
ident.append((uid8, abs(r["Z7"] - r["ZP"])))
n = len(twins)
print(f"\n=== СВОД {tag_}, пара {p}: глав отсужено {n} из {len(keys)} ==="
+ (f" · ответы из {ansdir}/" if ansdir else "")
+ (f"\n ⚠ ВЫБРОШЕНЫ ГЛАВЫ: {', '.join(drop)} — свод УСЛОВНЫЙ" if drop else ""))
for uid8, why in bad:
print(f"{uid8}: {why}")
@ -1401,7 +1409,8 @@ if __name__ == "__main__":
_tag = next((x.split("=", 1)[1] for x in a if x.startswith("--tag=")), "arch2")
_drop = tuple(next((x.split("=", 1)[1].split(",") for x in a if x.startswith("--drop=")), []))
_anch = next((x.split("=", 1)[1] for x in a if x.startswith("--anchor=")), "")
sys.exit(score_arch(_tag, next((x for x in a[1:] if x in PAIRS), "en"), _drop, _anch))
_ans = next((x.split("=", 1)[1] for x in a if x.startswith("--answers=")), "")
sys.exit(score_arch(_tag, next((x for x in a[1:] if x in PAIRS), "en"), _drop, _anch, _ans))
elif a[0] == "--coverage":
for p in ([x for x in a[1:] if x in PAIRS] or list(PAIRS)):
print(f"\n=== ПОКРЫТИЕ БОЕВЫХ ПРОМТОВ, пара {p} ===")