Files
2026-04-23 13:35:33 +02:00

450 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Runbook: BMAD Phase 4 Automation in Paperclip aufsetzen
End-to-End-Anleitung, um von einer leeren Paperclip-Instanz zu einem
laufenden BMAD-Phase-4-Autopilot mit drei Agents zu kommen. Arbeite sie
in dieser Reihenfolge ab jeder Schritt hat einen Verifikations-Check
am Ende.
**Zeit-Abschätzung:** 45-90 Min, wenn OpenCode und Paperclip schon
installiert sind. Plus die Zeit, die BMAD für Phase 1-3 und manuelles
Sprint Planning gebraucht hat.
## Voraussetzungen
- BMAD V6 Phase 1-3 abgeschlossen:
- `_bmad-output/planning-artifacts/PRD.md`
- `_bmad-output/planning-artifacts/architecture.md`
- Eine Epic-Quelle (siehe README für unterstützte Varianten)
- **Sprint Planning manuell durchgeführt:** Du hast `bmad-sprint-planning`
selbst ausgeführt, und `_bmad-output/implementation-artifacts/sprint-status.yaml`
existiert. Der Supervisor erwartet diese Datei und weigert sich zu
starten, wenn sie fehlt.
- OpenCode CLI installiert, `opencode auth login` durchgeführt, Zugriff
auf die gewünschten Modelle (das starke Code-Modell für Dev UND ein
anderes Modell für QA) bestätigt.
- Paperclip installiert und laufend (`paperclipai` lokal oder remote).
- `PAPERCLIP_API_URL` und `PAPERCLIP_API_KEY` als Env-Variablen gesetzt.
- Git-Worktree des Projekts ist clean.
## Schritt 1: Paperclip-Adapter-Schema live abfragen
Das Schema für `opencode_local` variiert leicht zwischen Paperclip-
Versionen. Hol dir die kanonische Form für deine Installation:
```bash
curl -sS "$PAPERCLIP_API_URL/llms/agent-configuration.txt" \
-H "Authorization: Bearer $PAPERCLIP_API_KEY" | less
curl -sS "$PAPERCLIP_API_URL/llms/agent-configuration/opencode_local.txt" \
-H "Authorization: Bearer $PAPERCLIP_API_KEY"
```
Vergleich die Felder mit `config/agents.jsonc`. Besonders relevant:
- Wie heißt das Modell-Pinning-Feld? (`env.OPENCODE_MODEL`, `model`,
`runtimeModel`, …) beide Worker brauchen ein explizites Pinning.
- Wird `sessionBehavior: "new"` unterstützt oder heißt es anders
(`fresh-always`, `no-resume`, …)?
**Verifikation:** Du hast Klarheit über die Pflicht- und Optional-Felder.
## Schritt 2: Skills in Paperclips Skill-Library einspielen
Drei SKILL.md-Dateien müssen in deine Company-Skill-Library:
1. `skills/monitor-bmad-progress/SKILL.md`
2. `skills/execute-bmad-dev-tasks/SKILL.md`
3. `skills/execute-bmad-qa-tasks/SKILL.md`
**Variante A via Paperclip-UI:** Company → Skills → Create New Skill,
Inhalt hineinkopieren. Der Skill-Name muss exakt zum `name:` im
YAML-Frontmatter passen.
**Variante B via API:** Endpoint aus deiner Installation abfragen:
```bash
curl -sS "$PAPERCLIP_API_URL/llms/skills-api.txt" \
-H "Authorization: Bearer $PAPERCLIP_API_KEY"
```
**Verifikation:**
```bash
curl -sS "$PAPERCLIP_API_URL/api/skills" \
-H "Authorization: Bearer $PAPERCLIP_API_KEY" \
| jq '.[] | select(.name | startswith("monitor-bmad") or
startswith("execute-bmad-dev") or
startswith("execute-bmad-qa")) | .name'
```
Drei Namen müssen zurückkommen.
## Schritt 3: Company anlegen
Im Paperclip-UI: **+ Company**.
- **Name:** "BMAD Phase 4 <dein-projektname>"
- **Mission:** "Automatisierte Ausführung der BMAD-V6-Implementation-
Phase mit Dev/QA-Rollen-Trennung."
- **Projekt-Pfad (cwd / project_root):** Dein BMAD-Projektverzeichnis.
```bash
curl -sS "$PAPERCLIP_API_URL/api/companies" \
-H "Authorization: Bearer $PAPERCLIP_API_KEY" \
| jq '.[] | select(.name | contains("BMAD Phase 4"))'
```
Notiere `companyId` brauchst du für alle folgenden Calls.
## Schritt 4: Supervisor hiren
```bash
export COMPANY_ID="<aus Schritt 3>"
export PROJECT_ROOT="/srv/projects/<dein-projektname>"
curl -sS -X POST "$PAPERCLIP_API_URL/api/agents" \
-H "Authorization: Bearer $PAPERCLIP_API_KEY" \
-H "Content-Type: application/json" \
-d @- <<EOF
{
"companyId": "$COMPANY_ID",
"name": "PM Supervisor",
"role": "supervisor",
"icon": "📋",
"adapterType": "process",
"adapterConfig": {
"adapter": "opencode_local",
"cwd": "$PROJECT_ROOT",
"sessionBehavior": "resume-or-new",
"heartbeat": {"enabled": false}
},
"runtimeConfig": {"maxTurns": 80, "timeoutMs": 900000},
"desiredSkills": ["monitor-bmad-progress"],
"prompt": "<siehe agents.jsonc für den vollen Prompt>",
"budget": {"monthlyUsd": 20}
}
EOF
```
Notiere die `agentId` Dev und QA referenzieren sie als `reportsTo`.
## Schritt 5: Dev-Worker hiren
```bash
curl -sS -X POST "$PAPERCLIP_API_URL/api/agents" \
-H "Authorization: Bearer $PAPERCLIP_API_KEY" \
-H "Content-Type: application/json" \
-d @- <<EOF
{
"companyId": "$COMPANY_ID",
"name": "Dev Worker",
"role": "developer",
"icon": "💻",
"reportsTo": "<supervisor-agentId>",
"adapterType": "process",
"adapterConfig": {
"adapter": "opencode_local",
"cwd": "$PROJECT_ROOT",
"sessionBehavior": "new",
"env": {"OPENCODE_MODEL": "<starkes-code-modell>"},
"heartbeat": {"enabled": false}
},
"runtimeConfig": {"maxTurns": 300, "timeoutMs": 2700000},
"desiredSkills": ["execute-bmad-dev-tasks"],
"prompt": "<siehe agents.jsonc>",
"budget": {"monthlyUsd": 300, "perTaskUsdMax": 10}
}
EOF
```
## Schritt 6: QA-Engineer hiren
**Wichtig:** Das Modell MUSS sich nachweislich vom Dev-Modell
unterscheiden. Sonst verliert das adversariale Review seinen Wert.
```bash
curl -sS -X POST "$PAPERCLIP_API_URL/api/agents" \
-H "Authorization: Bearer $PAPERCLIP_API_KEY" \
-H "Content-Type: application/json" \
-d @- <<EOF
{
"companyId": "$COMPANY_ID",
"name": "QA Engineer",
"role": "qa",
"icon": "🔍",
"reportsTo": "<supervisor-agentId>",
"adapterType": "process",
"adapterConfig": {
"adapter": "opencode_local",
"cwd": "$PROJECT_ROOT",
"sessionBehavior": "new",
"env": {"OPENCODE_MODEL": "<anderes-modell-als-dev>"},
"heartbeat": {"enabled": false}
},
"runtimeConfig": {"maxTurns": 200, "timeoutMs": 1800000},
"desiredSkills": ["execute-bmad-qa-tasks"],
"prompt": "<siehe agents.jsonc>",
"budget": {"monthlyUsd": 150, "perTaskUsdMax": 5}
}
EOF
```
**Verifikation Schritt 4-6:**
```bash
curl -sS "$PAPERCLIP_API_URL/api/companies/$COMPANY_ID/agents" \
-H "Authorization: Bearer $PAPERCLIP_API_KEY" \
| jq '[.[] | {name, role, reportsTo, model: .adapterConfig.env.OPENCODE_MODEL}]'
```
Drei Agents, Supervisor top-level, Dev und QA beide unter Supervisor,
mit unterschiedlichen Modellen bei Dev/QA.
## Schritt 7: Smoke-Test der beiden Worker
Bevor echte Arbeit reinkommt: je ein Dummy-Task an Dev und QA.
**Dev-Smoke:**
```bash
curl -sS -X POST "$PAPERCLIP_API_URL/api/issues" \
-H "Authorization: Bearer $PAPERCLIP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"companyId": "'$COMPANY_ID'",
"title": "Smoke test Dev: write hello-dev.txt",
"description": "Erzeuge hello-dev.txt im Projekt-Root mit Inhalt \"dev online\". Dann status=success melden.",
"assignedAgentId": "<dev-worker-agentId>"
}'
```
**QA-Smoke:**
```bash
curl -sS -X POST "$PAPERCLIP_API_URL/api/issues" \
-H "Authorization: Bearer $PAPERCLIP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"companyId": "'$COMPANY_ID'",
"title": "Smoke test QA: read hello-dev.txt",
"description": "Lies hello-dev.txt, bestätige Inhalt, KEINE Änderungen. status=success mit dem gelesenen Text melden.",
"assignedAgentId": "<qa-engineer-agentId>"
}'
```
Beide Runs mit `exitCode: 0`. Räume `hello-dev.txt` danach auf.
**NICHT weitermachen**, bevor beide Smoke-Tests grün sind.
## Schritt 8: Bootstrap-Task einspielen
Jetzt der eigentliche Start: Supervisor baut die Task-Hierarchie aus den
BMAD-Planning-Artefakten.
```bash
curl -sS -X POST "$PAPERCLIP_API_URL/api/issues" \
-H "Authorization: Bearer $PAPERCLIP_API_KEY" \
-H "Content-Type: application/json" \
-d @bootstrap/initial-task.json
```
(Vorher in `initial-task.json` die `companyId` und `assignedAgentId`
eintragen letzteres ist die Supervisor-ID aus Schritt 4.)
**Erwartung (im Paperclip-UI):**
- Bootstrap-Task: `ready``in-progress``completed`
- Child-Issues entstehen pro Story:
- `create-story (X.Y)` — Dev-Worker
- `dev-story (X.Y)` — Dev-Worker
- `code-review (X.Y)` — QA-Engineer
- Pro Epic zusätzlich `retrospective (Epic N)` — QA-Engineer
- Supervisor postet Comment: Epics, Stories, `epic_source_layout`
- Nur der erste `create-story`-Task ist auf `ready`, alle anderen
`blocked` mit Dependencies
**Mögliche Abbrüche beim Bootstrap:**
- `sprint_status_missing` → Sprint Planning nicht vorab ausgeführt.
Lauf `bmad-sprint-planning` manuell, starte neu.
- `no_epic_source_found` → keine der vier Epic-Layouts gefunden.
Prüfe `_bmad-output/planning-artifacts/`.
- `sprint_status_inconsistent` → Stories im sprint-status.yaml passen
nicht zur Epic-Quelle.
- `planning_incomplete` → PRD.md oder architecture.md fehlt.
## Schritt 9: Erste Story durchlaufen lassen
Der Supervisor setzt automatisch den ersten `create-story`-Task auf
`ready`, sobald Bootstrap fertig ist. Der Dev-Worker sollte ihn binnen
Sekunden aufgreifen.
**Happy Path für Story 1.1 → 1.2 → …:**
1. Dev: `create-story (1.1)` → Story-Datei existiert → completed
2. Dev: `dev-story (1.1)` → Implementierung, Commits, Tests → completed
3. QA: `code-review (1.1)` → verdict=approved → completed
4. ERST JETZT: Dev: `create-story (1.2)` → ...
**Keine Parallelität über Story-Grenzen hinweg.** Policy C (Strikte
Story-Ordnung) verhindert, dass `create-story (1.2)` startet, solange
Story 1.1 nicht approved ist. Die einzige Gleichzeitigkeit: während
Dev `dev-story (1.2)` macht, kann QA theoretisch `code-review (1.1)`
noch am Laufen haben aber das passiert in der Praxis nicht, weil
Policy C auch das verhindert (Story 1.2 rührt sich ja erst, wenn Story
1.1 approved, d.h. code-review completed ist).
In der Praxis läuft also zu jedem Zeitpunkt EIN Task. Beide Agents
sind selten gleichzeitig beschäftigt. Das ist bewusste Verlangsamung
zugunsten sauberer Sequenzierung.
**Bei needs-rework:**
1. QA: `code-review (1.1)` → verdict=needs-rework → completed
2. Supervisor legt an:
- `dev-story (1.1) retry 1` (Dev) — mit Findings als Metadata
- `code-review (1.1) retry 1` (QA) — blockiert auf den Retry-Dev
3. Benachrichtigung an Operator: "Story 1.1 Retry 1/3 — N HIGH, M MEDIUM"
Bei Retry-Limit (3) erreicht → Eskalation mit vier Handlungsoptionen.
**Epic-Übergang:**
Nach `code-review` der letzten Story im Epic:
1. QA: `retrospective (Epic 1)` → completed
2. Erst jetzt wird der erste `create-story`-Task des nächsten Epics
ready gesetzt. Davor: blocked durch Single-Epic-Policy.
## Schritt 10: Häufige Fehler
**BMAD-Skill fragt interaktiv zurück:**
Prompt in Dev- oder QA-Skill präzisieren oder `--non-interactive`
an den BMAD-Skill-Aufruf anhängen.
**OpenCode-Session hängt > Timeout:**
Task-Timeout → SIGTERM. Supervisor markiert als `failed,
reason=timeout` und versucht Re-Schedule. Nach 3 Timeouts am gleichen
Task: Eskalation. Bei wiederholten Timeouts an einer Story: Story zu
groß, manuell splitten.
**Dev und QA nutzen versehentlich dasselbe Modell:**
Supervisor merkt das am `model_used`-Feld in den Agent-Reports und
informiert einmalig im Status-Report. Kein Abbruch aber das Review
ist dadurch schwächer. Korrigiere die `env.OPENCODE_MODEL`-Werte in
den Agent-Configs.
**`concurrent_task`-Fehler:**
Ein Agent hat zwei Tasks gleichzeitig. Sollte durch Policy B nie
passieren. Wenn doch: Sofort-Stopp, Paperclip-Audit-Log prüfen, dann
neu starten. Möglicherweise Supervisor-Bug oder Paperclip-Atomicity-
Issue.
**`sessionBehavior: "new"` wird ignoriert:**
Schema-Name in deiner Paperclip-Version abweichend. In agents.jsonc
anpassen basierend auf Schritt 1.
**Operator ändert sprint-status.yaml mid-run:**
Supervisor erkennt das am Timestamp, eskaliert. Besser: Workflow
stoppen, anpassen, neu bootstrappen.
**QA findet NIE etwas:**
Entweder QA-Modell ist zu permissiv (Modell-Upgrade) oder die Stories
sind tatsächlich trivial (akzeptabel, dann warning_zero_findings
regelmäßig). Nach 3-5 approved-ohne-Findings: Stichprobe auf die
Implementierung werfen.
## Schritt 11: Patrol verstehen
Der Supervisor läuft nicht nur bei Events (`task_completed`), sondern
patrouilliert alle 15 Minuten (konfigurierbar in agents.jsonc
`heartbeat.intervalSec`). Das sorgt für maximale Autonomie: wenn ein
Agent hängt oder ein Ready-Setting verloren geht, bemerkt und behebt
der Supervisor das, ohne dass du eingreifen musst.
**Was du in Paperclip sehen wirst:**
- **Patrol ohne Funde:** Keine Comments. Stille Einträge im
Audit-Trail ("Patrol OK"). Das ist der Normalfall bei gesundem Lauf.
- **Patrol mit autonomer Aktion:** Ein Comment am Parent-Issue im
Format:
```
### Patrol-Report <zeitstempel>
Graph-Status: 5/20 completed, 1 in-progress, 0 ready, 14 blocked
Aktuelle Story: Epic 1 Story 1.3, Task dev-story
Gefundene Blocker: stuck_in_progress_task (story 1.3, 47 min)
Autonome Aktionen: reset-to-ready für task dev-story (1.3)
Offene Eskalationen: keine
```
- **Patrol mit Eskalation:** Comment mit `attention_required=true`
das heißt, du musst ran. Z.B. bei dirty worktree oder Retry-Limit.
**Was Patrol autonom auflöst:**
| Blocker | Aktion |
| --- | --- |
| Task hängt in-progress ohne Heartbeat | als failed markieren, ready reset, normaler Retry-Pfad |
| Task ready, aber kein Agent zugewiesen | manuelles Re-Assignment an zuständigen Agent |
| Vorgänger completed, Folge blocked | Ready-Check nachholen, falls passt → ready setzen |
| Zwei Tasks mit identischem Kompositschlüssel | jüngeren cancellen, älteren behalten |
| Goal offen, aber kein aktiver Task | nächsten korrekten Task identifizieren und ready setzen |
| Dirty worktree (uncommitted changes) | WIP-Commit mit erkennbarer Message, Flow weiter (kein Code-Verlust) |
**Was Patrol NICHT autonom macht (immer Eskalation):**
- Retry-Limit erreicht (inhaltliche Entscheidung nötig)
- Fehlender Agent (Governance-Entscheidung)
- Meta-Stall > 1 h trotz Patrol-Aktionen (autonome Mittel erschöpft)
**Besonderheit Dirty Worktree:**
Wenn der Supervisor uncommittete Changes im Projekt findet (typisch
nach einem abgebrochenen Dev-Task), macht er einen automatischen
WIP-Commit mit Message `wip: patrol-auto-commit from {task_type}
(story {story_id})`. Damit ist der Worktree wieder clean, der
Workflow läuft weiter, und du behältst die Änderungen vollständig
im Git-History. Du solltest solche WIP-Commits später manuell
prüfen entweder revertst du sie und lässt den Dev-Agent sauber
neu arbeiten, oder du behältst sie, falls der Inhalt sinnvoll ist.
Diese landen als Info-Notiz mit `attention_required=false`. Du wirst
sie im Log sehen, aber sie stören deinen Schlaf nicht.
**Wenn du Patrol vorübergehend abschalten willst:**
In `agents.jsonc` beim Supervisor `heartbeat.enabled: false` setzen.
Dann läuft er wieder nur event-basiert aber rechne damit, dass Hänger
dann liegen bleiben, bis du sie manuell lösst.
## Schritt 12: Reporting einrichten (optional)
Der Supervisor postet Status-Reports als Comments auf das Parent-Issue.
Für Push-Notifications:
- Paperclip-UI → Company → Integrations → Webhook auf
`issue_comment_created` für das Phase-4-Parent-Issue.
- Alternativ: Im Supervisor-Prompt Hook einbauen, der bei
`attention_required=true` einen connected MCP (Slack, Email) triggert.
## Was danach?
Sobald Story 1.1 einmal sauber durchgelaufen ist, ist die Schleife
bewiesen.
- **Cost-Dashboard täglich prüfen:** Retry-Spiralen sind der teuerste
Failure-Mode. 3-Retry-Limit deckelt, aber früh eingreifen lohnt sich.
- **Nach 3 Stories manuelle Stichprobe:** Qualität auf deinem Level?
- **QA-Findings-Muster beobachten:** Wenn eine Finding-Klasse
immer wiederkehrt → `project-context.md` erweitern, damit der Dev die
Konvention von Anfang an einhält.
## Zweites BMAD-Projekt automatisieren
Paperclip unterstützt mehrere Companies pro Installation:
1. Neue Company anlegen
2. Die drei Skills sind instance-weit verfügbar, kein Re-Upload
3. Drei neue Agents hiren mit neuem `cwd`
4. Bootstrap wie in Schritt 8
Die SKILL.md-Dateien sind projekt-agnostisch. Nur `cwd` der Agents
ändert sich.