Files
rune/scripts/gen_structural_model_truth.py
T
Nick 00839d1af7 feat(structural_model): close PARTIAL gaps — dichotomy wave
Port the 11 audit-missing functions of src/rune/structural_model.py to the
Rust crate (name-preserving, logic-1:1): workspace_record, workspace_advance,
_init_project, save, reload, add, relate, state_owned,
verification_surfaces, canonical_state_owner, supersession — plus a true
deployment_surfaces (the old deployment_surfaces_for stub is gone, no
callers), the lowercase-stale filters on dependencies/consumers, and the
full §18F impact_closure shape the W6-era port had reduced.

Fix-first: the delegation seam imported rune.sm_loader — the SHARD_MANAGER
loader (no query symbol), so every kernel call died into the Python floor.
The seam now targets stm_loader (the crate's sm_* FFI, RUNE_STM_CORE=python
pins the floor). workspace_advance keeps the oracle's in-place law.

Verification (verification/structural_model-summary.md): frozen truth 70
cases byte-identical (gen_structural_model_truth.py --verify), battery 16/16
with truth embedded via include_str!, live parity 4620/4620 (frozen replay +
300-doc seeded fuzz + dual-mode facade), clippy -D warnings clean, Python
suites green in both pins (pre-existing 2F/12E verified identical on the
stashed base). Audit: 9/20 PARTIAL -> 21/21 FULL.
2026-10-14 05:53:36 +01:00

398 lines
17 KiB
Python

#!/usr/bin/env python3
"""Freeze the dichotomy-wave gap-closing truth corpus for
src/rune/structural_model.py (issue #2479 tranche).
LAW (poisoned-truth): RUNE_STM_CORE=python and RUNE_STRUCTURAL_CORE=python
are pinned at the top — truth is generated by the PYTHON ORACLE ONLY.
Inputs are deep-copied before every oracle call (no leakage between
cases). The clock is pinned by monkeypatching structural_store.now (the
no-clock law on the Rust side: `now` is always an argument).
The frozen corpus is embedded VERBATIM in the crate's cfg(test) battery
(src/frozen_battery.rs, include_str!) and replayed by
scripts/check_structural_model_parity.py through the live FFI.
--verify regenerates from the live oracle and byte-compares the frozen
file (layer 3 of the verification ladder: truth consumed, not
self-generated).
"""
import copy
import json
import os
import sys
import tempfile
from pathlib import Path
os.environ["RUNE_STM_CORE"] = "python" # poisoned-truth law
os.environ["RUNE_STRUCTURAL_CORE"] = "python" # the floor's store core too
REPO = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(REPO / "src"))
from rune import structural_store as ss # noqa: E402
from rune import structural_model as sm # noqa: E402
FIXED_NOW = "2026-10-13T01:02:03Z"
ss.now = lambda: FIXED_NOW # pin the clock the floor's add/save stamps use
OUT = REPO / "src" / "rust" / "structural_model" / "src" / "frozen_sm_truth.json"
groups: dict[str, list] = {}
def case(group, name, args, expect):
groups.setdefault(group, []).append({"fn": group, "name": name, "args": args, "expect": expect})
def receiver(doc, project_id="proj", path="/tmp/sm-frozen/structural.json"):
"""A StructuralModel with a pre-set doc — no filesystem in __init__."""
m = sm.StructuralModel.__new__(sm.StructuralModel)
m.store_dir = None
m.project_id = project_id
m.path = path
m.doc = doc
return m
def ent(id, kind="component", maturity="DECLARED", **kw):
e = {
"id": id,
"kind": kind,
"maturity": maturity,
"tags": [],
"identities": {},
"evidence_refs": [],
"observed_at": FIXED_NOW,
}
e.update(kw)
return e
def rel(t, f, to, **kw):
r = {"type": t, "from": f, "to": to, "evidence_refs": ["ev"], "observed_at": FIXED_NOW}
r.update(kw)
return r
def fixture_doc():
"""The Scaffolding-shaped reference model (entities + every rel class)."""
d = {
"schema_version": 1,
"generated_at": FIXED_NOW,
"entities": [
ent("project:proj", "project"),
ent("domain:core", "domain"),
ent("component:alpha", "component"),
ent("component:beta", "component"),
ent("component:gamma", "component", aliases=["component:old"]),
ent("interface:api", "interface"),
ent("state_store:s1", "state_store"),
ent("state_store:s2", "state_store"),
ent("test_suite:t1", "test_suite"),
ent("deployment_surface:d1", "deployment_surface"),
],
"relationships": [
rel("belongs_to", "domain:core", "project:proj"),
rel("belongs_to", "component:alpha", "domain:core"),
rel("belongs_to", "component:beta", "domain:core"),
rel("belongs_to", "interface:api", "domain:core"),
rel("belongs_to", "state_store:s1", "project:proj"),
rel("belongs_to", "test_suite:t1", "project:proj"),
rel("belongs_to", "deployment_surface:d1", "project:proj"),
rel("depends_on", "component:beta", "component:alpha"),
rel("depends_on", "component:gamma", "component:beta", status="stale"),
rel("provides", "component:alpha", "interface:api"),
rel("consumes", "component:beta", "interface:api"),
rel("consumes", "component:gamma", "interface:api", status="STALE"),
rel("owns", "component:alpha", "state_store:s1"),
rel("owns", "component:beta", "state_store:s2"),
rel("verified_by", "component:alpha", "test_suite:t1"),
rel("deployed_by", "component:alpha", "deployment_surface:d1", status="stale"),
rel("supersedes", "component:alpha", "component:beta"),
rel("supersedes", "component:gamma", "component:alpha"),
rel("legacy_of", "component:alpha", "component:gamma"),
rel("connects_to", "deployment_surface:d1", "test_suite:t1"),
],
"observations": [],
}
return d
def q_case(group, doc, eid, call):
args = {"doc": copy.deepcopy(doc), "eid": eid}
case(group, f"{eid}", args, {"ok": call(receiver(copy.deepcopy(doc)), eid)})
def main():
doc = fixture_doc()
m = receiver(copy.deepcopy(doc))
# ── query kernels (incl. the stale filters) ─────────────────────────
for eid in ["domain:core", "project:proj", "component:alpha", "component:beta", "component:old"]:
q_case("children", doc, eid, lambda mm, e: mm.children(e))
q_case("beneath", doc, "domain:core", lambda mm, e: mm.beneath(e))
q_case("beneath", doc, "project:proj", lambda mm, e: mm.beneath(e))
for eid in ["component:alpha", "domain:core", "component:gamma", "deployment_surface:d1"]:
q_case("owning_domain", doc, eid, lambda mm, e: mm.owning_domain(e))
for eid in ["component:beta", "component:alpha", "component:gamma"]:
q_case("dependencies", doc, eid, lambda mm, e: mm.dependencies(e))
for eid in ["component:alpha", "interface:api", "state_store:s1"]:
q_case("consumers", doc, eid, lambda mm, e: mm.consumers(e))
q_case("interfaces_for", doc, "component:alpha", lambda mm, e: mm.interfaces_for(e))
for eid in ["component:alpha", "component:beta", "component:gamma"]:
q_case("state_owned", doc, eid, lambda mm, e: mm.state_owned(e))
q_case("verification_surfaces", doc, "component:alpha", lambda mm, e: mm.verification_surfaces(e))
# surfaces carry NO stale filter (oracle)
q_case("deployment_surfaces", doc, "component:alpha", lambda mm, e: mm.deployment_surfaces(e))
for eid in ["component:alpha", "state_store:s1", "component:old", "component:zz"]:
q_case("canonical_state_owner", doc, eid, lambda mm, e: mm.canonical_state_owner(e))
q_case("supersession", doc, "component:alpha", lambda mm, e: mm.supersession(e))
q_case("supersession", doc, "component:gamma", lambda mm, e: mm.supersession(e))
# ── impact_closure (full §18F shape) ─────────────────────────────────
for name, eid, depth in [
("full", "component:alpha", None),
("root", "project:proj", None),
("leaf_state_store", "state_store:s1", None),
("depth_bound_1", "component:alpha", 1),
("unknown_entity", "nope:x", None),
("quoted_eid", "it's", None),
]:
args = {"doc": copy.deepcopy(doc), "eid": eid}
kwargs = {}
if depth is not None:
args["max_depth"] = depth
kwargs = {"max_depth": depth}
r = receiver(copy.deepcopy(doc)).impact_closure(eid, **kwargs)
case("impact_closure", name, args, {"ok": r})
# ── workspace_record / workspace_advance ─────────────────────────────
wr = sm.workspace_record(contract_id="C-1", construction_base="sha1")
case("workspace_record", "defaults", {"contract_id": "C-1", "construction_base": "sha1"}, {"ok": wr})
wr2 = sm.workspace_record(
contract_id="C-2",
construction_base="sha2",
runtime_generation="rt",
candidate_generation="cd",
promotion_target="gitea/release",
rollback_generation="rb",
)
case(
"workspace_record",
"full",
{
"contract_id": "C-2",
"construction_base": "sha2",
"runtime_generation": "rt",
"candidate_generation": "cd",
"promotion_target": "gitea/release",
"rollback_generation": "rb",
},
{"ok": wr2},
)
def wa_case(name, stages, stage, evidence="", build=None):
record = build if build is not None else sm.workspace_record(contract_id="C-3", construction_base="sha3")
for s in stages:
record = sm.workspace_advance(record, s)
args = {"record": copy.deepcopy(record), "stage": stage, "evidence": evidence}
try:
out = sm.workspace_advance(copy.deepcopy(record), stage, evidence=evidence)
expect = {"ok": out}
except ValueError as exc:
expect = {"err": str(exc)}
case("workspace_advance", name, args, expect)
wa_case("first_stage", [], "base_verified")
wa_case("second_stage", ["base_verified"], "worktree_created")
wa_case("evidence_truncated", ["base_verified"], "worktree_created", evidence="e" * 250)
wa_case("evidence_empty_no_key", ["base_verified"], "construction")
wa_case("evidence_second_appends", ["base_verified", "worktree_created"], "construction", evidence="second")
wa_case("wrong_first", [], "construction")
wa_case("skip_stage", ["base_verified"], "verified")
wa_case("backwards", ["base_verified", "worktree_created"], "base_verified")
wa_case("unknown_stage", [], "bogus")
wa_case("unknown_mid", ["base_verified"], "bogus")
# missing stages_completed → KeyError (crash parity)
args = {"record": {"contract_id": "C"}, "stage": "base_verified", "evidence": ""}
try:
sm.workspace_advance(copy.deepcopy(args["record"]), "base_verified")
expect = {"ok": None}
except KeyError as exc:
expect = {"err": f"KeyError: {exc}"}
case("workspace_advance", "missing_stages_key", args, expect)
# ── add ──────────────────────────────────────────────────────────────
def add_case(name, d, kind, name_, parent=None, ext=None, evidence_ref="structural-model"):
args = {
"doc": copy.deepcopy(d),
"kind": kind,
"name": name_,
"parent": parent,
"ext": ext,
"evidence_ref": evidence_ref,
}
mm = receiver(copy.deepcopy(d))
try:
eid = mm.add(kind, name_, parent=parent, ext=ext, evidence_ref=evidence_ref)
expect = {"ok": {"doc": mm.doc, "eid": eid}}
except (ValueError, KeyError) as exc:
expect = {"err": f"{type(exc).__name__}: {exc}" if isinstance(exc, KeyError) else str(exc)}
case("add", name, args, expect)
base = {
"schema_version": 1,
"generated_at": FIXED_NOW,
"entities": [
ent("project:proj", "project"),
ent("domain:core", "domain"),
ent("component:there", "component", maturity="PRESENT"),
],
"relationships": [],
"observations": [],
}
add_case("fresh", base, "component", "alpha", parent="domain:core")
add_case("with_ext", base, "interface", "api", ext={"proto": "grpc", "notes": "n"})
add_case("unknown_kind", base, "widget", "w")
add_case("quoted_kind", base, "it's", "w")
add_case("custom_evidence", base, "test_suite", "t", evidence_ref="ev-x")
readd = copy.deepcopy(base)
readd["entities"].append(
ent("component:again", "component", maturity="PRESENT", identities={"name": "old"}, ext={"keep": 1})
)
add_case("readd_refreshes", readd, "component", "again", ext={"new": 2})
no_identities = copy.deepcopy(base)
no_identities["entities"].append({"id": "component:bare", "kind": "component", "maturity": "DECLARED"})
add_case("missing_identities_crash", no_identities, "component", "bare")
add_case("empty_ext_falsy_skipped", base, "environment", "prod", ext={})
# ── relate ──────────────────────────────────────────────────────────
def relate_case(
name,
d,
from_id,
rl,
to_id,
evidence_ref="structural-model",
authority="model-author",
status="active",
ext=None,
):
args = {
"doc": copy.deepcopy(d),
"from_id": from_id,
"rel": rl,
"to_id": to_id,
"evidence_ref": evidence_ref,
"authority": authority,
"status": status,
"ext": ext,
}
mm = receiver(copy.deepcopy(d))
try:
r = mm.relate(from_id, rl, to_id, evidence_ref=evidence_ref, authority=authority, status=status, ext=ext)
expect = {"ok": {"doc": mm.doc, "rel": r}}
except ValueError as exc:
expect = {"err": str(exc)}
case("relate", name, args, expect)
relate_case("defaults", base, "component:there", "depends_on", "project:proj")
relate_case(
"importer_authority", base, "component:there", "calls", "domain:core", authority="importer", status="CURRENT"
)
relate_case("with_ext", base, "component:there", "reads", "domain:core", ext={"line": 3})
relate_case("unknown_rel", base, "component:there", "hates", "domain:core")
relate_case("empty_evidence", base, "component:there", "writes", "domain:core", evidence_ref="")
relate_case("empty_ext_falsy_skipped", base, "component:there", "connects_to", "domain:core", ext={})
dupdoc = copy.deepcopy(base)
sm.StructuralModel.relate(receiver(dupdoc), "component:there", "depends_on", "project:proj")
relate_case(
"dup_keeps_stored", dupdoc, "component:there", "depends_on", "project:proj", authority="user", status="legacy"
)
# ── _init_project / save / reload (real filesystem, byte law) ───────
with tempfile.TemporaryDirectory() as td:
m2 = sm.StructuralModel(td + "/s1", "init-proj")
# the constructor's pre-_init_project doc IS new_doc() (pinned clock)
case(
"init_project",
"fresh_construction",
{"doc": ss.new_doc(), "project_id": "init-proj"},
{"ok": {"doc": m2.doc, "content": Path(m2.path).read_text()}},
)
m3 = sm.StructuralModel(td + "/s2", "save-proj")
m3.add("domain", "core", parent="project:save-proj")
m3.add("component", "alpha", parent="domain:core")
m3.relate("component:alpha", "owns", "state_store:s1")
m3.save()
case(
"save",
"byte_law",
{"doc": copy.deepcopy(m3.doc)},
{"ok": {"doc": m3.doc, "content": Path(m3.path).read_text()}},
)
# a doc with secrets — the store's redaction law applies on disk
m4 = sm.StructuralModel(td + "/s3", "redact-proj")
m4.doc["credentials"] = {"token": "s3cret", "note": "keep"}
m4.save()
case(
"save",
"secrets_redacted",
{"doc": copy.deepcopy(m4.doc)},
{"ok": {"doc": m4.doc, "content": Path(m4.path).read_text()}},
)
# save() stamps schema_version=1 BEFORE the store save — a stale
# 99 is coerced, never raised (the facade's own law)
m5 = receiver({"schema_version": 99, "entities": [], "relationships": []}, "bad", td + "/s4/structural.json")
m5.save()
case(
"save",
"schema_version_stamped",
{"doc": {"schema_version": 99, "entities": [], "relationships": []}},
{"ok": {"doc": m5.doc, "content": Path(m5.path).read_text()}},
)
# reload: existing / missing / corrupt
m6 = sm.StructuralModel(td + "/s2", "save-proj")
m6.reload()
case("reload", "existing_file", {}, {"ok": {"doc": m6.doc}})
m7 = receiver(
{"schema_version": 1, "entities": [], "relationships": []}, "miss", td + "/missing/structural.json"
)
m7.reload()
case("reload", "missing_file_keeps_doc", {}, {"ok": {"doc": m7.doc}})
corrupt = td + "/corrupt/structural.json"
Path(corrupt).parent.mkdir(parents=True, exist_ok=True)
Path(corrupt).write_text("{not json")
m8 = receiver({"schema_version": 1, "entities": [], "relationships": []}, "corrupt", corrupt)
m8.reload()
case("reload", "corrupt_file_keeps_doc", {}, {"ok": {"doc": m8.doc}})
out = {"module": "structural_model", "now": FIXED_NOW, "groups": groups}
text = json.dumps(out, indent=1, sort_keys=True) + "\n"
if "--verify" in sys.argv:
frozen = OUT.read_text()
if frozen == text:
print(
f"OK: frozen truth byte-identical against live oracle "
f"({sum(len(v) for v in groups.values())} cases) -> {OUT}"
)
return 0
print("MISMATCH: regenerated truth differs from frozen file")
for a, b in zip(frozen.splitlines(), text.splitlines()):
if a != b:
print(f" frozen: {a[:200]}")
print(f" fresh: {b[:200]}")
break
return 1
OUT.write_text(text)
total = sum(len(v) for v in groups.values())
print(f"frozen {total} cases across {len(groups)} groups -> {OUT}")
return 0
if __name__ == "__main__":
sys.exit(main())