AP2.0: Archetyp-Katalog, Method-Stubs und sichtbare Steuerung in Kontrolle.
Some checks failed
Deploy Development / deploy (push) Successful in 46s
Test Suite / pytest-backend (push) Failing after 2m2s
Test Suite / k6 /api/health Baseline (push) Has been skipped
Test Suite / playwright-smoke (push) Has been skipped
Test Suite / lint-backend (push) Successful in 3s
Test Suite / compose-smoke (push) Has been skipped

PO-Dokumente (ADP v0.2, MVP v0.3) und Minimal Complete Slice: Registry-Methoden, Initiative/Project-Spiegel, Default-Methode bei Anlage, Lagebild mit Archetyp und Guidance.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Lars 2026-07-10 10:44:38 +02:00
parent 21d948634e
commit 3bd983297b
30 changed files with 2093 additions and 52 deletions

View File

@ -11,6 +11,7 @@ from psycopg2.extras import RealDictCursor
from db import get_connection from db import get_connection
from data_layer.attention import get_next_action_candidates_for_initiative from data_layer.attention import get_next_action_candidates_for_initiative
from entity_archetypes.registry import archetype_label
from steering.context import get_steering_context_dto from steering.context import get_steering_context_dto
from steering.signals.snapshot_signals import derive_initiative_signals from steering.signals.snapshot_signals import derive_initiative_signals
from services.initiatives import get_initiative from services.initiatives import get_initiative
@ -20,6 +21,41 @@ OPEN_BLOCKER = ("open", "in_progress")
OPEN_ACTION = ("open", "ready", "in_progress", "blocked", "review_required") OPEN_ACTION = ("open", "ready", "in_progress", "blocked", "review_required")
ACTIVE_INITIATIVE = ("active", "paused") ACTIVE_INITIATIVE = ("active", "paused")
_REASON_LABELS = {
"open_action_priority": "Offenes Arbeitspaket",
"milestone_at_risk_or_active": "Plan-Element aktiv oder gefährdet",
"blocked_action": "Blockiertes Arbeitspaket",
"backlog_triage": "Eingang triagieren",
}
def _steering_guidance(
*,
next_actions: list[dict[str, Any]],
signals: list[str],
method_key: str,
) -> str:
if next_actions:
item = next_actions[0]
title = item.get("title") or "Nächster Schritt"
hint = (
item.get("recommended_action")
or item.get("summary")
or _REASON_LABELS.get(item.get("reason_code", ""), "")
)
if hint:
return f"Als Nächstes: {title}{hint}"
return f"Als Nächstes: {title}"
if signals:
return "Attention: Struktur oder Ist-Arbeit ergänzen, um Next Actions zu erzeugen."
return (
f"Methode {method_key}: Plan oder Eingang befüllen, dann committete Arbeit starten."
)
def _attention_items(signals: list[str]) -> list[dict[str, str]]:
return [{"code": code, "label": code.replace("_", " ")} for code in signals]
def _sid(value: Any) -> Optional[str]: def _sid(value: Any) -> Optional[str]:
return str(value) if value else None return str(value) if value else None
@ -261,16 +297,32 @@ def get_initiative_steering_snapshot(
) )
steering = get_steering_context_dto(ctx, initiative_id=initiative_id) steering = get_steering_context_dto(ctx, initiative_id=initiative_id)
metadata = steering.get("lifecycle_metadata") or {}
if isinstance(metadata, str):
metadata = {}
method_profile_key = metadata.get("method_profile_key")
initiative_archetype = initiative.get("archetype_key") or "initiative.generic"
return { return {
"initiative_id": initiative_id, "initiative_id": initiative_id,
"initiative_title": initiative["title"], "initiative_title": initiative["title"],
"initiative_status": initiative["status"], "initiative_status": initiative["status"],
"archetype_key": initiative_archetype,
"archetype_label": archetype_label(
entity_type="initiative", archetype_key=initiative_archetype
),
"method_profile_key": method_profile_key,
"lifecycle_state": steering["lifecycle_state"], "lifecycle_state": steering["lifecycle_state"],
"lifecycle_label": steering["lifecycle_label"], "lifecycle_label": steering["lifecycle_label"],
"method_key": steering["method_key"], "method_key": steering["method_key"],
"method_label": steering.get("method_label"), "method_label": steering.get("method_label"),
"method_version": steering["method_version"], "method_version": steering["method_version"],
"steering_guidance": _steering_guidance(
next_actions=next_actions,
signals=signals,
method_key=steering["method_key"],
),
"attention_items": _attention_items(signals),
"signals": signals, "signals": signals,
"upcoming_milestones": upcoming_milestones, "upcoming_milestones": upcoming_milestones,
"upcoming_roadmap_items": upcoming_milestones, "upcoming_roadmap_items": upcoming_milestones,

View File

@ -1,13 +1,21 @@
from entity_archetypes.registry import ( from entity_archetypes.registry import (
ENTITY_ARCHETYPES,
INITIATIVE_ARCHETYPES, INITIATIVE_ARCHETYPES,
PROJECT_ARCHETYPES,
archetype_label, archetype_label,
list_archetypes, list_archetypes,
mirror_project_archetype_key,
resolve_default_method_key,
validate_archetype_key, validate_archetype_key,
) )
__all__ = [ __all__ = [
"ENTITY_ARCHETYPES",
"INITIATIVE_ARCHETYPES", "INITIATIVE_ARCHETYPES",
"PROJECT_ARCHETYPES",
"archetype_label", "archetype_label",
"list_archetypes", "list_archetypes",
"mirror_project_archetype_key",
"resolve_default_method_key",
"validate_archetype_key", "validate_archetype_key",
] ]

View File

@ -1,4 +1,4 @@
"""System-Archetypen (AP1.10a/10b) — In-Memory-Seed + DB-Registry.""" """System-Archetypen (AP1.10 + AP2.0) — Seeds, Bindings, Spiegel Project."""
from __future__ import annotations from __future__ import annotations
@ -8,39 +8,136 @@ from psycopg2.extras import RealDictCursor
from db import get_connection from db import get_connection
INITIATIVE_ARCHETYPES: tuple[dict[str, Any], ...] = ( # initiative suffix → default method (shared by initiative + project mirror)
{ _METHOD_BY_SUFFIX: dict[str, str] = {
"key": "initiative.generic", "generic": "generic_operating",
"entity_type": "initiative", "maturity_journey": "maturity_progression",
"label": "Allgemeines Vorhaben", "linear_project": "sequential_dependency",
"description": "Standard-Vorhaben ohne spezielle Vorlage.", "recurring_program": "recurring_control",
"is_system": True, "support_queue": "queue_pull",
}, "program": "program_delivery",
{ "product": "continuous_product",
"key": "initiative.program", "dispute_case": "dispute_procedure",
"entity_type": "initiative", "content_project": "chapter_based_progression",
"label": "Programm / Mega-Vorhaben", }
"description": "Mehrere Stränge, Zielzustand und Vision zentral.",
"is_system": True, _INITIATIVE_SPEC_META: tuple[tuple[str, str, str], ...] = (
}, ("generic", "Allgemeines Vorhaben", "Fallback ohne spezielle Steuerungsvorlage."),
{ (
"key": "initiative.product", "maturity_journey",
"entity_type": "initiative", "Reifegrad-Entwicklung",
"label": "Produkt / Release", "Mehrstufige Entwicklung, Routinen, Graph-Voraussetzungen.",
"description": "Produkt- oder Release-orientiertes Vorhaben.", ),
"is_system": True, (
}, "linear_project",
"Lineares Vorhaben",
"Einmalprojekte mit Pfaden, Gates und Graph.",
),
(
"recurring_program",
"Dauerprogramm / Rhythmus",
"Haushalt, Rhythmen, Abweichungs-Steuerung.",
),
(
"support_queue",
"Inbox / Queue",
"Ad-hoc-Eingang, triage, thematische Zuordnung.",
),
(
"program",
"Programm (begrenzt)",
"Phasen, Release-Programm mit Abschluss.",
),
(
"product",
"Produkt (kontinuierlich)",
"Dauerbetrieb, Wartung, Issues, Weiterentwicklung.",
),
(
"dispute_case",
"Verfahren / Konflikt",
"Reaktive Steuerung, Fristen, Entscheidungen.",
),
(
"content_project",
"Inhalt / Kapitel",
"Bücher, Konzepte, Kapitelstruktur.",
),
) )
_ARCHETYPE_INDEX = {
(item["entity_type"], item["key"]): item for item in INITIATIVE_ARCHETYPES def _build_specs() -> tuple[dict[str, Any], ...]:
specs: list[dict[str, Any]] = []
for suffix, label, description in _INITIATIVE_SPEC_META:
method = _METHOD_BY_SUFFIX[suffix]
specs.append(
{
"key": f"initiative.{suffix}",
"entity_type": "initiative",
"label": label,
"description": description,
"is_system": True,
"default_method_key": method,
"default_method_profile_key": None,
}
)
specs.append(
{
"key": f"project.{suffix}",
"entity_type": "project",
"label": label,
"description": f"Project-Spiegel: {description}",
"is_system": True,
"default_method_key": method,
"default_method_profile_key": None,
}
)
return tuple(specs)
ENTITY_ARCHETYPES: tuple[dict[str, Any], ...] = _build_specs()
INITIATIVE_ARCHETYPES: tuple[dict[str, Any], ...] = tuple(
item for item in ENTITY_ARCHETYPES if item["entity_type"] == "initiative"
)
PROJECT_ARCHETYPES: tuple[dict[str, Any], ...] = tuple(
item for item in ENTITY_ARCHETYPES if item["entity_type"] == "project"
)
_ARCHETYPE_INDEX: dict[tuple[str, str], dict[str, Any]] = {
(item["entity_type"], item["key"]): item for item in ENTITY_ARCHETYPES
} }
_KEY_INDEX: dict[str, dict[str, Any]] = {item["key"]: item for item in ENTITY_ARCHETYPES}
def _list_archetypes_from_memory(*, entity_type: Optional[str] = None) -> list[dict[str, Any]]: def _list_archetypes_from_memory(*, entity_type: Optional[str] = None) -> list[dict[str, Any]]:
if entity_type is None: items = ENTITY_ARCHETYPES
return [dict(item) for item in INITIATIVE_ARCHETYPES] if entity_type is not None:
return [dict(item) for item in INITIATIVE_ARCHETYPES if item["entity_type"] == entity_type] items = tuple(i for i in items if i["entity_type"] == entity_type)
return [_public_archetype(item) for item in items]
def _public_archetype(item: dict[str, Any]) -> dict[str, Any]:
return {
"key": item["key"],
"entity_type": item["entity_type"],
"label": item["label"],
"description": item["description"],
"is_system": item["is_system"],
"default_method_key": item["default_method_key"],
"default_method_profile_key": item.get("default_method_profile_key"),
}
def _enrich_row(row: dict[str, Any]) -> dict[str, Any]:
base = dict(row)
spec = _KEY_INDEX.get(base.get("key", ""))
if spec:
base.setdefault("default_method_key", spec["default_method_key"])
base.setdefault("default_method_profile_key", spec.get("default_method_profile_key"))
return base
def list_archetypes(*, entity_type: Optional[str] = None) -> list[dict[str, Any]]: def list_archetypes(*, entity_type: Optional[str] = None) -> list[dict[str, Any]]:
@ -67,7 +164,7 @@ def list_archetypes(*, entity_type: Optional[str] = None) -> list[dict[str, Any]
) )
rows = cur.fetchall() rows = cur.fetchall()
if rows: if rows:
return [dict(row) for row in rows] return [_enrich_row(dict(row)) for row in rows]
except Exception: except Exception:
pass pass
finally: finally:
@ -83,3 +180,19 @@ def validate_archetype_key(*, entity_type: str, archetype_key: str) -> None:
def archetype_label(*, entity_type: str, archetype_key: str) -> Optional[str]: def archetype_label(*, entity_type: str, archetype_key: str) -> Optional[str]:
item = _ARCHETYPE_INDEX.get((entity_type, archetype_key)) item = _ARCHETYPE_INDEX.get((entity_type, archetype_key))
return item["label"] if item else None return item["label"] if item else None
def resolve_default_method_key(archetype_key: str) -> str:
spec = _KEY_INDEX.get(archetype_key)
if not spec:
return "generic_operating"
return spec.get("default_method_key", "generic_operating")
def mirror_project_archetype_key(initiative_archetype_key: str) -> str:
if initiative_archetype_key.startswith("initiative."):
suffix = initiative_archetype_key[len("initiative.") :]
candidate = f"project.{suffix}"
if ( "project", candidate) in _ARCHETYPE_INDEX:
return candidate
return "project.generic"

View File

@ -1,4 +1,4 @@
"""System-Felddefinitionen (Seed) — AP1.10b.""" """System-Felddefinitionen (Seed) — AP1.10b / AP2.0b."""
from __future__ import annotations from __future__ import annotations
@ -45,4 +45,44 @@ FIELD_DEFINITIONS: tuple[dict[str, Any], ...] = (
"sort_order": 20, "sort_order": 20,
"validation_json": {}, "validation_json": {},
}, },
{
"archetype_key": "initiative.maturity_journey",
"field_key": "current_focus",
"field_type": "text",
"label": "Aktueller Fokus",
"required": False,
"searchable": True,
"sort_order": 10,
"validation_json": {},
},
{
"archetype_key": "initiative.maturity_journey",
"field_key": "training_frequency",
"field_type": "enum",
"label": "Trainingsfrequenz",
"required": False,
"searchable": False,
"sort_order": 20,
"validation_json": {"options": ["daily", "3x_week", "weekly", "flexible"]},
},
{
"archetype_key": "initiative.content_project",
"field_key": "manuscript_status",
"field_type": "text",
"label": "Manuskript-Status",
"required": False,
"searchable": True,
"sort_order": 10,
"validation_json": {},
},
{
"archetype_key": "initiative.content_project",
"field_key": "word_count_goal",
"field_type": "number",
"label": "Wortziel",
"required": False,
"searchable": False,
"sort_order": 20,
"validation_json": {},
},
) )

View File

@ -1,11 +1,11 @@
"""Sync Entity-Archetypen und Felddefinitionen in PostgreSQL — AP1.10b.""" """Sync Entity-Archetypen und Felddefinitionen in PostgreSQL — AP1.10b / AP2.0b."""
from __future__ import annotations from __future__ import annotations
import json import json
from db import get_connection from db import get_connection
from entity_archetypes.registry import INITIATIVE_ARCHETYPES from entity_archetypes.registry import ENTITY_ARCHETYPES
from entity_fields.definitions import FIELD_DEFINITIONS from entity_fields.definitions import FIELD_DEFINITIONS
@ -13,7 +13,7 @@ def sync_entity_field_registry_to_db() -> int:
conn = get_connection() conn = get_connection()
try: try:
with conn.cursor() as cur: with conn.cursor() as cur:
for archetype in INITIATIVE_ARCHETYPES: for archetype in ENTITY_ARCHETYPES:
cur.execute( cur.execute(
""" """
INSERT INTO entity_archetypes ( INSERT INTO entity_archetypes (
@ -68,7 +68,7 @@ def sync_entity_field_registry_to_db() -> int:
conn.commit() conn.commit()
print( print(
"[entity_fields] Sync OK — " "[entity_fields] Sync OK — "
f"{len(INITIATIVE_ARCHETYPES)} Archetyp(en), " f"{len(ENTITY_ARCHETYPES)} Archetyp(en), "
f"{len(FIELD_DEFINITIONS)} Felddefinition(en)" f"{len(FIELD_DEFINITIONS)} Felddefinition(en)"
) )
return 0 return 0

View File

@ -0,0 +1 @@
"""Package marker for method profile seeds."""

View File

@ -0,0 +1,63 @@
"""Referenz-Ausprägungen (Method Profiles) — Code-Seeds AP2.0b."""
from __future__ import annotations
from typing import Any, Optional
METHOD_PROFILES: tuple[dict[str, Any], ...] = (
{
"key": "maturity.karate_kumite",
"label": "Karate Kumite",
"description": "Mehrere Fähigkeiten mit Stufen, Routinen und Voraussetzungs-Graph.",
"initiative_archetype_key": "initiative.maturity_journey",
"method_key": "maturity_progression",
"seed_hints": {
"skill_count": 8,
"stages_per_skill": "5-7",
"graph_prerequisites": True,
},
},
{
"key": "content.book_writing",
"label": "Buch schreiben",
"description": "Kapitelstruktur, Schreib-APs, Review-Gates.",
"initiative_archetype_key": "initiative.content_project",
"method_key": "chapter_based_progression",
"seed_hints": {
"roadmap_item_type": "chapter",
"review_gates": True,
},
},
{
"key": "product.kairo_dev",
"label": "Kairo Entwicklung",
"description": "Kontinuierliches Produkt mit Gate-Orientierung und optionaler Sprint-Zeitbox.",
"initiative_archetype_key": "initiative.product",
"method_key": "continuous_product",
"seed_hints": {
"agile_iteration_profile": True,
"default_actor_setup": "po_plus_vibe_coder",
},
},
)
_PROFILE_INDEX = {item["key"]: item for item in METHOD_PROFILES}
def get_method_profile(key: str) -> Optional[dict[str, Any]]:
item = _PROFILE_INDEX.get(key)
return dict(item) if item else None
def list_method_profiles(*, initiative_archetype_key: Optional[str] = None) -> list[dict[str, Any]]:
items = METHOD_PROFILES
if initiative_archetype_key:
items = tuple(
i for i in items if i["initiative_archetype_key"] == initiative_archetype_key
)
return [dict(item) for item in items]
def resolve_method_for_profile(profile_key: str) -> Optional[str]:
profile = get_method_profile(profile_key)
return profile["method_key"] if profile else None

View File

@ -0,0 +1,27 @@
-- AP2.0b: Project archetype_key (Spiegel der Initiative)
ALTER TABLE projects
ADD COLUMN IF NOT EXISTS archetype_key VARCHAR(64) NULL;
CREATE INDEX IF NOT EXISTS idx_projects_archetype
ON projects (tenant_id, archetype_key)
WHERE archetype_key IS NOT NULL;
-- Bestehende Projects: Mirror aus Initiative (einmalig)
UPDATE projects p
SET archetype_key = CASE i.archetype_key
WHEN 'initiative.generic' THEN 'project.generic'
WHEN 'initiative.maturity_journey' THEN 'project.maturity_journey'
WHEN 'initiative.linear_project' THEN 'project.linear_project'
WHEN 'initiative.recurring_program' THEN 'project.recurring_program'
WHEN 'initiative.support_queue' THEN 'project.support_queue'
WHEN 'initiative.program' THEN 'project.program'
WHEN 'initiative.product' THEN 'project.product'
WHEN 'initiative.dispute_case' THEN 'project.dispute_case'
WHEN 'initiative.content_project' THEN 'project.content_project'
ELSE 'project.generic'
END
FROM initiatives i
WHERE p.initiative_id = i.id
AND p.tenant_id = i.tenant_id
AND p.archetype_key IS NULL;

View File

@ -124,6 +124,7 @@ def create_initiative(
tenant_id=tenant_id, tenant_id=tenant_id,
initiative_id=row["id"], initiative_id=row["id"],
user_id=user_id, user_id=user_id,
archetype_key=archetype_key,
) )
return row return row

View File

@ -9,6 +9,7 @@ from psycopg2.extras import RealDictCursor
from db import get_connection from db import get_connection
from services.audit import log_audit from services.audit import log_audit
from entity_archetypes import mirror_project_archetype_key, validate_archetype_key
from services.initiatives import get_initiative from services.initiatives import get_initiative
ProjectStatus = Literal["active", "paused", "completed", "archived"] ProjectStatus = Literal["active", "paused", "completed", "archived"]
@ -21,7 +22,7 @@ MAX_PROJECT_DEPTH = 5
_PROJECT_COLUMNS = """ _PROJECT_COLUMNS = """
id, tenant_id, initiative_id, parent_project_id, container_kind, id, tenant_id, initiative_id, parent_project_id, container_kind,
title, description, status, archetype_key, title, description, status,
roadmap_item_id, sort_order, target_date, created_at, updated_at roadmap_item_id, sort_order, target_date, created_at, updated_at
""" """
@ -227,6 +228,7 @@ def create_project(
roadmap_item_id: Optional[str] = None, roadmap_item_id: Optional[str] = None,
sort_order: int = 0, sort_order: int = 0,
target_date: Optional[date] = None, target_date: Optional[date] = None,
archetype_key: Optional[str] = None,
user_id: Optional[str] = None, user_id: Optional[str] = None,
) -> dict[str, Any]: ) -> dict[str, Any]:
title = title.strip() title = title.strip()
@ -234,9 +236,15 @@ def create_project(
raise ValueError("Titel ist erforderlich") raise ValueError("Titel ist erforderlich")
_validate_status(status) _validate_status(status)
_validate_container_kind(container_kind) _validate_container_kind(container_kind)
if not get_initiative(tenant_id=tenant_id, initiative_id=initiative_id): initiative = get_initiative(tenant_id=tenant_id, initiative_id=initiative_id)
if not initiative:
raise ValueError("Initiative nicht gefunden") raise ValueError("Initiative nicht gefunden")
resolved_archetype = archetype_key or mirror_project_archetype_key(
initiative["archetype_key"]
)
validate_archetype_key(entity_type="project", archetype_key=resolved_archetype)
conn = get_connection() conn = get_connection()
try: try:
with conn.cursor(cursor_factory=RealDictCursor) as cur: with conn.cursor(cursor_factory=RealDictCursor) as cur:
@ -257,10 +265,10 @@ def create_project(
f""" f"""
INSERT INTO projects ( INSERT INTO projects (
tenant_id, initiative_id, parent_project_id, container_kind, tenant_id, initiative_id, parent_project_id, container_kind,
title, description, status, archetype_key, title, description, status,
roadmap_item_id, sort_order, target_date roadmap_item_id, sort_order, target_date
) )
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
RETURNING {_PROJECT_COLUMNS} RETURNING {_PROJECT_COLUMNS}
""", """,
( (
@ -268,6 +276,7 @@ def create_project(
initiative_id, initiative_id,
parent_project_id, parent_project_id,
container_kind, container_kind,
resolved_archetype,
title, title,
description, description,
status, status,

View File

@ -100,6 +100,8 @@ def ensure_steering_context(
initiative_id: str, initiative_id: str,
initial_state: Optional[str] = None, initial_state: Optional[str] = None,
user_id: Optional[str] = None, user_id: Optional[str] = None,
method_key: Optional[str] = None,
lifecycle_metadata: Optional[dict[str, Any]] = None,
) -> dict[str, Any]: ) -> dict[str, Any]:
existing = get_steering_context(tenant_id=tenant_id, initiative_id=initiative_id) existing = get_steering_context(tenant_id=tenant_id, initiative_id=initiative_id)
if existing: if existing:
@ -113,6 +115,16 @@ def ensure_steering_context(
) )
validate_lifecycle_state(state) validate_lifecycle_state(state)
resolved_method = method_key or DEFAULT_METHOD_KEY
from steering.methods.registry import get_method
method = get_method(resolved_method)
if not method:
resolved_method = DEFAULT_METHOD_KEY
method = get_method(resolved_method)
method_version = method.version if method else DEFAULT_METHOD_VERSION
metadata = lifecycle_metadata or {}
conn = get_connection() conn = get_connection()
try: try:
with conn.cursor(cursor_factory=RealDictCursor) as cur: with conn.cursor(cursor_factory=RealDictCursor) as cur:
@ -129,10 +141,10 @@ def ensure_steering_context(
( (
tenant_id, tenant_id,
initiative_id, initiative_id,
DEFAULT_METHOD_KEY, resolved_method,
DEFAULT_METHOD_VERSION, method_version,
state, state,
Json({}), Json(metadata),
), ),
) )
row = _serialize_row(dict(cur.fetchone())) row = _serialize_row(dict(cur.fetchone()))
@ -144,7 +156,11 @@ def ensure_steering_context(
"steering_context.created", "steering_context.created",
user_id=user_id, user_id=user_id,
tenant_id=tenant_id, tenant_id=tenant_id,
details={"initiative_id": initiative_id, "lifecycle_state": state}, details={
"initiative_id": initiative_id,
"lifecycle_state": state,
"method_key": resolved_method,
},
) )
return row return row
@ -250,10 +266,25 @@ def create_context_for_new_initiative(
tenant_id: str, tenant_id: str,
initiative_id: str, initiative_id: str,
user_id: Optional[str] = None, user_id: Optional[str] = None,
archetype_key: str = "initiative.generic",
method_profile_key: Optional[str] = None,
) -> dict[str, Any]: ) -> dict[str, Any]:
from entity_archetypes.registry import resolve_default_method_key
from method_profiles.registry import resolve_method_for_profile
method_key = resolve_default_method_key(archetype_key)
lifecycle_metadata: dict[str, Any] = {}
if method_profile_key:
profile_method = resolve_method_for_profile(method_profile_key)
if profile_method:
method_key = profile_method
lifecycle_metadata["method_profile_key"] = method_profile_key
return ensure_steering_context( return ensure_steering_context(
tenant_id=tenant_id, tenant_id=tenant_id,
initiative_id=initiative_id, initiative_id=initiative_id,
initial_state="intake", initial_state="intake",
user_id=user_id, user_id=user_id,
method_key=method_key,
lifecycle_metadata=lifecycle_metadata or None,
) )

View File

@ -1,9 +1,15 @@
"""Adaptive Steering Core — AP1.0 Foundation.""" """Adaptive Steering Core — AP1.0 Foundation + AP2.0 methods."""
from __future__ import annotations from __future__ import annotations
from steering.hooks.registry import register_builtin_hooks from steering.hooks.registry import register_builtin_hooks
from steering.methods.registrations import generic_operating, product_milestone_driven from steering.methods.registrations import (
ap20_method_stubs,
continuous_product,
generic_operating,
product_milestone_driven,
program_delivery,
)
from steering.strategies.next_action import register_builtin_strategies from steering.strategies.next_action import register_builtin_strategies
@ -13,6 +19,9 @@ def bootstrap_steering() -> None:
register_builtin_strategies() register_builtin_strategies()
generic_operating.register() generic_operating.register()
product_milestone_driven.register() product_milestone_driven.register()
program_delivery.register()
continuous_product.register()
ap20_method_stubs.register()
bootstrap_steering() bootstrap_steering()

View File

@ -0,0 +1,70 @@
"""Shared registration helper for AP2.0 method stubs."""
from __future__ import annotations
from steering.lifecycle.states import STANDARD_LIFECYCLE_STEPS
from steering.methods.registry import MethodDefinition, get_method, register_method
_PRODUCT_LIKE_STEPS = (
"intake",
"method_selection",
"structure_setup",
"planning",
"action_selection",
"assignment",
"waiting",
"result_intake",
"validation",
"review",
"adaptation",
"closure",
)
_LIGHT_STEPS = (
"intake",
"structure_setup",
"action_selection",
"assignment",
"waiting",
"review",
"adaptation",
"closure",
)
def register_stub_method(
*,
key: str,
label: str,
description: str,
next_action_strategy_key: str = "default",
lifecycle_steps: tuple[str, ...] | None = None,
) -> None:
if get_method(key):
return
register_method(
MethodDefinition(
key=key,
version="0.1.0",
label=label,
description=description,
default_lifecycle_steps=lifecycle_steps or STANDARD_LIFECYCLE_STEPS,
next_action_strategy_key=next_action_strategy_key,
)
)
def register_product_like_method(
*,
key: str,
label: str,
description: str,
next_action_strategy_key: str,
) -> None:
register_stub_method(
key=key,
label=label,
description=description,
next_action_strategy_key=next_action_strategy_key,
lifecycle_steps=_PRODUCT_LIKE_STEPS,
)

View File

@ -0,0 +1,50 @@
"""AP2.0a — remaining method stubs."""
from __future__ import annotations
from steering.methods.registrations._helpers import register_stub_method
def register() -> None:
register_stub_method(
key="maturity_progression",
label="Reifegrad-Entwicklung",
description="Stufen, Routinen, historische Entwicklung",
next_action_strategy_key="default",
)
register_stub_method(
key="sequential_dependency",
label="Sequenzielle Abhängigkeit",
description="Graph-Pfade, kritischer Pfad (read model)",
next_action_strategy_key="default",
)
register_stub_method(
key="recurring_control",
label="Rhythmus-Steuerung",
description="Dauerprogramm, fällig/überfällig, Abweichungen",
next_action_strategy_key="default",
)
register_stub_method(
key="queue_pull",
label="Inbox / Queue",
description="Pull oder Empfehlung aus Queue",
next_action_strategy_key="default",
)
register_stub_method(
key="agile_iteration",
label="Iterations-Zeitbox",
description="Sprint/work_cycle Profil auf Product/Programm",
next_action_strategy_key="default",
)
register_stub_method(
key="dispute_procedure",
label="Verfahren / Konflikt",
description="Reaktive Steuerung, Fristen, Entscheidungen",
next_action_strategy_key="default",
)
register_stub_method(
key="chapter_based_progression",
label="Kapitel-Entwicklung",
description="Inhaltliche Progression, Reviews",
next_action_strategy_key="default",
)

View File

@ -0,0 +1,14 @@
"""Built-in method: continuous_product — AP2.0a."""
from __future__ import annotations
from steering.methods.registrations._helpers import register_product_like_method
def register() -> None:
register_product_like_method(
key="continuous_product",
label="Produkt (kontinuierlich)",
description="Kontinuierlicher Betrieb — Ist zuerst, Plan als Orientierung",
next_action_strategy_key="continuous_product",
)

View File

@ -0,0 +1,14 @@
"""Built-in method: program_delivery — AP2.0a."""
from __future__ import annotations
from steering.methods.registrations._helpers import register_product_like_method
def register() -> None:
register_product_like_method(
key="program_delivery",
label="Programm (begrenzt)",
description="Meilenstein- und gate-orientierte Steuerung mit Abschluss",
next_action_strategy_key="program_delivery",
)

View File

@ -2,10 +2,18 @@
from __future__ import annotations from __future__ import annotations
from steering.strategies.next_action.continuous_product import (
continuous_product_strategy,
register_continuous_product_strategy,
)
from steering.strategies.next_action.default_strategy import default_strategy from steering.strategies.next_action.default_strategy import default_strategy
from steering.strategies.next_action.product_milestone_driven import ( from steering.strategies.next_action.product_milestone_driven import (
product_milestone_strategy, product_milestone_strategy,
) )
from steering.strategies.next_action.program_delivery import (
program_delivery_strategy,
register_program_delivery_strategy,
)
from steering.strategies.next_action.registry import ( from steering.strategies.next_action.registry import (
get_next_action_strategy, get_next_action_strategy,
register_next_action_strategy, register_next_action_strategy,
@ -16,3 +24,5 @@ def register_builtin_strategies() -> None:
for strategy in (default_strategy, product_milestone_strategy): for strategy in (default_strategy, product_milestone_strategy):
if not get_next_action_strategy(strategy.key): if not get_next_action_strategy(strategy.key):
register_next_action_strategy(strategy) register_next_action_strategy(strategy)
register_program_delivery_strategy()
register_continuous_product_strategy()

View File

@ -0,0 +1,114 @@
"""Continuous product NextAction strategy — AP2.0a (Ist zuerst)."""
from __future__ import annotations
from typing import Any
from db import get_connection
from psycopg2.extras import RealDictCursor
from steering.signals import default_rules
from steering.strategies.next_action.default_strategy import DefaultNextActionStrategy
from steering.strategies.next_action.registry import (
get_next_action_strategy,
register_next_action_strategy,
)
from tenant_context import TenantContext
_default = DefaultNextActionStrategy()
_OPEN_ACTION = ("open", "ready", "in_progress", "blocked", "review_required")
class ContinuousProductStrategy:
key = "continuous_product"
def evaluate(
self,
ctx: TenantContext,
*,
initiative_id: str | None = None,
limit: int = 10,
) -> list[dict[str, Any]]:
if limit < 1:
limit = 1
if not initiative_id:
return _default.evaluate(ctx, limit=limit)
candidates: list[dict[str, Any]] = []
conn = get_connection()
try:
with conn.cursor(cursor_factory=RealDictCursor) as cur:
cur.execute(
"""
SELECT
'action' AS kind,
a.title AS title,
'Offenes Arbeitspaket priorisieren' AS summary,
a.initiative_id,
a.id AS action_id,
NULL::uuid AS backlog_item_id,
'open_action_priority' AS reason_code,
'Als Nächstes ausführen' AS recommended_action
FROM actions a
WHERE a.tenant_id = %s AND a.initiative_id = %s
AND a.status = ANY(%s)
ORDER BY
CASE a.status
WHEN 'blocked' THEN 0
WHEN 'review_required' THEN 1
WHEN 'in_progress' THEN 2
WHEN 'ready' THEN 3
ELSE 4
END,
CASE a.priority WHEN 'critical' THEN 0 WHEN 'high' THEN 1 ELSE 2 END,
a.due_at ASC NULLS LAST,
a.updated_at DESC
LIMIT %s
""",
(ctx.tenant_id, initiative_id, list(_OPEN_ACTION), limit),
)
for row in cur.fetchall():
item = dict(row)
item["initiative_id"] = str(item["initiative_id"])
item["action_id"] = str(item["action_id"])
candidates.append(item)
finally:
conn.close()
remaining = limit - len(candidates)
if remaining > 0:
from steering.strategies.next_action.product_milestone_driven import (
ProductMilestoneDrivenStrategy,
)
gate_items = ProductMilestoneDrivenStrategy().evaluate(
ctx, initiative_id=initiative_id, limit=remaining
)
for item in gate_items:
if item.get("kind") == "review_milestone":
candidates.append(item)
remaining -= 1
if remaining <= 0:
break
if len(candidates) < limit:
rest = default_rules.get_next_action_candidates_for_initiative(
ctx, initiative_id=initiative_id, limit=limit - len(candidates)
)
seen = {c.get("action_id") for c in candidates if c.get("action_id")}
for item in rest:
if item.get("action_id") and item["action_id"] in seen:
continue
candidates.append(item)
if len(candidates) >= limit:
break
return candidates[:limit]
continuous_product_strategy = ContinuousProductStrategy()
def register_continuous_product_strategy() -> None:
if not get_next_action_strategy(continuous_product_strategy.key):
register_next_action_strategy(continuous_product_strategy)

View File

@ -0,0 +1,28 @@
"""Program delivery NextAction strategy — AP2.0a (Gate-Horizont)."""
from __future__ import annotations
from steering.strategies.next_action.product_milestone_driven import (
ProductMilestoneDrivenStrategy,
)
from steering.strategies.next_action.registry import (
get_next_action_strategy,
register_next_action_strategy,
)
_strategy = ProductMilestoneDrivenStrategy()
class ProgramDeliveryStrategy:
key = "program_delivery"
def evaluate(self, ctx, *, initiative_id=None, limit=10):
return _strategy.evaluate(ctx, initiative_id=initiative_id, limit=limit)
program_delivery_strategy = ProgramDeliveryStrategy()
def register_program_delivery_strategy() -> None:
if not get_next_action_strategy(program_delivery_strategy.key):
register_next_action_strategy(program_delivery_strategy)

View File

@ -49,7 +49,11 @@ def test_list_entity_archetypes(client):
) )
assert res.status_code == 200 assert res.status_code == 200
keys = {item["key"] for item in res.json()} keys = {item["key"] for item in res.json()}
assert keys == {"initiative.generic", "initiative.program", "initiative.product"} assert "initiative.generic" in keys
assert "initiative.program" in keys
assert "initiative.product" in keys
assert "initiative.maturity_journey" in keys
assert "initiative.content_project" in keys
def test_invalid_archetype_rejected(client): def test_invalid_archetype_rejected(client):

View File

@ -0,0 +1,104 @@
"""AP2.0 — Method registry, Archetyp defaults, Project mirror."""
from __future__ import annotations
from auth import AUTH_HEADER
from steering.methods.registry import list_methods
from tests.factories import provision_user_in_tenant
from tests.test_initiatives_actions import _auth, _create_initiative, _login
def test_ap20_all_methods_registered():
keys = {m.key for m in list_methods()}
assert "generic_operating" in keys
assert "product_milestone_driven" in keys
assert "program_delivery" in keys
assert "continuous_product" in keys
assert "maturity_progression" in keys
assert "chapter_based_progression" in keys
assert "agile_iteration" in keys
def test_product_initiative_gets_continuous_product_method(client):
user = provision_user_in_tenant(tenant_role="member")
token = _login(client, user)
created = _create_initiative(
client,
token,
title="Kairo Product",
archetype_key="initiative.product",
)
assert created.status_code == 201
initiative_id = created.json()["id"]
snap = client.get(
f"/api/initiatives/{initiative_id}/steering-snapshot",
headers=_auth(token),
)
assert snap.status_code == 200
body = snap.json()
assert body["method_key"] == "continuous_product"
assert body["archetype_key"] == "initiative.product"
assert body.get("archetype_label")
assert body.get("steering_guidance")
def test_program_initiative_gets_program_delivery_method(client):
user = provision_user_in_tenant(tenant_role="member")
token = _login(client, user)
created = _create_initiative(
client,
token,
title="Release Program",
archetype_key="initiative.program",
)
assert created.status_code == 201
initiative_id = created.json()["id"]
ctx = client.get(
f"/api/steering/initiatives/{initiative_id}/context",
headers=_auth(token),
)
assert ctx.status_code == 200
assert ctx.json()["method_key"] == "program_delivery"
def test_project_inherits_mirror_archetype(client):
user = provision_user_in_tenant(tenant_role="member")
token = _login(client, user)
created = _create_initiative(
client,
token,
title="Mirror Test",
archetype_key="initiative.product",
)
initiative_id = created.json()["id"]
project = client.post(
f"/api/initiatives/{initiative_id}/projects",
json={"title": "Product Stream"},
headers=_auth(token),
)
assert project.status_code == 201
assert project.json()["archetype_key"] == "project.product"
def test_entity_archetypes_include_ap20_portfolio(client):
user = provision_user_in_tenant(tenant_role="member")
token = _login(client, user)
res = client.get(
"/api/entity-archetypes?entity_type=initiative",
headers=_auth(token),
)
assert res.status_code == 200
keys = {item["key"] for item in res.json()}
assert "initiative.maturity_journey" in keys
assert "initiative.content_project" in keys
assert "initiative.product" in keys
sample = next(i for i in res.json() if i["key"] == "initiative.product")
assert sample.get("default_method_key") == "continuous_product"

View File

@ -1,3 +1,3 @@
APP_VERSION = "0.17.0-ap1.5d" APP_VERSION = "0.18.0-ap2.0"
DB_SCHEMA_VERSION = "018" DB_SCHEMA_VERSION = "019"
APP_NAME = "jinkendo-kairo" APP_NAME = "jinkendo-kairo"

View File

@ -0,0 +1,303 @@
# ADP — Archetyp- & Methoden-Katalog v0.1
> **⚠ Superseded (2026-07-10):** Verwende [`ADP_Archetype_and_Method_Catalog_v0.2.md`](ADP_Archetype_and_Method_Catalog_v0.2.md) — enthält B3 Agile Iteration, Steuerungs-Matrix, Sprint-Semantik.
**Status:** superseded — siehe v0.2
**Stand:** 2026-07-10
**Bezug:** `Kairo_MVP_Definition_v0.3.md`, `ADP_AP1_10_Initiative_Archetypes_and_Entity_Field_System_v0.1.md`, `Kairo_Method_Design_Principles_v0.1.md`
**Auslöser:** Vorhaben jenseits von Software (Gewohnheit, Haushalt, Queue, Verfahren); Archetypen auf Initiative- **und** Project-Ebene; Steuerung methodengebunden
---
## 1. Problem
Heute:
- `archetype_key` nur auf **Initiative**, drei Seeds (`generic`, `program`, `product`) — Dev-Sprache
- Archetyp ändert **Felder**, nicht **Steuerungsmethode**, Plan-Sicht oder Next-Action-Logik
- `project.archetype_key` **deferred** (ADP AP1.10)
- Nutzer mit heterogenem Portfolio (privat + beruflich) sieht **eine flache Vorhabenliste** und keine methodengerechte Führung
**Ziel:** Archetyp = Eintritt in ein **Steuerungspaket** (Methode + Struktur-Empfehlung + UI-Profil + EFS), nicht nur Label.
---
## 2. Entscheidung
### 2.1 Zwei Registry-Ebenen
| Ebene | Tabelle / Registry | Zweck |
|-------|-------------------|--------|
| **Initiative-Archetyp** | `entity_archetypes` + EFS | Welches **Programm/Vorhaben** ist das? Default-`method_key`, Profilfelder |
| **Project-Archetyp** | `entity_archetypes` (`entity_type=project`) + EFS | Welche **Rolle** hat dieser Strang im Vorhaben? |
Bestehende Initiativen: Default `initiative.generic` + `generic_operating` — unverändert.
### 2.2 Archetyp bindet Default-Methode
Jeder Initiative-Archetyp referenziert genau eine **Default-Steuerungsmethode** (`steering_context.method_key`). Nutzer kann später wechseln (mit Audit), MVP: Default reicht.
Methoden sind **registrierte Pakete** in `backend/steering/methods/` — keine Hardcodierung in React.
### 2.3 UI-Profil (kein neues OM-Objekt)
Pro Archetyp: **dominante Modus-Ansichten** und **versteckte** Patterns (z. B. Queue zeigt Pull-Queue, nicht Gate-Graph).
Speicherung MVP: Seed-JSON in Registry-Sync (`ui_profile_json`), nicht ad-hoc im Frontend.
---
## 3. Katalog — Initiative-Archetypen
| `archetype_key` | Label (DE) | Beispiel | Default-Methode | MVP-Stufe |
|-----------------|------------|----------|-------------------|-----------|
| `initiative.generic` | Allgemeines Vorhaben | Fallback | `generic_operating` | ✓ (bestehend) |
| `initiative.maturity_journey` | Reifegrad-Entwicklung | Spagat können | `maturity_progression` | **A** |
| `initiative.linear_project` | Lineares Vorhaben | Neue Küche | `sequential_dependency` | **A** |
| `initiative.recurring_program` | Dauerprogramm / Rhythmus | Haus in Ordnung | `recurring_control` | **B** |
| `initiative.support_queue` | Queue / Supportdesk | Tickets, Pool | `queue_pull` | **B** |
| `initiative.program` | Programm / Mega-Vorhaben | Kairo Gesamt | `product_milestone_driven` | **A** (bestehend, umbenannt semantisch) |
| `initiative.product` | Produkt / Release | Release-Track | `product_milestone_driven` | **B** |
| `initiative.dispute_case` | Verfahren / Konflikt | Miterstreit | `dispute_procedure` | **C** (Katalog) |
**Hinweis:** `initiative.program` / `initiative.product` bleiben technisch; semantisch = agile/technische Entwicklung (B2).
---
## 4. Katalog — Project-Archetypen
| `archetype_key` | Label (DE) | Typische Initiative | Rolle |
|-----------------|------------|---------------------|--------|
| `project.generic` | Allgemeines Projekt | alle | Standard-Container |
| `project.maturity_lane` | Reifegrad-Spur | maturity_journey | Übungs-/Entwicklungsspur pro Körperregion o.ä. |
| `project.primary_chain` | Primärstrang | linear_project | Kritischer Pfad (Wasserfall-Hauptlinie) |
| `project.companion_track` | Begleitstrang | linear_project | Parallele Nebenaktivitäten |
| `project.recurring_domain` | Bereich mit Rhythmus | recurring_program | Küche, Garten, Kind — Recurring-Owner |
| `project.queue_stream` | Ticket-Strom | support_queue | Kategorie/Team-Queue |
| `project.release_stream` | Release/Phase | program, product | Technischer Strang |
| `project.dispute_track` | Verfahrensstrang | dispute_case | z. B. „Gericht“, „Mediation“ |
Migration: `projects.archetype_key VARCHAR(64) DEFAULT 'project.generic'` (AP2.0b).
---
## 5. Steuerungsmethoden (Registry-Ziel)
| `method_key` | Status heute | Kurzbeschreibung | Next-Action-Fokus |
|--------------|--------------|------------------|-------------------|
| `generic_operating` | ✓ registriert | Leichte Struktur, Gates optional | offene Actions, Backlog-Triage |
| `product_milestone_driven` | ✓ registriert | Gate-horizont, Meilenstein | Gate + offene AP am Gate |
| `maturity_progression` | ○ Ziel | Reifegrad-Stufen, Übungswechsel | **heutige Übung** + Stufen-Kriterium |
| `sequential_dependency` | ○ Ziel | Linearer Graph, Begleitstränge | **nächster freier Schritt** am kritischen Pfad |
| `recurring_control` | ○ Ziel | Dauerprogramm, Assignments | **fällig / überfällig** pro Actor, nicht Gesamtliste |
| `queue_pull` | ○ Ziel | Pool, Selbstwahl oder Empfehlung | **1 Empfehlung** oder gewähltes Item |
| `dispute_procedure` | ○ Katalog | Phasen, Fristen, Iterationen | **nächste Frist / Entscheidung** |
Neue Methoden: nur via `steering/methods/registrations/*.py` + Tests — siehe `Kairo_Method_Design_Principles_v0.1.md`.
---
## 6. Archetyp-Detail (PO-Spezifikation)
### A1 — `initiative.maturity_journey` (Spagat)
**Plan:**
- `RoadmapItem` mit `item_type=maturity_stage` (Reifegrad-Stufen)
- Kriterien pro Stufe (Checkliste AP1.4b)
**Ist:**
- `RecurringElement` für Übungsroutine **pro Stufe**
- Bei Verify `reached` → Recurring-Set wechseln (Hook/Service, AP2.0d)
**Steuerung:**
- Next Action: heutige Recurring-Instanz + Hinweis „Stufe X, Kriterium Y offen“
- Attention: Stagnation (keine Recurring-Erfüllung), Stufe ohne Fortschritt
**EFS (Seed):**
- `current_body_focus` (text), `training_frequency` (enum), `progress_notes` (longtext)
**UI-Profil:** Kontrolle dominant; Plan = Stufen; Ausführen = heute; Gates-Graph **aus**
---
### A2 — `initiative.linear_project` (Küche)
**Plan:**
- `project.primary_chain` + `project.companion_track`
- Gates entlang Primärstrang; `roadmap_item_dependencies` (AP1.4d/13)
**Ist:**
- Actions an Blatt-Projects / Initiative
- Begleit-APs parallel
**Steuerung:**
- Next Action: nächster **ready** Schritt am kritischen Pfad (Graph Engine read model)
- Attention: Blocker auf Pfad, Gate at risk, überfälliges `target_date`
**EFS:**
- `budget_summary`, `primary_contractor`, `target_completion` (date)
**UI-Profil:** Plan (Graph/Liste) + Kontrolle; Recurring **aus**
---
### A3 — `initiative.recurring_program` (Haus)
**Plan:**
- optional `project.recurring_domain` pro Bereich/Person
- wenig / keine Gates (`generic_operating`-light)
**Ist:**
- `RecurringElement` + `ActionAssignment` pro Familien-Actor
- Roll-up: überfällige Recurring → Attention
**Steuerung:**
- Next Action: **eigene** fällige Recurring (+ optional eine aus Pool „Haus“)
- Cockpit: wer ist überfällig — **nicht** alle Tasks aller Personen
**EFS:**
- `household_members` (longtext / später actor_ref_list), `cadence_default` (enum)
**UI-Profil:** Ausführen + Team; Plan minimal
---
### B1 — `initiative.support_queue` (Supportdesk)
**Plan:**
- flacher Eingang → triage → Queue
- optional `project.queue_stream` pro Kategorie
**Ist:**
- Actions als Tickets; Status open/ready/in_progress
- Actor-Gruppe: Pull-Berechtigung
**Steuerung:**
- Next Action: **Empfehlung** aus Queue-Strategie oder selbst gewählt (Pull)
- Attention: SLA, unassigned high-priority
**EFS:**
- `queue_policy` (enum: pull, assign, hybrid), `sla_hours` (number)
**UI-Profil:** Ausführen (Queue) dominant; Plan = Eingang
---
### B2 — `initiative.program` / `initiative.product` (Agile / Kairo)
Bestehendes Modell — im Katalog **explizit** als technische Entwicklung verankert, nicht als einziger Typ.
**UI-Profil:** Plan (Gates) + Kontrolle (Snapshot) + Ausführen
---
### C1 — `initiative.dispute_case` (Miterstreit)
**Plan:**
- Phasen-Gates: Auslöser → Reaktion → … → Einigung → Abschluss
- Iterationen (Reopen / neue Runde) mit Decision-Pflicht
**Ist:**
- Decisions (Argumentationsketten), Evidence (Dokumente), Fristen auf Gates/Actions
- optional `project.dispute_track` (Anwalt, Gericht, Mediation)
**Steuerung:**
- Next Action: **nächste Frist** oder **offene Entscheidung**
- Attention: Frist läuft ab, fehlende Evidence
**EFS:**
- `counterparty`, `legal_counsel_actor_ref`, `next_deadline` (date), `case_reference` (text)
**MVP-Stufe C:** Katalog + Profilfelder + generische Gates; spezialisierte UI post-MVP
---
## 7. Plan-/Ist-Muster (übergreifend)
```text
Eingang Plan (optional) Ist Steuerung
maturity_journey selten maturity_stages Recurring heutige Übung
linear_project selten Gate-Graph Actions kritischer Pfad
recurring_program selten Domains Recurring fällig/heute
support_queue triage Queue-Streams Actions Pull/Empfehlung
program/product Backlog Gates Actions+Tasks Gate+Next AP
dispute_case Eingang Phasen-Gates Decisions+Ev. Frist/Entscheidung
```
---
## 8. Scope Lock
| Verboten | Erlaubt |
|----------|---------|
| React-Formulare pro Archetyp hardcoden | FieldRenderer + Registry |
| OM-Tabelle `disputes`, `habits`, … | EFS + bestehende OM-Entitäten |
| Steering-Heuristiken in Routern | `backend/steering/` |
| Alle Methoden voll implementieren vor A-Abnahme | Stubs + A1/A2/B2 zuerst |
| Archetyp ohne `method_key`-Bindung | Seed + Sync |
---
## 9. Implementierungspakete
```text
AP2.0a Method-Stubs registrieren (4 neue + dispute stub)
AP2.0b entity_archetypes Seeds (Initiative + Project); projects.archetype_key; EFS field_definitions
AP2.0c Kontrolle-Lagebild: method_key, lifecycle, next action, attention (UI)
AP2.0d Next-Action-Strategien: maturity, sequential, recurring, queue (minimal)
AP2.0e Recurring-Stufenwechsel bei maturity_stage reached (A1)
AP2.1 Validation Report v0.3 — Referenz A1, A2, B2 mit echten Daten
```
Erweitert AP1.10 — **ersetzt nicht** EFS-Architektur, nutzt sie.
---
## 10. Risiko
| Risiko | Mitigation |
|--------|------------|
| Methoden-Overengineering | Stubs + eine Strategie pro A-Archetyp |
| dispute_case zu groß | Stufe C, nur Katalog im MVP |
| Recurring-Stufenwechsel komplex | AP2.0e nach A1-Grundlage |
| Todo-Wand trotz Archetyp | MVP v0.3 UI-Regeln + Review-Pflicht |
---
## 11. PO-Freigabe
- [ ] Acht Initiative-Archetypen (+ generic) akzeptiert oder korrigiert
- [ ] Project-Archetypen akzeptiert
- [ ] Methoden-Keys akzeptiert
- [ ] MVP-Stufen A/B/C akzeptiert
- [ ] AP2.0-Reihenfolge freigegeben
---
## Referenzen
- `docs/product/Kairo_MVP_Definition_v0.3.md`
- `docs/architecture/ADP_AP1_10_Initiative_Archetypes_and_Entity_Field_System_v0.1.md`
- `docs/architecture/Kairo_Target_Architecture_Method_Driven_Adaptive_Steering_Core_v0.1.md`
- `backend/steering/methods/registrations/generic_operating.py`
- `backend/steering/methods/registrations/product_milestone_driven.py`

View File

@ -0,0 +1,601 @@
# ADP — Archetyp- & Methoden-Katalog v0.2
**Status:** PO-freigegeben
**Stand:** 2026-07-10 (Archetypen-, Project- und Methoden-Schichten; Vier-Schichten-Modell)
**Bezug:** `Kairo_MVP_Definition_v0.3.md`, `ADP_AP1_10_Initiative_Archetypes_and_Entity_Field_System_v0.1.md`, `Kairo_Method_Design_Principles_v0.1.md`, `Kairo_Canonical_Operating_Model_v0.2.md`
**Ersetzt:** `ADP_Archetype_and_Method_Catalog_v0.1.md` (Inhalt konsolidiert + B3 Agile Iteration)
**Auslöser:** Vorhaben jenseits von Software; heterogenes Portfolio; **Agile (Backlog, Sprint, Release)** vollständig im Katalog verankern
---
## 1. Problem
Heute:
- `archetype_key` nur auf **Initiative**, drei Seeds (`generic`, `program`, `product`) — Dev-Sprache
- Archetyp ändert **Felder**, nicht **Steuerungsmethode**, Plan-Sicht oder Next-Action-Logik
- `project.archetype_key` **deferred** (ADP AP1.10)
- **Agile** ist implizit in B2 (`product_milestone_driven`) — **Release-/Gate-Agile**, nicht **Iterations-Agile** (Sprint, Sprint-Backlog)
- Nutzer mit heterogenem Portfolio sieht **eine flache Vorhabenliste** und keine methodengerechte Führung
**Ziel:** Generische **Archetypen** liefern den **Methodenbaukasten** (Default-Methode, Felder, UI); **Ausprägungen** konkretisieren (Buch schreiben, Kumite, …). Die **Magie** (automatische Steuerung, Monitoring, KI, Gitea, Vibe-Coder) sitzt in der **Methoden-Modulregistrierung** auf dem Standard-Framework — nicht im Archetyp hardcodiert.
---
## 2. Entscheidung
### 2.0 Vier Schichten — wo die Magie sitzt — **PO 2026-07-10**
```text
┌─────────────────────────────────────────────────────────────────┐
│ Schicht 4 (später) Integrationen & Agenten │
│ MCP/Vibe-Coder, Gitea, Webhooks — an Hook Slugs gebunden │
├─────────────────────────────────────────────────────────────────┤
│ Schicht 3 Ausprägung (Method Profile / Domain Template) │
│ „Buch schreiben“, „Karate Kumite“ — Felder, Vorbefüllung, │
│ Kategorien, Mitwirkende, Struktur-Seeds │
├─────────────────────────────────────────────────────────────────┤
│ Schicht 2 Generischer Archetyp (entity_archetypes + EFS) │
│ maturity_journey, product, linear_project, … │
│ → Default method_key, Feldprofil, UI-Profil (Methodenbaukasten)│
├─────────────────────────────────────────────────────────────────┤
│ Schicht 1 Methode (Method Registry — Steuerungsmodul) │
│ register_method: Lifecycle, Hooks, Builder, Strategies, Signals│
│ → automatische Steuerung, Planung, Monitoring, Next Action │
├─────────────────────────────────────────────────────────────────┤
│ Schicht 0 Standard-Framework (Adaptive Steering Core) │
│ backend/steering/, OM, TenantContext, Audit, Operational API │
└─────────────────────────────────────────────────────────────────┘
```
| Schicht | Was | MVP | Später |
|---------|-----|-----|--------|
| **0 Framework** | Steering Core, OM, Capabilities | ✓ Foundation | Waiting, Runtime |
| **1 Methode** | Modul in `steering/methods/registrations/` | Stubs + 12 Strategien | Volle Profiles, Workflow-Fragmente |
| **2 Archetyp** | `entity_archetypes` + EFS + `ui_profile_json` | Seeds AP2.0b | Tenant-Templates |
| **3 Ausprägung** | `method_profile_key` + `configuration_json` + EFS-Seeds | Katalog + 12 Referenz-Seeds | Designer, Tenant-Kopien |
| **4 Integration** | Hooks → MCP, Gitea, Vibe-Coder (`/api/operational/`) | **eingefroren** | KI-gestützte Steuerung |
**PO-Regel:** Archetyp **beschreibt den Baukasten**, Ausprägung **beschreibt die konkrete Variante**. Keine Sonder-OM-Tabellen pro Ausprägung.
**Beispiele Ausprägungen (Schicht 3) — referenzieren generischen Archetyp:**
| `profile_key` (Ziel) | Archetyp (Schicht 2) | Methode (Schicht 1) | Liefert u. a. |
|----------------------|----------------------|----------------------|---------------|
| `maturity.karate_kumite` | `initiative.maturity_journey` | `maturity_progression` | 8 Fähigkeiten-Seed, Stufen-Raster, Coach-Rolle |
| `content.book_writing` | `initiative.content_project` | `chapter_based_progression` | Kapitel-Gliederung, Wortziel, Lector |
| `product.kairo_dev` | `initiative.product` | `continuous_product` + `agile_iteration` | Gate-Set, Sprint-Cadence, Agent-Actor |
| `recurring.household` | `initiative.recurring_program` | `recurring_control` | Domains, Score-Policy (AP2.0g) |
Speicherung Zielbild: `method_profiles` (tenant-scoped, siehe Target Architecture §15) + EFS `field_definitions` pro Archetyp/Profile; MVP: **Code-Seeds** in Registry-Sync.
**Integrationen (Schicht 4):** Methoden exponieren **Hook Slugs** (`on_next_action_requested`, `on_result_received`, …). Bindings:
- **Vibe-Coder / MCP** → Operational API + Hook-Handler (kein Prompt hardcoden)
- **Gitea** → Events → `result_intake` / Journey / Gate-Verify
- **KI** → Signal Engine / Next-Action-Vorschläge — **ersetzt nicht** Methoden-Strategie ohne Audit
Siehe `Kairo_Method_Design_Principles_v0.1.md`, `ADP_Operational_Actor_Interface_Vibe_Coder_v0.1.md`.
### 2.1 Zwei Registry-Ebenen (Archetyp Initiative + Project)
| Ebene | Tabelle / Registry | Zweck |
|-------|-------------------|--------|
| **Initiative-Archetyp** | `entity_archetypes` + EFS | Welches **Programm/Vorhaben** ist das? Default-`method_key`, Profilfelder |
| **Project-Archetyp** | `entity_archetypes` (`entity_type=project`) + EFS | Welche **Rolle** hat dieser Strang im Vorhaben? |
Bestehende Initiativen: Default `initiative.generic` + `generic_operating` — unverändert.
### 2.2 Archetyp → Default-Methode + optional Ausprägung
Jeder Archetyp referenziert:
```text
default_method_key # Schicht 1 — Steuerungsmodul
default_method_profile_key # Schicht 3 — optional, z. B. content.book_writing
efs_field_profile # Schicht 2/3 — Felder
ui_profile_json # dominante Modus-Ansichten
```
Nutzer/PO wählt bei Anlage: **Archetyp** (generisch) und optional **Ausprägung** (konkret). Project erbt + darf `method_key` / Profile **override** (§4.3).
Methoden = **registrierte Module** in `backend/steering/methods/` — keine Hardcodierung in React, keine Steuerung in Routern.
### 2.3 Methoden-Komposition (Product + Sprint)
**Release/Programm** und **Iterations-Zeitbox** sind **keine Gegensätze**:
| Methode | Horizont | Steuerungsfrage |
|---------|----------|-----------------|
| `program_delivery` (B2a) | Begrenztes Programm, Abschluss | „Was blockiert den nächsten Meilenstein?“ |
| `continuous_product` (B2b) | Dauerbetrieb, Wartung, Issues | „Was ist jetzt am wirksamsten — ohne fixes Ende?“ |
| `agile_iteration` (B3 Profil) | Sprint / `work_cycle` auf B2 | „Was ist der Schritt **in dieser Zeitbox**?“ |
**Komposition:** Kairo als **`initiative.product`** nutzt `continuous_product` **und** optional `work_cycle`**kein** eigener Archetyp `agile_team`. Sprint kann in Release/Product-Betrieb übergehen. PO + Vibe Coder; Kairo übernimmt Scrum-Master-Logik (Next Action, Attention).
Kein zweiter SteeringContext, kein paralleles OM.
### 2.4 Project-Archetyp: Spiegel der Initiative, Struktur separat — **PO 2026-07-10**
**Grundsatz:** Project-Archetypen **entsprechen** den Initiative-Archetypen (gleiche Familie, `project.*`-Prefix) — **kein** paralleles Typensystem (`primary_chain`, `maturity_lane`, …).
| Aspekt | Regel |
|--------|--------|
| **Default bei Anlage** | `project.archetype_key` = **abgeleitet** von `initiative.archetype_key` (Mapping 1:1) |
| **Abweichung erlaubt** | Project darf **andere Methode** (`method_key`) und **andere EFS-Felder** als die Initiative haben |
| **Struktur** | Abhängigkeiten, Pfade, Lanes, Domains → **Graph + Roadmap + Konfiguration**, nicht eigener Archetyp pro Pfadtyp |
| **`project.generic`** | Nur wenn **nichts** ableitbar — UI-Hinweis: *keine Steuerungsstruktur*; **Prefer inherit** |
**Beispiel Kumite (A1):** Initiative `maturity_journey` → Projects pro Fähigkeit (ebenfalls `maturity_journey`); Stufen = `maturity_stage`; Routinen = Recurring; **Voraussetzungen** = Graph-Kanten zwischen Stufen/Projects — kein Sondermodell „lane“.
**Beispiel Küche (A2):** Mehrere Haupt- und Nebenpfade; **kritischer Pfad** = **berechnetes** Read Model aus Graph + Status — nicht fest ein `primary_chain`-Objekt.
### 2.5 UI-Profil (kein neues OM-Objekt)
Pro Archetyp: **dominante Modus-Ansichten** und **versteckte** Patterns (z. B. Queue zeigt Pull-Queue, nicht Gate-Graph).
Speicherung MVP: Seed-JSON in Registry-Sync (`ui_profile_json`), nicht ad-hoc im Frontend.
---
## 3. Steuerungs-Landschaft — Vollständigkeits-Matrix
Diese Matrix ist die **Checkliste**, dass keine wesentliche Steuerungsform übersehen wird.
### 3.1 Initiative-Archetypen (Referenz-Portfolio)
| ID | `archetype_key` | Label (DE) | Beispiel | Default-Methode | MVP-Stufe |
|----|-----------------|------------|----------|-------------------|-----------|
| — | `initiative.generic` | Allgemeines Vorhaben | Fallback | `generic_operating` | ✓ (bestehend) |
| **A1** | `initiative.maturity_journey` | Reifegrad-Entwicklung | Spagat können | `maturity_progression` | **A** |
| **A2** | `initiative.linear_project` | Lineares Vorhaben | Neue Küche | `sequential_dependency` | **A** |
| **A3** | `initiative.recurring_program` | Dauerprogramm / Rhythmus | Haus in Ordnung | `recurring_control` | **B** |
| **B1** | `initiative.support_queue` | Queue / Supportdesk | Tickets, Pool | `queue_pull` | **B** |
| **B2a** | `initiative.program` | Programm (begrenzt) | Kairo-Release-Programm, Großprojekt mit Abschluss | `program_delivery` | **A** |
| **B2b** | `initiative.product` | Produkt (kontinuierlich) | Kairo-Betrieb, Wartung, Issues | `continuous_product` | **A** |
| **B3** | *(kein eigener Initiative-Archetyp)* | Sprint / Iteration | PO + Vibe-Coder-Zeitbox | `agile_iteration` als **Profil** auf B2 | **A** (Minimal) |
| **C1** | `initiative.dispute_case` | Verfahren / Konflikt | Miterstreit | `dispute_procedure` | **C** (Katalog) |
| **D1** | `initiative.content_project` | Inhalt / Kapitel | Buch, Konzept schreiben | `chapter_based_progression` | **B** |
**PO 2026-07-10 — Archetypen:** A1 ✓ · A2 ✓ · A3 ✓ (Score-Logik, siehe §5) · B1 ✓ · B2a/B2b getrennt · B3 kein eigener Typ · C1 Katalog · D1 in MVP Stufe B
**Hinweis B2/B3:** `program` vs. `product` = **unterschiedlicher Lifecycle** (begrenzt vs. kontinuierlich). Sprint/`work_cycle` hängt an **Product/Programm**, nicht an `initiative.agile_team`. Kairo-Setup: PO + Vibe Coder; „Scrum Master“ = Kairo-Steuerungslogik.
### 3.2 Steuerungsmethoden (Registry)
| `method_key` | Status heute | Archetyp(e) | Kurzbeschreibung | Next-Action-Fokus |
|--------------|--------------|-------------|------------------|-------------------|
| `generic_operating` | ✓ registriert | generic | Leichte Struktur, Gates optional | offene Actions, Backlog-Triage |
| `program_delivery` | ○ Ziel (Stub; heute: `product_milestone_driven`) | program | Begrenztes Programm, Phasen, Abschluss | Gate + AP am Horizont; **Closure** vorgesehen |
| `continuous_product` | ○ Ziel (Stub AP2.0a) | product | Kontinuierlicher Betrieb, Wartung, Issues | Nächster wirkungsvoller Schritt; **kein** fixes End-Gate |
| `agile_iteration` | ○ Ziel (Profil/Hook) | product, program | Zeitbox / Sprint auf Ist-Ebene | 13 Items im aktiven `work_cycle` |
| `product_milestone_driven` | ✓ registriert | *(Legacy-Seed → migrieren zu program/product)* | Meilenstein-orientiert | Gate + offene AP am Gate |
| `maturity_progression` | ○ Ziel | maturity_journey | Reifegrad-Stufen, Übungswechsel | **heutige Übung** + Stufen-Kriterium |
| `sequential_dependency` | ○ Ziel | linear_project | Linearer Graph, Begleitstränge | **nächster ready Schritt** am kritischen Pfad |
| `recurring_control` | ○ Ziel | recurring_program | Dauerprogramm, Assignments | **fällig / überfällig** pro Actor |
| `queue_pull` | ○ Ziel | support_queue | Pool, Selbstwahl oder Empfehlung | **1 Empfehlung** oder gewähltes Item |
| `dispute_procedure` | ○ Katalog | dispute_case | Phasen, Fristen, Iterationen | **nächste Frist / Entscheidung** |
| `chapter_based_progression` | ○ Katalog | content_project | Kapitel-Reihenfolge, Review-Gates | **nächstes Kapitel / Review** |
Neue Methoden: nur via `steering/methods/registrations/*.py` + Tests — siehe `Kairo_Method_Design_Principles_v0.1.md`.
### 3.3 RoadmapItem-Typen (Plan-Schicht)
Kanoniche Typen aus OM v0.2 — **keine eigenen Tabellen** pro Typ.
| `item_type` | Bedeutung | Primär-Archetyp | MVP |
|-------------|-----------|-----------------|-----|
| `milestone` | Meilenstein / Release-Punkt | program, product, linear_project | ✓ AP1.4 |
| `maturity_stage` | Reifegrad-Stufe | maturity_journey | A |
| `feature` | Feature-Landschaft (optional) | program, product | post-A |
| `review_gate` | Review / Quality Gate | program, product, content_project | ◐ |
| `chapter` | Kapitel / Abschnitt | content_project | **B** |
| `work_cycle` | **Sprint / Iteration / Zeitbox** | product, program | **A (B3)** |
| `phase` | Verfahrensphase | dispute_case | C |
**Sprint in Kairo** = `RoadmapItem(type=work_cycle)`, nicht eigene `sprints`-Tabelle.
### 3.4 Ist-Schicht — Was committet wird
| OM-Entität | Rolle | Nicht verwechseln mit |
|------------|-------|------------------------|
| `BacklogItem` | Eingang, noch nicht committet | Sprint-Backlog (Ist!) |
| `Action` | Committetes Arbeitspaket | Task |
| `Task` | Feingranularität unter Action | BacklogItem |
| `RecurringElement` | Rhythmus / Routine | Backlog, Sprint |
| `Decision` | Steuerungsentscheidung | Action |
| `Evidence` | Nachweis für Gate/DoD | Attachment-Dummy |
**Sprint-Backlog-Semantik (B3):**
- **Product Backlog** = `BacklogItem` (+ optional Gate-Link) — Plan-Eingang
- **Sprint Backlog** = `Action` (Status open/ready/in_progress) mit **`work_cycle_id`** (FK auf `roadmap_items.id` wo `item_type=work_cycle`)
- Commit aus Eingang → Action **mit** aktivem Zyklus = Sprint-Commit
- Abgeschlossener Sprint: Actions done/cancelled; Zyklus `reached` oder `closed`; Review optional via `Review`-Objekt
Migration: `actions.work_cycle_id UUID NULL REFERENCES roadmap_items(id)` (AP2.0f).
### 3.5 Agile-Begriffe — Abbildung in Kairo
| Scrum/Agile-Begriff | In Kairo | Status |
|---------------------|----------|--------|
| Product Backlog | `BacklogItem`, Plan → Eingang | ✓ implementiert |
| Sprint | `RoadmapItem(type=work_cycle)` | ○ Katalog + AP2.0f |
| Sprint Goal | `work_cycle.title` + optional EFS `sprint_goal` | ○ |
| Sprint Backlog | `Action.work_cycle_id` | ○ AP2.0f |
| Sprint Planning | Commit/Triage Eingang → Sprint-Actions | ○ |
| Daily / Standup | **kein Objekt** — Ausführen-Modus zeigt Next Action | bewusst |
| Sprint Review | `Review` + Gate optional | ◐ |
| Retrospective | `Review` / `Decision` | ◐ |
| Velocity / Burndown | — | **explizit post-MVP** |
| Kanban-Board | — | **explizit nicht Kern** |
| Story Points | EFS optional | post-MVP |
### 3.6 Explizit nicht im MVP-Kern (Anti-Scope)
Damit nichts „vergessen“ wirkt, aber klar **ausgeschlossen** ist:
| Thema | Warum nicht Kern |
|-------|------------------|
| Kanban-Board als Haupt-UI | Todo-Wand-Risiko; Queue (B1) deckt Pull ab |
| Velocity, Burndown, CFD | Reporting-Edge, nicht Steuerungskern |
| Scrum-Rituale als Workflow-Engine | Lifecycle + Review reicht |
| Jira/Linear-Import | post-MVP |
| `sprints`-Tabelle parallel zu RoadmapItem | Scope Lock — nur `work_cycle` |
| Mitai/Shinkan-Trainingslogik | Produktfamilien-Trennung |
| Billing, SSO, MCP/KI | eingefroren |
---
## 4. Katalog — Project-Archetypen — **PO-Neuausrichtung 2026-07-10**
### 4.1 Spiegel-Tabelle (1:1 zur Initiative)
Project-Registry **spiegelt** Initiative-Registry (`entity_archetypes`, `entity_type=project`):
| Initiative-Archetyp | Project-Archetyp (Default bei Anlage) | Anmerkung |
|---------------------|----------------------------------------|-----------|
| `initiative.generic` | `project.generic` | **Vermeiden** — lieber von Initiative erben |
| `initiative.maturity_journey` | `project.maturity_journey` | z. B. eine **Fähigkeit** (Kumite-Angriff) |
| `initiative.linear_project` | `project.linear_project` | Strang in einem Gesamtvorhaben |
| `initiative.recurring_program` | `project.recurring_program` | Domain **konfigurierbar** (Raum, Person, Thema) |
| `initiative.support_queue` | `project.support_queue` | Queue **unter** Product/Programm |
| `initiative.program` | `project.program` | Phase/Release-Strang |
| `initiative.product` | `project.product` | Stream unter Produkt (Feature, Ops, …) |
| `initiative.dispute_case` | `project.dispute_case` | Verfahrensstrang |
| `initiative.content_project` | `project.content_project` | Teil, Band, großer Block |
**Migration AP2.0b:** `projects.archetype_key VARCHAR(64) NULL` — bei INSERT Default = **Mirror** der Initiative, nicht blind `generic`.
### 4.2 Was **kein** Project-Archetyp ist (Struktur statt Label)
Diese Konzepte aus v0.2-Entwurf sind **keine** eigenen Archetypen — sie werden **generisch** modelliert:
| Konzept | Modellierung | Werkzeug |
|---------|--------------|----------|
| Reifegrad-Spur / Lane | Project oder Roadmap-Lane mit gleichem Archetyp | Roadmap + Graph |
| Primär- / Nebenpfad | Knoten + Kanten; Rolle an Kante/Knoten | **Gate-Graph (AP1.13)** |
| Kritischer Pfad | **Berechnet** aus Graph + Ist-Status | Steering Read Model |
| Voraussetzung Stufe 3 Angriff braucht Stufe 2 Bein | `roadmap_item_dependencies` / Graph | A1 Kumite-Beispiel |
| Recurring-Domain (Küche / Person) | `project.recurring_program` + **EFS-Konfiguration** | Felder, nicht Typ |
| Sprint-Zeitbox | `RoadmapItem(work_cycle)` + `Action.work_cycle_id` | B3 Profil — **kein** Project-Typ |
| Thema ohne Project | **eigene Initiative** (`support_queue`) oder BacklogItem-Triage | B1 PO |
**PO:** Kein exaktes Datenmodell + exakte Steuerung **pro Bezeichner** — Archetyp liefert **Default-Methode + Feldprofil + UI-Empfehlung**; Feinsteuerung über Graph, EFS, optional `method_key`-Override am Project.
### 4.3 Abweichende Methode / Struktur am Project
```text
Initiative (method_key, archetype_key)
└── Project (archetype_key default=Mirror, method_key optional OVERRIDE)
├── structure: parent_project_id, roadmap_item_id, graph edges
└── Actions / Recurring / Tasks
```
- **Override `method_key`:** z. B. Initiative `product` (continuous), ein Project `linear_project` (method `sequential_dependency`) für einen begrenzten Release-Strang
- **Audit** bei Override; MVP: manuelle Wahl, kein Designer
- **`container_kind`** (bestehend: `project|stream|phase|release`) bleibt **Strukturhint** — orthogonal zu `archetype_key` (Variante 1)
### 4.4 `project.generic` — bewusst schwach
**PO:** Default `generic` ohne Ableitung ist ** strukturlos** und **steuerungslos** — nur Notfall.
| Bevorzugt | Statt generic |
|-----------|----------------|
| Anlage unter Initiative | Archetyp **erben** |
| Thema/Inbox ohne Parent-Project | **Neue Initiative** (`support_queue`) |
| Explizit unstrukturiert | generic + Attention „Struktur fehlt“ |
### 4.5 Referenz — Kumite (Komplexität A1)
```text
Initiative: Karate Kumite (maturity_journey)
├── Project: Angriff (maturity_journey) — 57 Stufen
├── Project: Beinarbeit (maturity_journey)
├── … (8 Fähigkeiten)
│ └── RoadmapItem maturity_stage je Stufe
│ └── RecurringElement: Trainingsroutinen (Varianten)
└── Graph: Stufe 3 Angriff REQUIRES Stufe 2 Beinarbeit, Stufe 2 Reaktion, …
```
Kein Sonder-Archetyp „lane“ — nur **Spiegel-Archetyp** + **Graph** + **Roadmap** + **Recurring**.
---
## 5. Archetyp-Detail (PO-Spezifikation)
### A1 — `initiative.maturity_journey` (Reifegrad) — **PO ✓**
**Nutzerbild:** Karate, Fitness, Fähigkeiten mit **mehrstufigen Reifegradmodellen**, Abhängigkeiten zwischen Fähigkeiten, **Variation** der Übungen. Ziel **entwicklungsbasiert**, nicht fest definierter Endzustand — Fortschritt aus **Historie** und erreichtem (weichen) Status. **Ausprägung** z. B. `maturity.karate_kumite` (8 Fähigkeiten, Stufen-Raster, Routinen-Seed, Voraussetzungs-Graph).
**Plan:** Projects (Spiegel-Archetyp) + `maturity_stage` RoadmapItems; **Graph** für Voraussetzungen zwischen Stufen/Projects
**Ist:** `RecurringElement` pro Stufe (Übungsvarianten rotierend); bei Verify `reached` → Recurring-Set wechseln (AP2.0e); Journey dokumentiert Entwicklung
**Steuerung (`maturity_progression`):**
- Next Action: heutige Recurring-Instanz + Hinweis auf offenes Stufen-Kriterium
- Attention: Stagnation (keine Erfüllung), Stufe ohne Fortschritt über Zeit
- **Nicht:** starres „Ziel erreicht = Ende“ — Reifegrad bleibt adaptierbar
**EFS:** `current_body_focus`, `training_frequency`, `progress_notes`, optional `discipline` (enum: karate, fitness, …)
**UI-Profil:** Kontrolle dominant; Plan = Stufen; Gates-Graph **aus**; Journey **ein**
---
### A2 — `initiative.linear_project` (Linear / Einmalprojekt) — **PO ✓**
**Nutzerbild:** Einmalige Vorhaben (Küche, Umzug, Event). **Ein oder mehrere lineare Pfade** plus **unabhängige/parallele** Aktivitäten — daher **Gate-Graph** als Zielmodell, nicht nur eine Liste.
**Plan:** Projects + Gates; **mehrere Pfade**, Graph-Designer (AP1.13); kritischer Pfad **dynamisch**
**Ist:** Actions an Strängen; parallele APs ohne Pfad-Blockade wo erlaubt
**Steuerung (`sequential_dependency`):**
- Next Action: nächster **ready** Schritt am gewählten Pfad / kritischen Pfad
- Attention: Blocker auf Pfad, Gate at risk, überfälliges `target_date`
**EFS:** `budget_summary`, `primary_contractor`, `target_completion`
**UI-Profil:** Plan (Graph/Liste) + Kontrolle; Recurring **aus**
---
### A3 — `initiative.recurring_program` (Dauerprogramm / Haushalt) — **PO ✓**
**Nutzerbild:** Rhythmus-Vorhaben (Haus in Ordnung). Steuerung über **Abweichungen und Gesundheit des Systems****nicht** über x-fach auflaufende Einzel-Tasks („10× Staubsaugen mit unterschiedlichem Datum“).
**Plan:** optional Projects (`recurring_program`); Domains **konfigurierbar** (EFS: Raum, Person, Thema)
**Ist:** `RecurringElement` + `ActionAssignment` pro Actor; **eine** offene Instanz pro Rhythmus — bei Nicht-Erledigung **Eskalation/Score**, kein neuer Duplikat-Task
**Steuerung (`recurring_control`) — MVP minimal, Zielbild:**
| Signal | Logik (Ziel) |
|--------|----------------|
| Dringlichkeit | Datum **+** Anzahl verpasster Zyklen (nicht nur Fälligkeit) |
| Regelmäßigkeit | Bonus / grüner Score bei stabil erfüllter Cadence |
| Freiwilligkeit | Bonus bei freiwilliger Übernahme fremder offener Rhythmen |
| Haushalts-Pool | Offene Rhythmen einer Person für **alle** sichtbar; andere können **freiwillig übernehmen** (Assignment-Wechsel mit Audit) |
| Attention | Abweichung vom Soll-Rhythmus, nicht Gesamtliste aller Haus-Tasks |
**Anti-Pattern:** Jede verpasste Ausführung erzeugt neuen Task → **verboten**. Stattdessen: Recurring-Instanz + Score/Attention.
**EFS:** `household_members`, `cadence_default`, optional `domain_label` (Küche, Garten, …)
**UI-Profil:** Ausführen + Team-Health; Plan minimal; **kein** Task-Wall aller Familienmitglieder
**MVP-Stufe:** **B** (Minimal: fällig/heute ohne Score); **B+** / AP2.0g: Score + freiwillige Übernahme
---
### B1 — `initiative.support_queue` (Inbox / Queue) — **PO ✓**
**Nutzerbild:** **Inbox** für Ad-hoc-Aufgaben („nicht vergessen“), plus **Queue** für bearbeitbare Items. Items müssen **themenbezogen** zuordenbar sein (Initiative, Project, Tag/Thema) — nicht alles in einer globalen Mülltonne.
**Plan:** Eingang → triage; Queue **unter** Product/Programm **oder** als **eigene Initiative** (Thema = Vorhaben)
**Ist:** Actions als Tickets; Zuordnung zu Vorhaben/Thema bei Triage oder Commit
**Steuerung (`queue_pull`):**
- Next Action: Empfehlung aus Queue **im gewählten Themen-Scope** oder Pull
- Attention: SLA, unassigned high-priority
**EFS:** `queue_policy`, `sla_hours`, `default_topic_ref` (optional)
**UI-Profil:** Eingang + Ausführen (Queue) dominant; thematische Filter Pflicht
**MVP-Stufe:** **B** (Inbox + Queue + Themen-Zuordnung minimal)
---
### B2a — `initiative.program` (Programm, begrenzt) — **PO ✓**
**Abgrenzung zu Product:** Programm hat **Ziel und Abschluss** (Phasen, Release-Programme, Großvorhaben mit Ende). Lifecycle führt zu **Closure**.
**Plan:** `RoadmapItem`: `milestone`, `feature`, `review_gate`; Product Backlog im Eingang
**Ist:** Actions + Tasks; optional Gate- und `work_cycle`-Bindung
**Steuerung (`program_delivery`):**
- Next Action: nächstes Gate / AP am Programm-Horizont
- Attention: Gate at risk, Blocker, offenes Backlog am aktiven Gate
- Lifecycle: Standard inkl. **closure**
**Komposition B3:** `work_cycle` (Sprint) optional; Sprint kann in Release münden → Übergang in Product-Betrieb
**UI-Profil:** Plan (Gates) + Kontrolle + Ausführen
---
### B2b — `initiative.product` (Produkt, kontinuierlich) — **PO ✓**
**Abgrenzung zu Program:** Produkt = **kontinuierliche Weiterentwicklung** ohne definiertes Ende — **Wartung, Issues, Betrieb** sind Dauer-Themen. Lifecycle **ohne** fixes Closure-Ziel (Adaptation statt Abschluss).
**Plan:** Gates/Meilensteine als **Orientierung**, nicht als finales End-Gate; Backlog dauerhaft
**Ist:** Actions (Features, Fixes, Ops); Sprint/`work_cycle` als **Zeitbox** auf Ist-Ebene
**Steuerung (`continuous_product`):**
- Next Action: wirkungsvollster Schritt im aktiven Horizont (Gate **oder** aktiver Sprint)
- Attention: kritische Issues, technische Schuld, leerer Sprint bei aktivem Zyklus
- Lifecycle: **kein** erzwungenes `closure``adaptation` / Dauerbetrieb
**Kairo-Referenz:** Kairo selbst eher **Product** als begrenztes Programm; Vibe-Coding-Sprints hängen hier als `work_cycle`.
**UI-Profil:** Plan + Kontrolle; Betrieb/Issues sichtbar; Sprint-Banner wenn Zyklus aktiv
**Technik:** Bestehendes `product_milestone_driven` bleibt Übergangs-Seed bis AP2.0a Split in `program_delivery` + `continuous_product`.
---
### B3 — Sprint / Iteration ( **kein** Initiative-Archetyp) — **PO ✓**
**PO-Entscheidung:** Sprint ist **kein eigener Vorhaben-Typ**, sondern **Plan-/Ist-Konstrukt** auf Product/Programm — fühlt sich nahe an **Arbeitspaket-Zeitbox** an, kann in Release/Product-Betrieb übergehen.
**Erstes Setup:** **Product Owner + Vibe Coder** — kein klassisches Dev-Team; **Scrum-Master-Rolle** = Kairo-Steuerungslogik (Next Action, Attention, Sprint-Grenzen).
**Plan:** `RoadmapItem(type=work_cycle)` — optional, nicht jedes Product braucht Sprints
**Ist:** Actions mit optional `work_cycle_id`; Sprint kann **klein** sein (13 APs)
**Steuerung (`agile_iteration` Profil):** Hook auf `continuous_product` / `program_delivery` wenn aktiver Zyklus
**Offen (bewusst):** Ob Sprint langfristig eher `Action`-Granularität oder `work_cycle`-Granularität — MVP: `work_cycle` minimal, ohne Team-Archetyp
**MVP-Stufe A:** ein aktiver Zyklus auf Kairo-Product, Next Action im Zyklus — **ohne** Team-Board
---
### C1 — `initiative.dispute_case` (Miterstreit) — **PO ✓ Katalog, nicht MVP**
**Nutzerbild:** **Reaktiv**, nicht planerisch — aus **Status** entstehen fortlaufend neue Handlungsstränge und Aufgaben (Fristen, Entscheidungen, Reaktionen).
**Plan:** Phasen-Gates als Orientierung; Iterationen (Reopen) mit Decision-Pflicht
**Ist:** Decisions, Evidence, Fristen auf Gates/Actions
**Steuerung (`dispute_procedure`):** Next Action: nächste Frist / offene Entscheidung / neuer Strang aus Statuswechsel
**MVP-Stufe C:** Katalog + Profilfelder; UI spezialisiert post-MVP
---
### D1 — `initiative.content_project` (Inhalt / Kapitel) — **PO ✓ MVP Stufe B**
**Nutzerbild:** Buch- und Konzeptprojekte — generischer Archetyp; **Ausprägung** z. B. `content.book_writing` mit Kapitel-Seed, Mitwirkenden, Vorbefüllung.
**Plan:** `RoadmapItem(type=chapter)` + `review_gate`
**Ist:** Actions (Schreib-APs, Recherche)
**Steuerung (`chapter_based_progression`):** Next Action: nächstes Kapitel / Review / Schreib-AP
**Ausprägung `content.book_writing` (Schicht 3):** Gliederungs-Template, `word_count_goal`, Rollen (Autor, Lector), Kategorien
**MVP-Stufe B:** Archetyp + eine Ausprägung als Seed
---
## 6. Plan-/Ist-Muster (übergreifend)
```text
Eingang Plan (optional) Ist Steuerung
maturity_journey selten maturity_stages Recurring heutige Übung
linear_project selten Gate-Graph Actions kritischer Pfad
recurring_program selten Domains Recurring fällig/heute
support_queue triage Queue-Streams Actions (Tickets) Pull/Empfehlung
program Product Backlog milestones, gates Actions+Tasks Gate-Horizont + Closure
product Product Backlog milestones (orientierend) Actions+Tasks+Ops Next Step + Dauerbetrieb
(work_cycle) — work_cycles on B2 Actions (Zeitbox) Sprint Next Action (Profil)
dispute_case Eingang phase gates Decisions+Evidence reaktiv: Frist/Strang
content_project Ideen chapters Actions (Schreib-AP) nächstes Kapitel
```
---
## 7. Scope Lock
| Verboten | Erlaubt |
|----------|---------|
| React-Formulare pro Archetyp hardcoden | FieldRenderer + Registry |
| OM-Tabelle `disputes`, `habits`, `sprints` | EFS + RoadmapItem + bestehendes OM |
| Steering-Heuristiken in Routern | `backend/steering/` |
| Alle Methoden voll implementieren vor A-Abnahme | Stubs + A1/A2/B2/B3-minimal zuerst |
| Archetyp ohne `method_key`-Bindung | Seed + Sync |
| Sprint-Backlog als BacklogItem-Liste | Actions mit `work_cycle_id` |
---
## 8. Implementierungspakete
```text
AP2.0a Method-Stubs: maturity_progression, sequential_dependency, recurring_control,
queue_pull, program_delivery, continuous_product, agile_iteration (Profil),
dispute_procedure (stub), chapter_based_progression (stub)
AP2.0b entity_archetypes Seeds (Initiative + Project Spiegel); projects.archetype_key;
EFS profiles; 23 Referenz-Ausprägungen (Seeds): kumite, book_writing, kairo_dev
AP2.0c Kontrolle-Lagebild: method_key, lifecycle, next action, attention (UI)
AP2.0d Next-Action-Strategien: maturity, sequential, recurring, queue (minimal)
AP2.0e Recurring-Stufenwechsel bei maturity_stage reached (A1)
AP2.0f work_cycle + actions.work_cycle_id; Sprint auf Product/Programm; agile_iteration Profil
AP2.0g A3 Score + freiwillige Übernahme (recurring_control erweitert) — Stufe B+
AP2.1 Validation Report v0.3 — A1, A2, B2b (Kairo Product), D1 mit echten Daten
```
Erweitert AP1.10 — **ersetzt nicht** EFS-Architektur, nutzt sie.
---
## 9. Risiko
| Risiko | Mitigation |
|--------|------------|
| Methoden-Overengineering | Stubs + eine Strategie pro A-Archetyp |
| B2/B3 Verwechslung | Kompositions-Regel §2.3; UI zeigt aktiven Horizont |
| Sprint = Todo-Wand | Default-Ansicht Sprint-Next-Action, nicht alle Actions |
| dispute_case zu groß | Stufe C |
| work_cycle ohne Migration | AP2.0f explizit, FK auf roadmap_items |
---
## 10. PO-Freigabe
- [x] Initiative-Archetypen A1D1 — **2026-07-10** (Details §5)
- [x] Project-Archetypen — **Spiegel-Modell §4** (2026-07-10)
- [x] Vier-Schichten-Modell §2.0 (Framework → Methode → Archetyp → Ausprägung)
- [x] Methoden-Keys §3.2 inkl. `program_delivery`, `continuous_product`, `agile_iteration`-Profil
- [x] B3 ohne eigenen Archetyp; Sprint/`work_cycle` auf Product/Programm
- [x] A3 Score-Logik Zielbild §5; MVP minimal, AP2.0g für Score/Übernahme
- [x] MVP-Stufen A/B/C (§3.1)
- [x] AP2.0-Reihenfolge §8 inkl. AP2.0f/2.0g
---
## 11. PO-Beschluss — Kurzfassung
**Gültig ab 2026-07-10.** Verbindlich für MVP v0.3 und AP2.0-Reihenfolge.
1. **Vier Schichten:** Framework → **Methode (Modul/Registry)****generischer Archetyp****Ausprägung (Profile)** → Integrationen später (MCP, Gitea, KI).
2. **Initiative-Archetypen:** A1A3, B1, B2a/B2b, B3 als Profil, C1 Katalog, D1 Stufe B — Portfolio vollständig im Katalog.
3. **Project-Archetypen:** 1:1-Spiegel der Initiative; Struktur via Graph/Roadmap/EFS; Override `method_key` erlaubt; `generic` nur Notfall.
4. **Agile:** Product Backlog = Eingang; Sprint = `work_cycle`; Sprint-Backlog = Actions mit `work_cycle_id`; kein Kanban/Burndown-Kern.
5. **Program vs Product:** unterschiedlicher Lifecycle (Abschluss vs. Dauerbetrieb); gleiche Steuerungsbausteine.
6. **Nächster Code-Auftrag nach Push-Freigabe:** AP2.0a → 2.0b → 2.0c (kein Plan-Politur ohne Steuerung).
---
## Referenzen
- `docs/product/Kairo_MVP_Definition_v0.3.md`
- `docs/architecture/ADP_AP1_10_Initiative_Archetypes_and_Entity_Field_System_v0.1.md`
- `docs/architecture/Kairo_Target_Architecture_Method_Driven_Adaptive_Steering_Core_v0.1.md`
- `docs/architecture/Kairo_Method_Design_Principles_v0.1.md`
- `docs/product/Kairo_Canonical_Operating_Model_v0.2.md`
- `backend/steering/methods/registrations/generic_operating.py`
- `backend/steering/methods/registrations/product_milestone_driven.py`

View File

@ -65,7 +65,8 @@ Verhindert, dass Zielbild-Dokumente als Ist-Stand gelesen werden.
| steering_contexts (009) | ✓ | Lifecycle, method_key | | steering_contexts (009) | ✓ | Lifecycle, method_key |
| backend/steering/ lifecycle | ✓ | | | backend/steering/ lifecycle | ✓ | |
| Signal Engine | ◐ | Regeln begrenzt | | Signal Engine | ◐ | Regeln begrenzt |
| Method Registry | ◐ | generic_operating, product_milestone_driven | | Method Registry | ◐ | generic_operating, product_milestone_driven; **Ziel AP2.0a:** program_delivery, continuous_product, … — siehe `ADP_Archetype_and_Method_Catalog_v0.2.md` |
| Archetyp-/Methoden-Katalog PO | ✓ | ADP v0.2 + MVP v0.3 freigegeben 2026-07-10 |
| NextActionCandidate | ◐ | API + Widget; nicht konfigurierbar auf beiden Ebenen | | NextActionCandidate | ◐ | API + Widget; nicht konfigurierbar auf beiden Ebenen |
| Portfolio-Priorität (Initiativen) | ✗ | | | Portfolio-Priorität (Initiativen) | ✗ | |
| Situativer Steuerungskontext (Next Action) | ✗ | 📄 Vision §7.6 | | Situativer Steuerungskontext (Next Action) | ✗ | 📄 Vision §7.6 |

View File

@ -0,0 +1,223 @@
# Jinkendo Kairo
## MVP Definition v0.3
**Status:** PO-freigegeben (bezogen auf `ADP_Archetype_and_Method_Catalog_v0.2.md`)
**Stand:** 2026-07-10
**Auslöser:** Programm-Director-Ziel vs. flache Vorhabenliste; private und professionelle Vorhaben gleichwertig; Steuerung vor Status-Monitoring; **Agile vollständig** (Backlog ✓, Sprint/Iteration ○)
**Bezug:** `Kairo_Vision_and_Product_Direction_v0.2.md`, `Kairo_Canonical_Operating_Model_v0.2.md`, `ADP_Archetype_and_Method_Catalog_v0.2.md`
**Ersetzt als MVP-Nordstern:** implizite Annahme „MVP = Software-Programm mit Gates + Tasks“ in Sprint-Delivery; **nicht** die technische Roadmap v0.2 (bleibt Referenz für AP-Reihenfolge)
---
## 1. Nordstern
Kairo ist der **operative Program Director** — nicht ein To-do-Tool.
**Leitfrage (unverändert):**
> Welcher nächste Schritt bringt dieses Vorhaben **jetzt** am wirksamsten voran — und **warum**?
Der MVP ist erreicht, wenn ein Nutzer **mehrere typische Vorhabenarten** (privat und professionell) in Kairo **erfassen, steuern und nachvollziehen** kann — **ohne** dass die Oberfläche in unendliche To-do-Listen kollabiert.
---
## 2. Was der MVP **ist** und **nicht ist**
### MVP ist
- **Steuerung sichtbar:** Methode, Lifecycle, Attention, Next Action (begründet) — nicht nur Status-Ampeln
- **Schichtenmodell:** Framework → Methode (Registry) → Archetyp (Baukasten) → Ausprägung (z. B. Buch, Kumite) — siehe ADP §2.0
- **Archetyp-gesteuert:** Vorhaben- und Projekt-Typ bestimmt Default-Methode, Felder, dominante Modus-Ansichten
- **Plan vs. Ist getrennt:** Eingang ≠ committete Arbeit; Recurring ≠ Backlog; **Product Backlog ≠ Sprint-Backlog**
- **Agile zweigleisig:** Release-Horizont (Gates, B2) **und** Iterations-Horizont (Sprint/`work_cycle`, B3) — komponierbar
- **Referenz-Portfolio:** mehrere Vorhaben **unterschiedlicher Typen** parallel im Tenant, davon **23 voll** durchspielbar
- **Historie:** Journey als steuerungsrelevante Narrative (inkl. rückwirkender Erfassung wichtiger Ereignisse)
### MVP ist nicht
- Vollständiger Import aus externen Tools
- Tenant-Admin-UI für Archetyp-Designer
- KI/Prompt/Workflow/MCP (bleibt eingefroren)
- Alle Archetypen **gleichzeitig voll implementiert** — Katalog ja, Vollimplementierung gestaffelt
- **Kanban-Board, Velocity, Burndown** als Kern
- Gantt-/Capacity-Planung
- Ersatz für Mitai/Shinkan oder Rechts-/Gesundheits-Spezialsoftware
---
## 3. Anti-Patterns (explizit verboten im MVP-Slice)
| Verboten | Warum |
|----------|--------|
| Hauptbild = flache Liste aller offenen Actions/Tasks | Todo-Explosion; widerspricht Program Director |
| Archetyp nur als Formular-Label ohne Methode/Steuerung | Täuscht Vielfalt vor |
| Annahme „Vorhaben = Software-Release“ | schließt private Vorhaben aus |
| **Sprint-Backlog als BacklogItem-Liste** | Sprint = committete Actions am `work_cycle` |
| Plan-Modus ausbauen ohne Kontrolle/Steuerung | Monitoring ohne Begleitung |
| Neue OM-Tabellen pro Archetyp (`sprints`, `habits`, …) | Scope Lock — Method Registry + EFS + OM |
| Steering-Logik in Routern oder Frontend hardcoden | nur `backend/steering/` + Registry |
---
## 4. Referenz-Portfolio (Archetyp-Katalog)
Vollständige Matrix: **`ADP_Archetype_and_Method_Catalog_v0.2.md`** §3.
| ID | Typ | Beispiel | Default-Methode | Agile-Bezug |
|----|-----|----------|-------------------|-------------|
| **A1** | Reifegrad | Spagat können | `maturity_progression` | — |
| **A2** | Linear / Wasserfall | Neue Küche | `sequential_dependency` | — |
| **A3** | Dauerprogramm / Rhythmus | Haus in Ordnung | `recurring_control` | — |
| **B1** | Queue / Supportdesk | Tickets | `queue_pull` | Pull statt Board |
| **B2a** | Programm (begrenzt) | Release-Programm | `program_delivery` | Release + Abschluss |
| **B2b** | Produkt (kontinuierlich) | Kairo, Betrieb | `continuous_product` | Dauerbetrieb + Issues |
| **B3** | Sprint-Zeitbox *(Profil, kein Archetyp)* | PO + Vibe-Coder | `agile_iteration` | Zeitbox auf B2b |
| **C1** | Verfahren / Konflikt | Miterstreit | `dispute_procedure` | reaktiv, Katalog |
| **D1** | Inhalt / Kapitel | Buch, Konzept | `chapter_based_progression` | **Stufe B** |
### B2a vs B2b vs B3 (PO 2026-07-10)
- **Programm:** Ziel, Phasen, **Abschluss** — z. B. Release-Programm
- **Product:** **Kein** fixes Ende — Wartung, Issues, Weiterentwicklung; Kairo selbst = Product
- **Sprint:** Kein eigener Vorhaben-Typ — `work_cycle` auf Product/Programm; nahe an Arbeitspaket-Zeitbox
### MVP-Abnahfe-Priorität
| Stufe | Archetypen | Bedeutung |
|-------|------------|-----------|
| **Abnahfe A** | A1, A2, B2b (+ B3 minimal auf Kairo-Product) | Reifegrad, Linear, Kairo Product + optional Sprint |
| **Abnahfe B** | A3, B1, **D1**, B3 ausgebaut | Haushalt-Score (AP2.0g), Inbox/Queue, Buch |
| **Katalog C** | C1 | Miterstreit — Spezifikation, nicht MVP |
---
## 5. MVP-Nutzbarkeits-Bar (v0.3)
Kairo ist **MVP-nah**, wenn ein Nutzer **pro Archetyp der Stufe A**:
1. Ein Vorhaben **anlegt** (Initiative-Archetyp, Default-Methode, Profil/EFS)
2. Die **passende Struktur** modelliert (Reifegrad-Stufen / Gate-Kette / Sprint-Zyklen — methodenabhängig)
3. **Ist** committet (Actions, Tasks, Recurring — nicht alles gleichzeitig sichtbar)
4. In **Kontrolle** den **Lagebild-Steuerungskern** sieht: Lifecycle, Methode, 13 Next Actions, Attention — **mit Begründung**
5. In **Journey** Entwicklung und Abweichungen **nachvollzieht** (min. 5 steuerungsrelevante Events, auch rückwirkend)
6. **Ohne CRUD-Wand** in ≤2 Minuten die Leitfrage für dieses Vorhaben beantworten kann
**Portfolio-Ebene (zusätzlich):**
7. Auf **Cockpit** sieht, **welches** Vorhaben welche Art von Attention braucht — nicht Details aller offenen Tasks
---
## 6. Steuerung vs. Monitoring
| Monitoring (reicht nicht) | Steuerung (MVP-Pflicht) |
|---------------------------|-------------------------|
| „12 offen“ | „Nächster Schritt: X, weil Gate Y blockiert / Stufe Z / **Sprint endet Freitag**“ |
| Status-Dropdown | Lifecycle-Übergang + Methode |
| Alle Tasks listen | Recurring: **heute fällig**; Queue: **nächster Pull**; Reifegrad: **aktuelle Übung**; Sprint: **13 Items im aktiven Zyklus** |
| Journey als Archiv | Journey + Decision als **Plan-Abweichung** |
| Product Backlog als Hauptliste | Sprint-Modus: **nur Sprint-Backlog** als Default |
Technische Anker: `steering_context.method_key`, `backend/steering/`, NextActionCandidate, AttentionItem, Method Registry, `actions.work_cycle_id` (AP2.0f).
---
## 7. Todo-Explosion verhindern (verbindliche UI-Regeln)
1. **Default-Ansicht** pro Methode zeigt **Next Action** (13), nicht Gesamtbestand
2. **Recurring** erscheint in Rhythmus-Ansicht, nicht im Action-Backlog
3. **Backlog/Eingang** (Product Backlog) getrennt von committeter Arbeit und von **Sprint-Backlog**
4. **Plan** (Gates, Graph, Stufen, **Sprints**) = Orientierung; **Ist** = Ausführung
5. **Drill-down** zu vollen Listen nur auf explizite Nutzeraktion („Alle anzeigen“)
6. **Scope:** Portfolio → Vorhaben → Projekt filtert sichtbare Operative
7. **Aktiver Sprint:** Ausführen-Modus default = Sprint-Backlog, nicht Product Backlog
---
## 8. Abnahme-Szenarien (konkret)
### A1 — Spagat (Reifegrad)
- Stufen als `maturity_stage` RoadmapItems
- Recurring-Übungen; bei Stufenübergang **andere** Routine
- Kontrolle: aktuelle Stufe + heutige Übung + Kriterium bis nächste Stufe
- **Nicht:** 200 Übungs-Tasks in der Hauptliste
### A2 — Küche (Wasserfall)
- Primärstrang mit Abhängigkeiten (Graph oder sequenzielle Liste)
- Begleitprojekte parallel
- Kontrolle: kritischer Pfad / nächster blockierender Schritt
- **Nicht:** alle Handwerker-Schritte als flache Todo-Liste
### B2b — Kairo (Product, kontinuierlich)
- Gates/Meilensteine als Orientierung; Backlog im Eingang; Issues/Betrieb als Dauer-Thema
- Optional: `work_cycle` (Sprint-Zeitbox) für PO + Vibe Coder
- Kontrolle: Next Action im aktiven Horizont (Gate **oder** Sprint) — begründet
- **Nicht:** alle APs aller Gates gleichzeitig in der Hauptliste
### B3 — Sprint-Zeitbox (Profil auf Product, kein eigener Archetyp)
- Optional ein aktiver `work_cycle`; 13 Actions in der Zeitbox
- Kairo-Steuerung statt Scrum-Master-Rolle
- **Nicht:** Team-Board, Velocity
### D1 — Buch / Konzept (Stufe B)
- Kapitel als `chapter` RoadmapItems; mindestens ein Schreib-AP committet
- Kontrolle: nächstes Kapitel / aktuelles Schreib-AP
---
## 9. Implementierungsfolge (nach PO-Freigabe dieses Dokuments)
**Kein weiterer „Plan-Modus-Politur“-Slice ohne Steuerungs-Bezug.**
```text
1. ADP Archetype & Method Catalog v0.2 — ✓ PO-freigegeben 2026-07-10
2. AP2.0a Method Registry: Stubs inkl. program_delivery, continuous_product, agile_iteration
3. AP2.0b Archetyp-Seeds (Initiative + Project Spiegel); EFS; Referenz-Ausprägungen (Kumite, Buch, Kairo)
4. AP2.0c Kontrolle/Lagebild: Methode + Next Action + Attention (Hauptfläche)
5. AP2.0d Next-Action-Strategien: maturity, sequential, recurring, queue (minimal)
6. AP2.0f work_cycle + actions.work_cycle_id; Sprint auf Product; agile_iteration Profil
7. AP2.0g A3 Score + freiwillige Übernahme (Stufe B+)
8. AP2.1 Referenz-Abnahme A1, A2, B2b (+ B3 minimal), D1 (Validation v0.3)
9. Parallel wenn tragfähig: AP1.13 Gate-Graph für A2/B2 — nicht Default für alle
```
Bestehende APs (1.12, 1.10, 1.5d) bleiben **Infrastruktur** — werden im MVP v0.3 erst **wertvoll**, wenn 2.0c/2.0d/2.0f sie archetyp- und methodengebunden nutzen.
---
## 10. Dokumentenpriorität bei Konflikten
Bei MVP-Fragen gilt:
1. Dieses Dokument (v0.3) + `ADP_Archetype_and_Method_Catalog_v0.2.md`
2. `Kairo_Vision_and_Product_Direction_v0.2.md`
3. `Kairo_Canonical_Operating_Model_v0.2.md`
4. `Kairo_Corrected_MVP_Roadmap_v0.2.md` (AP-Reihenfolge, technisch)
5. Sprint Completion Reports (historisch)
---
## 11. PO-Freigabe
- [x] Nordstern und Anti-Patterns akzeptiert
- [x] Referenz-Portfolio A1D1 als Katalog akzeptiert
- [x] Vier-Schichten-Modell (ADP §2.0) akzeptiert
- [x] B2a/B2b + B3-Profil; Project-Spiegel-Modell akzeptiert
- [x] Abnahfe Stufe A = A1 + A2 + B2b + B3-minimal; Stufe B = A3, B1, D1
- [x] Sprint-Semantik (Product Backlog vs. Sprint-Backlog) akzeptiert
- [x] Implementierungsfolge §9 akzeptiert
- [x] Kein MVP-Fortschritt mehr ohne sichtbare Steuerung pro Archetyp
---
## Referenzen
- `docs/architecture/ADP_Archetype_and_Method_Catalog_v0.2.md`
- `docs/architecture/Kairo_Method_Design_Principles_v0.1.md`
- `docs/architecture/Kairo_Target_Architecture_Method_Driven_Adaptive_Steering_Core_v0.1.md`
- `docs/product/Kairo_Implementation_Truth_Table_v0.1.md`

View File

@ -0,0 +1,117 @@
# AP2.0 — Steering, Archetypen & Ausprägungen (Minimal Complete Slice)
## Implementierungsauftrag v0.1
**Status:** umgesetzt (2026-07-10)
**Stand:** 2026-07-10
**PO-Basis:** `ADP_Archetype_and_Method_Catalog_v0.2.md` §11, `Kairo_MVP_Definition_v0.3.md`
**Vorgänger:** AP1.10 (EFS), AP1.1 (Method Registry), AP1.9 (Kontrolle-Shell)
**Zielversion:** `0.18.0-ap2.0` · Schema `019`
---
## 1. Ziel
Erster **Minimal Complete Steering Slice**: Archetyp-Katalog und Methoden-Module sind registriert; neues Vorhaben startet mit **passender Default-Methode**; **Kontrolle** zeigt Methode, Archetyp, Lifecycle, Next Actions **mit Begründung** — nicht nur Zähler.
**Leitfrage-Test (MVP §5):** Nutzer kann für ein Kairo-Product-Vorhaben in ≤2 Minuten beantworten: *Was ist als Nächstes dran — und warum?*
---
## 2. Vier Schichten — was dieser Slice liefert
| Schicht | AP2.0 | Nicht in AP2.0 |
|---------|-------|----------------|
| **0 Framework** | unverändert nutzen | Waiting Runtime, Workflow |
| **1 Methode** | **2.0a** — alle Keys registriert; 2 Strategien (program/continuous) | Volle Builder, KI |
| **2 Archetyp** | **2.0b** — Initiative + Project Spiegel, Default-Methode | Tenant-Designer |
| **3 Ausprägung** | **2.0b** — 3 Code-Seeds (Kumite, Buch, Kairo) | `method_profiles`-DB, UI |
| **4 Integration** | — | MCP, Gitea, KI |
---
## 3. Arbeitspakete
### AP2.0a — Method Registry erweitern
**DoD:**
- [ ] Registriert: `program_delivery`, `continuous_product`, `maturity_progression`, `sequential_dependency`, `recurring_control`, `queue_pull`, `agile_iteration`, `dispute_procedure`, `chapter_based_progression`
- [ ] Legacy `product_milestone_driven` bleibt (Alias-Kompatibilität)
- [ ] Next-Action-Strategien: `program_delivery` (Gate-Horizont), `continuous_product` (Ist zuerst, dann Plan)
- [ ] Stubs nutzen `default`-Strategy bis AP2.0d
- [ ] `GET /api/steering/methods` listet alle Methoden
- [ ] pytest: Methoden registriert, unbekannte Keys abgewiesen
**Nicht-Scope:** Structure Builder, Hook-Handler mit MCP, Method Profiles DB.
---
### AP2.0b — Archetyp- & Project-Spiegel
**DoD:**
- [ ] `entity_archetypes` Seeds: alle Initiative-Archetypen aus ADP §3.1 + Project-Spiegel §4.1
- [ ] Jeder Initiative-Archetyp: `default_method_key` (Code-Registry, API-Response)
- [ ] Migration **019**: `projects.archetype_key` NULL → Default = Mirror der Initiative bei INSERT
- [ ] `create_initiative` → SteeringContext mit **Archetyp-Default-Methode** (nicht blind `generic_operating`)
- [ ] `create_project``archetype_key` = Mirror der Initiative
- [ ] 3 Referenz-**Ausprägungen** (Code-Seeds): `maturity.karate_kumite`, `content.book_writing`, `product.kairo_dev`
- [ ] EFS: mindestens Felder für `initiative.product`, `initiative.content_project`, `initiative.maturity_journey`
- [ ] pytest: Product → `continuous_product`; Project erbt Archetyp
**Nicht-Scope:** Graph-Designer, Score-Logik (→ AP2.0g), `method_profiles`-Tabelle.
---
### AP2.0c — Kontrolle / Lagebild
**DoD:**
- [ ] `steering-snapshot` enthält: `archetype_key`, `archetype_label`, optional `method_profile_key`, `steering_guidance` (1 Satz)
- [ ] Next Actions enthalten `reason_code` / `recommended_action` sichtbar in UI
- [ ] `SteeringSnapshotPanel`: Archetyp-Zeile, Guidance, Attention aus Signals
- [ ] Kein neues Omnibus-CRUD; nutzt bestehende Kontrolle-Route (`ControlStatusPage`)
- [ ] pytest: Snapshot-Felder für Product-Initiative
**Nicht-Scope:** Burndown, Kanban, Sprint-UI (→ AP2.0f), Gate-Graph (→ AP1.13).
---
## 4. Referenz-Abnahme (manuell nach Deploy)
1. Vorhaben **Kairo** anlegen: Archetyp `initiative.product` → Methode `continuous_product`
2. Kontrolle: Lifecycle, Methode, Archetyp, ≥1 Next Action mit Begründung
3. Project anlegen → `archetype_key` = `project.product`
4. Optional: Archetyp `initiative.content_project` + Feldprofil sichtbar
---
## 5. Explizit nicht in AP2.0
- Kanban-Board, Velocity, Burndown
- `work_cycle` / Sprint (`actions.work_cycle_id`) — AP2.0f
- A3 Score / freiwillige Übernahme — AP2.0g
- Gate-Graph-Designer — AP1.13
- MCP / Gitea / KI-Anbindung — eingefroren
- `method_profiles` PostgreSQL-Tabelle
- Archetyp-Designer Admin-UI
---
## 6. Reihenfolge & Abhängigkeiten
```text
AP2.0a → AP2.0b → AP2.0c (ein Release-Strang 0.18.0-ap2.0)
Danach: AP2.0d (Strategien pro Archetyp), AP2.0f (Sprint), AP2.0g (Score)
```
**Guardrail:** Kein AP1.12/Plan-Politur-Commit ohne Bezug zu §3 AP2.0c DoD.
---
## 7. Referenzen
- `docs/architecture/ADP_Archetype_and_Method_Catalog_v0.2.md`
- `docs/product/Kairo_MVP_Definition_v0.3.md`
- `docs/architecture/Kairo_Method_Design_Principles_v0.1.md`
- `docs/sprints/Sprint1_AP1_1_Method_Registry_Assignment_v0.1.md`

View File

@ -1,6 +1,6 @@
{ {
"name": "kairo-jinkendo-frontend", "name": "kairo-jinkendo-frontend",
"version": "0.17.0-ap1.5d", "version": "0.18.0-ap2.0",
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {

View File

@ -49,6 +49,11 @@ export function SteeringSnapshotPanel({
lifecycle_label, lifecycle_label,
method_key, method_key,
method_label, method_label,
archetype_key,
archetype_label,
method_profile_key,
steering_guidance,
attention_items = [],
signals = [], signals = [],
counts, counts,
upcoming_milestones = [], upcoming_milestones = [],
@ -74,6 +79,9 @@ export function SteeringSnapshotPanel({
<h2 className="steering-hero-title"> <h2 className="steering-hero-title">
Wo stehe ich und was ist als Nächstes dran? Wo stehe ich und was ist als Nächstes dran?
</h2> </h2>
{steering_guidance && (
<p className="steering-guidance">{steering_guidance}</p>
)}
</div> </div>
<span className="badge status-badge status-active steering-lifecycle-badge"> <span className="badge status-badge status-active steering-lifecycle-badge">
{displayLabel} {displayLabel}
@ -81,6 +89,12 @@ export function SteeringSnapshotPanel({
</header> </header>
<div className="steering-hero-toolbar"> <div className="steering-hero-toolbar">
{(archetype_label || archetype_key) && (
<p className="steering-archetype-row muted">
Archetyp: <strong>{archetype_label || archetype_key}</strong>
{method_profile_key ? ` · Ausprägung: ${method_profile_key}` : ''}
</p>
)}
{(method_label || canManageMethod) && ( {(method_label || canManageMethod) && (
<p className="steering-method-row"> <p className="steering-method-row">
<span className="muted">Methode: </span> <span className="muted">Methode: </span>
@ -117,9 +131,13 @@ export function SteeringSnapshotPanel({
</ul> </ul>
</div> </div>
{signals?.length > 0 && ( {(attention_items?.length > 0 || signals?.length > 0) && (
<p className="muted snapshot-signals"> <p className="muted snapshot-signals snapshot-attention">
{signals.map((s) => SIGNAL_LABELS[s] || s).join(' · ')} Attention:{' '}
{(attention_items.length > 0
? attention_items.map((a) => a.label)
: signals.map((s) => SIGNAL_LABELS[s] || s)
).join(' · ')}
</p> </p>
)} )}
@ -135,6 +153,7 @@ export function SteeringSnapshotPanel({
<strong>{item.title}</strong> <strong>{item.title}</strong>
<span className="muted list-item-sub"> <span className="muted list-item-sub">
{NEXT_ACTION_KIND_LABELS[item.kind] || item.kind} {NEXT_ACTION_KIND_LABELS[item.kind] || item.kind}
{item.reason_code ? ` · ${item.reason_code}` : ''}
{item.recommended_action ? `${item.recommended_action}` : ''} {item.recommended_action ? `${item.recommended_action}` : ''}
</span> </span>
</div> </div>

View File

@ -716,6 +716,21 @@
margin: 0.75rem 0 0; margin: 0.75rem 0 0;
} }
.steering-guidance {
margin: 0.35rem 0 0;
font-size: 0.95rem;
color: var(--text-secondary, #555);
}
.steering-archetype-row {
margin: 0 0 0.5rem;
font-size: 0.875rem;
}
.snapshot-attention {
font-weight: 500;
}
.steering-method-row { .steering-method-row {
margin: 0.5rem 0 0; margin: 0.5rem 0 0;
font-size: 0.9rem; font-size: 0.9rem;