"""Sequential dependency NextAction strategy — AP2.0d.""" from __future__ import annotations from typing import Any from steering.signals import default_rules from steering.strategies.next_action.default_strategy import DefaultNextActionStrategy from steering.strategies.next_action.execution_ready import ( list_execution_ready_candidates, merge_candidates, ) from steering.strategies.next_action.registry import ( get_next_action_strategy, register_next_action_strategy, ) from tenant_context import TenantContext _default = DefaultNextActionStrategy() class SequentialDependencyStrategy: key = "sequential_dependency" def evaluate( self, ctx: TenantContext, *, initiative_id: str | None = None, limit: int = 10, ) -> list[dict[str, Any]]: if limit < 1: limit = 1 if not initiative_id: return _default.evaluate(ctx, limit=limit) ready = list_execution_ready_candidates( ctx, initiative_id, limit=limit, prefer_critical_path=True, ) if len(ready) >= limit: return ready[:limit] from steering.strategies.next_action.execution_ready import ( blocked_execution_action_ids, ) rest = default_rules.get_next_action_candidates_for_initiative( ctx, initiative_id=initiative_id, limit=limit - len(ready) ) blocked_ids = blocked_execution_action_ids(ctx, initiative_id) filtered = [ item for item in rest if not item.get("action_id") or item["action_id"] not in blocked_ids ] return merge_candidates(ready, filtered, limit=limit) sequential_dependency_strategy = SequentialDependencyStrategy() def register_sequential_dependency_strategy() -> None: if not get_next_action_strategy(sequential_dependency_strategy.key): register_next_action_strategy(sequential_dependency_strategy)