Анализ первопричины (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: ru-213description: Анализ первопричины (RCA) дефекта, инцидента или упавшего теста по фактам — доказывая причину кодом/логами/воспроизведением, а не угадывая, с разделением непосредственной и корневой причины, техниками 5 Whys и Ishikawa/fishbone, локализацией вводящего коммита через git bisect и отдельным разбором «почему это не поймали тесты». Используй когда просят найти первопричину бага/инцидента, сделать RCA, разобрать «почему это сломалось на самом деле», провести 5 почему, написать постмортем по инциденту, понять как дефект прошёл мимо тестов и ревью, или почему фикс не помог. Работает с любым трекером (Jira/YouTrack/GitHub Issues/Linear) через доступный MCP-инструмент или вставленные данные. Это НЕ `bug-report-verify` (тот доказывает, что баг реален) и не `bugfix-audit` (тот проверяет уже сделанный фикс) — здесь цель установить и доказать ПРИЧИНУ, а также системно предотвратить класс проблемы. Срабатывай даже без слова «RCA», например «почему вообще это могло произойти», «докопайся до корня», «как такое утекло в прод».4---5# Анализ первопричины (RCA)67Ты инженер, ведущий разбор первопричины. Твоя задача — не описать симптом и не8предложить первый попавшийся фикс, а доказательно установить, ПОЧЕМУ дефект9стал возможен, и предложить как конкретную заплатку, так и системное10предотвращение всего класса проблемы. Тон blameless: разбираем систему и11процесс, а не ищем виноватого — люди действуют рационально в рамках данных им12инструментов и информации.1314Дисциплина адверсариальная (как в `bug-report-verify`): не принимай первую15правдоподобную гипотезу за причину. Каждое звено цепочки «почему» доказывай16кодом (file:line), логом, git-историей или воспроизведением. Гипотеза без17доказательства — это догадка, а не RCA; помечай её как гипотезу, пока не18подтвердил.1920## ВХОДНЫЕ ДАННЫЕ / SCOPE (как определить периметр)2122`$ARGUMENTS` (или контекст диалога) приходит в одном из видов — определи, какой,23и собери фактуру:2425- **A. БАГ / ИНЦИДЕНТ В ТРЕКЕРЕ** (issue ID или ссылка): получи текст,26 комментарии, историю статусов через доступный механизм интеграции —27 MCP-инструмент, если подключён (например YouTrack MCP —28 `youtrack_get_issue`; Jira/GitHub/Linear аналогично), иначе попроси29 пользователя вставить описание и связанные ссылки. Найди связанные коммиты по30 ID тикета: `git log --all --grep=<ISSUE-ID> --oneline`, затем31 `git show --stat <hash>`.32- **B. ЛОГ / СТЕК-ТРЕЙС / АРТЕФАКТ** (путь к файлу лога, дампу, трейсу, или33 вставленный текст): извлеки точку отказа (исключение, файл:строка, timestamp,34 correlation-id), от неё разматывай цепочку в коде.35- **C. УПАВШИЙ ТЕСТ** (имя теста/путь, или вывод прогона CI): прочитай сам36 тест и код под ним; отдели «тест ловит реальный баг» от «тест флейки/37 устарел». Прогони локально, если возможно.38- **D. ОПИСАНИЕ СИМПТОМА словами** (без артефактов): сначала воспроизведи или39 собери недостающую фактуру (лог, шаги), не строй RCA на пересказе.4041Зафиксируй в начале отчёта SCOPE: что разбираем (симптом одной фразой), какие42артефакты на руках (лог/трейс/тикет/тест/коммиты), какое окружение, временное43окно инцидента. Если фактуры недостаточно, чтобы дойти до причины44доказательно (нет логов, нет доступа к окружению, симптом неясен) — остановись45и перечисли, что нужно собрать, вместо того чтобы гадать.4647Периметр шире буквального симптома: включай вызывающий код, потребителей48данных, соседние модули того же класса, конфигурацию и окружение, где это49проявилось.5051## КЛЮЧЕВОЙ ПРИНЦИП: СИМПТОМ ≠ ПРИЧИНА5253Разбор проваливается, когда останавливаются на первом слое («упало из-за54NullPointerException» — это симптом, а не причина). Держи три уровня раздельно:55561. **Непосредственная причина (proximate)** — что технически сломалось в57 момент отказа (какая строка кинула исключение, какой запрос вернул не то).582. **Корневая причина (root)** — почему это стало ВОЗМОЖНО (почему на вход59 пришёл null; почему не было валидации; почему контракт разошёлся). Обычно60 на 3–5 «почему» глубже симптома.613. **Способствующие факторы (contributing)** — что усугубило или помогло62 пройти незамеченным (отсутствие теста, слабый мониторинг, спешка релиза,63 неоднозначное требование).6465Правило остановки «почему»: копай, пока следующее «почему» ещё находится в66зоне вашего контроля и подсказывает действие. Останавливайся, когда упёрся во67внешний факт или в осмысленное системное решение. Не превращай 5 Whys в68пальцем-в-небо: каждое звено — доказано, а не предположено.6970## МЕТОДОЛОГИЯ7172Работай по порядку; тяжёлые шаги (разматывание кода, bisect) при большом73объёме делегируй субагентам через Agent tool, передав им конкретные пути и74разделы этого скилла.75761. **Собери timeline инцидента.** Восстанови хронологию по фактам: когда77 задеплоили что / когда появились первые ошибки (логи, метрики, алерты) /78 когда заметили / что делали при разборе / когда стабилизировали. Timeline79 часто сам указывает на вводящее изменение (ошибки начались через 10 минут80 после деплоя X).812. **Точно зафиксируй симптом.** Что именно наблюдается, воспроизводимо ли,82 при каких входных данных/окружении. Если можешь — воспроизведи минимально83 (тест/скрипт/запрос) и зафиксируй фактический результат. Невоспроизводимость84 — тоже факт (гонка, специфичные данные, только прод).853. **5 Whys — доказательно.** Построй цепочку от симптома вглубь. На КАЖДОЕ86 «почему» приложи доказательство (file:line, лог, git). Пример скелета:87 - Почему упал запрос? → БД вернула 0 строк, код не обработал пустой список88 (`service/x.py:42`).89 - Почему пришёл пустой список? → фильтр по company_id получил None.90 - Почему None? → контекст запроса не прокинул tenant в фоновую задачу.91 - Почему не прокинул? → фоновой воркер добавлен позже основного контекста и92 не подхватил middleware (`worker/y.py:88`, коммит abc123).93 - Почему это не заметили? → нет теста на фоновый путь с изоляцией тенанта.94 Первая и последняя строки — вход для разных выводов (фикс и предотвращение).954. **Ishikawa / fishbone — проверь все категории причин**, чтобы не96 зациклиться на «это код виноват». Пройди по категориям и отметь вклад97 каждой (или явно «не при чём»):98 - **Код** — логика, обработка ошибок, контракт/типы, конкурентность.99 - **Данные** — некорректные/неожиданные/«грязные» данные, миграция,100 граничные значения, объём.101 - **Конфигурация** — флаги, env, лимиты, таймауты, отличие сред.102 - **Окружение / инфра** — версия рантайма, сеть, ресурсы (OOM/CPU), внешний103 сервис, деплой.104 - **Процесс** — ревью, тестирование, релизный процесс, откат.105 - **Требования** — неоднозначное/неполное/противоречивое ТЗ, не тот кейс106 реализован.107 - **Человеческий фактор** — но blameless: не «Вася ошибся», а «система108 позволила совершить и не поймать эту ошибку».1095. **Локализуй вводящее изменение в коде.** Если баг — регрессия: найди110 коммит, который её ввёл. `git log -p -- <файл>`, `git blame <файл> -L111 <строки>`, при воспроизводимости — `git bisect start / bad / good <ref>`,112 чтобы бинарным поиском выйти на коммит. Зафиксируй хеш, автора-контекст (без113 обвинения), что именно изменилось и почему тогда это выглядело безопасно.1146. **Раздели три уровня причин** (непосредственная / корневая /115 способствующие) явно — это ядро вывода.1167. **«Почему не поймали?»** — отдельный обязательный разбор. Чего не хватило,117 чтобы дефект не дошёл до прода:118 - какого теста (юнит/интеграционного/E2E/регрессионного) не было или он не119 покрывал этот кейс/ветку/границу;120 - какой проверки на ревью/линте/типах/контракте не хватило;121 - какого гейта в CI/мониторинга/алерта не хватило, чтобы поймать раньше.122 Этот блок — прямой вход для скиллов проектирования тестов и анализа123 покрытия (`test-case-design`, анализ пробелов покрытия): сформулируй124 конкретно, какой тест/проверку добавить.1258. **Рекомендации на двух уровнях:**126 - **Локальный фикс** — что конкретно поправить, чтобы устранить этот127 дефект (file:line, суть изменения). НЕ вноси правку сам — это read-only128 разбор.129 - **Системное предотвращение класса** — что не даст всему классу таких130 проблем повториться: недостающий тест, линт-правило, типовой контракт,131 CI-гейт, изменение процесса/шаблона, дефолт конфигурации. Именно этот132 уровень отличает RCA от «просто починили».133134## РАЗЛИЧЕНИЕ: РЕАЛЬНЫЙ БАГ vs ФЛЕЙКИ / АРТЕФАКТ ТЕСТА135136Если вход — упавший тест, прежде чем строить RCA продукта, докажи, что баг в137продукте, а не в тесте:138- воспроизводится ли падение стабильно или мигает (флейки: таймауты, гонки,139 зависимость от порядка/времени/внешнего сервиса, незамоканный рандом/дата);140- не устарел ли сам тест (ассерт под старое поведение, которое осознанно141 изменили) — тогда причина в тесте/процессе обновления тестов, не в продукте;142- не общий ли это ресурс между тестами (shared state, не изолированная БД).143Квалифицируй явно: «баг в продукте» / «баг в тесте» / «флейки-инфраструктура».144145## EDGE CASES, КОТОРЫЕ ЧАСТО ПРОПУСКАЮТ ПРИ RCA146147- Остановились на непосредственной причине и назвали её корневой (починили148 симптом, класс проблемы остался).149- Единственная «причина» при нескольких способствующих факторах — у инцидентов150 редко одна причина; фикс одной не закрывает окно, если остальные на месте.151- Confirmation bias: нашли правдоподобную гипотезу и перестали копать, не152 опровергнув альтернативы. Активно ищи опровержение своей версии.153- «Причина» = последний коммит по времени, без bisect-доказательства, что154 именно он вводит дефект (могли совпасть два изменения).155- Латентный баг: код с дефектом жил давно, «сломало» его изменение ДАННЫХ/156 нагрузки/конфигурации, а не коммит в этом файле — не вешай вину на невиновный157 коммит.158- Причина в окружении/конфиге (отличие prod от staging), а разбор ведётся159 только по коду.160- Гонка/конкурентность: воспроизводится только под нагрузкой; «не могу161 повторить локально» ≠ «бага нет».162- Внешняя зависимость (сторонний API/сервис изменил поведение) — корневая163 причина вне вашего кода, но предотвращение (таймаут/ретрай/деградация) —164 внутри.165- Каскад: первичный отказ вызвал вторичные; не прими вторичный симптом за166 корень. Идентифицируй первое звено по timeline.167- «Почему не поймали» подменяют на «добавим ещё тестов вообще» — нужен168 КОНКРЕТНЫЙ недостающий кейс/граница/ветка, а не лозунг.169- Blame вместо blameless: вывод «человек был невнимателен» не подсказывает170 системного действия и вредит культуре — переформулируй в термины системы.171- Фикс уже был, но не помог/откатили — разбери, почему предыдущая гипотеза172 причины была неверна (это само по себе находка).173174## КРИТЕРИИ КАЧЕСТВА RCA (DoD)175176RCA считается завершённым, только если:177- симптом воспроизведён ИЛИ явно объяснено, почему воспроизведение невозможно;178- цепочка «почему» доведена до уровня, где следующий шаг — уже внешний факт179 или системное решение, и КАЖДОЕ звено доказано;180- разделены непосредственная / корневая / способствующие причины;181- есть раздел «почему не поймали» с конкретным пробелом контроля;182- рекомендации даны на ДВУХ уровнях (заплатка + предотвращение класса);183- action items имеют владельца (или пометку «владелец не определён —184 требуется назначить») и приоритет.185186## ФОРМАТ ОТЧЁТА (постмортем)187188Сохрани отчёт в `docs/qa/rca/<incident-slug>.md` (slug — по ID инцидента/189тикета или короткому имени). Перед созданием проверь структуру репозитория и190следуй ей; `docs/qa/rca/` — дефолт. Если разбор по этому инциденту уже есть —191дополняй, а не пересоздавай.192193Структура постмортема:1941951. **Краткое резюме** — что произошло, кого/что задело, каков был масштаб и196 длительность, какова корневая причина одной фразой. Без жаргона, читаемо197 для менеджмента.1982. **SCOPE / входные данные** — что разбирали, какие артефакты на руках,199 окружение, временное окно.2003. **Timeline** — хронология по фактам с timestamp (деплой → первые ошибки →201 обнаружение → стабилизация).2024. **Симптом** — что наблюдалось, воспроизводимость, входные данные.2035. **Анализ причин** — 5 Whys (с доказательствами по каждому звену) +204 fishbone-разбивка по категориям; явно: непосредственная / корневая /205 способствующие. Вводящий коммит (хеш) при регрессии.2066. **Почему не поймали** — конкретный пробел в тестах/ревью/CI/мониторинге.2077. **Рекомендации** — таблица: заплатка (локальный фикс) и системное208 предотвращение класса; для каждого — уровень, суть, ссылка на file:line209 если применимо.2108. **Action items** — список действий с владельцем и приоритетом (P0..P3);211 тесты/гейты, которые надо добавить, вынеси отдельно как вход для212 `test-case-design`/анализа покрытия.2139. **Что не проверено / ограничения** — нет доступа к прод-логам, не214 воспроизвёл вживую, гипотезы, оставшиеся недоказанными (пометь как215 гипотезы, а не факты).216217## ПРАВИЛА ОФОРМЛЕНИЯ218219- Каждое звено причинной цепочки — со ссылкой на доказательство (file:line,220 лог с timestamp/строкой, git-хеш, результат воспроизведения). Недоказанное221 помечай словом «гипотеза».222- Blameless: формулируй в терминах системы/процесса, не личностей.223- Разделяй факт и вывод: «в логе X» (факт) vs «вероятно, из-за Y» (вывод).224- Action items без владельца бесполезны — если владелец неизвестен, так и225 напиши «назначить владельца», не оставляй пустым.226227Это разбор, а не имплементация: фикс и предотвращающие изменения вносит228команда по итогам RCA — код в рамках этого скилла не правь (временные229скрипты/тесты для воспроизведения удали после проверки).