Add all BMAD skill artifacts: epics, stories, sprint-status, QA tests, project-context, readiness report
Co-authored-by: Kenearos <86194771+Kenearos@users.noreply.github.com>
This commit is contained in:
parent
e37cb6f4c0
commit
3be3cb73b6
14 changed files with 1577 additions and 4 deletions
159
_bmad-output/implementation-artifacts/qa-e2e-tests.md
Normal file
159
_bmad-output/implementation-artifacts/qa-e2e-tests.md
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
---
|
||||
inputDocuments:
|
||||
- _bmad-output/planning-artifacts/epics.md
|
||||
- _bmad-output/planning-artifacts/architecture.md
|
||||
- backend/tests/
|
||||
bmadSkill: 'QA Agent (Quinn) — /bmad-agent-bmm-qa → [QE] Generate E2E Tests'
|
||||
bmadWorkflow: '_bmad/bmm/workflows/qa-generate-e2e-tests/workflow.yaml'
|
||||
---
|
||||
|
||||
<!-- 🧪 Generated by BMAD QA Skill — Agent: Quinn (QA Engineer) -->
|
||||
<!-- Skill Command: /bmad-agent-bmm-qa → Generate E2E Tests -->
|
||||
<!-- Workflow: _bmad/bmm/workflows/qa-generate-e2e-tests/workflow.yaml -->
|
||||
|
||||
# QA E2E Test-Manifest — CouncilOS
|
||||
|
||||
**Autor:** Quinn (🧪 BMAD QA Agent)
|
||||
**Datum:** 2026-03-12
|
||||
|
||||
---
|
||||
|
||||
## 1. Bestehende Unit-Tests (Backend)
|
||||
|
||||
| Datei | Beschreibung | Status |
|
||||
|-------|-------------|--------|
|
||||
| `backend/tests/test_state.py` | CouncilState-Reducer, operator.add | ✅ |
|
||||
| `backend/tests/test_routing.py` | Routing-Logik (score < 8, ≥ 8, safety valve) | ✅ |
|
||||
| `backend/tests/test_api.py` | Health-Check, Run-Endpunkte (httpx AsyncClient) | ✅ |
|
||||
| `backend/tests/test_blueprint_api.py` | Blueprint CRUD REST-API | ✅ |
|
||||
| `backend/tests/test_blueprint_service.py` | Blueprint-Service-Layer | ✅ |
|
||||
| `backend/tests/test_dynamic_graph_builder.py` | Dynamischer Graph-Builder | ✅ |
|
||||
| `backend/tests/test_god_mode.py` | Human-in-the-Loop (approve/reject/modify) | ✅ |
|
||||
| `backend/tests/test_run_service.py` | Run-History-Service | ✅ |
|
||||
| `backend/tests/test_run_store.py` | In-Memory-Run-Store | ✅ |
|
||||
| `backend/tests/test_tools.py` | Web-Search und PDF-Reader (gemockt) | ✅ |
|
||||
|
||||
## 2. Frontend-Unit-Tests
|
||||
|
||||
| Datei | Beschreibung | Status |
|
||||
|-------|-------------|--------|
|
||||
| `frontend/app/__tests__/` | Vitest-Tests für React-Komponenten | ✅ |
|
||||
|
||||
---
|
||||
|
||||
## 3. E2E-Test-Szenarien (für Playwright / Cypress — Post-MVP)
|
||||
|
||||
### TC-E2E-001: Council erstellen und ausführen (Happy Path)
|
||||
|
||||
**Voraussetzung:** Backend läuft auf Port 8000, Frontend auf 3000
|
||||
|
||||
**Schritte:**
|
||||
1. Öffne `http://localhost:3000`
|
||||
2. Wechsel zum Tab „Rat-Architekt"
|
||||
3. Ziehe einen Agent-Node auf den Canvas
|
||||
4. Setze Name: „Test Master", System-Prompt: „Du bist ein Test-Agent"
|
||||
5. Ziehe einen zweiten Node (Critic)
|
||||
6. Verbinde die Nodes mit einer linearen Edge
|
||||
7. Klicke „Speichern" → Bestätigungsmeldung erscheint
|
||||
8. Wechsel zum Tab „Konferenzzimmer"
|
||||
9. Gib Prompt: „Schreibe einen kurzen Test-Text" ein
|
||||
10. Wähle „Auto-Pilot"
|
||||
11. Klicke „Starten"
|
||||
12. Beobachte: Erster Node pulsiert gelb
|
||||
13. Nach Abschluss: Finaler Text erscheint im Output-Bereich
|
||||
|
||||
**Erwartetes Ergebnis:** Run erreicht `status=completed`, `final_draft` nicht leer
|
||||
|
||||
---
|
||||
|
||||
### TC-E2E-002: God Mode — Approve
|
||||
|
||||
**Schritte:**
|
||||
1. Wähle „God Mode" im Toggle
|
||||
2. Starte Run mit beliebigem Prompt
|
||||
3. Nach erstem Node: Overlay erscheint
|
||||
4. Klicke „Genehmigen"
|
||||
5. Nächster Node startet (pulsiert)
|
||||
6. Bis Abschluss: alle Nodes genehmigen
|
||||
|
||||
**Erwartetes Ergebnis:** Run erreicht `status=completed`
|
||||
|
||||
---
|
||||
|
||||
### TC-E2E-003: God Mode — Reject
|
||||
|
||||
**Schritte:**
|
||||
1. Starte Run in God Mode
|
||||
2. Overlay erscheint
|
||||
3. Klicke „Ablehnen"
|
||||
|
||||
**Erwartetes Ergebnis:** Run `status=failed`, Fehlermeldung „Rejected by user" sichtbar
|
||||
|
||||
---
|
||||
|
||||
### TC-E2E-004: PDF-Upload und Verwendung
|
||||
|
||||
**Schritte:**
|
||||
1. Öffne `POST /api/councils/upload-pdf` mit Test-PDF
|
||||
2. Response enthält `chunks_ingested > 0`
|
||||
3. Erstelle Council mit Agent, der `pdf_reader=true` hat
|
||||
4. Starte Run mit Thema aus dem PDF
|
||||
5. Agent-Output referenziert PDF-Inhalte
|
||||
|
||||
**Erwartetes Ergebnis:** Chunks werden korrekt eingelesen und sind abrufbar
|
||||
|
||||
---
|
||||
|
||||
### TC-E2E-005: WebSocket-Events in korrekter Reihenfolge
|
||||
|
||||
**Schritte:**
|
||||
1. Verbinde mit `WS /ws/council/{run_id}`
|
||||
2. Starte Run
|
||||
3. Zeichne alle empfangenen Events auf
|
||||
|
||||
**Erwartetes Ergebnis:**
|
||||
```
|
||||
{"node": "master_agent", "status": "running"}
|
||||
{"node": "master_agent", "status": "completed"}
|
||||
{"node": "critic_agent", "status": "running"}
|
||||
{"node": "critic_agent", "status": "completed"}
|
||||
... (ggf. Schleife)
|
||||
{"node": "writer_agent", "status": "running"}
|
||||
{"node": "writer_agent", "status": "completed"}
|
||||
{"status": "done"}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Test-Mocking-Konventionen
|
||||
|
||||
```python
|
||||
# Standard-Mock-Pattern für alle Agent-Tests (CLAUDE.md-Anforderung)
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
@patch("agents.master_agent.ChatAnthropic")
|
||||
def test_master_agent_node_appends_to_messages(mock_llm):
|
||||
mock_llm.return_value.invoke.return_value = MagicMock(content="Draft v2")
|
||||
state = {...}
|
||||
result = master_agent_node(state)
|
||||
assert result["current_draft"] == "Draft v2"
|
||||
```
|
||||
|
||||
**Regeln (aus CLAUDE.md):**
|
||||
- ❌ Niemals echte LLM-API-Aufrufe in Tests
|
||||
- ❌ Kein shared Test-Datenbankzustand (Transactions rollback)
|
||||
- ❌ Kein Snapshot-Test für React Flow Canvas
|
||||
- ✅ Immer beide Seiten der Threshold-Grenze testen (7.9 und 8.0)
|
||||
|
||||
---
|
||||
|
||||
## 5. Coverage-Ziele
|
||||
|
||||
| Modul | Ziel-Coverage |
|
||||
|-------|--------------|
|
||||
| `backend/state.py` | ≥ 90 % |
|
||||
| `backend/services/graph_builder.py` | ≥ 90 % |
|
||||
| `backend/services/dynamic_graph_builder.py` | ≥ 85 % |
|
||||
| `backend/agents/` | ≥ 80 % |
|
||||
| `backend/api/` | ≥ 75 % |
|
||||
| `backend/tools/` | ≥ 75 % |
|
||||
91
_bmad-output/implementation-artifacts/sprint-status.yaml
Normal file
91
_bmad-output/implementation-artifacts/sprint-status.yaml
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
# Sprint Status — CouncilOS
|
||||
# Generated by BMAD SM Skill — Agent: Bob (Scrum Master)
|
||||
# Skill Command: /bmad-agent-bmm-sm → [SP] Sprint Planning
|
||||
# Workflow: _bmad/bmm/workflows/4-implementation/sprint-planning/workflow.yaml
|
||||
|
||||
# generated: 2026-03-12
|
||||
# project: CouncilOS (KI-Rat Baukasten)
|
||||
# project_key: COUNCILSOOS
|
||||
# tracking_system: file-system
|
||||
# story_location: "_bmad-output/implementation-artifacts/stories"
|
||||
|
||||
# STATUS DEFINITIONS:
|
||||
# ==================
|
||||
# Epic Status:
|
||||
# - backlog: Epic not yet started
|
||||
# - in-progress: Epic actively being worked on
|
||||
# - done: All stories in epic completed
|
||||
#
|
||||
# Story Status:
|
||||
# - backlog: Story only exists in epic file
|
||||
# - ready-for-dev: Story file created, ready for development
|
||||
# - in-progress: Developer actively working on implementation
|
||||
# - review: Implementation complete, ready for review
|
||||
# - done: Story completed
|
||||
#
|
||||
# Retrospective Status:
|
||||
# - optional: Can be completed but not required
|
||||
# - done: Retrospective has been completed
|
||||
#
|
||||
# WORKFLOW NOTES:
|
||||
# ===============
|
||||
# - Mark epic as 'in-progress' when starting work on its first story
|
||||
# - SM typically creates next story ONLY after previous one is 'done' to incorporate learnings
|
||||
# - Dev moves story to 'review', then Dev runs code-review (fresh context, ideally different LLM)
|
||||
|
||||
generated: 2026-03-12
|
||||
project: CouncilOS
|
||||
project_key: COUNCILSOOS
|
||||
tracking_system: file-system
|
||||
story_location: "_bmad-output/implementation-artifacts/stories"
|
||||
|
||||
development_status:
|
||||
# ─────────────────────────────────────────────────────────────────
|
||||
# Epic 1: Projekt-Setup & Infrastruktur
|
||||
# ─────────────────────────────────────────────────────────────────
|
||||
epic-1: done
|
||||
1-1-docker-compose-umgebung-aufsetzen: done
|
||||
1-2-backend-python-umgebung-requirements: done
|
||||
1-3-datenbank-migrationen-mit-alembic: done
|
||||
epic-1-retrospective: done
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────
|
||||
# Epic 2: LangGraph Engine Backend (Phase 1)
|
||||
# ─────────────────────────────────────────────────────────────────
|
||||
epic-2: done
|
||||
2-1-councilstate-typeddict-implementieren: done
|
||||
2-2-master-agent-node-implementieren: done
|
||||
2-3-critic-agent-node-implementieren: done
|
||||
2-4-writer-agent-node-implementieren: done
|
||||
2-5-langgraph-graph-bauen-und-ausfuehren: done
|
||||
2-6-fastapi-run-endpunkte-implementieren: done
|
||||
epic-2-retrospective: done
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────
|
||||
# Epic 3: Visueller Baukasten Frontend (Phase 2)
|
||||
# ─────────────────────────────────────────────────────────────────
|
||||
epic-3: done
|
||||
3-1-react-flow-canvas-mit-custom-agent-node: done
|
||||
3-2-lineare-und-bedingte-edges: done
|
||||
3-3-blueprint-parser-react-flow-json: done
|
||||
3-4-blueprint-crud-frontend-backend: done
|
||||
epic-3-retrospective: optional
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────
|
||||
# Epic 4: Frontend-Backend-Integration (Phase 3)
|
||||
# ─────────────────────────────────────────────────────────────────
|
||||
epic-4: done
|
||||
4-1-dynamischer-graph-builder-aus-blueprint-json: done
|
||||
4-2-websocket-agent-events-integrieren: done
|
||||
4-3-konferenzzimmer-live-execution-ui: done
|
||||
epic-4-retrospective: optional
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────
|
||||
# Epic 5: Tools & God Mode (Phase 4)
|
||||
# ─────────────────────────────────────────────────────────────────
|
||||
epic-5: done
|
||||
5-1-tavily-web-suche-als-agent-tool: done
|
||||
5-2-pdf-upload-chromadb-ingestion: done
|
||||
5-3-god-mode-human-in-the-loop: done
|
||||
5-4-run-verlauf-history: done
|
||||
epic-5-retrospective: optional
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
# Story 2.3: Critic-Agent-Node implementieren
|
||||
|
||||
<!-- 🏃 Prepared by BMAD SM Skill — Agent: Bob (Scrum Master) -->
|
||||
<!-- Skill Command: /bmad-agent-bmm-sm → [CS] Context Story -->
|
||||
<!-- Workflow: _bmad/bmm/workflows/4-implementation/create-story/workflow.yaml -->
|
||||
|
||||
Status: done
|
||||
|
||||
## Story
|
||||
|
||||
Als **Backend-Entwickler**,
|
||||
möchte ich **den `critic_agent_node` mit Score-Parsing, Routing-Logik und Safety-Valve**,
|
||||
so dass er **Drafts bewertet, `route_decision` korrekt setzt und Endlosschleifen verhindert**.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
1. Score < 8 → `route_decision = "rework"`, Feedback wird an `feedback_history` angehängt
|
||||
2. Score ≥ 8 → `route_decision = "approve"`, `feedback_history` bleibt unverändert
|
||||
3. `iteration_count >= MAX_ITERATIONS` → automatische Genehmigung ohne LLM-Aufruf (Safety Valve)
|
||||
4. Nicht-parsbare LLM-Antwort → Fallback `route_decision = "rework"`, kein Crash
|
||||
5. Score wird auf 0–10 geclampt (kein Overflow)
|
||||
|
||||
## Tasks / Subtasks
|
||||
|
||||
- [x] Task 1: `_parse_critic_response()` implementieren (AC: 1, 4, 5)
|
||||
- [x] Subtask 1.1: Regex für SCORE, VERDICT, FEEDBACK-Blöcke
|
||||
- [x] Subtask 1.2: Score-Clamping (max 0.0, min 10.0)
|
||||
- [x] Subtask 1.3: Fallback auf (0.0, "rework", full_content) bei Parse-Fehler
|
||||
- [x] Task 2: `critic_agent_node()` implementieren (AC: 1, 2, 3)
|
||||
- [x] Subtask 2.1: Safety-Valve prüfen vor LLM-Aufruf
|
||||
- [x] Subtask 2.2: LLM-Aufruf mit temperature=0.2
|
||||
- [x] Subtask 2.3: Route-Decision aus Score und APPROVAL_THRESHOLD ableiten
|
||||
- [x] Subtask 2.4: `feedback_history` nur bei rework anhängen
|
||||
- [x] Task 3: Unit-Tests schreiben (AC: 1–5)
|
||||
- [x] Subtask 3.1: Test score < 8 → rework
|
||||
- [x] Subtask 3.2: Test score ≥ 8 → approve
|
||||
- [x] Subtask 3.3: Test safety valve bei MAX_ITERATIONS
|
||||
- [x] Subtask 3.4: Test Parse-Fehler-Fallback
|
||||
|
||||
## Dev Notes
|
||||
|
||||
- **LLM-Mocking:** `@patch("agents.critic_agent.ChatAnthropic")` in allen Unit-Tests
|
||||
- **Kein echter API-Aufruf in CI** — strikte Anforderung aus CLAUDE.md
|
||||
- **Threshold-Tests:** Immer beide Seiten testen (score=7.9 → rework, score=8.0 → approve)
|
||||
- Bezug: `backend/state.py#APPROVAL_THRESHOLD`, `backend/state.py#MAX_ITERATIONS`
|
||||
|
||||
### Project Structure Notes
|
||||
|
||||
- Implementiert in: `backend/agents/critic_agent.py`
|
||||
- Tests in: `backend/tests/test_routing.py`
|
||||
|
||||
### References
|
||||
|
||||
- [Source: CLAUDE.md#Python Code Style] — Type hints mandatory
|
||||
- [Source: _bmad-output/planning-artifacts/architecture.md#CouncilState] — State contract
|
||||
- [Source: _bmad-output/planning-artifacts/epics.md#Story-2.3] — ACs
|
||||
|
||||
## Dev Agent Record
|
||||
|
||||
### Agent Model Used
|
||||
|
||||
Amelia (💻 BMAD Dev Agent) — `dev-story` workflow
|
||||
|
||||
### Completion Notes List
|
||||
|
||||
- Score-Clamping verhindert Werte außerhalb 0–10 auch bei fehlerhafter LLM-Formatierung.
|
||||
- Safety-Valve gibt `APPROVAL_THRESHOLD` als Score zurück (nicht 10.0), damit Tests einheitlich bleiben.
|
||||
- Feedback wird nur bei `rework` angehängt, da `operator.add`-Reducer andernfalls Genehmigungen in die History schreibt.
|
||||
|
||||
### File List
|
||||
|
||||
- `backend/agents/critic_agent.py`
|
||||
- `backend/tests/test_routing.py`
|
||||
- `backend/state.py` (nur gelesen, nicht verändert)
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
# Story 4.1: Dynamischer Graph-Builder aus Blueprint-JSON
|
||||
|
||||
<!-- 🏃 Prepared by BMAD SM Skill — Agent: Bob (Scrum Master) -->
|
||||
<!-- Skill Command: /bmad-agent-bmm-sm → [CS] Context Story -->
|
||||
<!-- Workflow: _bmad/bmm/workflows/4-implementation/create-story/workflow.yaml -->
|
||||
|
||||
Status: done
|
||||
|
||||
## Story
|
||||
|
||||
Als **Backend-Entwickler**,
|
||||
möchte ich **`dynamic_graph_builder.py`**,
|
||||
so dass er **aus einem Blueprint-JSON zur Laufzeit einen kompilierten LangGraph-Graphen baut, der Zyklen korrekt erhält**.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
1. Valides Blueprint-JSON mit N Nodes → kompilierter `StateGraph`
|
||||
2. Blueprint mit Zyklus (A→B→A, bedingt) → Graph kompiliert, Zyklus erhalten
|
||||
3. Blueprint mit nicht-existenter Node-ID in Edge → `ValueError` mit sprechender Fehlermeldung
|
||||
4. Blueprint mit 0 Nodes → `ValueError`
|
||||
5. Blueprint mit 2 Nodes, 0 Edges → `ValueError`
|
||||
6. Bedingte Edge mit `condition`-Label wird korrekt als conditional edge verdrahtet
|
||||
7. Nodes mit `tools.web_search = true` bekommen Tavily-Tool gebunden
|
||||
8. Nodes mit `tools.pdf_reader = true` bekommen PDF-Search-Tool gebunden
|
||||
|
||||
## Tasks / Subtasks
|
||||
|
||||
- [x] Task 1: Blueprint-JSON-Schema validieren (AC: 3, 4, 5)
|
||||
- [x] Subtask 1.1: Prüfen ob `nodes` nicht leer
|
||||
- [x] Subtask 1.2: Alle Edge `source`/`target` IDs auf Existenz in `nodes` prüfen
|
||||
- [x] Subtask 1.3: Sicherstellen ≥1 Edge vorhanden
|
||||
- [x] Task 2: Node-Funktionen dynamisch erzeugen (AC: 1, 7, 8)
|
||||
- [x] Subtask 2.1: Agent-Node-Fabrik mit konfigurierbarem System-Prompt und Modell
|
||||
- [x] Subtask 2.2: Tool-Binding für web_search/pdf_reader
|
||||
- [x] Task 3: Graph-Topologie aufbauen (AC: 1, 2, 6)
|
||||
- [x] Subtask 3.1: Entry-Point = erster Node ohne eingehende Edges
|
||||
- [x] Subtask 3.2: Lineare Edges als `add_edge`
|
||||
- [x] Subtask 3.3: Bedingte Edges als `add_conditional_edges` mit Routing-Funktion
|
||||
- [x] Task 4: God-Mode-Unterstützung via `interrupt_before` (AC für Story 5.3)
|
||||
- [x] Subtask 4.1: `interrupt_before=node_ids` beim Kompilieren setzen
|
||||
- [x] Task 5: Unit-Tests (AC: 1–6)
|
||||
- [x] Subtask 5.1: Test valides Blueprint
|
||||
- [x] Subtask 5.2: Test Blueprint mit Zyklus
|
||||
- [x] Subtask 5.3: Test Blueprint mit ungültiger Edge (ValueError)
|
||||
- [x] Subtask 5.4: Test Blueprint mit 0 Nodes (ValueError)
|
||||
|
||||
## Dev Notes
|
||||
|
||||
- **Zyklen sind First-Class**: Niemals den Graphen zu einem DAG vereinfachen.
|
||||
- **Entry-Point-Erkennung**: Node ohne eingehende Edges = Startpunkt. Bei Zyklen: erster Node in `nodes`-Array.
|
||||
- **Routing-Funktion**: Dynamisch erzeugte Closure über `route_decision`-State-Feld.
|
||||
- Bezug: `backend/state.py`, `backend/services/graph_builder.py` (Phase-1-Referenz)
|
||||
|
||||
### Project Structure Notes
|
||||
|
||||
- Implementiert in: `backend/services/dynamic_graph_builder.py`
|
||||
- Tests in: `backend/tests/test_dynamic_graph_builder.py`
|
||||
- Nutzt: `backend/tools/web_search.py`, `backend/tools/pdf_reader.py`
|
||||
|
||||
### References
|
||||
|
||||
- [Source: _bmad-output/planning-artifacts/architecture.md#ADR-004] — Dynamischer Graph-Builder
|
||||
- [Source: _bmad-output/planning-artifacts/architecture.md#Blueprint-JSON-Schema] — Datenformat
|
||||
- [Source: _bmad-output/planning-artifacts/epics.md#Story-4.1] — ACs
|
||||
- [Source: CLAUDE.md#Key Design Constraints] — Zyklen sind First-Class
|
||||
|
||||
## Dev Agent Record
|
||||
|
||||
### Agent Model Used
|
||||
|
||||
Amelia (💻 BMAD Dev Agent) — `dev-story` workflow
|
||||
|
||||
### Completion Notes List
|
||||
|
||||
- Entry-Point-Erkennung via Set-Differenz: `{alle Node-IDs} - {IDs die als Edge-Target vorkommen}`
|
||||
- Routing-Closure für bedingte Edges: `lambda state: state.get("route_decision", "rework")`
|
||||
- `interrupt_before` wird als Liste aller Node-IDs gesetzt wenn `god_mode=True`
|
||||
|
||||
### File List
|
||||
|
||||
- `backend/services/dynamic_graph_builder.py`
|
||||
- `backend/tests/test_dynamic_graph_builder.py`
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
# Story 5.3: God Mode — Human-in-the-Loop
|
||||
|
||||
<!-- 🏃 Prepared by BMAD SM Skill — Agent: Bob (Scrum Master) -->
|
||||
<!-- Skill Command: /bmad-agent-bmm-sm → [CS] Context Story -->
|
||||
<!-- Workflow: _bmad/bmm/workflows/4-implementation/create-story/workflow.yaml -->
|
||||
|
||||
Status: done
|
||||
|
||||
## Story
|
||||
|
||||
Als **Nutzer**,
|
||||
möchte ich **im God Mode jeden Schritt des Councils genehmigen, ablehnen oder modifizieren**,
|
||||
so dass ich **volle Kontrolle über den KI-Prozess habe und kritische Entscheidungen absegnen kann**.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
1. `god_mode=true` → Graph pausiert via `interrupt_before` nach dem ersten Node-Abschluss
|
||||
2. `POST /approve` mit `action=approve` → Run setzt am nächsten Node fort
|
||||
3. `POST /approve` mit `action=reject` → Run bricht mit `status=failed` ab
|
||||
4. `POST /approve` mit `action=modify` und `modified_state` → Run setzt mit modifiziertem Draft fort
|
||||
5. `GET /councils/run/{run_id}/state` gibt den pausierten State zurück (inkl. `current_draft`, `next_nodes`)
|
||||
6. Frontend-Overlay erscheint bei `status=paused` und zeigt Agent-Name, aktuellen Draft und drei Buttons
|
||||
7. Zwei parallele god-mode Runs kontaminieren sich nicht gegenseitig (Session-Isolation)
|
||||
8. Zweimaliges Approve ohne laufenden Run gibt `400 Bad Request` zurück
|
||||
|
||||
## Tasks / Subtasks
|
||||
|
||||
- [x] Task 1: `interrupt_before` in dynamischem Graph-Builder implementieren (AC: 1)
|
||||
- [x] Subtask 1.1: `compile(interrupt_before=[...alle node IDs...])` bei `god_mode=True`
|
||||
- [x] Subtask 1.2: Nach `graph.invoke()` auf `__interrupt__`-Signal prüfen
|
||||
- [x] Task 2: God-Mode-State-Verwaltung implementieren (AC: 1, 5, 7)
|
||||
- [x] Subtask 2.1: `_god_mode_sessions: dict[run_id, GodModeSession]` in-memory
|
||||
- [x] Subtask 2.2: `GodModeSession` mit `graph`, `config`, `current_state`, `next_nodes`
|
||||
- [x] Subtask 2.3: Session-Isolation sicherstellen (kein shared-state)
|
||||
- [x] Task 3: Resume-Logik implementieren (AC: 2, 3, 4)
|
||||
- [x] Subtask 3.1: `resume_god_mode(run_id, action, modified_state)` Funktion
|
||||
- [x] Subtask 3.2: Bei `modify`: State-Override vor `graph.invoke(None, config)`
|
||||
- [x] Subtask 3.3: Bei `reject`: Session löschen, Status auf `failed`
|
||||
- [x] Task 4: API-Endpunkte (AC: 2–5, 8)
|
||||
- [x] Subtask 4.1: `POST /councils/run/{run_id}/approve` Route
|
||||
- [x] Subtask 4.2: `GET /councils/run/{run_id}/state` Route
|
||||
- [x] Subtask 4.3: `400`-Guard wenn Session nicht pausiert
|
||||
- [x] Task 5: Frontend God-Mode-UI (AC: 6)
|
||||
- [x] Subtask 5.1: Polling `GET /councils/run/{run_id}` auf `status=paused`
|
||||
- [x] Subtask 5.2: Overlay-Komponente mit Draft-Text, Agent-Name, drei Buttons
|
||||
- [x] Subtask 5.3: Modify-Modus mit Textarea für Draft-Bearbeitung
|
||||
- [x] Task 6: Tests (AC: 1–5, 7, 8)
|
||||
- [x] Subtask 6.1: `test_god_mode.py` — alle AC als Tests
|
||||
|
||||
## Dev Notes
|
||||
|
||||
- **LangGraph `interrupt_before`**: Dies ist der einzige Pause-Mechanismus — kein eigener einbauen.
|
||||
- **`graph.invoke(None, config)`**: Der `None`-Input setzt die Ausführung nach einem Interrupt fort.
|
||||
- **God-Mode-State-Isolation**: Jede `run_id` hat eine eigene Session-Instanz im Dict.
|
||||
- **Thread Safety**: Da LangGraph-Invokes in `run_in_executor` laufen, muss der Session-Store thread-safe sein.
|
||||
- Bezug: `backend/services/dynamic_graph_builder.py`, LangGraph-Dokumentation zu `interrupt_before`
|
||||
|
||||
### Project Structure Notes
|
||||
|
||||
- Implementiert in: `backend/services/dynamic_graph_builder.py` (GodMode-Logik)
|
||||
- Implementiert in: `backend/api/routes.py` (Endpunkte)
|
||||
- Frontend: `frontend/app/konferenzzimmer/page.tsx` (Overlay)
|
||||
- Tests in: `backend/tests/test_god_mode.py`
|
||||
|
||||
### References
|
||||
|
||||
- [Source: _bmad-output/planning-artifacts/architecture.md#ADR-001] — LangGraph interrupt_before
|
||||
- [Source: _bmad-output/planning-artifacts/architecture.md#God-Mode-Sequenzdiagramm]
|
||||
- [Source: _bmad-output/planning-artifacts/epics.md#Story-5.3] — ACs
|
||||
- [Source: CLAUDE.md#Key Design Constraints] — Human-in-the-Loop via interrupt_before
|
||||
|
||||
## Dev Agent Record
|
||||
|
||||
### Agent Model Used
|
||||
|
||||
Amelia (💻 BMAD Dev Agent) — `dev-story` workflow
|
||||
|
||||
### Completion Notes List
|
||||
|
||||
- LangGraph `interrupt_before` gibt nach Pause eine `Command`-Instanz zurück; der Typ wird via `isinstance` geprüft.
|
||||
- Der `config`-Parameter (`{"configurable": {"thread_id": run_id}}`) wird für LangGraph-Checkpointer benötigt.
|
||||
- In-Memory-Sessions gehen bei Server-Neustart verloren — für MVP akzeptabel.
|
||||
|
||||
### File List
|
||||
|
||||
- `backend/services/dynamic_graph_builder.py`
|
||||
- `backend/api/routes.py`
|
||||
- `backend/tests/test_god_mode.py`
|
||||
- `frontend/app/konferenzzimmer/page.tsx`
|
||||
Loading…
Add table
Add a link
Reference in a new issue