#!/usr/bin/env python3 """Freeze the dichotomy-wave gap truth for src/rune/construction_interface through the SHARED harness (scripts/freeze_truth.py — one law). The oracle is a stateful facade (ConstructionInterface over a Scaffold store) with clock/uuid nondeterminism, so this generator runs under the freeze rig (scripts/ci_freeze_seams/sitecustomize.py): pinned RUNE_*_CORE=python floors, frozen clock, deterministic uuid mint, hermetic per-case stores (deterministic per-case dirs — envelopes that carry paths, like mini_doc, replay byte-identically), and DOC-CARRYING seam bindings the shared harness can getattr: the Rust kernel is a pure doc-in/doc-out membrane, so every stateful case carries the full input doc in its args and replays in the battery with no store. Run (from the repo root): rm -rf /tmp/ci_gap_freeze_home CI_FREEZE_HOME=/tmp/ci_gap_freeze_home \ PYTHONPATH=scripts/ci_freeze_seams:src \ python3 scripts/gen_construction_interface_truth.py Verify (byte-identical, same rig): CI_FREEZE_HOME=/tmp/ci_gap_freeze_home \ PYTHONPATH=scripts/ci_freeze_seams:src \ python3 scripts/freeze_truth.py --verify \ src/rust/construction_interface/frozen_ci_truth.json \ --module rune.construction_interface Every public function and branch is exercised. The obligation-id seam (_obligations_projection carries process-randomized str hash) lives in the SEPARATE frozen_ci_truth_hash.json battery (captured + verified with PYTHONHASHSEED=0) and is SHAPE-pinned downstream — never value-frozen here. """ import os import subprocess import sys from pathlib import Path REPO = Path(__file__).resolve().parents[1] sys.path.insert(0, str(REPO / "scripts")) from freeze_truth import freeze, write # noqa: E402 import sitecustomize as rig # noqa: E402 # ── deterministic input docs (builder helpers; NOT frozen fns) ── DOC0 = rig.build_doc() # fixture authority, no contract DOC_SUBMITTED = rig.submit_doc("b-submitted", rig.build_doc()) DOC_WALKED = rig.walk_doc("b-walked", rig.build_doc()) DOC_WITH_LEDGER_CAPS = rig.build_ledger_caps() PROGRAMMES_BOUND = [{ "programme_id": "prog-gap-ci", "objective": "close the gap", "stages": [ {"stage_id": rig._submitted_cid(DOC_SUBMITTED), "objective": "the gap stage"}, {"stage_id": "next-stage", "objective": "the next stage"}, ], }] GUARD_FAIL = [{"name": "always-fail", "kind": "command", "argv": ["false"]}] GUARD_PASS = [{"name": "always-pass", "kind": "command", "argv": ["true"]}] GUARD_ASSERT = [{"name": "truthy", "kind": "assert", "description": "always true"}] cases = [ # ── _envelope: success + failure shapes, extra keys ── ("_envelope", ("op",), {"success": True}), ("_envelope", ("op",), {"success": False, "errors": [{"error": "X"}], "warnings": [{"warning": "W"}], "ids": {"a": "b"}, "state": {"k": 1}, "extra": {"extra_key": "extra"}}), # ── _to_stage_check: full spec, defaults ── ("ci_to_stage_check", ({"name": "g", "kind": "command", "argv": ["true"], "output_pattern": "ok", "path": "/x", "description": "d"},), {}), ("ci_to_stage_check", ({},), {}), # ── _guard_specs_from_obligations: guard rows, junk, bad JSON ── ("_guard_specs_from_obligations", ({"identities": {"verification_obligations": [ 'guard:{"name": "g1", "kind": "command", "argv": ["true"]}', "free-text obligation", "guard:not-json{{{", '["not", "a", "dict"]', 'guard:{"name": "g2"}', ]}},), {}), ("_guard_specs_from_obligations", ({},), {}), # ── t_layout: present + absent ── ("t_layout", ({"decision_trace": {"layout_obligations": [ {"component": "c", "obligation": "o"}]}},), {}), ("t_layout", ({},), {}), # ── _obligations_projection: synthetic hash-free fixtures (empty, # pattern-only, layout-only — the contract/structural id branches # carry process-randomized hash → hash battery) ── ("_obligations_projection", ({},), {}), ("_obligations_projection", ({"ext": {"decision_trace": {"obligations": {"pattern": [ {"id": "pat-1", "pattern": "seed_loop", "revision": 3, "obligation": "keep the seed loop closed", "verdict": "SATISFIED", "reason": "evidence row 1", "pattern_applicability": "always"}]}}}},), {}), ("_obligations_projection", ({"ext": {"decision_trace": {"layout_obligations": [ {"component": "ui:header", "obligation": "stay in region top", "verification": "adapter observation"}]}}},), {}), # ── _obligation_scope_files: passthrough stub ── ("_obligation_scope_files", ([{"id": "x"}],), {}), ("_obligation_scope_files", ([],), {}), # ── _authorities: external mode, rune-internal w/ + w/o spine ── ("_authorities", (rig.build_doc(),), {}), ("_authorities", (rig.build_doc(), {"schema_version": 1, "entities": []}), {"mode": "rune_internal"}), ("_authorities", (rig.build_doc(), None), {"mode": "rune_internal"}), # ── _record_session: append + long-detail truncation ── ("_record_session", (rig.build_doc(), "submit_need", "short detail"), {}), ("_record_session", (rig.build_doc(), "close", "d" * 500), {}), # ── classify: envelope assembly over classifier results ── ("classify", ({"mode": "UNKNOWN", "evidence": ["probe: which surface?"], "probe_questions": ["q1"]},), {}), ("classify", ({"mode": "EXISTING_PROJECT_CHANGE", "evidence": ["e1"], "probe_questions": []},), {}), ("classify", ({"mode": "LOCAL_CHANGE"},), {"builder": "other-builder"}), # ── construction_context: none active, explicit unknown id (the # ACTIVE projection carries obligation ids → hash battery) ── ("construction_context", ("cc-none", rig.build_doc()), {}), ("construction_context", ("cc-unknown", DOC_SUBMITTED, "NOPE"), {}), # ── capabilities: the full discovery envelope, both modes ── ("capabilities", (), {"mode": "external_project"}), ("capabilities", (), {"mode": "rune_internal", "project": "issue161-harness"}), # ── submit_need: happy, empty objective, MATERIAL_GAP, approval, # no-generate, custom contract id, task_ref ── ("submit_need", ("sn-ok", rig.build_doc(), "persistent project export"), {}), ("submit_need", ("sn-empty", rig.build_doc(), ""), {}), ("submit_need", ("sn-gap", rig.build_doc(), "change the exporter widget colors"), {"affected_surface": ["capability:exporter"], "constraints": {}, "evidence_refs": ["x"]}), ("submit_need", ("sn-appr", rig.build_doc(), "start a brand new repository for billing"), {"constraints": {"new_repository": True}, "evidence_refs": ["x"]}), ("submit_need", ("sn-nogen", rig.build_doc(), "persistent project export"), {"generate": False}), ("submit_need", ("sn-cid", rig.build_doc(), "persistent project export"), {"contract_id": "MY-CID"}), ("submit_need", ("sn-task", rig.build_doc(), "persistent project export"), {"task_ref": "task-1"}), # ── inspect_decision: ok + unknown ── ("inspect_decision", ("in-ok", DOC_SUBMITTED, rig._submitted_cid(DOC_SUBMITTED)), {}), ("inspect_decision", ("in-no", DOC_SUBMITTED, "NOPE"), {}), # ── get_scope: ok + unknown ── ("get_scope", ("gs-ok", DOC_SUBMITTED, rig._submitted_cid(DOC_SUBMITTED)), {}), ("get_scope", ("gs-no", DOC_SUBMITTED, "NOPE"), {}), # ── get_obligations: unknown (ok carries hash ids → hash battery) ── ("get_obligations", ("go-no", DOC_SUBMITTED, "NOPE"), {}), # ── report_observation: ok, bare-dict, missing entity, unknown ── ("report_observation", ("ro-ok", DOC_SUBMITTED, rig._submitted_cid(DOC_SUBMITTED), [{"entity": "contract:csv_export", "detail": "observed while building"}]), {}), ("report_observation", ("ro-bare", DOC_SUBMITTED, rig._submitted_cid(DOC_SUBMITTED), {"entity": "x"}), {}), ("report_observation", ("ro-noent", DOC_SUBMITTED, rig._submitted_cid(DOC_SUBMITTED), [{"detail": "x"}]), {}), ("report_observation", ("ro-no", DOC_SUBMITTED, "NOPE", [{"entity": "x"}]), {}), # ── verify: unknown, scope unknown/green/red, layout PASS/FAIL/UNKNOWN, # walked-contract contract-quality projection ── ("verify", ("vf-no", DOC_SUBMITTED, "NOPE"), {}), ("verify", ("vf-base", DOC_SUBMITTED, rig._submitted_cid(DOC_SUBMITTED)), {}), ("verify", ("vf-green", DOC_SUBMITTED, rig._submitted_cid(DOC_SUBMITTED)), {"changed_files": ["src/allowed.py"]}), ("verify", ("vf-red", DOC_SUBMITTED, rig._submitted_cid(DOC_SUBMITTED)), {"changed_files": ["src/evil.py"]}), ("verify", ("vf-pass", DOC_SUBMITTED, rig._submitted_cid(DOC_SUBMITTED)), {"layout_observations": {"components": []}}), ("verify", ("vf-fail", DOC_SUBMITTED, rig._submitted_cid(DOC_SUBMITTED)), {"layout_observations": {"header": {"region": "bottom"}}}), ("verify", ("vf-unk", DOC_SUBMITTED, rig._submitted_cid(DOC_SUBMITTED)), {"layout_observations": {"header": {"region": "top"}}}), # ── transition: happy edge, illegal edge, unknown, guard block/pass ── ("transition", ("tr-appr", DOC_SUBMITTED, rig._submitted_cid(DOC_SUBMITTED), "approved"), {}), ("transition", ("tr-ill", DOC_SUBMITTED, rig._submitted_cid(DOC_SUBMITTED), "closed"), {}), ("transition", ("tr-no", DOC_SUBMITTED, "NOPE", "approved"), {}), ("transition", ("tr-block", DOC_SUBMITTED, rig._submitted_cid(DOC_SUBMITTED), "approved"), {"guard_checks": GUARD_FAIL}), ("transition", ("tr-pass", DOC_SUBMITTED, rig._submitted_cid(DOC_SUBMITTED), "approved"), {"guard_checks": GUARD_PASS}), ("transition", ("tr-assert", DOC_SUBMITTED, rig._submitted_cid(DOC_SUBMITTED), "approved"), {"guard_checks": GUARD_ASSERT}), # ── close: full ladder doc, unknown, custom scope files ── ("close", ("cl-ok", DOC_WALKED, rig._submitted_cid(DOC_WALKED), [{"kind": "port_evidence", "detail": "gap closed"}]), {}), ("close", ("cl-scope", DOC_WALKED, rig._submitted_cid(DOC_WALKED), [{"kind": "port_evidence", "detail": "gap closed"}]), {"scope_files": ["src/export.py"]}), ("close", ("cl-no", DOC_WALKED, "NOPE", [{"entity": "x"}]), {}), # ── _programme_continuation: bound, unbound stage, no programme dir ── ("_programme_continuation", ("pc-hit", DOC_SUBMITTED, rig._submitted_cid(DOC_SUBMITTED)), {"programmes": PROGRAMMES_BOUND}), ("_programme_continuation", ("pc-miss", DOC_SUBMITTED, "other-stage"), {"programmes": PROGRAMMES_BOUND}), ("_programme_continuation", ("pc-none", DOC_SUBMITTED, rig._submitted_cid(DOC_SUBMITTED)), {}), # ── _auto_material_change: hit, miss, no ledger ── ("_auto_material_change", ("mc-hit", DOC_SUBMITTED, ["src/export.py"]), {"capabilities": DOC_WITH_LEDGER_CAPS}), ("_auto_material_change", ("mc-miss", DOC_SUBMITTED, ["src/zzz.py"]), {"capabilities": DOC_WITH_LEDGER_CAPS}), ("_auto_material_change", ("mc-nol", DOC_SUBMITTED, ["src/export.py"]), {}), # ── discover_active_contract: seeded store, empty store ── ("discover_active_contract", ("dc-seed", [{"project": "alpha", "doc": rig._discover_doc("old", "2026-10-01T00:00:00Z", "alpha")}, {"project": None, "doc": rig._discover_doc("main-latest", "2026-10-03T00:00:00Z", "gamma")}]), {}), ("discover_active_contract", ("dc-empty", []), {}), # ── resume: unknown (ok carries hash ids → hash battery) ── ("resume", ("rs-no", DOC_SUBMITTED, "NOPE"), {}), # ── amend_scope: ok, non-user, unknown ── ("amend_scope", ("am-ok", DOC_SUBMITTED, rig._submitted_cid(DOC_SUBMITTED), ["src/a.py"]), {"reason": "user asked"}), ("amend_scope", ("am-nouser", DOC_SUBMITTED, rig._submitted_cid(DOC_SUBMITTED), ["src/a.py"]), {"reason": "x", "authority": "builder"}), ("amend_scope", ("am-no", DOC_SUBMITTED, "NOPE", ["a"]), {"reason": "x"}), # ── main: every CLI command ── ("main", ("m-help",), {"argv": ["--help"]}), ("main", ("m-unk",), {"argv": ["frobnicate"]}), ("main", ("m-caps",), {"argv": ["capabilities"]}), ("main", ("m-cls",), {"argv": ["classify", '{"objective": "fix typo"}']}), ("main", ("m-ctx",), {"argv": ["context"]}), ("main", ("m-sub",), {"argv": ["submit-need", '{"objective": "x"}']}), ("main", ("m-dec",), {"argv": ["decision", "NOPE"]}), ("main", ("m-scope",), {"argv": ["scope", "NOPE"]}), ("main", ("m-obl",), {"argv": ["obligations", "NOPE"]}), ("main", ("m-obs",), {"argv": ["observe", "NOPE", "[]"]}), ("main", ("m-ver",), {"argv": ["verify", "NOPE"]}), ("main", ("m-tr",), {"argv": ["transition", "NOPE", "approved"]}), ("main", ("m-close",), {"argv": ["close", "NOPE", "[]"]}), ("main", ("m-res",), {"argv": ["resume", "NOPE"]}), # ── the FULL ladder in ONE process (shared-store clobber law) ── ("ladder_walk", ("walk1",), {}), ("ladder_walk", ("walk2", "start a brand new repository for billing"), {}), ] truth = freeze("rune.construction_interface", cases, oracle_module="rune.construction_interface") write(truth, REPO / "src" / "rust" / "construction_interface" / "frozen_ci_truth.json") print(f"froze {len(truth)} cases") # ── §2 hash battery: every envelope carrying obligation ids. Captured + # verified with PYTHONHASHSEED=0 (set at INTERPRETER start — the seed # cannot be changed mid-process, so the main run re-execs itself for # this part); the Rust battery SHAPE-pins these ids (prefix before ":", # stable description/kind/provenance/status) — never value-freezes the # randomized suffix. ── HASH_CASES = [ ("_obligations_projection", (rig.contract_of(DOC_SUBMITTED, rig._submitted_cid(DOC_SUBMITTED)),), {}), ("construction_context", ("hc-active", DOC_SUBMITTED), {}), ("construction_context", ("hc-explicit", DOC_SUBMITTED, rig._submitted_cid(DOC_SUBMITTED)), {}), ("get_obligations", ("ho-ok", DOC_SUBMITTED, rig._submitted_cid(DOC_SUBMITTED)), {}), ("resume", ("hr-ok", DOC_SUBMITTED, rig._submitted_cid(DOC_SUBMITTED)), {}), ] if os.environ.get("CI_GEN_HASH_ONLY") == "1": assert os.environ.get("PYTHONHASHSEED") == "0", \ "hash battery requires PYTHONHASHSEED=0 at interpreter start" hash_truth = freeze("rune.construction_interface", HASH_CASES, oracle_module="rune.construction_interface") write(hash_truth, REPO / "src" / "rust" / "construction_interface" / "frozen_ci_truth_hash.json") print(f"froze {len(hash_truth)} hash cases (PYTHONHASHSEED=0)") else: env = dict(os.environ, PYTHONHASHSEED="0", CI_GEN_HASH_ONLY="1", PYTHONPATH="scripts/ci_freeze_seams:src") subprocess.run([sys.executable, str(Path(__file__).resolve())], check=True, env=env, cwd=str(REPO))