Kairo-Jinkendo/backend/steering/elements/registry.py
Lars a3b14d9c00
All checks were successful
Deploy Development / deploy (push) Successful in 47s
Test Suite / pytest-backend (push) Successful in 3m56s
Test Suite / lint-backend (push) Successful in 2s
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 13s
feat(steering): Backlog-Vokabular aus Methoden-Vertrag (ADP P3)
backlog_epic_hierarchy als Steuerungselement, effektive steering_elements im Operating Context, Backend-Guards und UI ohne Slice-Ifs.

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

97 lines
3.0 KiB
Python

"""Steering element catalog — AP2.4."""
from __future__ import annotations
from dataclasses import dataclass
from typing import Literal
ModeKey = Literal["plan", "work", "control"]
@dataclass(frozen=True)
class SteeringElementDefinition:
key: str
label: str
description: str
modes: tuple[ModeKey, ...]
STEERING_ELEMENTS: dict[str, SteeringElementDefinition] = {
"next_action_primary": SteeringElementDefinition(
key="next_action_primary",
label="Nächster Schritt",
description="Next-Action-Widget als primäre Steuerungsansicht",
modes=("control", "work"),
),
"critical_path": SteeringElementDefinition(
key="critical_path",
label="Kritischer Pfad",
description="Execution-Graph und Pfad-Priorisierung",
modes=("control",),
),
"gate_fulfillment": SteeringElementDefinition(
key="gate_fulfillment",
label="Gate-Erfüllung",
description="Zielzustände, Verify und Fortschritt",
modes=("control", "plan"),
),
"work_cycle_scope": SteeringElementDefinition(
key="work_cycle_scope",
label="Sprint-Zeitbox",
description="Aktive work_cycle und Sprint-Backlog",
modes=("work", "plan"),
),
"backlog_epic_hierarchy": SteeringElementDefinition(
key="backlog_epic_hierarchy",
label="Epic-Hierarchie",
description="Epic-Container und Story-Baum im Plan-Eingang (Agile-Modifier)",
modes=("plan",),
),
"recurring_rhythm": SteeringElementDefinition(
key="recurring_rhythm",
label="Rhythmen",
description="RecurringElement und Journey-Fokus",
modes=("control",),
),
"queue_inbox": SteeringElementDefinition(
key="queue_inbox",
label="Queue / Eingang",
description="Pull-Steuerung aus Backlog/Queue",
modes=("plan", "work"),
),
"maturity_stage": SteeringElementDefinition(
key="maturity_stage",
label="Reifegrad-Stufen",
description="Stufen und Routinen in Plan/Kontrolle",
modes=("plan", "control"),
),
"chapter_progression": SteeringElementDefinition(
key="chapter_progression",
label="Kapitel-Fortschritt",
description="Kapitel-basierte Progression",
modes=("plan", "control"),
),
"dispute_timeline": SteeringElementDefinition(
key="dispute_timeline",
label="Verfahren / Fristen",
description="Fristen, Entscheidungen, Verfahrensstrang",
modes=("control",),
),
}
def get_steering_element(key: str) -> SteeringElementDefinition | None:
return STEERING_ELEMENTS.get(key)
def list_steering_elements() -> tuple[SteeringElementDefinition, ...]:
return tuple(STEERING_ELEMENTS.values())
def validate_steering_element_keys(keys: frozenset[str]) -> None:
unknown = [k for k in keys if k not in STEERING_ELEMENTS]
if unknown:
raise ValueError(
f"Unbekannte steering_elements: {', '.join(sorted(unknown))}"
)