Zum Inhalt

Spec-Driven Development

Spec-Driven Development (SDD) ist eine Entwicklungsmethodik für die strukturierte Zusammenarbeit zwischen Entwicklern und Coding Agents (Claude Code, Cursor, Gemini CLI, etc.). Polycrate stellt die technische Infrastruktur bereit: ein standardisiertes .specs/-Verzeichnis-Layout, ein maschinenlesbares Spec-Format mit ID-basiertem Lifecycle-Management sowie vollständige CLI-Commands für alle Phasen.

Warum Spec-Driven Development?

Ohne SDD entstehen in AI-gestützten Entwicklungsworkflows typische Probleme:

  • Coding Agents schreiben Code ohne dokumentierten Kontext — niemand weiß mehr, warum etwas so implementiert wurde
  • Releases sind schwer nachvollziehbar — welche Änderungen gehören zu welcher Version?
  • Agents bearbeiten Dateien direkt und korrumpieren dabei Strukturen, die Maschinen lesen müssen
  • Kein gemeinsames "Backlog" zwischen Mensch und Agent — Aufgaben existieren nur im Chat-Kontext

SDD löst diese Probleme durch einen definierten Prozess:

Frage SDD-Antwort
Warum wurde etwas implementiert? Spec als permanentes Archiv (Problem, Analyse, Lösung)
Was ist der aktuelle Stand? index.yml mit Status aller Specs
Wie kommt eine Änderung zum Release? Definierter Lifecycle: planned → implemented → released
Was kommt als nächstes? Backlog via .specs/.next/

Konzepte

Specs

Eine Spec ist ein strukturiertes Markdown-Dokument, das eine Änderung, einen Bugfix oder ein Feature von der Idee bis zur Implementierung begleitet. Jede Spec hat:

  • Eine eindeutige ID (ganzzahlig, nie wiederverwendet)
  • Einen Status (planned, in-progress, ready, implemented, cancelled)
  • Einen Typ (Conventional Commits: feat, fix, breaking, …)
  • Strukturierte Sektionen: abhängig vom Typ (siehe Spec-Typen)
  • Optionale Labels für Filterung und Grouping
  • Optionale Abhängigkeiten (needs) zu anderen Specs

Specs liegen in .specs/.next/ (Backlog) oder .specs/<version>/ (einem Release zugewiesen).

Index

Die Datei .specs/index.yml ist die einzige Quelle der Wahrheit für alle Specs. Sie enthält ID, Name, Status, Typ, Labels, Needs, Datei-Pfad und Version jeder Spec sowie den next_id-Counter.

Niemals direkt bearbeiten

index.yml darf niemals manuell oder durch Agents direkt bearbeitet werden. Alle Mutations gehen ausschließlich über polycrate spec * oder polycrate release * Commands. Direkte Edits korrumpieren den Index.

Zwei Lifecycle-Phasen

ARBEITSPHASE                          RELEASE-PHASE
polycrate spec *                      polycrate release *
────────────────────────────          ────────────────────────────────────
Tage bis Wochen                       Minuten, nach abgeschlossener Arbeit

Specs erstellen, ausarbeiten,         Specs einer Version zuweisen
implementieren                        CHANGELOG.poly schreiben
"Was machen wir, und warum?"          workspace.poly version setzen
                                      Git-Tag erstellen
                                      "Dokumentation, dass etwas fertig ist"

Verzeichnisstruktur

my-workspace/
├── .specs/
│   ├── index.yml           # Einzige Quelle der Wahrheit (nie direkt bearbeiten!)
│   ├── .rules.md           # Projekt-spezifische Regeln für Agents (optional)
│   ├── .next/              # Backlog — noch keiner Version zugewiesen
│   │   ├── 0-login-timeout-fix.md
│   │   └── 1-api-integration.md
│   ├── 1.0.0/              # Released
│   │   └── 2-initial-setup.md
│   └── 1.1.0/              # In Vorbereitung
│       └── 3-neue-funktion.md
├── workspace.poly
└── CHANGELOG.poly

.specs/.rules.md

Optionale Datei mit projektspezifischen Regeln für Agents. Wird von polycrate spec rules show ausgegeben und in die generierten Agent-Rules-Dateien integriert.

# Projekt-Regeln

## Sprache
Alle Specs auf Deutsch verfassen.

## Spec-Scope
Jede Spec deckt genau ein Problem ab.

Spec-Lifecycle

Status-Übergänge

planned ──► in-progress ──► ready ──► implemented
   │                                      │
   └──────────────────────────────────────┤
                                    cancelled (jederzeit)
Status Bedeutung
planned Spec angelegt, noch nicht in Bearbeitung
in-progress Aktiv in Bearbeitung
ready Finalisiert und validiert, bereit für Release-Zuweisung
implemented Code ist fertig, Spec kann einem Release zugewiesen werden
cancelled Feature abgelehnt oder durch andere Spec ersetzt — Begründung archiviert

implemented vs. ready

ready wird durch polycrate spec finalize gesetzt — der Command validiert, dass Solution nicht leer und Open Questions leer ist. implemented setzt der Entwickler manuell nach erfolgreicher Implementierung.

Cancelled Specs

Wenn ein Feature abgelehnt oder durch eine andere Spec ersetzt wird, kann es nicht-destruktiv archiviert werden:

polycrate spec update <id> --set status=cancelled --set cancellation_reason="Replaced by spec #18"
  • spec list blendet cancelled per Default aus; --all zeigt alle inkl. cancelled
  • spec validate ignoriert cancelled Specs
  • release diff ignoriert cancelled Specs

Abhängigkeiten (needs)

Specs können von anderen Specs abhängig sein. spec finalize verhindert den Abschluss, solange Abhängigkeiten nicht implemented sind:

# Spec 5 kann erst finalisiert werden, wenn Specs 3 und 4 implemented sind
polycrate spec link 5 --needs 3 --needs 4

# Äquivalent via spec update
polycrate spec update 5 --add-needs 3 --add-needs 4

# Abhängigkeit entfernen
polycrate spec update 5 --remove-needs 3

spec list zeigt [BLOCKED] wenn mindestens eine needs-Spec nicht implemented ist.

Validierung: Das System verhindert self-references (Spec hängt von sich selbst ab) und Zirkularitäten — direkte wie transitive.


Spec-Typen

Jede Spec hat einen Typ nach Conventional Commits. Der Typ steuert, welche Sektionen beim spec create als Scaffolding erzeugt werden.

polycrate spec create --name "Fix login bug" --type fix
polycrate spec create --name "Add dark mode" --type feat   # Default wenn --type fehlt
polycrate spec create --name "Drop v1 API"   --type breaking
polycrate spec update <id> --set type=refactor

Gültige Typen: fix | perf | feat | refactor | chore | docs | ci | build | style | test | breaking | analysis

Typ-Familien und Sektionsschema

Familie A — Diagnose (fix, perf, analysis):

Sektionen: ProblemAnalysisRoot CauseSolutionMigrationOpen Questions

Geeignet für Bugfixes, Performance-Analysen und Ursachenforschung. Root Cause ist Pflicht für spec finalize.

Familie B — Feature (feat, refactor, chore, docs, ci, build, style, test):

Sektionen: ProblemFeature DescriptionSolutionAffected FilesAcceptance CriteriaOpen Questions

Feature Description beschreibt Intent und Scope. Affected Files listet betroffene Dateipfade.

Familie C — Breaking Change (breaking):

Sektionen wie Familie B, aber Migration ist Pflichtspec finalize schlägt ohne Migration-Sektion mit einem Error fehl.


Labels

Labels ermöglichen freies Tagging von Specs für Filterung und Grouping:

# Labels hinzufügen und entfernen
polycrate spec update <id> --add-label sdd --add-label agent
polycrate spec update <id> --remove-label sdd

# Filtern
polycrate spec list --label sdd
polycrate spec list --label sdd --type fix

Quickstart

1. SDD initialisieren

polycrate spec init

Legt .specs/, index.yml und .specs/.rules.md an. Generiert außerdem Agent-Rules-Dateien im Workspace-Root (siehe Agent-Integration).

2. Spec anlegen

# Mit explizitem Typ — steuert das Scaffolding
polycrate spec create --name "Login Timeout Fix" --type fix
# → Erstellt .specs/.next/0-login-timeout-fix.md mit Family-A-Sektionen
# → Registriert in index.yml mit ID 0, Status: planned

polycrate spec create --name "Dark Mode" --type feat
# → Erstellt .specs/.next/1-dark-mode.md mit Family-B-Sektionen

3. Quick-Capture für neue Observations

Wenn während der Implementierung ein neues Problem auffällt — ohne den aktuellen Kontext zu unterbrechen:

polycrate spec note "S3 upload schlägt still fehl bei 403" --type fix --label s3
# → Erstellt planned Spec sofort, gibt ID zurück
# → Weiterarbeiten am aktuellen Task

4. Spec ausarbeiten

# Status aktualisieren
polycrate spec update 0 --set status=in-progress

# Sektionen füllen — inline
polycrate spec update 0 --section problem="Nach 30 Minuten Inaktivität werden Nutzer ausgeloggt."
polycrate spec update 0 --section root-cause="SESSION_COOKIE_AGE ist auf 1800s gesetzt."
polycrate spec update 0 --section solution="Erhöhe auf 28800s, aktiviere Sliding-Window."

# Sektionen aus Datei (für längeren Content)
polycrate spec update 0 --section-file solution=/tmp/solution.md

# Sektionen aus Stdin (für Pipes und Scripte)
polycrate spec inspect 0 --section analysis | process.py | \
  polycrate spec update 0 --section-stdin solution

Verfügbare Sektionen: problem, analysis, root-cause, feature-description, solution, affected-files, acceptance-criteria, migration, open-questions

5. Spec lesen

polycrate spec inspect 0
polycrate spec inspect 0 --section solution   # Nur eine Sektion

6. Finalisieren

polycrate spec finalize 0
# Validiert: solution nicht leer, open-questions leer
# Bei type=breaking: migration nicht leer
# Bei needs: alle Abhängigkeiten müssen implemented sein
# Setzt status: ready

7. Nach Implementierung

polycrate spec update 0 --set status=implemented

8. Überblick behalten

# Kompakte Tabelle (Default seit 0.32.0)
polycrate spec list

# Filter
polycrate spec list --status in-progress
polycrate spec list --label sdd
polycrate spec list --type fix
polycrate spec list --blocked          # Nur Specs mit nicht-implementierten Abhängigkeiten
polycrate spec list --all              # Inkl. cancelled Specs

# Maschinenlesbar
polycrate spec list --format json

Code-Referenzen in Kommentaren

Wenn eine Spec in einem Code-Kommentar referenziert wird, ist die stabile Referenz die Spec-ID, nicht der Dateipfad:

// Spec: polycrate spec inspect 5     ← KORREKT (stabil, funktioniert nach Release)
// Spec: .specs/.next/5-feature.md    ← FALSCH (Pfad ändert sich beim Release)

Der Dateipfad ist ein Implementierungsdetail. polycrate spec inspect <id> funktioniert unabhängig von Status und Speicherort.


Release-Lifecycle

Release erstellen

# Vorschau: welche Specs sind bereit?
polycrate release diff 1.0.0

# Release erstellen und Specs zuweisen
polycrate release create 1.0.0 --spec 0 --spec 1
# → Verschiebt Spec-Dateien von .next/ nach 1.0.0/
# → Aktualisiert index.yml

Changelog schreiben

polycrate release update 1.0.0 \
  --set type=feat \
  --set message="Login Timeout Fix + API Integration" \
  --changelog-item "FIX: Session-Timeout auf 8h erhöht, Sliding-Window aktiviert" \
  --changelog-item "FEAT: Neue REST-API Integration für Kundendaten"

# Dokumentations-Link setzen (erscheint als Warning in release status wenn fehlend)
polycrate release update 1.0.0 \
  --set docs_url="https://docs.ayedo.de/polycrate/releases/cli/1.0.0/"

Release abschließen

Vor release finalize führt Polycrate automatisch Guards durch:

Guard Verhalten
0 Specs zugewiesen Error — Specs müssen zugewiesen werden
Specs nicht implemented (oder cancelled) Error — erst implementieren
message-Feld leer Warning (blockiert nicht)
docs_url fehlt Warning in release status
Git-Tag existiert bereits Error--force zum Überschreiben
polycrate release status 1.0.0    # Zeigt Warnings und Checklist

polycrate release finalize 1.0.0
# → Setzt workspace.poly version: 1.0.0
# → Erstellt Git-Tag v1.0.0
# → Führt Pre/Post-Actions aus (falls konfiguriert)

# Danach committen und pushen
polycrate workspace sync

Release-Übersicht

polycrate release list
polycrate release status 1.0.0

Validation

polycrate spec validate

Prüft alle Specs auf Konsistenz. Fehlermeldungen sind aktionierbar — sie zeigen immer den Fix-Command:

WARNING: spec 5 [feat]: both 'Feature Description' and 'Solution' are empty
  → Fix: polycrate spec update 5 --section feature-description="Intent and scope."

ERROR: spec 12 [breaking]: 'Migration' section is empty — required for type=breaking
  → Fix: polycrate spec update 12 --section-file migration=/tmp/migration.md

ERROR: spec 7 cannot be finalized — blocked by:
  #3 "Volume Discovery" [planned]
  → Fix: implement spec #3 first

Agent-Integration

SDD ist für die Arbeit mit Coding Agents konzipiert. polycrate spec init und polycrate spec rules generate erzeugen automatisch Instruktionsdateien im Workspace-Root:

Datei Ziel-Agent
CLAUDE.md Claude Code (Anthropic)
AGENTS.md OpenAI Codex, Gemini CLI, andere
.cursor/rules/sdd.mdc Cursor IDE (wird in jede Conversation injiziert)

Was die Agent-Rules-Dateien enthalten

  • Absolute Verbote: Direkte Edits in .specs/ sind verboten
  • Session-Start-Protokoll: Was der Agent zu Beginn einer Session tun muss
  • Vollständige Command-Referenz mit konkreten Beispielen — inkl. Typen, Labels, Needs, Quick-Capture, Code-Referenzen, Release-Guards
  • Recovery-Commands für Index-Inkonsistenzen
  • Projektspezifische Regeln aus .specs/.rules.md
  • Versionsheader: Zeigt mit welcher Polycrate-Version die Rules generiert wurden

Agent-Workflow (Session-Start)

# 1. Manual lesen (LLM-optimiert)
polycrate spec manual --no-pager -w /path/to/workspace

# 2. Projektspezifische Regeln lesen
polycrate spec rules show --no-pager -w /path/to/workspace

# 3. Aktuellen Stand sehen
polycrate spec list --format json -w /path/to/workspace

Agent-Rules aktualisieren

# Nach Polycrate-Upgrade (enthält Versionsheader für Erkennung)
polycrate spec rules generate --force

# Vorschau ohne Schreiben
polycrate spec rules show --no-pager

CLAUDE.md / AGENTS.md

Existieren CLAUDE.md oder AGENTS.md bereits (mit eigenem User-Content), werden sie nicht überschrieben — auch nicht mit --force. Stattdessen wird der SDD-Abschnitt im Terminal ausgegeben, damit er manuell eingefügt werden kann.


Recovery

Wenn der Index durch externe Eingriffe inkonsistent geworden ist:

# Index aus Dateisystem neu aufbauen
# Erkennt automatisch Legacy-Formate und vergibt stabile IDs via Dateiname-Hash
polycrate spec index rebuild

# Konsistenz prüfen
polycrate spec validate

Sandbox und Runtime-Verzeichnis

SDD-Commands (polycrate spec *, polycrate release *) starten keinen vollständigen Workspace — kein Docker, kein Container. Sie sind leichtgewichtig und funktionieren auch in eingeschränkten Umgebungen.

In Sandbox-Umgebungen (z. B. eingeschränkte Schreibrechte auf HOME):

polycrate spec list --runtime-dir /tmp/polycrate-run -w /pfad/zum/projekt

→ Details: CLI-Referenz — Runtime-Verzeichnis


Typischer Workflow (Gesamtübersicht)

sequenceDiagram
    participant Dev as Entwickler
    participant CLI as polycrate spec
    participant Agent as Coding Agent
    participant Rel as polycrate release

    Dev->>CLI: spec init
    CLI-->>Dev: .specs/ + Agent-Rules-Dateien

    Dev->>CLI: spec create --name "Feature X" --type feat
    CLI-->>Dev: ID 0, status: planned

    Dev->>CLI: spec update 0 --set status=in-progress
    Dev->>CLI: spec update 0 --section feature-description="..."
    Dev->>CLI: spec update 0 --section solution="..."

    Agent->>CLI: spec inspect 0
    CLI-->>Agent: Spec-Inhalt
    Agent->>Agent: Implementierung
    Agent->>CLI: spec note "Neues Problem entdeckt" --type fix
    Agent->>CLI: spec update 0 --set status=implemented

    Dev->>Rel: release create 1.0.0 --spec 0
    Dev->>Rel: release update 1.0.0 --set type=feat ...
    Dev->>Rel: release status 1.0.0
    Dev->>Rel: release finalize 1.0.0
    Rel-->>Dev: workspace.poly version=1.0.0, Git-Tag v1.0.0

Alle Commands im Überblick

polycrate spec

Command Beschreibung
spec init .specs/-Struktur + Agent-Rules initialisieren
spec create --name <name> Neue Spec anlegen (--type für Typ-Scaffolding)
spec note "<text>" Quick-Capture: minimale Spec sofort anlegen (--type, --label)
spec list Alle Specs als kompakte Tabelle (--label, --type, --blocked, --all, --format json)
spec inspect <id> Spec-Inhalt anzeigen (--section <name>)
spec update <id> Frontmatter (--set), Sektionen (--section, --section-file, --section-stdin), Labels (--add-label, --remove-label), Needs (--add-needs, --remove-needs)
spec link <id> Abhängigkeit deklarieren: --needs <dep-id> (Alias für --add-needs)
spec finalize <id> Spec validieren und auf ready setzen (prüft needs, type-Regeln)
spec delete <id> Spec löschen
spec validate Alle Specs auf Konsistenz prüfen — aktionierbare Fehlermeldungen
spec index rebuild Index aus Dateisystem neu aufbauen (Recovery)
spec manual Vollständiges LLM-optimiertes Manual ausgeben (--no-pager)
spec rules generate Agent-Rules-Dateien erzeugen (--force zum Überschreiben)
spec rules show Agent-Rules-Inhalt anzeigen ohne Dateien zu schreiben

polycrate release

Command Beschreibung
release create <version> Release erstellen, Specs zuweisen (--spec <id>)
release update <version> Changelog schreiben (--set, --changelog-item, --set docs_url=...), weitere Specs zuweisen
release finalize <version> Guards prüfen, Version setzen, Git-Tag, Pre/Post-Actions (--force)
release list Alle Releases auflisten
release status <version> Release-Detail anzeigen inkl. Warnings (fehlende docs_url, leeres message)
release diff <version> Vorschau: welche Specs würden zugewiesen
release unassign <version> Spec zurück in .next/ verschieben
release delete <version> Release rückgängig machen (destructive)

Siehe auch