Wer schreibt hier eigentlich noch?
Es gibt diesen Moment, der noch vor drei Jahren nach Science-Fiction geklungen hätte und heute Alltag ist: Man tippt eine Beschreibung – „ein Endpoint, der eine Bestellung entgegennimmt, den Warenkorb gegen den Lagerbestand prüft, bei Unterdeckung mit einer klaren Fehlermeldung ablehnt und sonst eine Reservierung anlegt" – und Minuten später läuft Code, der genau das tut. Kompiliert, getestet, deploybar.
Wenn man kurz innehält und fragt, was man in diesen Minuten eigentlich produziert hat, kommt eine unbequeme Antwort. Nicht den Code – den hat das Modell getippt, und man könnte ihn morgen aus derselben Beschreibung neu erzeugen. Produziert hat man die Beschreibung. Die Präzision, mit der man Absicht, Bedingungen und Verhalten festgelegt hat, war die eigentliche Arbeit. Der Code war die Folge davon.
Das ist keine Spielerei am Rand, sondern eine Verschiebung im Fundament. Über Jahrzehnte war der Quellcode das Ding, das zählte – das, was man verfasste, versionierte, pflegte und verteidigte. Die Spezifikation, sofern es sie überhaupt gab, war Beiwerk. Diese Rangordnung kippt gerade. Das dauerhafte Artefakt wandert stromaufwärts, zur Spec. Der Code wird zu etwas, das man aus ihr ableitet – näher an einer kompilierten Ausgabe als an einer Handschrift.
Die Umkehrung
Die alte Ordnung hatte ein eisernes Gesetz, und jeder erfahrene Entwickler kennt es: Der Code ist die einzige akkurate Dokumentation. Alles andere lügt. Das Design-Doc beschreibt ein System, das so nie gebaut wurde. Das Wiki ist zwei Jahre alt. Der Kommentar über der Funktion beschreibt, was sie einmal tun sollte, nicht, was sie heute tut. Nur der Code lügt nie, weil der Code das ist, was tatsächlich läuft. Wer wissen wollte, wie das System sich verhält, las den Code – nicht die Spec.
Diese Wahrheit war unangenehm, aber richtig, und sie hatte eine klare Konsequenz: Specs verrotten, Code lebt. Also investierte man in Code und ließ Specs verwahrlosen. Warum ein Dokument pflegen, das schon veraltet ist, während man es tippt?
KI dreht diese Logik um. Wenn das Modell aus einer präzisen Beschreibung verlässlich den passenden Code erzeugt, ist plötzlich die Spec das, was Wirkung entfaltet, und der Code das, was folgt. Eine gute Spec erzeugt guten Code. Und – das ist die scharfe Kante – eine vage Spec erzeugt plausibel-falschen Code. Das Modell füllt jede Lücke, die man offenlässt, mit einer Annahme. Es fragt nicht nach, es rät, und es rät souverän. Man wollte, dass doppelte Einreichungen idempotent behandelt werden – hat es aber nicht hingeschrieben? Dann bekommt man eine Implementierung, die bei der zweiten identischen Anfrage fröhlich eine zweite Bestellung anlegt. Der Code sieht tadellos aus. Er tut nur nicht, was man meinte.
Damit verschiebt sich der Engpass. Nicht mehr das Tippen des Codes ist der teure Schritt, sondern das präzise Formulieren dessen, was der Code können soll. Genau das nennt man inzwischen spec-driven oder intent-driven Development: Man verfasst nicht die Lösung, man verfasst die Absicht so scharf, dass die Lösung daraus zwingend folgt. Die Vagheit, die man früher im Kopf mit sich trug und beim Tippen unbewusst auflöste, muss jetzt raus – auf Papier, ins Repo, in Worte. Denn das Modell teilt den Kopf nicht.
Was in einer guten Spec steht
Wenn die Spec das primäre Artefakt wird, lohnt die Frage, woraus sie eigentlich besteht. Und die Antwort ist erhellend, weil sie fast exakt das ist, was ein Modell nicht erraten kann. Eine gute Spezifikation ist kein Roman und keine 40-seitige Zeremonie. Sie ist ein knapper, dichter Satz von Festlegungen:
- Absicht. Welches Problem löst das hier, für wen, und woran erkennt man, dass es gelöst ist? Nicht „ein Rabattsystem", sondern „Bestandskunden sollen im Warenkorb einen Prozentnachlass sehen, der sich aus ihrem Vorjahresumsatz ergibt". Ohne Absicht baut das Modell etwas plausibel Aussehendes am Ziel vorbei.
- Invarianten. Was muss immer gelten, egal was passiert? Ein Konto geht nie ins Minus. Eine Bestellsumme ist nie negativ. Zwei Nutzer bekommen nie dieselbe Reservierung. Das sind die Sätze, die ein Modell nicht ableiten kann, weil sie aus dem Geschäft kommen, nicht aus dem Code.
- Edge Cases. Die leere Liste, der gleichzeitige Zugriff, die Zeitzone an der Tagesgrenze, der Betrag null, das abgelaufene Token. Genau die Fälle, die im Glückspfad nie auftauchen – und die das Modell überspringt, wenn man sie nicht benennt.
- Nicht-Ziele. Der am meisten unterschätzte Teil. Was soll das hier ausdrücklich nicht tun? „Keine Teilrückerstattungen in Version eins." „Wir behandeln keine Fremdwährungen." Ein Nicht-Ziel spart mehr Code, als jede Feature-Beschreibung erzeugt, weil es das Modell davon abhält, Umfang zu erfinden, den niemand bestellt hat.
- Akzeptanzkriterien. Die überprüfbaren Aussagen, an denen „fertig" hängt. „Bei Bestand null wird mit HTTP 409 abgelehnt." „Zwei identische Requests innerhalb von zehn Sekunden erzeugen genau eine Bestellung." Das Schöne daran: Diese Kriterien sind fast schon Tests. Ein Akzeptanzkriterium sauber formuliert ist ein Testfall im Wartezustand – und Akzeptanzkriterien-als-Tests schließen den Kreis, weil sie sowohl das Modell steuern als auch nachträglich beweisen, dass es traf, was gemeint war.
Man erkennt das Muster: Jeder dieser Punkte ist Kontext, den das Modell aus der Aufgabe allein nicht herleiten kann. Die Syntax kann es. Die Struktur kann es. Was es nicht hat, ist die Vorstellung davon, was in diesem Geschäft, mit diesen Daten, unter diesen Regeln wahr sein muss. Genau das schreibt die Spec auf – und nur das muss sie aufschreiben.
Die Spec als lebendes Artefakt
Damit wird eine Konsequenz unausweichlich, die viele Teams noch nicht gezogen haben: Wenn die Spec das ist, was den Code erzeugt, dann gehört die Spec ins Repo. Nicht in ein Confluence, das niemand öffnet. Nicht in ein Google Doc, das ein Ex-Kollege besitzt. Neben den Code, unter Versionskontrolle, mit Historie, in Pull Requests reviewt wie Code.
Das ist die eigentliche Auflösung des alten „der Code ist die einzige Wahrheit"-Problems – nicht durch Widerlegung, sondern durch Umkehrung. Früher verrottete die Spec, weil sie dem Code hinterherlief; man änderte den Code und vergaß das Dokument. Jetzt läuft der Code der Spec hinterher: Man ändert die Spec und leitet den Code daraus neu ab. Die Spec kann gar nicht mehr veralten, wenn sie die Quelle ist, aus der die aktuelle Version entsteht. Das Verrottungsproblem kehrt seine Richtung um.
Praktisch sieht man das schon überall in Frühform. Die README- oder AGENTS-Datei, die ein Coding-Agent als Erstes liest, bevor er eine Zeile anfasst, ist eine Spec – eine, die dem Modell sagt, wie dieses Projekt tickt. Das Design-Doc, aus dem sich Gerüste, Modultrennung und Schnittstellen generieren lassen, ist eine Spec. Die Sammlung von Akzeptanzkriterien, die zugleich die Test-Suite speist, ist eine Spec. Diese Dateien sind keine Doku über das System mehr. Sie sind der Eingang in das System – das, was man ändert, wenn man das Verhalten ändern will.
Und weil sie das sind, verdienen sie die Behandlung, die man früher dem Code vorbehielt: Reviews, in denen jemand die Absicht anzweifelt, bevor eine Zeile generiert wird. Diffs, an denen man sieht, wie sich eine Invariante geändert hat. Blame, das zeigt, wer wann festgelegt hat, dass Fremdwährungen ausgeschlossen sind. Das ist der Punkt, an dem aus „wir haben mal was aufgeschrieben" ein gepflegtes, verantwortetes Artefakt wird.
Neu generieren statt flicken
Hier wird die Verschiebung wirklich radikal, denn sie ändert, wie man mit Fehlern umgeht. In der alten Welt war Code kostbar, weil ein Mensch ihn Zeile für Zeile geschrieben hatte. Ihn wegzuwerfen und neu zu schreiben, fühlte sich an wie Geldverbrennen – also flickte man. Man patchte den Bug, fügte eine Sonderbehandlung ein, klebte einen Workaround über die schiefe Annahme. Über Jahre wuchs so eine Geologie aus Flicken, in der niemand mehr die ursprüngliche Absicht fand.
Wenn Code aus einer Spec in Minuten entsteht, verschiebt sich die Rechnung. Bei einem echten Fehler ist die erste Frage nicht mehr „wo flicke ich?", sondern „liegt der Fehler im Code oder in der Spec?". Und oft liegt er in der Spec: Man hat den Edge Case nie benannt, die Invariante nie festgehalten, das Nicht-Ziel nie gezogen. Dann ist der billigste Weg nicht, den generierten Code zu operieren, sondern die Spec zu schärfen und den betroffenen Teil neu abzuleiten. Man behebt die Absicht, nicht die Ausgabe.
Das ist mehr als eine Bequemlichkeit, es ist ein anderes Kostenmodell. Ein Workaround, der einen Entwickler einen halben Tag kostet – sagen wir grob ein paar Hundert €, wenn man ehrlich rechnet – produziert Code, den beim nächsten Mal wieder jemand verstehen muss. Eine geschärfte Spec kostet dieselbe halbe Stunde Denken, erzeugt sauberen Code und verbessert das Artefakt, aus dem alle Zukunft entsteht. Der Flicken zahlt einmal; die bessere Spec zahlt jedes Mal.
Das gilt nicht absolut – dazu gleich mehr. Ein isolierter Ein-Zeilen-Fix ist ein isolierter Ein-Zeilen-Fix, und ihn über eine Spec-Runde zu schicken wäre Zeremonie. Aber als Grundhaltung stimmt es: Wenn der Code halb wegwerfbar ist, weil er billig neu entsteht, dann repariert man nicht mehr die Kopie, sondern das Original.
Die Disziplin, die der Mensch mitbringen muss
Nun der Haken, und er ist groß. Diese ganze Umkehrung verlangt vom Menschen genau das, was Menschen am wenigsten gern tun: vorher klar denken.
Code zu tippen war lange auch eine Form, sich vor dem Nachdenken zu drücken. Man fing an, spürte beim Schreiben, wo es hakte, entdeckte den Edge Case, weil der Compiler meckerte, verstand das Problem durch das Bauen. Das Tippen war ein Denkwerkzeug – langsam, aber nachsichtig. Man durfte unklar anfangen und unterwegs klar werden.
Spec-driven Development nimmt diese Nachsicht weg. Eine Spec zu schreiben heißt, die Vagheit vorne aufzulösen, bevor eine Zeile existiert. Man muss die Absicht kennen, ehe man sie tippt. Man muss die Invarianten benennen, ehe irgendetwas sie verletzen kann. Man muss die Nicht-Ziele ziehen, ehe man in Versuchung gerät, Umfang zu erfinden. Das ist schwerer als Programmieren, nicht leichter, weil es die eine Arbeit einfordert, die kein Werkzeug abnimmt: zu wissen, was man eigentlich will, und es präzise zu sagen.
Genau daran scheitern schlechte Specs, und sie scheitern auf die teuerste Weise. Denn – und das ist der ehrliche Nachtrag – eine Spec kann so falsch sein wie Code. Eine präzise formulierte, sauber reviewte, im Repo versionierte Spezifikation, die auf einer falschen Annahme über das Geschäft beruht, erzeugt zuverlässig und in großem Maßstab das Falsche. Präzision ist nicht Richtigkeit. Man kann sich mit voller Sorgfalt in die falsche Richtung festlegen. Die Spec verschiebt den Denkaufwand nach vorne; sie schafft ihn nicht ab.
Nicht alles verdient eine Spec
Und damit zur ehrlichen Gegenseite, denn wer diese Lehre zu weit zieht, ersetzt eine Form von Verschwendung durch eine andere. Nicht alles verdient eine formale Spezifikation, und Spec-first als Dogma wird zu genau der Bürokratie, gegen die gute Ingenieure zu Recht allergisch sind.
Das Wegwerf-Skript, das einmal eine CSV in ein anderes Format schaufelt, braucht keine Absichtserklärung mit Invarianten und Nicht-Zielen. Man will es in fünf Minuten haben und danach nie wieder sehen. Es ihm eine Spec voranzustellen, wäre so absurd, wie für einen Einkaufszettel ein Anforderungsdokument zu schreiben.
Ernster ist der zweite Fall: exploratives Arbeiten. Manchmal weiß man schlicht noch nicht, was man will – und der ehrlichste Weg, es herauszufinden, ist nicht, an einer leeren Spec zu grübeln, sondern den Agenten eine grobe, halbgare Version bauen zu lassen und darauf zu reagieren. Man sieht die laufende Sache, spürt, was falsch ist, und dann verdichtet sich die Absicht. In diesem Modus entsteht die Spec aus dem Prototyp, nicht umgekehrt. Vorne auf Klarheit zu bestehen, die man noch gar nicht haben kann, ist keine Disziplin, sondern Selbsttäuschung.
Die Auflösung ist dieselbe wie bei jedem guten Engineering-Prinzip: Zeremonie an den Sprengradius anpassen. Was passiert im schlimmsten Fall, wenn das hier falsch ist? Berührt es Geld, Kundendaten, Authentifizierung, etwas Unumkehrbares, etwas, das lange lebt und wächst – dann verdient die Absicht eine echte, versionierte, reviewte Spec, und der Aufwand zahlt sich vielfach zurück. Ist es ein Nachmittags-Experiment oder ein Skript, das nach einmaligem Lauf stirbt – dann ist Spec-first Ballast. Spec-driven Development ist ein Werkzeug, keine Religion. Der Fehler ist nicht, ohne Spec zu bauen; der Fehler ist, das teure, langlebige, gefährliche Ding ohne Spec zu bauen und das billige, tote Skript mit einer.
Fazit
Jahrzehntelang war der Quellcode das Ding, das zählte – das dauerhafte Artefakt, an dem man die Wahrheit über ein System ablas, weil alles andere log. Diese Ära endet nicht dramatisch, sondern leise: Sobald ein Modell aus einer präzisen Beschreibung verlässlich Code erzeugt, wandert das, was man tatsächlich verfasst und pflegt, eine Ebene höher – zur Spezifikation. Der Code wird zur Ausgabe. Die Absicht wird zur Quelle.
Das ist keine Erleichterung, sondern eine Verlagerung der Anstrengung. Die schwere Arbeit verschwindet nicht, sie zieht nach vorne: klar denken, bevor gebaut wird; Absicht, Invarianten, Ränder und Nicht-Ziele so scharf benennen, dass ein Modell nichts Falsches erraten muss; und dann das Artefakt pflegen, aus dem der Code immer wieder neu entsteht. Wer diese Arbeit meidet, bekommt plausibel-falschen Code in großem Maßstab – schneller als je zuvor.
Genau deshalb behandeln wir bei NH Labs die Spec als primäres Artefakt für alles, was zählt. Für das Wegwerf-Skript nicht, und das ist Absicht. Aber für das System, das Geld bewegt, Kundendaten hält und über Jahre wächst, verfassen und versionieren wir die Absicht selbst – im Repo, reviewt, verantwortet – nicht nur den Code, der aus ihr folgt. So ist am Ende nicht bloß nachvollziehbar, was das System tut, sondern belegt und verantwortet, was es tun sollte. Der Code kann neu entstehen. Die Absicht muss bleiben.