#!/usr/bin/env python3
"""P7 gate comparator: walks both implementations' canonical JSON outputs.
Numeric agreement threshold 1e-9 (prereg §5); classifications and counts exact.
Excludes top-level keys: meta, hash_check (prereg addition A2)."""
import json, sys

TOL = 1e-9
EXCLUDE = {"meta", "hash_check"}
mismatches = []


def walk(a, b, path):
    if isinstance(a, dict) and isinstance(b, dict):
        ka, kb = set(a), set(b)
        for k in sorted(ka ^ kb):
            mismatches.append(f"{path}: key {k!r} only in one impl")
        for k in sorted(ka & kb):
            walk(a[k], b[k], f"{path}.{k}")
    elif isinstance(a, list) and isinstance(b, list):
        if len(a) != len(b):
            mismatches.append(f"{path}: length {len(a)} vs {len(b)}")
            return
        for i, (x, y) in enumerate(zip(a, b)):
            walk(x, y, f"{path}[{i}]")
    elif isinstance(a, bool) or isinstance(b, bool):
        if a is not b:
            mismatches.append(f"{path}: {a!r} vs {b!r}")
    elif isinstance(a, (int, float)) and isinstance(b, (int, float)):
        if not (abs(a - b) <= TOL):
            mismatches.append(f"{path}: {a!r} vs {b!r} (|d|={abs(a-b):.3e})")
    else:
        if a != b:
            mismatches.append(f"{path}: {a!r} vs {b!r}")


A = json.load(open(sys.argv[1]))
B = json.load(open(sys.argv[2]))
for k in sorted((set(A) | set(B)) - EXCLUDE):
    if k not in A or k not in B:
        mismatches.append(f"top-level key {k!r} missing in one impl")
        continue
    walk(A[k], B[k], k)

print(f"P7 comparator: {sys.argv[1]} vs {sys.argv[2]}")
print(f"compared sections: {sorted((set(A)|set(B))-EXCLUDE)}")
print(f"mismatches: {len(mismatches)}")
for m in mismatches[:200]:
    print("  MISMATCH", m)
print("P7 GATE:", "PASS" if not mismatches else "FAIL")
sys.exit(0 if not mismatches else 1)
