Workflow-Anpassung für Brownfield-Projekte
Einleitung
Du hast den Greenfield-Workflow gemeistert. Jetzt willst du ihn auf eine bestehende Codebasis anwenden.
Die Grundprinzipien bleiben gleich: kleine Schritte, hohe Autonomie, Fehlerkorrektur-Schleifen. Aber Brownfield-Projekte bringen eine Herausforderung, die Greenfield-Projekte nicht haben: das System existiert bereits. Man kann nicht bei null anfangen. Man muss verstehen, was da ist, bevor man etwas ändert.
Dieses Dokument beschreibt, wie man eine bestehende Codebasis in den Spec-Driven-Workflow überführt. Die zentrale Erkenntnis stammt aus Simon Martinellis AI Unified Process: Man muss nicht das gesamte System spezifizieren. Man arbeitet einen Bounded Context nach dem anderen. Die Spec-Abdeckung wächst inkrementell, Feature für Feature.
Das Brownfield-Paradox
Bei Greenfield-Projekten schreibt man zuerst die Spec, dann folgt der Code. Bei Brownfield-Projekten existiert der Code bereits — aber die Spec oft nicht. Das System ist die Spezifikation, nur kann sie niemand lesen.
Die Versuchung ist groß, das gesamte System vor jeder Änderung in Dokumentation zu überführen. Das ist Big Upfront Documentation, und es scheitert aus denselben Gründen wie Big Upfront Design.
Stattdessen: Nur den Bounded Context spezifizieren, den man gerade ändern will, und auch nur so viel, wie für eine sichere Änderung nötig ist.
Phase 0: Bounded Context eingrenzen
Vor jeder Code-Änderung den Bereich identifizieren, der geändert werden soll.
Ein Bounded Context ist ein zusammenhängender Ausschnitt des Systems mit klaren Grenzen. Das kann ein Modul sein, ein Service, ein Feature-Bereich oder ein Bildschirm. Die Grenzen sollten klein genug sein, dass man den Kontext in einer einzigen Session verstehen kann.
⚓ Domain-Driven Design nutzen, um die Kontextgrenzen zu identifizieren. Die KI kann dabei helfen: auf den Code zeigen und nach Bounded Contexts und deren Schnittstellen fragen.
Analyze the codebase in src/. Identify bounded contexts using Domain-Driven Design. For each context, list: name, responsibility, key entities, interfaces to other contexts. Present as a table.
Einen Bounded Context zum Starten auswählen. Einen wählen, der klein, gut isoliert ist und eine anstehende Änderungsanforderung hat.
Phase 0.5: Socratic Code-Theory Recovery
Vor jeder Änderung muss die "Theorie" des Bounded Context rekonstruiert werden — das, was Peter Naur das mentale Modell nannte, das in den Köpfen der ursprünglichen Entwickler lebt. In einem Brownfield-Projekt ist dieses Modell nicht dokumentiert. Der Code ist die einzige Quelle.
Diese Phase nutzt Socratic Code-Theory Recovery: einen zweiphasigen Workflow, der Verständnis durch rekursive Frageverfeinerung aufbaut, bevor Dokumentation erzeugt wird.
|
Die Prompts dieser Phase sind auch als installierbarer Claude Code Skill verpackt. Installations-Anleitungen für Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI und Amazon Kiro auf der Skill-Seite Socratic Code-Theory Recovery. |
Phase 1: Question Tree aufbauen
Mit fünf Wurzelfragen zum Bounded Context starten. Ihre zweite Ebene ist fix: jeder Lauf erzeugt denselben vorgegebenen Satz an Unterfragen — die sechs PRD-Elemente (Q1.1–Q1.6), sechs Spezifikationskategorien (Q2.1–Q2.6), die zwölf arc42-Kapitel (Q3.1–Q3.12), die acht ISO/IEC-25010-Merkmale plus eine Prioritätsfrage (Q4.1–Q4.9) und fünf Risikokategorien (Q5.1–Q5.5). Freie, code-getriebene Zerlegung gilt nur unterhalb dieser fixen Ebene. Die fixe Ebene hält Q-IDs stabil — Q3.7 ist immer die Verteilungssicht —, sodass Bäume verschiedener Läufe Knoten für Knoten verglichen werden können.
Jedes Blatt im Baum ist entweder [ANSWERED] (mit Code-Evidenz: Datei, Funktion, Zeile) oder [OPEN] (mit Category und Ask-Rolle). Der Output sind zwei AsciiDoc-Dateien: QUESTION_TREE.adoc (vollständige Begründungs-Spur) und OPEN_QUESTIONS.adoc (Handoff-Dokument, nach Rolle gruppiert).
Den Prompt unten 1:1 in eine Session kopieren, die Lesezugriff auf den Bounded Context hat. [bounded context path] und die Beispielfragen an die eigene Domäne anpassen; die Blatt-Klassifikation, das Q-ID-Schema und die Output-Dateien nicht verändern.
You are performing Socratic Code-Theory Recovery on a brownfield bounded
context located at [bounded context path]. Phase 1 of two.
Goal: recover the program's theory (Naur, 1985) from source code through
recursive question refinement, before any documentation is written.
Process:
1. Start with five root questions about the bounded context:
Q1 What problem does this bounded context solve, and for whom?
Q2 What is the specification of this bounded context?
Q3 What is the architecture of this bounded context?
Q4 What quality goals drive the design?
Q5 What risks and technical debt exist?
2. The second level of the tree is FIXED, not free. Emit exactly these
nodes, in this order, even when a node's only leaf is [OPEN] or
[ANSWERED: not applicable]:
Q1.1-Q1.6 product identity, primary users, channels, why-built,
success metrics, segment priority
Q2.1-Q2.6 actors, use-case catalog, per-interface system specs,
data/entity model, acceptance criteria, cross-cutting
business rules
Q3.1-Q3.12 the twelve arc42 chapters, in arc42 order
Q4.1-Q4.8 the eight ISO/IEC 25010 characteristics;
Q4.9 which characteristic has priority
Q5.1-Q5.5 technical debt, security risks, operational risks,
dependency/supply-chain risks, scaling/performance risks
3. Below the fixed second level, decompose freely and code-driven. Stop
when a leaf is small enough to answer from a single piece of code
evidence, or to pose as a single precise question to a stakeholder.
Third-level depth varies between runs — that is expected. Q-IDs are
stable: Q3.7 is always the Deployment View, in every run, so trees
from different runs can be diffed node-by-node.
4. For each leaf, classify it:
[ANSWERED]
- You found the answer in the code.
- Cite the evidence as <file>:<line> or <file>::<function>.
- Be exact. No "see X for details."
[OPEN]
- The answer is not derivable from code alone.
- Category: business-context | design-rationale | quality-goals |
stakeholder-context | future-direction
- Ask role: Product Owner | Architect | Developer | Domain Expert |
Operations
- State precisely what cannot be answered, and why.
Quality (the Q4 branch) is not wholly team knowledge. Where the code
shows measurable behaviour — a timeout, a truncation limit, a budget,
a retry policy, the threats and test concept from Q3.8 — write it as
an [ANSWERED] quality scenario with file:line. Never invent a target
number. Only the quality-goal ranking (Q4.9) is [OPEN].
5. Output two files in AsciiDoc:
QUESTION_TREE.adoc
- Full hierarchical tree with all nodes and Q-IDs
- Each leaf marked [ANSWERED] (with evidence) or [OPEN] (with Category
and Ask role)
- Includes all reasoning, not only the leaves
OPEN_QUESTIONS.adoc
- Only the [OPEN] leaves, copied verbatim from QUESTION_TREE.adoc
- Always one section per Ask role (Product Owner, Architect,
Developer, Domain Expert, Operations) — emit every section even
when it is empty ("No open questions for this role")
- Each question short enough to be answered in 1-3 sentences
Do not write any other documentation in this phase. Phase 2 will synthesize
the answered tree into PRD, specification, arc42, and ADRs — only after the
team has filled in the [OPEN] leaves.
Zwischen den Phasen: Das Team beantwortet die offenen Fragen
Die Open Questions an die Personen weiterleiten, die sie beantworten können. In einem kontrollierten Experiment mit einer 13.000-Zeilen-Go-Codebasis reichten 11 gezielte Fragen aus, um die Lücke zwischen reverse-engineerter Dokumentation und Original zu schließen. Die Fragen sind präzise, weil die rekursive Zerlegung sie spezifisch macht, nicht vage.
Typische Fragen, die das LLM nicht aus dem Code beantworten kann:
| Category | Beispiel |
|---|---|
Business Context |
Warum wurde das gebaut? Welche Alternativen gab es? |
Design Rationale |
Warum JSONC statt YAML? Warum diese Library? |
Quality Goals |
Welches Qualitätsziel hat Priorität? Welche Schwellwerte? |
Stakeholder Context |
Wer nutzt das? Welches Erfahrungslevel? |
Future Direction |
Was ist geplant, aber noch nicht umgesetzt? |
Phase 2: Dokumentation synthetisieren
Das LLM synthetisiert die beantworteten Fragen plus die Code-Evidenz aus Phase 1 zur Dokumentation gemäß dem Spec-Driven-Workflow:
-
PRD aus den Antworten im Q1-Ast
-
Spezifikation (Cockburn Use Cases, CLI-Spec, Datenmodelle, Gherkin-Akzeptanzkriterien) aus dem Q2-Ast
-
arc42 mit allen 12 Kapiteln aus dem Q3-Ast
-
Nygard-ADRs mit Pugh-Matrix aus dem Q3.9-Ast
Code-basierte Aussagen tragen die file:line-Evidenz aus ihrem [ANSWERED]-Leaf — eine Referenz auf den Code, das einzige dauerhafte Artefakt; teamgegebene Information wird mit (team answer) markiert. Der Question Tree ist temporäres Gerüst, daher landen Q-IDs nicht in den finalen Dokumenten — beim Synthetisieren wird jede Aussage als Build-Time-Prüfung auf ein Leaf zurückgeführt. Diese doppelte Rückverfolgbarkeit (Code-Evidenz + Team-Input) ist der entscheidende Unterschied zu einem einfachen Reverse-Engineering-Prompt.
Basis-Tests aufbauen
Aus den synthetisierten Use Cases Tests schreiben, die das bestehende Verhalten verifizieren. Diese Tests sind das Sicherheitsnetz.
Based on the Use Cases in docs/specs/use-cases-[context-name].adoc, write tests that verify the current behavior.
Use TDD, London School. Each test references its Use Case ID for traceability.
Do not change any production code. Only add tests.
Tests ausführen. Jeder Test muss gegen den aktuellen Code bestehen. Wenn ein Test fehlschlägt, war der extrahierte Use Case falsch — Use Case korrigieren, dann Test korrigieren.
|
Basis-Tests nicht überspringen. Ohne sie kann man nicht unterscheiden zwischen "meine Änderung hat etwas kaputt gemacht" und "es war schon vorher kaputt". Das ist die geschlossene Schleife, die Brownfield-Änderungen sicher macht. |
Was das LLM rekonstruieren kann — und was nicht
Ein kontrolliertes Experiment (Dokumentation aus einem Greenfield-Projekt löschen und aus dem Code wieder erzeugen) zeigte:
Aus dem Code ableitbar: funktionale Anforderungen (21 vs. 7 im Original), Akzeptanzkriterien (69 vs. 40), Building-Block-Views, Glossar (31 Begriffe vs. 2 Platzhalter), Sicherheitsmechanismen, Crosscutting Concepts.
NICHT aus dem Code ableitbar: Business Context, Design Rationale (das ADR-"Warum"), Priorisierung von Qualitätszielen, Stakeholder-Belange, geplante Features, Performance-Budgets, Tutorials, Review-Ergebnisse.
Semantic Anchors haben in diesem Workflow eine doppelte Funktion: Prompt-Kompression (ein 69-Zeilen-Prompt erzeugte 3.850 Zeilen korrekt strukturierter Dokumentation) und Zerlegungs-Heuristik ("arc42" erzeugt 12 MECE-Subfragen ohne weitere Anweisungen).
Spec-Drift und Abgleich
Selbst in gut dokumentierten Projekten driftet die Spezifikation vom Code weg. Das Implementierungs-LLM ergänzt Security-Hardening, Validierungsregeln und Edge Cases, die nie in der ursprünglichen Spec standen. Das ist kein Disziplinproblem — es ist eine strukturelle Eigenschaft des Workflows.
Die Lösung: regelmäßiger Spec-Reconciliation. Den Reverse-Engineering-Prompt gegen den aktuellen Code laufen lassen und gegen die bestehende Spec diffen. Der Diff zeigt neue Anforderungen (im Code, nicht in der Spec), verändertes Verhalten (auseinandergedriftet) und tote Spec (dokumentiert, aber entfernt).
Drei natürliche Trigger-Punkte: vor einem Release, nach einem Security-Review, vor einem Onboarding.
Phase 1-12: Der Standard-Workflow
Sobald Use Cases und Basis-Tests für den Bounded Context vorhanden sind, greift der normale Workflow.
-
Neue Features bekommen neue Use Cases, neue Akzeptanzkriterien und neue Tests — genau wie bei Greenfield.
-
Bug Fixes beginnen damit, den verletzten Use Case zu identifizieren, dann folgt der TDD-Bug-Fix-Loop (Schritt 12).
-
Refactoring ist durch die Basis-Tests abgesichert. Solange die Tests grün bleiben, ist das Refactoring sicher.
Der einzige Unterschied: Die arc42-Dokumentation ist vielleicht anfangs unvollständig. Das ist in Ordnung. Die Architektur-Abschnitte ausfüllen, während man das System kennenlernt. Nach ein paar Bounded Contexts deckt die Architekturdokumentation die relevanten Teile ab.
Inkrementelle Erweiterung
Nach dem ersten Bounded Context den nächsten auswählen. Jeder eingeführte Kontext erweitert die Spec-Abdeckung des Systems.
Mit der Zeit ergibt sich ein Muster:
| Iteration | Abdeckung |
|---|---|
Erster Kontext |
Ein Feature-Bereich hat Use Cases, Tests und Architekturdokumentation. |
3-5 Kontexte |
Der Kern des Systems ist dokumentiert. Querschnittsthemen werden sichtbar. |
10+ Kontexte |
Die meisten Änderungen passieren in Bereichen mit bestehenden Specs. Neue Arbeit fühlt sich an wie Greenfield. |
100% Abdeckung ist nicht nötig. Das Ziel ist, die Bereiche abzudecken, die sich am häufigsten ändern. Stabiler Code, den niemand anfasst, braucht keine Specs.
Prompt Cheat Sheet: Brownfield
| Phase | Prompt | Anker |
|---|---|---|
Scope |
|
|
Theory Recovery (Phase 1) |
|
|
Team Answers |
OPEN_QUESTIONS.adoc nach Ask-Rolle ans Team verteilen. Typisch 10-15 Fragen. |
— |
Theory Recovery (Phase 2) |
|
|
Basis-Tests |
|
|
Weiter |
Ab hier dem Standard-Workflow ab Schritt 3 (PRD) oder Schritt 8 (Implementierung) folgen, je nachdem ob neue Features oder Bugs bearbeitet werden. |
— |
Reconciliation |
|
— |
Wann dieser Ansatz nicht passt
Dieser Workflow setzt voraus, dass man das bestehende System weiterentwickeln will. Wer einen kompletten Neubau plant, nimmt stattdessen den Greenfield-Workflow.
Er setzt auch voraus, dass der bestehende Code lauffähig ist. Wenn das System nicht gebaut oder gestartet werden kann, liegt ein anderes Problem vor — das zuerst lösen.
Weiterführende Literatur
-
The Harness Inventory — die Error-Correction-Schichten, die jeden agentischen Workflow umgeben, auch diesen. Brownfield Recovery erhöht das Signal; das Harness-Inventar katalogisiert, was das verbleibende Rauschen abfängt.
-
Simon Martinelli, AI Unified Process — der Bounded-Context-Ansatz für Spec-Driven Development in bestehenden Systemen.
-
Eric Evans, Domain-Driven Design — das grundlegende Werk zu Bounded Contexts und strategischem Design.
-
Michael Feathers, Working Effectively with Legacy Code — Techniken zum Aufbau von Testabdeckung in Systemen ohne Tests.
-
Peter Naur, "Programming as Theory Building" (1985) — argumentiert, dass Programmieren der Aufbau eines mentalen Modells ("Theorie") ist, das sich nicht vollständig in Dokumentation einfangen lässt. Socratic Code-Theory Recovery prüft diese Behauptung im Kontext von LLM-generiertem Code.
-
Brownfield Experiment Report — kontrolliertes Experiment: Dokumentation aus einem Greenfield-Projekt löschen, aus Code regenerieren, vergleichen. Vollständige Methodik und Befunde.
-
Fair Comparison Report — drei Ansätze (Direct, Socratic, Two-Phase) mit identischen Team-Antworten. Misst den strukturellen Wert des Question Tree.