audit 4/6 PARTIAL -> 8/8 FULL (RUST). The landed FULL port (b5228ace+e41562aa) left record_trace/read_traces as facade-side IO by its strangler verdict; this close ports them name-preserving with the file IO itself in the kernel (mkdir, I1 source-guard rotation replace chain, O_APPEND write, file reads; path RESOLUTION stays the _trace_path seam the tests pin, and the facade passes module rotation knobs read at call time so the TRACE_ROTATE_BYTES monkeypatch contract survives). FFI it_record_trace / it_read_traces + it_loader wrappers + byte-identical _py_record_trace / _py_read_traces fallbacks (RUNE_IT_CORE=python pin). Fix-first (proved by frozen truth): (1) serialize/format_record ensure_ascii divergence — json.dumps escapes non-ASCII as \uXXXX (astral = surrogate pairs), serde emitted raw UTF-8; py_escape emitter added for both shapes (quirk #24, extends the context_broker pyDumpsSorted law). (2) limit=0 — Python lines[-0:] keeps ALL lines, rev().take(0) returned none; read_select + cli_tail fixed (quirk #25). (3) malformed JSONL line silently skipped by read_select where the oracle raises ValueError — now an Err through the FFI envelope so the facade fallback re-raises the AUTHENTIC exception (quirk #26; crash class pinned in truth). Frozen truth: 17-case gap corpus via the shared freeze_truth.py harness + scripts/it_freeze_seams rig (RUNE_IT_CORE=python, relative RUNE_HOME, cwd-is-the-rig, row-private it_t stores; record/read branches incl. rotation matrix + unicode line law + limit 0/2/99 + missing stores + ValueError class + round-trip). gen x2 + --verify x2 byte-identical. Battery: gap_battery.rs replays rows VERBATIM in a throwaway cwd (cargo test 9/9: old 6 + new 3). Live parity scripts/check_inference_trace_parity .py: seam 17/17 + FFI composites 17/17. Landed PARITY=1 flow preserved (byte-identical modulo the original freeze's baked worktree root). cargo build/clippy -D warnings/fmt clean. Python suite both pins 108/108 live + 108/108 RUNE_IT_CORE=python (p1_03 memory_selection failures pre-exist at pristine HEAD, outside this port's cone). Audit: FULL 65% (125/192). Evidence: verification/it-*.exit + summary-inference_trace.md (logs local, *.log gitignored).
135 lines
5.2 KiB
Python
135 lines
5.2 KiB
Python
#!/usr/bin/env python3
|
|
"""check_inference_trace_parity — live-parity replay for the
|
|
inference_trace dichotomy gap-close (worktree rune-wave-dk).
|
|
|
|
Two passes over the gap truth (frozen_it_gap_truth.json, generated from
|
|
the pristine Python oracle under scripts/it_freeze_seams):
|
|
|
|
PASS 1 (seam, live delegation): replay every row through the module's
|
|
JSON runners with RUNE_IT_CORE unset — record_trace/read_traces
|
|
delegate their file IO to the freshly built Rust core (the
|
|
production strangler path: the facade resolves the path, the
|
|
kernel mkdirs/rotates/appends/reads).
|
|
|
|
PASS 2 (FFI composites): drive it_loader.record_trace /
|
|
it_loader.read_traces directly at the row-built paths, assembling
|
|
the record fruit (dir walk) on this side — proving the kernel's
|
|
own IO bytes match the oracle-frozen expectations. The record
|
|
payload carries the full dataclass shape (asdict(InferenceTrace)),
|
|
mirroring the production facade.
|
|
|
|
RUNE_HOME is pinned relative and the cwd is a fresh throwaway per pass
|
|
(rows speak cwd-relative paths). Exit 0 iff every compared row matches
|
|
the frozen expected byte-for-byte (semantic JSON compare, sorted keys).
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import os
|
|
import sys
|
|
import tempfile
|
|
from dataclasses import asdict
|
|
from pathlib import Path
|
|
|
|
REPO = Path(__file__).resolve().parents[1]
|
|
|
|
os.environ.pop("RUNE_IT_CORE", None) # live: the facade must delegate
|
|
os.environ["RUNE_HOME"] = "it_rig_home"
|
|
|
|
sys.path.insert(0, str(REPO / "src"))
|
|
os.chdir(tempfile.mkdtemp(prefix="it-parity-"))
|
|
|
|
from rune import it_loader # noqa: E402
|
|
from rune import inference_trace as it # noqa: E402
|
|
|
|
TRUTH = REPO / "src" / "rust" / "inference_trace" / "src" / "frozen_it_gap_truth.json"
|
|
|
|
|
|
def same(a, b) -> bool:
|
|
return json.dumps(a, sort_keys=True) == json.dumps(b, sort_keys=True)
|
|
|
|
|
|
def row_dir(row) -> Path:
|
|
kw = row["kwargs"]
|
|
td = row["args"][1] if row["fn"] == "record_trace_json" else row["args"][0]
|
|
if td is not None:
|
|
return Path(td)
|
|
return Path(kw.get("rune_home", "")) / "state"
|
|
|
|
|
|
def fruit(base: Path) -> dict:
|
|
files = {}
|
|
if base.is_dir():
|
|
for p in sorted(base.rglob("*")):
|
|
if p.is_file():
|
|
files[str(p)] = p.read_text(encoding="utf-8")
|
|
return files
|
|
|
|
|
|
def main() -> int:
|
|
assert it_loader.available(), "Rust core .so not built (cargo build --release)"
|
|
it_loader._load()
|
|
rows = json.loads(TRUTH.read_text())
|
|
seam_failures: list[str] = []
|
|
ffi_failures: list[str] = []
|
|
ffi_skipped = 0
|
|
|
|
# ── PASS 1: the seam with live delegation ────────────────────────────
|
|
for i, row in enumerate(rows):
|
|
fn, args, kwargs = row["fn"], row["args"], row["kwargs"]
|
|
got = getattr(it, fn)(*args, **kwargs)
|
|
if not same(got, row["expected"]):
|
|
seam_failures.append(
|
|
f"row {i} {fn}: {json.dumps(got, sort_keys=True)[:200]} != "
|
|
f"{json.dumps(row['expected'], sort_keys=True)[:200]}")
|
|
|
|
# ── PASS 2: the FFI composites via it_loader ─────────────────────────
|
|
# fresh cwd: pass 1 realized every row's writes; the composites must
|
|
# see the same virgin state the oracle froze
|
|
os.chdir(tempfile.mkdtemp(prefix="it-parity-ffi-"))
|
|
for i, row in enumerate(rows):
|
|
fn, kwargs = row["fn"], row["kwargs"]
|
|
base = row_dir(row)
|
|
path = base / it.TRACE_FILENAME
|
|
try:
|
|
if fn == "record_trace_json":
|
|
it._py_seed(kwargs.get("prestate"))
|
|
got = {
|
|
"path": it_loader.record_trace(
|
|
asdict(it.InferenceTrace(**row["args"][0])), str(path),
|
|
kwargs.get("rotate_bytes", it.TRACE_ROTATE_BYTES),
|
|
kwargs.get("backups", it.TRACE_BACKUPS)),
|
|
"files": fruit(base),
|
|
}
|
|
elif fn == "read_traces_json":
|
|
it._py_seed(kwargs.get("prestate"))
|
|
try:
|
|
got = {"ok": True,
|
|
"records": it_loader.read_traces(str(path),
|
|
kwargs.get("limit"))}
|
|
except RuntimeError:
|
|
got = {"ok": False, "err_kind": "ValueError"}
|
|
else:
|
|
ffi_skipped += 1
|
|
continue
|
|
except RuntimeError as e:
|
|
got = {"error": str(e)}
|
|
if not same(got, row["expected"]):
|
|
ffi_failures.append(
|
|
f"row {i} {fn}: {json.dumps(got, sort_keys=True)[:200]} != "
|
|
f"{json.dumps(row['expected'], sort_keys=True)[:200]}")
|
|
|
|
total = len(rows)
|
|
print(f"pass1 seam-live: {total - len(seam_failures)}/{total} rows match")
|
|
print(f"pass2 ffi-composite: {total - ffi_skipped - len(ffi_failures)}"
|
|
f"/{total - ffi_skipped} rows match ({ffi_skipped} skipped by design)")
|
|
for f in seam_failures + ffi_failures:
|
|
print("FAIL", f)
|
|
ok = not seam_failures and not ffi_failures
|
|
print("PARITY OK" if ok else "PARITY FAILED")
|
|
return 0 if ok else 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|