"""Shared evaluation context for steering read models and proposals (K-Ext-1).""" from __future__ import annotations from dataclasses import dataclass, field from typing import Any from steering.kernel.models import HorizonMarker, LifecycleContext, SteeringBinding from tenant_context import TenantContext @dataclass class SteeringEvalContext: """Tenant-scoped context — lazy OM loads for extension providers.""" tenant_ctx: TenantContext initiative_id: str binding: SteeringBinding horizon: HorizonMarker lifecycle: LifecycleContext operating_context: dict[str, Any] _actions: list[dict[str, Any]] | None = field(default=None, repr=False) _backlog_items: list[dict[str, Any]] | None = field(default=None, repr=False) _work_cycles: list[dict[str, Any]] | None = field(default=None, repr=False) @property def steering_elements(self) -> frozenset[str]: return frozenset(self.operating_context.get("steering_elements") or []) @property def data_slices(self) -> list[str]: return list(self.operating_context.get("data_slices") or []) @property def backlog_vocabulary(self) -> dict[str, Any]: return dict(self.operating_context.get("backlog_vocabulary") or {}) @property def actions(self) -> list[dict[str, Any]]: if self._actions is None: from services import actions as action_service self._actions = action_service.list_actions_for_initiative( tenant_id=self.tenant_ctx.tenant_id, initiative_id=self.initiative_id, ) return self._actions @property def backlog_items(self) -> list[dict[str, Any]]: if self._backlog_items is None: from services import backlog as backlog_service self._backlog_items = backlog_service.list_backlog_for_initiative( tenant_id=self.tenant_ctx.tenant_id, initiative_id=self.initiative_id, ) return self._backlog_items @property def work_cycles(self) -> list[dict[str, Any]]: if self._work_cycles is None: from services.work_cycle import list_work_cycles_for_initiative self._work_cycles = list_work_cycles_for_initiative( tenant_id=self.tenant_ctx.tenant_id, initiative_id=self.initiative_id, ) return self._work_cycles def build_steering_eval_context( tenant_ctx: TenantContext, *, initiative_id: str, binding: SteeringBinding, horizon: HorizonMarker, lifecycle: LifecycleContext, ) -> SteeringEvalContext: from services.operating_context import get_operating_context operating = ( get_operating_context( tenant_id=tenant_ctx.tenant_id, initiative_id=initiative_id ) or {} ) return SteeringEvalContext( tenant_ctx=tenant_ctx, initiative_id=initiative_id, binding=binding, horizon=horizon, lifecycle=lifecycle, operating_context=operating, )