Files
rune/tests/test_graph_projection.py
T
Nick aa9750c59f feat(v1): self-scaffold + self-scaffolded upgrade + graph projection + convergence (T18 18M-18Q)
- 18O: ONE canonical structural Scaffold of Scaffolding itself
  (store/scaffold/structural.json — 31 entities, 46 authority-graded
  relationships: domains/subsystems/components with real source paths,
  state stores, verification, deployment, the bounded build_mode
  adapter marked legacy_of). 5 consistency held-outs: sources exist,
  no duplicate truth with Spine, legacy not hidden, schema known to
  consent machinery.
- 18P SELF-SCAFFOLDED UPGRADE PROOF: contract 18q-graph-projection
  driven end-to-end FROM the maintained scaffold — structural lookup →
  contextually-generated research plan → qualified Build Basis →
  impact closure → visible preview → contract+workspace record →
  event-bridged verification (resumed via event, verdict success) →
  authority re-read → scaffold updated by the model itself → closed.
  All 11 steps scaffold-driven; zero architecture rediscovery.
- 18Q: graph_projection.py — stable versioned READ-ONLY projection
  (JSON/DOT/Mermaid) over structural truth; never an authority. 4
  held-outs incl. read-only proof.
- 18N generalisation: adversarial paraphrase families (37 unseen
  phrases across 6 tests) found and fixed 4 REAL semantic gaps:
  negation frames, idiom-prefix imperatives, modal+proposal referent
  ordering, all-stale-proposals fallthrough, preceding-context
  relative-that disambiguation.
- 18M full backend convergence: /build start now MINTS a canonical
  Construction Contract (classified) before BuildManager — no route
  runs an independent construction state machine.

Suite 1966 green; ratchets PASS.
2026-09-15 23:33:42 +01:00

67 lines
2.5 KiB
Python

"""test_graph_projection.py — T18 §18Q/§18P: read-only graph projection
+ the self-scaffolded upgrade proof record."""
from __future__ import annotations
import sys
from pathlib import Path
REPO = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(REPO / "src"))
from rune import graph_projection as gp # noqa: E402
from rune import structural_model as sm # noqa: E402
SELF = REPO / "store" / "scaffold"
def _self_model():
return sm.StructuralModel(SELF, "scaffolding")
def test_18q_projection_is_versioned_and_complete():
m = _self_model()
j = gp.project_json(m)
assert j["schema_version"] == gp.PROJECTION_SCHEMA_VERSION == 1
assert j["node_count"] >= 25 and j["edge_count"] >= 30
# no internal storage layout leaked: only curated ext keys
for n in j["nodes"]:
assert set(n.keys()) <= {"id", "kind", "maturity", "name", "ext"}
assert set((n.get("ext") or {}).keys()) <= {"source",
"bounded_adapter"}
def test_18q_dot_and_mermaid_render_parse():
m = _self_model()
dot = gp.project_dot(m)
assert dot.startswith("digraph") and dot.count("->") >= 30
mm = gp.project_mermaid(m)
assert mm.startswith("graph LR") and mm.count("-->") >= 30
# DOT/Mermaid ids are safe (quoted / mangled) even with ':' in ids
assert '"component:scaffold"' in dot # quoted DOT ids
assert " component:scaffold " not in mm # mangled in mermaid
def test_18q_projection_is_read_only():
m = _self_model()
before = (SELF / "structural.json").read_text()
gp.project_json(m); gp.project_dot(m); gp.project_mermaid(m)
assert (SELF / "structural.json").read_text() == before
def test_18p_upgrade_proof_artifacts_exist():
rec = REPO / "store/scaffold/programmes" # programme records live
contract_docs = (SELF / "current.json").read_text()
assert "18q-graph-projection" in contract_docs
assert "closed" in contract_docs
wsr = REPO / "store/evidence/t18/18P_workspace_record.json"
import json
r = json.loads(wsr.read_text())
assert r["stages_completed"][:4] == ["base_verified", "worktree_created",
"construction", "verified"]
assert r["construction_base"] # started from a verified base SHA
# the projection output exists and matches the live model
j = json.loads((REPO / "store/evidence/t18/projection/"
"structural_graph.json").read_text())
assert any(n["id"] == "component:graph_projection" for n in j["nodes"])