Free

3.000 Zeilen in einem Commit: warum komplexe Features zuerst plan mode brauchen

Der Instinkt bei komplexen Features ist "lass mich einfach was probieren" — aber architektonische Entscheidungen verstecken sich im 3. Modell, im 5. Edge Case. Der eigentliche Wert von Plan Mode liegt darin, das architektonische Gespräch vor dem Code auf die Textebene zu verlagern. Realer Fall: Pickfuls Community-Jury-System — 3.000 Zeilen, 119 Specs grün, ein Commit, danach null Architekturumbau.


Vor einem komplexen Feature ist der Instinkt der meisten Leute „lass mich einfach was probieren".

Das Problem: Komplexe Systeme haben eine Eigenheit — architektonische Entscheidungen verstecken sich im 3. Modell, im 5. Edge Case, in der 8. Punkteregel. Kopfüber in den Code springen und mittendrin auf diese Entscheidungen stoßen, dann zurückrudern und ändern — das kostet 10× mehr, als sie zu Beginn in Textform auszudiskutieren.

Ich habe den Plan Mode von Claude Code genutzt, um TopicReview zu bauen — das Community-Jury-System in Pickful — und sah die Extremversion dieser Ungleichung: ein Commit, 3.032 Zeilen, 119 Specs grün, in einem Rutsch ausgeliefert. Keiner der über ein Dutzend Commits, die folgten, war ein architektonischer Umbau — alle sind Parameter-Tuning, UI-Feinschliff, Edge-Case-Pflaster. Das System läuft seither stabil und ist heute zentral dafür, wie sich die Community selbst moderiert.

Dieser Beitrag geht darauf ein, warum komplexe Features zuerst Plan Mode brauchen, was die Plan-Phase wirklich tut und wann die Unterhaltung reif genug ist, um mit dem Code zu beginnen.

Wie komplex das System ist

TopicReview ist eine Community-Abstimmung darüber, ob ein qualitativ minderwertiger Post entfernt wird. Ein Satz reicht für die Erklärung — aber die Spezifikation faltet sich in Schichten auf:

  • 5 Zustände: open → voting → decided → appealed → closed
  • 3 Urteile: remove / warn / keep
  • 2 Phasen: Erstverfahren durch 12 Geschworene; Berufung durch 5 Richter (aus den Top-20-Usern nach Punkten ausgelost)
  • Mehrdimensionaler Punktefluss: 10 pt vorläufige Strafe, 10 pt Berufungs-Stake, +5 für Geschworene, die mit dem Urteil gestimmt haben, +10 für Richter, die mit dem Urteil gestimmt haben, +3 für Melder, deren Meldung bestätigt wurde, Erstattung bei gewonnener Berufung = Stake + Bonus + vorläufige Strafe
  • 4 Arten von geplanten Jobs: 24-h-Fenster für Erstabstimmung, 24-h-Berufungsfenster, 24-h-Berufungsprüfungsfenster und — Geschworenenpunkte nach einem Remove-Urteil 24 h aufgeschoben (weil eine Berufung es kippen könnte)
  • Parallele Flüsse + Rollback: Wenn Stimmen während der vorläufigen Entfernung kippen, muss der Post wiederhergestellt und die vorläufige Strafe erstattet werden; wenn die Berufung das Urteil kippt, wird der Stake plus Bonus zurückerstattet, evtl. zusammen mit der vorläufigen Strafe, und Geschworene werden nach dem neuen Urteil neu bewertet

Der Kern der Komplexität liegt in keiner einzelnen Regel — er liegt in der Art, wie die Regeln miteinander interagieren. Jede zusätzliche Regel kann anderswo ein Rollback auslösen.

Wände, gegen die du ohne Plan knallst

Wenn du durchgehend schreibst, sind die schwersten Probleme nicht die sichtbaren Fakten — es sind die Fragen, die du nicht auf die Idee gekommen bist zu stellen. Liest man den TopicReview-Code rückwärts, gibt es mindestens vier Wände, gegen die du ohne Plan unweigerlich rennst:

Zulassungsregeln für Geschworene. Sieht aus wie bloß User.jurors_and_judges.sample(12). Aber die tatsächlichen Regeln lauten: den Post-Autor ausschließen, den Melder ausschließen, jeden ausschließen, der in der Erstrunde bereits abgestimmt hat (damit er nicht auch in der Berufung abstimmt). Drei gestapelte Ausschlüsse. Schreibst du das Modell in einem Rutsch, fällt dir einer oder zwei weg.

Aufgeschobene Punktausschüttung. Ein Remove-Urteil würde normalerweise die Geschworenenauszahlung auslösen. Aber eine Berufung kann ein Remove kippen — und wenn sie es tut, stehen die Geschworenen, die mit dem alten Urteil gestimmt haben, plötzlich auf der falschen Seite, und die Auszahlungen müssen gegen das neue Urteil neu berechnet werden. Deshalb muss das Remove-Urteil auf das Schließen des 24-Stunden-Berufungsfensters warten, bevor Geschworene bezahlt werden. Lässt du diese Regel ungeschrieben, zahlst zuerst, dann endest du damit, Punkte zurückzuholen — 10× mühsamer als spät zu zahlen.

Schnittstellen-Design des geplanten Jobs. CloseTopicReviewJob sieht aus wie „beende eine Review". In der Praxis behandelt er drei Situationen:

# Ablauf des Erstabstimmungsfensters
CloseTopicReviewJob.set(wait_until: voting_ends_at).perform_later(review.id)
# Aufgeschobene Geschworenenauszahlung nach einem Remove-Urteil
CloseTopicReviewJob.set(wait: 24.hours).perform_later(review.id, award_juror_points: true)
# Ablauf des Berufungsfensters
CloseTopicReviewJob.set(wait: 24.hours).perform_later(review.id, appeal_id: appeal.id)

Ohne vorausgehende Planung schreibst du die erste Signatur, merkst im zweiten Fall, dass die Schnittstelle sich ändern muss.

Die teuerste Wand: kann während der vorläufigen Entfernung Berufung eingelegt werden? Sobald die Remove-Stimmen die Schwelle überschreiten, wird der Post sofort ausgeblendet (vorläufig), aber die Review bleibt im Zustand voting — nicht decided. Kann der User jetzt schon Berufung einlegen?

  • Ja → die Übergänge zwischen decided und appealed müssen erweitert werden
  • Nein → UX leidet: der Post ist verborgen und der User muss 24 h warten, um protestieren zu können
  • Die tatsächliche Wahl von TopicReview: ja, Berufung während der vorläufigen Entfernung ist erlaubt — aber die Review muss zuerst finalize → decided durchlaufen, bevor Berufung eröffnet wird

Diese eine Entscheidung wirkt zurück und ändert die Parameterprüfungen in open_appeal! sowie die Logik der Zustandsmaschine. Mittendrin entscheiden = das halbe System neu schreiben.

Was die Plan-Phase tatsächlich tut

Der Plan Mode von Claude Code ist ein Modus, in dem Code schreiben nicht erlaubt ist — Claude kann das Repo lesen, Ansätze durchdenken, mit dir diskutieren, aber jede Dateimodifikation wird hart blockiert, bis du einen Plan genehmigst.

Diese mechanische Beschränkung ist der Kern: sie zwingt das architektonische Gespräch dazu, in Text stattzufinden.

Ein paar Dinge, die die Plan-Phase in der Praxis tut:

1. Zustandsmaschine und Rollen zeichnen. 5 Zustände, 4 Rollen (Geschworener / Richter / Post-Autor / Melder), was jede Rolle in jedem Zustand tun und nicht tun kann — alles in wenigen Zeilen Markdown. Wenige Zeilen vs. Dutzende Dateien. Der Änderungsaufwand liegt zwei Größenordnungen auseinander.

2. Den Ablauf jeder Rolle durchlaufen:

  • Geschworener: bekommt Benachrichtigung → öffnet Review → liest Post und Begründung → stimmt mit Reasoning ab → erhält Punkte
  • Post-Autor: bekommt Benachrichtigung → sieht Urteil → erwägt Berufung bei Remove → hinterlegt Stake → wartet
  • Richter: erhält die aus den Top-20 gezogene Berufung → stimmt ab → erhält Punkte

Wo der Gang stolpert, taucht eine versteckte Frage auf: „sehen Geschworene die Stimmen der anderen Geschworenen?", „was kann der Autor während der vorläufigen Entfernung tun?"

3. Edge Cases verhören. Die Plan-Phase entwirft nicht den „Normalpfad" — sie stellt absichtlich die Fragen, die sonst nicht auftauchen:

  • Was, wenn das Fenster mit 0 Stimmen schließt? (Endgültige Wahl: standardmäßig keep.)
  • Was, wenn die Berufung mit 0 Stimmen schließt? (dismissed; Stake verfällt.)
  • Darf ein Richter über einen Post abstimmen, den er selbst gemeldet hat? (Nein — dieselbe Ausschlussregel.)
  • Mehrere Geschworene lösen gleichzeitig finalize aus — verdoppelt der Race die Auszahlung? (Ein juror_points_awarded-Feld für Idempotenz hinzufügen.)

95 % dieser Fragen tauchen beim Schreiben von Code nicht natürlich auf. Die Plan-Phase zwingt dich, sie eine nach der anderen anzugehen.

4. Das Punkte-Hauptbuch. Das Punktesystem ist zu komplex, als dass Diskussion reichen würde — man muss die Tabelle tatsächlich zeichnen: jeder Punktefluss mit seinem Auslöser, seinem Betrag und seinem Rollback-Pfad. Stimmt das Hauptbuch, versöhnen sich alle Edge Cases (vorläufige Rückerstattung, Berufungserstattung, Boni) rechnerisch.

Wie tief muss das Gespräch sein, bevor man mit dem Code beginnt

Ein harter Maßstab:

  • Du kannst jeden Pfad ohne Stocken durchgehen — jede Kombination vom Öffnen der Review bis zu closed (keep / remove / warn × mit/ohne Berufung × vorläufig/nicht vorläufig) — du erzählst sie von Anfang bis Ende
  • Jeder Edge Case hat ein definiertes Verhalten — nicht „schauen wir später", sondern „0 Stimmen default keep", „vorläufig erlaubt Berufung, muss aber zuerst finalize"
  • Kein „ach, das habe ich noch nicht durchdacht" — jede Frage, die du stellen kannst, hat bereits eine Antwort

Bei Erreichen dieses Niveaus wird Code schreiben zu: den Plan nach Ruby übersetzen.

Wie die Durchschreib-Phase aussieht

Die erste Auslieferung des Systems:

d162f1e Add community moderation system with jury/judge review and appeals
  63 files changed, 3032 insertions(+)
  119 specs, 0 failures

63 Dateien, 3.032 Zeilen, 119 Specs grün. In einem Rutsch ausgeliefert.

Die zehn-plus folgenden Commits bestätigen, dass die Architektur hielt:

Apply legacy penalty (1pt) for posts created before 2026-03-26
Fix topic review appeal bugs: window mismatch and verdict not updated
Add topic_removed status for posts removed by community review
Default to keep verdict when review expires with zero votes
Reduce provisional removal penalty to 1pt during trial period
Allow topic creator to withdraw active reviews
Add handled tab to jury dashboard, fix tabs styling

Jeder ist Tuning / Fix / Feinschliff / kleines Feature. Keiner ist „zurückgehen und die Zustandsmaschine neu entwerfen" oder „das Punktemodell muss geändert werden". Das Skelett saß komplett richtig.

Das ist die wahre Belohnung des Plans: Die Ausführung bleibt ununterbrochen. Kein „warte, wie läuft dieser Pfad" — der Plan hat es abgedeckt. Kein „an diesen Edge Case hatte ich nicht gedacht" — die Plan-Phase hat gefragt. Kein „diese Schnittstelle muss neu entworfen werden" — der Plan hat es schon sortiert.

Stunden Code schreiben, dabei nur eine Sache tun: ein klares Design auf die Tastatur übertragen.

Wann man Plan nicht nutzen sollte

Nicht jede Aufgabe verdient einen Plan:

  • Einfache Bugfixes — lokalisieren + beheben + Regressionstest hinzufügen; keine Vorabdiskussion nötig
  • Mechanisches Refactoring — umbenennen, extrahieren, verschieben; der Pfad ist eindeutig, Plan ist ein überflüssiger Schritt
  • Nur ein offensichtlicher Weg — einen GET-Endpunkt hinzufügen, ein UI-Toggle; nichts zu debattieren
  • Explorative Prototypen — du weißt selbst noch nicht, was du willst; etwas Grobes zum Laufen zu bringen schlägt weiteres Nachdenken

Der Gewinn von Plan Mode entsteht durch das Senken von Neuschreibkosten. Wenn die Aufgabe kein Neuschreibrisiko hat, ist Plan nur Overhead.

Zum Abschluss

„Erst denken, dann handeln" klingt wie ein Charakterratschlag. Plan Mode ist das nicht.

Plan Mode heißt, das Gespräch auf Architekturebene dort stattfinden zu lassen, wo 10 Wörter es ändern können — nicht dort, wo 30 Dateien geändert werden müssen.

Unter Komplexität muss dieses alte Sprichwort der Branche „words are cheap, code is expensive" umgedreht werden — es heißt nicht „schreib erst Code und schau dann" (das gilt nur, wenn die Kostenlücke klein ist), es heißt die Kostenlücke nutzen: das teure Gespräch nach vorn holen, in das billige Medium.

3.000 Zeilen in einem Commit fühlt sich großartig an. Nicht weil ich schnell schreibe — sondern weil der Plan „Schreiben" in einen rein mechanischen Akt verwandelte.