496 lines
20 KiB
Markdown
496 lines
20 KiB
Markdown
# DisClaw — Projekt- und Git-Workflow
|
||
|
||
Autor: Projekt- und Git-Manager-Agent
|
||
Datum: 2026-04-08
|
||
Quelle der Wahrheit für Inhalt: `docs/development-plan.md`.
|
||
Quelle der Wahrheit für den Backlog: `docs/backlog.md`.
|
||
|
||
Dieses Dokument definiert, wie an DisClaw gearbeitet wird: wie Branches heißen,
|
||
wie Forgejo strukturiert ist, wie Issues geschnitten werden, wie ein Developer-Agent
|
||
(Claude Sonnet 4.6) pro Issue vorgeht, und wann eine Phase als abgeschlossen gilt.
|
||
|
||
Forgejo-Remote: `http://localhost:3000/dev/disclaw.git` (lokale Instanz).
|
||
|
||
---
|
||
|
||
## 1. Branch-Strategie
|
||
|
||
### 1.1 `main` ist protected
|
||
|
||
- `main` ist **protected**. Keine direkten Pushes, keine Force-Pushes, kein Rebase.
|
||
- Änderungen kommen ausschließlich über Pull Requests.
|
||
- Jeder PR benötigt mindestens ein Review-Approval und grüne Checks, bevor er gemerged wird.
|
||
- Merge-Strategie: **Squash-Merge**. Eine Aufgabe = ein Commit auf `main`. Das hält die Historie
|
||
linear und macht Rollback (`git revert <sha>`) trivial.
|
||
|
||
### 1.2 Naming-Convention für Feature-Branches
|
||
|
||
```
|
||
phase-<n>/<kurz-slug>
|
||
```
|
||
|
||
Beispiele:
|
||
- `phase-0/harden-spawn`
|
||
- `phase-0/sanitize-env`
|
||
- `phase-1/channel-queue`
|
||
- `phase-1/split-for-discord`
|
||
|
||
**Begründung**: Der Phase-Prefix macht sofort sichtbar, an welchem Phasen-Ziel ein Branch
|
||
arbeitet. Das hilft beim Filtern in Forgejo (`refs/heads/phase-0/*`), beim Review-Priorisieren
|
||
und beim mentalen Mapping zu Milestones. Der Kurz-Slug ist imperativ und eindeutig
|
||
(`harden-spawn`, nicht `fix-stuff`). Keine Trailing-Nummern, keine Issue-IDs im Branch-Namen —
|
||
die Verknüpfung passiert im PR via `Closes #N`.
|
||
|
||
### 1.3 Lifecycle eines Feature-Branches
|
||
|
||
1. Issue wird in Forgejo `Ready` gesetzt und einem Developer-Agent zugewiesen.
|
||
2. Developer-Agent checkt aktuellen `main` aus (`git fetch origin && git checkout main && git pull --ff-only`).
|
||
3. Developer-Agent erstellt den Branch: `git checkout -b phase-<n>/<slug>`.
|
||
4. Implementierung gegen die Definition of Done des Issues.
|
||
5. Commits folgen Conventional-Commits (§5).
|
||
6. Push: `git push -u origin phase-<n>/<slug>`.
|
||
7. PR gegen `main` öffnen (Template in `.forgejo/PULL_REQUEST_TEMPLATE.md`).
|
||
8. Review, Anpassungen, grüne Checks.
|
||
9. Squash-Merge.
|
||
10. Branch wird automatisch gelöscht (Forgejo-Setting: "Delete branch after merge").
|
||
|
||
### 1.4 Keine langlebigen Integration-Branches
|
||
|
||
- Kein `dev`, kein `next`, kein `phase-1-integration`.
|
||
- Eine Phase gilt als abgeschlossen, wenn **alle Issues ihres Milestones** gemerged sind und
|
||
der manuelle Smoke-Test (§8) durch ist.
|
||
- Der einzige geteilte Branch ist `main`.
|
||
|
||
---
|
||
|
||
## 2. Forgejo-Projektstruktur
|
||
|
||
### 2.1 Labels
|
||
|
||
Maximal schlank gehalten. Ziel: jeder Developer versteht das Label-Set in < 30 Sekunden.
|
||
|
||
| Name | Farbe (hex) | Zweck |
|
||
|---|---|---|
|
||
| `phase:0` | `#b71c1c` | Phase 0 — Härtung |
|
||
| `phase:1` | `#e65100` | Phase 1 — Solides MVP |
|
||
| `phase:2` | `#f9a825` | Phase 2 — Context-Effizienz (`--resume`) |
|
||
| `phase:3` | `#2e7d32` | Phase 3 — UX-Feinschliff |
|
||
| `phase:4` | `#1565c0` | Phase 4 — Skills & Permissions |
|
||
| `phase:5` | `#4527a0` | Phase 5 — Streaming |
|
||
| `phase:6` | `#424242` | Phase 6+ — Zukunft / Platzhalter |
|
||
| `type:feat` | `#0e8a16` | Neues Feature |
|
||
| `type:fix` | `#d93f0b` | Bugfix |
|
||
| `type:refactor` | `#5319e7` | Umstrukturierung ohne Verhaltensänderung |
|
||
| `type:test` | `#006b75` | Tests oder Test-Infrastruktur |
|
||
| `type:docs` | `#1d76db` | Dokumentation |
|
||
| `type:chore` | `#bfbfbf` | Build, CI, Dependencies, Housekeeping |
|
||
| `priority:p0` | `#b60205` | Blocker, muss sofort |
|
||
| `priority:p1` | `#d93f0b` | Wichtig in aktueller Phase |
|
||
| `priority:p2` | `#fbca04` | Kann in späteren Phasen warten |
|
||
| `blocked` | `#000000` | Hängt an anderem Issue — Body nennt Blocker |
|
||
| `needs-review` | `#fbca04` | PR wartet auf Review |
|
||
| `security` | `#b60205` | Sicherheitsrelevant (CVE, Secret-Leak, Injection) |
|
||
|
||
**Begründung**: Phase-Label + Type-Label + Priority-Label sind orthogonal und genügen, um
|
||
einen Backlog zu filtern. Zusätzliche Labels wie `good-first-issue`, `help-wanted`,
|
||
`discussion` lehnen wir ab — sie sind bei einem Zwei-Agent-Setup (PM + Developer) wertlos
|
||
und erzeugen Noise. `security` ist ein Sonderfall: separat, weil es automatisierte
|
||
Eskalations-Policies erlauben soll (z. B. P0 + security → sofortige Zuweisung).
|
||
|
||
### 2.2 Milestones
|
||
|
||
Ein Milestone pro Phase. Titel und Description exakt aus `docs/development-plan.md` §4
|
||
abgeleitet:
|
||
|
||
| Milestone | Titel | Description (Kurzform der Definition of Done) |
|
||
|---|---|---|
|
||
| M0 | Phase 0 — Härtung | Kein `shell: true`, sanitizedEnv, Path-Containment, `--bare` + `--append-system-prompt-file`, Workspace-Root außerhalb Repo, CLAUDE.md mit Injection-Klausel, settings.json mit Deny-Liste. Alle P0-Security-Issues geschlossen. |
|
||
| M1 | Phase 1 — Solides MVP | Pino-Logger, ChannelQueue, Semaphore, `splitForDiscord`, Zod-Schemas, codeblock-aware Splitting, `.env.example`, `npm test` grün, keine `console.*` im Prod-Code. |
|
||
| M2 | Phase 2 — Context-Effizienz | `claude_session_id` in DB, Runner nutzt `--resume`, Fork-Case abgefangen, Usage-Metriken geloggt, Session überlebt Bot-Neustart. |
|
||
| M3 | Phase 3 — UX-Feinschliff | Attachment-Download, Reaction-Markers, `sendResponse` mit Attachment-Fallback, Typing-Refresh 8s. |
|
||
| M4 | Phase 4 — Skills & Permissions | Profile-Registry (5 Profiles), PreToolUse-Hook `guard-tool.cjs`, Audit-Log, `profile`-Option in `/new-agent`. |
|
||
| M5 | Phase 5 — Streaming | `runAgentStream`, NDJSON-Parser defensiv, `stream-to-discord` mit Rate-Limit, Feature-Flag in `disclaw.yaml`. |
|
||
| M6 | Phase 6+ — Zukunft | `/list-agents`, `/delete-agent`, `/agent-config`, Rate-Limits, Budget, Agent-zu-Agent, Docker, Dashboard. Nur Platzhalter, wird bei Phase-Start verfeinert. |
|
||
|
||
Ein Milestone ist **closed**, sobald alle seine Issues `closed` sind und der Smoke-Test
|
||
erfolgreich durchgeführt wurde.
|
||
|
||
### 2.3 Kanban-Board (Forgejo Project)
|
||
|
||
Ein einziges Projekt namens **DisClaw Delivery** mit fünf Spalten. Kein separates Board
|
||
pro Phase — Phase wird über Label-Filter dargestellt.
|
||
|
||
| Spalte | Kriterium für Einzug |
|
||
|---|---|
|
||
| `Backlog` | Issue existiert, wurde vom PM geschnitten, hat Titel, Phase-Label, Type-Label, Milestone. Noch nicht priorisiert für aktuelle Phase. |
|
||
| `Ready` | Issue hat vollständige Definition of Done, alle Dependencies aufgelöst (keine `blocked`-Labels), Priority gesetzt, für aktuelle Phase priorisiert. Darf sofort von einem Developer-Agent gezogen werden. |
|
||
| `In Progress` | Ein Developer-Agent ist zugewiesen, ein Feature-Branch existiert und wurde nach `origin` gepusht (mindestens der erste Commit). |
|
||
| `In Review` | PR ist geöffnet, `needs-review`-Label gesetzt, CI-Checks laufen oder sind grün. |
|
||
| `Done` | PR ist gemerged, Issue ist geschlossen. Kein manuelles Verschieben — Forgejo erledigt das automatisch über `Closes #N` im PR-Body. |
|
||
|
||
**Regel**: Eine Karte wird rückwärts verschoben, wenn ein Kriterium verloren geht
|
||
(z. B. PR wird geschlossen ohne Merge → zurück nach `In Progress`; neue Abhängigkeit
|
||
wird entdeckt → zurück nach `Backlog` mit `blocked`-Label).
|
||
|
||
### 2.4 Bootstrap via Forgejo-API
|
||
|
||
Die folgenden Endpunkte setzen Labels, Milestones und das Projekt-Board auf. Alle Pfade
|
||
sind **echte Forgejo-API-Pfade** (Forgejo spricht die Gitea-API v1 und deckt zusätzlich
|
||
eigene Project-Routen ab). Das Bootstrap passiert per Script (siehe §2.5); **dieses
|
||
Dokument erstellt nichts direkt**.
|
||
|
||
Umgebungsvariablen:
|
||
```
|
||
FORGEJO_BASE=http://localhost:3000
|
||
FORGEJO_OWNER=dev
|
||
FORGEJO_REPO=disclaw
|
||
FORGEJO_TOKEN=<personal-access-token mit repo-scope>
|
||
```
|
||
|
||
**Labels anlegen**: `POST /api/v1/repos/{owner}/{repo}/labels`
|
||
```bash
|
||
curl -sS -X POST \
|
||
-H "Authorization: token $FORGEJO_TOKEN" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"name":"phase:0","color":"#b71c1c","description":"Phase 0 — Härtung"}' \
|
||
"$FORGEJO_BASE/api/v1/repos/$FORGEJO_OWNER/$FORGEJO_REPO/labels"
|
||
```
|
||
|
||
**Milestones anlegen**: `POST /api/v1/repos/{owner}/{repo}/milestones`
|
||
```bash
|
||
curl -sS -X POST \
|
||
-H "Authorization: token $FORGEJO_TOKEN" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"title":"Phase 0 — Härtung","description":"Kein shell:true, sanitizedEnv, ..."}' \
|
||
"$FORGEJO_BASE/api/v1/repos/$FORGEJO_OWNER/$FORGEJO_REPO/milestones"
|
||
```
|
||
|
||
**Issues anlegen**: `POST /api/v1/repos/{owner}/{repo}/issues`
|
||
```bash
|
||
curl -sS -X POST \
|
||
-H "Authorization: token $FORGEJO_TOKEN" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"title":"...","body":"...","labels":[1,5,12],"milestone":1}' \
|
||
"$FORGEJO_BASE/api/v1/repos/$FORGEJO_OWNER/$FORGEJO_REPO/issues"
|
||
```
|
||
(Label- und Milestone-IDs kommen aus der Response der Create-Calls oben.)
|
||
|
||
**Branch-Protection für `main`**: `POST /api/v1/repos/{owner}/{repo}/branch_protections`
|
||
```bash
|
||
curl -sS -X POST \
|
||
-H "Authorization: token $FORGEJO_TOKEN" \
|
||
-H "Content-Type: application/json" \
|
||
-d '{
|
||
"branch_name":"main",
|
||
"enable_push":false,
|
||
"required_approvals":1,
|
||
"enable_status_check":true,
|
||
"status_check_contexts":["build","test","lint"],
|
||
"block_on_rejected_reviews":true,
|
||
"block_on_outdated_branch":true
|
||
}' \
|
||
"$FORGEJO_BASE/api/v1/repos/$FORGEJO_OWNER/$FORGEJO_REPO/branch_protections"
|
||
```
|
||
|
||
**Projekte (Kanban-Board)**: Forgejo unterstützt Projekte pro Repo unter
|
||
`POST /api/v1/repos/{owner}/{repo}/projects` mit `{"title":"DisClaw Delivery","board_type":"basic_kanban"}`.
|
||
Spalten werden nachgelagert angelegt über `POST /api/v1/projects/{id}/columns` mit
|
||
`{"title":"Ready"}` etc.
|
||
|
||
**Alternative**: `tea` CLI (`https://gitea.com/gitea/tea`). Die relevanten Kommandos:
|
||
```bash
|
||
tea labels create --name "phase:0" --color "#b71c1c" --description "Phase 0 — Härtung"
|
||
tea milestones create --title "Phase 0 — Härtung" --description "..."
|
||
tea issues create --title "..." --body "..." --labels "phase:0,type:fix,priority:p0" --milestone "Phase 0 — Härtung"
|
||
```
|
||
`tea` authentifiziert sich über `tea login add` einmalig mit `FORGEJO_TOKEN`.
|
||
|
||
### 2.5 Bootstrap-Script (skizziert, NICHT angelegt)
|
||
|
||
Ein späteres Script unter `scripts/bootstrap-forgejo.ts` soll:
|
||
|
||
1. `docs/backlog.md` parsen (jedes Issue als YAML-Frontmatter-Block oder strukturiertes
|
||
Markdown).
|
||
2. Labels anlegen (idempotent: vorher `GET /labels`, skip wenn vorhanden).
|
||
3. Milestones anlegen (idempotent).
|
||
4. Projekt + Spalten anlegen (idempotent).
|
||
5. Branch-Protection setzen.
|
||
6. Für jedes Backlog-Issue: `POST /issues`, `DIS-XXX` im Backlog-File durch die echte
|
||
Issue-Nummer ersetzen.
|
||
7. Jede Karte ins `Backlog`-Kanban-Board einhängen.
|
||
|
||
Abhängigkeiten: `node-fetch` (oder Node 20 native), `js-yaml`, nichts weiteres.
|
||
Läuft einmalig, ist re-runnable (idempotent). **Legt dieses Dokument nicht an.**
|
||
|
||
---
|
||
|
||
## 3. Issue-Template
|
||
|
||
Jedes Issue folgt exakt diesem Template. Abweichungen werden vom PM vor dem Create
|
||
korrigiert. Das Template landet zusätzlich unter
|
||
`.forgejo/ISSUE_TEMPLATE/feature.md` als Forgejo-Template.
|
||
|
||
```markdown
|
||
## Ziel
|
||
<1–2 Sätze, was erreicht werden soll.>
|
||
|
||
## Kontext
|
||
Referenz: `docs/development-plan.md` §<Abschnitt>, ggf. `docs/ai-engineer-analyse.md` §<Abschnitt>.
|
||
<Kurze Begründung, warum das jetzt gemacht wird und welches Problem es löst.>
|
||
|
||
## Scope
|
||
- **In**: <konkret was gemacht wird>
|
||
- **Out**: <konkret was NICHT gemacht wird — damit kein Scope-Creep>
|
||
|
||
## Definition of Done
|
||
- [ ] <konkreter, überprüfbarer Punkt 1>
|
||
- [ ] <konkreter, überprüfbarer Punkt 2>
|
||
- [ ] Unit-Tests geschrieben und grün (`npm test`)
|
||
- [ ] Keine `console.*` im Produktionscode (falls betroffen)
|
||
- [ ] PR-Template ausgefüllt, Review bestanden, CI grün
|
||
|
||
## Dateien (erwartet)
|
||
- `src/<pfad1>` — <zweck>
|
||
- `tests/<pfad2>` — <zweck>
|
||
|
||
## Branch
|
||
`phase-<n>/<slug>`
|
||
|
||
## Abhängigkeiten
|
||
- Blockiert durch: #<issue-nr> (falls vorhanden)
|
||
- Blockiert: #<issue-nr> (falls vorhanden)
|
||
```
|
||
|
||
---
|
||
|
||
## 4. PR-Template
|
||
|
||
Datei: `.forgejo/PULL_REQUEST_TEMPLATE.md` (Forgejo liest dieses Verzeichnis; Fallback
|
||
`.gitea/PULL_REQUEST_TEMPLATE.md` wird ebenfalls erkannt).
|
||
|
||
```markdown
|
||
## Summary
|
||
<1–3 Sätze: was ändert dieser PR und warum.>
|
||
|
||
## Closes
|
||
Closes #<issue-nr>
|
||
|
||
## Changes
|
||
- <Bullet für jede relevante Datei-Gruppe>
|
||
|
||
## Test plan
|
||
- [ ] `npm run build` läuft grün
|
||
- [ ] `npm test` läuft grün
|
||
- [ ] Manueller Smoke-Test: <falls sinnvoll; sonst "n/a">
|
||
- [ ] Neue Dateien haben Unit-Tests (falls anwendbar)
|
||
|
||
## Screenshots / Logs
|
||
<optional — Log-Snippets bei Runtime-Änderungen>
|
||
|
||
## Breaking Changes
|
||
- [ ] Keine
|
||
- [ ] Ja: <Beschreibung + Migrationshinweis>
|
||
|
||
## Reviewer-Checklist
|
||
- [ ] Code-Diff passt zum Issue-Scope (kein Scope-Creep)
|
||
- [ ] Definition of Done aus dem Issue ist erfüllt
|
||
- [ ] Keine neuen `console.*`-Calls (außer in Tests/Probe-Scripts)
|
||
- [ ] Keine Secrets, Tokens oder absoluten Pfade in Logs
|
||
- [ ] `shell: false` bei jedem Spawn (falls Spawn betroffen)
|
||
- [ ] Sicherheitsrelevanter Code hat mindestens einen negativen Test
|
||
```
|
||
|
||
---
|
||
|
||
## 5. Commit-Convention
|
||
|
||
**Conventional Commits** mit Phase-Scope. Format:
|
||
|
||
```
|
||
<type>(<scope>): <subject>
|
||
|
||
<optional body>
|
||
|
||
<optional footer: Closes #N>
|
||
```
|
||
|
||
**Types** (deckungsgleich mit `type:*`-Labels): `feat`, `fix`, `refactor`, `test`, `docs`,
|
||
`chore`, `perf`, `build`, `ci`.
|
||
|
||
**Scope**: Phase oder Modul. Bevorzugt Phase bei Phase-spezifischen Changes
|
||
(`feat(phase-1): add channel queue`), Modul bei Cross-Phase-Infrastruktur
|
||
(`fix(runner): handle ENOENT on claude.cmd`).
|
||
|
||
**Beispiele**:
|
||
```
|
||
feat(phase-0): sanitize child env before spawning claude
|
||
|
||
Removes DISCORD_BOT_TOKEN and all TOKEN_/SECRET_/API_KEY_ variables
|
||
from the environment passed to the claude child process. Adds an
|
||
allow-only whitelist helper in src/runtime/env.ts.
|
||
|
||
Closes #3
|
||
```
|
||
|
||
```
|
||
fix(runner): resolve claude.cmd via cross-spawn on Windows
|
||
|
||
CVE-2024-27980 blocks direct .cmd spawning without shell:true on
|
||
Node 20.12+. cross-spawn handles the wrapper resolution and arg
|
||
quoting transparently.
|
||
|
||
Closes #2
|
||
```
|
||
|
||
```
|
||
refactor(router): extract ChannelQueue into runtime/channel-queue.ts
|
||
```
|
||
|
||
**Regel**: Subject <= 72 Zeichen, imperativ, kein Punkt am Ende. Body erklärt das
|
||
*Warum*, nicht das *Was* — der Diff zeigt bereits das Was.
|
||
|
||
**Squash-Merge**: Beim Merge in `main` wird der PR-Titel zum finalen Commit-Subject.
|
||
Der PM achtet deshalb darauf, dass der PR-Titel Conventional-Commits-konform ist.
|
||
|
||
---
|
||
|
||
## 6. Developer-Agent-Workflow (Claude Sonnet 4.6)
|
||
|
||
Ein Developer-Agent arbeitet **genau ein Issue pro Branch/PR**. Nie Issue-Pooling.
|
||
|
||
### 6.1 Ablauf pro Issue
|
||
|
||
1. **Ticket ziehen**: Issue aus `Ready` nehmen, sich selbst zuweisen, Status auf
|
||
`In Progress` setzen.
|
||
2. **Branch erstellen**:
|
||
```bash
|
||
git fetch origin
|
||
git checkout main
|
||
git pull --ff-only
|
||
git checkout -b phase-<n>/<slug>
|
||
```
|
||
3. **Implementieren**: Strikt entlang der Definition of Done. Keine zusätzlichen
|
||
Änderungen außerhalb des `Dateien (erwartet)`-Blocks — wenn eine zusätzliche Datei
|
||
nötig wird, zuerst das Issue kommentieren, nicht einfach drauflosschreiben.
|
||
4. **Tests**: Für jede neue reine Funktion ein Unit-Test. Integration-Tests nur, wenn
|
||
das Issue es explizit verlangt oder ein Mehrkomponenten-Flow betroffen ist.
|
||
5. **Commits**: Kleine, thematisch fokussierte Commits mit Conventional-Format.
|
||
Der finale Squash verdichtet sie ohnehin, aber die Branch-Historie hilft beim Review.
|
||
6. **Lokale Vor-Checks**:
|
||
```bash
|
||
npm run build
|
||
npm test
|
||
```
|
||
Beide müssen grün sein, bevor gepusht wird.
|
||
7. **Pushen**: `git push -u origin phase-<n>/<slug>`.
|
||
8. **PR öffnen**: Via `tea pulls create` oder Forgejo-Web-UI. PR-Template ausfüllen,
|
||
`Closes #<n>` einfügen, Label `needs-review` setzen. Spalte `In Review`.
|
||
9. **Self-Review-Checklist**: Reviewer-Checklist im PR-Body selbst durchgehen, bevor
|
||
um ein Review gebeten wird. Saves a round-trip.
|
||
10. **Auf Review warten**. Bei Change-Requests: Anpassungen als neue Commits (kein
|
||
Force-Push) auf denselben Branch.
|
||
11. **Nach Merge**: Branch wird automatisch gelöscht, Issue schließt automatisch über
|
||
`Closes #N`.
|
||
|
||
### 6.2 Rolle des Projekt-/Git-Manager-Agents (dieser Agent)
|
||
|
||
- Schneidet Issues gemäß `docs/development-plan.md` und schreibt sie in `docs/backlog.md`.
|
||
- Priorisiert innerhalb eines Milestones (`priority:p0` > `p1` > `p2`).
|
||
- Weist Developer-Agenten zu (im Ein-Developer-Setup trivial, bei mehreren nach Load).
|
||
- Koordiniert Reviews, triggert bei festhängenden PRs nach.
|
||
- Stellt Phasen-Abschluss fest, führt den Smoke-Test durch (siehe §8).
|
||
- Entscheidet über `blocked`-Labels und löst Blocker auf, indem fehlende Vor-Issues
|
||
nachgeschnitten werden.
|
||
- **Schreibt keinen Produktionscode**. Ausnahme: Bootstrap-Scripts und Dokumentation.
|
||
|
||
### 6.3 Rollback bei kaputtem PR
|
||
|
||
- **PR ist nach Merge kaputt**: `git revert <merge-sha>` auf einem neuen Branch
|
||
`phase-<n>/revert-<slug>`, normaler PR-Flow. Niemals `git reset` auf `main`.
|
||
- **PR ist vor Merge kaputt**: Branch bleibt offen, `In Review` → `In Progress`,
|
||
Developer-Agent fixt auf demselben Branch. Kein Force-Push. Keine neuen Branches.
|
||
- **Feature muss komplett zurückgezogen werden**: Issue wieder öffnen, `blocked`-Label,
|
||
Begründung als Kommentar, Revert-PR mergen.
|
||
|
||
---
|
||
|
||
## 7. Test-Gate pro PR
|
||
|
||
Jeder PR muss vor Merge folgende Gates passieren:
|
||
|
||
1. **Build**: `npm run build` — TypeScript-Compile ohne Fehler.
|
||
2. **Unit-Tests**: `npm test` — Vitest-Suite grün.
|
||
3. **Lint** (sobald Phase 0 Issue "Add ESLint + `shell:false`-Rule" gemerged ist):
|
||
`npm run lint` grün.
|
||
4. **Manueller Smoke-Test**: Nur bei Änderungen am Bot-Startup, Runner, oder
|
||
Discord-Integration. Im PR-Template als separater Haken dokumentiert.
|
||
|
||
**CI** wird in Phase 0 als eigenes Issue aufgesetzt (siehe `docs/backlog.md` Issue
|
||
`DIS-008`: Forgejo Actions Workflow mit `build`, `test`, `lint` auf `ubuntu-latest`
|
||
und `windows-latest`).
|
||
|
||
**Lokal ausführbar**:
|
||
```bash
|
||
npm install
|
||
npm run build
|
||
npm test
|
||
```
|
||
|
||
Ein fehlgeschlagener Test = kein Merge. Keine `--skip`-Flags, kein `xit`-Workaround.
|
||
|
||
---
|
||
|
||
## 8. Phasen-Übergang
|
||
|
||
### 8.1 Definition "Phase abgeschlossen"
|
||
|
||
Eine Phase ist genau dann abgeschlossen, wenn **alle folgenden** Bedingungen gelten:
|
||
|
||
1. Alle Issues des Milestones sind im Status `Done` (PR gemerged).
|
||
2. Der manuelle Smoke-Test für die Phase ist durchgelaufen (siehe §8.2).
|
||
3. Der PM hat das Milestone in Forgejo manuell auf `closed` gesetzt.
|
||
4. Der User hat die nächste Phase explizit freigegeben (siehe §8.3).
|
||
|
||
### 8.2 Smoke-Test pro Phase
|
||
|
||
Der PM führt einen kurzen End-to-End-Test auf dem aktuellen `main` durch. Mindest-Umfang:
|
||
|
||
- **Phase 0**: Bot startet, `/new-agent` erstellt Workspace unter `~/.disclaw/workspaces/`,
|
||
`.claude/settings.json` enthält Deny-Liste, ein Test-Prompt mit Eval-Versuch
|
||
(`echo $DISCORD_BOT_TOKEN`) kommt leer zurück.
|
||
- **Phase 1**: Drei Messages schnell hintereinander im gleichen Channel werden in
|
||
Reihenfolge beantwortet, Logs sind strukturiertes JSON, `splitForDiscord` schneidet
|
||
einen langen Codeblock sauber auf.
|
||
- **Phase 2**: Zweite Message im selben Channel zeigt `cache_read_input_tokens > 0` im Log.
|
||
- **Phase 3**: Bild-Upload im Discord wird vom Agent beschrieben.
|
||
- **Phase 4**: Agent mit `profile:researcher` kann nicht schreiben; Audit-Log enthält
|
||
blockierten Tool-Call.
|
||
- **Phase 5**: Lange Antwort erscheint inkrementell, finaler Stand stimmt.
|
||
|
||
Das konkrete Skript wird in Phase 1 als `scripts/smoke/<phase>.md`-Checkliste gepflegt.
|
||
|
||
### 8.3 Keine automatische Phasen-Progression
|
||
|
||
Der PM **startet die nächste Phase nicht automatisch**. Der User muss explizit
|
||
freigeben ("Phase X ist fertig, starte Phase Y"). Ohne diese Freigabe bleibt der Backlog
|
||
für die nächste Phase im Zustand `Backlog` (noch nicht `Ready`).
|
||
|
||
Grund: Phasen-Übergänge sind der natürliche Moment, um den Plan zu überprüfen, die
|
||
verbleibenden Epic-Level-Issues der nächsten Phase zu verfeinern, und eventuell
|
||
gelernte Erkenntnisse zurückzuspielen.
|
||
|
||
---
|
||
|
||
## 9. Anhang — Konventionen zusammengefasst
|
||
|
||
| Artefakt | Ort | Format |
|
||
|---|---|---|
|
||
| Branch-Name | Git | `phase-<n>/<slug>` |
|
||
| Commit-Message | Git | Conventional Commits mit Phase-Scope |
|
||
| Issue | Forgejo | Template §3, Labels aus §2.1, Milestone aus §2.2 |
|
||
| PR | Forgejo | Template §4, squash-merge, `Closes #N` im Body |
|
||
| PR-Template-Datei | Repo | `.forgejo/PULL_REQUEST_TEMPLATE.md` |
|
||
| Issue-Template-Datei | Repo | `.forgejo/ISSUE_TEMPLATE/feature.md` |
|
||
| Backlog | Repo | `docs/backlog.md` (Source of Truth vor Forgejo-Sync) |
|
||
| Workflow | Repo | `docs/workflow.md` (dieses Dokument) |
|
||
| Bootstrap-Script | Repo | `scripts/bootstrap-forgejo.ts` (noch nicht angelegt) |
|