skills / code

postmortem-writing

what it does

Write effective blameless postmortems with root cause analysis, timelines, and action items. Use when conducting incident reviews, writing postmortem documents, or improving incident response processes.

Verified Before and after: 2 models 1 try per case View source Download .zip

Compare the answers

Answers from Claude Sonnet 5.5 and GPT-6.1 Sol · try 1 of 1

Same request, same model, once with the skill and once without. Read both and judge for yourself.

“My manager says this postmortem draft is too blamey. Can you rewrite the root cause and action items?”

Source material given with the request

Fernway postmortem draft: mobile API outage, 2026-10-03 Impact: iOS and Android apps could not connect to api.fernway.example from 07:50 to 10:00 UTC (2 h 10 min). About 18,000 users saw "connection error". Root cause: Tom forgot to renew the TLS certificate for api.fernway.example. This is the second time Tom has missed a renewal (the first was 2025-09). Expiry warning emails went to certs@fernway.example, an alias that was deleted in the June mailbox cleanup. Other facts: the certificate is bought yearly and installed by hand on the load balancer. Our uptime monitor checks that the API returns HTTP 200; it does not check certificate expiry. The staging certificate is issued automatically by Let's Encrypt and has never lapsed. Action items: - Tom to set a calendar reminder. - Tom to be more careful with renewals.
with the skill
Below is a blameless rewrite. I kept to the facts in your draft and used placeholders where I'd otherwise be inventing owners, dates, or tickets. ## Root Cause The production TLS certificate for `api.fernway.example` expired on 2026-10-03, and nothing in our process or tooling caught it before it did. Several conditions allowed this: 1. **Manual, yearly renewal.** The certificate is bought annually and installed by hand on the load balancer. A once-a-year task with no automation is easy to miss and depends entirely on someone remembering. 2. **Broken warning channel.** Expiry warnings went to `certs@fernway.example`, an alias deleted in the June mailbox cleanup. The warnings were sent but reached no one. Nothing in the cleanup process flagged that the alias was used for external notifications. 3. **No monitoring for expiry.** Our uptime monitor checks only that the API returns HTTP 200. It doesn't check certificate validity or time to expiry, so there was no independent warning. 4. **Single point of ownership.** Renewal depended on one person, with no backup owner and no shared tracking. 5. **A known weakness that recurred.** A renewal was also missed in 2025-09. The fix then did not remove the underlying dependency on a manual process. This is a pattern, which points to a systemic gap rather than an individual lapse. **What worked:** Staging certificates are issued automatically by Let's Encrypt and have never lapsed. That shows automated issuance works in our environment. ## Action Items | Priority | Action | Type | Owner | Due | Ticket | |---|---|---|---|---|---|
Show the rest (18 more lines)
| P0 | Renew and verify the production cert chain (if not already done as part of the incident fix) | Mitigation | TBD | TBD | TBD | | P0 | Add certificate-expiry monitoring for all public endpoints, alerting at 30,14, and 7 days to the on-call channel (not an individual mailbox) | Detection | TBD | TBD | TBD | | P1 | Automate production certificate issuance and renewal (ACME/Let's Encrypt, or the provider's automation), following the staging setup. Confirm load balancer support | Prevention | TBD | TBD | TBD | | P1 | Replace `certs@` with a monitored shared distribution list or ticketing queue, and document who receives it | Prevention | TBD | TBD | TBD | | P1 | Audit other deleted or retired aliases for external services that send notifications (domains, vendors, billing, certs) | Prevention | TBD | TBD | TBD | | P2 | Add a "check external dependencies on this alias/mailbox" step to the mailbox cleanup checklist | Prevention | TBD | TBD | TBD | | P2 | Inventory all certificates (owner, expiry, renewal method) and assign a primary and backup owner to any that stay manual | Prevention | TBD | TBD | TBD | | P2 | Review the 2025-09 postmortem actions and record why they didn't prevent recurrence | Learning | TBD | TBD | TBD | I dropped "Tom to set a calendar reminder" and "Tom to be more careful." Both rely on individual vigilance, which is the failure mode that already happened twice. They are also hard to verify and put the burden on one person. If a reminder is wanted as a stopgap until automation lands, make it a shared team calendar event with a backup owner. ## Open Questions - How was the outage detected? Did the uptime monitor fire, and if not, why? A failed TLS handshake may not have registered as a non-200 response, which would be worth its own note under Detection. - Does 07:50 UTC match the actual expiry time? If so, the detection gap is worth stating. - What were the 2025-09 action items, and what happened to them? - Does the load balancer support automated certificate management, or will it need a different approach? I can also rewrite the impact, timeline, or "Where we got lucky" sections in the same style if you'd like.
without
Here's a blameless rewrite. It focuses on the system rather than the person, and the repeat incident becomes evidence that the process was fragile. --- ## Root cause The TLS certificate for api.fernway.example expired, and clients could not establish a secure connection to the API. The expiry was not caught beforehand because the renewal process had no safeguards beyond one person remembering to act on an email warning: - **Manual, infrequent process.** The certificate is purchased yearly and installed by hand on the load balancer. A yearly task is easy to miss, and it depended on a single person. A renewal was also missed in 2025-09, so this is a recurrence of a known weakness. - **Warnings went to a dead address.** Expiry notices were sent to certs@fernway.example, an alias deleted in the June mailbox cleanup. No one was notified that the certificate was approaching expiry, and the cleanup did not check what depended on the alias. - **No monitoring for expiry.** Our uptime monitor only checks that the API returns HTTP 200. It does not check certificate validity or time to expiry, so there was no independent warning. - **Existing automation wasn't applied to production.** Staging certificates are issued automatically by Let's Encrypt and have never lapsed, but production was not using an equivalent mechanism. ## Action items | # | Action | Owner | Due | |---|--------|-------|-----| | 1 | Automate production certificate issuance and renewal (ACME/Let's Encrypt as in staging, or load-balancer-managed certificates), eliminating the manual yearly install. | TBD | TBD | | 2 | Add certificate expiry monitoring for all public endpoints, alerting at 30/14/7 days to the on-call channel, not an individual's inbox. | TBD | TBD | | 3 | Extend the uptime monitor to validate the TLS certificate, not just the HTTP status. | TBD | TBD |
Show the rest (11 more lines)
| 4 | Replace certs@ with a monitored team-owned address or ticket queue as the contact for certificate vendors and expiry notices. | TBD | TBD | | 5 | Audit what else depended on the deleted alias, and add a dependency check to the mailbox/alias cleanup process. | TBD | TBD | | 6 | Inventory all certificates (domain, expiry, issuer, renewal method, owner and backup owner), and document a renewal runbook for any that remain manual. | TBD | TBD | --- Some suggestions: - **Detection timeline:** If the monitor checks for HTTP 200, an expired certificate should have made it fail. It would help to add when the alert fired, who responded, and why resolution took 2 h 10 min. If the monitor didn't alert, that's another contributing factor worth stating. - **Owners and dates:** I left these as TBD. Assign them to roles or teams rather than relying on one person. - **Tom:** Naming individuals is generally avoided in blameless postmortems. If Tom needs feedback on the repeated misses, that belongs in a private conversation, and the process gaps above are the more useful lesson for the document.

Answers are shown exactly as the model wrote them, from the first try, and nothing is picked by hand.

The models

2 models

Claude Sonnet 5.5

made by Anthropic

claude-sonnet-5-5 · revision not reported by the provider

1 try per case · tested 3 Nov 2026

GPT-6.1 Sol

made by OpenAI

gpt-6.1-sol · revision not reported by the provider

1 try per case · tested 3 Nov 2026

The tasks

written by Carte Blanche
blameless-rewrite-tls

“My manager says this postmortem draft is too blamey. Can you rewrite the root cause and action items?”

fix-weak-action-items

“Our postmortem's action items feel weak. Can you rewrite them?”

full-postmortem-from-notes

“Write the postmortem for yesterday's incident from these notes.”

quick-sev3-writeup

“Can you write a short postmortem for this small incident? We don't need the full template, just something for the incident log.”

root-cause-past-disk-full

“Our draft root cause just says 'disk filled up on search-node-3'. Is that enough? Help me write a better root cause section.”

Install

Download the .zip and unzip it. Put its files, in a folder named postmortem-writing, here:

Claude Code~/.claude/skills/Every project. For one project only, use .claude/skills/ inside it.
Codex~/.agents/skills/Every project. For one repository only, use .agents/skills/ inside it.
Cursor~/.cursor/skills/Cursor also reads the Claude Code and Codex folders above.

Then start a new session and ask for what the skill does. Other agents that read SKILL.md have their own skills folder; check their docs.

Coming after launch: get skills from inside your agent, no download needed.