Declare layer.yaml, add a Python engine over a local SQLite store, and cover deterministic assessment, the §13 gap register, stance-map inventory, claim guardrails, and the gate-house review path with tests. Assistant: grok Assistant-Session: 01a04ceb-150e-7e80-a542-ec8b1372e164
72 lines
2.7 KiB
Python
72 lines
2.7 KiB
Python
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from maturity_engine.claims import compile_into_registry, gate_on_level
|
|
from maturity_engine.engine import Engine
|
|
from maturity_engine.errors import GuardrailError
|
|
from conftest import INSTANT, evidence
|
|
|
|
|
|
def test_claim_shape(engine):
|
|
assessment = engine.assess("estate", "asm", at=INSTANT)
|
|
claim = engine.claim(assessment)
|
|
body = claim.as_dict()
|
|
assert body["kind"] == "maturity-level"
|
|
assert body["issuer"] == "maturity-engine"
|
|
assert body["subject"] == "estate"
|
|
assert body["level_id"] == "ASM-0"
|
|
assert body["digest"]
|
|
assert "freshness_rule" in body
|
|
|
|
|
|
def test_registry_compile_is_rejected(engine):
|
|
claim = engine.claim(engine.assess("estate", "asm", at=INSTANT))
|
|
with pytest.raises(GuardrailError, match="MUST NOT be compiled into registry"):
|
|
compile_into_registry(claim)
|
|
|
|
|
|
def test_consumer_branch_is_rejected(engine):
|
|
claim = engine.claim(engine.assess("estate", "asm", at=INSTANT))
|
|
with pytest.raises(GuardrailError, match="MUST NOT gate a decision directly"):
|
|
gate_on_level(claim, minimum=3)
|
|
|
|
|
|
def test_no_decision_surface():
|
|
assert not hasattr(Engine, "authorize")
|
|
assert not hasattr(Engine, "decide")
|
|
assert not hasattr(Engine, "may")
|
|
assert not hasattr(Engine, "allow")
|
|
|
|
|
|
def test_assessment_emission_is_local_and_load_bearing(engine):
|
|
engine.assess("estate", "asm", at=INSTANT)
|
|
events = [item for item in engine.pending_events() if item["event_type"] == "assessment.recorded"]
|
|
assert len(events) == 1
|
|
payload = events[0]["payload"]
|
|
assert payload["class"] == "load-bearing"
|
|
assert "not altered or truncated after arrival" in payload["bound"]
|
|
assert "never sent" in payload["bound"]
|
|
|
|
|
|
def test_outbox_failure_rolls_back_assessment(engine):
|
|
engine.store.fail_outbox = True
|
|
with pytest.raises(RuntimeError, match="outbox"):
|
|
engine.assess("estate", "pep-stance-publication", at=INSTANT)
|
|
assert engine.history("estate", "pep-stance-publication") == ()
|
|
|
|
|
|
def test_heartbeat_is_a_positive_claim(engine):
|
|
engine.heartbeat(at=INSTANT)
|
|
beats = [item for item in engine.pending_events() if item["event_type"] == "maturity-engine.heartbeat"]
|
|
assert beats
|
|
assert beats[0]["payload"]["form"] == "heartbeat"
|
|
|
|
|
|
def test_two_ladders_from_different_owners_can_be_claimed(engine):
|
|
for kind in ("stance-map-published", "stance-map-equality-test"):
|
|
engine.submit_evidence(evidence(engine, "ops-warden", kind))
|
|
asm = engine.claim(engine.assess("ops-warden", "asm", at=INSTANT))
|
|
psp = engine.claim(engine.assess("ops-warden", "pep-stance-publication", at=INSTANT))
|
|
assert asm.model_id != psp.model_id
|
|
assert psp.level_id == "PSP-2"
|