From 3bd983297bd5dca823f208948ddcf609204324a5 Mon Sep 17 00:00:00 2001 From: Lars Date: Fri, 10 Jul 2026 10:44:38 +0200 Subject: [PATCH] AP2.0: Archetyp-Katalog, Method-Stubs und sichtbare Steuerung in Kontrolle. 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 --- backend/data_layer/initiative_snapshot.py | 52 ++ backend/entity_archetypes/__init__.py | 8 + backend/entity_archetypes/registry.py | 171 ++++- backend/entity_fields/definitions.py | 42 +- backend/entity_fields/sync.py | 8 +- backend/method_profiles/__init__.py | 1 + backend/method_profiles/registry.py | 63 ++ .../migrations/019_project_archetype_key.sql | 27 + backend/services/initiatives.py | 1 + backend/services/projects.py | 17 +- backend/services/steering_context.py | 39 +- backend/steering/__init__.py | 13 +- .../methods/registrations/_helpers.py | 70 ++ .../registrations/ap20_method_stubs.py | 50 ++ .../registrations/continuous_product.py | 14 + .../methods/registrations/program_delivery.py | 14 + .../strategies/next_action/__init__.py | 10 + .../next_action/continuous_product.py | 114 ++++ .../next_action/program_delivery.py | 28 + .../tests/test_ap110_initiative_archetypes.py | 6 +- .../tests/test_ap20_steering_archetypes.py | 104 +++ backend/version.py | 4 +- .../ADP_Archetype_and_Method_Catalog_v0.1.md | 303 +++++++++ .../ADP_Archetype_and_Method_Catalog_v0.2.md | 601 ++++++++++++++++++ .../Kairo_Implementation_Truth_Table_v0.1.md | 3 +- docs/product/Kairo_MVP_Definition_v0.3.md | 223 +++++++ ...2_0_Steering_Archetypes_Assignment_v0.1.md | 117 ++++ frontend/package.json | 2 +- .../src/components/SteeringSnapshotPanel.jsx | 25 +- frontend/src/styles/components.css | 15 + 30 files changed, 2093 insertions(+), 52 deletions(-) create mode 100644 backend/method_profiles/__init__.py create mode 100644 backend/method_profiles/registry.py create mode 100644 backend/migrations/019_project_archetype_key.sql create mode 100644 backend/steering/methods/registrations/_helpers.py create mode 100644 backend/steering/methods/registrations/ap20_method_stubs.py create mode 100644 backend/steering/methods/registrations/continuous_product.py create mode 100644 backend/steering/methods/registrations/program_delivery.py create mode 100644 backend/steering/strategies/next_action/continuous_product.py create mode 100644 backend/steering/strategies/next_action/program_delivery.py create mode 100644 backend/tests/test_ap20_steering_archetypes.py create mode 100644 docs/architecture/ADP_Archetype_and_Method_Catalog_v0.1.md create mode 100644 docs/architecture/ADP_Archetype_and_Method_Catalog_v0.2.md create mode 100644 docs/product/Kairo_MVP_Definition_v0.3.md create mode 100644 docs/sprints/Sprint1_AP2_0_Steering_Archetypes_Assignment_v0.1.md diff --git a/backend/data_layer/initiative_snapshot.py b/backend/data_layer/initiative_snapshot.py index 5eecf66..44ae0b1 100644 --- a/backend/data_layer/initiative_snapshot.py +++ b/backend/data_layer/initiative_snapshot.py @@ -11,6 +11,7 @@ from psycopg2.extras import RealDictCursor from db import get_connection 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.signals.snapshot_signals import derive_initiative_signals from services.initiatives import get_initiative @@ -20,6 +21,41 @@ OPEN_BLOCKER = ("open", "in_progress") OPEN_ACTION = ("open", "ready", "in_progress", "blocked", "review_required") 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]: 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) + 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 { "initiative_id": initiative_id, "initiative_title": initiative["title"], "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_label": steering["lifecycle_label"], "method_key": steering["method_key"], "method_label": steering.get("method_label"), "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, "upcoming_milestones": upcoming_milestones, "upcoming_roadmap_items": upcoming_milestones, diff --git a/backend/entity_archetypes/__init__.py b/backend/entity_archetypes/__init__.py index 783cd51..f7790e4 100644 --- a/backend/entity_archetypes/__init__.py +++ b/backend/entity_archetypes/__init__.py @@ -1,13 +1,21 @@ from entity_archetypes.registry import ( + ENTITY_ARCHETYPES, INITIATIVE_ARCHETYPES, + PROJECT_ARCHETYPES, archetype_label, list_archetypes, + mirror_project_archetype_key, + resolve_default_method_key, validate_archetype_key, ) __all__ = [ + "ENTITY_ARCHETYPES", "INITIATIVE_ARCHETYPES", + "PROJECT_ARCHETYPES", "archetype_label", "list_archetypes", + "mirror_project_archetype_key", + "resolve_default_method_key", "validate_archetype_key", ] diff --git a/backend/entity_archetypes/registry.py b/backend/entity_archetypes/registry.py index 7cc802c..4c4251a 100644 --- a/backend/entity_archetypes/registry.py +++ b/backend/entity_archetypes/registry.py @@ -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 @@ -8,39 +8,136 @@ from psycopg2.extras import RealDictCursor from db import get_connection -INITIATIVE_ARCHETYPES: tuple[dict[str, Any], ...] = ( - { - "key": "initiative.generic", - "entity_type": "initiative", - "label": "Allgemeines Vorhaben", - "description": "Standard-Vorhaben ohne spezielle Vorlage.", - "is_system": True, - }, - { - "key": "initiative.program", - "entity_type": "initiative", - "label": "Programm / Mega-Vorhaben", - "description": "Mehrere Stränge, Zielzustand und Vision zentral.", - "is_system": True, - }, - { - "key": "initiative.product", - "entity_type": "initiative", - "label": "Produkt / Release", - "description": "Produkt- oder Release-orientiertes Vorhaben.", - "is_system": True, - }, +# initiative suffix → default method (shared by initiative + project mirror) +_METHOD_BY_SUFFIX: dict[str, str] = { + "generic": "generic_operating", + "maturity_journey": "maturity_progression", + "linear_project": "sequential_dependency", + "recurring_program": "recurring_control", + "support_queue": "queue_pull", + "program": "program_delivery", + "product": "continuous_product", + "dispute_case": "dispute_procedure", + "content_project": "chapter_based_progression", +} + +_INITIATIVE_SPEC_META: tuple[tuple[str, str, str], ...] = ( + ("generic", "Allgemeines Vorhaben", "Fallback ohne spezielle Steuerungsvorlage."), + ( + "maturity_journey", + "Reifegrad-Entwicklung", + "Mehrstufige Entwicklung, Routinen, Graph-Voraussetzungen.", + ), + ( + "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]]: - if entity_type is None: - return [dict(item) for item in INITIATIVE_ARCHETYPES] - return [dict(item) for item in INITIATIVE_ARCHETYPES if item["entity_type"] == entity_type] + items = ENTITY_ARCHETYPES + if entity_type is not None: + 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]]: @@ -67,7 +164,7 @@ def list_archetypes(*, entity_type: Optional[str] = None) -> list[dict[str, Any] ) rows = cur.fetchall() if rows: - return [dict(row) for row in rows] + return [_enrich_row(dict(row)) for row in rows] except Exception: pass 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]: item = _ARCHETYPE_INDEX.get((entity_type, archetype_key)) 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" diff --git a/backend/entity_fields/definitions.py b/backend/entity_fields/definitions.py index 613f3b0..46b4d0c 100644 --- a/backend/entity_fields/definitions.py +++ b/backend/entity_fields/definitions.py @@ -1,4 +1,4 @@ -"""System-Felddefinitionen (Seed) — AP1.10b.""" +"""System-Felddefinitionen (Seed) — AP1.10b / AP2.0b.""" from __future__ import annotations @@ -45,4 +45,44 @@ FIELD_DEFINITIONS: tuple[dict[str, Any], ...] = ( "sort_order": 20, "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": {}, + }, ) diff --git a/backend/entity_fields/sync.py b/backend/entity_fields/sync.py index 7e09ff7..bd16a7f 100644 --- a/backend/entity_fields/sync.py +++ b/backend/entity_fields/sync.py @@ -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 import json 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 @@ -13,7 +13,7 @@ def sync_entity_field_registry_to_db() -> int: conn = get_connection() try: with conn.cursor() as cur: - for archetype in INITIATIVE_ARCHETYPES: + for archetype in ENTITY_ARCHETYPES: cur.execute( """ INSERT INTO entity_archetypes ( @@ -68,7 +68,7 @@ def sync_entity_field_registry_to_db() -> int: conn.commit() print( "[entity_fields] Sync OK — " - f"{len(INITIATIVE_ARCHETYPES)} Archetyp(en), " + f"{len(ENTITY_ARCHETYPES)} Archetyp(en), " f"{len(FIELD_DEFINITIONS)} Felddefinition(en)" ) return 0 diff --git a/backend/method_profiles/__init__.py b/backend/method_profiles/__init__.py new file mode 100644 index 0000000..725b914 --- /dev/null +++ b/backend/method_profiles/__init__.py @@ -0,0 +1 @@ +"""Package marker for method profile seeds.""" diff --git a/backend/method_profiles/registry.py b/backend/method_profiles/registry.py new file mode 100644 index 0000000..5e72222 --- /dev/null +++ b/backend/method_profiles/registry.py @@ -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 diff --git a/backend/migrations/019_project_archetype_key.sql b/backend/migrations/019_project_archetype_key.sql new file mode 100644 index 0000000..a9b17a9 --- /dev/null +++ b/backend/migrations/019_project_archetype_key.sql @@ -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; diff --git a/backend/services/initiatives.py b/backend/services/initiatives.py index cfcf930..0cc4c25 100644 --- a/backend/services/initiatives.py +++ b/backend/services/initiatives.py @@ -124,6 +124,7 @@ def create_initiative( tenant_id=tenant_id, initiative_id=row["id"], user_id=user_id, + archetype_key=archetype_key, ) return row diff --git a/backend/services/projects.py b/backend/services/projects.py index 8059b59..e13667f 100644 --- a/backend/services/projects.py +++ b/backend/services/projects.py @@ -9,6 +9,7 @@ from psycopg2.extras import RealDictCursor from db import get_connection from services.audit import log_audit +from entity_archetypes import mirror_project_archetype_key, validate_archetype_key from services.initiatives import get_initiative ProjectStatus = Literal["active", "paused", "completed", "archived"] @@ -21,7 +22,7 @@ MAX_PROJECT_DEPTH = 5 _PROJECT_COLUMNS = """ 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 """ @@ -227,6 +228,7 @@ def create_project( roadmap_item_id: Optional[str] = None, sort_order: int = 0, target_date: Optional[date] = None, + archetype_key: Optional[str] = None, user_id: Optional[str] = None, ) -> dict[str, Any]: title = title.strip() @@ -234,9 +236,15 @@ def create_project( raise ValueError("Titel ist erforderlich") _validate_status(status) _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") + 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() try: with conn.cursor(cursor_factory=RealDictCursor) as cur: @@ -257,10 +265,10 @@ def create_project( f""" INSERT INTO projects ( tenant_id, initiative_id, parent_project_id, container_kind, - title, description, status, + archetype_key, title, description, status, 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} """, ( @@ -268,6 +276,7 @@ def create_project( initiative_id, parent_project_id, container_kind, + resolved_archetype, title, description, status, diff --git a/backend/services/steering_context.py b/backend/services/steering_context.py index 74d48f5..02852aa 100644 --- a/backend/services/steering_context.py +++ b/backend/services/steering_context.py @@ -100,6 +100,8 @@ def ensure_steering_context( initiative_id: str, initial_state: Optional[str] = None, user_id: Optional[str] = None, + method_key: Optional[str] = None, + lifecycle_metadata: Optional[dict[str, Any]] = None, ) -> dict[str, Any]: existing = get_steering_context(tenant_id=tenant_id, initiative_id=initiative_id) if existing: @@ -113,6 +115,16 @@ def ensure_steering_context( ) 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() try: with conn.cursor(cursor_factory=RealDictCursor) as cur: @@ -129,10 +141,10 @@ def ensure_steering_context( ( tenant_id, initiative_id, - DEFAULT_METHOD_KEY, - DEFAULT_METHOD_VERSION, + resolved_method, + method_version, state, - Json({}), + Json(metadata), ), ) row = _serialize_row(dict(cur.fetchone())) @@ -144,7 +156,11 @@ def ensure_steering_context( "steering_context.created", user_id=user_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 @@ -250,10 +266,25 @@ def create_context_for_new_initiative( tenant_id: str, initiative_id: str, user_id: Optional[str] = None, + archetype_key: str = "initiative.generic", + method_profile_key: Optional[str] = None, ) -> 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( tenant_id=tenant_id, initiative_id=initiative_id, initial_state="intake", user_id=user_id, + method_key=method_key, + lifecycle_metadata=lifecycle_metadata or None, ) diff --git a/backend/steering/__init__.py b/backend/steering/__init__.py index b389bb2..b638607 100644 --- a/backend/steering/__init__.py +++ b/backend/steering/__init__.py @@ -1,9 +1,15 @@ -"""Adaptive Steering Core — AP1.0 Foundation.""" +"""Adaptive Steering Core — AP1.0 Foundation + AP2.0 methods.""" from __future__ import annotations 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 @@ -13,6 +19,9 @@ def bootstrap_steering() -> None: register_builtin_strategies() generic_operating.register() product_milestone_driven.register() + program_delivery.register() + continuous_product.register() + ap20_method_stubs.register() bootstrap_steering() diff --git a/backend/steering/methods/registrations/_helpers.py b/backend/steering/methods/registrations/_helpers.py new file mode 100644 index 0000000..73d8115 --- /dev/null +++ b/backend/steering/methods/registrations/_helpers.py @@ -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, + ) diff --git a/backend/steering/methods/registrations/ap20_method_stubs.py b/backend/steering/methods/registrations/ap20_method_stubs.py new file mode 100644 index 0000000..39e6f6b --- /dev/null +++ b/backend/steering/methods/registrations/ap20_method_stubs.py @@ -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", + ) diff --git a/backend/steering/methods/registrations/continuous_product.py b/backend/steering/methods/registrations/continuous_product.py new file mode 100644 index 0000000..11a27c5 --- /dev/null +++ b/backend/steering/methods/registrations/continuous_product.py @@ -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", + ) diff --git a/backend/steering/methods/registrations/program_delivery.py b/backend/steering/methods/registrations/program_delivery.py new file mode 100644 index 0000000..ea87a01 --- /dev/null +++ b/backend/steering/methods/registrations/program_delivery.py @@ -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", + ) diff --git a/backend/steering/strategies/next_action/__init__.py b/backend/steering/strategies/next_action/__init__.py index 259ac00..78ef077 100644 --- a/backend/steering/strategies/next_action/__init__.py +++ b/backend/steering/strategies/next_action/__init__.py @@ -2,10 +2,18 @@ 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.product_milestone_driven import ( 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 ( get_next_action_strategy, register_next_action_strategy, @@ -16,3 +24,5 @@ def register_builtin_strategies() -> None: for strategy in (default_strategy, product_milestone_strategy): if not get_next_action_strategy(strategy.key): register_next_action_strategy(strategy) + register_program_delivery_strategy() + register_continuous_product_strategy() diff --git a/backend/steering/strategies/next_action/continuous_product.py b/backend/steering/strategies/next_action/continuous_product.py new file mode 100644 index 0000000..619a130 --- /dev/null +++ b/backend/steering/strategies/next_action/continuous_product.py @@ -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) diff --git a/backend/steering/strategies/next_action/program_delivery.py b/backend/steering/strategies/next_action/program_delivery.py new file mode 100644 index 0000000..8d29883 --- /dev/null +++ b/backend/steering/strategies/next_action/program_delivery.py @@ -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) diff --git a/backend/tests/test_ap110_initiative_archetypes.py b/backend/tests/test_ap110_initiative_archetypes.py index 74e6731..1658a60 100644 --- a/backend/tests/test_ap110_initiative_archetypes.py +++ b/backend/tests/test_ap110_initiative_archetypes.py @@ -49,7 +49,11 @@ def test_list_entity_archetypes(client): ) assert res.status_code == 200 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): diff --git a/backend/tests/test_ap20_steering_archetypes.py b/backend/tests/test_ap20_steering_archetypes.py new file mode 100644 index 0000000..e1607aa --- /dev/null +++ b/backend/tests/test_ap20_steering_archetypes.py @@ -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" diff --git a/backend/version.py b/backend/version.py index 3db984c..028726c 100644 --- a/backend/version.py +++ b/backend/version.py @@ -1,3 +1,3 @@ -APP_VERSION = "0.17.0-ap1.5d" -DB_SCHEMA_VERSION = "018" +APP_VERSION = "0.18.0-ap2.0" +DB_SCHEMA_VERSION = "019" APP_NAME = "jinkendo-kairo" diff --git a/docs/architecture/ADP_Archetype_and_Method_Catalog_v0.1.md b/docs/architecture/ADP_Archetype_and_Method_Catalog_v0.1.md new file mode 100644 index 0000000..67297a8 --- /dev/null +++ b/docs/architecture/ADP_Archetype_and_Method_Catalog_v0.1.md @@ -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` diff --git a/docs/architecture/ADP_Archetype_and_Method_Catalog_v0.2.md b/docs/architecture/ADP_Archetype_and_Method_Catalog_v0.2.md new file mode 100644 index 0000000..217a107 --- /dev/null +++ b/docs/architecture/ADP_Archetype_and_Method_Catalog_v0.2.md @@ -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 + 1–2 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 + 1–2 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 | 1–3 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) — 5–7 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 (1–3 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; 2–3 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 A1–D1 — **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:** A1–A3, 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` diff --git a/docs/product/Kairo_Implementation_Truth_Table_v0.1.md b/docs/product/Kairo_Implementation_Truth_Table_v0.1.md index a086bc2..97cc74c 100644 --- a/docs/product/Kairo_Implementation_Truth_Table_v0.1.md +++ b/docs/product/Kairo_Implementation_Truth_Table_v0.1.md @@ -65,7 +65,8 @@ Verhindert, dass Zielbild-Dokumente als Ist-Stand gelesen werden. | steering_contexts (009) | ✓ | Lifecycle, method_key | | backend/steering/ lifecycle | ✓ | | | 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 | | Portfolio-Priorität (Initiativen) | ✗ | | | Situativer Steuerungskontext (Next Action) | ✗ | 📄 Vision §7.6 | diff --git a/docs/product/Kairo_MVP_Definition_v0.3.md b/docs/product/Kairo_MVP_Definition_v0.3.md new file mode 100644 index 0000000..b5b17cb --- /dev/null +++ b/docs/product/Kairo_MVP_Definition_v0.3.md @@ -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 **2–3 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, 1–3 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: **1–3 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** (1–3), 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`; 1–3 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 A1–D1 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` diff --git a/docs/sprints/Sprint1_AP2_0_Steering_Archetypes_Assignment_v0.1.md b/docs/sprints/Sprint1_AP2_0_Steering_Archetypes_Assignment_v0.1.md new file mode 100644 index 0000000..08a9d5d --- /dev/null +++ b/docs/sprints/Sprint1_AP2_0_Steering_Archetypes_Assignment_v0.1.md @@ -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` diff --git a/frontend/package.json b/frontend/package.json index a02683f..e8127f6 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "kairo-jinkendo-frontend", - "version": "0.17.0-ap1.5d", + "version": "0.18.0-ap2.0", "private": true, "type": "module", "scripts": { diff --git a/frontend/src/components/SteeringSnapshotPanel.jsx b/frontend/src/components/SteeringSnapshotPanel.jsx index e9c9484..1264520 100644 --- a/frontend/src/components/SteeringSnapshotPanel.jsx +++ b/frontend/src/components/SteeringSnapshotPanel.jsx @@ -49,6 +49,11 @@ export function SteeringSnapshotPanel({ lifecycle_label, method_key, method_label, + archetype_key, + archetype_label, + method_profile_key, + steering_guidance, + attention_items = [], signals = [], counts, upcoming_milestones = [], @@ -74,6 +79,9 @@ export function SteeringSnapshotPanel({

Wo stehe ich — und was ist als Nächstes dran?

+ {steering_guidance && ( +

{steering_guidance}

+ )} {displayLabel} @@ -81,6 +89,12 @@ export function SteeringSnapshotPanel({
+ {(archetype_label || archetype_key) && ( +

+ Archetyp: {archetype_label || archetype_key} + {method_profile_key ? ` · Ausprägung: ${method_profile_key}` : ''} +

+ )} {(method_label || canManageMethod) && (

Methode: @@ -117,9 +131,13 @@ export function SteeringSnapshotPanel({

- {signals?.length > 0 && ( -

- {signals.map((s) => SIGNAL_LABELS[s] || s).join(' · ')} + {(attention_items?.length > 0 || signals?.length > 0) && ( +

+ Attention:{' '} + {(attention_items.length > 0 + ? attention_items.map((a) => a.label) + : signals.map((s) => SIGNAL_LABELS[s] || s) + ).join(' · ')}

)} @@ -135,6 +153,7 @@ export function SteeringSnapshotPanel({ {item.title} {NEXT_ACTION_KIND_LABELS[item.kind] || item.kind} + {item.reason_code ? ` · ${item.reason_code}` : ''} {item.recommended_action ? ` — ${item.recommended_action}` : ''} diff --git a/frontend/src/styles/components.css b/frontend/src/styles/components.css index f4ff176..e1d3da7 100644 --- a/frontend/src/styles/components.css +++ b/frontend/src/styles/components.css @@ -716,6 +716,21 @@ 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 { margin: 0.5rem 0 0; font-size: 0.9rem;