v0.2 content-binding regression matrix
#!/usr/bin/env python3
============================================================================
v0.2-hardening -- CONTENT-BINDING REGRESSION EXTENSION (DEV-ONLY)
Black-box: every case runs the REAL SUT and/or the content-binding verifier as
an OS subprocess, captures the OBSERVED process exit, and compares it to a
STATIC expected-exit spec (no synthesized/inferred exits -- the V3 black-box
CLI oracle discipline). Fail-closed: exit 0 iff every observed verdict matches.
Required matrix (macro section 4):
untampered content -> content-bind PASS
tampered content (correct filenames) -> content-bind FAIL
stale oracle hash vs updated corpus -> content-bind FAIL (drift)
oracle-from-SUT laundering attempt -> rejected / banned
V3 baseline current-mode -> real SUT --produce PASS (NOT failed)
autonomous-seal strict, NO oracle -> FAIL (exit 6)
content-binding strict, WITH oracle -> PASS (exit 0)
Plus contrast: real SUT --produce on TAMPERED content -> exit 0 (the gap)
while content-bind verify on the SAME corpus -> exit 5 (the fix).
decision_effect=NONE may_gate=false NON_AUTHORITY NOT_PROMOTED
============================================================================
import os, sys, json, subprocess, tempfile, shutil import content_bind_oracle as O
HERE = os.path.dirname(os.path.abspath(file)) SUT = os.path.join(HERE, "real-sut", "fix7_canon_v1_ssot.py") VERIFY = os.path.join(HERE, "content_bind_verify.py") ORACLE = os.path.join(HERE, "content_bind_oracle.json")
def run(argv, logdir, case): proc = subprocess.run([sys.executable]+argv, capture_output=True, text=True, cwd=HERE) log = os.path.join(logdir, f"cb-{case}.log") open(log,"w").write("CMD: %s\nEXIT: %d\n--- OUT ---\n%s\n--- ERR ---\n%s\n" % (" ".join(argv), proc.returncode, proc.stdout, proc.stderr)) return proc.returncode, proc.stdout+proc.stderr, log
def main(): logdir = sys.argv[1] if len(sys.argv)>1 else os.path.join(HERE,"rerun-out-contentbind","logs") os.makedirs(logdir, exist_ok=True) scratch = tempfile.mkdtemp(prefix="cb-") clean = O.build_fixture(os.path.join(scratch,"clean"),"CLEAN") tamper = O.build_fixture(os.path.join(scratch,"tamper"),"TAMPER_ONE") drop = O.build_fixture(os.path.join(scratch,"drop"),"DROP_ONE") extra = O.build_fixture(os.path.join(scratch,"extra"),"EXTRA_ONE") updated = O.build_fixture(os.path.join(scratch,"updated"),"UPDATED_ONE")
cases = [
# case_id, argv, expected_exit, note
("T1_untampered_PASS", [VERIFY,"--verify",clean,"--oracle",ORACLE], 0,
"untampered content -> content-binding PASS"),
("T2_tampered_FAIL", [VERIFY,"--verify",tamper,"--oracle",ORACLE], 5,
"content tamper (correct filenames) -> content-binding FAIL"),
("T3_stale_oracle_FAIL", [VERIFY,"--verify",updated,"--oracle",ORACLE], 5,
"legitimately updated corpus vs stale oracle pin -> FAIL (drift detected)"),
("T4_missing_member_FAIL", [VERIFY,"--verify",drop,"--oracle",ORACLE], 5,
"missing frozen member -> content-binding FAIL (membership)"),
("T5_extra_member_FAIL", [VERIFY,"--verify",extra,"--oracle",ORACLE], 5,
"extra member -> content-binding FAIL (membership)"),
("T6_launder_BANNED", [VERIFY,"--demo-launder",tamper], 3,
"oracle self-derived from corpus-under-test -> rejected/banned (exit 3)"),
("T7_strict_no_oracle_FAIL", [VERIFY,"--strict-autonomous-seal",clean,"--oracle","NONE"], 6,
"autonomous-seal strict mode with NO content oracle -> FAIL (exit 6)"),
("T8_strict_with_oracle_PASS",[VERIFY,"--strict-autonomous-seal",clean,"--oracle",ORACLE], 0,
"content-binding strict mode WITH oracle on clean corpus -> PASS"),
# --- V3 baseline current-mode: NOT retroactively failed ---
("T9_v3_baseline_clean_PASS", [SUT,"--produce",clean], 0,
"real SUT --produce on clean corpus -> exit 0 (V3 current-mode unchanged)"),
("T10_v3_baseline_selftest", [SUT,"--selftest"], 0,
"real SUT --selftest -> exit 0 (baseline intact, unmutated)"),
# --- headline contrast: the gap vs the fix on the SAME tampered corpus ---
("T11_GAP_sut_tamper_exit0", [SUT,"--produce",tamper], 0,
"ADOPT-FIND-1 LIVE: SUT --produce on TAMPERED content -> exit 0 (filename-membership only)"),
("T12_FIX_cb_tamper_exit5", [VERIFY,"--verify",tamper,"--oracle",ORACLE], 5,
"content-binding profile on the SAME tampered corpus -> exit 5 (gap closed at dev level)"),
]
results=[]; allok=True
for cid, argv, exp, note in cases:
rc, out, log = run(argv, logdir, cid)
ok = (rc == exp)
allok = allok and ok
results.append({"case":cid,"expected_exit":exp,"observed_exit":rc,
"verdict":"PASS" if ok else "FAIL","note":note,"log":log})
print(f"[{'PASS' if ok else 'FAIL'}] {cid:30s} exp={exp} obs={rc} {note}")
summary={"suite":"content-binding-regression","all_pass":allok,
"n_cases":len(cases),"n_pass":sum(1 for r in results if r['verdict']=='PASS'),
"sut":SUT,"oracle":ORACLE,"authority":"NON_AUTHORITY / NOT_PROMOTED / may_gate=false"}
json.dump({"summary":summary,"results":results},
open(os.path.join(logdir,"content-binding-regression-summary.json"),"w"), indent=2)
shutil.rmtree(scratch)
print(f"\nCONTENT_BINDING_REGRESSION: {summary['n_pass']}/{summary['n_cases']} "
f"-> {'ALL_PASS' if allok else 'FAIL'}")
return 0 if allok else 1
if name=="main": sys.exit(main())