81 lines
2.4 KiB
Python
81 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Live parity: the task_persist gap-closing port vs the frozen truth
|
|
(dichotomy wave #2479, worktree rune-wave-cw2).
|
|
|
|
Composition law: the frozen truth was generated against the LIVE Python
|
|
oracle and re-proved byte-identical by gen_task_persist_gap_truth.py
|
|
--verify (live oracle == frozen); this script replays every truth row
|
|
through the BUILT tp_parity binary — the same tpops engine the frozen
|
|
battery replays in-process — and compares got vs expected exactly
|
|
(port == frozen). Port == frozen == live oracle at 100%.
|
|
|
|
Run: python3 scripts/check_task_persist_parity.py
|
|
Needs: cargo build --release in src/rust/task_persist (tp_parity bin).
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
REPO = Path(__file__).resolve().parents[1]
|
|
TRUTH = REPO / "src" / "rust" / "task_persist" / "src" / "frozen_tp_truth.json"
|
|
BIN = (
|
|
REPO
|
|
/ "src"
|
|
/ "rust"
|
|
/ "task_persist"
|
|
/ "target"
|
|
/ "release"
|
|
/ "tp_parity"
|
|
)
|
|
|
|
|
|
def main() -> int:
|
|
truth = json.loads(TRUTH.read_text())
|
|
cases = truth["cases"]
|
|
proc = subprocess.run(
|
|
[str(BIN), str(TRUTH)],
|
|
capture_output=True,
|
|
text=True,
|
|
check=True,
|
|
)
|
|
lines = [json.loads(ln) for ln in proc.stdout.splitlines() if ln.strip()]
|
|
if len(lines) != len(cases):
|
|
print(
|
|
f"FAIL: driver emitted {len(lines)} rows for {len(cases)} truth cases"
|
|
)
|
|
return 1
|
|
|
|
per_fn: dict[str, list[int]] = {}
|
|
fails: list[str] = []
|
|
for case, line in zip(cases, lines):
|
|
fn = case["fn"]
|
|
ok = line["got"] == case["expected"]
|
|
bucket = per_fn.setdefault(fn.rsplit(".", 1)[-1], [0, 0])
|
|
bucket[1] += 1
|
|
if ok:
|
|
bucket[0] += 1
|
|
else:
|
|
fails.append(fn)
|
|
print(f"DIVERGE [{fn}]")
|
|
print(f" want: {json.dumps(case['expected'], sort_keys=True)[:400]}")
|
|
print(f" got: {json.dumps(line['got'], sort_keys=True)[:400]}")
|
|
|
|
total = len(cases)
|
|
passed = total - len(fails)
|
|
for fn in sorted(per_fn):
|
|
hit, n = per_fn[fn]
|
|
print(f" {fn:<16} {hit}/{n}")
|
|
print(f"PARITY {passed}/{total} ({100.0 * passed / total:.1f}%)")
|
|
if fails:
|
|
print(f"FAILED FNS: {sorted(set(f.rsplit('.', 1)[-1] for f in fails))}")
|
|
return 1
|
|
print("OK: 100% parity with frozen truth (== live oracle)")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|