# Srekit Postmortem

> Создаёт постмортем через `srekit postmortem` и наполняет секции (Summary, Impact, Timeline, Root cause, Action items, Lessons learned) фактами из текущего диалога. Срабатывай на «написать/оформить постмортем», «разбор инцидента», «постмортем по INC-…» — даже без упоминания srekit. Метаданные (title, severity, owner, start, end) бери из контекста или спроси; blameless, без личных имён, GAP-маркеры вместо галлюцинаций.

- Skill: `jtprogru/srekit-postmortem-2` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add jtprogru/srekit-postmortem-2`
- Raw SKILL.md: https://api.skillmd.com/api/skills/jtprogru/srekit-postmortem-2/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: jtprogru (https://skillmd.com/u/jtprogru)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/jtprogru/srekit-postmortem-2

---


# srekit-postmortem

Скаффолдит постмортем через `srekit postmortem` и помогает заполнить его на основе того, что обсуждалось в текущей сессии.

## Когда использовать

- Пользователь просит написать/оформить постмортем (любая формулировка).
- Пользователь начинает разбор инцидента и хочет файл-каркас, который дальше можно дописывать.
- Пользователь явно упоминает утилиту `srekit`.

**Никакого «исходного файла» (live-incident отчёта, INC-тикета, чат-лога) скилл не предполагает.** Все данные для постмортема приходят из текущего разговора: что пользователь рассказал об инциденте, какие факты вы вместе зафиксировали, что видно в логах/коммитах. Если по какому-то полю данных в сессии нет — спрашивай у пользователя или ставь GAP-маркер; не выдумывай.

## Что делает `srekit postmortem`

`srekit postmortem` — это локально установленная CLI-утилита, которая генерирует markdown-каркас постмортема в Google-SRE-стиле из встроенного (или кастомного) шаблона. Утилита не заполняет содержимое — она только готовит структуру с frontmatter (id, creation_date, severity, owner, …) и пустыми секциями.

Полный CLI-справочник: см. [`references/srekit-cli.md`](references/srekit-cli.md).

Ключевые флаги, которые ты будешь использовать:

| Флаг | Назначение |
| --- | --- |
| `-T, --title` | **обязательный** — заголовок инцидента |
| `--severity` | `SEV-1` / `SEV-2` / `SEV-3` (по умолчанию SEV-3) |
| `--owner` | ответственный (всегда роль, не имя — см. ниже) |
| `--start` | начало в RFC3339 |
| `--end` | конец/mitigation в RFC3339 |
| `--out` | путь к выходному файлу |
| `--templates-dir` | one-shot override директории пользовательских шаблонов (на одну команду; иначе берётся из конфига) |
| `--force` | перезаписать существующий файл |
| `--dry-run` | напечатать в stdout, не писать на диск |
| `--from FILE` | прочитать секции из JSON (`-` для stdin) — round-trip workflow |
| `--schema` | вывести JSON Schema для `--from` входа |
| `--validate FILE` | валидировать input-файл без рендера |

`--template FILE` (one-shot подмена шаблона) у `postmortem` больше нет — удалён в v0.22.0. Кастомный шаблон подключается через `--templates-dir` (или через конфиг — `templates_dir:` в `~/.config/srekit/config.yaml` / env `SREKIT_TEMPLATES_DIR`).

## Рабочий процесс

### 1. Убедись, что `srekit` доступен

```bash
srekit --version
```

Если команда не найдена — сообщи пользователю, что нужно поставить `srekit` (`https://github.com/jtprogru/srekit`), и остановись. Не пытайся обойтись без неё — пользователь явно хочет именно эту утилиту.

### 2. Найди upstream-артефакты в репо

Прежде чем спрашивать метаданные — быстро просканируй репозиторий на материалы, которые попадут в **References** или подскажут title / severity. Это **не источник наполнения секций** (наполнение всё равно из сессии — см. правило «не заполняй секции без данных в сессии»), но это контекст и линки.

Что искать:

1. **Runbook на алерт, который сработал.** Если пользователь упомянул имя алерта или сервиса — поищи в репо `runbooks/`, `docs/runbooks/`. Релевантный runbook — это:
   - источник Mitigate-шагов, которые применялись (полезно для секции «Что сработало»);
   - линк под References;
   - сигнал, насколько runbook оказался полезен (если не помог — это _What went wrong_).
2. **Прошлые постмортемы по тому же failure mode.** `incidents/postmortem-*.md`, `runbooks/postmortems/*.md`. Если этот же сценарий уже происходил — это критичный контекст («повтор инцидента» сразу попадает в Lessons learned, и related-постмортем идёт в References).
3. **Legacy `incidents/incident-<slug>.md`-файлы.** Команды `srekit incident` нет с v0.29.0, но старые файлы могут лежать в репо в проектах, где live-doc вели в markdown. Если такой файл по этому инциденту есть — прочитай и используй timeline как fact-источник (но **в постмортеме timeline консолидированный, а не копия** — см. шаг 7). Под References — ссылка на live-doc.
4. **SLO-документ для затронутого сервиса.** `docs/slo/slo-<service>.md` или подобное. Конкретные SLI / target из SLO — то, что попадает в секцию Impact и в Action items по теме error-budget burn.

Сделай не больше двух-трёх grep'ов / `ls`'ов — это сканирование, не deep-research. Если ничего не нашёл — ок, идём дальше.

Что **не** делать:
- Не вытаскивай content из найденных файлов в секции постмортема. Это материал для References и для подтверждения / уточнения того, что пользователь рассказал, не источник.
- Не предполагай, что live-doc / runbook есть, если не видишь его. Отсутствие — нормальное состояние. Не блокируй работу.

### 3. Собери метаданные

Минимально необходимые для скаффолда:

| Поле | Откуда брать |
| --- | --- |
| title | из формулировки пользователя или явно спроси («как назовём инцидент?») |
| severity | `SEV-1` / `SEV-2` / `SEV-3`. Если не указано — спроси; если контекст явно говорит (например, обсуждается полная деградация прод) — предложи и подтверди |
| owner | роль/команда, не личное имя. Дефолт для h3llo — `SRE Lead`. Подтверди у пользователя |
| start | момент начала инцидента в RFC3339. Если только дата — уточни время. Если ничего нет — спроси |
| end | момент mitigation/resolved в RFC3339. Если инцидент ещё открыт — оставь пустым и поставь GAP в теле |

Стратегия:

- Что явно прозвучало в диалоге — подставь и подтверди одним сообщением («собираюсь скаффолдить с такими-то полями, ок?»).
- Что не прозвучало и не выводится — спроси короткой репликой. Не плоди вопросов: одно сообщение с 2–4 пунктами лучше, чем 4 отдельных.
- Не выдумывай timestamps. Если пользователь сказал «вчера утром» — переспроси точное время.

Все timestamps в RFC3339, в локальной TZ (например MSK = `+03:00`). В **Timeline** постмортема ты потом сконвертируешь их в UTC (см. шаг 7).

### 4. Выбери шаблон

`srekit` сам резолвит шаблон: если в конфиге задан `templates_dir` (или есть env `SREKIT_TEMPLATES_DIR`) и там лежит `postmortem.yaml` — берётся он, иначе fallback на embedded. Обычно ничего делать не нужно.

Когда стоит вмешаться:

- В репозитории есть свой шаблон постмортема в нестандартной директории (типично для h3llo — `runbooks/templates/`, где формат — расширенная h3llo-структура с Impact-таблицей, Why it took N minutes, Communications log, Follow-up через 30/90 дней). В этом случае на одну команду переопредели через `--templates-dir <DIR>` (директория должна содержать `postmortem.yaml` в корне). Это **директория**, не путь к конкретному файлу — флаг `--template FILE` у `postmortem` был удалён в v0.22.0.
- Хочешь убедиться, что подхватится именно проектный шаблон, а не глобальный из конфига — передай `--templates-dir` явно.

Скажи пользователю, какой шаблон выбран (embedded / configured / `--templates-dir`) и почему.

### 5. Определи путь к файлу постмортема

Правило (в порядке приоритета — выбирай первое, что подходит):

1. **`incidents/postmortem-<YYYY-MM-DD>-<slug>.md`** — если в репозитории есть каталог `incidents/`. Это конвенция h3llo: всё, что связано с конкретным инцидентом, лежит в `incidents/`, постмортем различается префиксом `postmortem-`. (До v0.29.0 в этом же каталоге могли лежать legacy live-incident-отчёты — теперь `srekit incident` нет; новые постмортемы туда же.)
2. **`runbooks/postmortems/postmortem-<YYYY-MM-DD>-<slug>.md`** — если есть такой каталог (другие проекты, явно отдельная директория для постмортемов).
3. **`postmortem-<YYYY-MM-DD>-<slug>.md` в CWD** — последний fallback.

Имя файла — **всегда** в формате `postmortem-<YYYY-MM-DD>-<slug>.md`:

- Префикс `postmortem-` — срекит-конвенция, не меняется.
- Дата — день инцидента (не creation_date файла), `YYYY-MM-DD`. Даёт читаемый хронологический sort в каталоге и быстро отвечает «когда это было?» взглядом на имя файла.
- Slug — kebab-case, короткий, передающий суть инцидента: `disk-50gb-create-hang`, `csi-controller-oom`, `vm-network-loss-az-b`, `inotify-kubelet-crash`.

Не используй чужие схемы (`<date>-<slug>-postmortem.md`, `INC-NNNN.md`, `<topic>-postmortem-<date>.md`).

**Важно: всегда передавай `--out` явно.** Срекит-дефолтное имя — `postmortem-<YYYY-MM-DD>-<slug>.md` (дата = creation date, не дата инцидента), и сладжификатор плохо работает с кириллицей (для `-T "Зависание создания 50ГБ дисков при создании ВМ"` он выдаёт мусорное `postmortem-…-50.md` — выкидывает кириллицу, оставляет только цифры). Дата в дефолте — creation date файла, а нам нужна дата инцидента. Поэтому полагаться на авто-имя нельзя ни в одном из случаев — всегда собирай `--out` сам из выбранного каталога, даты инцидента и slug'а.

Если итоговый путь уже существует — **спроси перед `--force`**. Возможно, пользователь уже начал заполнять.

### 6. Скаффолд через `srekit`

```bash
srekit postmortem \
  -T "<title>" \
  --severity SEV-N \
  --owner "<роль>" \
  --start "<RFC3339 start>" \
  --end "<RFC3339 end>" \
  --out "<путь из шага 5>" \
  [--templates-dir "<DIR с postmortem.yaml>"]   # только если нужен проектный шаблон
```

Перед записью можешь прогнать `--dry-run` и показать пользователю первые 30 строк, чтобы он убедился, что метаданные верные.

### 7. Наполни секции

Это самая важная часть — `srekit` сделал каркас, дальше ты редактируешь его in-place через `Edit`. Заполняй по порядку, опираясь на то, что обсуждалось в сессии: реплики пользователя, выводы из логов/команд, найденные коммиты. Подробное руководство по каждой секции — [`references/section-guide.md`](references/section-guide.md).

Краткая логика:

- **TL;DR / Summary** — 2-3 предложения. Что случилось, кого затронуло, как смягчили, главный урок.
- **Impact** — масштаб (затронутые сервисы, число пользователей/тенантов, длительность). Если SLO ещё не зафиксированы — пиши GAP-маркер со ссылкой на каталог SLO, **не выдумывай цифр**.
- **Timeline** — собери в хронологическом порядке (от ранних событий к поздним), **в UTC**. Каждая строка — одно конкретное событие, а не пересказ. Если ты помнишь точные timestamps из сессии — ставь; если знаешь только относительные («через полчаса после первого репорта») — спроси у пользователя точное время или поставь GAP. **Линкуется, не копируется.** Если по этому инциденту существует подробный live-coordination-лог (Slack-тред, чат, Google Doc, legacy `incidents/incident-*.md`) с минутными апдейтами — **не копируй его сюда**. Постмортем-Timeline — это **консолидированные milestone'ы**: detection, escalation, первая попытка mitigation, успешная mitigation, resolved. Детальный лог — ссылкой под References. Если консолидируешь — каждая строка добавляет ценность по сравнению с живым логом (контекст, связка с тех. фактом, источник), иначе вырезай.
- **Root cause** — раздели _непосредственный технический фактор_ и _contributing factors_ (отсутствующий алерт, накопление состояния месяцами, отсутствие automation). Если непосредственная причина не до конца ясна — пометь как «hypothesis, not confirmed», не объявляй преждевременно.
- **What went well / wrong / lucky** — синтезируй из обсуждавшегося. «Хорошо» = что сработало как задумано. «Плохо» = что замедлило (detection через чат, а не алерт; нет baseline; нет runbook). «Повезло» = blast radius мог быть больше, но не стал.
- **Action items** — из того, что в ходе сессии обозначилось как «надо сделать». Каждый action item обязан иметь **owner (роль), priority, deadline**. Если deadline неизвестен — GAP и предложи дефолт, **не пиши «TBD»**.
- **Lessons learned** — обобщи системные выводы, не пересказ.

### 8. Примени проектные правила

Эти правила — обязательные для документов в репозиториях h3llo и любых других, где они зафиксированы (`CONTRIBUTING.md`, глобальные memory). Если живёшь в другой кодовой базе — проверь её соглашения, но эти почти всегда уместны для постмортема:

1. **Без личных имён.** Везде — роли/команды: «SRE Lead», «Storage owner», «Internal Developers», «продуктовая разработка». Личные имена в опубликованном постмортеме запрещены (см. memory `feedback_no-personal-names-in-docs`). Это не только про action items — это про весь текст.
2. **Blameless.** Фокус на системе и процессе: «процесс позволил X», «не было guard rail на Y». Никогда — «инженер N сделал Z».
3. **GAP-маркеры вместо галлюцинаций.** Если данных нет — пиши `<GAP — что нужно дополнить>` или `_TBD_` с пояснением, чего именно не хватает. Никогда не выдумывай числа, SLO-таргеты, дедлайны, имена тикетов (см. memory `feedback_doc-pragmatism`).
4. **Markdown без хардврапа.** Один абзац = одна длинная строка. Структурные переносы (списки, таблицы, code fences) — как есть.
5. **Cross-refs — relative markdown.** `[название](relative/path.md)`, без Obsidian-wikilinks `[[…]]` в коммитимых файлах.
6. **Язык — как у пользователя в диалоге.** Если разговор на русском — постмортем на русском. На английском — на английском. Не смешивай.

### 9. Сообщи пользователю

- Путь к созданному файлу.
- Какой шаблон использован.
- Список оставшихся GAP-маркеров — это TODO для пользователя/команды, что нужно ещё дополнить (timestamps, owner'ы, SLO-цифры, ссылки на тикеты).

Не предлагай коммит — пользователь сам решит, когда постмортем готов к review.

## Что НЕ делать

- **Не заполняй секции без данных.** Лучше большой постмортем с GAP-маркерами, чем красивый текст с выдуманными фактами. Это критично — пользователь явно указал, что выдумывать значения недопустимо.
- **Не ищи «исходный live-incident отчёт» как условие старта.** Данные для **содержания** секций приходят из сессии, не из отдельного файла. С v0.29.0 в `srekit` нет команды `incident` — markdown-live-doc больше не стандарт; live-координация уехала в IM-инструменты. Если такой файл всё-таки лежит в репо (legacy, прошлая практика, ручной артефакт) — прочитай в шаге 2 для контекста и ссылки под References, но не блокируйся на его отсутствие.
- **Не теряй contributing factors.** Корневая причина часто закопана глубже, чем «непосредственная»: симптом починен mitigation'ом, но реальная причина массовости (накопление, отсутствие алерта, систематический bias) — отдельный пункт. Не своди root cause к одному фактору.
- **Не используй `git commit`/`git push`** в рамках работы скилла. Пользователь сам решает, когда коммитить.

## Пример

Диалог: пользователь рассказывает, что вчера в 14:25 MSK продуктовая разработка пожаловалась на зависание создания 50 ГБ дисков; mitigation сделали к 18:30 через серию `drbdadm secondary` на ноде w1; статус — `mitigated`, не `resolved`. Заголовок согласовали: «Зависание создания 50ГБ дисков при создании ВМ», severity SEV-2, owner — SRE Lead.

Команда скаффолда:

```bash
srekit postmortem \
  -T "Зависание создания 50ГБ дисков при создании ВМ" \
  --severity SEV-2 \
  --owner "SRE Lead" \
  --start 2026-06-03T14:25:00+03:00 \
  --end 2026-06-03T18:30:00+03:00 \
  --out incidents/postmortem-2026-06-03-disk-50gb-create-hang.md \
  --templates-dir /Users/jtprogru/Work/h3llo.cloud/docs/infrastructure/runbooks/templates
```

(`--templates-dir` тут указан явно, потому что проектный `postmortem.yaml` лежит вне директории, прописанной в `~/.config/srekit/config.yaml`. Если в конфиге уже стоит нужный `templates_dir` — флаг не нужен.)

Дальше — `Edit` по секциям. Timeline (фрагмент, в UTC):

| Время (UTC) | Событие | Источник |
|---|---|---|
| 2026-06-03 11:25 | Продуктовая разработка сообщает о hang при create 50 GiB VM | внутренний чат |
| 2026-06-03 12:25 | SRE Lead запрашивает прод-доступ | внутренний чат |
| 2026-06-03 12:35 | Инцидент объявлен SEV-2 ретроспективно | сессия |
| 2026-06-03 15:30 | Verify: retry-storm схлопнулся (10+ → 1 PVC), статус mitigated | сессия |
| 2026-06-03 16:41 | pvc-create-bench: 0/10 hung, p95=77s — symptom закрыт | bench CSV |

Action items:

| # | Action | Owner | Priority | Deadline | Status | Ссылка на тикет |
|---|---|---|---|---|---|---|
| 1 | Kernel-check `blkio_throttle` на всех воркер-нодах (cgroup v1/v2) | Storage / Piraeus owner | P0 | 2026-06-05 | Open | `<GAP — тикет>` |
| 2 | P0 RCA: «все Primary на w1» (16/16 zombie) | Storage / Piraeus owner | P0 | 2026-06-10 | Open | `<GAP — тикет>` |
| 3 | Зафиксировать baseline SLO disk-create в 53-slo-catalog | SRE | P1 | 2026-06-10 | Open | `<GAP — тикет>` |
| 4 | Регулярный pvc-create-bench в CI (baseline) | Storage / Piraeus owner | P2 | 2026-06-30 | Open | `<GAP — тикет>` |

GAP-маркеры в постмортеме:

- `Communications Lead` — `_TBD_` (роль не была явно назначена)
- `Error budget impact` — `<GAP — error budget policy ещё не утверждена, см. ADR-0011 (Proposed)>`
- Финальный `Resolved` timestamp — `<GAP — инцидент в статусе mitigated, не resolved>`

