Praktischer Teil 10. Schutz von Metriken vor Goodhart: Wächtermetriken und Notfallmodus
Status: Empfehlung. Der Schutz von KPIs durch eine gepaarte Wächtermetrik (Guard-Metrik) und einen blockierenden Notfallmodus ist eine etablierte Praxis, die im Google SRE Book beschrieben wird. Konkrete Schwellenwerte (silent_p0, manual_review_floor, audit_trace_coverage) und das Format validation.md v1.1 sind ein empfohlener Rahmen, den die meisten Teams anpassen.
Für den didaktischen Durchlauf reicht es, examples/goodhart-validator/ auszuführen und zu sehen, wie ein gutes MTTR durch den Anstieg von silent_p0 blockiert wird. Das Metriknetzwerk, Trace-Felder und die Kalibrierung von Schwellenwerten gehören zum vollständigen Production-Track. Wenn unten der Begriff „rote Taste“ vorkommt, lesen Sie ihn als Kurzbezeichnung für den formalen Notfallmodus.
In Teil 9 des ersten Bandes reichte eine Metrik pro Prüfung aus: „Review ist nach Veröffentlichung sichtbar“, „Summe geht nicht ins Minus“. Im Production-Szenario cdn_error_budget_burn reicht dieselbe Logik nicht mehr. Das Dashboard des Agenten- und Krankheitsjournals aus Teil 11 zeigt nach dem Release ein widersprüchliches Bild, und die einzelne Metrik wird zur Lockvogelmetrik. Hier entwickeln wir sie zu einem Netzwerk gepaarter Wächtermetriken – das sind Paare aus „KPI + Absicherungskennzahl“, wobei die zweite nicht zulässt, dass die erste auf Kosten versteckter Schäden optimiert wird. Der Katalog typischer Manipulationen, gegen die dieses Netzwerk schützt, ist systematisiert in Teil 20. SDD-Antipatterns.
Vor dem Lesen
- Fundierung aus dem ersten Band: Teil 9 lehrt, Fakten zu prüfen, nicht überzeugende Prosa; Teil 20 zeigt, wie ein Prozess anfängt, das falsche Ziel zu schützen.
- Lokaler didaktischer Fall:
cdn_error_budget_burn, weil ein verbessertes MTTR durch den Anstieg vonsilent_p0blockiert werden kann. - Spur für
capstone/: eine Zielmetrik, eine Guard-Metrik und ein blockiertes Beispiel fürhigh_memory_usage.
- Hauptbegriffe des ersten Durchgangs: Guard-Metrik und Notfallmodus („rote Taste“). Die übrigen –
silent_p0,manual_review_floor,audit_trace_coverage,edge_drift, Trace-Felder, Metriknetzwerk – sind referenzartig; öffnen Sie sie nur, wenn sie für eine Zeile incapstone/goodhart-note.mdbenötigt werden. - Was zurückzustellen ist: Metriknetzwerk, Trace-Felder, Drift-Kalibrierung und vollwertiger Notfallmodus.
Ziel
Am Ende des Abschnitts erstellen Sie ein validation.md, das Goodhart-Fallen vorab erkennt und nicht zulässt, dass die LLM-Incident-Pipeline berichtete KPIs auf Kosten der Degradation des Triage verbessert.
Der Hauptgewinn ist folgender: Sie teilen Metriken in steuerbare Ziele und unverletzliche Qualitätsinvarianten auf. Dann verankern Sie für diese prüfbare Schwellenwerte, Nachweise in Traces und Blockierungen im CI.
„Lockvogelmetriken“ bedeuten hier KPIs, die als Signal nützlich sind, aber gefährlich werden, wenn sie isoliert von Qualitätsinvarianten optimiert werden. KPI (key performance indicator) ist ein Kennzahl, die das Team mit einem Release verbessern möchte.
Dieser Ansatz setzt den SDD-Zyklus fort: Spezifikation, Prüfkriterien und Iterationen werden vor der Implementierung von Änderungen festgelegt, nicht nachträglich an ein schönes Ergebnis angeglichen (GitHub Spec Kit Quickstart).
Der Effekt selbst, „wenn eine Maßnahme zum Ziel wird, hört sie auf, eine gute Maßnahme zu sein“, ist klassisch als Goodharts Gesetz bekannt (Wikipedia: Goodhart's law). Die Definition von SLO bei Google SRE stützt sich direkt auf diese Vorsicht (SRE Book: Service Level Objectives).
Minimaler didaktischer Szenario
Didaktischer Fall
Production-Incident cdn_error_budget_burn, projiziert auf das didaktische Agentenjournal aus book/part-11-second-feature-phase.md. Das Release verbesserte MTTR von 660s auf 290s, was formal wie ein Erfolg aussieht. Aber silent_p0 sprang von 0,02 auf 0,18, manual_review_rate fiel von 0,18 auf 0,12. Ziel ist es zu sehen, dass das CI-Gateway diesen Shift erkennt und die Zusammenführung blockiert, trotz „grünem“ MTTR.
Vorbereitung
book2/examples/goodhart-validator/specs/validation.yaml– Invarianten und Prüfung der roten Taste.
book2/examples/goodhart-validator/fixtures/baseline_metrics.json– Referenz (MTTR 660s, silent_p0 0,02).book2/examples/goodhart-validator/fixtures/new_metrics_good.json– Verbesserung ohne blinde Flecken.book2/examples/goodhart-validator/fixtures/new_metrics_bad.json– „MTTR-Blindheit“ (290s, silent_p0 0,18).book2/examples/goodhart-validator/fixtures/new_metrics_drift.json– Drift bei Kantenkorrelationen.book2/examples/goodhart-validator/scripts/run_validation.py,compare_drift.py,ci_gate.py.
Schritte
cd book2/examples/goodhart-validator. Erwartung: Sie befinden sich im Beispielverzeichnis, keine zusätzlichen Abhängigkeiten.- Durchlauf „gut“:
python3 scripts/run_validation.py --validation specs/validation.yaml --metrics fixtures/new_metrics_good.json. *Erwartung: Rückgabecode 0, StatusPASS, alle drei InvariantenOK.* - Durchlauf „MTTR-Blindheit“:
python3 scripts/run_validation.py --validation specs/validation.yaml --metrics fixtures/new_metrics_bad.json. *Erwartung: Rückgabecode 1,red_button_mttr_blindnesslöst aus,manual_review_floorundsilent_p0_capwerden mit FAIL markiert.*
Schlecht: Nur auf MTTR zu schauen – das Release ist schneller, scheint „besser“.
Gut: Validierung mit Invarianten ausführen – „schneller“ bei silent_p0=0.18 wird automatisch blockiert.
- Drift-Durchlauf gegen Drift-Fixture:
python3 scripts/compare_drift.py --baseline fixtures/baseline_metrics.json --new fixtures/new_metrics_drift.json. *Erwartung:edge_drift > 0.12, Rückgabecode 1.* - Kontrolle: Derselbe
compare_drift.pygegen gute Metriken. *Erwartung:edge_drift <= 0.12, Rückgabecode 0.* - Vollständiges CI-Gateway:
python3 scripts/ci_gate.py --validation specs/validation.yaml --baseline fixtures/baseline_metrics.json --new fixtures/new_metrics_bad.json. *Erwartung: Rückgabecode 1, inreasonswerden konkrete verletzte Invarianten aufgelistet, nicht allgemeinesFAIL.* - Den Durchlauf als kurzen Anti-Goodhart-Befund festhalten: Zielmetrik verbessert, aber
silent_p0_capundmanual_review_floorblockierten das Release. Erwartung: Beim nächsten Pull-Request mit MTTR-Beschleunigung vergleicht der Validator nicht „grün gegen alten Baseline“, sondern gegen good/bad/drift-Fixtures.
Wenn Qwen Code installiert ist und eine Erklärung für das Review benötigt wird, führen Sie einen separaten optionalen Schritt aus:
qwen -p "Lies @fixtures/new_metrics_bad.json und @specs/validation.yaml. Welche Invariante darf auch bei MTTR=290s nicht umgangen werden? Dateien nicht ändern." --approval-mode plan
Diese Ausgabe ist als Erläuterung nützlich, ersetzt aber nicht run_validation.py, compare_drift.py und ci_gate.py.
Kontrollfakt
Schritt 2 liefert Rückgabecode 0, Schritte 3 und 4 – Rückgabecode 1 mit konkreter Angabe verletzter Invarianten. Schritt 6 zeigt dasselbe Verhalten im zusammengesetzten Gateway. Wenn das CI-Gateway new_metrics_bad.json durchlässt, ist die Validator-Konfiguration geschwächt – der Schwellenwert silent_p0_cap oder manual_review_floor wurde verschoben.
Wie das in capstone/ übernommen wird
Übertragen Sie in capstone/goodhart-note.md eine Zielmetrik, eine Guard-Metrik und ein blockiertes Beispiel. Wenn der Hauptprüfungsfall high_memory_usage ist, notieren Sie diesen Durchlauf als Anti-Goodhart-Risiko für denselben Kontur: Memory oder MTTR dürfen nicht auf Kosten von silent_p0, manuellem Audit oder 5xx verbessert werden. Übertragen Sie nicht das gesamte Metriknetzwerk, wenn es nicht neu berechnet wurde; für den didaktischen Minimalumfang reicht es zu zeigen, dass ein verbesserter KPI ohne Schutzinvariante nicht durchkommt.
Minimaler Fragment:
target_metric: "MTTR <= 5m"
guard_metric: "silent_p0 <= 0.05 and manual_review_rate >= 0.15"
blocked_example: "new_metrics_bad.json"
reason: "MTTR improved, but silent_p0 and manual_review_floor fail"
Reviewfähige Spur
Die Skripte run_validation.py, compare_drift.py und ci_gate.py schreiben Ergebnisse nach stdout, sie erstellen kein separates out/-Verzeichnis. Für den didaktischen Pfad übertragen Sie das Ergebnis in capstone/goodhart-note.md: Zielmetrik, Guard-Metrik, blockiertes Beispiel und Grund.
Wenn Sie in Ihrem Projekt outputs/goodhart.last-run.txt speichern, muss es als lesbarer Anhang zum Review dienen, nicht als leerer Marker. In SDD gilt als Fakt eine reproduzierbare Befehl oder lesbares Artefakt, nicht die bloße Existenz eines Commits.
Schlüsselideen
Definieren Sie zuerst, welche Kennzahlen Qualitätsinvarianten bleiben und welche zu Optimierungszielen werden und daher manipulierbar sind. Eine Invariante darf nicht direkt „verbessert“ werden: Sie beschreibt den minimal zulässigen Systemzustand. Beispiele für Invarianten:
- Vollständigkeit des Audits;
- Anteil manueller Prüfung;
- Obergrenze von
silent_p0(das ist der Anteil „stillen“ kritischer Incidents, die ohne Eskalation geschlossen wurden).
Das Optimierungsziel hingegen kann gesenkt oder erhöht werden, aber nur innerhalb eines Schutzkorridors. MTTR ist als Indikator für Wiederherstellungsgeschwindigkeit nützlich, aber als einzige Belohnung für Modell oder Team gefährlich.
Machen Sie diese Unterscheidung in validation.md explizit. MTTR<=5m kann ein Ziel sein. manual_review_rate>=15%, silent_p0<=5% und audit_trace_coverage==100% bleiben Zulassungsbedingungen.
Schlecht:
> MTTR unter 5 Minuten erreichen.
Problem: Nacktes Ziel ohne Wächtermetriken, direkter Weg zu silent_p0.
Gut:
> MTTR <= 5m AND silent_p0 <= 5% AND manual_review_rate >= 15% AND audit_trace_coverage == 100% – Verletzung jeder Bedingung = CI_BLOCK.
Die Goodhart-Falle zeigt sich, wenn eine Metrik zum Ersatz für die Realität wird. Das System beginnt, die Messmethode zu optimieren, nicht die Triage-Qualität. Wenn MTTR isoliert geprüft wird, lernt das Modell, Incidents schneller zu schließen, den Eskalationsanteil zu senken und lange Untersuchungen zu vermeiden – genau diese verschlechtern die mittlere Wiederherstellungszeit.
Im Diagramm sieht das wie ein Sieg aus: MTTR fällt auf 5 Minuten oder darunter. Aber im operativen Kontur kann das Gegenteil bedeuten. Komplexe P0 sind nicht verschwunden, sondern unbemerkt geworden, weil sie fälschlich als Fehlalarme, niedrige Dringlichkeit oder „selbstheilende“ Ereignisse klassifiziert wurden.
Die „MTTR 5 Minuten“-Falle ist besonders gefährlich für seltene schwere Incidents, wo Schnelligkeit der Schließung mit Vollständigkeit der Untersuchung konkurriert. In Zahlen sieht das so aus:
- Referenz bei 300 Incidents im Replay: MTTR 11:00, Eskalationsanteil 14%,
silent_p02%; - neue optimierte Version: MTTR 4:50, Eskalationen 6%,
silent_p018%.
Formal hat sich der KPI verbessert. Aber das System übersieht häufiger kritische Ereignisse ohne manuelle Prüfung und Eskalation. Blockieren Sie ein solches Release: Es verschiebt das Risiko aus dem sichtbaren Bericht in zukünftige wiederholte Incidents, Post-Mortem-Regressionen und verlorene Verantwortungsketten.
Die Antikörper in validation.md sind formale Bedingungen, die nicht zulassen, dass Optimierung die Bedeutung von Qualität neu definiert. Der Minimalumfang sind drei Regeln, die gleichzeitig geprüft werden müssen:
| Regel | Was geschützt wird | Grenze |
|---|---|---|
manual_review_floor | Anteil Entscheidungen mit manueller Verifikation | nicht unter 15% |
| silent_p0_cap | Anteil „stiller“ P0, ohne Eskalation geschlossen | nicht über 5% | | audit_trace_required | Vollständigkeit der Entscheidungsspur (Prompt, Diff, Quelle) | 100%, ohne Ausnahmen |
Einzeln lassen diese Regeln Schlupflöcher. Hohe Traceability kompensiert nicht steigendes silent_p0. Manuelle Prüfung ist nutzlos, wenn Prompt, Diff und Quelle der Entscheidung nicht rekonstruierbar sind. Konfigurieren Sie die „rote Taste“ so, dass sie nicht bei einer schlechten Zahl auslöst, sondern bei Verletzung des Schutzkonturs.
Was als Ziel und was als Schutz zu wählen ist
Nicht alle KPIs erfordern denselben Schutz. Manuelle Triage-Operation und automatische Remediation haben unterschiedliche Risikostufen, daher ist der Minimalumfang an Invarianten verschieden. Die Hauptregel ist eine: Je gefährlicher die Handlung, desto mehr Wächtermetriken gehören zum Ziel-KPI.
| Entscheidungstyp | Was verbessert wird | Was zwingend dazugehört |
|---|---|---|
| Manuelle Triage-Operation | MTTR | Entscheidungsspur vollständig gespeichert |
| Auto-Klassifikation ohne Handlung | Geschwindigkeit und Genauigkeit der Klassifikation | Keine stillen P0; Entscheidungsspur gespeichert |
| Auto-Eskalation | Eskalationsverzögerung | Keine stillen P0; Keine Fehleskalationen |
| Auto-Remediation ohne Zustand | MTTR | Keine stillen P0; Manuelle Prüfung vorhanden; Vollständiger Audit-Trail | | Auto-Remediation mit Zustand (DB, Cache) | MTTR | Dasselbe + Bestätigtes Backup | | Release neuer Richtlinie | Genauigkeit bei Wiederholung | Kein „Drift an den Grenzen“; Vollständiger Audit-Trail |
Die vollständigen englischen Metriknamen (silent_p0, manual_review_floor, audit_trace_coverage, false_escalation_rate, edge_drift, postmortem_gap, backup_verified) mit Schwellenwerten und Formeln sind in Anhang D ausgelagert. Hier zählt die Regel, nicht die Namenstabelle: Zu jeder Zeile „was verbessert wird“ muss ein bis zwei Wächter aus demselben Risikobereich gehören.
Für gefährliche Handlungen (letzte drei Zeilen) zusätzlich die „rote Taste“ einbinden – ein blockierendes Gateway, das nicht ohne Referendum aus Kapitel 3 umgangen werden kann. Für manuelle und beobachtende Operationen (erste drei Zeilen) reicht eine weiche Warnung.
Zweck der Tabelle ist nicht, sie zur Dogma zu machen, sondern zu helfen, was übersehen wurde. Wenn in der Zeile „Auto-Remediation mit Zustand“ keine Backup-Prüfung vorhanden ist – das ist ein Signal, validation.md neu zu schreiben, nicht „MTTR zu optimieren“.
> [conceptual interface] — Struktur von validation.md, die Sie an Ihre Trace-Dateien anpassen.
#### Minimale Struktur validation.md v1.1
version: 1.1
invariants:
- name: manual_review_floor
expression: "manual_review_rate >= 0.15"
- name: silent_p0_cap
expression: "silent_p0 <= 0.05"
- name: audit_trace_required
expression: "audit_trace_coverage == 1.0"
checks:
- name: red_button_mttr_blindness
when: "MTTR <= 5m"
assert: "manual_review_rate >= 0.15 and silent_p0 <= 0.05 and audit_trace_coverage == 1.0"
fail: "CI_BLOCK"
Die vollständige Form mit artifact_inputs, network_consistency und dem exakten Ausdruck für audit_trace_required über COUNT(events_with(...)) – in [examples/goodhart-validator/specs/validation.yaml](examples/goodhart-validator/specs/validation.yaml).
Die nächste Schutzschicht ist ein Detektor für versteckte Verzerrungen direkt in der Spezifikation. Zählen Sie eine Verhaltensänderung der Triage bei unveränderten KPI als Regression. Hier ist Regression eine Verschiebung in der Entscheidungsverteilung, die in Aggregaten nicht sichtbar ist.
Grund: Der Schaden ist nicht immer in oberflächlichen Zahlen sichtbar. MTTR kann gleich bleiben, der Eskalationsanteil kann normal aussehen, aber das Modell beginnt, streitige Fälle anders zwischen auto_close, manual_review und defer zu verteilen.
Daher in validation.md nicht nur Aggregate vergleichen, sondern Verhaltensmuster:
- Übergangsmatrix der Schweregrade;
- Verteilung der Schließungsgründe;
- Anteil wiedereröffneter Incidents;
- Verzögerung bis zur Post-Mortem-Markierung;
- Änderung der Beziehung zwischen
manual_review_rateundsilent_p0.
Wenn drift_budget (zulässiger Korridor der Abweichung vom Referenzwert) überschritten wird, blockieren Sie den Build auch bei „grünen“ KPIs. Das bedeutet, dass das System bereits den Entscheidungsmodus gewechselt hat.
Um die Hauptfalle zu erkennen, reichen drei Metriken und ein Wächter:
flowchart LR
MTTR[MTTR]
silent_p0[silent_p0]
manual_review_rate[manual_review_rate]
audit_trace_coverage[audit_trace_coverage]
silent_p0 -->|zieht MTTR unlauter nach unten| MTTR
manual_review_rate -->|zieht MTTR lauter nach oben| MTTR
audit_trace_coverage -->|begrenzt silent_p0| silent_p0So zu lesen: Man kann MTTR künstlich verbessern, wenn man „stille“ P0 ohne Eskalation schließen lässt. Der Wächter audit_trace_coverage verbietet Schließung ohne Spur, und manual_review_rate hält den Anteil manueller Prüfungen aufrecht. Das vollständige Bild mit zusätzlichen Metriken (escalation_rate, postmortem_regression) – in Anhang D; dort auch formale Schwellenwerte und Verbindungen.
Binden Sie Prüfungen an Qwen-Logs, Entscheidungen und Diff-Ketten – sonst sind sie nicht ohne Kontextverlust in Production übertragbar. Minimale Trace-Zusammensetzung pro Ereignis: trace_id (Kette), prompt_hash (Prompt-Hash), decision (was gewählt wurde), policy_version + diff_id (welche Version und welche Änderung sie einbrachte) und postmortem_label (was die Analyse bestätigte). Der vollständige Satz Felder mit agent, raw_alert_excerpt, reasoning_delta und review_outcome gehört zum vollständigen Track und ist in [examples/templates/validation.md](examples/templates/validation.md) zusammengestellt.
Diese fünf Felder ermöglichen es, technische Fragen nach einer Blockierung zu beantworten: Welche Spezifikationsversion änderte das Verhalten, welcher Prompt trieb das Modell zur Auto-Schließung, welcher Diff brachte die neue Heuristik ein. Ohne diese Verknüpfung bleibt validation.md eine Deklaration; mit ihr wird er zu einem reproduzierbaren Audit-Artefakt.
Entwerfen Sie Metriken als Netzwerk von Abhängigkeiten, nicht als Satz unabhängiger Zähler. Das ist network_consistency: Die Änderung einer Metrik darf nicht mit verbundenen im Widerspruch stehen. Berechnen Sie zusammen MTTR, silent_p0, manual_review_rate, escalation_rate, postmortem_regression, rollback_rate und audit_gap (siehe Diagramm oben). Lokale Verbesserung einer Größe schafft oft eine Schuld in einer anderen. Praktisches Kriterium – Konsistenz der Kanten: Wenn MTTR fällt, aber gleichzeitig manuelle Prüfung sinkt und der Anteil spät bestätigter P0 steigt, markieren Sie das System als riskant. Das verwandelt CI aus der Prüfung „KPI bestanden/nicht bestanden“ in eine Prüfung der Triage-Verhaltensstabilität.
> [conceptual interface] — scripts/metrics/network_recompute.py zeigt die Form der lokalen Neuberechnung des Metriknetzwerks; ein fertiges CLI gibt es im Lehrbuch-Repository nicht. Runnable-Analogon des CI-Gateways selbst mit Anti-Goodhart-Prüfungen – python3 examples/goodhart-validator/scripts/run_validation.py und ci_gate.py (siehe unten „Kontrollfakt“).
#### Aktualisierung des Metriknetzwerks und Validierungs-CI-Gate nach Spec-Änderung
python3 scripts/metrics/network_recompute.py \
--spec specs/incident-spec.md \
--replay data/replay_*.jsonl \
--out .artifacts/metric_network.json
python3 scripts/metrics/ci_gate.py \
--artifact validation.md \
--metric-network .artifacts/metric_network.json \
--traces .artifacts/qwen_trace.ndjson
CONTROL: CI_GATE = PASS if (edge_drift <= 0.12 && silent_p0 <= 0.05 && manual_review_rate >= 0.15 && audit_trace_coverage == 1.0) else CI_BLOCK
Vollständiger Track: Kalibrierung der Schwellenwerte
Die Tabelle „Niedrig / Standard / Hoch“ für silent_p0, manual_review_rate, edge_drift, audit_trace_coverage, die Übung zum „gefährlichen“ gleichzeitigen Abschwächen zweier Schutzmaßnahmen und das vollständige Netzwerk der Metrikabhängigkeiten – in Anhang D, Abschnitt D.4. Beim ersten Durchgang reicht es zu sehen, dass ein schlechtes Release durch eine Guard-Metrik blockiert wird.
Beispiele und Anwendung
Beispiel: Ein Team möchte die Bereitschaft einer neuen Triage-Pipeline für aggressiveres Auto-Schließen nachweisen. Zuerst wird ein Replay-Durchlauf mit Zieloptimierung MTTR<=5m gestartet. Dann wird derselbe Incident-Satz durch red_button_mttr_blindness geprüft.
Wenn das Ergebnis wie MTTR=4:50, silent_p0=18%, manual_review_rate=12% aussieht, blockieren Sie das Release. Der Grund liegt nicht in der schlechten Geschwindigkeit, sondern in der Verletzung der Schutzinvarianten. Diese Unterscheidung ist wichtig: Das Ziel wurde erreicht, aber der Qualitätsvertrag ist gebrochen.
> [conceptual interface] — scripts/metrics/simulate.py und validate_red_button.py zeigen die Form der Notfallmodus-Prüfung; ein fertiges CLI gibt es im Lehrbuch-Repository nicht. Runnable-Analogon der Prüfung derselben Invarianten auf didaktischen Fixtures – python3 examples/goodhart-validator/scripts/run_validation.py (siehe examples/goodhart-validator/README.md).
#### Beispieldurchlauf der roten Taste auf Replay
python3 scripts/metrics/simulate.py \
--scenario data/replay_300.jsonl \
--goal "MTTR<=5m" \
--spec specs/incident-spec.md
python3 scripts/metrics/validate_red_button.py \
--artifact validation.md \
--mode red_button \
--assert "silent_p0<=5% && manual_review_rate>=15% && audit_trace_coverage==1.0"
CONTROL: red_button = BLOCKED (MTTR=4:50, silent_p0=18%, manual_review_rate=12%)
Zweites Beispiel – Fehlerhaftes Auto-Schließen von 40 P0 als „Fehlalarme“. Vor dem Post-Mortem sieht die Metrik sauber aus: Incidents schnell geschlossen, weniger Eskalationen, Warteschlange wächst nicht.
Nach der Abgleich mit Labels ergibt sich etwas anderes. Fünf Ereignisse waren echte kritische Ausfälle. Genau diese müssen silent_p0, escalation_regret und postmortem_regression erhöhen.
In validation.md notieren Sie einen solchen Fall als prädiktives Triage-Versagen. Warten Sie nicht auf Benutzerschaden in Production. Verwenden Sie Replay und Post-Mortem-Wahrheit als frühes Blockiersignal.
Praktisch speichern Sie validation.md neben der Spezifikation und aktualisieren ihn nur durch denselben Review-Prozess wie die Triage-Regeln. CI baut bei jeder Änderung das Metriknetzwerk neu, führt Replay durch, prüft Trace-Vollständigkeit und vergleicht Verhalten mit Referenz. Eine Schwellenwertänderung – z.B. zulässiges silent_p0 von 5% auf 7% anheben – führen Sie als Risikovertragsänderung durch das Mutable-Regel aus Teil 3, nicht als technische YAML-Korrektur. Diese Hürde schützt das System vor schleichender Aushöhlung von Invarianten unter dem Druck bequemer Berichte.
Zusammenfassung
Lockvogelmetriken sind nicht deshalb gefährlich, weil sie falsch sind. Sie sind nützlich bis zum Moment, wenn sie zum einzigen Optimierungsziel werden.
Ein zuverlässiges validation.md löst fünf Aufgaben:
- Trennt Ziele von Invarianten;
- Blockiert MTTR-Verbesserungen bei steigendem
silent_p0; - Erfordert minimale manuelle Verifikation;
- Prüft Triage-Verhaltensdrift;
- Bewahrt die Beweiskette aus Qwen-Logs, Entscheidungen und Diffs.
> [runnable] — Minimaler Smoke-Test für dieses Kapitel liegt in [examples/goodhart-validator/](examples/goodhart-validator/README.md).
cd book2/examples/goodhart-validator
python3 scripts/run_validation.py \
--validation specs/validation.yaml \
--metrics fixtures/new_metrics_good.json
python3 scripts/ci_gate.py \
--validation specs/validation.yaml \
--baseline fixtures/baseline_metrics.json \
--new fixtures/new_metrics_good.json
Das Beispiel mit erwartetem Fehlschlag für den Notfallmodus-Szenario verwendet fixtures/new_metrics_bad.json: run_validation.py und ci_gate.py müssen mit Code 1 enden, weil manual_review_floor und silent_p0_cap verletzt sind.
Im nächsten Kapitel wird dieser Schutzkontur an echte Monitoring- und Deployment-APIs angeschlossen.
Artefakte und Fertigstellungskriterien
| Artefakt | Fertig, wenn |
|---|---|
Lokaler Durchlauf book2/examples/goodhart-validator | Optimierungsziel von unverletzlicher Invariante getrennt |
| Drei Fixtures: good / bad / drift | new_metrics_good.json besteht, new_metrics_bad.json wird mit konkretem Grund blockiert, new_metrics_drift.json wird von compare_drift.py blockiert | | Ein Blockierbeispiel durch Wächtermetrik | MTTR verbessert, aber Release wegen silent_p0 oder manual_review_floor blockiert | | Eintrag in capstone/goodhart-note.md | Drei Zeilen: Zielmetrik, gepaarte Guard-Metrik, Blockierbedingung |
Der vollständige Track ergänzt validation.md mit Zielmetrik und Qualitätsinvarianten, .artifacts/metric_network.json oder ausführbares Analogon des Metriknetzwerks, Replay-Set und CI-Gateway-Bericht mit edge_drift, silent_p0 und audit_trace_coverage. Als fertig gilt es, wenn der Notfallmodus MTTR<<5m bei steigendem silent_p0 blockiert, Trace-Felder Prompt, Diff, Entscheidung und Post-Mortem-Label verknüpfen, und eine Schwellenwertänderung als Risikovertragsänderung, nicht als YAML-Kosmetik, behandelt wird.
Praxis
cd book2/examples/goodhart-validator && python3 scripts/run_validation.py --validation specs/validation.yaml --metrics fixtures/new_metrics_good.json --json— *Erwartung: Code 0, in JSON"status": "PASS", alle drei Invariantenmanual_review_floor,silent_p0_cap,audit_trace_requiredhaben"ok": true.*python3 scripts/run_validation.py --validation specs/validation.yaml --metrics fixtures/new_metrics_bad.json --json— *Erwartung: Code 1, in JSON"status": "CI_BLOCK", Prüfungred_button_mttr_blindnesslöst aus mit"fail": "CI_BLOCK"undviolated_invariants: [manual_review_floor, silent_p0_cap]. Ebensopython3 scripts/compare_drift.py --baseline fixtures/baseline_metrics.json --new fixtures/new_metrics_drift.json --threshold 0.12gibt Code 1 zurück und drucktedge_drift=0.18 threshold=0.12 -> FAIL.*- Übertragen Sie in
capstone/goodhart-note.mddrei Zeilen: Zielmetrik (MTTR), Guard-Metrik (silent_p0oderaudit_trace_coverage), Regel der roten Taste. *Erwartung: Der nächste Zusammenführungsversuch mit verbessertem MTTR, aber fallenderaudit_trace_coveragewird automatisch blockiert.*
Kontrollfragen
- Warum ist MTTR als einziges Optimierungsziel gefährlich?
- Worin unterscheidet sich eine Qualitätsinvariante von einem KPI?
- Welche Trace-Felder werden benötigt, um eine Goodhart-Regression zu untersuchen?
- Nach dem Release fiel MTTR um 30%, aber
silent_p0stieg von 4% auf 12%. Was tun Sie – Release annehmen, zurückrollen oder zusätzliche Diagnose fordern? Was prüfen Sie genau?