textmachine/eval/tenant_panel/checks21.py

132 lines
7.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""Ф0.3 — ПРОВЕРКА ИСПОЛНЕНИЕМ четырёх починок, заказанных эксп-21 §8. $0.
Промт эксп-22 объявляет их обязательными ДО первой покупки. Список §8 писался как «что надо
сделать», и часть пунктов эксп-21 закрыл сам, не вычеркнув из списка. Поэтому здесь не чтение
кода, а ЗАПУСК: каждый пункт проверяется на входе с известным ответом, а где возможно — на том
самом артефакте, из-за которого пункт появился.
§8-1 гейт ре-гена черновика обязан ловить и целевую письменность (был принят и оплачен
английский выход с долей латиницы 0.79);
§8-2 карта раскладки слепого чтения лежит ВНЕ каталога пакетов;
§8-3 обоснование судьи персистируется, и голос с ненулевой осью без цитаты отвергается;
§8-4 три докстринга, названные лживыми, больше не противоречат исполняемому коду.
Ненулевой код возврата = покупать нельзя.
"""
from __future__ import annotations
import io
import json
import re
import sys
from contextlib import redirect_stdout
from pathlib import Path
REPO = Path("/home/ubuntu/projects/textmachine")
ZONE = REPO / "eval" / "role_topology"
sys.path.insert(0, str(ZONE))
RAW21 = Path.home() / "books" / "role-topology"
BAD = 0
def chk(name: str, ok: bool, detail: str = "") -> None:
global BAD # noqa: PLW0603
BAD += not ok
print(f"[{'OK ' if ok else 'ПРОВАЛ'}] {name}" + (f" {detail}" if detail else ""))
def c1_draft_gate() -> None:
"""Гейт письменности: пустой · эхо исходника · не целевой язык · годный."""
import bakeoff as BO # noqa: PLC0415
chk("§8-1 пустой выход отвергнут", bool(BO.draft_reject_reason(" ")))
chk("§8-1 эхо исходника отвергнуто",
BO.draft_reject_reason("第一章 蛊真人转世重生,方源看着眼前的青茅山,心中冷笑" * 8)
== "эхо исходника")
chk("§8-1 английский выход отвергнут",
BO.draft_reject_reason("The young man looked at the mountain and smiled coldly. " * 8)
== "выход не на целевом языке")
chk("§8-1 русский выход принят",
BO.draft_reject_reason("Юноша посмотрел на гору и холодно усмехнулся. " * 8) == "")
# Регрессия на ТОМ САМОМ артефакте: он оплачен и принят прежним гейтом.
f = RAW21 / "bo2-DRAFT-34749d6ccc-r2.json"
if f.exists():
why = BO.draft_reject_reason(json.loads(f.read_text(encoding="utf-8"))["content"])
chk("§8-1 исторический артефакт (латиница) отвергается", why != "", f"вердикт: {why!r}")
else:
chk("§8-1 исторический артефакт доступен", False, f"нет {f}")
def c2_blind_map() -> None:
"""Карта раскладки не должна лежать в каталоге, который отдают читателю."""
import blind_read as BR # noqa: PLC0415
chk("§8-2 карта вне каталога пакетов", BR.KEYS.resolve() != BR.PACKETS.resolve(),
f"пакеты {BR.PACKETS.name} · карта {BR.KEYS.name}")
maps = list(BR.KEYS.glob("*-MAP.json")) if BR.KEYS.exists() else []
stray = list(BR.PACKETS.glob("*MAP*")) if BR.PACKETS.exists() else []
chk("§8-2 карт в каталоге пакетов нет", not stray, f"карт в ключах: {len(maps)}")
def c3_judge_reasons() -> None:
"""Ненулевая ось без цитаты обязана быть отвергнута, и отказ обязан снимать прежний голос."""
import absjudge as AJ # noqa: PLC0415
buf = io.StringIO()
with redirect_stdout(buf):
rc = AJ.selfcheck()
out = buf.getvalue()
chk("§8-3 selfcheck рига без провалов", rc == 0, f"провалов {rc}")
for probe in ("ненулевая ось без цитаты отвергнута",
"голое имя оси без цитаты отвергнуто",
"отказ СНЯЛ прежний годный голос"):
chk(f"§8-3 регрессия «{probe}»", f"[OK ] {probe}" in out)
# Персист: у боевых голосов эксп-21 обоснование обязано быть непустым там, где ось ненулевая.
votes = list((RAW21 / "aj-abs4-votes").glob("*.json"))
if votes:
bad = 0
tot = 0
for f in votes:
for r in json.loads(f.read_text(encoding="utf-8")).values():
tot += 1
if sum(r.get(a, 0) for a in ("ВЕРНОСТЬ", "ТЕРМИН", "ЯЗЫК", "ФОРМА")) and \
not (r.get("why") or "").strip():
bad += 1
chk("§8-3 боевые голоса несут обоснование", bad == 0, f"{tot - bad}/{tot} клеток с текстом")
def c4_docstrings() -> None:
"""Три докстринга, названные лживыми. Проверяем ПРОТИВОРЕЧИЕ КОДУ, а не наличие слов."""
bo = (ZONE / "bakeoff.py").read_text(encoding="utf-8")
ju = (ZONE / "judges.py").read_text(encoding="utf-8")
doc_bo = bo.split('"""')[1] if '"""' in bo else ""
doc_ju = ju.split('"""')[1] if '"""' in ju else ""
# (а) «черновик стоит $0» — код черновик ПОКУПАЕТ (`run_draft`) и кладёт цену в экономику.
chk("§8-4 докстринг bakeoff не утверждает «черновик стоит $0»",
not re.search(r"черновик\s+стоит\s+\$0", doc_bo))
chk("§8-4 код черновик действительно покупает", "def run_draft" in bo and "bo2-DRAFT-" in bo)
# (б) «вердикт при ≥2 повторах из 3» — REPS_PER_ORDER=1, правило вердикта другое.
import bakeoff as BO # noqa: PLC0415
claims_2of3 = bool(re.search(r"\s*2\s+(?:повтор\w*\s+)?из\s+3", doc_bo))
chk("§8-4 докстринг bakeoff не обещает правило «≥2 из 3»", not claims_2of3,
f"REPS_PER_ORDER={BO.REPS_PER_ORDER}")
# (в) состав судей в докстринге judges.py обязан совпадать с кортежем JUDGES.
import judges as J # noqa: PLC0415
named = [m for m in J.JUDGES if m in doc_ju]
chk("§8-4 докстринг judges называет ровно действующий состав",
len(named) == len(J.JUDGES) and "grok-4.3` выпал" in doc_ju,
f"{', '.join(J.JUDGES)}")
def main() -> int:
print("Ф0.3 — ПОЧИНКИ ЭКСП-21 §8, ПРОВЕРКА ИСПОЛНЕНИЕМ\n")
c1_draft_gate()
c2_blind_map()
c3_judge_reasons()
c4_docstrings()
print(f"\n{'ВСЕ ЧЕТЫРЕ ПУНКТА ЗАКРЫТЫ' if not BAD else f'ОТКРЫТО ПУНКТОВ: {BAD} — ПОКУПКИ ЗАПРЕЩЕНЫ'}")
return BAD
if __name__ == "__main__":
sys.exit(1 if main() else 0)