Incident post-mortem
Purpose
Post-mortems fail in three predictable ways: they stop at the trigger ("a bad
deploy went out") and call it a cause, they blame a person instead of the
conditions that made the error easy, and they end in actions nobody owns. This
skill fixes the timeline to evidence, forces the cause analysis past the first
plausible answer, and refuses to close on an action without an owner and a date.
Prerequisites
- Inputs: the incident record (ID, severity, declared and resolved times);
the alert or report that started detection; deploy/change log for the affected
services covering the 48h before impact; chat transcript or timeline of
responder actions; the customer-visible impact (what broke, for whom, for how
long, measured — not estimated).
- Access: monitoring/dashboards for the impact window, change management
records, ticket system to file actions.
If the impact window or the change log is missing, say so and stop. A post-mortem
built on recollection produces a plausible story and the wrong actions.
Procedure
Fix the timeline before writing any narrative. Build a table of
timestamped events with a source for each. Every row is one of: a change, a
signal, a human action, or a state transition. If a row has no source, mark it
[unverified] — never silently promote recollection to fact.
| Time (UTC) |
Event |
Type |
Source |
| 09:14 |
Config change deployed to payments-api |
change |
deploy log |
| 09:41 |
Error rate crosses 2% |
signal |
dashboard |
| 09:58 |
On-call paged |
signal |
alert record |
Derive the four durations. Time to detect (impact start → first signal),
time to page (signal → human engaged), time to diagnose (engaged →
cause identified), time to mitigate (diagnose → impact ends). Whichever is
longest is where the actions must concentrate. Teams routinely write five
actions about the code change and none about the 44 minutes of undetected
impact.
Separate trigger, cause, and contributing conditions.
| Layer |
Question it answers |
Test that it is the right layer |
| Trigger |
What set it off this time? |
Would removing it prevent this recurrence only? |
| Cause |
What made that trigger able to cause harm? |
Would fixing it stop a class of incidents? |
| Contributing conditions |
What made detection or recovery slow? |
Would fixing it shorten the next unrelated incident? |
A trigger is never a sufficient answer. "Someone deployed a bad config" is a
trigger; "config changes deploy to all regions simultaneously with no
validation gate" is the cause.
Push each cause chain until it lands on something you can change. Stop
when the next "why" would be a statement about human nature or organisational
budget you cannot action. Stopping early gives you "the engineer made a
mistake"; going too far gives you "we are under-resourced". The actionable
band sits between: the missing guardrail, the misleading interface, the alert
that did not exist.
Test each candidate cause against the counterfactual. For each, ask: if
this had been different, would the impact have been prevented or materially
reduced? If no, it is context, not cause — move it to the narrative and drop
it from the action list.
Write actions in the required shape. Every action: a verb, a specific
system, an owner (a named individual, never a team), a due date, and a
ticket ID. Classify each:
| Class |
Reduces |
Ship within |
| Prevent |
Probability of recurrence |
The current cycle |
| Detect |
Time to detect |
The current cycle |
| Mitigate |
Blast radius or time to recover |
Next cycle |
| Process/knowledge |
Repeat confusion in response |
Next cycle |
If every action is class Prevent, the review is incomplete — detection and
mitigation gaps almost always exist and are usually cheaper to close.
Run the blameless check before circulation. Scan the draft for named
individuals. A person's name is acceptable in the timeline as an actor
("on-call acknowledged") and unacceptable in the cause section. Rewrite
"X misconfigured the limit" as "the limit could be set to an invalid value
without validation".
Set a verification date. Actions are marked done when the change is in
production, not when the ticket closes. Book a check 30 days out that
confirms the guardrail exists and fires.
Failure modes this skill exists to prevent
- Cause laundering. The trigger is restated in passive voice and presented as
the root cause. Caught by step 3's "class of incidents" test.
- Action inflation. Fourteen actions, none prioritised; six months later two
are done and none are the important ones. Cap at five; the rest are backlog.
- Duration blindness. The whole review addresses the change and ignores that
detection took 44 minutes. Caught by step 2.
- Silent unknowns. Gaps in the timeline get smoothed over by narrative.
Write "we do not know why the retry storm began; investigation ticket X" — an
explicit unknown is a finding, an implicit one is a lie.
Data handling
Classification: Internal by default; Confidential if the incident
involved a security breach, personal data exposure, or financial loss. Post-mortem
text must not carry customer identifiers, account numbers, or log lines
containing personal data — reference the affected records by count and by ticket,
not by value. If someone pastes raw customer records or credentials into the
review, flag it and do not incorporate them.
Boundaries
- Incident still active, or you are deciding mitigations in the moment — use
engineering-incident-command, not this.
- Change was routine and had no customer or availability impact — record it in
the ticket; a post-mortem adds process cost and no learning.
- Security breach requiring regulatory notification — this skill covers the
engineering review only; notification obligations run through
legal-compliance-breach-notification.
- Choosing between architectural options to close an action — that decision
belongs in
engineering-decision-record.
Hand-offs
- Receives from:
engineering-incident-command (timeline, severity, responder log).
- Routes to:
engineering-decision-record when a remediation implies an
architectural change; it-change-management when the fix needs a controlled
change window; engineering-code-review for the review depth on the fix itself.
- See also:
data-analytics-report-qa when impact numbers must be quoted
externally and need a verification pass first.
1---2name: engineering-incident-postmortem3description: Runs a blameless incident post-mortem: reconstructs the timeline from evidence, separates trigger from cause from contributing conditions, and produces owned, dated remediation actions. Use when an incident, outage, degradation, or severe bug has been resolved and a written review is due, or when a draft post-mortem needs review before it goes to a review board. Trigger on 'write the post-mortem', 'RCA for the outage', 'incident review', 'five whys', 'what was the root cause', 'corrective actions for INC-'. Not for triaging an incident that is still live — that is engineering-incident-command; not for routine bug write-ups with no customer or availability impact, which belong in the ticket.4---56# Incident post-mortem78## Purpose910Post-mortems fail in three predictable ways: they stop at the trigger ("a bad11deploy went out") and call it a cause, they blame a person instead of the12conditions that made the error easy, and they end in actions nobody owns. This13skill fixes the timeline to evidence, forces the cause analysis past the first14plausible answer, and refuses to close on an action without an owner and a date.1516## Prerequisites1718- **Inputs:** the incident record (ID, severity, declared and resolved times);19 the alert or report that started detection; deploy/change log for the affected20 services covering the 48h before impact; chat transcript or timeline of21 responder actions; the customer-visible impact (what broke, for whom, for how22 long, measured — not estimated).23- **Access:** monitoring/dashboards for the impact window, change management24 records, ticket system to file actions.2526If the impact window or the change log is missing, say so and stop. A post-mortem27built on recollection produces a plausible story and the wrong actions.2829## Procedure30311. **Fix the timeline before writing any narrative.** Build a table of32 timestamped events with a source for each. Every row is one of: a change, a33 signal, a human action, or a state transition. If a row has no source, mark it34 `[unverified]` — never silently promote recollection to fact.3536 | Time (UTC) | Event | Type | Source |37 | --- | --- | --- | --- |38 | 09:14 | Config change deployed to payments-api | change | deploy log |39 | 09:41 | Error rate crosses 2% | signal | dashboard |40 | 09:58 | On-call paged | signal | alert record |41422. **Derive the four durations.** Time to detect (impact start → first signal),43 time to page (signal → human engaged), time to diagnose (engaged →44 cause identified), time to mitigate (diagnose → impact ends). Whichever is45 longest is where the actions must concentrate. Teams routinely write five46 actions about the code change and none about the 44 minutes of undetected47 impact.48493. **Separate trigger, cause, and contributing conditions.**5051 | Layer | Question it answers | Test that it is the right layer |52 | --- | --- | --- |53 | Trigger | What set it off this time? | Would removing it prevent *this* recurrence only? |54 | Cause | What made that trigger able to cause harm? | Would fixing it stop a class of incidents? |55 | Contributing conditions | What made detection or recovery slow? | Would fixing it shorten the next unrelated incident? |5657 A trigger is never a sufficient answer. "Someone deployed a bad config" is a58 trigger; "config changes deploy to all regions simultaneously with no59 validation gate" is the cause.60614. **Push each cause chain until it lands on something you can change.** Stop62 when the next "why" would be a statement about human nature or organisational63 budget you cannot action. Stopping early gives you "the engineer made a64 mistake"; going too far gives you "we are under-resourced". The actionable65 band sits between: the missing guardrail, the misleading interface, the alert66 that did not exist.67685. **Test each candidate cause against the counterfactual.** For each, ask: if69 this had been different, would the impact have been prevented or materially70 reduced? If no, it is context, not cause — move it to the narrative and drop71 it from the action list.72736. **Write actions in the required shape.** Every action: a verb, a specific74 system, an owner (a named individual, never a team), a due date, and a75 ticket ID. Classify each:7677 | Class | Reduces | Ship within |78 | --- | --- | --- |79 | Prevent | Probability of recurrence | The current cycle |80 | Detect | Time to detect | The current cycle |81 | Mitigate | Blast radius or time to recover | Next cycle |82 | Process/knowledge | Repeat confusion in response | Next cycle |8384 If every action is class Prevent, the review is incomplete — detection and85 mitigation gaps almost always exist and are usually cheaper to close.86877. **Run the blameless check before circulation.** Scan the draft for named88 individuals. A person's name is acceptable in the timeline as an actor89 ("on-call acknowledged") and unacceptable in the cause section. Rewrite90 "X misconfigured the limit" as "the limit could be set to an invalid value91 without validation".92938. **Set a verification date.** Actions are marked done when the change is in94 production, not when the ticket closes. Book a check 30 days out that95 confirms the guardrail exists and fires.9697## Failure modes this skill exists to prevent9899- **Cause laundering.** The trigger is restated in passive voice and presented as100 the root cause. Caught by step 3's "class of incidents" test.101- **Action inflation.** Fourteen actions, none prioritised; six months later two102 are done and none are the important ones. Cap at five; the rest are backlog.103- **Duration blindness.** The whole review addresses the change and ignores that104 detection took 44 minutes. Caught by step 2.105- **Silent unknowns.** Gaps in the timeline get smoothed over by narrative.106 Write "we do not know why the retry storm began; investigation ticket X" — an107 explicit unknown is a finding, an implicit one is a lie.108109## Data handling110111Classification: **Internal** by default; **Confidential** if the incident112involved a security breach, personal data exposure, or financial loss. Post-mortem113text must not carry customer identifiers, account numbers, or log lines114containing personal data — reference the affected records by count and by ticket,115not by value. If someone pastes raw customer records or credentials into the116review, flag it and do not incorporate them.117118## Boundaries119120- Incident still active, or you are deciding mitigations in the moment — use121 `engineering-incident-command`, not this.122- Change was routine and had no customer or availability impact — record it in123 the ticket; a post-mortem adds process cost and no learning.124- Security breach requiring regulatory notification — this skill covers the125 engineering review only; notification obligations run through126 `legal-compliance-breach-notification`.127- Choosing between architectural options to close an action — that decision128 belongs in `engineering-decision-record`.129130## Hand-offs131132- **Receives from:** `engineering-incident-command` (timeline, severity, responder log).133- **Routes to:** `engineering-decision-record` when a remediation implies an134 architectural change; `it-change-management` when the fix needs a controlled135 change window; `engineering-code-review` for the review depth on the fix itself.136- **See also:** `data-analytics-report-qa` when impact numbers must be quoted137 externally and need a verification pass first.