Files
rune/scripts/check_construction_interface_parity.py
Nick 192c63b36e feat(construction_interface): close PARTIAL gaps — dichotomy wave
Audit 25/27 → 27/27 FULL (main + _programme_continuation were the two
unmatched fns; the port carries the full envelope surface). Freeze rig
scripts/ci_freeze_seams/sitecustomize.py (PYTHONPATH auto-import, used by
BOTH generator and --verify): every RUNE_*_CORE gate pinned python for
the whole dependency cone, frozen clock on structural_store.now +
scaffold.now + capability_ledger._now + programme_continuation.time,
deterministic uuid mint (counter resets per rig helper), hermetic
per-case stores under CI_FREEZE_HOME (mini-doc paths replay
byte-identically), doc-carrying seam bindings for every stateful method.

Truth: 85-case frozen corpus + 5-case hash corpus (obligation ids carry
Python's process-randomized str hash — captured with PYTHONHASHSEED=0,
SHAPE-pinned downstream, the memory_consolidation law). Regeneration
byte-identical; freeze_truth --verify OK both corpora.

Rust kernels (src/rust/construction_interface): kernel.rs adds the
doc-in/doc-out halves of submit_need (need assembly + envelope over the
construction_decision make_decision kernel + contract generation twin),
verify (scope check + layout gate via the layout_contract kernel),
transition (guard canary over frozen command outcomes + legality map +
checkpoint/session assembly + normalize_sorted commit twin),
close (close_contract + observed-impact + close_quality bucket math +
contract_quality projection), _programme_continuation (load/save shape
twins + continuation canary), _auto_material_change (via the
capability_ledger op_material_change kernel), main (CLI dispatch + exit
law), ladder_walk (full ladder in ONE process); projection.rs the pure
helpers (to_stage_check, guard_specs, obligations projection with the
FNV-1a stand-in id, envelope with extra merge, _match).

Store-normalization law discovered: the oracle's commit path sorts
lists by canonical JSON (structural_store._sorted) — the kernel applies
the same normalization at its commit points or read-back projections
(patterns_considered) diverge.

Battery: 25 tests — the 85-case corpus replays VERBATIM through
kernel::dispatch, the 5 hash cases shape-pinned, gap-fns-are-real-ports
probe. clippy --all-targets -D warnings 0. Parity
scripts/check_construction_interface_parity.py: FROZEN layer 85/85 + 5
through the ci_replay ctypes FFI of the built cdylib; LIVE layer
fresh re-freeze byte-identical. Python 37/37 both pins (floors pinned
python + live cores).
2026-10-13 19:03:37 +01:00

129 lines
4.6 KiB
Python

#!/usr/bin/env python3
"""Live parity: construction_interface Rust kernels vs the frozen oracle
truth (dichotomy wave, contract factory-gap-ci). Layers:
1. FROZEN — the frozen truth corpora (frozen_ci_truth.json 85 cases +
frozen_ci_truth_hash.json 5 shape-pinned cases, generated by
scripts/gen_construction_interface_truth.py against the LIVE Python
oracle through the scripts/ci_freeze_seams rig) replayed through
the ci_replay ctypes FFI entry of the built cdylib, case by case.
2. LIVE — a fresh re-freeze of the oracle through the same rig in a
subprocess; the regenerated corpora must be byte-identical to the
committed files (the oracle is still the parity authority while the
strangler runs).
Exit 0 only at 100% parity (85 verbatim + 5 shape-pinned + byte-identical
re-freeze).
"""
import ctypes
import json
import os
import subprocess
import sys
import tempfile
from pathlib import Path
REPO = Path(__file__).resolve().parents[1]
CRATE = REPO / "src" / "rust" / "construction_interface"
LIB = CRATE / "target" / "release" / "libconstruction_interface.so"
FROZEN = CRATE / "frozen_ci_truth.json"
FROZEN_HASH = CRATE / "frozen_ci_truth_hash.json"
HASH_ID_PREFIXES = (
"contract:", "regression:", "verification:",
"composition:", "acquisition:",
)
def normalize_hash_ids(obj):
if isinstance(obj, str):
kind, _, digits = obj.partition(":")
if (f"{kind}:" in HASH_ID_PREFIXES and digits
and len(digits) <= 8 and digits.isdigit()):
return f"{kind}:#"
return obj
if isinstance(obj, list):
return [normalize_hash_ids(v) for v in obj]
if isinstance(obj, dict):
return {k: normalize_hash_ids(v) for k, v in obj.items()}
return obj
def replay(lib, case):
payload = json.dumps(case, separators=(",", ":")).encode()
ptr = lib.ci_replay(payload, len(payload))
if not ptr:
raise RuntimeError("ci_replay returned NULL")
text = ctypes.c_char_p(ptr).value.decode()
lib.ci_free_string(ptr)
return json.loads(text)
def frozen_layer():
lib = ctypes.CDLL(str(LIB))
lib.ci_replay.argtypes = [ctypes.c_char_p, ctypes.c_size_t]
lib.ci_replay.restype = ctypes.c_void_p
lib.ci_free_string.argtypes = [ctypes.c_void_p]
lib.ci_free_string.restype = None
ok = 0
cases = json.loads(FROZEN.read_text())
for case in cases:
got = replay(lib, case)
assert got == case["expected"], (
f"FROZEN divergence: {case['fn']} "
f"{case['args'][0] if case['args'] else '?'}")
ok += 1
hash_ok = 0
for case in json.loads(FROZEN_HASH.read_text()):
got = normalize_hash_ids(replay(lib, case))
want = normalize_hash_ids(case["expected"])
assert got == want, (
f"HASH divergence: {case['fn']} "
f"{case['args'][0] if case['args'] else '?'}")
hash_ok += 1
print(f"FROZEN: PARITY OK {ok}/{len(cases)} verbatim "
f"+ {hash_ok} hash-shape cases")
return ok, hash_ok
def main() -> int:
committed_main = FROZEN.read_bytes()
committed_hash = FROZEN_HASH.read_bytes()
n_main, n_hash = frozen_layer()
with tempfile.TemporaryDirectory(prefix="ci_gap_parity_") as _scratch:
# the re-freeze must run at the CANONICAL rig home — the mini-doc
# paths are embedded in the frozen truth, so a different
# CI_FREEZE_HOME changes the bytes without changing behavior
home = "/tmp/ci_gap_freeze_home"
subprocess.run(["rm", "-rf", home], check=True)
env = dict(
os.environ,
CI_FREEZE_HOME=home,
PYTHONPATH="scripts/ci_freeze_seams:src",
CS_RUST_LIB="/mnt/workdrive/rune/src/rust/capability_scoring/"
"target/release/libcapability_scoring.so",
)
r = subprocess.run(
[sys.executable, "scripts/gen_construction_interface_truth.py"],
cwd=str(REPO), env=env, capture_output=True, text=True, timeout=600)
if r.returncode != 0:
print(r.stdout[-2000:])
print(r.stderr[-2000:])
print("LIVE: re-freeze FAILED")
return 1
same_main = FROZEN.read_bytes() == committed_main
same_hash = FROZEN_HASH.read_bytes() == committed_hash
if not (same_main and same_hash):
print(f"LIVE: re-freeze NOT byte-identical "
f"(main={same_main} hash={same_hash})")
return 1
print(f"LIVE: fresh re-freeze byte-identical "
f"({n_main}+{n_hash} cases, oracle authority held)")
print("PARITY OK construction_interface")
return 0
if __name__ == "__main__":
sys.exit(main())