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:
copilot-swe-agent[bot] 2026-03-12 14:26:40 +00:00
parent e37cb6f4c0
commit 3be3cb73b6
14 changed files with 1577 additions and 4 deletions

View file

@ -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 010 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: 15)
- [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 010 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)

View file

@ -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: 16)
- [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`

View file

@ -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: 25, 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: 15, 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`