idea135-crisisops-open-crisis/tests/test_planner.py

58 lines
2.0 KiB
Python

import json
from crisisops.planner import ADMMPlanner
from crisisops.core import GraphOfContracts, Object, Morphism
from crisisops.governance import GovernanceLedger
from crisisops.replay import graph_snapshot, restore_graph
def build_simple_goC():
a = Object(id="a1", type="resource", attributes={"qty": 10})
b = Object(id="b1", type="node", attributes={"cap": 5})
m = Morphism(id="m1", source_id=a.id, target_id=b.id, type="dispatch", signals={})
return GraphOfContracts(objects={a.id: a, b.id: b}, morphisms={m.id: m})
def test_planner_allocates_dispatch_actions():
gof = build_simple_goC()
planner = ADMMPlanner()
plan = planner.optimize(gof)
assert isinstance(plan.actions, list)
assert plan.actions[0]["action"] == "dispatch"
assert plan.actions[0]["details"]["utility_score"] > 0
def test_graph_snapshot_is_deterministic_and_restorable():
gof_a = build_simple_goC()
gof_b = GraphOfContracts(
objects={"b1": gof_a.objects["b1"], "a1": gof_a.objects["a1"]},
morphisms={"m1": gof_a.morphisms["m1"]},
)
snapshot_a = graph_snapshot(gof_a)
snapshot_b = graph_snapshot(gof_b)
assert snapshot_a["snapshot_hash"] == snapshot_b["snapshot_hash"]
restored = restore_graph(snapshot_a)
assert restored.objects["a1"].attributes["qty"] == 10
assert restored.morphisms["m1"].target_id == "b1"
def test_snapshot_hash_tracks_plan_changes():
gof = build_simple_goC()
planner = ADMMPlanner()
plan = planner.optimize(gof)
snapshot = graph_snapshot(gof, plan=plan)
assert snapshot["plan_delta"]["actions"][0]["details"]["utility_score"] > 0
assert snapshot["snapshot_hash"]
def test_governance_ledger_canonicalizes_structured_details():
ledger = GovernanceLedger()
ledger.log_plan(actor="planner-1", status="approved", plan_hash="abc123", details={"agency": "ngo-a"})
record = ledger.list_logs()[0]
assert json.loads(record["details"]) == {"agency": "ngo-a", "plan_hash": "abc123"}