Specs, Tests und Code in der KI-Entwicklung synchron halten

Verhindern Sie, dass KI-Agenten von den Spezifikationen, Tests und dem Code abweichen.

Inhaltsverzeichnis

KI-Coding-Agenten liefern Features schnell, aber Spezifikationen, Tests und Code veralten stillschweigend und gehen auseinander. Dieser Leitfaden behandelt ein Nachverfolgungsmodell (Traceability), die Zuordnung von Spezifikation zu Test und von Spezifikation zu Code sowie die CI-Prüfungen, die Abweichungen vor einem Merge erkennen.

Eine Spezifikation, die niemand gegen das laufende System überprüft, ist schlimmer als gar keine Spezifikation, da sie falsches Vertrauen schafft. Reviewer vertrauen dem Dokument statt auf den Diff, und ein KI-Agent, der angewiesen wird, „dem bestehenden Muster zu folgen“, folgt gerne dem, was der Code tatsächlich tut, selbst wenn dies der Anforderung widerspricht, die er erfüllen sollte.

Die Lösung ist nicht mehr Dokumentation. Es ist ein kleiner, durchsetzbarer Zusammenhang zwischen vier Dingen, die in den meisten Repositories bereits existieren: die Anforderung, die dahinterliegende Designentscheidung, die Tests, die sie beweisen, und die Commits oder Pull Requests, die sie geändert haben.

Nachverfolgungslinks, die Spezifikationen, Tests und Code verbinden

Sobald dieser Zusammenhang als Daten und nicht als gemeinsames Verständnis existiert, können Sie ihn abfragen. Sie können fragen, welche Anforderungen keine Testabdeckung haben, welche Tests nicht mehr auf eine Anforderung verweisen und welche Dateien in einem Pull Request geändert wurden, ohne dass eine passende Anforderungs-ID vorliegt. Diese Abfrage ist das eigentliche Ergebnis dieses Artikels, und der Rest des Beitrags zeigt, wie Sie ihn mit Tools aufbauen, die Sie wahrscheinlich bereits verwenden.

Das Abweichungsproblem: Warum Spezifikationen, Tests und Code aus dem Takt geraten

Abweichungen zeigen sich in vier erkennbaren Formen, und KI-gestützte Teams stoßen tendenziell schneller auf alle vier als Teams, die jede Zeile von Hand schreiben.

  • Spezifikation ändert sich, Code nicht. Eine Anforderung wird in einer Folgekonversation oder einem Kommentar-Thread geklärt, aber niemand regeneriert oder bearbeitet die Implementierung, um sie anzupassen.
  • Code ändert sich, Spezifikation nicht. Ein Agent oder Entwickler behebt einen Fehler oder refaktorisiert ein Modul, und die Spezifikation beschreibt weiterhin das alte Verhalten, als wäre es noch aktuell.
  • Tests decken die Implementierung ab, nicht die Absicht. Unit-Tests prüfen, was der Code aktuell tut, was zirkulär ist: Sie bestehen per Konstruktion, auch wenn der Code die falsche Anforderung erfüllt.
  • Pull Requests verweisen nicht auf Anforderungen. Reviewer genehmigen einen Diff basierend auf „sieht vernünftig aus“, da es keinen expliziten Anspruch gibt, gegen den er überprüft werden könnte.

Neuere Prozessforschung zu KI-Entwicklungsframeworks identifiziert Spezifikationsabweichungen als wiederkehrendes Risiko, genau deshalb, weil Agents Code schnell und wiederholt regenerieren, und jede Regeneration eine neue Gelegenheit bietet, dass Spezifikation und Implementierung etwas weiter auseinanderdriften. Die Debatte über Spec-Driven Development vs. Vibe Coding ist im Grunde ein Streit über genau dieses Versagensmuster: Eine Spezifikation, die niemand durchsetzt, degeneriert in die gleiche Abweichung wie ohne eine, nur mit zusätzlichem Zeremoniell.

Moderne Workflow-Ansätze im Stil von Spec-Kit betrachten dies zunehmend als Spezifikationsverfall: Die Spezifikation wirkt weiterhin autoritativ, verliert aber stillschweigend ihre Verbindung zu dem, was das System tatsächlich tut. Die Kerndefinition von spec-getriebener Entwicklung behandelt die Spezifikation als Single Source of Truth, aber eine Single Source of Truth bleibt nur wahr, wenn etwas sie kontinuierlich gegen die Realität überprüft.

Ein Nachverfolgungsmodell für KI-gestützte Entwicklung

Ein funktionierendes Nachverfolgungsmodell benötigt sechs Identifikatoren, die eine Geschäftsanforderung bis hinunter zu den Codezeilen und dem Pull Request, der sie implementiert hat, verbinden. Die meisten Teams haben bereits drei oder vier davon; die fehlenden sind in der Regel die Designentscheidungs-ID und der explizite Rückverweis von Tests und Commits.

Identifikator Existiert in Beispiel
Anforderungs-ID requirements.md oder Spec-Tool REQ-014
Designentscheidungs-ID ADR / Entscheidungsprotokoll ADR-0032
Task-ID Task-Aufschlüsselung oder Issue-Tracker TASK-014-3
Test-ID Testdatei oder Testname test_req_014_password_reset
Commit-/PR-Link Git-Historie PR #482
Geänderte Dateien Git-Diff auth/reset.go, auth/reset_test.go

Die Beziehungen zwischen diesen Identifikatoren bilden einen Graphen und keine gerade Linie, da eine Anforderung mehrere Tasks auslösen kann und ein Pull Request gleichzeitig mehrere Anforderungen betreffen kann.

graph TD REQ["Anforderung
REQ-014"] --> ADR["Designentscheidung
ADR-0032"] ADR --> TASK["Task
TASK-014-3"] TASK --> CODE["Code-Änderung
auth/reset.go"] TASK --> TEST["Test
test_req_014_password_reset"] CODE --> PR["Pull Request
#482"] TEST --> PR PR --> COMMIT["Commit-Historie"]

Die Speicherung dieses Graphen als strukturierte Daten und nicht als Prosa ermöglicht es, ihn später abzufragen. Das GitHub-Spec-Kit-Ökosystem hat sich genau in diese Richtung entwickelt: Erweiterungen wie spec-kit-trace scannen REQ-XXX-Tokens, die in Spezifikations- und Testdateien eingebettet sind, und generieren daraus eine deterministische Matrix basierend auf dieser wörtlichen Textübereinstimmung, wobei sie bewusst ungenaue, namebasierte Vermutungen vermeiden, die zu stillen falschen Positiven führen.

Spezifikation-zu-Test-Zuordnung: Akzeptanzkriterien in Testfälle verwandeln

Jedes Akzeptanzkriterium in einer Spezifikation ist per Konstruktion eine Verhaltensbehauptung: Bei diesem Zustand, wenn der Akteur dies tut, sollte das System so reagieren. Das ist bereits die Struktur eines Testfalls, weshalb die stärksten SDD-Workflows Tests aus denselben Akzeptanzkriterien generieren, die auch den Code generieren, anstatt den Code-generierenden Agenten nachträglich zu bitten, seine eigenen Tests zu erfinden.

Ein weit verbreitetes Format für die Formulierung dieser Kriterien ist EARS (Easy Approach to Requirements Syntax), das jede Anforderung in ein unambiges, testbares Muster zwingt, wie „Wenn <Trigger>, dann soll das System <Antwort>.“ Diese Struktur lässt sich sauber auf vier Kategorien von Tests abbilden, die jede Anforderung enthalten sollte:

  • Positive Tests — der Happy Path, den die Anforderung explizit beschreibt.
  • Negative Tests — Eingaben oder Zustände, die die Anforderung ablehnen muss.
  • Grenzwerttests — die Ränder von Bereichen, Limits und Schwellenwerten, die in den Akzeptanzkriterien erwähnt werden.
  • Migrationstests — Verhalten für Daten oder Zustände, die vor der Anforderung existierten, sodass ein alter Datensatz nicht stillschweigend eine neue Regel umgeht.
Anforderungstyp Hinzuzufügende Testkategorie Häufiger Fehler
„System soll X ablehnen“ Negativ Nur der Akzeptanzpfad wird getestet
„Limit ist N Elemente“ Grenzwert N-1, N und N+1 werden nicht alle abgedeckt
„Neues Feld ersetzt altes Feld“ Migration Alte Datensätze ohne neues Feld stürzen stillschweigend ab
„Innerhalb von 60 Sekunden“ Grenzwert + Timing Test prüft Logik, nicht den tatsächlichen Zeitbudget

Unit-Tests, die auf diese Weise geschrieben werden, sind weiterhin als schnelle, günstige Schicht der Pyramide relevant; die praktischen Muster für ihre Strukturierung werden im Go-Unit-Testing-Leitfaden und im Python-Unit-Testing-Leitfaden behandelt. Was Nachverfolgbarkeit zusätzlich bietet, ist ein wörtlicher, stabiler Anforderungstoken, der im Testnamen oder in einem Testkommentar eingebettet ist, sodass eine spätere Abfrage beweisen kann – statt anzunehmen –, dass REQ-014 abgedeckt ist.

Spezifikation-zu-Code-Zuordnung: Von Designplänen zu einer Trace-Tabelle

Die Spezifikation-zu-Test-Zuordnung beweist Verhalten; die Spezifikation-zu-Code-Zuordnung beweist den Umfang. Sie beantwortet eine andere Frage: Welche Dateien sollten für diese Anforderung tatsächlich geändert werden, und ist der Diff innerhalb dieser Grenze geblieben oder hat er sich in unbezogene Module ergossen?

Ein Designplan, der von vornherein betroffene Dateien auflistet – selbst eine grobe Liste – gibt Ihnen etwas, gegen das Sie den tatsächlichen Pull Request später diffen können. Kommentare im Code sollten nur dann eine Anforderungs-ID referenzieren, wenn dies Informationen hinzufügt, die ein Reviewer nicht aus der Spezifikation selbst erhalten kann; ein Kommentar, der den Anforderungstext wortwörtlich wiederholt, ist Rauschen, aber // erzwingt REQ-014-Grenze: max 5 Reset-Versuche pro Stunde verdient seinen Platz, da die Zahl im Diff sonst unsichtbar wäre.

Eine generierte Trace-Tabelle verwandelt dies in etwas, das in Sekunden überprüft werden kann, anstatt dass ein Reviewer es durch das Lesen beider Dokumente nebeneinander rekonstruieren muss:

Anforderung Designentscheidung Geänderte Dateien Tests Status
REQ-014 ADR-0032 auth/reset.go, auth/reset_test.go test_req_014_* (4) Abgedeckt
REQ-015 ADR-0032 auth/reset.go keine Lücke
REQ-016 auth/notify.go test_notify_basic Verwaister Spec-Link

Diese einzelne Tabelle macht zwei der häufigsten Versagensmuster auf einen Blick sichtbar: REQ-015 hat Code geändert, ohne dass passende Tests vorhanden sind, und der Test, der an REQ-016 angehängt ist, referenziert keine Anforderungs-ID, was bedeutet, dass entweder die Spezifikation fehlt oder der Test falsch abgelegt wurde.

Der Pull-Request-Workflow: Spezifikation, Code und Test-Diffs gemeinsam überprüfen

Ein Pull Request, der auf Nachverfolgbarkeit basiert, überprüft drei Diffs nebeneinander anstatt eines: Was sich in der Spezifikation geändert hat, was sich im Code geändert hat und was sich in den Tests geändert hat. Die Review-Frage hört auf, „sieht das richtig aus?“ zu sein, und wird zur viel spezifischeren Frage: „Welche Anforderung erfüllt diese Änderung, und beweisen die Beweise dies?“

sequenceDiagram participant Dev as Entwickler oder Agent participant PR as Pull Request participant CI as CI-Pipeline participant Rev as Reviewer Dev->>PR: PR öffnen mit Spec-Diff + Code-Diff + Test-Diff PR->>CI: Nachverfolgungsprüfungen auslösen CI->>CI: Überprüfen, ob REQ-ID in PR-Beschreibung vorhanden ist CI->>CI: Spec-zu-Test-Abdeckungsprüfung ausführen CI->>CI: Spec-zu-Code-Dateiumfangsprüfung ausführen CI-->>PR: Trace-Bericht als PR-Kommentar posten Rev->>PR: Überprüfung gegen „welche Anforderung erfüllt dies?“ Rev->>PR: Genehmigen oder Änderungen anfordern

Eine kurze, konkrete Reviewer-Checkliste funktioniert hier besser als eine lange, da Reviewer lange Checklisten unter Zeitdruck überspringen:

  1. Nennt die PR-Beschreibung die Anforderungs-ID(s), die sie erfüllt?
  2. Erscheint jede geänderte Datei in der Liste der betroffenen Dateien des Designplans, oder wird der zusätzliche Umfang erklärt?
  3. Referenziert mindestens ein neuer oder bestehender Test jede Anforderungs-ID, die von diesem PR berührt wird?
  4. Wenn sich die Spezifikation geändert hat, haben sich Code und Tests im selben PR geändert, oder gibt es eine verfolgte Folgeaktion?

Automatisierung der Nachverfolgbarkeit in CI

Manuelle Überprüfung fängt Abweichungen nur so oft ein, wie Reviewer daran denken, nach ihnen zu suchen, weshalb die oben genannten Prüfungen in CI gehören und nicht auf einer Wiki-Seite, die niemand erneut liest. Die gleichen GitHub Actions Cheat Sheet-Muster, die Sie bereits für Build- und Testjobs verwenden, gelten hier direkt – Nachverfolgbarkeitsprüfungen sind einfach ein weiterer Job in derselben Pipeline.

Praktische Automatisierungsideen, grob in Reihenfolge des Aufwands:

  • CI-Prüfungen für Spezifikationsdateien — Build fehlgeschlagen, wenn eine Spezifikationsdatei bearbeitet wurde, ohne dass eine entsprechende Code- oder Teständerung im selben PR vorlag, oder umgekehrt.
  • Anforderungs-IDs in PR-Titeln oder Beschreibungen erforderlich machen — eine leichte Regex-Prüfung (REQ-\d+) blockiert Merges, die nicht benennen, was sie implementieren.
  • Agent-generierte Trace-Zusammenfassungen — lassen Sie einen Agenten eine kurze Zusammenfassung der Anforderungen erstellen, die ein PR berührt, damit ein Mensch diese bestätigen kann, anstatt sie von Grund auf neu zu schreiben.
  • Testabdeckung nach Akzeptanzkriterium, nicht nur nach Zeile — Zeilenabdeckung sagt Ihnen, dass Code ausgeführt wurde; Anforderungsabdeckung sagt Ihnen, dass ein Anspruch überprüft wurde.
  • Warnungen für veraltete Spezifikationen — markieren Sie Spezifikationen, die seit N Commits, die ihre verknüpften Dateien berühren, nicht berührt wurden, da lang stille Spezifikationen die sind, die am wahrscheinlichsten stillschweigend verfallen sind.

Auf dem GitHub-Spec-Kit basierende Erweiterungen implementieren mehrere dieser mechanisch: Eine scannt wörtliche REQ-XXX-Tokens über Spezifikations- und Testdateien hinweg, um eine Matrix zu erstellen und verwaiste Tests zu markieren, und ein strengerer, V-Modell-orientierter Pack geht noch weiter, indem er für jede Entwicklungsspezifikation eine gepaarte Testspezifikation generiert und mehrere Nachverfolgungsmatrizen für Teams erzeugt, die unter regulatorischen Frameworks wie IEC 62304 oder ISO 26262 arbeiten. Sie benötigen dieses Maß an Zeremoniell für die meisten Projekte nicht, aber die zugrunde liegende Idee – eine deterministische, skriptgenerierte Matrix statt einer manuell gepflegten Tabelle – skaliert genauso gut nach unten wie nach oben.

KI-Agenten für Nachverfolgbarkeit nutzen, nicht als Orakel

KI-Agenten sind gut für die mechanischen Teile der Nachverfolgbarkeit geeignet und schlecht dafür, das letzte Urteil abzugeben, ob eine Anforderung tatsächlich erfüllt wurde. Drei Aufgaben passen direkt zu den Stärken eines Agents:

  • Spezifikation und Diff vergleichen — bitten Sie den Agenten, jede Anforderung aufzulisten, die in den von einem PR berührten Spezifikationsdateien erwähnt wird, und jede, für die er keinen entsprechenden Code gefunden hat.
  • Unabgedeckte Anforderungen finden — bitten Sie den Agenten, die Testsuite nach Anforderungstokens zu scannen und zu berichten, welche Anforderungen in der Spezifikation keine haben.
  • Code erkennen, der nicht durch Spezifikation beschrieben wird — bitten Sie den Agenten, geänderte Dateien oder Funktionen zu markieren, die anforderungstragende Module berühren, aber nicht mit einer Anforderungs-ID im Diff korrespondieren.

Das Versagensmuster, dem man vorbeugen muss, ist das Vertrauen in die Zusammenfassung des Agents als Grundwahrheit statt als Ausgangspunkt für einen Reviewer. Ein Agent kann einen Kommentar falsch lesen, einen Anforderungstoken über zwei Dateien hinweg verpassen oder selbstbewusst Abdeckung für einen Test erklären, der den Codepfad nur oberflächlich ausübt. Behandeln Sie jeden agentengenerierten Trace-Bericht so, wie Sie den Pass eines Junior-Reviewers behandeln würden: nützlich, schnell und immer noch einem zweiten Blick unterworfen, bevor er einen Merge blockiert. Dies ist die gleiche Vorsicht, die auf Entscheidungsprotokolle für KI-gesteuerte Entwicklung zutrifft – das Protokoll bleibt nur vertrauenswürdig, wenn etwas anderes als der Agent, der es geschrieben hat, es schließlich überprüft.

Eine minimale Nachverfolgungsvorlage, die Sie kopieren können

Sie benötigen kein schweres Framework, um zu beginnen. Eine fünf-Datei-Vorlage, die neben dem Code, den sie beschreibt, in das Repository eingecheckt wird, deckt die Grundlagen ab:

docs/
  requirements.md     # REQ-IDs mit EARS-ähnlichen Akzeptanzkriterien
  design.md           # ADR-IDs, betroffene Dateien, Architekturentscheidungen
  tasks.md            # TASK-IDs zugeordnet zu einer oder mehreren REQ-IDs
  tests.md            # welche Testdateien/-funktionen welche REQ-IDs referenzieren
  traceability.md     # generierte Tabelle: REQ -> ADR -> TASK -> Dateien -> Tests -> PR

requirements.md, design.md und tasks.md werden von Menschen und Agents gemeinsam geschrieben oder bearbeitet, genau wie der spec-getriebene Entwicklungsworkflow bereits beschreibt. tests.md und traceability.md sollten generiert und nicht manuell gepflegt werden, selbst wenn der Generator ein kurzes Skript ist, das einfach nach REQ-\d+ im Testverzeichnis und den Spezifikationsdateien greppt – manuell gepflegte Trace-Tabellen sind selbst eine Form des Abweichungsrisikos, da niemand eine Tabelle unter Zeitdruck aktualisiert.

Fazit

Spec-getriebene Entwicklung ist nicht abgeschlossen, sobald Code aus einem Agenten herauskommt; sie ist erst dann nützlich, wenn Code, Tests und Spezifikationen sich über die Zeit hinweg gegenseitig ehrlich halten, durch PRs, Refaktorisierungen und Anforderungsänderungen, die Monate auseinanderliegen. Ein Nachverfolgungsmodell, das aus sechs einfachen Identifikatoren besteht, durch eine Handvoll CI-Prüfungen durchgesetzt wird und mit einer kurzen PR-Checkliste überprüft wird, bringt Ihnen den größten Teil des Nutzens ohne den Overhead eines vollständigen Compliance-Frameworks. Beginnen Sie mit der minimalen Vorlage, schließen Sie zuerst die kostengünstigste CI-Prüfung an – Anforderungs-IDs in PR-Beschreibungen – und fügen Sie die Trace-Tabelle und Warnungen für veraltete Spezifikationen hinzu, sobald diese Routine sitzt.

Nachverfolgbarkeit ist ein Teil einer größeren Test- und Dokumentationsdisziplin, die im Cluster App Architecture in Production behandelt wird, und sie steht neben den Werkzeugfragen, die im Cluster AI Developer Tools für Teams erkundet werden, die entscheiden, welche Agent-Workflows sie standardisieren möchten.

Abonnieren

Neue Beiträge zu Systemen, Infrastruktur und KI-Engineering.