Kairo-Jinkendo/backend/steering/backlog_vocabulary.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

96 lines
2.5 KiB
Python

"""Profilgebundenes Backlog-Vokabular — ADP P3 / AP2.4 Methoden-Vertrag."""
from __future__ import annotations
from typing import Any
_EMPTY: dict[str, Any] = {
"profile_key": "none",
"kinds": [],
"labels": {},
"default_kind": "story",
"epic_hierarchy": False,
"convertible_kinds": [],
"capabilities": {
"sprint_commit": False,
"epic_hierarchy": False,
},
}
_AGILE_INTAKE: dict[str, Any] = {
"profile_key": "agile_intake",
"kinds": ["epic", "story", "bug", "issue"],
"labels": {
"epic": "Epic",
"story": "Story",
"bug": "Bug",
"issue": "Issue",
},
"default_kind": "story",
"epic_hierarchy": True,
"convertible_kinds": ["story", "bug", "issue"],
}
_CONTINUOUS_INTAKE: dict[str, Any] = {
"profile_key": "continuous_intake",
"kinds": ["story", "bug", "issue"],
"labels": {
"story": "Idee",
"bug": "Bug",
"issue": "Störung",
},
"default_kind": "story",
"epic_hierarchy": False,
"convertible_kinds": ["story", "bug", "issue"],
}
_STANDARD_INTAKE: dict[str, Any] = {
"profile_key": "standard_intake",
"kinds": ["story", "bug", "issue"],
"labels": {
"story": "Story",
"bug": "Bug",
"issue": "Issue",
},
"default_kind": "story",
"epic_hierarchy": False,
"convertible_kinds": ["story", "bug", "issue"],
}
def _with_capabilities(
vocabulary: dict[str, Any],
*,
steering_elements: frozenset[str],
) -> dict[str, Any]:
result = dict(vocabulary)
sprint_commit = "work_cycle_scope" in steering_elements
epic_hierarchy = "backlog_epic_hierarchy" in steering_elements
result["epic_hierarchy"] = epic_hierarchy
result["capabilities"] = {
"sprint_commit": sprint_commit,
"epic_hierarchy": epic_hierarchy,
}
return result
def resolve_backlog_vocabulary(
*,
data_slices: list[str],
method_key: str,
steering_elements: frozenset[str],
) -> dict[str, Any]:
"""Backlog-Typen/Labels aus effektivem Methoden-Vertrag — nicht aus Page-Ifs."""
if "backlog" not in data_slices:
return dict(_EMPTY)
if "backlog_epic_hierarchy" in steering_elements:
return _with_capabilities(dict(_AGILE_INTAKE), steering_elements=steering_elements)
if method_key == "continuous_product":
return _with_capabilities(
dict(_CONTINUOUS_INTAKE), steering_elements=steering_elements
)
return _with_capabilities(dict(_STANDARD_INTAKE), steering_elements=steering_elements)