Kairo-Jinkendo/docs/sprints/Sprint1_AP1_0_Steering_Foundation_Assignment_v0.1.md

225 lines
6.6 KiB
Markdown
Raw Permalink Normal View History

# AP1.0 — Steering Foundation (Skeleton)
## Implementierungsauftrag v0.1
**Status:** umgesetzt
**Stand:** 2026-07-05
**Vorgänger:** AP0.10b ✓
**ADP:** `docs/architecture/ADP_AP1_0_Steering_Foundation_Scope_Lock_v0.1.md`
**Zielversion:** `0.11.0-ap1.0` · Schema `009`
---
## Ziel
**Eine persistierte Steuerungswahrheit pro Initiative** — Standard Lifecycle als Foundation, in die Methoden später einhängen.
Leitfrage bleibt: *Welcher nächste Schritt bringt ein Vorhaben am wirkungsvollsten voran?* — technisch beantwortet über `SteeringContext.lifecycle_state` + Signal Engine, nicht über verstreute Heuristiken.
---
## Scope Lock (verbindlich)
Siehe ADP § Scope Lock. **Kein AP0.10c.** Keine neuen Attention-Regeln. Keine neuen OM-Tabellen außer `steering_contexts`.
---
## Teil A — Schema 009
### Tabelle `steering_contexts`
```sql
CREATE TABLE steering_contexts (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
initiative_id UUID NOT NULL REFERENCES initiatives(id) ON DELETE CASCADE,
method_key VARCHAR(64) NOT NULL DEFAULT 'generic_operating',
method_version VARCHAR(32) NOT NULL DEFAULT '0.1.0',
lifecycle_state VARCHAR(64) NOT NULL DEFAULT 'intake',
lifecycle_metadata JSONB NOT NULL DEFAULT '{}',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
UNIQUE (tenant_id, initiative_id)
);
CREATE INDEX idx_steering_contexts_tenant ON steering_contexts(tenant_id);
```
### Backfill (Seed oder Migration-Block)
Bestehende Initiativen erhalten Context:
| Bedingung | `lifecycle_state` |
|-----------|-------------------|
| `status IN (completed, archived)` | `closure` |
| offene Actions existieren | `action_selection` |
| nur Backlog (new/triaged/accepted), keine offenen Actions | `structure_setup` |
| sonst active/paused | `planning` |
---
## Teil B — `backend/steering/`
### B1 — Lifecycle
**Datei:** `steering/lifecycle/states.py`
```python
STANDARD_LIFECYCLE_STEPS = (
"intake", "method_selection", "structure_setup", "planning",
"action_selection", "assignment", "waiting", "result_intake",
"validation", "review", "adaptation", "closure",
)
```
**Datei:** `steering/lifecycle/orchestrator.py`
- `get_lifecycle_state(ctx, initiative_id) -> str`
- `transition(ctx, initiative_id, to_state, *, reason: str) -> dict` — Guard minimal: nur erlaubte Übergänge aus `generic_operating` oder freier Übergang für AP1.0 stub
- Audit-Log bei Transition
### B2 — Hook Registry
**Datei:** `steering/hooks/registry.py`
- `HookDefinition` dataclass (slug, lifecycle_step, description, since_version)
- `register_hook()`, `get_hook()`, `list_hooks()`
- Registrierung der Slugs aus Target Architecture §7.3 (Definition only, Implementierung stub)
**Datei:** `steering/hooks/dispatch.py`
- `dispatch_hook(slug, ctx, payload) -> list[dict]` — ruft registrierte Handler; AP1.0: leere Handler + Audit-Eintrag
### B3 — Method Registry
**Datei:** `steering/methods/registry.py` + `registrations/generic_operating.py`
- Eine Built-in-Methode: `generic_operating`
- Liefert: `default_lifecycle_steps`, erlaubte Hooks (alle globalen), keine Structure Builder
### B4 — Signal Engine
**Datei:** `steering/signals/default_rules.py`
- Bestehende Regeln aus `data_layer/attention.py` **verschieben** (nicht duplizieren)
- `evaluate_attention(ctx) -> list[dict]`
- `evaluate_next_actions(ctx, *, limit, initiative_id=None) -> list[dict]`
**Datei:** `steering/signals/engine.py`
- `evaluate(ctx, kind='attention'|'next_action', **kwargs)` — delegiert an default_rules
**Datei:** `data_layer/attention.py`
- Wird dünner Wrapper um `steering.signals.engine` (API-Kompatibilität)
### B5 — Steering Context Service
**Datei:** `steering/context.py` + `services/steering_context.py` (Write)
- `get_or_create_for_initiative(ctx, initiative_id)`
- `get_steering_context(ctx, initiative_id) -> Optional[dict]`
- Tenant-scoped; Cross-Tenant → None / 404
---
## Teil C — Integration bestehender Flows
### C1 — `operating_transitions.py`
Vor/nach bestehender Logik:
```python
from steering.hooks.dispatch import dispatch_hook
dispatch_hook("on_blocker_resolved", ctx, {...})
# optional: lifecycle transition assignment → action_selection
```
Verhalten Blocker→entblocken **unverändert** (Regression-Tests).
### C2 — `initiative_snapshot.py`
Snapshot ergänzt:
```json
{
"lifecycle_state": "action_selection",
"lifecycle_label": "Maßnahmen auswählen",
"operating_phase": "execute",
"operating_phase_deprecated": true
}
```
`_derive_operating_phase` bleibt für Rückwärtskompatibilität; markiert deprecated in Docstring.
### C3 — Initiative Create
Bei `create_initiative` → `steering_contexts` Zeile anlegen (`lifecycle_state=intake` oder Backfill-Regel).
---
## Teil D — API
| Endpoint | Capability | Beschreibung |
|----------|------------|--------------|
| `GET /api/initiatives/{id}/steering-context` | `kairo.initiative.read` | Context DTO |
| `GET .../steering-snapshot` | (bestehend) | + lifecycle Felder |
---
## Teil E — Frontend (minimal)
**Datei:** `frontend/src/constants/operating.js`
- `LIFECYCLE_LABELS` für 12 Standard-Schritte (DE)
- Steuerungszustand-Panel: primär `lifecycle_label`; `operating_phase` nur Fallback
Kein Maßnahmen-Hub. Keine neuen Widgets.
---
## Teil F — Tests
| Test | Erwartung |
|------|-----------|
| `test_ap1_steering_context.py` | CRUD Context, tenant isolation |
| `test_ap1_lifecycle.py` | Transition + Audit |
| `test_ap1_signals_regression.py` | Attention/NextAction gleich wie vor Refactor |
| `test_ap10_integration.py` | weiter grün; Snapshot hat lifecycle_state |
---
## Nicht-Scope
- Workflow Runtime, Waiting/Reminder Scheduler
- Zweite Built-in-Methode (`product_milestone_driven`) → AP1.1
- `roadmap_items`, `projects`, `milestones`-Migration
- AP0.10c UI
- Prompt/KI/MCP
- Entfernen von `operating_phase` → AP1.2
---
## Abnahme
1. Migration 009 deployed; bestehende Initiativen haben Context
2. `backend/steering/` existiert mit Lifecycle, Hooks, Methods, Signals
3. Attention/NextAction APIs unverändert im Verhalten (Regression)
4. Snapshot + neuer steering-context Endpoint liefern `lifecycle_state`
5. Scope Lock aus ADP eingehalten (kein AP0.10c)
6. pytest grün remote
---
## Reihenfolge Implementierung
1. Migration 009 + Backfill
2. `steering/lifecycle`, `steering/context`
3. Initiative-Create Hook
4. `steering/signals` Refactor aus attention.py
5. Hook dispatch in operating_transitions
6. API + Snapshot + Frontend Labels
7. Tests + Version bump
---
*Nächster Schritt nach Abnahme: AP0.10d Validation Report, dann AP1.1 Method Registry erweitern*