Kairo-Jinkendo/backend/tests/test_ap20d_next_action_strategies.py
Lars 284b9d50fe
Some checks failed
Test Suite / lint-backend (push) Waiting to run
Test Suite / compose-smoke (push) Waiting to run
Test Suite / k6 /api/health Baseline (push) Blocked by required conditions
Test Suite / playwright-smoke (push) Blocked by required conditions
Deploy Development / deploy (push) Successful in 45s
Test Suite / pytest-backend (push) Has been cancelled
AP2.0d: Next-Action-Strategien nutzen Execution-Graph ready_actions.
Archetyp-Strategien priorisieren ausführungsbereite APs mit Begründung execution_ready/critical_path; continuous_product und program_delivery integriert.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-12 12:04:40 +02:00

137 lines
4.4 KiB
Python

"""Unit tests for AP2.0d NextAction execution-ready strategies."""
from __future__ import annotations
from steering.graph.execution_engine import compute_execution_graph_state
from steering.methods.registry import list_methods
from steering.strategies.next_action import register_builtin_strategies
from steering.strategies.next_action.execution_ready import (
build_execution_ready_candidates,
merge_candidates,
rank_ready_action_ids,
)
from steering.strategies.next_action.registry import get_next_action_strategy
def _action(action_id: str, status: str = "open", **kwargs):
return {
"id": action_id,
"initiative_id": kwargs.get("initiative_id", "init-1"),
"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_rank_ready_prefers_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)
ranked = rank_ready_action_ids(state, prefer_critical_path=True)
assert ranked == ["b"]
def test_build_execution_ready_skips_blocked():
actions = [
_action("first", "open", sort_order=0),
_action("second", "open", sort_order=1),
]
state = compute_execution_graph_state(actions=actions, dependencies=[])
candidates = build_execution_ready_candidates(
actions=actions, graph_state=state, limit=5
)
assert len(candidates) == 1
assert candidates[0]["action_id"] == "first"
assert candidates[0]["reason_code"] in ("execution_ready", "execution_critical_path")
def test_critical_path_reason_code():
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)
candidates = build_execution_ready_candidates(
actions=actions, graph_state=state, limit=5, prefer_critical_path=True
)
assert candidates[0]["reason_code"] == "execution_critical_path"
def test_merge_candidates_deduplicates_actions():
first = [
{
"kind": "action",
"action_id": "a1",
"title": "A",
}
]
second = [
{
"kind": "action",
"action_id": "a1",
"title": "A duplicate",
},
{
"kind": "review_milestone",
"title": "Gate",
},
]
merged = merge_candidates(first, second, limit=5)
assert len(merged) == 2
assert merged[0]["action_id"] == "a1"
assert merged[1]["kind"] == "review_milestone"
def test_ap20d_strategies_registered():
register_builtin_strategies()
for key in (
"sequential_dependency",
"maturity_progression",
"recurring_control",
"queue_pull",
"continuous_product",
"program_delivery",
):
assert get_next_action_strategy(key) is not None
def test_ap20d_methods_wire_strategies():
register_builtin_strategies()
methods = {m.key: m for m in list_methods()}
assert methods["sequential_dependency"].next_action_strategy_key == "sequential_dependency"
assert methods["maturity_progression"].next_action_strategy_key == "maturity_progression"
assert methods["recurring_control"].next_action_strategy_key == "recurring_control"
assert methods["queue_pull"].next_action_strategy_key == "queue_pull"
assert methods["continuous_product"].next_action_strategy_key == "continuous_product"
assert methods["program_delivery"].next_action_strategy_key == "program_delivery"