Анализ первопричины (RCA)
Ты инженер, ведущий разбор первопричины. Твоя задача — не описать симптом и не
предложить первый попавшийся фикс, а доказательно установить, ПОЧЕМУ дефект
стал возможен, и предложить как конкретную заплатку, так и системное
предотвращение всего класса проблемы. Тон blameless: разбираем систему и
процесс, а не ищем виноватого — люди действуют рационально в рамках данных им
инструментов и информации.
Дисциплина адверсариальная (как в bug-report-verify): не принимай первую
правдоподобную гипотезу за причину. Каждое звено цепочки «почему» доказывай
кодом (file:line), логом, git-историей или воспроизведением. Гипотеза без
доказательства — это догадка, а не RCA; помечай её как гипотезу, пока не
подтвердил.
ВХОДНЫЕ ДАННЫЕ / SCOPE (как определить периметр)
$ARGUMENTS (или контекст диалога) приходит в одном из видов — определи, какой,
и собери фактуру:
- A. БАГ / ИНЦИДЕНТ В ТРЕКЕРЕ (issue ID или ссылка): получи текст,
комментарии, историю статусов через доступный механизм интеграции —
MCP-инструмент, если подключён (например YouTrack MCP —
youtrack_get_issue; Jira/GitHub/Linear аналогично), иначе попроси
пользователя вставить описание и связанные ссылки. Найди связанные коммиты по
ID тикета: git log --all --grep=<ISSUE-ID> --oneline, затем
git show --stat <hash>.
- B. ЛОГ / СТЕК-ТРЕЙС / АРТЕФАКТ (путь к файлу лога, дампу, трейсу, или
вставленный текст): извлеки точку отказа (исключение, файл:строка, timestamp,
correlation-id), от неё разматывай цепочку в коде.
- C. УПАВШИЙ ТЕСТ (имя теста/путь, или вывод прогона CI): прочитай сам
тест и код под ним; отдели «тест ловит реальный баг» от «тест флейки/
устарел». Прогони локально, если возможно.
- D. ОПИСАНИЕ СИМПТОМА словами (без артефактов): сначала воспроизведи или
собери недостающую фактуру (лог, шаги), не строй RCA на пересказе.
Зафиксируй в начале отчёта SCOPE: что разбираем (симптом одной фразой), какие
артефакты на руках (лог/трейс/тикет/тест/коммиты), какое окружение, временное
окно инцидента. Если фактуры недостаточно, чтобы дойти до причины
доказательно (нет логов, нет доступа к окружению, симптом неясен) — остановись
и перечисли, что нужно собрать, вместо того чтобы гадать.
Периметр шире буквального симптома: включай вызывающий код, потребителей
данных, соседние модули того же класса, конфигурацию и окружение, где это
проявилось.
КЛЮЧЕВОЙ ПРИНЦИП: СИМПТОМ ≠ ПРИЧИНА
Разбор проваливается, когда останавливаются на первом слое («упало из-за
NullPointerException» — это симптом, а не причина). Держи три уровня раздельно:
- Непосредственная причина (proximate) — что технически сломалось в
момент отказа (какая строка кинула исключение, какой запрос вернул не то).
- Корневая причина (root) — почему это стало ВОЗМОЖНО (почему на вход
пришёл null; почему не было валидации; почему контракт разошёлся). Обычно
на 3–5 «почему» глубже симптома.
- Способствующие факторы (contributing) — что усугубило или помогло
пройти незамеченным (отсутствие теста, слабый мониторинг, спешка релиза,
неоднозначное требование).
Правило остановки «почему»: копай, пока следующее «почему» ещё находится в
зоне вашего контроля и подсказывает действие. Останавливайся, когда упёрся во
внешний факт или в осмысленное системное решение. Не превращай 5 Whys в
пальцем-в-небо: каждое звено — доказано, а не предположено.
МЕТОДОЛОГИЯ
Работай по порядку; тяжёлые шаги (разматывание кода, bisect) при большом
объёме делегируй субагентам через Agent tool, передав им конкретные пути и
разделы этого скилла.
- Собери timeline инцидента. Восстанови хронологию по фактам: когда
задеплоили что / когда появились первые ошибки (логи, метрики, алерты) /
когда заметили / что делали при разборе / когда стабилизировали. Timeline
часто сам указывает на вводящее изменение (ошибки начались через 10 минут
после деплоя X).
- Точно зафиксируй симптом. Что именно наблюдается, воспроизводимо ли,
при каких входных данных/окружении. Если можешь — воспроизведи минимально
(тест/скрипт/запрос) и зафиксируй фактический результат. Невоспроизводимость
— тоже факт (гонка, специфичные данные, только прод).
- 5 Whys — доказательно. Построй цепочку от симптома вглубь. На КАЖДОЕ
«почему» приложи доказательство (file:line, лог, git). Пример скелета:
- Почему упал запрос? → БД вернула 0 строк, код не обработал пустой список
(
service/x.py:42).
- Почему пришёл пустой список? → фильтр по company_id получил None.
- Почему None? → контекст запроса не прокинул tenant в фоновую задачу.
- Почему не прокинул? → фоновой воркер добавлен позже основного контекста и
не подхватил middleware (
worker/y.py:88, коммит abc123).
- Почему это не заметили? → нет теста на фоновый путь с изоляцией тенанта.
Первая и последняя строки — вход для разных выводов (фикс и предотвращение).
- Ishikawa / fishbone — проверь все категории причин, чтобы не
зациклиться на «это код виноват». Пройди по категориям и отметь вклад
каждой (или явно «не при чём»):
- Код — логика, обработка ошибок, контракт/типы, конкурентность.
- Данные — некорректные/неожиданные/«грязные» данные, миграция,
граничные значения, объём.
- Конфигурация — флаги, env, лимиты, таймауты, отличие сред.
- Окружение / инфра — версия рантайма, сеть, ресурсы (OOM/CPU), внешний
сервис, деплой.
- Процесс — ревью, тестирование, релизный процесс, откат.
- Требования — неоднозначное/неполное/противоречивое ТЗ, не тот кейс
реализован.
- Человеческий фактор — но blameless: не «Вася ошибся», а «система
позволила совершить и не поймать эту ошибку».
- Локализуй вводящее изменение в коде. Если баг — регрессия: найди
коммит, который её ввёл.
git log -p -- <файл>, git blame <файл> -L <строки>, при воспроизводимости — git bisect start / bad / good <ref>,
чтобы бинарным поиском выйти на коммит. Зафиксируй хеш, автора-контекст (без
обвинения), что именно изменилось и почему тогда это выглядело безопасно.
- Раздели три уровня причин (непосредственная / корневая /
способствующие) явно — это ядро вывода.
- «Почему не поймали?» — отдельный обязательный разбор. Чего не хватило,
чтобы дефект не дошёл до прода:
- какого теста (юнит/интеграционного/E2E/регрессионного) не было или он не
покрывал этот кейс/ветку/границу;
- какой проверки на ревью/линте/типах/контракте не хватило;
- какого гейта в CI/мониторинга/алерта не хватило, чтобы поймать раньше.
Этот блок — прямой вход для скиллов проектирования тестов и анализа
покрытия (
test-case-design, анализ пробелов покрытия): сформулируй
конкретно, какой тест/проверку добавить.
- Рекомендации на двух уровнях:
- Локальный фикс — что конкретно поправить, чтобы устранить этот
дефект (file:line, суть изменения). НЕ вноси правку сам — это read-only
разбор.
- Системное предотвращение класса — что не даст всему классу таких
проблем повториться: недостающий тест, линт-правило, типовой контракт,
CI-гейт, изменение процесса/шаблона, дефолт конфигурации. Именно этот
уровень отличает RCA от «просто починили».
РАЗЛИЧЕНИЕ: РЕАЛЬНЫЙ БАГ vs ФЛЕЙКИ / АРТЕФАКТ ТЕСТА
Если вход — упавший тест, прежде чем строить RCA продукта, докажи, что баг в
продукте, а не в тесте:
- воспроизводится ли падение стабильно или мигает (флейки: таймауты, гонки,
зависимость от порядка/времени/внешнего сервиса, незамоканный рандом/дата);
- не устарел ли сам тест (ассерт под старое поведение, которое осознанно
изменили) — тогда причина в тесте/процессе обновления тестов, не в продукте;
- не общий ли это ресурс между тестами (shared state, не изолированная БД).
Квалифицируй явно: «баг в продукте» / «баг в тесте» / «флейки-инфраструктура».
EDGE CASES, КОТОРЫЕ ЧАСТО ПРОПУСКАЮТ ПРИ RCA
- Остановились на непосредственной причине и назвали её корневой (починили
симптом, класс проблемы остался).
- Единственная «причина» при нескольких способствующих факторах — у инцидентов
редко одна причина; фикс одной не закрывает окно, если остальные на месте.
- Confirmation bias: нашли правдоподобную гипотезу и перестали копать, не
опровергнув альтернативы. Активно ищи опровержение своей версии.
- «Причина» = последний коммит по времени, без bisect-доказательства, что
именно он вводит дефект (могли совпасть два изменения).
- Латентный баг: код с дефектом жил давно, «сломало» его изменение ДАННЫХ/
нагрузки/конфигурации, а не коммит в этом файле — не вешай вину на невиновный
коммит.
- Причина в окружении/конфиге (отличие prod от staging), а разбор ведётся
только по коду.
- Гонка/конкурентность: воспроизводится только под нагрузкой; «не могу
повторить локально» ≠ «бага нет».
- Внешняя зависимость (сторонний API/сервис изменил поведение) — корневая
причина вне вашего кода, но предотвращение (таймаут/ретрай/деградация) —
внутри.
- Каскад: первичный отказ вызвал вторичные; не прими вторичный симптом за
корень. Идентифицируй первое звено по timeline.
- «Почему не поймали» подменяют на «добавим ещё тестов вообще» — нужен
КОНКРЕТНЫЙ недостающий кейс/граница/ветка, а не лозунг.
- Blame вместо blameless: вывод «человек был невнимателен» не подсказывает
системного действия и вредит культуре — переформулируй в термины системы.
- Фикс уже был, но не помог/откатили — разбери, почему предыдущая гипотеза
причины была неверна (это само по себе находка).
КРИТЕРИИ КАЧЕСТВА RCA (DoD)
RCA считается завершённым, только если:
- симптом воспроизведён ИЛИ явно объяснено, почему воспроизведение невозможно;
- цепочка «почему» доведена до уровня, где следующий шаг — уже внешний факт
или системное решение, и КАЖДОЕ звено доказано;
- разделены непосредственная / корневая / способствующие причины;
- есть раздел «почему не поймали» с конкретным пробелом контроля;
- рекомендации даны на ДВУХ уровнях (заплатка + предотвращение класса);
- action items имеют владельца (или пометку «владелец не определён —
требуется назначить») и приоритет.
ФОРМАТ ОТЧЁТА (постмортем)
Сохрани отчёт в docs/qa/rca/<incident-slug>.md (slug — по ID инцидента/
тикета или короткому имени). Перед созданием проверь структуру репозитория и
следуй ей; docs/qa/rca/ — дефолт. Если разбор по этому инциденту уже есть —
дополняй, а не пересоздавай.
Структура постмортема:
- Краткое резюме — что произошло, кого/что задело, каков был масштаб и
длительность, какова корневая причина одной фразой. Без жаргона, читаемо
для менеджмента.
- SCOPE / входные данные — что разбирали, какие артефакты на руках,
окружение, временное окно.
- Timeline — хронология по фактам с timestamp (деплой → первые ошибки →
обнаружение → стабилизация).
- Симптом — что наблюдалось, воспроизводимость, входные данные.
- Анализ причин — 5 Whys (с доказательствами по каждому звену) +
fishbone-разбивка по категориям; явно: непосредственная / корневая /
способствующие. Вводящий коммит (хеш) при регрессии.
- Почему не поймали — конкретный пробел в тестах/ревью/CI/мониторинге.
- Рекомендации — таблица: заплатка (локальный фикс) и системное
предотвращение класса; для каждого — уровень, суть, ссылка на file:line
если применимо.
- Action items — список действий с владельцем и приоритетом (P0..P3);
тесты/гейты, которые надо добавить, вынеси отдельно как вход для
test-case-design/анализа покрытия.
- Что не проверено / ограничения — нет доступа к прод-логам, не
воспроизвёл вживую, гипотезы, оставшиеся недоказанными (пометь как
гипотезы, а не факты).
ПРАВИЛА ОФОРМЛЕНИЯ
- Каждое звено причинной цепочки — со ссылкой на доказательство (file:line,
лог с timestamp/строкой, git-хеш, результат воспроизведения). Недоказанное
помечай словом «гипотеза».
- Blameless: формулируй в терминах системы/процесса, не личностей.
- Разделяй факт и вывод: «в логе X» (факт) vs «вероятно, из-за Y» (вывод).
- Action items без владельца бесполезны — если владелец неизвестен, так и
напиши «назначить владельца», не оставляй пустым.
Это разбор, а не имплементация: фикс и предотвращающие изменения вносит
команда по итогам RCA — код в рамках этого скилла не правь (временные
скрипты/тесты для воспроизведения удали после проверки).
1---2name: root-cause-analysis-23description: Анализ первопричины (RCA) дефекта, инцидента или упавшего теста по фактам — доказывая причину кодом/логами/воспроизведением, а не угадывая, с разделением непосредственной и корневой причины, техниками 5 Whys и Ishikawa/fishbone, локализацией вводящего коммита через git bisect и отдельным разбором «почему это не поймали тесты». Используй когда просят найти первопричину бага/инцидента, сделать RCA, разобрать «почему это сломалось на самом деле», провести 5 почему, написать постмортем по инциденту, понять как дефект прошёл мимо тестов и ревью, или почему фикс не помог. Работает с любым трекером (Jira/YouTrack/GitHub Issues/Linear) через доступный MCP-инструмент или вставленные данные. Это НЕ `bug-report-verify` (тот доказывает, что баг реален) и не `bugfix-audit` (тот проверяет уже сделанный фикс) — здесь цель установить и доказать ПРИЧИНУ, а также системно предотвратить класс проблемы. Срабатывай даже без слова «RCA», например «почему вообще это могло произойти», «докопайся до корня», «как такое утекло в прод».4---56# Анализ первопричины (RCA)78Ты инженер, ведущий разбор первопричины. Твоя задача — не описать симптом и не9предложить первый попавшийся фикс, а доказательно установить, ПОЧЕМУ дефект10стал возможен, и предложить как конкретную заплатку, так и системное11предотвращение всего класса проблемы. Тон blameless: разбираем систему и12процесс, а не ищем виноватого — люди действуют рационально в рамках данных им13инструментов и информации.1415Дисциплина адверсариальная (как в `bug-report-verify`): не принимай первую16правдоподобную гипотезу за причину. Каждое звено цепочки «почему» доказывай17кодом (file:line), логом, git-историей или воспроизведением. Гипотеза без18доказательства — это догадка, а не RCA; помечай её как гипотезу, пока не19подтвердил.2021## ВХОДНЫЕ ДАННЫЕ / SCOPE (как определить периметр)2223`$ARGUMENTS` (или контекст диалога) приходит в одном из видов — определи, какой,24и собери фактуру:2526- **A. БАГ / ИНЦИДЕНТ В ТРЕКЕРЕ** (issue ID или ссылка): получи текст,27 комментарии, историю статусов через доступный механизм интеграции —28 MCP-инструмент, если подключён (например YouTrack MCP —29 `youtrack_get_issue`; Jira/GitHub/Linear аналогично), иначе попроси30 пользователя вставить описание и связанные ссылки. Найди связанные коммиты по31 ID тикета: `git log --all --grep=<ISSUE-ID> --oneline`, затем32 `git show --stat <hash>`.33- **B. ЛОГ / СТЕК-ТРЕЙС / АРТЕФАКТ** (путь к файлу лога, дампу, трейсу, или34 вставленный текст): извлеки точку отказа (исключение, файл:строка, timestamp,35 correlation-id), от неё разматывай цепочку в коде.36- **C. УПАВШИЙ ТЕСТ** (имя теста/путь, или вывод прогона CI): прочитай сам37 тест и код под ним; отдели «тест ловит реальный баг» от «тест флейки/38 устарел». Прогони локально, если возможно.39- **D. ОПИСАНИЕ СИМПТОМА словами** (без артефактов): сначала воспроизведи или40 собери недостающую фактуру (лог, шаги), не строй RCA на пересказе.4142Зафиксируй в начале отчёта SCOPE: что разбираем (симптом одной фразой), какие43артефакты на руках (лог/трейс/тикет/тест/коммиты), какое окружение, временное44окно инцидента. Если фактуры недостаточно, чтобы дойти до причины45доказательно (нет логов, нет доступа к окружению, симптом неясен) — остановись46и перечисли, что нужно собрать, вместо того чтобы гадать.4748Периметр шире буквального симптома: включай вызывающий код, потребителей49данных, соседние модули того же класса, конфигурацию и окружение, где это50проявилось.5152## КЛЮЧЕВОЙ ПРИНЦИП: СИМПТОМ ≠ ПРИЧИНА5354Разбор проваливается, когда останавливаются на первом слое («упало из-за55NullPointerException» — это симптом, а не причина). Держи три уровня раздельно:56571. **Непосредственная причина (proximate)** — что технически сломалось в58 момент отказа (какая строка кинула исключение, какой запрос вернул не то).592. **Корневая причина (root)** — почему это стало ВОЗМОЖНО (почему на вход60 пришёл null; почему не было валидации; почему контракт разошёлся). Обычно61 на 3–5 «почему» глубже симптома.623. **Способствующие факторы (contributing)** — что усугубило или помогло63 пройти незамеченным (отсутствие теста, слабый мониторинг, спешка релиза,64 неоднозначное требование).6566Правило остановки «почему»: копай, пока следующее «почему» ещё находится в67зоне вашего контроля и подсказывает действие. Останавливайся, когда упёрся во68внешний факт или в осмысленное системное решение. Не превращай 5 Whys в69пальцем-в-небо: каждое звено — доказано, а не предположено.7071## МЕТОДОЛОГИЯ7273Работай по порядку; тяжёлые шаги (разматывание кода, bisect) при большом74объёме делегируй субагентам через Agent tool, передав им конкретные пути и75разделы этого скилла.76771. **Собери timeline инцидента.** Восстанови хронологию по фактам: когда78 задеплоили что / когда появились первые ошибки (логи, метрики, алерты) /79 когда заметили / что делали при разборе / когда стабилизировали. Timeline80 часто сам указывает на вводящее изменение (ошибки начались через 10 минут81 после деплоя X).822. **Точно зафиксируй симптом.** Что именно наблюдается, воспроизводимо ли,83 при каких входных данных/окружении. Если можешь — воспроизведи минимально84 (тест/скрипт/запрос) и зафиксируй фактический результат. Невоспроизводимость85 — тоже факт (гонка, специфичные данные, только прод).863. **5 Whys — доказательно.** Построй цепочку от симптома вглубь. На КАЖДОЕ87 «почему» приложи доказательство (file:line, лог, git). Пример скелета:88 - Почему упал запрос? → БД вернула 0 строк, код не обработал пустой список89 (`service/x.py:42`).90 - Почему пришёл пустой список? → фильтр по company_id получил None.91 - Почему None? → контекст запроса не прокинул tenant в фоновую задачу.92 - Почему не прокинул? → фоновой воркер добавлен позже основного контекста и93 не подхватил middleware (`worker/y.py:88`, коммит abc123).94 - Почему это не заметили? → нет теста на фоновый путь с изоляцией тенанта.95 Первая и последняя строки — вход для разных выводов (фикс и предотвращение).964. **Ishikawa / fishbone — проверь все категории причин**, чтобы не97 зациклиться на «это код виноват». Пройди по категориям и отметь вклад98 каждой (или явно «не при чём»):99 - **Код** — логика, обработка ошибок, контракт/типы, конкурентность.100 - **Данные** — некорректные/неожиданные/«грязные» данные, миграция,101 граничные значения, объём.102 - **Конфигурация** — флаги, env, лимиты, таймауты, отличие сред.103 - **Окружение / инфра** — версия рантайма, сеть, ресурсы (OOM/CPU), внешний104 сервис, деплой.105 - **Процесс** — ревью, тестирование, релизный процесс, откат.106 - **Требования** — неоднозначное/неполное/противоречивое ТЗ, не тот кейс107 реализован.108 - **Человеческий фактор** — но blameless: не «Вася ошибся», а «система109 позволила совершить и не поймать эту ошибку».1105. **Локализуй вводящее изменение в коде.** Если баг — регрессия: найди111 коммит, который её ввёл. `git log -p -- <файл>`, `git blame <файл> -L112 <строки>`, при воспроизводимости — `git bisect start / bad / good <ref>`,113 чтобы бинарным поиском выйти на коммит. Зафиксируй хеш, автора-контекст (без114 обвинения), что именно изменилось и почему тогда это выглядело безопасно.1156. **Раздели три уровня причин** (непосредственная / корневая /116 способствующие) явно — это ядро вывода.1177. **«Почему не поймали?»** — отдельный обязательный разбор. Чего не хватило,118 чтобы дефект не дошёл до прода:119 - какого теста (юнит/интеграционного/E2E/регрессионного) не было или он не120 покрывал этот кейс/ветку/границу;121 - какой проверки на ревью/линте/типах/контракте не хватило;122 - какого гейта в CI/мониторинга/алерта не хватило, чтобы поймать раньше.123 Этот блок — прямой вход для скиллов проектирования тестов и анализа124 покрытия (`test-case-design`, анализ пробелов покрытия): сформулируй125 конкретно, какой тест/проверку добавить.1268. **Рекомендации на двух уровнях:**127 - **Локальный фикс** — что конкретно поправить, чтобы устранить этот128 дефект (file:line, суть изменения). НЕ вноси правку сам — это read-only129 разбор.130 - **Системное предотвращение класса** — что не даст всему классу таких131 проблем повториться: недостающий тест, линт-правило, типовой контракт,132 CI-гейт, изменение процесса/шаблона, дефолт конфигурации. Именно этот133 уровень отличает RCA от «просто починили».134135## РАЗЛИЧЕНИЕ: РЕАЛЬНЫЙ БАГ vs ФЛЕЙКИ / АРТЕФАКТ ТЕСТА136137Если вход — упавший тест, прежде чем строить RCA продукта, докажи, что баг в138продукте, а не в тесте:139- воспроизводится ли падение стабильно или мигает (флейки: таймауты, гонки,140 зависимость от порядка/времени/внешнего сервиса, незамоканный рандом/дата);141- не устарел ли сам тест (ассерт под старое поведение, которое осознанно142 изменили) — тогда причина в тесте/процессе обновления тестов, не в продукте;143- не общий ли это ресурс между тестами (shared state, не изолированная БД).144Квалифицируй явно: «баг в продукте» / «баг в тесте» / «флейки-инфраструктура».145146## EDGE CASES, КОТОРЫЕ ЧАСТО ПРОПУСКАЮТ ПРИ RCA147148- Остановились на непосредственной причине и назвали её корневой (починили149 симптом, класс проблемы остался).150- Единственная «причина» при нескольких способствующих факторах — у инцидентов151 редко одна причина; фикс одной не закрывает окно, если остальные на месте.152- Confirmation bias: нашли правдоподобную гипотезу и перестали копать, не153 опровергнув альтернативы. Активно ищи опровержение своей версии.154- «Причина» = последний коммит по времени, без bisect-доказательства, что155 именно он вводит дефект (могли совпасть два изменения).156- Латентный баг: код с дефектом жил давно, «сломало» его изменение ДАННЫХ/157 нагрузки/конфигурации, а не коммит в этом файле — не вешай вину на невиновный158 коммит.159- Причина в окружении/конфиге (отличие prod от staging), а разбор ведётся160 только по коду.161- Гонка/конкурентность: воспроизводится только под нагрузкой; «не могу162 повторить локально» ≠ «бага нет».163- Внешняя зависимость (сторонний API/сервис изменил поведение) — корневая164 причина вне вашего кода, но предотвращение (таймаут/ретрай/деградация) —165 внутри.166- Каскад: первичный отказ вызвал вторичные; не прими вторичный симптом за167 корень. Идентифицируй первое звено по timeline.168- «Почему не поймали» подменяют на «добавим ещё тестов вообще» — нужен169 КОНКРЕТНЫЙ недостающий кейс/граница/ветка, а не лозунг.170- Blame вместо blameless: вывод «человек был невнимателен» не подсказывает171 системного действия и вредит культуре — переформулируй в термины системы.172- Фикс уже был, но не помог/откатили — разбери, почему предыдущая гипотеза173 причины была неверна (это само по себе находка).174175## КРИТЕРИИ КАЧЕСТВА RCA (DoD)176177RCA считается завершённым, только если:178- симптом воспроизведён ИЛИ явно объяснено, почему воспроизведение невозможно;179- цепочка «почему» доведена до уровня, где следующий шаг — уже внешний факт180 или системное решение, и КАЖДОЕ звено доказано;181- разделены непосредственная / корневая / способствующие причины;182- есть раздел «почему не поймали» с конкретным пробелом контроля;183- рекомендации даны на ДВУХ уровнях (заплатка + предотвращение класса);184- action items имеют владельца (или пометку «владелец не определён —185 требуется назначить») и приоритет.186187## ФОРМАТ ОТЧЁТА (постмортем)188189Сохрани отчёт в `docs/qa/rca/<incident-slug>.md` (slug — по ID инцидента/190тикета или короткому имени). Перед созданием проверь структуру репозитория и191следуй ей; `docs/qa/rca/` — дефолт. Если разбор по этому инциденту уже есть —192дополняй, а не пересоздавай.193194Структура постмортема:1951961. **Краткое резюме** — что произошло, кого/что задело, каков был масштаб и197 длительность, какова корневая причина одной фразой. Без жаргона, читаемо198 для менеджмента.1992. **SCOPE / входные данные** — что разбирали, какие артефакты на руках,200 окружение, временное окно.2013. **Timeline** — хронология по фактам с timestamp (деплой → первые ошибки →202 обнаружение → стабилизация).2034. **Симптом** — что наблюдалось, воспроизводимость, входные данные.2045. **Анализ причин** — 5 Whys (с доказательствами по каждому звену) +205 fishbone-разбивка по категориям; явно: непосредственная / корневая /206 способствующие. Вводящий коммит (хеш) при регрессии.2076. **Почему не поймали** — конкретный пробел в тестах/ревью/CI/мониторинге.2087. **Рекомендации** — таблица: заплатка (локальный фикс) и системное209 предотвращение класса; для каждого — уровень, суть, ссылка на file:line210 если применимо.2118. **Action items** — список действий с владельцем и приоритетом (P0..P3);212 тесты/гейты, которые надо добавить, вынеси отдельно как вход для213 `test-case-design`/анализа покрытия.2149. **Что не проверено / ограничения** — нет доступа к прод-логам, не215 воспроизвёл вживую, гипотезы, оставшиеся недоказанными (пометь как216 гипотезы, а не факты).217218## ПРАВИЛА ОФОРМЛЕНИЯ219220- Каждое звено причинной цепочки — со ссылкой на доказательство (file:line,221 лог с timestamp/строкой, git-хеш, результат воспроизведения). Недоказанное222 помечай словом «гипотеза».223- Blameless: формулируй в терминах системы/процесса, не личностей.224- Разделяй факт и вывод: «в логе X» (факт) vs «вероятно, из-за Y» (вывод).225- Action items без владельца бесполезны — если владелец неизвестен, так и226 напиши «назначить владельца», не оставляй пустым.227228Это разбор, а не имплементация: фикс и предотвращающие изменения вносит229команда по итогам RCA — код в рамках этого скилла не правь (временные230скрипты/тесты для воспроизведения удали после проверки).231