"""Unit tests for execution graph engine (AP1.16b).""" from steering.graph.execution_engine import ( compute_execution_graph_state, compute_planning_debt, execution_waiting_to_attention_items, planning_debt_to_attention_items, ) def _action(action_id: str, status: str = "open", **kwargs): return { "id": action_id, "status": status, "sort_order": kwargs.get("sort_order", 0), "title": kwargs.get("title", action_id), "action_kind": kwargs.get("action_kind", "delivery"), "roadmap_item_id": kwargs.get("roadmap_item_id"), } def test_requires_blocks_until_predecessor_done(): actions = [_action("b", "open"), _action("a", "open")] deps = [ { "predecessor_action_id": "b", "successor_action_id": "a", "dependency_kind": "requires", } ] state = compute_execution_graph_state(actions=actions, dependencies=deps) assert state["items"]["a"]["blocked"] is True assert state["items"]["a"]["blocked_by"] == ["b"] assert "a" in state["blocked_actions"] assert "a" not in state["ready_actions"] actions[0]["status"] = "done" state = compute_execution_graph_state(actions=actions, dependencies=deps) assert state["items"]["a"]["ready"] is True assert "a" in state["ready_actions"] def test_sequential_fallback_without_edges(): actions = [ _action("first", "open", sort_order=0), _action("second", "open", sort_order=1), ] state = compute_execution_graph_state(actions=actions, dependencies=[]) assert state["items"]["first"]["ready"] is True assert state["items"]["second"]["blocked"] is True assert state["items"]["second"]["blocked_by"] == ["first"] actions[0]["status"] = "done" state = compute_execution_graph_state(actions=actions, dependencies=[]) assert state["items"]["second"]["ready"] is True def test_blocks_edge(): actions = [_action("blocker", "in_progress"), _action("blocked", "open")] deps = [ { "predecessor_action_id": "blocker", "successor_action_id": "blocked", "dependency_kind": "blocks", } ] state = compute_execution_graph_state(actions=actions, dependencies=deps) assert state["items"]["blocked"]["blocked"] is True actions[0]["status"] = "done" state = compute_execution_graph_state(actions=actions, dependencies=deps) assert state["items"]["blocked"]["ready"] is True def test_critical_path(): actions = [ _action("a", "done", sort_order=0), _action("b", "open", sort_order=1), _action("c", "open", sort_order=2), ] deps = [ { "predecessor_action_id": "a", "successor_action_id": "b", "dependency_kind": "requires", }, { "predecessor_action_id": "b", "successor_action_id": "c", "dependency_kind": "requires", }, ] state = compute_execution_graph_state(actions=actions, dependencies=deps) assert state["critical_path"] == ["a", "b", "c"] def test_planning_debt_active_gate_without_actions(): actions = [_action("x", roadmap_item_id="gate-2")] roadmap_items = [ {"id": "gate-1", "status": "active", "title": "G5"}, {"id": "gate-2", "status": "active", "title": "G6"}, ] debts = compute_planning_debt(actions=actions, roadmap_items=roadmap_items) assert len(debts) == 1 assert debts[0]["roadmap_item_id"] == "gate-1" def test_scope_filters_to_gate(): actions = [ _action("a", roadmap_item_id="g1", sort_order=0), _action("b", roadmap_item_id="g2", sort_order=0), ] state = compute_execution_graph_state( actions=actions, dependencies=[], scope_roadmap_item_id="g1", ) assert set(state["items"].keys()) == {"a"} def test_planning_debt_attention_items(): items = planning_debt_to_attention_items( initiative_id="init-1", debts=[ { "roadmap_item_id": "gate-1", "title": "G5 Plan", "message": "Aktiver Zielzustand ohne Durchführungsplan", } ], ) assert len(items) == 1 assert items[0]["kind"] == "planning_debt" assert items[0]["initiative_id"] == "init-1" assert items[0]["milestone_id"] == "gate-1" def test_execution_waiting_attention_items(): actions = [ _action("a", "open", sort_order=0), _action("b", "open", sort_order=1), ] state = compute_execution_graph_state( actions=actions, dependencies=[ { "predecessor_action_id": "a", "successor_action_id": "b", "dependency_kind": "requires", } ], ) items = execution_waiting_to_attention_items( initiative_id="init-1", actions=actions, graph_state=state, ) assert len(items) == 1 assert items[0]["kind"] == "execution_waiting" assert items[0]["action_id"] == "b"