Oracle src/rune/construction_mode.py 412 lines / 5 fns: 2/5 -> 5/5 per
scripts/dichotomy_audit.py (name-preserving match). The three audit-named
gaps land as ported Rust functions: ConstructionMode::to_dict (the ten-key
projection in the oracle's insertion order, construction_mode.py:155-167),
ConstructionMode::from_dict (known-keys-only + dataclass defaults, mode
required — TypeError message carried on the err envelope,
construction_mode.py:169-187), and _contains_any (renamed to the oracle's
name; lowering moved inside to mirror the Python signature). classify_mode
now routes every return through the ported ConstructionMode struct.
PARITY BUGS FIXED WITH PROOF (frozen truth from the live oracle):
1. Early-return defaults law — the override/NOT_CONSTRUCTION/empty-objective
branches left target_project/project_authority/proposed_by_model at
their dataclass defaults in the oracle but leaked kwargs through in the
port (construction_mode.py:249-259/276/279-286). Frozen cases
'what is a chord' + target_project/model_proposal and '' + kwargs pin
the None/None/None shape.
2. model_proposal falsy collapse — 'model_proposal if model_proposal else
None' (construction_mode.py:400): empty dict now collapses to None.
3. Evidence list rendering — Rust {:?} emitted double quotes where Python
repr emits single ('affected surface known: [\'module:deploy_stage\']');
py_repr_list/py_repr_tuple reproduce the oracle's repr, including the
MODES tuple in the invalid-override ValueError text.
4. Lexicon set-iteration order — the oracle's lexicons are Python sets, so
multi-hit evidence order is hash-random per process (dichotomy quirk);
truth is frozen under PYTHONHASHSEED=0 (generator re-execs itself,
memory_consolidation precedent) and the Rust const arrays reproduce
the seed-0 order.
COLLATERAL (fix-first): construction_decision's frozen truth was frozen
with RUNE_CM_CORE unpinned, so its construction_mode trace captured the
old divergent Rust output (double-quoted evidence). gen_construction_decision_truth.py
now pins RUNE_CM_CORE=python (transitive-core law) + the seed; truth
regenerated (11 evidence lines corrected), byte-identical verify green,
cd battery 18/18.
Truth: scripts/gen_construction_mode_truth.py via the shared freeze_truth.py
harness + rig scripts/cm_freeze_seams (pins RUNE_CM_CORE +
RUNE_CONSTRUCTION_DECISION_CORE for the file-scope branch's transitive
classify_surface import; binds the cm_classify_to_dict seam — classify_mode
returns a dataclass instance, the frozen contract is its to_dict projection).
39 harness cases (36 classify + 3 to_dict receivers) + 5 from_dict
projections + 3 error shapes in the battery envelope; freeze_truth --verify
byte-identical. Battery replays the corpus VERBATIM via include_str!
(frozen_cm_truth.json + frozen_cm_truth.verify.json pinned together by
envelope_cases_match_verify_file) with FULL structural equality.
FFI: cm_to_dict / cm_from_dict doc-envelope externs; cm_loader gains
to_dict/from_dict bindings. Live parity scripts/check_construction_mode_parity.py:
100% — 36 classify + 3 to_dict + 5 from_dict + 4 error shapes, rust == oracle
== frozen (92 comparisons; oracle side subprocessed under PYTHONHASHSEED=0).
clippy --all-targets -D warnings clean (construction_mode +
construction_decision + construction_interface). Python suite green in BOTH
pins (RUNE_CM_CORE=python and delegation live): 138 passed each.
Audit: construction_mode 5/5 FULL (85/192 modules at FULL).
191 lines
6.7 KiB
Python
191 lines
6.7 KiB
Python
#!/usr/bin/env python3
|
|
"""check_construction_mode_parity.py — live parity: the Rust construction_mode
|
|
core (.so via cm_loader) vs the live Python oracle, 100% on the full gap
|
|
surface (dichotomy wave #2479 gap close).
|
|
|
|
Corpus: the frozen envelope (frozen_cm_truth.json — 36 classify cases, 3
|
|
to_dict receiver cases, 5 from_dict projections, 3 error shapes) replayed
|
|
against BOTH sides live, plus the invalid-override ValueError crash-parity
|
|
case (un-freezable through the shared harness; compared here).
|
|
|
|
The oracle side runs in a SUBPROCESS with PYTHONHASHSEED=0 — the oracle's
|
|
lexicons are Python sets, so multi-hit evidence order is hash-random per
|
|
process and the deterministic contract is the seed-0 order the Rust
|
|
arrays reproduce (memory_consolidation precedent; the truth generator
|
|
re-execs itself under the same seed).
|
|
|
|
Usage: python3 scripts/check_construction_mode_parity.py
|
|
Exit 0 iff every case matches on BOTH sides (and the frozen expected).
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
sys.path.insert(0, str(ROOT / "src"))
|
|
|
|
from rune import cm_loader # noqa: E402
|
|
|
|
ENV = ROOT / "src" / "rust" / "construction_mode" / "src" / "frozen_cm_truth.json"
|
|
|
|
ORACLE_HELPER = r"""
|
|
import json, sys, os
|
|
sys.path.insert(0, %(src)r)
|
|
os.environ["RUNE_CM_CORE"] = "python"
|
|
os.environ["RUNE_CONSTRUCTION_DECISION_CORE"] = "python"
|
|
from rune import construction_mode as cm
|
|
|
|
CASES = json.load(sys.stdin)["CASES"]
|
|
out = {"classify": [], "to_dict": [], "from_dict": [], "errors": {}}
|
|
for case in CASES["classify"]:
|
|
d = cm.classify_mode(case["objective"], **case["kwargs"])
|
|
out["classify"].append(d.to_dict())
|
|
for inst in CASES["to_dict"]:
|
|
obj = cm.ConstructionMode.__new__(cm.ConstructionMode)
|
|
for k, v in inst.items():
|
|
setattr(obj, k, v)
|
|
out["to_dict"].append(obj.to_dict())
|
|
for d in CASES["from_dict"]:
|
|
out["from_dict"].append(cm.ConstructionMode.from_dict(d).to_dict())
|
|
try:
|
|
cm.ConstructionMode.from_dict({"evidence": []})
|
|
except TypeError as e:
|
|
out["errors"]["from_dict_missing_mode"] = str(e)
|
|
try:
|
|
cm.ConstructionMode.from_dict(123)
|
|
except TypeError as e:
|
|
out["errors"]["from_dict_non_dict"] = str(e)
|
|
_broken = cm.ConstructionMode.__new__(cm.ConstructionMode)
|
|
_broken.mode = "X"
|
|
try:
|
|
_broken.to_dict()
|
|
except AttributeError as e:
|
|
out["errors"]["to_dict_missing_attribute"] = str(e)
|
|
try:
|
|
cm.classify_mode("anything", explicit_override="MAGIC_MODE")
|
|
except ValueError as e:
|
|
out["errors"]["classify_invalid_override"] = str(e)
|
|
print(json.dumps(out))
|
|
"""
|
|
|
|
FAILS = [0]
|
|
|
|
|
|
def check(label: str, got, want) -> None:
|
|
if json.dumps(got, sort_keys=True) != json.dumps(want, sort_keys=True):
|
|
FAILS[0] += 1
|
|
print(f"MISMATCH {label}")
|
|
print(f" rust: {json.dumps(got, sort_keys=True)[:220]}")
|
|
print(f" oracle: {json.dumps(want, sort_keys=True)[:220]}")
|
|
else:
|
|
print(f"ok {label}")
|
|
|
|
|
|
def run_oracle(cases: dict) -> dict:
|
|
env = {**os.environ, "PYTHONHASHSEED": "0"}
|
|
code = ORACLE_HELPER % {"src": str(ROOT / "src")}
|
|
r = subprocess.run(
|
|
[sys.executable, "-c", code],
|
|
input=json.dumps({"CASES": cases}), capture_output=True, text=True,
|
|
env=env, timeout=120,
|
|
)
|
|
if r.returncode != 0:
|
|
print("ORACLE SUBPROCESS FAILED:", r.stderr[-500:])
|
|
sys.exit(1)
|
|
return json.loads(r.stdout)
|
|
|
|
|
|
def rust_classify(objective: str, kwargs: dict) -> dict:
|
|
payload = {"objective": objective}
|
|
for k, v in kwargs.items():
|
|
if v is not None:
|
|
payload[k] = v
|
|
return cm_loader._call(payload)
|
|
|
|
|
|
def main() -> int:
|
|
env = json.loads(ENV.read_text())
|
|
|
|
classify_cases = []
|
|
for case in env["cases"]:
|
|
if case["fn"] != "cm_classify_to_dict":
|
|
continue
|
|
classify_cases.append({
|
|
"objective": case["args"][0],
|
|
"kwargs": case["kwargs"],
|
|
"frozen": case["expected"],
|
|
})
|
|
to_dict_insts = [
|
|
{k: v for k, v in case["recv"].items() if k != "cls"}
|
|
for case in env["cases"] if case["fn"] == "ConstructionMode.to_dict"
|
|
]
|
|
to_dict_frozen = [
|
|
case["expected"]["result"]
|
|
for case in env["cases"] if case["fn"] == "ConstructionMode.to_dict"
|
|
]
|
|
from_dict_inputs = [c["args"] for c in env["from_dict_cases"]]
|
|
from_dict_frozen = [c["expected"] for c in env["from_dict_cases"]]
|
|
|
|
oracle = run_oracle({
|
|
"classify": [{"objective": c["objective"], "kwargs": c["kwargs"]}
|
|
for c in classify_cases],
|
|
"to_dict": to_dict_insts,
|
|
"from_dict": from_dict_inputs,
|
|
})
|
|
|
|
for i, case in enumerate(classify_cases):
|
|
got = rust_classify(case["objective"], case["kwargs"])
|
|
check(f"classify[{i}] {case['objective'][:40]!r}", got, oracle["classify"][i])
|
|
check(f"classify[{i}] frozen {case['objective'][:40]!r}", got, case["frozen"])
|
|
|
|
for i, inst in enumerate(to_dict_insts):
|
|
got = cm_loader.to_dict(inst)
|
|
check(f"to_dict[{i}] {inst['mode']}", got, oracle["to_dict"][i])
|
|
check(f"to_dict[{i}] frozen {inst['mode']}", got, to_dict_frozen[i])
|
|
|
|
for i, d in enumerate(from_dict_inputs):
|
|
got = cm_loader.from_dict(d)
|
|
check(f"from_dict[{i}]", got, oracle["from_dict"][i])
|
|
check(f"from_dict[{i}] frozen", got, from_dict_frozen[i])
|
|
|
|
shapes = env["error_shapes"]
|
|
for key, call in [
|
|
("from_dict_missing_mode", lambda: cm_loader.from_dict({"evidence": []})),
|
|
("from_dict_non_dict", lambda: cm_loader.from_dict(123)),
|
|
("to_dict_missing_attribute", lambda: cm_loader.to_dict({"mode": "X"})),
|
|
]:
|
|
try:
|
|
call()
|
|
print(f"MISMATCH {key}: rust returned ok, oracle raises")
|
|
FAILS[0] += 1
|
|
except RuntimeError as e:
|
|
check(f"error[{key}]", str(e), shapes[key])
|
|
|
|
# invalid override: the facade path raises ValueError before the FFI
|
|
# (cm_loader mirrors the oracle's own validation message).
|
|
try:
|
|
cm_loader.classify("anything", explicit_override="MAGIC_MODE")
|
|
print("MISMATCH classify_invalid_override: no ValueError")
|
|
FAILS[0] += 1
|
|
except ValueError as e:
|
|
check("error[classify_invalid_override]", str(e),
|
|
oracle["errors"]["classify_invalid_override"])
|
|
|
|
total = (2 * (len(classify_cases) + len(to_dict_insts) + len(from_dict_inputs))
|
|
+ 3 + 1)
|
|
if FAILS[0]:
|
|
print(f"\nPARITY FAILED: {FAILS[0]} mismatches")
|
|
return 1
|
|
print(f"\nPARITY OK: 100% — {len(classify_cases)} classify + "
|
|
f"{len(to_dict_insts)} to_dict + {len(from_dict_inputs)} from_dict "
|
|
f"+ 4 error shapes, rust == oracle == frozen ({total} comparisons)")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|