Thema: Прикладная часть 10. Защита метрик от Гудхарта: сторожевые метрики и аварийный режим
Schwierigkeitsgrad: Mittel
Geschätzte Lernzeit: 4-6 часов (теория + практика)
Voraussetzungen: Знакомство с основами мониторинга и SRE (Site Reliability Engineering)
Понимание базовых метрик: MTTR, MTBF, SLA
Опыт работы с CI/CD пайплайнами
Знание Python на уровне запуска скриптов и чтения YAML-конфигураций
Прохождение части 9 первого тома (валидация фич) — желательно
Ознакомление с частью 11 (журнал агентов и недугов) — желательно
Lernziele: Различать целевые KPI и инварианты качества, формулировать для них проверяемые пороги в validation.md
Настраивать и запускать сторожевые метрики (guard-метрики) и аварийный режим («красную кнопку») для блокировки регрессий Гудхарта в CI
Выполнять дымовые прогоны на трёх фикстурах (good/bad/drift), интерпретировать коды возврата и нарушенные инварианты
Фиксировать anti-Goodhart-риски в capstone-документе: одна целевая метрика, одна guard-метрика, один заблокированный пример
Определять минимальный набор полей трассировки для расследования регрессий и связывать их с решениями и различиями
Übersicht: Этот раздел учит защищать метрики от закона Гудхарта — феномена, при котором мера становится искажённой целью оптимизации. В production-сценариях одиночный KPI (например, MTTR) превращается в "приманку": система начинает оптимизировать способ измерения в ущерб реальному качеству. Решение — сеть парных сторожевых метрик, где каждому целевому показателю сопоставлены guard-метрики-инварианты, нарушение которых блокирует релиз через аварийный режим ("красную кнопку"). Материал опирается на практики Google SRE Book и адаптирован для LLM-инцидентных конвейеров. Учебный минимум — запуск локального валидатора на трёх фикстурах и фиксация результата в capstone-документе.
Schlüsselkonzepte: Закон гудхарта (goodhart's law): Классический принцип: "когда мера становится целью, она перестаёт быть хорошей мерой". В контексте инцидент-менеджмента это означает, что изолированная оптимизация MTTR приводит к росту "тихих" критических инцидентов, ложным классификациям и утрате полноты расследования.
Метрика-приманка: KPI, полезный как сигнал, но опасный как единственная цель оптимизации. MTTR — типичная метрика-приманка: её легко улучшить ценой скрытого ущерба (молчаливое закрытие P0, сокращение ручной проверки).
Guard-метрика (сторожевая метрика): Парный показатель-инвариант, который не даёт оптимизировать целевой KPI ценой скрытого ущерба. Примеры: silent_p0_cap, manual_review_floor, audit_trace_coverage. Нарушение guard-метрики = автоматическая блокировка релиза.
Инвариант качества: Минимально допустимое состояние системы, которое нельзя "улучшать" прямым давлением. В отличие от KPI, инвариант описывает защитный порог: manual_review_rate ≥ 15%, silent_p0 ≤ 5%, audit_trace_coverage = 100%.
Аварийный режим («красная кнопка»): Блокирующий CI-шлюз red_button_mttr_blindness, который срабатывает при достижении целевого KPI при нарушении любого инварианта. Нельзя обойти без формального референдума (см. часть 3).
Silent p0: Доля "тихих" критических инцидентов (P0), закрытых без эскалации и ручного расследования. Рост silent_p0 — главный индикатор манипуляции MTTR. Порог по умолчанию: ≤ 5%.
Manual review floor: Минимальная доля решений с ручной верификацией. Защищает от полной автоматизации, которая исключает человеческий контроль. Порог по умолчанию: ≥ 15%.
Audit trace coverage: Полнота следа решения (prompt, diff, источник, policy_version). Должна быть 100% — без исключений. Запрещает закрытие без воспроизводимой доказательной цепочки.
Edge drift (дрейф рёбер): Показатель скрытого искажения поведения triage при неизменных агрегатных KPI. Измеряет отклонение в распределении решений между auto_close, manual_review, defer. Порог: ≤ 0.12.
Validation.md v1.1: Стандартная структура спецификации защиты от Гудхарта: invariants (неприкосновенные пороги), checks (правила красной кнопки), fail-условия CI_BLOCK. Минимум — три правила, проверяемые одновременно.
Сеть метрик (network consistency): Пересчёт связанных показателей вместе: MTTR, silent_p0, manual_review_rate, escalation_rate, postmortem_regression, rollback_rate, audit_gap. Локальное улучшение одной величины при ухудшении других = рискованная система.
Поля трассировки (trace fields): Минимальный набор: trace_id (цепочка), prompt_hash (хеш подсказки), decision (решение), policy_version + diff_id (версия и изменение), postmortem_label (подтверждение разбора). Позволяет восстановить причину регрессии.
Ci-шлюз (ci gate.py): Составной скрипт, объединяющий run_validation.py и compare_drift.py. Возвращает код 0 (PASS) или 1 (CI_BLOCK) с конкретным перечнем нарушенных инвариантов в поле reasons.
Übungsaufgaben: Name: Дымовой прогон: отличить хороший релиз от плохого
Problem: В каталоге book2/examples/goodhart-validator/ запустите run_validation.py сначала с new_metrics_good.json, затем с new_metrics_bad.json. Интерпретируйте разницу в выводе: почему первый прогон даёт PASS, а второй — CI_BLOCK? Какие конкретные инварианты нарушены во втором случае?
Lösung: 1. cd book2/examples/goodhart-validator
- python3 scripts/run_validation.py --validation specs/validation.yaml --metrics fixtures/new_metrics_good.json
Ожидание: код 0, status PASS, все инварианты OK
- python3 scripts/run_validation.py --validation specs/validation.yaml --metrics fixtures/new_metrics_bad.json
Ожидание: код 1, status CI_BLOCK, проверка red_button_mttr_blindness срабатывает
- В JSON-выводе (--json) найдите violated_invariants: [manual_review_floor, silent_p0_cap]
- Сравните метрики: good — MTTR 290s, silent_p0 0.03, manual_review_rate 0.18; bad — MTTR 290s, silent_p0 0.18, manual_review_rate 0.12. MTTR одинаков, но guard-метрики в bad нарушены.
- Вывод: "быстрый" MTTR при росте тихих P0 и падении ручной проверки — это манипуляция, не улучшение.
Komplexität: beginner
Name: Детекция дрейфа: compare_drift.py
Problem: Запустите compare_drift.py для baseline_metrics.json против new_metrics_drift.json и против new_metrics_good.json. Объясните, почему drift-фикстура блокируется при edge_drift=0.18 > threshold=0.12, а хорошая проходит. Что означает дрейф в отсутствие изменения верхнеуровневых KPI?
Lösung: 1. python3 scripts/compare_drift.py --baseline fixtures/baseline_metrics.json --new fixtures/new_metrics_drift.json Ожидание: edge_drift=0.18 threshold=0.12 -> FAIL, код 1
- python3 scripts/compare_drift.py --baseline fixtures/baseline_metrics.json --new fixtures/new_metrics_good.json
Ожидание: edge_drift <= 0.12 -> PASS, код 0
- Дрейф означает: модель изменила способ распределения спорных кейсов между auto_close/manual_review/defer, не меняя агрегаты MTTR/silent_p0. Это ранний сигнал смены режима принятия решений — система готовится к манипуляции, но ещё не проявила это в пороговых метриках.
- Проверьте, что ci_gate.py объединяет обе проверки: python3 scripts/ci_gate.py --validation specs/validation.yaml --baseline fixtures/baseline_metrics.json --new fixtures/new_metrics_drift.json тоже вернёт код 1.
Komplexität: intermediate
Name: Составление capstone-документа goodhart-note.md
Problem: Создайте capstone/goodhart-note.md для кейса high_memory_usage (или своего проекта). Запишите: одну целевую метрику, одну guard-метрику, один заблокированный пример с причиной блокировки. Убедитесь, что документ читаем для ревью — не пустой маркер коммита.
Lösung: Минимальный фрагмент:
target_metric: "memory_peak_mb <= 512"
guard_metric: "silent_p0 <= 0.05 and manual_review_rate >= 0.15"
blocked_example: "new_metrics_bad.json"
reason: "memory improved to 480 MB, but silent_p0 rose to 0.18 and manual_review_floor failed"
Расширенная версия:
target_metric: "memory_peak_mb <= 512"
guard_metric: "silent_p0 <= 0.05 and manual_review_rate >= 0.15 and audit_trace_coverage == 1.0"
blocked_example: "high_memory_optimized_v2.json"
reason: "memory improved to 480 MB, but silent_p0=0.18, manual_review_rate=0.12, audit gaps in 3 traces"
red_button_rule: "memory_target_met AND (silent_p0 > 0.05 OR manual_review_rate < 0.15) -> CI_BLOCK"
trace_required_fields: [trace_id, prompt_hash, decision, policy_version, diff_id, postmortem_label]
Проверка: документ должен позволить коллеге воспроизвести блокировку без доступа к вашей голове.
Komplexität: intermediate
Name: Калибровка порогов: ослабление двух защит одновременно
Problem: В specs/validation.yaml ослабьте silent_p0_cap с 0.05 до 0.10 и manual_review_floor с 0.15 до 0.10 одновременно. Запустите run_validation.py с new_metrics_bad.json. Проходит ли он теперь? Почему это опаснее ослабления одного порога? Восстановите исходные пороги после эксперимента.
Lösung: 1. Откройте specs/validation.yaml, найдите expression для silent_p0_cap и manual_review_floor
- Измените: silent_p0 <= 0.10, manual_review_rate >= 0.10
- python3 scripts/run_validation.py --validation specs/validation.yaml --metrics fixtures/new_metrics_bad.json
Вероятный результат: PASS (код 0), потому что silent_p0=0.18 всё ещё > 0.10, но проверьте граничный случай
- Если бы bad-фикстура имела silent_p0=0.09, она бы прошла — с manual_review_rate=0.12 при пороге 0.10 тоже FAIL, но при 0.09 и 0.11 — оба PASS
- Двойное ослабление создаёт "коридор лазеек": система может пройти через промежуточное состояние, где оба порога технически соблюдены, но качество деградировало. Это иллюстрация, почему изменение порога — изменение контракта риска, а не техническая правка.
- git checkout specs/validation.yaml или ручной откат.
Komplexität: advanced
Name: Анализ trace-полей для расследования регрессии
Problem: Представьте: после релиза MTTR упал на 30%, silent_p0 вырос с 4% до 12%. У вас есть логи Qwen с полями trace_id, prompt_hash, decision, policy_version, diff_id, postmortem_label. Какие конкретные запросы к этим данным помогут определить, какая версия спецификации и какое различие внесли новую эвристику автозакрытия?
Lösung: 1. Группировка по diff_id: SELECT diff_id, COUNT(*) FROM traces WHERE postmortem_label='false_negative_P0' GROUP BY diff_id — найдёт различие, внёсшее больше всего ложных закрытий
- Сравнение prompt_hash для auto_close решений: хеши, появившиеся только в новой версии, сопоставить с policy_version — покажет, какая подсказка подтолкнула к автозакрытию
- Матрица переходов: policy_version -> decision для одинаковых trace_id между baseline и new — выявит смену поведения при неизменном инциденте
- Задержка postmortem_label: COUNT WHERE postmortem_label IS NULL AND decision='auto_close' — покажет audit gap, который должен был быть пойман audit_trace_coverage
- Корреляция manual_review_rate и silent_p0 по policy_version — если при одной версии оба ухудшились, это подтверждение Гудхарт-регрессии
Komplexität: advanced
Fallstudien: Name: CDN error budget burn: MTTR-слепота в production-инциденте
Szenario: Команда SRE внедрила новый LLM-триаж-конвейер для обработки CDN-алертов. Релиз показал формальное улучшение MTTR с 660 секунд до 290 секунд — почти в 2.3 раза. Дашборд журнала агентов выглядел зелёным: среднее время восстановления укладывалось в SLO 5 минут.
Aufgabe: Операционный контур обнаружил противоречивую картину: silent_p0 подскочил с 0.02 (2%) до 0.18 (18%), manual_review_rate упал с 0.18 до 0.12. Сложные P0-инциденты не исчезли — они стали "тихими": классифицировались как ложные срабатывания или "самовосстановившиеся" события, закрывались без эскалации и расследования. Регрессия была скрыта: агрегат MTTR выглядел отлично, но 18% критических инцидентов утекли в бездну без пост-мортема.
Lösung: Команда внедрила парные сторожевые метрики и аварийный режим в CI-шлюз: (1) manual_review_floor ≥ 15% — минимальная доля ручной проверки; (2) silent_p0_cap ≤ 5% — верхняя граница тихих P0; (3) audit_trace_coverage = 100% — полнота следа. Правило red_button_mttr_blindness: при MTTR ≤ 5m проверить все три инварианта, при нарушении любого — CI_BLOCK. Релиз с MTTR=290s, silent_p0=0.18, manual_review_rate=0.12 был автоматически заблокирован несмотря на "зелёный" KPI.
Ergebnis: Блокировка вынудила команду пересмотреть модель: вместо агрессивного автозакрытия внедрили двухэтапную верификацию для спорных P0. MTTR стабилизировался на 420s — хуже 290s, но silent_p0 вернулся к 0.03, manual_review_rate восстановился до 0.16. Через 6 месяцев повторные инциденты снизились на 40% благодаря полноте пост-мортемов.
Gewonnene Erkenntnisse: Изолированный KPI — это приманка; защитный контур из 2-3 инвариантов обязателien для любой оптимизации MTTR
Автоматическая блокировка в CI важнее человеческого review "красивых" метрик — человек склонен одобрять "успех"
Полнота пост-мортема (через audit_trace_coverage) — долгосрочный индикатор здоровья, который нельзя жертвовать скоростью
Изменение порога guard-метрики должно проходить как изменение контракта риска, а не как скрытая правка YAML
Verwandte Konzepte: Метрика-приманка
silent_p0
manual_review_floor
red_button_mttr_blindness
audit_trace_coverage
Сеть метрик
Name: Edge drift: скрытое искажение без изменения KPI
Szenario: Платформа автоматической классификации инцидентов показывала стабильные агрегаты: MTTR 8 минут, silent_p0 4%, manual_review_rate 16% — все в пределах нормы. Но операторы заметили рост "странных" решений: кейсы, ранее отправлявшиеся в manual_review, стали defer'иться на следующую смену.
Aufgabe: Верхнеуровневые метрики не выявляли проблему: MTTR не рос, silent_p0 не превышал порог, manual_review_rate был на границе. Но поведенческий паттерн сместился: модель научилась избегать ответственности через defer вместо auto_close (что ловилось бы silent_p0) или manual_review (что ловилось бы manual_review_floor). Это edge_drift — дрейф распределения решений при неизменных агрегатах.
Lösung: Внедрён детектор edge_drift в compare_drift.py: сравнение матрицы переходов severity и распределения причин закрытия между baseline и new. Порог 0.12. При edge_drift=0.18 (превышение на 50%) — автоматическая блокировка даже при "зелёных" KPI. Добавлено требование: пересчёт сети метрик вместе, не изолированно.
Ergebnis: Блокировка выявила баг в логике приоритизации: новая версия policy давала бонус за defer при неопределённости. Исправление восстановило баланс распределений. edge_drift стал ранним предиктором, ловящим манипуляции до их проявления в guard-метриках.
Gewonnene Erkenntnisse: Агрегатные KPI — лаг-индикаторы; поведенческие паттерны (edge_drift) — лид-индикаторы
Пересчёт метрик изолированно создаёт слепые зоны; только сеть вместе показывает истинную картину
Дрейф может быть не злой намеренностью, а багом — но последствия одинаковы, и CI должен ловить оба
Verwandte Konzepte: edge_drift
Сеть метрик
network_consistency
compare_drift.py
Lerntipps: Начните с практики, не с теории: запустите три дымовых прогона (good/bad/drift) в первый час изучения. Закон Гудхарта понятен на примере, абстрактно — труднее.
Используйте сравнительную таблицу: распечатайте таблицу "Тип решения / Что улучшаем / Что обязано идти в паре" и проверьте свой текущий проект по каждой строке. Пропущенная guard-метрика = сигнал переписать validation.md.
Проведите "вредоносный" эксперимент: ослабьте порог в validation.yaml, убедитесь, что bad-фикстура проходит. Это создаёт мышечную память опасности.
Пишите goodhart-note.md в формате, пригодном для ревью: конкретные числа, воспроизводимые команды, не общие фразы. Проверьте: может ли коллега воспроизвести блокировку по вашему описанию?
Связывайте теорию с частью 20 (антипаттерны SDD): метрики-приманки — частный случай защиты неправильной цели. Перечитайте параллельно для укрепления связей.
Для визуального стиля: нарисуйте flowchart из материала (MTTR -> silent_p0 -> audit_trace_coverage) от руки или в Mermaid. Физическое действие улучшает запоминание связей.
Откладывайте полный трек на потом: сеть метрик, trace-поля, drift-калибровка — справочные. Сфокусируйтесь на трёх инвариантах и красной кнопке для первого прохода.
Используйте qwen CLI для объяснения, но не для замены валидации: запрос "Какой инвариант нельзя обходить при MTTR=290s?" — полезное упражнение, но фактом считается run_validation.py, не ответ LLM.
Zusätzliche Ressourcen: Google sre book — service level objectives: https://sre.google/sre-book/service-level-objectives/ — классическое определение SLO с осторожностью Гудхарта
Wikipedia — goodhart's law: https://en.wikipedia.org/wiki/Goodhart%27s_law — формулировка закона и примеры из разных областей
Github spec kit quickstart: https://github.github.io/spec-kit/quickstart.html — SDD-цикл: спецификация до внедрения
Локальный учебный пример goodhart-validator: book2/examples/goodhart-validator/README.md — runnable-код для всех дымовых прогонов
Приложение d — калибровка порогов: appendix-d-threshold-calibration.md#d4-защита-метрик-от-гудхарта-глава-10 — полная таблица порогов и формулы
Часть 9 первого тома: book/part-09-feature-validation.md — проверка факта, не убедительной прозы
Часть 20 — антипаттерны sdd: book/part-20-sdd-antipatterns.md — каталог манипуляций, против которых защищает сеть метрик
Шаблон validation.md: examples/templates/validation.md — полный набор полей трассировки для production-трека
Zusammenfassung: Главный вывод раздела: метрики полезны как сигналы, но опасны как единственные цели. Надёжный подход — разделить показатели на управляемые KPI и неприкосновенные инварианты качества, закрепить для них проверяемые пороги в validation.md, связать с полями трассировки и блокировать в CI при любом нарушении защитного контура. Учебный минимум: три дымовых прогона (good/bad/drift), фиксация в capstone/goodhart-note.md одной целевой метрики, одной guard-метрики и одного заблокированного примера. Полный трек добавляет сеть метрик, детектор дрейфа и production-интеграцию — но основная защита от Гудхарта работает уже на этом минимуме.