Kairo-Jinkendo/docs/architecture/ADP_UX_Composition_Kernel_v0.1.md
Lars 43d33d0edb
All checks were successful
Deploy Development / deploy (push) Successful in 47s
Test Suite / pytest-backend (push) Successful in 4m24s
Test Suite / lint-backend (push) Successful in 2s
Test Suite / compose-smoke (push) Has been skipped
Test Suite / k6 /api/health Baseline (push) Successful in 18s
Test Suite / playwright-smoke (push) Successful in 12s
feat(AP2.2b, UX): Linear E2E, Composition-Kernel und Steering-Paritaet
AP2.2b: Integrationstests Neue-Kueche-Happy-Path, Truth Table und Execution Plan abgeschlossen. UX Composition Kernel (Control/Plan/Cockpit-Slots), CriticalPathPanel aus Kernel-Read-Model mit Gate-Horizont, Next Action elementgesteuert ohne Snapshot-Doppelung, Product-Continuous-Copy und Plan/Arbeit ueber Kernel planning_debt.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-27 13:34:13 +02:00

183 lines
6.9 KiB
Markdown

# ADP — UX Composition Kernel v0.1 (AP-UX-0 / AP-UX-1)
**Status:** PO-Arbeitsentwurf — **MVP geliefert** (2026-07-27)
**Stand:** 2026-07-27
**Bezug:** `ADP_Steering_Kernel_Extension_Model_v0.1.md`, `ADP_AP2_4_Steering_Elements_and_Method_Contract_v0.1.md`, `Kairo_PM_Frontend_UI_Concept_v0.1.md`, `ARCHETYPE_UI_NAVIGATION_v0.1.md`
---
## 1. Problem
Das Backend hat mit dem **Steering Kernel v0.4** einen zentralen Steuerungs-Einstieg (`evaluate_steering()`). Provider für Read Models, Proposals und Agent-Slots hängen an **registrierten Keys** und `steering_elements` — nicht an Archetyp-Ifs.
Das Frontend spiegelt das **noch nicht zentral**:
| Baustein | Heute | Soll |
|----------|-------|------|
| Control-Panels | `InitiativeOverviewPage` mit manuellen Ifs | UI-Slots + Provider |
| Proposals | `SteeringProposalsPanel` direkt in Plan-Pages | Slot `plan.*.proposals` |
| Agent-Slots | Direktimport in Overview | Slot `control.status.agent` |
| Cockpit-Widgets | `widgetRegistry` + manuelle Grid-Schleife | Slot `cockpit.main` |
| Steuerungselement-Registry | Labels/Hints only | Aktiviert Composition-Provider |
**Leitfrage:** Wie composen Cockpit, Control und Plan konsistent aus dem gleichen Modell — analog zum Steering Kernel?
---
## 2. Entscheidung — Vier Schichten (Frontend-Spiegel)
```text
Operating Context + Steering Snapshot
resolveSteeringComposition(mode, routeKey, scope, context)
UI-Slots (z.B. control.status.steering, plan.inbox.proposals)
registrierte Provider (steering_element | proposal | agent_slots | widget | core)
React-Komponenten (generisch, keine Archetyp-Ifs)
```
| Schicht | Registry | Liefert |
|---------|----------|---------|
| **UI-Slot** | `composition/uiSlotRegistry.js` | Benannte Flächen pro Modus/Route |
| **Provider** | `composition/compositionProviders.js` | Match-Regeln + Slot-Zuordnung |
| **Resolver** | `composition/resolveSteeringComposition.js` | Aktive Provider pro Slot zur Laufzeit |
| **Renderer** | `CompositionSlot.jsx`, `providerComponents.jsx` | Generisches Rendering |
**Parallele zum Backend:**
| Backend (Steering Kernel) | Frontend (UX Composition) |
|---------------------------|---------------------------|
| `steering_elements` | Provider `kind: steering_element` |
| `proposals[key]` | Provider `kind: proposal` |
| `agent_slots[]` | Provider `kind: agent_slots` |
| Portfolio-Aggregation | Provider `kind: widget` (Cockpit) |
| Snapshot-Kern | Provider `kind: core` |
---
## 3. UI-Slots (MVP)
Slots sind **stabil benannte Flächen** — unabhängig von React-Page-Struktur.
| Slot-Key | Modus | Route | Inhalt (MVP) |
|----------|-------|-------|--------------|
| `cockpit.main` | cockpit | — | Portfolio-Widgets |
| `control.status.core` | control | status | Steering-Snapshot |
| `control.status.steering` | control | status | Kritischer Pfad, Next Action |
| `control.status.agent` | control | status | Agent-Slots |
| `control.status.alerts` | control | status | Roadblocker-Strip |
| `plan.inbox.proposals` | plan | inbox | Triage-Vorschläge |
| `plan.sprint.proposals` | plan | sprint | Sprint-Commit-Vorschläge |
| `plan.gates.proposals` | plan | gates | Gate-Vorschläge |
**Erweiterung (post-MVP):** `control.plan-ist.read_models`, `plan.inbox.read_models`, Work-Modus-Slots.
---
## 4. Provider-Vertrag
```javascript
{
key: 'steering.critical_path',
kind: 'steering_element', // steering_element | proposal | agent_slots | widget | core | conditional
steeringElement: 'critical_path',
slotKeys: ['control.status.steering'],
componentKey: 'CriticalPathPanel',
requiresCapability: 'kairo.action.read',
scopeTypes: ['initiative'], // portfolio | initiative
order: 10,
}
```
### Match-Regeln
| kind | Aktiv wenn |
|------|------------|
| `steering_element` | `steering_elements` enthält Key |
| `proposal` | `steering_kernel.proposals[key]` nicht leer (+ optional `filterContext`) |
| `agent_slots` | `agent_slots` oder `steering_kernel.agent_slots` nicht leer |
| `widget` | Capability erfüllt; Widget aus `widgetRegistry` |
| `core` | Immer auf Surface (Scope + Capability) |
| `conditional` | Custom predicate (z.B. Roadblocker counts > 0) |
**Verboten:** `archetype_key === '…'` in Pages — nur Provider-Match über Operating Context.
---
## 5. Auflösung zur Laufzeit
```javascript
resolveSteeringComposition({
mode: 'control',
routeKey: 'status',
scope: 'initiative',
operatingContext,
steeringSnapshot,
capabilities,
filterContext: {},
// Initiative-Ops für Props:
opsContext: { initiativeId, actions, ... },
})
// → { surfaceKey: 'control.status', slots: { 'control.status.core': [ProviderInstance, ...], ... } }
```
Surfaces sind deklarativ in `COMPOSITION_SURFACES` — eine Page rendert `<CompositionSurface surfaceKey="control.status" />` statt ad-hoc Imports.
---
## 6. Frontend-Dateien (MVP)
```text
frontend/src/composition/
uiSlotRegistry.js — Slot- + Surface-Definitionen
compositionProviders.js — Provider-Registry
resolveSteeringComposition.js — Resolver + buildProviderProps
resolveSteeringComposition.test.js
providerComponents.jsx — Component-Map + Prop-Adapter
CompositionSlot.jsx — Slot-Renderer
CompositionSurface.jsx — Surface-Renderer (mehrere Slots)
useSteeringComposition.js — Hook (InitiativeOperationsContext)
```
---
## 7. Migration (AP-UX-1)
| Page | Vorher | Nachher |
|------|--------|---------|
| `InitiativeOverviewPage` | Manuelle Panel-Ifs | `CompositionSurface surfaceKey="control.status"` |
| `InitiativeInboxPage` | Direkt `SteeringProposalsPanel` | Slot `plan.inbox.proposals` |
| `PlanSprintPage` | Direkt `SteeringProposalsPanel` | Slot `plan.sprint.proposals` |
| `InitiativePlanPage` | Direkt `SteeringProposalsPanel` | Slot `plan.gates.proposals` |
| `CockpitPage` | `getWidgetsForArea` Schleife | Slot `cockpit.main` via Composition |
**Nicht migriert (post-MVP):** `PlanIstPanel`, `BacklogSection`, `GatesPlanPanel` — Domain-CRUD bleibt außerhalb Composition (P4: Übersicht entscheidet, Detail pflegt).
---
## 8. Abnahme (AP-UX-1)
- [ ] `resolveSteeringComposition` Unit-Tests für alle Provider-Kinds
- [ ] Control/Plan-Pages ohne direkte `SteeringProposalsPanel`/`AgentSlotsPanel`-Imports
- [ ] Keine neuen Archetyp-Ifs in migrierten Pages
- [ ] Vitest grün (`npm test`)
- [ ] Dev-Deploy: Cockpit, Control/status, Plan/inbox/sprint/gates funktional
---
## 9. Referenzen
| Artefakt | Pfad |
|----------|------|
| Steering Element Registry | `frontend/src/registry/steeringElementRegistry.js` |
| Proposal UI Config | `frontend/src/utils/steeringProposals.js` |
| Widget Registry | `frontend/src/registry/widgetRegistry.js` |
| Operating Profile | `frontend/src/registry/resolveOperatingProfile.js` |
| Steering Kernel Coding Rules | `docs/architecture/ADP_Steering_Kernel_Coding_Rules_v0.1.md` |
---
*AP-UX-0 = dieses ADP. AP-UX-1 = MVP-Implementierung unter `frontend/src/composition/`.*