Initial Commit

This commit is contained in:
2026-04-23 13:35:33 +02:00
commit adc17d29ac
8 changed files with 2402 additions and 0 deletions
+449
View File
@@ -0,0 +1,449 @@
# 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.