audit 1/4 PARTIAL -> 15/15 FULL (RUST side; the 15-fn surface = the 4 oracle fns _scaffold_for/activate/_auto_structural_awareness/dispatch_from_decision + the JSON parity shims + seam machinery; nested rig closures under the _py_* exclusion law). Ported name-preserving into src/rust/construction_activation: the full mode-dispatch matrix (NOT_CONSTRUCTION/UNKNOWN/LOCAL_CHANGE/EXISTING_PROJECT_CHANGE/PROJECT_BUILD/unhandled incl. int-mode py_display reason), identity-before-repository slug derivation (unicode+astral lowercasing, run-collapsed dashes, [:48] by chars, unnamed-project fallback), store-v2 Scaffold persistence ported for the battery (segments WIN, idempotent journals, canonical-digest commit verify), the T21.5 awareness branch matrix (registry x spine x {registered,skipped,recorded,error} with save-only error injection and 120-char error-note truncation), and crash-parity error envelopes (AttributeError object-access, TypeError list() non-iterables, char-spread str list() quirk).
Kernel/facade split preserves the monkeypatch contract: the Rust kernel computes rec+plan (ca_activate FFI returns them UNPERSISTED); the Python facade owns all persistence IO (Scaffold.init/commit, registry.save, spine.save — the seams the failure-tolerance tests pin) and always runs awareness on its side. activate_json (battery surface) applies the plan + realizes awareness writes = oracle-equivalent standalone.
Frozen truth: 52-case corpus via the shared freeze_truth.py harness + scripts/coa_freeze_seams rig (cwd-is-the-rig; row-private two-level roots because the oracle derives the spine from the parent scaffold's GRANDPARENT — shared roots bleed spine state). Verified byte-identical twice. Battery gap_battery.rs replays the truth VERBATIM in order in a throwaway cwd (52/52 + slug edges). Live parity scripts/check_construction_activation_parity.py: seam-delegation 52/52, FFI composites 39/39 (13 shim-only: validation-crash/io-errors-injection/files_after rows pinned by the seam pass). cargo build/clippy -D warnings/fmt clean. Python suite both pins: native_activation 6/6 + construction_interface 37/37; full-suite failure set byte-identical across pins (140 pre-existing; one isolated load-timing flake in test_mimo_tty_contract re-verified green 4x, construction-unrelated).
Evidence: verification/ca-*.exit + ca-summary.md (logs local, *.log gitignored).
150 lines
6.7 KiB
Python
150 lines
6.7 KiB
Python
#!/usr/bin/env python3
|
|
"""check_construction_activation_parity — live-parity replay for the
|
|
construction_activation dichotomy gap-close (worktree rune-wave-de).
|
|
|
|
Two passes over the frozen truth (frozen_ca_truth.json, generated from
|
|
the pristine Python oracle under scripts/coa_freeze_seams):
|
|
|
|
PASS 1 (seam, live delegation): replay every row through the module's
|
|
JSON shims with RUNE_CA_CORE unset — activate drives ca_activate
|
|
through _activate_via_core (the production strangler path: Rust
|
|
computes rec+plan, the facade realizes init/commit + awareness).
|
|
|
|
PASS 2 (FFI composites): drive ca_loader directly —
|
|
ca_scaffold_for / ca_auto_structural_awareness /
|
|
ca_dispatch_from_decision replay their rows through the FFI
|
|
envelope surface; activate rows replay through loader.activate
|
|
(pure {rec, plan} doc-domain computation; rec compared, plan
|
|
presence asserted). Rows that crash on the PYTHON side before
|
|
delegation (validation TypeError/AttributeError rows) are
|
|
shim-pass-only by construction.
|
|
|
|
Sibling cores are pinned python (isolate the module under test); the
|
|
cwd is a fresh throwaway (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 pathlib import Path
|
|
|
|
REPO = Path(__file__).resolve().parents[1]
|
|
|
|
# isolate the module under test: pin every SIBLING core the call graph
|
|
# reaches; leave RUNE_CA_CORE unset so construction_activation delegates
|
|
for sym in ("CM", "CONSTRUCTION_DECISION", "STRUCTURAL", "PR", "SPINE"):
|
|
os.environ[f"RUNE_{sym}_CORE"] = "python"
|
|
os.environ.pop("RUNE_CA_CORE", None)
|
|
|
|
sys.path.insert(0, str(REPO / "src"))
|
|
os.chdir(tempfile.mkdtemp(prefix="ca-parity-"))
|
|
|
|
from rune import ca_loader # noqa: E402
|
|
from rune import construction_activation as ca # noqa: E402
|
|
|
|
TRUTH = REPO / "src" / "rust" / "construction_activation" / "src" / "frozen_ca_truth.json"
|
|
|
|
|
|
def same(a, b) -> bool:
|
|
return json.dumps(a, sort_keys=True) == json.dumps(b, sort_keys=True)
|
|
|
|
|
|
def main() -> int:
|
|
assert ca_loader.available(), "Rust core .so not built (cargo build --release)"
|
|
lib = ca_loader._load() # fails loudly if the free-fallback is missing
|
|
assert lib is not None
|
|
rows = json.loads(TRUTH.read_text())
|
|
shim_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(ca, fn)(*args, **kwargs)
|
|
if not same(got, row["expected"]):
|
|
shim_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 ca_loader ─────────────────────────
|
|
# fresh cwd: pass 1 already realized every row's writes; the FFI
|
|
# composites must see the same virgin state the oracle froze
|
|
os.chdir(tempfile.mkdtemp(prefix="ca-parity-ffi-"))
|
|
for i, row in enumerate(rows):
|
|
fn, kwargs = row["fn"], row["kwargs"]
|
|
try:
|
|
if fn == "scaffold_for_json":
|
|
got = ca_loader.scaffold_for({
|
|
"project": row["args"][0],
|
|
"create": kwargs.get("create", False),
|
|
"parent_current": kwargs.get("parent_current"),
|
|
"now": kwargs.get("now", ""),
|
|
"prestate": kwargs.get("prestate") or [],
|
|
})
|
|
elif fn == "awareness_json":
|
|
got = ca_loader.auto_structural_awareness({
|
|
"project": row["args"][0],
|
|
"ps_current": kwargs["ps_current"],
|
|
"parent_store_dir": kwargs["parent_store_dir"],
|
|
"now": kwargs.get("now", ""),
|
|
"prestate": kwargs.get("prestate") or [],
|
|
"io_errors": kwargs.get("io_errors") or {},
|
|
})
|
|
elif fn == "dispatch_from_decision_json":
|
|
got = ca_loader.dispatch_from_decision({
|
|
"trace": row["args"][0],
|
|
"need": row["args"][1] if len(row["args"]) > 1 else {},
|
|
"parent_store_dir": kwargs["parent_store_dir"],
|
|
"builder": kwargs.get("builder", "rune"),
|
|
"now": kwargs.get("now", ""),
|
|
"prestate": kwargs.get("prestate") or [],
|
|
"io_errors": kwargs.get("io_errors") or {},
|
|
})
|
|
elif fn == "activate_json":
|
|
md = row["args"][0]
|
|
if isinstance(row["expected"], dict) and "error" in row["expected"]:
|
|
ffi_skipped += 1 # Python-side validation crash — pinned in PASS 1
|
|
continue
|
|
if kwargs.get("io_errors"):
|
|
ffi_skipped += 1 # error injection is a facade seam — PASS 1 covers it
|
|
continue
|
|
out = ca_loader.activate({
|
|
"mode_decision": ca._mode_view(ca._mode_from_dict(md)),
|
|
"need": row["args"][1],
|
|
"parent_store_dir": kwargs["parent_store_dir"],
|
|
"builder": kwargs.get("builder", "rune"),
|
|
"now": kwargs.get("now", ""),
|
|
"prestate": kwargs.get("prestate") or [],
|
|
})
|
|
got = out.get("rec")
|
|
if row["expected"].get("mode") == "PROJECT_BUILD":
|
|
assert out.get("plan"), f"row {i}: PROJECT_BUILD returned no plan"
|
|
else:
|
|
ffi_skipped += 1 # files_after reads the facade's cwd — PASS 1 covers it
|
|
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(shim_failures)}/{total} rows match")
|
|
print(f"pass2 ffi-composite: {total - ffi_skipped - len(ffi_failures)}"
|
|
f"/{total - ffi_skipped} rows match ({ffi_skipped} shim-only by design)")
|
|
for f in shim_failures + ffi_failures:
|
|
print("FAIL", f)
|
|
ok = not shim_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())
|