Warum Windsurf Code Bugs durchs Review rutschen

Ein Review durch Menschen skaliert mit der Zahl der Zeilen, die eine Person im Kopf behalten kann. Eine breite, mechanische Änderung hebelt es auf eine ganz bestimmte Weise aus: Jeder Hunk ist für sich genommen plausibel, also lässt die Aufmerksamkeit nach. Die zwölfte Datei geben Sie mit weniger Sorgfalt frei als die erste – und der Defekt sitzt fast immer am Ende.

Der Defekt steckt außerdem selten in dem, was geändert wurde. Er steckt in dem, was nicht geändert wurde: eine Umbenennung, die eine Aufrufstelle übersehen hat; ein neues Pflichtfeld, das drei Konstruktoren nicht übergeben; ein Handler, der überall aktualisiert wurde, nur nicht im Fehlerpfad.

Die drei Muster, nach denen eine breite Änderung fehlschlägt

Unvollständige Durchläufe

  • Elf Aufrufstellen aktualisiert, eine übersehen – und die liegt auf einem Pfad, den niemand täglich durchläuft.

  • Typen fangen das oft nicht ab, weil die übersehene Stelle ohnehin lose typisiert war.

Auseinanderdriftende Annahmen

  • Zwei Dateien sind sich am Ende uneinig, was ein Wert bedeutet – etwa ob ein Zeitstempel in Sekunden oder in Millisekunden vorliegt.

  • Jede Datei ist in sich konsistent, also wirkt für sich betrachtet nichts falsch.

Stille Verhaltensänderung

  • Ein Refactoring erhält die Schnittstelle und ändert im Stillen die Reihenfolge, Standardwerte oder einen Fehlerpfad.

  • Tests, die gegen die alte Implementierung geschrieben wurden, laufen weiterhin durch, weil sie die Schnittstelle prüfen.

Alle drei haben eines gemeinsam: Sie finden diese Fehler, indem Sie die Anwendung benutzen, nicht indem Sie den Code lesen. Genau das macht sie teuer.

Prüfen Sie das Verhalten, nicht den Diff

Bei einer breiten Änderung lautet die nützliche Frage nicht „Ist jede einzelne Bearbeitung korrekt?", sondern „Tut das Produkt noch, was es vorher tat – plus das Neue?". Das ist eine Frage nach dem Verhalten, und beantwortet wird sie, indem Sie die ausgelieferte Anwendung durch die Abläufe führen, die die Änderung plausibel berührt haben könnte.

Die Abdeckung muss nicht vollständig sein, um zu nützen. Bei einer Änderung, die ein Feld über den gesamten Checkout-Pfad umbenennt, reicht es, den Checkout einmal von Anfang bis Ende durchzuspielen – das ist mehr wert, als zwölf Diffs sorgfältig zu lesen.

Installieren Sie den Verifizierungs-Skill in den Editor, damit der Agent diese Prüfung selbst ausführen kann, statt auf Sie zu warten.

Terminal

npm install -g @testsprite/testsprite-cli
testsprite setup

Das Dashboard übernimmt dasselbe Setup, wenn Sie lieber nichts installieren möchten. Der übrige Funktionsumfang der CLI findet sich im CLI-Repository.

Geben Sie dem Agenten den Fehler, nicht Ihre Zusammenfassung

Wenn doch etwas kaputtgeht, schließt sich die Fix-Schleife nur, wenn die Belege brauchbar sind: was versucht wurde, was die Anwendung getan hat und wo beides auseinanderging. Damit ausgestattet, geht der Agent mit einem konkreten Ziel zurück in dieselben zwölf Dateien. Mit einem Screenshot ausgestattet, rät er – und Sie beschreiben wieder alles selbst.

Einen breiten Diff lesen, ohne sich etwas vorzumachen

Es gibt eine ehrliche Variante, eine Änderung über zwölf Dateien zu reviewen, und sie besteht nicht darin, jeden Hunk zu lesen. Sie besteht darin, vor dem Öffnen des Diffs festzulegen, was zutreffen müsste, damit diese Änderung korrekt ist – und dann nur das zu prüfen.

Bei einer Umbenennung ist das die Frage, ob jede Aufrufstelle mitgezogen wurde, was der Compiler weitgehend beantwortet, und ob irgendwo der Name dynamisch zusammengebaut wird, was er nicht beantwortet. Bei einem neuen Pflichtfeld ist es jeder Pfad, der das Objekt erzeugt, einschließlich Tests und Fixtures, die stillschweigend weiter eine unvollständige Version übergeben. Bei einem Refactoring, das eine Schnittstelle erhält, sind es die Reihenfolge und die Fehlerpfade, denn genau die ändern Refactorings im Stillen.

Drei Fragen pro Änderung sind mehr wert als das Überfliegen von vierhundert Zeilen – und am Ende haben Sie die ehrliche Liste dessen, was sich nur durch Ausführen der Anwendung prüfen lässt.

Wählen Sie die Abläufe nach Wirkungsradius aus, nicht nach Wichtigkeit

Instinktiv deckt man das wichtigste Feature ab. Bei einer breiten Änderung ist die bessere Frage, welche Abläufe die Änderung plausibel berührt haben könnte – geordnet danach, wie unbemerkt sie ausfallen würden.

Ein Zahlungsablauf ist wichtig, und er wird auch beobachtet. Wenn er ausfällt, erfahren Sie es innerhalb einer Stunde. Gefährlich sind die Abläufe, die zwar zählen, aber wöchentlich statt stündlich genutzt werden: ein Export, eine Einladung, eine Einstellungsseite, eine geplante Zusammenfassung. Dort sitzt ein unvollständiger Durchlauf einen Monat lang ungestört.

Nehmen Sie sich nach einer breiten Änderung deshalb zuerst die stillen Pfade vor. Sie sind günstig abzudecken – und niemand sonst prüft sie.

Bei jedem Pull Request ausführen

Breite Änderungen sind genau die, die man schnell mergen möchte, weil der Diff langweilig ist. Das ist das Argument dafür, die Prüfung zu automatisieren, statt an sie zu denken.

Zwei Wege, und die Wahl hängt im Kern davon ab, wem die Pipeline gehört. Die Anbindung der GitHub App über das Dashboard erfordert überhaupt keine Änderung an Ihrem Repository, weil sie auf das Deployment reagiert, das Ihr Build ohnehin erzeugt. Ein Schritt mit GitHub Actions legt die Prüfung dagegen ins Repository, wo sie wie der Rest des Builds im Review landet.

Eine breite Änderung prüfen, ohne sie zu lesen

TestSprite beantwortet die Frage, die ein breiter Diff nicht beantworten kann: Tut das Produkt noch, was es vorher tat, plus das Neue? TestSprite öffnet die ausgelieferte Anwendung, arbeitet die Abläufe durch, die die Änderung plausibel berührt haben könnte, und meldet Verhalten statt Struktur.

Das passt genau zu diesem Problem. Unvollständige Durchläufe, auseinanderdriftende Annahmen und stille Verhaltensänderungen sind im Quellcode unsichtbar und in der Benutzung offensichtlich. Die Abdeckung wird aus Ihrem Produkt generiert statt von Hand geschrieben – die stillen Abläufe, der Export, die Einladung und die Einstellungsseite, sind also enthalten, ohne dass jemand an sie denken muss.

Wenn doch etwas kaputtgeht, kommt der Fehler als ein Paket zurück, mit dem Ihr Agent arbeiten kann. Darauf kommt es hier am meisten an: Ihn auf die konkrete Abweichung zu stoßen, ist besser, als ihn zwölf Dateien erneut durchsehen zu lassen.

Warum fangen Typen das nicht ab?

Typen fangen einen guten Teil der unvollständigen Durchläufe ab, aber so gut wie nichts von auseinanderdriftenden Annahmen oder stillen Verhaltensänderungen, denn beide sind konstruktionsbedingt typkorrekt.

Sollte ich einfach kleinere Änderungen anfordern?

Das hilft, und es verschenkt zugleich einen Großteil des Grunds, überhaupt einen agentischen Editor zu nutzen. Ein Verifizierungsschritt lässt Ihnen die Breite und sagt Ihnen trotzdem, ob das Ergebnis funktioniert.

Funktioniert das auch, wenn die Änderung nur das Backend betrifft?

Ja, über Abdeckung auf API-Ebene statt über die Oberfläche. Das Prinzip bleibt gleich: das Verhalten ausführen, statt die Änderung zu lesen.

Wie lange dauert eine solche Prüfung?

Lange genug, dass Sie sie nicht bei jedem Tastendruck laufen lassen würden, kurz genug, um in einen Pull Request zu passen. Genau dort gehört sie hin.

Was ist, wenn der Agent die Unit-Tests bereits ausgeführt hat?

Nützlich, aber Unit-Tests wurden meist gegen genau die Annahmen geschrieben, die die Änderung soeben verändert hat. Sie bestätigen interne Konsistenz, nicht externe Korrektheit.

Kurz gefasst

Bei zwölf Dateien ist das Lesen des Diffs keine Prüfung.

Windsurf Code Bugs verstecken sich in unvollständigen Durchläufen, auseinanderdriftenden Annahmen und stillen Verhaltensänderungen. Prüfen Sie das laufende Produkt statt des Diffs, geben Sie Fehler als Belege zurück und lassen Sie die Prüfung bei jedem Pull Request laufen.