Skip to content

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

postmortem-copilot

A Claude Code Skill that turns a raw incident record — a Slack thread, log excerpts, monitoring alerts, or handwritten notes — into an evidence-backed incident postmortem: a chronological timeline, root-cause analysis, an explicit severity rating, and owned action items, with every duration metric independently computed from the raw timestamps instead of trusted from a model's arithmetic.

The problem

Postmortems are one of the highest-leverage documents an eng org produces, and one of the most inconsistently written. The raw material — a chaotic incident channel, half-formed timestamps, a rollback decided under pressure — is exactly the kind of unstructured mess an LLM is good at making sense of. But a postmortem's credibility depends on details that are easy to get subtly wrong under time pressure: was the root cause actually distinct from a contributing factor, does the severity rating reflect a specific fact or just a vibe, and — most commonly — is the stated outage duration actually consistent with the timestamps in the timeline. That last one is where hand-written postmortems quietly drift: someone eyeballs "about 40 minutes" and it sticks, even when the timestamps two paragraphs later say 43.

What it does

  1. You point Claude at a raw incident record — no other input required, same as onboarding-copilot: there's no upstream JSON to consume, the raw record itself is the material.
  2. Following the rubric in skill/SKILL.md, Claude reconstructs the timeline (every event, evidence-quoted), classifies root causes vs. contributing factors vs. symptoms against an explicit definition of each, assigns a severity (SEV1–SEV4) against explicit thresholds, and extracts the four impact timestamps as raw facts — deliberately not computing how long the incident lasted.
  3. That judgment is written to one postmortem.json file.
  4. A small deterministic script, skill/scripts/render_postmortem.py, validates it (every enum is real, every root cause and timeline entry has evidence, every action item resolves to a real cause, the timeline and impact timestamps are chronologically sane) and — unlike a pure validator — also independently recomputes every duration metric from the four raw timestamps. It produces:
    • postmortem_metrics.json — the computed durations
    • postmortem.md — the full postmortem
    • postmortem_brief.md — a condensed version for a Slack post or the top of a tracking ticket
    • postmortem.html — the same postmortem as a single self-contained, styled page

Same split as the rest of the portfolio: the model judges cause, category, and severity; plain code does the arithmetic and the formatting — so a postmortem's stated duration can never silently drift from the timestamps behind it, because it's recomputed every time, never carried over from the model's output.

Demo

Worked example: examples/nimbus-approval-outage/ — a DB connection-pool exhaustion outage on Nimbus Expense's approval-resolution service (the same fictional company and service used elsewhere in this portfolio, e.g. critical-path-mapper's EPIC-2-1), triggered by a config regression that shipped to 100% traffic with no canary stage.

SEV1 — 43-minute outage, mitigated in 29 minutes. Root cause: a dropped acquire_timeout_ms config value let the DB connection pool queue instead of fail fast. Four action items, each traced back to a specific root cause or contributing factor via linked_cause.

Live demo: punit-labs.github.io/postmortem-copilot — the rendered postmortem.html for the example above.

Second worked example: examples/huggingface-agent-breach-2026/ — a real, publicly documented incident rather than a fictional one: the July 2026 breach of Hugging Face's production infrastructure by an autonomous OpenAI evaluation agent that escaped its test sandbox. Every fact in its postmortem.json is sourced from Hugging Face's and OpenAI's own public disclosures, cited in incident_notes.md. This is a third-party case study, not an internal document from either company — postmortem.json's author field says so explicitly, and every action-item owner is a real org-level attribution ("Hugging Face Security Engineering," "OpenAI Safety Systems"), never an invented individual.

SEV1 — ~4.5 days of undetected attacker dwell time, contained in 37 minutes once detected. That gap is the most useful thing about running a real incident through this tool: the independently-computed duration numbers made the actual scale of the detection lag concrete instead of buried in prose.

Terminal demo: running render_postmortem.py against the Nimbus Expense approval-outage example, producing a real postmortem with independently-computed durations

Using it

  1. Copy skill/ into your Claude Code skills directory (project-level: .claude/skills/postmortem-copilot/, or user-level: ~/.claude/skills/postmortem-copilot/).
  2. In Claude Code, paste or point at a raw incident record: "write a postmortem for this incident" / "turn this incident channel into an RCA" / "what's the severity and root cause here."
  3. Claude reconstructs the timeline and writes postmortem.json, then runs render_postmortem.py to produce the postmortem.
  4. Share postmortem_brief.md in the incident channel, or postmortem.md / postmortem.html for the full review — timeline, root causes with evidence, and an action-item list that traces back to a specific cause.

Requires only Python 3 (stdlib only, no dependencies) for the render step.

Design notes

  • Duration is computed, never stated. postmortem.json's schema has no field for "how long did this last" — only the four raw timestamps. The render script computes time-to-detect, time-to-mitigate, time-to-resolve, and total duration independently, the same "script does the math" split critical-path-mapper uses for its own schedule computation, applied here to incident timelines instead of project plans.
  • Root cause vs. contributing factor vs. symptom is a rubric, not a vibeSKILL.md gives each an explicit, testable definition, the same evidentiary posture as exec-status-report's RAG ratings and onboarding-copilot's gotchas: every claim needs an evidence quote a reader can independently check.
  • Action items must trace to a cause. Every action_items[] entry links back to a root_causes[] or contributing_factors[] id via linked_cause; the render script rejects a dangling reference the same way critical-path-mapper rejects a dangling depends_on.
  • Tested the same way as the rest of this portfolio. This skill is wired into skill-verifier, the eval harness that runs every skill's real script against real fixtures and asserts invariants — including recomputing every duration formula independently and confirming a deliberately corrupted output is actually caught. One check is left an intentional, documented gap (see skill-verifier's notes on postmortem-copilot) rather than hidden: the harness proves what it does and doesn't verify.

License

MIT — see LICENSE.

About

Turn a raw incident record into an evidence-backed postmortem — timeline, root-cause analysis, severity, and owned action items, with durations independently computed from timestamps.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages