Files
progcode/editorial/agent-rewrites/149.json
T
huncode 2d914b543f
Build and deploy / deploy (push) Failing after 15s
Publish rewritten technical article archive
2026-08-02 22:19:34 +03:00

8 lines
18 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"index": 149,
"slug": "editorial-2023-11-mechanism-postmortem",
"title": "Postmortem без заднего знания: как связать факт, решение и действие",
"excerpt": "После сбоя команда легко принимает позднюю гипотезу за причину. Разбираем временную границу знания, контракт записей и проверяемый профилактический шаг.",
"contentHtml": "<p>После сбоя в чате появляется короткое объяснение: «релиз сломал обработку, поэтому инженер откатил его». В одной фразе смешаны событие, причина, решение и оценка. Но в момент отката команда могла не знать, был ли виноват релиз. Она могла видеть только рост ошибок и доступный способ остановить поток.</p>\n<p>Цена ошибки — не неточная формулировка. Команда ставит защиту вокруг самого заметного элемента истории. Она добавляет проверку к релизу, хотя сбой мог возникнуть из-за данных, лимита или внешней зависимости. Следующий разбор повторяет ту же подмену. Postmortem становится рассказом задним числом, а не инструментом изменения системы.</p>\n<p>Рабочая модель разделяет три записи: наблюдаемый факт, решение с доступной в тот момент информацией и будущую проверку гипотезы. Время ограничивает вывод. Поздний лог может объяснить событие, но не доказывает, что этот лог был доступен оператору при выборе. Так документ сохраняет неизвестное и показывает, какое действие нужно проверить.</p>\n<h2>Граница между фактом и объяснением</h2>\n<p>Факт описывает то, что можно привязать к источнику: время, сигнал, значение поля, изменение состояния. Он не обязан содержать причину. Запись «в 10:03 доля ответов 5xx превысила порог» сильнее записи «сервис упал из-за релиза», если связь с релизом ещё не проверена.</p>\n<p>Решение описывает действие и снимок доступных фактов. Его нельзя оценивать полным набором данных, который появился позже. Иначе документ наказывает человека за информацию, которой у него не было, и скрывает вопрос к системе: почему нужный сигнал, инструкция или безопасный способ остановки не были доступны раньше.</p>\n<p>Эксперимент переводит гипотезу в проверяемую работу. Он должен назвать один риск, способ проверки, критерий успеха и обратный путь. Фраза «добавить больше мониторинга» не даёт критерия. Фраза «для этого маршрута появляется alert при трёх последовательных ошибках, а дежурный подтверждает его в тестовом окружении» уже задаёт проверку формы. Она всё ещё не доказывает эффект в production.</p>\n<table><caption>Как разобрать спорную фразу postmortem</caption><thead><tr><th scope=\"col\">Слой</th><th scope=\"col\">Что записать</th><th scope=\"col\">Что не утверждать</th></tr></thead><tbody><tr><td>Факт</td><td>Время, наблюдение и ссылка на лог, метрику или change.</td><td>«Это точно причина» без проверки связи.</td></tr><tr><td>Решение</td><td>Действие и факты, доступные до него.</td><td>Оценку через поздние данные.</td></tr><tr><td>Гипотеза</td><td>Какой механизм нужно проверить.</td><td>Причину, если она пока только предполагается.</td></tr><tr><td>Эксперимент</td><td>Критерий, владелец роли и rollback.</td><td>Обещание предотвратить любой повтор.</td></tr></tbody></table>\n<h2>Механизм: время ограничивает допустимый вывод</h2>\n<p>У каждой записи есть <code>occurredAt</code>. У решения есть <code>availableFactIds</code>. В список попадают только факты, которые уже существовали до решения. Это простое правило удерживает границу знания. Новая запись может изменить гипотезу о причине, но не меняет набор данных, на котором приняли исходное решение.</p>\n<p>Рассмотрим учебный пример. Он не читает реальные логи и не описывает настоящий инцидент. В нём зафиксированы три факта, решение остановить проверку изменения и эксперимент с обратным путём.</p>\n<pre><code>{\n \"facts\": [\n {\"id\": \"f-01\", \"at\": \"10:00\", \"text\": \"доля ответов 5xx выросла\", \"source\": \"metric-card-01\"},\n {\"id\": \"f-02\", \"at\": \"10:03\", \"text\": \"изменена версия конфигурации\", \"source\": \"change-02\"}\n ],\n \"decision\": {\n \"at\": \"10:05\",\n \"action\": \"остановить продвижение\",\n \"availableFactIds\": [\"f-01\", \"f-02\"]\n },\n \"experiment\": {\n \"hypothesis\": \"явная проверка версии сократит время обнаружения\",\n \"successCriterion\": \"проверка видна в тестовом сценарии\",\n \"rollback\": \"удалить проверку и вернуть прежнюю конфигурацию\"\n }\n}</code></pre>\n<p>Код показывает форму, а не результат. В реальном документе <code>source</code> должен указывать разрешённый артефакт, который команда действительно может открыть. Время должно использовать одну часовую зону. Если источник недоступен, это нужно записать как ограничение, а не заменить догадкой.</p>\n<p>Модель допускает, что причиной окажется не изменение версии. Например, поздняя проверка покажет исчерпанный лимит внешнего сервиса. Тогда факты и исходное решение остаются полезными. Меняется гипотеза и, возможно, эксперимент. Нельзя переписать факт так, чтобы он заранее подтверждал новую версию.</p>\n<figure><img src=\"/assets/editorial/2023/postmortem-2023-decision-record.svg\" alt=\"Схема связывает факты с решением, а решение — с ограниченным профилактическим экспериментом; ветка с именем виновника перечёркнута\" loading=\"lazy\" /><figcaption>Учебная схема границ postmortem: факты входят в решение только через доступную временную последовательность, а профилактика получает критерий и rollback. Рисунок не показывает настоящий инцидент.</figcaption></figure>\n<h2>Симптом → причина → проверка → действие</h2>\n<table><caption>Диагностическая матрица для разбора</caption><thead><tr><th scope=\"col\">Симптом</th><th scope=\"col\">Вероятная причина записи</th><th scope=\"col\">Проверка</th><th scope=\"col\">Действие</th></tr></thead><tbody><tr><td>В первом абзаце назван виновник.</td><td>Имя человека используется как объяснение состояния.</td><td>Убрать имя и спросить, какое условие системы нужно изменить.</td><td>Записать владельца будущего действия отдельно от причины.</td></tr><tr><td>Решение выглядит очевидным после чтения всей timeline.</td><td>К решению добавили факты, появившиеся позже.</td><td>Сравнить время решения с каждым <code>availableFactId</code>.</td><td>Оставить только предшествующие факты и сохранить unknown.</td></tr><tr><td>Action item звучит как «добавить мониторинг».</td><td>Гипотеза не имеет измеримого критерия.</td><td>Спросить, какой артефакт должен измениться и как увидеть проход.</td><td>Указать сигнал, порог, владельца роли и rollback.</td></tr><tr><td>После исправления обещают отсутствие повторов.</td><td>Учебная проверка выдана за production-результат.</td><td>Найти источник эффекта и период наблюдения.</td><td>Сузить вывод до «проверяет форму» или собрать реальные данные.</td></tr></tbody></table>\n<h2>Как писать решение без поиска виноватого</h2>\n<p>Отсутствие поиска виноватого не отменяет ответственности. В документе должны быть владельцы действий, сроки и правила эскалации. Но роль владельца отвечает на вопрос «кто доведёт изменение», а не на вопрос «почему система оказалась в таком состоянии». Для второго вопроса нужны условия: доступный сигнал, версия инструкции, права, лимит, автоматическая защита или отсутствие безопасной остановки.</p>\n<p>Полезно отделить две оценки. Первая: было ли действие разумным при доступной информации? Вторая: какие условия сделали такой выбор вероятным? Первая требует воспроизвести границу знания. Вторая ведёт к изменению интерфейса, runbook, алерта или архитектуры. Поздняя причина может помочь второй оценке, но не должна подменять первую.</p>\n<p>Отрицательный путь важен не меньше положительного. Если источник не открывается, поле остаётся неизвестным. Если rollback нельзя выполнить безопасно, эксперимент не готов. Если критерий нельзя проверить без production-доступа, нужно сначала спроектировать безопасную проверку или признать границу. Документ не должен заполнять пробелы уверенным тоном.</p>\n<h2>Порядок действий</h2>\n<ol><li>Запишите наблюдаемый симптом с временем, системой и доступным источником.</li><li>Отделите факт от слов «вызвал», «из-за», «виноват» и «предотвратит». Эти слова требуют отдельного доказательства.</li><li>Соберите решение как снимок: действие, время и полный список фактов, известных до выбора.</li><li>Проверьте временной порядок и единую часовую зону. Удалите из контекста решения все поздние записи.</li><li>Сформулируйте одну гипотезу о защите. Не превращайте список идей в план без критерия.</li><li>Добавьте бинарный или наблюдаемый критерий, владельца роли, границы доступа и rollback.</li><li>Проверьте учебную форму отдельно от production-эффекта. Успешная проверка JSON или документа не доказывает снижение числа инцидентов.</li><li>Закройте разбор только после того, как читатель, не участвовавший в инциденте, сможет восстановить факт, решение и следующий проверяемый шаг.</li></ol>\n<h2>Ограничения</h2>\n<p>Эта модель не заменяет incident command, расследование безопасности, юридическую оценку или правила хранения персональных данных. В security-контуре источники и доступы требуют отдельной политики. В распределённой системе часы могут расходиться, а источник может измениться после события. Тогда нужно хранить версию артефакта, часовой пояс и допустимый уровень точности.</p>\n<p>Три слоя не доказывают причинность. Они только не дают написать вывод шире доступных данных. Причинную связь проверяют отдельными методами: воспроизведением, сравнением изменений, экспериментом или анализом данных. Если эти методы недоступны, корректная формулировка — «причина не подтверждена».</p>\n<p>Учебный JSON выше фиксирует структуру и отрицательный путь. Он не запускается на настоящей инфраструктуре, не читает метрики и не измеряет влияние. Не переносите его идентификаторы, время и критерий в production без адаптации к своим источникам, ролям и процедурам отката.</p>\n<h2>Проверяемый критерий готовности</h2>\n<p>Postmortem готов к техническому review, если независимый читатель может открыть источник каждого факта, увидеть, что решение ссылается только на предшествующую информацию, и проверить один профилактический эксперимент по его критерию. Если хотя бы один пункт не выполняется, статус должен быть «не готов», а следующий шаг — устранение конкретного пробела: источник, временная граница, критерий или rollback.</p>\n<h2>Проверяемые источники</h2>\n<ul><li><a href=\"https://sre.google/sre-book/postmortem-culture/\" target=\"_blank\" rel=\"noopener noreferrer\">Google SRE Book: Postmortem Culture: Learning from Failure</a> — официальный материал о документировании инцидента, contributing causes и follow-up; он описывает практику Google и не доказывает эффект этой модели для любой команды.</li><li><a href=\"https://sre.google/sre-book/example-postmortem/\" target=\"_blank\" rel=\"noopener noreferrer\">Google SRE Book: Example Postmortem</a> — официальный учебный пример с timeline и action items; он показывает форму документа, а не данные конкретного инцидента.</li><li><a href=\"https://csrc.nist.gov/pubs/sp/800/61/r2/final\" target=\"_blank\" rel=\"noopener noreferrer\">NIST SP 800-61 Revision 2: Computer Security Incident Handling Guide</a> — официальное руководство для security incident response и lessons learned; его область не распространяется автоматически на любой эксплуатационный разбор.</li></ul>"
}