Files
rune/tests/test_spine.py
T
Nick 24d14ff8e1 fix(spine): preserve candidate discoveries without inventing module IDs (#2465)
Migrate 22 malformed contract-discovery IDs to construction-surface, retain evidence/edges, keep candidates DECLARED, unify cold/warm language projection, and refresh the pinned aiohttp lock. Red regression tests precede the fix; local full suite 2301 passed, spine canaries 19/19 and 21/21.
2026-10-05 22:14:46 +01:00

981 lines
53 KiB
Python

"""test_spine.py — Spine V1 contract tests.
Deterministic core, open-world extensibility, evidence-gated maturity,
snapshot/delta, drift, and the synthetic future-capability proof.
Machine-independent: deployment observations use fixture stores.
"""
import json
import sys
import tempfile
from pathlib import Path
import pytest
ROOT = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT / "src"))
from rune import spine
def test_contract_discovery_preserves_unqualified_surface_without_inventing_module(monkeypatch):
monkeypatch.setattr(spine, "_contract_discoveries", lambda: [
("example", [("src/rune/audit_ledger.py", "construction-surface", "candidate"),
("rust-crate:cognition_core", "rust-crate", "observed")])])
doc = spine.new_doc()
spine._apply_contract_discoveries(doc)
found = {e["id"]: e for e in doc["entities"]}
assert found["construction-surface:src/rune/audit_ledger.py"]["kind"] == "construction-surface"
assert found["construction-surface:src/rune/audit_ledger.py"]["maturity"] == "DECLARED"
assert found["rust-crate:cognition_core"]["maturity"] == "PRESENT"
def test_legacy_unqualified_discoveries_are_normalized_without_losing_evidence():
doc = spine.new_doc()
spine.add_entity(doc, id="src/rune/audit_ledger.py", kind="module",
maturity="PRESENT", evidence_refs=["contract-discovery:example"])
spine.add_relationship(doc, type="depends_on", from_id="src/rune/audit_ledger.py",
to_id="module:other", evidence_refs=["test"])
spine._normalize_discovery_ids(doc)
assert doc["entities"][0]["id"] == "construction-surface:src/rune/audit_ledger.py"
assert doc["entities"][0]["maturity"] == "DECLARED"
assert doc["entities"][0]["evidence_refs"] == ["contract-discovery:example"]
assert doc["relationships"][0]["from"] == "construction-surface:src/rune/audit_ledger.py"
# ── helpers ───────────────────────────────────────────────────────────────
@pytest.fixture
def doc():
return spine.new_doc()
@pytest.fixture
def seeded(doc):
"""Minimal structural world: two subsystems, two modules."""
spine.add_entity(doc, id="subsystem:alpha", kind="subsystem",
identities={"description": "Alpha"}, maturity="DECLARED")
spine.add_entity(doc, id="subsystem:beta", kind="subsystem",
identities={"description": "Beta"}, maturity="DECLARED")
spine.add_entity(doc, id="module:m_a", kind="module", maturity="DECLARED",
identities={"source": "src/rune/m_a.py"})
spine.add_entity(doc, id="module:m_b", kind="module", maturity="DECLARED",
identities={"source": "src/rune/m_b.py"})
spine.add_relationship(doc, type="belongs_to", from_id="module:m_a",
to_id="subsystem:alpha", evidence_refs=["test"])
spine.add_relationship(doc, type="belongs_to", from_id="module:m_b",
to_id="subsystem:beta", evidence_refs=["test"])
return doc
# ── deterministic entity projection / lookups ─────────────────────────────
class TestLookups:
def test_entity_projection_roundtrip(self, seeded, tmp_path):
p = tmp_path / "s.json"
spine.save(seeded, p)
loaded = spine.load(p)
assert loaded == spine.load(p) # byte-stable across loads
assert spine.entity(loaded, "module:m_a")["kind"] == "module"
def test_ownership_lookup(self, seeded):
subs = [r["to"] for r in spine.relationships(
seeded, from_id="module:m_a", type="belongs_to")]
assert subs == ["subsystem:alpha"]
def test_dependency_lookup(self, seeded):
spine.add_relationship(seeded, type="depends_on", from_id="module:m_a",
to_id="module:m_b", evidence_refs=["ast"])
deps = [r["to"] for r in spine.relationships(
seeded, from_id="module:m_a", type="depends_on")]
assert deps == ["module:m_b"]
def test_consumer_lookup(self, seeded):
# "consumed_by" edges run provider → consumer: m_a is consumed by m_b
spine.add_relationship(seeded, type="consumed_by", from_id="module:m_a",
to_id="module:m_b", evidence_refs=["ast"])
consumers = [r["to"] for r in spine.relationships(
seeded, from_id="module:m_a", type="consumed_by")]
assert consumers == ["module:m_b"]
def test_missing_entity_is_not_found(self, seeded):
assert spine.entity(seeded, "module:ghost") is None
assert spine.relationships(seeded, from_id="module:ghost") == []
# ── open-world extensibility (the Prime Directive) ────────────────────────
class TestOpenWorld:
def test_unknown_kind_relationship_and_metadata_survive_roundtrip(self, seeded, tmp_path):
"""THE extensibility test: a synthetic future capability Spine core
was never written to understand enters as DATA — no core change."""
spine.add_entity(
seeded, id="capability:quantum_resonator_cache", kind="quantum_resonator_cache",
tags=["synthetic-future"], maturity="DECLARED",
identities={"resonance": "7.83Hz", "home_node": "orb-9"},
evidence_refs=["synthetic:proof"],
ext={"entanglement_pair": "module:m_a", "wibble_level": 11,
"future_field_undefined_in_v1": {"nested": True}})
spine.add_relationship(
seeded, type="harmonizes_with", from_id="capability:quantum_resonator_cache",
to_id="module:m_a", evidence_refs=["synthetic:resonance-proof"],
ext={"coupling": "0.99", "unknown_later_field": [1, 2, 3]})
p = tmp_path / "roundtrip.json"
spine.save(seeded, p)
loaded = spine.load(p)
e = spine.entity(loaded, "capability:quantum_resonator_cache")
assert e["kind"] == "quantum_resonator_cache" # unknown kind preserved
assert e["ext"]["wibble_level"] == 11 # unknown metadata preserved
assert e["ext"]["future_field_undefined_in_v1"]["nested"] is True
assert e["identities"]["resonance"] == "7.83Hz"
rels = spine.relationships(loaded, type="harmonizes_with")
assert len(rels) == 1 # unknown relationship type preserved
assert rels[0]["ext"]["coupling"] == "0.99"
assert rels[0]["to"] == "module:m_a" # linked to a real entity
# delta sees it
base = spine.new_doc()
d = spine.diff(base, loaded)
assert "capability:quantum_resonator_cache" in d["entities_added"]
assert "harmonizes_with|capability:quantum_resonator_cache|module:m_a" \
in d["relationships_added"]
# Scaffolding-style consumption: generic queries work on unknown kinds
assert spine.relationships(loaded, from_id="capability:quantum_resonator_cache")
def test_no_closed_enum_in_core(self):
"""Core must not hardcode today's ontology as a whitelist."""
source = (ROOT / "src" / "rune" / "spine.py").read_text()
# the maturity ladder is a scale, not an entity-kind ontology
assert "VALID_KINDS" not in source and "VALID_RELATIONSHIP_TYPES" not in source
# ── evidence / maturity semantics ─────────────────────────────────────────
class TestMaturity:
def test_no_evidence_no_promotion(self, seeded):
with pytest.raises(ValueError, match="requires evidence"):
spine.promote(seeded, "module:m_a", "PRESENT", "")
def test_no_evidence_means_no_live_proven(self, seeded):
e = spine.entity(seeded, "module:m_a")
assert e["maturity"] == "DECLARED" # nothing observed: stays DECLARED
def test_ladder_is_monotonic_with_evidence(self, seeded):
for state, ev in [("PRESENT", "src"), ("WIRED", "imports"), ("EXERCISED", "tests")]:
spine.promote(seeded, "module:m_a", state, ev)
assert spine.entity(seeded, "module:m_a")["maturity"] == "EXERCISED"
def test_demotion_rejected_and_recorded(self, seeded):
spine.promote(seeded, "module:m_a", "WIRED", "imports-x")
e = spine.promote(seeded, "module:m_a", "DECLARED", "downgrade-attempt")
assert e["maturity"] == "WIRED" # not silently demoted
assert any(o["kind"] == "maturity_demotion_rejected"
for o in seeded["observations"])
def test_unknown_maturity_state_rejected(self, seeded):
with pytest.raises(ValueError, match="unknown maturity"):
spine.promote(seeded, "module:m_a", "TRANSCENDENT", "vibes")
# ── deployed identity observation ─────────────────────────────────────────
class TestDeployedObservation:
def test_observes_fixture_identity(self, doc, tmp_path, monkeypatch):
dep = tmp_path / "deploy"
(dep / "src" / "rune").mkdir(parents=True)
(dep / "src" / "rune" / "_build_identity.json").write_text(json.dumps(
{"commit": "a" * 40, "version": "9.9.9", "deployed_at": "T"}))
monkeypatch.setattr(spine, "DEPLOYED_LINK", dep)
obs = spine._deployed_observation()
assert obs["deployed_sha"] == "a" * 12 and obs["deployed_version"] == "9.9.9"
def test_absent_deployment_is_none_not_invented(self, monkeypatch, tmp_path):
monkeypatch.setattr(spine, "DEPLOYED_LINK", tmp_path / "nonexistent")
assert spine._deployed_observation() is None
def test_deployed_identity_drift_detected(self, seeded, tmp_path, monkeypatch):
dep = tmp_path / "deploy"
(dep / "src" / "rune").mkdir(parents=True)
(dep / "src" / "rune" / "_build_identity.json").write_text(json.dumps(
{"commit": "b" * 40, "version": "0.0.1-test-mismatch", "deployed_at": "T"}))
monkeypatch.setattr(spine, "DEPLOYED_LINK", dep)
monkeypatch.setattr(spine, "ROOT", tmp_path) # no pyproject → no source version
# no version drift observable without source; identity observation works
obs = spine._deployed_observation()
assert obs["deployed_version"] == "0.0.1-test-mismatch"
# ── drift ─────────────────────────────────────────────────────────────────
class TestDrift:
def test_registered_but_absent(self, seeded, monkeypatch):
monkeypatch.setattr(spine, "_canary_registry", lambda: ["m_ghost"])
monkeypatch.setattr(spine, "SRC_DIR", tmp_src := ROOT / "src" / "rune") # real dir
d = spine.drift(seeded)
assert any(x["class"] == "registered_but_absent" and x["entity"] == "module:m_ghost"
for x in d)
def test_relationship_disappeared(self, seeded, monkeypatch):
spine.add_relationship(seeded, type="consumed_by", from_id="module:m_a",
to_id="module:m_b", evidence_refs=["stale"])
monkeypatch.setattr(spine, "_import_graph", lambda: {"m_b": set()})
monkeypatch.setattr(spine, "_canary_registry", lambda: [])
monkeypatch.setattr(spine, "SRC_DIR", ROOT / "src" / "rune")
d = spine.drift(seeded)
assert any(x["class"] == "relationship_disappeared" for x in d)
def test_stale_evidence_does_not_prove_live(self, seeded):
"""A stale evidence ref must never read as LIVE_PROVEN."""
e = spine.entity(seeded, "module:m_a")
e["evidence_refs"].append("deployed-tree:deadbeef-old-observation")
assert e["maturity"] == "DECLARED" # evidence ref alone promotes nothing
# LIVE_PROVEN only via explicit evidence-gated promotion
spine.promote(seeded, "module:m_a", "PRESENT", "fresh-source-check")
assert spine.entity(seeded, "module:m_a")["maturity"] == "PRESENT"
def test_declared_but_unwired_capability(self, seeded):
"""Registered with no wiring evidence → must not read WIRED."""
spine.add_entity(seeded, id="capability:orphan_feature", kind="capability",
maturity="DECLARED", evidence_refs=["registry:orphan"])
assert spine.entity(seeded, "capability:orphan_feature")["maturity"] == "DECLARED"
# ── snapshots / deltas ────────────────────────────────────────────────────
class TestSnapshots:
def test_snapshot_deterministic(self, seeded, tmp_path, monkeypatch):
monkeypatch.setattr(spine, "SNAPSHOTS", tmp_path / "snaps")
monkeypatch.setattr(spine, "_deployed_observation", lambda: None)
seeded["generated_at"] = "FIXED"
p1 = spine.snapshot(seeded, "t")
p2 = spine.snapshot(seeded, "t")
assert p1.read_bytes() == p2.read_bytes() # byte-identical
def test_diff_categories(self, seeded):
old = json.loads(json.dumps(seeded))
spine.add_entity(seeded, id="module:m_new", kind="module", maturity="DECLARED")
spine.promote(seeded, "module:m_a", "WIRED", "new-import-evidence")
spine.add_relationship(seeded, type="depends_on", from_id="module:m_a",
to_id="module:m_b", evidence_refs=["ast"])
d = spine.diff(old, seeded)
assert d["entities_added"] == ["module:m_new"]
assert d["relationships_added"] == ["depends_on|module:m_a|module:m_b"]
assert {"id": "module:m_a", "from": "DECLARED", "to": "WIRED"} \
in d["maturity_changed"]
assert d["entities_removed"] == []
def test_diff_is_deterministic(self, seeded):
old = json.loads(json.dumps(seeded))
d1 = spine.diff(old, seeded)
d2 = spine.diff(old, seeded)
assert d1 == d2
# ── schema versioning ─────────────────────────────────────────────────────
class TestSchemaVersion:
def test_save_stamps_version(self, seeded, tmp_path):
p = spine.save(seeded, tmp_path / "s.json")
assert json.loads(p.read_text())["schema_version"] == spine.SCHEMA_VERSION
def test_future_version_refused_for_rewrite(self, seeded, tmp_path):
seeded["schema_version"] = 99
with pytest.raises(ValueError, match="schema_version"):
spine.save(seeded, tmp_path / "future.json")
def test_unknown_fields_of_document_survive(self, seeded, tmp_path):
seeded["a_field_spine_v2_will_understand"] = {"x": 1}
p = spine.save(seeded, tmp_path / "s.json")
# loader tolerates unknown document fields (no whitelist strip)
loaded = json.loads(p.read_text())
assert loaded["a_field_spine_v2_will_understand"] == {"x": 1}
# ── ingest / compatibility (umbrella migration) ───────────────────────────
class TestUmbrellaMigration:
def test_ingest_refuses_generated_view(self, tmp_path):
generated = {"_generated_by_spine": True, "umbrellas": {}}
p = tmp_path / "view.json"
p.write_text(json.dumps(generated))
with pytest.raises(ValueError, match="refusing to ingest"):
spine.ingest_umbrellas(spine.new_doc(), p)
def test_ingest_preserves_structure(self, tmp_path):
manifest = {"umbrellas": {
"alpha": {"description": "A", "modules": ["m_a", "m_b"],
"depends_on": ["beta"], "mirrors": ["shared/x.py"]},
"beta": {"description": "B", "modules": [], "depends_on": [], "mirrors": []}}}
p = tmp_path / "umbrellas.json"
p.write_text(json.dumps(manifest))
doc = spine.new_doc()
n = spine.ingest_umbrellas(doc, p)
assert n == 2
# ownership preserved
assert [r["to"] for r in spine.relationships(
doc, from_id="module:m_a", type="belongs_to")] == ["subsystem:alpha"]
# subsystem deps preserved
assert [r["to"] for r in spine.relationships(
doc, from_id="subsystem:alpha", type="depends_on")] == ["subsystem:beta"]
# mirrors preserved
assert [r["to"] for r in spine.relationships(
doc, from_id="subsystem:alpha", type="mirrors")] == ["file:shared/x.py"]
def test_export_reproduces_equivalent_view(self, tmp_path):
manifest = {"umbrellas": {
"alpha": {"description": "A", "modules": ["m_a"],
"depends_on": ["beta"], "mirrors": ["shared/x.py"]},
"beta": {"description": "B", "modules": ["m_b"],
"depends_on": [], "mirrors": []}}}
p = tmp_path / "umbrellas.json"
p.write_text(json.dumps(manifest))
doc = spine.new_doc()
spine.ingest_umbrellas(doc, p)
view = spine.export_umbrellas(doc)
assert view["_generated_by_spine"] is True
assert view["umbrellas"]["alpha"]["modules"] == ["m_a"]
assert view["umbrellas"]["alpha"]["depends_on"] == ["beta"]
assert view["umbrellas"]["alpha"]["mirrors"] == ["shared/x.py"]
assert view["umbrellas"]["beta"]["modules"] == ["m_b"]
# round-trip fidelity: the generated view re-ingests to the same graph
view_path = tmp_path / "view.json"
view_path.write_text(json.dumps(view))
doc2 = spine.new_doc()
# (direct ingest of the view is refused; equivalence is proven by
# comparing the exported view against the original manual truth)
assert view["umbrellas"] == manifest["umbrellas"]
def test_export_never_overwrites_manual_manifest(self, seeded, monkeypatch, tmp_path):
monkeypatch.setattr(spine, "UMBRELLA_MANIFEST", tmp_path / "manual.json")
(tmp_path / "manual.json").write_text(json.dumps({"umbrellas": {}}))
# main() with no path → refuses (manual manifest protection)
rc = spine.main(["export-umbrellas"])
assert rc == 1
# ── Scaffolding consumes Spine ────────────────────────────────────────────
class TestScaffoldingConsumesSpine:
def test_scaffold_projection_reads_spine_store(self, seeded, tmp_path, monkeypatch):
"""Scaffolding's structural facts must come from the Spine store,
not from re-deriving authorities independently."""
p = tmp_path / "current.json"
spine.save(seeded, p)
monkeypatch.setattr(spine, "CURRENT", p)
monkeypatch.setattr(spine, "ROOT", tmp_path)
monkeypatch.setattr(spine, "SRC_DIR", tmp_path / "src" / "rune")
(tmp_path / "src" / "rune").mkdir(parents=True, exist_ok=True)
(tmp_path / "src" / "rune" / "m_a.py").write_text("x = 1\n")
(tmp_path / "tests").mkdir(exist_ok=True)
monkeypatch.setattr(spine, "TESTS_DIR", tmp_path / "tests")
monkeypatch.setattr(spine, "_deployed_observation", lambda: None)
# fresh store → Scaffolding builds it deterministically
doc = spine.build()
spine.save(doc)
# a component card must be answerable from the store alone
card_deps = [r["to"] for r in spine.relationships(
doc, from_id="module:m_a", type="depends_on")]
subs = [r["to"] for r in spine.relationships(
doc, from_id="module:m_a", type="belongs_to")]
assert subs == ["subsystem:alpha"]
assert isinstance(card_deps, list)
# maturity visible to Scaffolding consumers — the fixture created
# src/rune/m_a.py, so the evidence gate correctly promotes PRESENT
assert spine.entity(doc, "module:m_a")["maturity"] == "PRESENT"
def test_scaffold_impact_uses_spine_store_not_umbrellas(self, monkeypatch, tmp_path):
"""The real integration: scripts/scaffold_projection.py resolves
ownership from the Spine store. Proven by pointing the store at a
fixture world and checking the card reflects SPINE data (and that
a Spine-only entity — absent from any umbrella file — is served)."""
import importlib
doc = spine.new_doc()
spine.add_entity(doc, id="subsystem:spine_test_world", kind="subsystem",
identities={"description": "fixture"})
spine.add_entity(doc, id="module:widget_core", kind="module", maturity="EXERCISED",
identities={"source": "src/rune/widget_core.py"},
evidence_refs=["fixture"])
spine.add_relationship(doc, type="belongs_to", from_id="module:widget_core",
to_id="subsystem:spine_test_world", evidence_refs=["fixture"])
spine.add_relationship(doc, type="consumed_by", from_id="module:widget_core",
to_id="module:widget_user", evidence_refs=["fixture"])
store = tmp_path / "current.json"
spine.save(doc, store)
monkeypatch.setattr(spine, "CURRENT", store)
import scripts.scaffold_projection as sp # noqa: E402
importlib.reload(sp)
monkeypatch.setattr(sp, "ROOT", tmp_path)
card = sp.component_card("widget_core", spine.load(store))
assert card["subsystem"] == "spine_test_world" # from Spine, not umbrellas.json
assert card["consumers"] == ["widget_user"] # from Spine relationships
assert card["spine_maturity"] == "EXERCISED" # evidence state surfaced
# ── graph separation + cross-linking (addendum 1) ─────────────────────────
class TestGraphSeparation:
def test_spine_queries_need_no_memory_infrastructure(self, seeded):
"""Structural lookup works on the Spine store alone — no Memory
fixture, no retrieval, no inference."""
q = spine.query(seeded, "module:m_a")
assert q["owner"] == ["subsystem:alpha"]
assert q["state"]["maturity"] == "DECLARED"
def test_stable_ids_survive_full_cycle(self, seeded, tmp_path):
p = spine.save(seeded, tmp_path / "s.json")
loaded = spine.load(p)
snap = tmp_path / "snap.json"
spine.save(loaded, snap)
d = spine.diff(spine.load(p), spine.load(snap))
assert d["entities_removed"] == [] and d["entities_added"] == []
assert spine.entity(spine.load(snap), "module:m_a") is not None
def test_spine_uri_cross_reference_without_authority_duplication(self, seeded):
"""A future Memory record references a Spine entity by URI — the
structural edge stays in Spine, the reference carries no authority."""
uri = spine.spine_uri("module:m_a")
assert uri == "spine://module/m_a"
assert spine.resolve_uri(uri) == "module:m_a"
# round-trip: resolve → the same entity Spine owns
assert spine.entity(seeded, spine.resolve_uri(uri))["kind"] == "module"
with pytest.raises(ValueError, match="not a spine URI"):
spine.resolve_uri("memory://lesson/42")
def test_memory_association_does_not_expand_frontier(self, seeded):
"""A hypothetical Memory-style association edge must NOT expand the
structural impact frontier (noisy impact = broken resolution)."""
spine.add_relationship(seeded, type="related_memory", from_id="module:m_a",
to_id="memory:old-incident-42", evidence_refs=["hypothetical"])
f = spine.impact_frontier(seeded, ["module:m_a"])
assert "memory:old-incident-42" not in f["level1_obligations"]
assert f["traversal_scope"] == "spine-structural-only"
# while a REAL structural edge does expand
spine.add_relationship(seeded, type="consumed_by", from_id="module:m_a",
to_id="module:m_b", evidence_refs=["ast"])
f2 = spine.impact_frontier(seeded, ["module:m_a"])
assert "module:m_b" in f2["level1_obligations"]
def test_unknown_relationship_is_obligation_bearing_fail_loud(self, seeded):
"""A previously unseen relationship type defaults to frontier
visibility — new structural relations deserve inspection until
evidence reclassifies them (data-driven semantics, open world)."""
spine.add_relationship(seeded, type="contextualises", from_id="module:m_a",
to_id="subsystem:beta", evidence_refs=["unseen-type"])
f = spine.impact_frontier(seeded, ["module:m_a"])
assert "subsystem:beta" in f["level1_obligations"]
def test_structural_facts_survive_hypothetical_memory_archive(self, seeded, tmp_path):
"""Spine retains current structural truth regardless of any future
Memory salience/decay/archive state — Spine is not Memory-dependent."""
spine.promote(seeded, "module:m_a", "WIRED", "import-evidence")
p = spine.save(seeded, tmp_path / "s.json")
# (hypothetical: Memory archives the story of how this was learned)
assert spine.entity(spine.load(p), "module:m_a")["maturity"] == "WIRED"
# ── contracts, task binding, frontier, predicted-vs-observed (T22) ────────
class TestContractsAndFrontier:
def _contract_world(self, doc):
spine.add_entity(doc, id="contract:chat_transport", kind="contract",
evidence_refs=["protocol:ChatTransport"], maturity="DECLARED")
spine.add_entity(doc, id="module:transport_a", kind="module", maturity="DECLARED")
spine.add_entity(doc, id="module:transport_b", kind="module", maturity="DECLARED")
spine.add_entity(doc, id="module:operator", kind="module", maturity="DECLARED")
spine.add_relationship(doc, type="implements", from_id="module:transport_a",
to_id="contract:chat_transport", evidence_refs=["ast"])
spine.add_relationship(doc, type="implements", from_id="module:transport_b",
to_id="contract:chat_transport", evidence_refs=["ast"])
spine.add_relationship(doc, type="consumes", from_id="module:operator",
to_id="contract:chat_transport", evidence_refs=["ast"])
return doc
def test_contract_change_expands_to_all_parties(self, seeded):
"""A CONTRACT change deserves every implementer + consumer's inspection."""
doc = self._contract_world(seeded)
f = spine.impact_frontier(doc, ["contract:chat_transport"])
assert {"module:transport_a", "module:transport_b", "module:operator"} \
<= set(f["level1_obligations"])
def test_implementation_change_is_bounded(self, seeded):
"""An IMPLEMENTATION change (one transport) touches the contract but
the frontier stays bounded — it does not pull sibling implementers
in as direct obligations (they see the contract, not this change)."""
doc = self._contract_world(seeded)
f = spine.impact_frontier(doc, ["module:transport_a"])
# HARDENED SEMANTICS (T1A): implementation change, contract preserved
# → contract is a direct obligation; siblings are CONTEXTUAL, never
# direct. (The pre-hardening expectation that siblings land in
# level1 encoded the wrong semantics — see final report.)
assert "contract:chat_transport" in f["level1_obligations"]
assert "module:transport_b" in f["contextual_not_obligations"]
assert "module:transport_b" not in f["level1_obligations"]
assert f["change_kind"] == "implementation_change"
assert f["level0_direct"] == ["module:transport_a"]
def test_task_binding_and_frontier(self, seeded):
doc = self._contract_world(seeded)
spine.bind_task(doc, "TASK-123", ["module:transport_a"], evidence_ref="issue")
assert spine.task_entities(doc, "TASK-123") == ["module:transport_a"]
seeds = spine.task_entities(doc, "TASK-123")
f = spine.impact_frontier(doc, seeds)
assert "contract:chat_transport" in f["level1_obligations"]
def test_predicted_vs_observed_flags_misses_as_candidates(self, seeded):
old = json.loads(json.dumps(seeded))
predicted = spine.impact_frontier(old, ["module:m_a"])
# the change reveals a consequence the structure didn't predict:
# m_b (a consumer nobody had recorded) starts consuming m_a
spine.add_relationship(seeded, type="consumed_by", from_id="module:m_a",
to_id="module:m_b", evidence_refs=["observed:real-run"])
r = spine.predicted_vs_observed(predicted, seeded, ["module:m_a"])
assert "module:m_b" in r["missed"]
assert r["candidate_corrections"][0]["status"] == "CANDIDATE"
assert "evidence required" in r["candidate_corrections"][0]["note"]
def test_structural_event_emission_is_generic(self, seeded):
spine.add_relationship(seeded, type="consumed_by", from_id="module:m_a",
to_id="module:m_b", evidence_refs=["ast"])
events = spine.structural_events(seeded)
kinds = {e["type"] for e in events}
assert "entity_observed" in kinds and "relationship_observed" in kinds
# dumb typed facts — no salience, no policy fields
rel_event = next(e for e in events if e["type"] == "relationship_observed"
and e["relationship"] == "consumed_by")
assert rel_event["from"] == "module:m_a" and rel_event["to"] == "module:m_b"
def test_evidence_conflict_drift(self, seeded):
e = spine.entity(seeded, "module:m_a")
e["maturity"] = "LIVE_PROVEN"
e["evidence_refs"] = [] # claim without proof
d = spine.drift(seeded)
assert any(x["class"] == "evidence_conflict" and x["entity"] == "module:m_a"
for x in d)
def test_intrinsic_query_answers_question_set_deterministically(self, seeded):
"""THE acceptance property: the representative question set answered
from the store alone — no LLM, no Memory, no rediscovery."""
doc = self._contract_world(seeded)
q = spine.query(doc, "module:transport_a")
assert q["kind"] == "module"
assert q["contracts_implements"] == ["contract:chat_transport"]
assert q["state"]["maturity"] == "DECLARED"
assert q["evidence"] == []
assert q["impact_frontier"]["level0_direct"] == ["module:transport_a"]
assert q["uri"] == "spine://module/transport_a"
def test_synthetic_future_capability_flows_through_frontier(self, seeded):
"""Extensibility end-to-end: the unknown capability registers,
round-trips, binds to a task, expands a frontier, and survives
delta — with zero Spine core changes (kind/relationship unseen)."""
spine.add_entity(seeded, id="capability:quantum_resonator_cache",
kind="quantum_resonator_cache", maturity="DECLARED",
identities={"resonance": "7.83Hz"},
evidence_refs=["synthetic"], ext={"wibble": 11})
spine.add_relationship(seeded, type="harmonizes_with",
from_id="capability:quantum_resonator_cache",
to_id="module:m_a", evidence_refs=["synthetic"])
spine.bind_task(seeded, "TASK-FUTURE", ["capability:quantum_resonator_cache"])
q = spine.query(seeded, "capability:quantum_resonator_cache")
assert q["kind"] == "quantum_resonator_cache" # unknown kind queried generically
assert q["state"]["maturity"] == "DECLARED"
f = spine.impact_frontier(seeded, spine.task_entities(seeded, "TASK-FUTURE"))
assert "module:m_a" in f["level1_obligations"] # unseen rel = obligation-bearing
# ── HARDENING T1: contract-change vs implementation-change semantics ──────
class TestHardeningContractSemantics:
def _world(self, seeded):
spine.add_entity(seeded, id="contract:chat_transport", kind="contract",
evidence_refs=["protocol"], maturity="DECLARED")
for m in ("transport_a", "transport_b"):
spine.add_entity(seeded, id=f"module:{m}", kind="module", maturity="DECLARED")
spine.add_relationship(seeded, type="implements", from_id=f"module:{m}",
to_id="contract:chat_transport", evidence_refs=["ast"])
spine.add_entity(seeded, id="module:operator", kind="module", maturity="DECLARED")
spine.add_relationship(seeded, type="consumes", from_id="module:operator",
to_id="contract:chat_transport", evidence_refs=["ast"])
return seeded
def test_A_implementation_change_siblings_not_direct(self, seeded):
doc = self._world(seeded)
f = spine.impact_frontier(doc, ["module:transport_a"])
assert f["change_kind"] == "implementation_change"
assert f["level0_direct"] == ["module:transport_a"]
assert "contract:chat_transport" in f["level1_obligations"]
assert "module:transport_b" in f["contextual_not_obligations"]
assert "module:transport_b" not in f["level1_obligations"]
# X (consumer) is reached through the contract's contextual parties
# or obligations per evidence — must NOT be silently direct here
assert "module:operator" in f["contextual_not_obligations"] or \
"module:operator" in f["level1_obligations"]
def test_B_contract_change_all_parties_direct(self, seeded):
doc = self._world(seeded)
f = spine.impact_frontier(doc, ["contract:chat_transport"])
assert f["change_kind"] == "contract_change"
for party in ("module:transport_a", "module:transport_b", "module:operator"):
assert party in f["level1_obligations"], party
def test_C_contract_violation_escalates(self, seeded):
doc = self._world(seeded)
f = spine.impact_frontier(doc, ["module:transport_a"],
change_kind="contract_violation")
# verification proved the implementation breaks the contract:
# every party becomes a direct obligation
assert f["change_kind"] == "contract_violation"
for party in ("module:transport_b", "module:operator"):
assert party in f["level1_obligations"], party
def test_kind_inference_is_deterministic(self, seeded):
doc = self._world(seeded)
assert spine.impact_frontier(doc, ["contract:chat_transport"])["change_kind"] == "contract_change"
assert spine.impact_frontier(doc, ["module:transport_a"])["change_kind"] == "implementation_change"
# ── HARDENING T3/T4: projector ownership, reconciliation, state semantics ─
class TestHardeningReconciliation:
def _fact(self, doc, type="depends_on", frm="module:x", to="module:y", auth="proj-x"):
spine.add_entity(doc, id=frm, kind="module", maturity="DECLARED")
spine.add_entity(doc, id=to, kind="module", maturity="DECLARED")
r = spine.add_relationship(doc, type=type, from_id=frm, to_id=to,
evidence_refs=["fixture"])
r["authority"] = auth
r["status"] = "CURRENT"
return r
def test_foreign_projector_refresh_never_deletes_other_authority_facts(self, seeded):
"""Projector Y's refresh must not touch projector X's facts —
the reconciliation boundary is AUTHORITY OWNERSHIP."""
doc = seeded
self._fact(doc, auth="proj-x")
foreign = spine.add_relationship(doc, type="related_thing", from_id="module:x",
to_id="module:y", evidence_refs=["fixture"])
spine._authority_observed(doc, foreign, "proj-y") # proj-y ran and owns it
# proj-x refresh observes its own fact; reconcile must leave proj-y's
# fact alone — only proj-y's own pass can stale it
spine._doc_authorities(doc).setdefault("proj-x", {"generation": 1, "observed": ["depends_on|module:x|module:y"]})
staled = spine.reconcile_authorities(doc)
assert foreign["status"] == "CURRENT" # foreign fact survives
assert all(s["authority"] != "proj-y" for s in staled)
def test_owner_stopping_emission_stales_not_deletes(self, seeded):
"""Projector X later stops observing its fact → STALE (marked,
reported in drift, excluded from frontier) — not silently deleted,
not silently current."""
doc = seeded
self._fact(doc, auth="proj-x")
spine._doc_authorities(doc)["proj-x"] = {"generation": 2, "observed": []}
staled = spine.reconcile_authorities(doc)
assert len(staled) == 1
f = spine.impact_frontier(doc, ["module:x"])
assert "module:y" not in f["level1_obligations"] # stale ≠ current truth
d = spine.drift(doc)
assert any(x["class"] == "stale_fact" for x in d)
def test_projector_failure_does_not_masquerade_as_fresh(self, seeded):
doc = seeded
self._fact(doc, auth="proj-x")
spine._doc_authorities(doc)["proj-x"] = {"generation": 1, "observed": ["depends_on|module:x|module:y"]}
spine.authority_failed(doc, "proj-x", "source tree unreachable")
h = spine.authority_health(doc)
assert h["proj-x"]["status"] == "DEGRADED"
r = [r for r in doc["relationships"] if r.get("authority") == "proj-x"][0]
assert r["status"] == "STALE"
f = spine.impact_frontier(doc, ["module:x"])
assert "module:y" not in f["level1_obligations"]
assert any(o["kind"] == "authority_degraded" for o in doc["observations"])
def test_manual_fact_without_authority_survives(self, seeded):
doc = seeded
r = self._fact(doc, auth=None)
r.pop("authority", None); r.pop("status", None)
spine.reconcile_authorities(doc)
assert r["status"] != "STALE" if "status" in r else True
assert r in doc["relationships"]
def test_two_authorities_conflicting_preserve_both(self, seeded):
spine.mark_conflict(seeded, "module:m_a", "registry", "exists",
"runtime", "unavailable", "evidence:live-check")
e = spine.entity(seeded, "module:m_a")
assert e["status"] == "CONFLICTING"
assert len(e["ext"]["conflicts"]) == 1 # BOTH preserved, not last-wins
assert spine.resolve_status(e) == "CONFLICTING"
q = spine.query(seeded, "module:m_a")
assert q["state"]["resolved_status"] == "CONFLICTING"
def test_conflict_requires_evidence(self, seeded):
with pytest.raises(ValueError, match="requires evidence"):
spine.mark_conflict(seeded, "module:m_a", "a", "x", "b", "y", "")
def test_unknown_is_not_healthy(self, seeded):
"""A never-observed entity is UNKNOWN — not current, not false."""
spine.add_entity(seeded, id="module:never_checked", kind="module",
maturity="DECLARED")
assert spine.resolve_status(spine.entity(seeded, "module:never_checked")) == "UNKNOWN"
def test_live_proven_without_evidence_is_conflict_not_stale(self, seeded):
"""Case A vs B distinction: no evidence at all = CONFLICTING claim;
a projector that stopped refreshing = STALE. Different conditions."""
spine.add_entity(seeded, id="module:no_proof", kind="module",
maturity="LIVE_PROVEN") # zero evidence refs
assert spine.resolve_status(spine.entity(seeded, "module:no_proof")) == "CONFLICTING"
# ── HARDENING T5: durable identity — rename/alias/supersession ────────────
class TestHardeningDurableIdentity:
def test_rename_old_spine_reference_stays_meaningful(self, seeded, tmp_path):
"""Memory stores spine://module/memory_selector; the module is later
renamed memory_orchestrator. The old reference must still resolve."""
spine.alias(seeded, "module:m_a", "module:m_a_old_name")
p = spine.save(seeded, tmp_path / "s.json")
reloaded = spine.load(p)
# old URI resolves to the same conceptual entity
old_ref = spine.resolve_uri("spine://module/m_a_old_name")
e = spine.entity(reloaded, old_ref)
assert e is not None and e["id"] == "module:m_a"
# survives another build cycle (aliases are data, carried forward)
doc2 = spine.build.__wrapped__(reloaded) if hasattr(spine.build, "__wrapped__") else reloaded
assert spine.entity(doc2, "module:m_a_old_name") is not None
def test_supersession_requires_evidence_and_preserves_history(self, seeded):
spine.add_entity(seeded, id="module:new_thing", kind="module", maturity="DECLARED")
with pytest.raises(ValueError, match="requires evidence"):
spine.supersede(seeded, "module:new_thing", "module:m_a", "")
spine.supersede(seeded, "module:new_thing", "module:m_a", "evidence:decision-record")
old = spine.entity(seeded, "module:m_a")
assert old is not None # never deleted
assert old["superseded_by"] == "module:new_thing"
assert old["status"] == "SUPERSEDED"
# the supersedes relationship is data, round-trips, and is
# non-obligation for frontier purposes (context, not live wiring)
p = spine.save(seeded, Path(tempfile.mkdtemp()) / "s.json")
assert spine.entity(spine.load(p), "module:m_a")["superseded_by"] == "module:new_thing"
def test_superseded_entity_not_treated_as_current(self, seeded):
spine.add_entity(seeded, id="module:new_thing", kind="module", maturity="DECLARED")
spine.supersede(seeded, "module:new_thing", "module:m_a", "evidence:decision")
f = spine.impact_frontier(seeded, ["module:m_a"])
# a superseded seed is still answerable, but its status is explicit
assert spine.resolve_status(spine.entity(seeded, "module:m_a")) == "SUPERSEDED"
# ── HARDENING T2: independent observed impact ─────────────────────────────
class TestHardeningObservedImpact:
def test_observed_impact_comes_from_evidence_not_frontier_rerun(self, seeded):
"""The observed side must be built from EXTERNAL evidence items —
test failures, canary results, runtime errors — each naming its
authority. The frontier function is not invoked for the observed set."""
spine.add_entity(seeded, id="module:m_c", kind="module", maturity="DECLARED")
ev = [{"entity": "module:m_b", "source": "pytest-failure",
"authority": "test-suite", "detail": "test_consumer_lookup failed"},
{"entity": "module:m_c", "source": "canary", "authority": "canary-runner",
"detail": "canary_native red"}]
r = spine.record_observed_impact(seeded, "TASK-X", ev)
assert r["observed_entities"] == ["module:m_b", "module:m_c"]
kinds = [o["kind"] for o in seeded["observations"]]
assert kinds.count("observed_consequence") == 2
# nothing was auto-promoted into structural relationships
assert not spine.relationships(seeded, type="consumed_by",
from_id="module:m_a", to_id="module:m_c")
def test_predicted_vs_observed_with_independent_evidence(self, seeded):
old = json.loads(json.dumps(seeded))
predicted = spine.impact_frontier(old, ["module:m_a"])
# the change ran; independent evidence implicates an entity the
# structure never predicted
spine.record_observed_impact(seeded, "TASK-X", [
{"entity": "module:m_b", "source": "runtime-error",
"authority": "deployed-runtime", "detail": "import crash"}])
# compare: prediction's frontier vs the EVIDENCE-derived set
observed_set = {"module:m_b"}
pred_set = {e for k in ("level0_direct", "level1_obligations",
"contracts", "level2_verification")
for e in predicted.get(k, [])}
missed = observed_set - pred_set
assert missed == {"module:m_b"}
# and the comparison helper records it as CANDIDATE, not truth
result = spine.predicted_vs_observed(predicted, seeded, ["module:m_a"])
assert all(c["status"] == "CANDIDATE" for c in result["candidate_corrections"])
# ── HARDENING: candidate relationships + event seam (T8) ──────────────────
class TestHardeningCandidatesAndEvents:
def test_model_speculation_is_candidate_never_truth(self, seeded):
"""A model-hypothesised relationship (no evidence) enters as
CANDIDATE: representable, queryable, but NOT structural truth —
excluded from impact frontiers until evidence promotes it."""
spine.add_relationship(seeded, type="depends_on", from_id="module:m_a",
to_id="module:m_b", evidence_refs=[]) # speculation
rel = spine.relationships(seeded, from_id="module:m_a", type="depends_on")[0]
assert rel["status"] == "CANDIDATE"
f = spine.impact_frontier(seeded, ["module:m_a"])
assert "module:m_b" not in f["level1_obligations"]
# evidence arrives → promotion to CURRENT makes it real
rel["evidence_refs"] = ["ast-import:m_a"]
rel["status"] = "CURRENT"
f2 = spine.impact_frontier(seeded, ["module:m_a"])
assert "module:m_b" in f2["level1_obligations"]
def test_event_seam_carries_future_event_kinds_without_core_redesign(self, seeded):
"""The seam must transport stale/conflict/supersession/degradation
events as typed facts — future event kinds flow without policy."""
spine.add_entity(seeded, id="module:new_thing", kind="module", maturity="DECLARED")
spine.supersede(seeded, "module:new_thing", "module:m_a", "evidence:decision")
spine.mark_conflict(seeded, "module:new_thing", "registry", "exists",
"runtime", "unavailable", "evidence:check")
spine._authority_observed(seeded, None, "proj-x")
spine.authority_failed(seeded, "proj-x", "boom")
events = spine.structural_events(seeded)
kinds = {e["type"] for e in events}
assert {"superseded", "authority_conflict", "authority_degraded"} <= kinds
# all dumb typed facts: no salience/policy/wake fields anywhere
for e in events:
assert not {"salience", "attention", "wake", "priority"} & set(e.keys())
def test_intrinsic_query_on_real_store_is_fast_and_deterministic(self):
"""T6: the self-knowledge property on the REAL store — one query,
deterministic, no LLM/memory/rebuild. And fast (bounded lookup)."""
doc = spine.load()
if doc is None:
pytest.skip("no spine store in this checkout")
import time as _t
t0 = _t.monotonic()
q1 = spine.query(doc, "module:rune_operator")
q2 = spine.query(doc, "module:rune_operator")
dt = _t.monotonic() - t0
assert q1 == q2 # deterministic
assert q1["owner"] and q1["state"]["maturity"]
assert "impact_frontier" in q1
assert dt < 2.0, f"query took {dt:.2f}s — intrinsic property lost"
# ── CLOSURE 1: durable identity through the REAL build path ───────────────
class TestClosureRealBuildDurability:
"""The hardening pass tested alias/supersession around save/load with a
build-path fallback that could mock the real refresh. Memory will depend
on spine:// references — prove durability through the ACTUAL build."""
def _seeded_store(self, tmp_path):
doc = spine.new_doc()
spine.add_entity(doc, id="subsystem:memory", kind="subsystem",
identities={"description": "fixture"}, maturity="DECLARED")
for m in ("memory_selector",):
spine.add_entity(doc, id=f"module:{m}", kind="module", maturity="DECLARED",
identities={"source": f"src/rune/{m}.py"})
spine.add_relationship(doc, type="belongs_to", from_id=f"module:{m}",
to_id="subsystem:memory", evidence_refs=["fixture"])
spine.save(doc, spine.CURRENT)
return doc
def test_alias_survives_real_build_refresh(self, tmp_path, monkeypatch):
"""create A → alias A_old → save → reload → REAL build() → save →
reload → spine://.../A_old still resolves to A. No mocked path."""
monkeypatch.setattr(spine, "STORE_DIR", tmp_path / "store")
monkeypatch.setattr(spine, "CURRENT", tmp_path / "store" / "current.json")
monkeypatch.setattr(spine, "SNAPSHOTS", tmp_path / "store" / "snaps")
monkeypatch.setattr(spine, "_deployed_observation", lambda: None)
monkeypatch.setattr(spine, "SRC_DIR", tmp_path / "src" / "rune")
(tmp_path / "src" / "rune").mkdir(parents=True)
(tmp_path / "src" / "rune" / "memory_selector.py").write_text("x = 1\n")
monkeypatch.setattr(spine, "TESTS_DIR", tmp_path / "tests")
(tmp_path / "tests").mkdir(exist_ok=True)
monkeypatch.setattr(spine, "UMBRELLA_MANIFEST", tmp_path / "no-manifest.json")
self._seeded_store(tmp_path)
doc = spine.load()
spine.alias(doc, "module:memory_selector", "module:mem_sel_old")
spine.save(doc)
# THE REAL PATH: spine.build() (loads the persisted store, carries
# everything forward, re-derives module facts, reconciles, saves)
rebuilt = spine.build()
spine.save(rebuilt)
reloaded = spine.load()
old_ref = spine.resolve_uri("spine://module/mem_sel_old")
e = spine.entity(reloaded, old_ref)
assert e is not None, "alias lost by real build"
assert e["id"] == "module:memory_selector"
assert "module:mem_sel_old" in e.get("aliases", [])
def test_supersession_survives_real_build_refresh(self, tmp_path, monkeypatch):
"""B supersedes A → REAL build() → superseded_by intact, historical
entity not silently deleted, old reference resolves meaningfully."""
monkeypatch.setattr(spine, "STORE_DIR", tmp_path / "store")
monkeypatch.setattr(spine, "CURRENT", tmp_path / "store" / "current.json")
monkeypatch.setattr(spine, "SNAPSHOTS", tmp_path / "store" / "snaps")
monkeypatch.setattr(spine, "_deployed_observation", lambda: None)
monkeypatch.setattr(spine, "SRC_DIR", tmp_path / "src" / "rune")
(tmp_path / "src" / "rune").mkdir(parents=True)
(tmp_path / "src" / "rune" / "memory_selector.py").write_text("x = 1\n")
monkeypatch.setattr(spine, "TESTS_DIR", tmp_path / "tests")
(tmp_path / "tests").mkdir(exist_ok=True)
monkeypatch.setattr(spine, "UMBRELLA_MANIFEST", tmp_path / "no-manifest.json")
self._seeded_store(tmp_path)
doc = spine.load()
spine.add_entity(doc, id="module:memory_orchestrator", kind="module",
maturity="DECLARED")
spine.supersede(doc, "module:memory_orchestrator", "module:memory_selector",
"evidence:closure-decision")
spine.save(doc)
rebuilt = spine.build()
spine.save(rebuilt)
reloaded = spine.load()
old = spine.entity(reloaded, "module:memory_selector")
assert old is not None, "superseded entity deleted by real build"
assert old["superseded_by"] == "module:memory_orchestrator"
assert old["status"] == "SUPERSEDED"
# the supersedes edge survives as data (non-obligation context)
assert spine.relationships(reloaded, type="supersedes",
from_id="module:memory_orchestrator",
to_id="module:memory_selector")
# ── CLOSURE 2+3: no competing structural authority for RUNE ──────────────
class TestClosureNoCompetingAuthority:
def test_dependency_tracker_scope_is_harness_not_rune(self):
"""dependency_tracker's graph describes ~/.config/opencode/scripts
(the harness), NOT Rune modules. The name collisions with src/rune
are coincidental. This test pins the separation so the harness map
can never silently become a second Rune structural authority.
CI-safe: asserts the CLASSIFICATION (resolution root is the harness
dir; the map is not derived from Spine), never harness filesystem
state — the CI runner has no ~/.config/opencode."""
import inspect
from rune import dependency_tracker as dt
assert "opencode" in dt.SCRIPTS_DIR, "tracker scope moved — re-classify"
# resolution root is the harness dir, by construction: propagate()
# checks os.path.exists against SCRIPTS_DIR, not src/rune
prop_src = inspect.getsource(dt.propagate)
assert "SCRIPTS_DIR" in prop_src and "os.path.join(SCRIPTS_DIR" in prop_src
# the map is a locally-owned table, NOT derived from the Spine store
# (check IMPORTS, not prose — the module docstring legitimately
# mentions Spine when documenting its scope classification)
import ast as _ast
tree = _ast.parse(inspect.getsource(dt))
imported = set()
for node in _ast.walk(tree):
if isinstance(node, _ast.Import):
imported.update(a.name for a in node.names)
elif isinstance(node, _ast.ImportFrom) and node.module:
imported.add(node.module)
assert not any("spine" in m for m in imported), \
f"tracker now imports Spine — re-classify as a consumer: {imported}"
# and Spine remains the authority for Rune structure
assert (spine.SRC_DIR / "spine.py").is_file()