Kairo-Jinkendo/backend/steering/proposals/registry.py
Lars b747200f3a
All checks were successful
Deploy Development / deploy (push) Successful in 46s
Test Suite / pytest-backend (push) Successful in 4m13s
Test Suite / lint-backend (push) Successful in 3s
Test Suite / compose-smoke (push) Has been skipped
Test Suite / k6 /api/health Baseline (push) Successful in 19s
Test Suite / playwright-smoke (push) Successful in 12s
feat(steering): K-Ext-2 Attention-Registry, Gate/Intake-Proposals, generische UI
Methodenuebergreifende Provider auf Kernel v0.3; verbindliche Coding Rules fuer Agenten in ADP und .cursor/rules.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-27 11:48:10 +02:00

89 lines
2.7 KiB
Python

"""Proposal provider registry — K-Ext-1 / P6."""
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any, Callable
from steering.eval_context import SteeringEvalContext
ProposalCompute = Callable[[SteeringEvalContext, dict[str, Any]], Any]
@dataclass(frozen=True)
class ProposalProvider:
key: str
requires_elements: frozenset[str]
requires_data_slices: frozenset[str]
compute: ProposalCompute
excludes_elements: frozenset[str] = field(default_factory=frozenset)
_PROVIDERS: list[ProposalProvider] = []
def register_proposal(provider: ProposalProvider) -> None:
_PROVIDERS.append(provider)
def compute_proposals(
ctx: SteeringEvalContext,
*,
read_models: dict[str, Any],
) -> dict[str, Any]:
elements = ctx.steering_elements
slices = frozenset(ctx.data_slices)
result: dict[str, Any] = {}
for provider in _PROVIDERS:
if provider.requires_elements and not provider.requires_elements <= elements:
continue
if provider.excludes_elements and provider.excludes_elements & elements:
continue
if provider.requires_data_slices and not provider.requires_data_slices <= slices:
continue
result[provider.key] = provider.compute(ctx, read_models)
return result
def _register_builtin_proposals() -> None:
from steering.proposals.gate_next_actions import propose_gate_next_actions
from steering.proposals.intake_triage import propose_intake_triage
from steering.proposals.sprint_commit import propose_sprint_commit
register_proposal(
ProposalProvider(
key="sprint_commit",
requires_elements=frozenset({"work_cycle_scope"}),
requires_data_slices=frozenset({"backlog", "work_cycles"}),
compute=lambda ctx, read_models: propose_sprint_commit(
ctx, read_models=read_models
),
)
)
register_proposal(
ProposalProvider(
key="gate_next_actions",
requires_elements=frozenset({"gate_fulfillment"}),
requires_data_slices=frozenset({"backlog", "roadmap", "actions"}),
compute=lambda ctx, read_models: propose_gate_next_actions(
ctx, read_models=read_models
),
)
)
register_proposal(
ProposalProvider(
key="intake_triage",
requires_elements=frozenset(),
requires_data_slices=frozenset({"backlog"}),
excludes_elements=frozenset({"work_cycle_scope"}),
compute=lambda ctx, read_models: propose_intake_triage(
ctx, read_models=read_models
),
)
)
_register_builtin_proposals()