"""test_construction_interface.py — SCAFFOLD-TRANCHE-007 test plans §29 (interface core), §30 (authority), §31 (pattern precision — integration), §17 (provider independence).""" import json import os import subprocess import sys from pathlib import Path import pytest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "src")) from rune import construction_interface as ci # noqa: E402 from rune import structural_store as ss # noqa: E402 from rune import scaffold as sc # noqa: E402 ROOT = os.path.join(os.path.dirname(__file__), "..") def _fixture_authorities(): """A self-contained project-scaffold authority (external-project mode without any real external repo — §16).""" spine = ss.new_doc() ss.add_entity( spine, id="capability:exporter", kind="capability", identities={}, maturity="WIRED", evidence_refs=["f"] ) ss.add_entity(spine, id="contract:csv_export", kind="contract", identities={}, evidence_refs=["f"]) ss.add_relationship( spine, type="implements", from_id="capability:exporter", to_id="contract:csv_export", evidence_refs=["f"] ) return spine def _iface(tmp_path, builder="test-builder", with_authority=True): store = str(tmp_path / ".rune" / "scaffold") iface = ci.ConstructionInterface(builder=builder, project_store=store, project_id="fixture-proj") if with_authority: # inject the fixture authority INTO the fixture scaffold store so # external-project mode has structural truth to consult iface.scaffold.init(purpose="fixture") doc = iface.scaffold.load() for e in _fixture_authorities()["entities"]: doc["entities"].append(json.loads(json.dumps(e))) for r in _fixture_authorities()["relationships"]: doc["relationships"].append(json.loads(json.dumps(r))) iface.scaffold.save(doc) return iface def _submit(iface, **kw): payload = dict( objective="persistent project export", constraints={"contracts": ["contract:csv_export"]}, affected_surface=[], evidence_refs=["x"], approval_context="covered by fixture authority", ) payload.update(kw) return iface.submit_need(**payload) # ── §29 interface core ────────────────────────────────────────────────────── def test_29a_submit_need(tmp_path): iface = _iface(tmp_path) env = _submit(iface) assert env["schema"] == ci.INTERFACE_SCHEMA_VERSION assert env["operation"] == "submit_need" assert env["success"] assert env["ids"]["need_id"] assert env["state"]["resolution"] == "REUSE" assert env["state"]["builder"] == "test-builder" def test_29b_retrieve_decision(tmp_path): iface = _iface(tmp_path) env = _submit(iface) cid = env["ids"]["contract_id"] d = iface.inspect_decision(cid) assert d["success"] assert d["state"]["resolution"] == "REUSE" assert d["state"]["toolchain"]["selected_language"] == "python" assert any(f["candidate"] == "capability:exporter" for f in d["state"]["fits"]) def test_29c_retrieve_contract(tmp_path): iface = _iface(tmp_path) cid = _submit(iface)["ids"]["contract_id"] r = iface.resume(cid) assert r["success"] assert r["state"]["phase"] == "draft" assert r["state"]["need"]["objective"] == "persistent project export" def test_29d_allowed_scope(tmp_path): iface = _iface(tmp_path) cid = _submit(iface)["ids"]["contract_id"] s = iface.get_scope(cid) assert s["success"] assert "allowed_paths" in s["state"] assert "affected_structural_entities" in s["state"] assert "unresolved_surfaces" in s["state"] assert "layout_obligations" in s["state"] def test_29e_obligations(tmp_path): iface = _iface(tmp_path) cid = _submit(iface)["ids"]["contract_id"] o = iface.get_obligations(cid) assert o["success"] assert o["state"]["obligations"] provs = {x["provenance"] for x in o["state"]["obligations"]} assert provs <= {"STRUCTURAL", "PATTERN", "LAYOUT_CONTRACT", "CONTRACT"} def test_29f_report_observation(tmp_path): iface = _iface(tmp_path) cid = _submit(iface)["ids"]["contract_id"] r = iface.report_observation(cid, [{"entity": "capability:exporter", "detail": "exercised by new test"}]) assert r["success"] assert r["state"]["recorded"] == 1 assert "cannot self-certify" not in r["state"]["note"] assert "determined by Scaffolding gates" in r["state"]["note"] def test_29g_verification_state(tmp_path): iface = _iface(tmp_path) cid = _submit(iface)["ids"]["contract_id"] v = iface.verify(cid, changed_files=["src/new_thing.py"]) assert v["success"] or v["errors"] assert "scope_check" in v["state"] or v["errors"] def test_29h_resume_fresh_process(tmp_path): """§11 THE MAJOR ACCEPTANCE CONDITION: a fresh builder process resumes from contract id alone.""" iface = _iface(tmp_path, builder="first-builder") env = iface.submit_need( "persistent project export", constraints={"contracts": ["contract:csv_export"]}, affected_surface=["src/export_module.py"], evidence_refs=["x"], approval_context="covered by fixture authority", ) cid = env["ids"]["contract_id"] iface.transition(cid, "approved") script = f""" import sys, json sys.path.insert(0, {os.path.join(ROOT, "src")!r}) from rune import construction_interface as ci iface = ci.ConstructionInterface(builder="fresh-builder", project_store={str(tmp_path / ".rune" / "scaffold")!r}, project_id="fixture-proj") env = iface.resume({cid!r}) print(json.dumps(env)) """ r = subprocess.run([sys.executable, "-c", script], capture_output=True, text=True, timeout=60) assert r.returncode == 0, r.stderr env = json.loads(r.stdout) assert env["success"] st = env["state"] assert st["need"]["objective"] == "persistent project export" assert st["decision"]["resolution"] == "REUSE" assert st["phase"] == "approved" assert st["scope"] assert st["obligations"] assert st["next_action"] assert st["builder"] == "fresh-builder" # this session's identity def test_29i_json_roundtrip(tmp_path): iface = _iface(tmp_path) env = _submit(iface) blob = json.dumps(env) back = json.loads(blob) assert back["operation"] == env["operation"] assert back["state"]["resolution"] == env["state"]["resolution"] def test_29j_unknown_contract(tmp_path): iface = _iface(tmp_path) for op in ( lambda: iface.inspect_decision("nope"), lambda: iface.get_scope("nope"), lambda: iface.get_obligations("nope"), lambda: iface.resume("nope"), ): env = op() assert not env["success"] assert env["errors"][0]["error"] == ci.Errors.UNKNOWN_CONTRACT def test_29k_approval_required(tmp_path): iface = _iface(tmp_path) env = iface.submit_need( "build a whole new application from scratch", constraints={}, affected_surface=[], evidence_refs=["x"], approval_context="", ) # no approval context # new-capability construction without approval context → gate fires if env["state"]["approval"]["required"]: assert env["errors"] assert any(e["error"] == ci.Errors.APPROVAL_REQUIRED for e in env["errors"]) else: # covered path must say so assert env["state"]["approval"]["covered_by"] or not env["state"]["approval"]["reasons"] def test_29l_scope_violation_refused(tmp_path): iface = _iface(tmp_path) env = iface.submit_need( "persistent project export", constraints={"contracts": ["contract:csv_export"]}, affected_surface=["src/export_module.py"], # scoped surface evidence_refs=["x"], approval_context="covered by fixture authority", ) cid = env["ids"]["contract_id"] iface.transition(cid, "approved") iface.transition(cid, "building") iface.transition(cid, "verifying") v = iface.verify(cid, changed_files=["src/completely/unrelated.py"]) # out-of-scope change must surface as a violation, never green assert v["state"]["scope_check"]["verdict"] == "red" or any( e["error"] == ci.Errors.SCOPE_VIOLATION for e in v["errors"] ) def test_29m_failed_verification_cannot_close(tmp_path): iface = _iface(tmp_path) cid = _submit(iface)["ids"]["contract_id"] # contract is in draft — closure must be refused by the phase map env = iface.close(cid, observed_evidence=[{"entity": "capability:exporter", "detail": "claimed done"}]) assert not env["success"] assert env["errors"][0]["error"] == ci.Errors.VERIFICATION_FAILED def test_29n_stale_state_store_write(tmp_path): """STORE_WRITE_FAILED: an unwritable store surfaces as an explicit error, not a silent lie.""" iface = _iface(tmp_path) # break the store path iface.scaffold.current = "/proc/nonexistent/current.json" env = iface.report_observation("any", [{"entity": "x"}]) assert not env["success"] or env["errors"] # ── §30 authority ──────────────────────────────────────────────────────────── def test_30a_rune_mode_reads_rune_authority(): """Rune-internal mode consults the real Spine store (read-only).""" iface = ci.ConstructionInterface(builder="t") auth = iface._authorities() assert "rune_spine" in auth assert iface.mode == "rune_internal" def test_30b_external_mode_reads_project_scaffold(tmp_path): iface = _iface(tmp_path) auth = iface._authorities() assert "rune_spine" not in auth # external project has no Rune Spine assert iface.mode == "external_project" assert auth["project_scaffold"]["entities"] def test_30c_builder_cannot_rewrite_structural_authority(): """The interface exposes NO operation that writes structural truth. (The only writes are contract/observation/session records in the scaffold store — never Spine entities.)""" public = [m for m in dir(ci.ConstructionInterface) if not m.startswith("_")] for forbidden in ("rewrite_spine", "set_entity", "promote", "supersede", "build_spine", "add_relationship"): assert forbidden not in public def test_30d_builder_cannot_override_user_locked(tmp_path): iface = _iface(tmp_path) from rune import layout_contract as lc doc = iface.scaffold.load() lc.define_region(doc, "footer-bar", provenance="scaffold") lc.bind_component(doc, "version_display", "footer-bar", lock=True, provenance="user", order=0) iface.scaffold.save(doc) # no interface operation amends layout at all public = [m for m in dir(ci.ConstructionInterface) if not m.startswith("_")] assert not any("layout" in m and "amend" in m for m in public) # and the direct amend path still refuses non-user authority doc2 = iface.scaffold.load() with pytest.raises(ValueError): lc.amend_layout_contract( doc2, "version_display", new_region="header", authorized_by="builder", reason="prefer it" ) def test_30e_builder_cannot_self_certify(tmp_path): iface = _iface(tmp_path) cid = _submit(iface)["ids"]["contract_id"] # no interface operation takes "done=True" v = iface.verify(cid) assert "cannot self-certify" in v["state"]["remaining"] # closure from draft fails env = iface.close(cid, observed_evidence=[{"entity": "x"}]) assert not env["success"] def test_30f_builder_identity_neutral(tmp_path): """§17: two builders with identical input get identical construction behavior (identity recorded, semantics unchanged).""" results = [] for b in ("mimo", "kimi", "deterministic-script"): iface = _iface(tmp_path / b, builder=b) env = _submit(iface) results.append( ( env["state"]["resolution"], env["state"]["completeness"], env["state"]["toolchain"] if "toolchain" in env["state"] else None, [o["id"] for o in iface.get_obligations(env["ids"]["contract_id"])]["obligations"] if False else None, ) ) resolutions = {r[0] for r in results} completions = {r[1] for r in results} assert len(resolutions) == 1 and len(completions) == 1 # ── §31 pattern precision (integration through the interface) ─────────────── def test_31a_ui_task_derives_ui_obligations(tmp_path): iface = _iface(tmp_path) from rune import layout_contract as lc doc = iface.scaffold.load() lc.define_region(doc, "footer-bar", provenance="scaffold") lc.bind_component(doc, "version_display", "footer-bar", provenance="scaffold") iface.scaffold.save(doc) env = iface.submit_need( "adjust the tui version widget", constraints={}, affected_surface=["ui:version_display"], evidence_refs=["x"], approval_context="covered", ) cid = env["ids"]["contract_id"] o = iface.get_obligations(cid) ids = {x["id"] for x in o["state"]["obligations"]} assert any("ui-" in i or "layout:" in i for i in ids) def test_31b_non_ui_task_no_active_ui_obligations(tmp_path): """§0 regression through the interface: non-UI work gets NO active ui-* obligations.""" iface = _iface(tmp_path) env = _submit(iface) cid = env["ids"]["contract_id"] o = iface.get_obligations(cid) ui_active = [x for x in o["state"]["obligations"] if x["id"].startswith("ui-")] assert ui_active == [] def test_31c_release_task_derives_release_obligations(tmp_path): iface = _iface(tmp_path) # the fixture authority needs the deploy structural truth for fit doc = iface.scaffold.load() ss.add_entity( doc, id="module:deploy_stage", kind="module", identities={"path": "scripts/deploy_stage.py"}, maturity="WIRED", evidence_refs=["f"], ) ss.add_entity(doc, id="contract:monotonic_promotion", kind="contract", identities={}, evidence_refs=["f"]) ss.add_relationship( doc, type="implements", from_id="module:deploy_stage", to_id="contract:monotonic_promotion", evidence_refs=["f"] ) iface.scaffold.save(doc) env = iface.submit_need( "repair the deploy promotion ordering", constraints={"contracts": ["contract:monotonic_promotion"]}, affected_surface=["scripts/deploy_stage.py", "scripts/deploy_promotion.py"], evidence_refs=["x"], approval_context="covered", ) cid = env["ids"]["contract_id"] o = iface.get_obligations(cid) ids = {x["id"] for x in o["state"]["obligations"]} assert "rel-monotonic-promotion" in ids or any("rel-" in i for i in ids) def test_31d_non_release_task_no_promotion_obligations(tmp_path): iface = _iface(tmp_path) env = _submit(iface) cid = env["ids"]["contract_id"] o = iface.get_obligations(cid) rel_active = [x for x in o["state"]["obligations"] if x["id"].startswith("rel-")] assert rel_active == [] def test_31g_partial_pattern_inspectable_without_activation(tmp_path): iface = _iface(tmp_path) env = iface.submit_need( "adjust the tui backlog plumbing", constraints={"contracts": ["contract:csv_export"]}, affected_surface=["src/rune/tui_backlog.py", "src/export_module.py"], evidence_refs=["x"], approval_context="covered", ) cid = env["ids"]["contract_id"] d = iface.inspect_decision(cid) considered = {a["pattern"]: a["verdict"] for a in d["state"]["patterns_considered"]} # PARTIAL patterns remain VISIBLE as candidates (inspectable) assert considered # but their UI obligations did not enter the ACTIVE obligation set o = iface.get_obligations(cid) ui_active = [x for x in o["state"]["obligations"] if x["id"].startswith("ui-")] assert ui_active == [] # ── CLI transport ──────────────────────────────────────────────────────────── def test_cli_roundtrip(tmp_path): store = tmp_path / ".rune" / "scaffold" iface = ci.ConstructionInterface(builder="seed", project_store=str(store), project_id="cli-fixture") iface.scaffold.init(purpose="cli") doc = iface.scaffold.load() for e in _fixture_authorities()["entities"]: doc["entities"].append(json.loads(json.dumps(e))) for r in _fixture_authorities()["relationships"]: doc["relationships"].append(json.loads(json.dumps(r))) iface.scaffold.save(doc) env = { "objective": "persistent project export", "constraints": {"contracts": ["contract:csv_export"]}, "affected_surface": [], "evidence_refs": ["x"], "approval_context": "covered", } r = subprocess.run( [ sys.executable, "-m", "rune.construction_interface", "submit-need", json.dumps(env), "--builder", "cli-builder", "--project-store", str(store), "--project-id", "cli-fixture", ], capture_output=True, text=True, timeout=120, env={**os.environ, "PYTHONPATH": os.path.join(ROOT, "src")}, ) assert r.returncode == 0, r.stderr[-400:] out = json.loads(r.stdout[r.stdout.index("{") :]) assert out["success"] assert out["state"]["resolution"] == "REUSE" # resume through the CLI from the returned contract id r2 = subprocess.run( [ sys.executable, "-m", "rune.construction_interface", "resume", out["ids"]["contract_id"], "--builder", "cli-2", "--project-store", str(store), "--project-id", "cli-fixture", ], capture_output=True, text=True, timeout=120, env={**os.environ, "PYTHONPATH": os.path.join(ROOT, "src")}, ) assert r2.returncode == 0, r2.stderr[-400:] out2 = json.loads(r2.stdout[r2.stdout.index("{") :]) assert out2["state"]["need"]["objective"] == "persistent project export" # ── §28 capabilities / schema negotiation (SCAFFOLD-TRANCHE-008) ──────────── def test_capabilities_operation(tmp_path): """Builders can detect the supported interface schema + operations BEFORE calling anything (T7 §28 requirement, closed by this tranche).""" iface = _iface(tmp_path) env = iface.capabilities() assert env["success"] st = env["state"] assert st["schema_version"] == ci.INTERFACE_SCHEMA_VERSION for op in ( "submit_need", "inspect_decision", "get_scope", "get_obligations", "report_observation", "verify", "transition", "close", "resume", "capabilities", ): assert op in st["operations"] assert ci.Errors.SCOPE_VIOLATION in st["error_states"] assert ci.Errors.UNKNOWN_CONTRACT in st["error_states"] # mode + project identity exposed for builder routing assert st["mode"] == "external_project" assert st["project"] == "fixture-proj" def test_capabilities_cli_roundtrip(tmp_path): """The CLI transport exposes the same capability set (§3 transport parity: the builder must not need the Python API for schema detection).""" import subprocess env = {"objective": "x", "constraints": {}, "affected_surface": [], "evidence_refs": [], "approval_context": ""} r = subprocess.run( [ sys.executable, "-m", "rune.construction_interface", "capabilities", "--builder", "probe", "--project-store", str(tmp_path / ".rune" / "scaffold"), "--project-id", "fixture-proj", ], capture_output=True, text=True, timeout=120, env={**os.environ, "PYTHONPATH": os.path.join(ROOT, "src")}, ) assert r.returncode == 0, r.stderr[-300:] out = json.loads(r.stdout[r.stdout.index("{") :]) assert out["success"] assert out["state"]["schema_version"] == ci.INTERFACE_SCHEMA_VERSION assert "capabilities" in out["state"]["operations"] def test_15u_discover_active_contract_migrated_to_interface(tmp_path): """§15U simplification: resume discovery lives in the INTERFACE (one canonical home), not in session-driver scripts. The drivers' helpers are shims over this.""" from rune import construction_interface as ci store = tmp_path / "scaffold" iface = ci.ConstructionInterface(builder="probe", project_store=str(store), project_id="t15u") iface.scaffold.init(purpose="15u probe") empty = ci.ConstructionInterface.discover_active_contract(str(store)) assert not empty["success"], "empty store must not invent a contract" doc = iface.scaffold.load() from rune import structural_store as ss ss.add_entity(doc, id="contract:spec-15u", kind="contract", identities={"objective": "spec"}, evidence_refs=["e"]) ss.add_entity(doc, id="capability:planned", kind="capability", maturity="DECLARED", evidence_refs=["e"]) ss.add_relationship(doc, type="implements", from_id="capability:planned", to_id="contract:spec-15u", evidence_refs=["e"]) iface.scaffold.commit(doc, what="seed 15u spec") sub = iface.submit_need( "build the 15u module", constraints={"environment": {"os": "linux"}, "contracts": ["contract:spec-15u"]}, evidence_refs=["e"], approval_context="15u") assert sub["success"] found = ci.ConstructionInterface.discover_active_contract(str(store)) assert found["success"] assert found["ids"]["contract_id"] == sub["ids"]["contract_id"] # capabilities() advertises the new op assert "discover_active_contract" in \ iface.capabilities()["state"]["operations"] # ── T5.15 completion wave: stage_guards wired into transition ─────────────── def _guard_contract(iface, tmp_path): """A contract whose obligations declare a PATH guard and a failing command guard — proving both BLOCK shapes.""" doc = iface.scaffold.load() ss.add_entity( doc, id="contract:guarded-1", kind="contract", identities={ "objective": "guarded stage", "verification_obligations": [ "guard:" + json.dumps({ "name": "artifact present", "kind": "path_exists", "path": str(tmp_path / "artifact.txt"), }), ], }, evidence_refs=["e"], ) iface.scaffold.commit(doc, what="seed guarded contract") doc = iface.scaffold.load() # move through the legal path so guards face verifying from building sc.Scaffold.transition_contract(iface.scaffold, doc, "guarded-1", "approved", evidence_ref="t") sc.Scaffold.transition_contract(iface.scaffold, doc, "guarded-1", "building", evidence_ref="t") iface.scaffold.commit(doc, what="advance to building") return "guarded-1" def test_15f_transition_to_verifying_blocked_when_guard_fails(tmp_path): iface = _iface(tmp_path) cid = _guard_contract(iface, tmp_path) env = iface.transition(cid, "verifying") assert not env["success"] assert env["errors"][0]["error"] == ci.Errors.VERIFICATION_FAILED assert env["state"]["guard"]["verdict"] == "BLOCKED" # phase UNCHANGED — the blocked stage does not move doc = iface.scaffold.load() c = iface.scaffold.contract(doc, cid) assert c["phase"] == "building" def test_15f_transition_passes_when_guard_satisfied(tmp_path): iface = _iface(tmp_path) cid = _guard_contract(iface, tmp_path) (tmp_path / "artifact.txt").write_text("real artifact") env = iface.transition(cid, "verifying") assert env["success"], env["errors"] doc = iface.scaffold.load() assert iface.scaffold.contract(doc, cid)["phase"] == "verifying" def test_15f_inline_guard_checks_override_obligations(tmp_path): iface = _iface(tmp_path) cid = _guard_contract(iface, tmp_path) # has the path guard, NOT satisfied env = iface.transition( cid, "verifying", guard_checks=[{"name": "inline truth", "kind": "command", "argv": [sys.executable, "-c", "print('ok')"]}], ) assert env["success"], env["errors"] assert iface.scaffold.contract(iface.scaffold.load(), cid)["phase"] == "verifying" def test_15f_transition_to_building_runs_no_guards(tmp_path): """Completion-facing edges ONLY (verifying/closed): building→verifying is guarded, but draft→approved passes freely even with obligations.""" iface = _iface(tmp_path) doc = iface.scaffold.load() ss.add_entity(doc, id="contract:guarded-2", kind="contract", identities={"objective": "2"}, evidence_refs=["e"]) iface.scaffold.commit(doc, what="seed guarded-2") cid = "guarded-2" doc = iface.scaffold.load() c = iface.scaffold.contract(doc, cid) c["identities"]["verification_obligations"] = [ "guard:" + json.dumps({"name": "never", "kind": "path_exists", "path": "/nonexistent/for-sure"}) ] iface.scaffold.commit(doc, what="attach guard") env = iface.transition(cid, "approved") # NOT a completion edge assert env["success"] # ── T5.15 slice 3: programme_continuation wired into close() ──────────────── def _seed_programme(iface, programme_id, stage_contract_ids, tmp_path): """Persist a real Programme bound to the interface's scaffold store.""" from rune import programme_continuation as pc base = Path(iface.scaffold.current).parent / pc.DEFAULT_PROGRAMME_AREA prog = pc.Programme(programme_id=programme_id, objective="wave test") for i, cid in enumerate(stage_contract_ids): prog.stages.append(pc.ProgrammeStage( stage_id=cid, objective=f"stage {i}", depends_on=[])) prog.save(base) return prog, base def test_close_marks_programme_stage_complete_and_surfaces_continuation(tmp_path): """Closing a contract that is a stage of a persisted Programme marks that stage COMPLETE and the envelope carries the continuation canary — the programme's next eligible stage is surfaced, not guessed.""" from rune import programme_continuation as pc iface = _iface(tmp_path) env1 = _submit(iface, objective="wave stage one") cid1 = env1["ids"]["contract_id"] env2 = _submit(iface, objective="wave stage two") cid2 = env2["ids"]["contract_id"] # drive both through to verifying so close is legal for cid in (cid1, cid2): iface.transition(cid, "approved") iface.transition(cid, "building") iface.transition(cid, "verifying") prog, base = _seed_programme(iface, "wave-x", [cid1, cid2], tmp_path) env = iface.close(cid1, observed_evidence=[{"entity": "capability:exporter", "detail": "done"}]) assert env["success"], env["errors"] cont = env["state"].get("programme_continuation") assert cont, "close envelope must carry the programme continuation" assert cont["programme_id"] == "wave-x" assert cont["stage_marked_complete"] == cid1 reloaded = pc.Programme.load(base, "wave-x") stage1 = next(s for s in reloaded.stages if s.stage_id == cid1) assert stage1.state == pc.COMPLETE assert cont["canary"]["verdict"] == "PROGRAMME_OPEN" assert cont["canary"]["next_action"] == ("start", cid2) def test_close_without_programme_has_no_continuation_block(tmp_path): iface = _iface(tmp_path) env = _submit(iface) cid = env["ids"]["contract_id"] iface.transition(cid, "approved") iface.transition(cid, "building") iface.transition(cid, "verifying") env = iface.close(cid, observed_evidence=[{"entity": "capability:exporter", "detail": "done"}]) assert env["success"] assert "programme_continuation" not in env["state"] def test_close_programme_completion_verdict_surfaces(tmp_path): """Closing the LAST stage yields PROGRAMME_COMPLETE — the canary says stop, the runner never guesses.""" iface = _iface(tmp_path) env = _submit(iface) cid = env["ids"]["contract_id"] iface.transition(cid, "approved") iface.transition(cid, "building") iface.transition(cid, "verifying") prog, base = _seed_programme(iface, "solo", [cid], tmp_path) env = iface.close(cid, observed_evidence=[{"entity": "capability:exporter", "detail": "done"}]) cont = env["state"]["programme_continuation"] assert cont["canary"]["verdict"] == "PROGRAMME_COMPLETE" def test_two_submits_same_second_get_distinct_contract_ids(tmp_path): """Second-granularity timestamps collide when two needs are filed in the same second (real builder-pair scenario) — ids must be distinct.""" iface = _iface(tmp_path) e1 = _submit(iface, objective="wave stage one") e2 = _submit(iface, objective="wave stage two") assert e1["success"] and e2["success"], (e1["errors"], e2["errors"]) assert e1["ids"]["contract_id"] != e2["ids"]["contract_id"]