- 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.
67 lines
2.5 KiB
Python
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"])
|