"""Signal Engine — method-aware NextAction (AP1.1).""" from __future__ import annotations from typing import Any, Literal from services import steering_context as sc_service from steering.methods.registry import get_method from steering.signals import default_rules from steering.strategies.next_action.default_strategy import default_strategy from steering.strategies.next_action.registry import get_next_action_strategy from tenant_context import TenantContext SignalKind = Literal["attention", "next_action"] def _resolve_method_key(ctx: TenantContext, initiative_id: str | None) -> str: if not initiative_id: return "generic_operating" row = sc_service.get_steering_context( tenant_id=ctx.tenant_id, initiative_id=initiative_id ) if row: return row["method_key"] return "generic_operating" def evaluate( ctx: TenantContext, kind: SignalKind = "attention", *, limit: int = 10, initiative_id: str | None = None, ) -> list[dict[str, Any]]: if kind == "attention": return default_rules.get_attention_items(ctx) method_key = _resolve_method_key(ctx, initiative_id) method = get_method(method_key) strategy_key = ( method.next_action_strategy_key if method else default_strategy.key ) strategy = get_next_action_strategy(strategy_key) or default_strategy return strategy.evaluate(ctx, initiative_id=initiative_id, limit=limit)