Root Cause First
Effort: free — pure Untersuchungs-Disziplin, die die Kosten meist unterm Strich senkt: Eine entscheidende Probe ersetzt das Abfeuern der ganzen Pipeline, nur um zu sehen, was passiert. Beseitigt: Pflaster auf der falschen Stelle — den Symptom-Fix, der den echten Bug versteckt und einen nachgelagerten Konsumenten bricht.
Keine Fixes ohne Untersuchung. Ein Pflaster, geklebt bevor du das Versagen
verstehst, fixt das Falsche, versteckt den echten Bug und bricht etwas
weiter unten. Dein Produkt ist kein Patch — es ist eine Grundursache, bewiesen
durch eine entscheidende Probe, und ein Fix, bewiesen frei von Regressionen.
Zwei Gesetze regieren alles hier drunter:
- Keine Annahmen — der Code, die Daten und das Live-System sind die
Wahrheit; Notizen sind nur Hinweise. Ein Kommentar, eine Erinnerung, ein
früherer Schluss, selbst dein eigener letzter Satz ist eine Hypothese, bis
eine Probe sie bestätigt. Die Wörter „alle / jeder / keiner“ lösen einen
Drei-Punkt-Check aus: die Umgebung, eine repo-weite Suche und ein Scan über
jeden Aufrufer.
- Ein verifiziertes Gegenbeispiel killt den früheren Schluss sofort. Wenn
eine Probe widerlegt, was du geglaubt hast, sag klar „Ich lag falsch — es
ist in Wirklichkeit X" und mach vom neuen Fakt aus weiter. Nie drüber
tapezieren.
Die Schleife (in dieser Reihenfolge; nichts überspringen)
- Lies den Fehler. Benenn das Symptom in einem präzisen Satz. Lies die
echte Meldung, nicht das, was du erwartest. Benenn den Explosionsradius:
was hängt an dem Ding, das du verdächtigst?
- Reproduzier. Bring das Versagen auf Kommando — live, oder in einem
fehlschlagenden Test. Stopp die Zeit. Ein „Versagen“, das in
Millisekunden zurückkommt, wo echte Arbeit Sekunden braucht, ist eine früh
geschluckte Exception, kein echtes Arbeits-Versagen. Die Zeitlücke ist
selbst ein Hinweis.
- Prüf jüngste Änderungen. Diffe, was sich geändert hat, seit es zuletzt
lief — Code, Config, Umgebung, Abhängigkeiten. Ist die Historie lang,
bisektier sie.
- Kartier die Konsumenten. Bei einem Bug in einer geteilten Fläche: list
jeden Aufrufer und wie er sie nutzt (exakter String-Match? Boolean? Liste?).
Die echte Regression versteckt sich meist in einem nachgelagerten
Exakt-Match-Vergleich, nicht in dem Regler, an dem du drehst.
- Instrumentier die Grenzen. Logge oder probe an jeder Komponenten-Naht —
was rein geht, was raus kommt. Verfolg die schlechten Daten rückwärts,
Grenze für Grenze, bis du an der Quelle bist. Fix die Quelle, nie das
Symptom.
- Grundursache per Hypothese. Bild eine falsifizierbare Hypothese. Find
die EINE entscheidende Probe, die sie von den Alternativen trennt, und fahr
nur die. Feuer nicht die ganze Pipeline ab, „um zu sehen, was passiert“.
- Fix chirurgisch, an der richtigen Naht. Die kleinste Änderung, die die
Grundursache auflöst. Bevorzug die eine geteilte Quelle (ein Normalizer,
ein Runner) statt N Aufrufstellen zu editieren. Wo möglich, mach den Fix
inert auf dem funktionierenden Pfad — er ändert dort beweisbar nichts und
greift nur auf dem kaputten. Keine Nachbar-Refactors als Beifahrer.
- Beweis es. Schreib den fehlschlagenden Test, der den Bug reproduziert;
sieh ihn rot werden; fix; sieh ihn grün werden. Dann fahr die Tests für
jeden Konsumenten-Pfad aus Schritt 4 — grün dort ist dein
Null-Regressions-Boden. Eine Suite, die genau die Naht mockt, die versagt
hat, beweist nichts.
- Verifizier live. Fahr das echte System — echte Requests, echte
Datenbank, echte Logs. Nie ein Beiwagen-Skript, das den Code in deinen
eigenen Prozess importiert. Halt Vorher/Nachher-Beweise fest.
- Lern. Schreib das Symptom, die entscheidende Probe, die Grundursache
und das Anti-Muster auf, das sie versteckt hat — damit der nächste Bug
dieser Form billiger wird.
Bau die Reproduktions-Schleife, BEVOR du Theorien baust
Ertappst du dich beim Code-Lesen für eine Theorie, bevor ein rot-fähiges
Kommando existiert — stopp. Kein rot-fähiges Kommando, keine Theorie. Ein
enges Pass/Fail-Signal, das bei DIESEM Bug rot wird, ist der größte einzelne
Debugging-Hebel. Investier hier überproportional.
Wege, eins zu bauen, grob in dieser Reihenfolge: ein fehlschlagender Test; ein
HTTP-Skript gegen einen Dev-Server; ein CLI-Lauf mit Fixture-Eingabe, gedifft
gegen einen bekannten guten Snapshot; ein Headless-Browser-Skript; ein
mitgeschnittenes echtes Payload, isoliert durch den Codepfad zurückgespielt;
ein Wegwerf-Harness, das eine Funktion aufruft; eine Fuzz-Schleife über
Zufallseingaben; ein Bisektions-Harness, damit automatisches Bisect läuft;
eine Differential-Schleife (gleiche Eingabe durch alte und neue Version, die
Ausgaben gedifft).
Dann zieh sie fest: schneller (Setup cachen, Scope verengen), schärfer (das
konkrete Symptom asserten, nicht „ist nicht abgestürzt“), deterministisch
(Zeit pinnen, RNG seeden, Netz einfrieren). Eine deterministische
Zwei-Sekunden-Schleife ist eine Superkraft.
Bei flatterhaften Bugs jag eine höhere Reproduktionsrate, keine saubere Repro:
loope den Auslöser 100-mal, gib Stress dazu, verenge die Timing-Fenster. Ein
50%-Flake ist debugbar; ein 1%-Flake nicht.
Kriegst du wirklich keine Schleife gebaut, stopp und sag es. List auf, was du
versucht hast, und bitte deinen Menschen um Zugang, ein mitgeschnittenes
Artefakt oder temporäre Instrumentierung. Theoretisier nicht ohne Schleife.
Und existiert keine Naht, die das echte Aufrufmuster nachstellen kann, IST
dieses Fehlen ein Fund — flagg die Architektur-Lücke, nachdem der Fix
gelandet ist.
Anti-Muster (wie harte Bugs am Leben bleiben)
- Aus einer Notiz oder einem Kommentar schließen, ohne Probe.
- Fixen vor dem Reproduzieren.
- Einer grünen Suite trauen, die genau die Naht mockt, die live versagt.
- Beiwagen-Verifikation — den Code importieren, statt das Live-System zu fahren.
- Einen Config-Regler drehen, ohne die Exakt-Match-Konsumenten zu kartieren,
die er füttert.
- Breite Refactors als Beifahrer eines Fixes.
- „alle / jeder / keiner“ sagen, ohne den Drei-Punkt-Check.
Passt gut zu
Scaffold credit: Matt Pocock, diagnosing-bugs (mattpocock/skills). Komposition und harte Regeln hier sind BACKS AIOS.
1---2name: root-cause-first-23description: Bei einem harten Bug, einem stillen Versagen, einer Regressions-Jagd oder einer riskanten Änderung, die leise einen nachgelagerten Konsumenten brechen könnte. Keine Fixes ohne Untersuchung — Fehler lesen, auf Kommando reproduzieren, jüngste Änderungen prüfen, Komponenten-Grenzen instrumentieren, den Datenfluss rückwärts zur Quelle verfolgen. Trigger words: debug, root cause, why is this failing, silent failure, regression, works in tests but fails live, systematic debugging, Ursache, Grundursache, warum schlägt das fehl, stilles Versagen, läuft im Test aber nicht live, systematisches Debuggen.4license: MIT5---67# Root Cause First8**Effort:** free — pure Untersuchungs-Disziplin, die die Kosten meist unterm Strich senkt: Eine entscheidende Probe ersetzt das Abfeuern der ganzen Pipeline, nur um zu sehen, was passiert. Beseitigt: Pflaster auf der falschen Stelle — den Symptom-Fix, der den echten Bug versteckt und einen nachgelagerten Konsumenten bricht.910Keine Fixes ohne Untersuchung. Ein Pflaster, geklebt bevor du das Versagen11verstehst, fixt das Falsche, versteckt den echten Bug und bricht etwas12weiter unten. Dein Produkt ist kein Patch — es ist eine Grundursache, bewiesen13durch eine entscheidende Probe, und ein Fix, bewiesen frei von Regressionen.1415Zwei Gesetze regieren alles hier drunter:16171. **Keine Annahmen — der Code, die Daten und das Live-System sind die18 Wahrheit; Notizen sind nur Hinweise.** Ein Kommentar, eine Erinnerung, ein19 früherer Schluss, selbst dein eigener letzter Satz ist eine Hypothese, bis20 eine Probe sie bestätigt. Die Wörter „alle / jeder / keiner“ lösen einen21 Drei-Punkt-Check aus: die Umgebung, eine repo-weite Suche und ein Scan über22 jeden Aufrufer.232. **Ein verifiziertes Gegenbeispiel killt den früheren Schluss sofort.** Wenn24 eine Probe widerlegt, was du geglaubt hast, sag klar „Ich lag falsch — es25 ist in Wirklichkeit X" und mach vom neuen Fakt aus weiter. Nie drüber26 tapezieren.2728## Die Schleife (in dieser Reihenfolge; nichts überspringen)29301. **Lies den Fehler.** Benenn das Symptom in einem präzisen Satz. Lies die31 echte Meldung, nicht das, was du erwartest. Benenn den Explosionsradius:32 was hängt an dem Ding, das du verdächtigst?332. **Reproduzier.** Bring das Versagen auf Kommando — live, oder in einem34 fehlschlagenden Test. **Stopp die Zeit.** Ein „Versagen“, das in35 Millisekunden zurückkommt, wo echte Arbeit Sekunden braucht, ist eine früh36 geschluckte Exception, kein echtes Arbeits-Versagen. Die Zeitlücke ist37 selbst ein Hinweis.383. **Prüf jüngste Änderungen.** Diffe, was sich geändert hat, seit es zuletzt39 lief — Code, Config, Umgebung, Abhängigkeiten. Ist die Historie lang,40 bisektier sie.414. **Kartier die Konsumenten.** Bei einem Bug in einer geteilten Fläche: list42 jeden Aufrufer und wie er sie nutzt (exakter String-Match? Boolean? Liste?).43 Die echte Regression versteckt sich meist in einem nachgelagerten44 Exakt-Match-Vergleich, nicht in dem Regler, an dem du drehst.455. **Instrumentier die Grenzen.** Logge oder probe an jeder Komponenten-Naht —46 was rein geht, was raus kommt. Verfolg die schlechten Daten rückwärts,47 Grenze für Grenze, bis du an der Quelle bist. Fix die Quelle, nie das48 Symptom.496. **Grundursache per Hypothese.** Bild eine falsifizierbare Hypothese. Find50 die EINE entscheidende Probe, die sie von den Alternativen trennt, und fahr51 nur die. Feuer nicht die ganze Pipeline ab, „um zu sehen, was passiert“.527. **Fix chirurgisch, an der richtigen Naht.** Die kleinste Änderung, die die53 Grundursache auflöst. Bevorzug die eine geteilte Quelle (ein Normalizer,54 ein Runner) statt N Aufrufstellen zu editieren. Wo möglich, mach den Fix55 inert auf dem funktionierenden Pfad — er ändert dort beweisbar nichts und56 greift nur auf dem kaputten. Keine Nachbar-Refactors als Beifahrer.578. **Beweis es.** Schreib den fehlschlagenden Test, der den Bug reproduziert;58 sieh ihn rot werden; fix; sieh ihn grün werden. Dann fahr die Tests für59 jeden Konsumenten-Pfad aus Schritt 4 — grün dort ist dein60 Null-Regressions-Boden. Eine Suite, die genau die Naht mockt, die versagt61 hat, beweist nichts.629. **Verifizier live.** Fahr das echte System — echte Requests, echte63 Datenbank, echte Logs. Nie ein Beiwagen-Skript, das den Code in deinen64 eigenen Prozess importiert. Halt Vorher/Nachher-Beweise fest.6510. **Lern.** Schreib das Symptom, die entscheidende Probe, die Grundursache66 und das Anti-Muster auf, das sie versteckt hat — damit der nächste Bug67 dieser Form billiger wird.6869## Bau die Reproduktions-Schleife, BEVOR du Theorien baust7071Ertappst du dich beim Code-Lesen für eine Theorie, bevor ein rot-fähiges72Kommando existiert — stopp. Kein rot-fähiges Kommando, keine Theorie. Ein73enges Pass/Fail-Signal, das bei DIESEM Bug rot wird, ist der größte einzelne74Debugging-Hebel. Investier hier überproportional.7576Wege, eins zu bauen, grob in dieser Reihenfolge: ein fehlschlagender Test; ein77HTTP-Skript gegen einen Dev-Server; ein CLI-Lauf mit Fixture-Eingabe, gedifft78gegen einen bekannten guten Snapshot; ein Headless-Browser-Skript; ein79mitgeschnittenes echtes Payload, isoliert durch den Codepfad zurückgespielt;80ein Wegwerf-Harness, das eine Funktion aufruft; eine Fuzz-Schleife über81Zufallseingaben; ein Bisektions-Harness, damit automatisches Bisect läuft;82eine Differential-Schleife (gleiche Eingabe durch alte und neue Version, die83Ausgaben gedifft).8485Dann zieh sie fest: schneller (Setup cachen, Scope verengen), schärfer (das86konkrete Symptom asserten, nicht „ist nicht abgestürzt“), deterministisch87(Zeit pinnen, RNG seeden, Netz einfrieren). Eine deterministische88Zwei-Sekunden-Schleife ist eine Superkraft.8990Bei flatterhaften Bugs jag eine höhere Reproduktionsrate, keine saubere Repro:91loope den Auslöser 100-mal, gib Stress dazu, verenge die Timing-Fenster. Ein9250%-Flake ist debugbar; ein 1%-Flake nicht.9394Kriegst du wirklich keine Schleife gebaut, stopp und sag es. List auf, was du95versucht hast, und bitte deinen Menschen um Zugang, ein mitgeschnittenes96Artefakt oder temporäre Instrumentierung. Theoretisier nicht ohne Schleife.97Und existiert keine Naht, die das echte Aufrufmuster nachstellen kann, IST98dieses Fehlen ein Fund — flagg die Architektur-Lücke, nachdem der Fix99gelandet ist.100101## Anti-Muster (wie harte Bugs am Leben bleiben)102103- Aus einer Notiz oder einem Kommentar schließen, ohne Probe.104- Fixen vor dem Reproduzieren.105- Einer grünen Suite trauen, die genau die Naht mockt, die live versagt.106- Beiwagen-Verifikation — den Code importieren, statt das Live-System zu fahren.107- Einen Config-Regler drehen, ohne die Exakt-Match-Konsumenten zu kartieren,108 die er füttert.109- Breite Refactors als Beifahrer eines Fixes.110- „alle / jeder / keiner“ sagen, ohne den Drei-Punkt-Check.111112## Passt gut zu113114- [red-first](../red-first/SKILL.md) — committe den fehlschlagenden Test vor dem Fix.115- [sniper-testing](../sniper-testing/SKILL.md) — gescopte Tests beim Iterieren.116- [seam-engineering](../seam-engineering/SKILL.md) — fix die Klasse, nicht die Instanz.117- [repair-loop](../repair-loop/SKILL.md) — der volle Fix-und-Lande-Zyklus.118119> Scaffold credit: Matt Pocock, diagnosing-bugs (mattpocock/skills). Komposition und harte Regeln hier sind BACKS AIOS.