| name | rollback-postmortem |
| description | Close the loop after a feature is rolled back. Records landed:rolled-back, writes a blameless postmortem from the contract's own timeline + guard reports + Sentry, posts it to Slack, and reopens the work as a follow-up. Invoked by /postmortem <ID> after a human confirms the rollback. The one ending the end-to-end loop was missing. |
| requiredScopes | ["sentry:read","slack:chat:write","github:issues:write"] |
Rollback postmortem
When rollback-guard recommends a rollback and the team reverts, the
loop has to actually end somewhere — with the status recorded and the
lesson captured, not just a flag flipped and silence. That's this skill.
It runs after a human has confirmed the rollback happened (you don't
flip flags — see rollback-guard). It's blameless by construction: the
output describes what the system did and what was learned, never who to
blame.
Inputs
- Contract ID
- Optional: a one-line reason from the human ("iOS crash on cold start")
- Optional: the guard report that triggered it
(
.manifest/contracts/<ID>.guard-*.md)
Process
1. Confirm a rollback actually happened
Read the contract. A postmortem is only appropriate once the feature is
no longer at its rollout stage (flag flipped off / previous release
redeployed). If the latest guardVerdict isn't recommend-rollback
and the human gave no reason, ask the human to confirm the rollback
before proceeding — don't write a postmortem for a feature that's still
live.
2. Reconstruct the timeline (from data the contract already has)
You don't need new infrastructure — the contract's own cycle-time
stamps plus the guard/deploy reports are the timeline:
promotedAt, prMergedAt, qaDeployedAt, canaryStartedAt,
currentRolloutPercent — when each stage happened and how far it got.
- The
guard-*.md reports — the signal that breached, when it was
first seen, and the values vs budget.
- Sentry (via MCP) — the top issues for the release tag: error class,
first-seen, affected users, stack location.
- The deploy report(s) — what verification said before rollout.
3. Write the postmortem
.manifest/contracts/<ID>.postmortem.md:
---
contractId: <ID>
revision: <N>
type: rollback-postmortem
generatedAt: <ISO>
rolledBackAt: <ISO>
rolledBackAtStage: 10%
---
# <title> — rollback postmortem
## What happened
One paragraph: what shipped, how far it ramped, what signal breached,
when it was caught, and what action was taken. Plain, blameless.
## Timeline (IST / UTC)
| When | Event |
|---|---|
| <t> | Promoted; SLA started |
| <t> | Merged; deployed to QA (verify: ready-for-canary) |
| <t> | Canary started at 1% |
| <t> | Advanced to 10% |
| <t> | rollback-guard: recommend-rollback (error rate 4.2× baseline) |
| <t> | Flag flipped to 0% by <owner> |
## Signal that breached
The guard verdict + the signal table: observed vs budget, adoption %,
and the top Sentry issue(s) with first-seen and affected users.
## Contributing factors
Blameless. What about the change, the spec, or the verification let this
reach users? Was there an edge case the contract didn't cover (link the
finding if so)? Did verification pass because the failure only appears
under real traffic / a cohort QA didn't exercise?
## What went well
Detection worked — the guard caught it at N% before full rollout. Note
the blast radius that was avoided.
## Action items
- [ ] <owner> — concrete fix (with a tracking ref)
- [ ] Add the missed edge case to the contract before re-promoting
- [ ] (if verification gap) strengthen the AC / device-cohort coverage
## Re-ship plan
The contract reopens at the spec phase: address the contributing
factors in a new revision, re-verify, re-promote. Link the follow-up.
3.5 Propose a bug pattern — if (and only if) the cause is a code shape
Look at the contributing factors. If one is a code-level bug class a
diff-level review could have caught — the shape of the bug, not a one-off
typo, not a spec/infra/process gap — propose it for the catalog so the same
class can't ship twice. This is the learning loop in reference/BUG-PATTERNS.md.
Append a candidate entry to reference/bug-patterns.candidates.md (the
staging file — never edit BUG-PATTERNS.md directly; a human accepts it
there). Use the catalog entry format plus two fields:
### <next-id> — <plain-English name>
**Where it bites**: <the user-visible impact this rollback showed>
**The shape**: <minimal stack-agnostic code example of the bug>
**Why it slips past basic review**: <one line>
**The fix**: <minimal code example after the fix>
**Where first observed**: postmortem <ID>
**Severity**: warning # machine-proposed → warning until proven
**Status**: provisional
Get <next-id> deterministically: node <plugin-root>/scripts/validate.mjs --next-pattern-id. Then validate the staging file structure:
node <plugin-root>/scripts/validate.mjs --check-patterns <plugin-root>/reference/BUG-PATTERNS.md <plugin-root>/reference/bug-patterns.candidates.md.
Be conservative. Only propose when the bug genuinely generalizes and is
detectable on a diff. If the cause was a missed edge case in the spec, a
flaky test, a config mistake, or an infra outage, do NOT propose a pattern —
that belongs in Action items, not the catalog. No candidate is fine; a noisy
catalog is worse than a small one. Note in the postmortem whether you proposed
one (and its candidate id) so the maintainer knows to review it.
4. Stamp the contract
landed: rolled-back
landedAt: <ISO> (the rollback is the terminal state for this revision)
rolledBackAt: <ISO>
- Leave
slaHit as recorded; a rollback doesn't retroactively change
whether the first 100% (if any) hit SLA — but note in the
postmortem that the feature did not durably land.
5. Reopen the work — don't let it vanish
A rolled-back feature is not a finished feature. Create the follow-up so
it can't silently disappear:
- If Atlassian/JIRA or GitHub Issues MCP is connected: open a follow-up
issue titled
<ID> re-ship after rollback, linking the postmortem and
the action items, and reference the original tracking issue.
- If the change is small and well-understood, suggest routing the fix
through the express lane (
/fix); otherwise the contract reopens
at the spec phase for a new revision.
Never close the tracking issue as "done" — a rollback is the opposite of
done.
6. Post to Slack
Reply in the contract's thread with the verdict (rolled-back) and a
3-line summary, AND post a brief top-level alert (rollback is an
urgent-alert exception) linking the postmortem and the follow-up issue.
DM the contract owner the full postmortem link.
Anti-patterns
- Not blameless. Never name a person as the cause. Describe systems,
specs, and gaps.
- Don't flip flags or revert. The human already did the rollback;
you record and learn from it.
- Don't write "success — caught early!" as if the rollback were the
goal. Detection working is good; the feature still didn't land. Say
both.
- Don't close the loop as "done." Reopen it.
- Don't invent a root cause the data doesn't support — if Sentry is
thin, say the cause is unconfirmed and make "reproduce + confirm" the
first action item.
Slack threading
Replies go in the contract's thread (thread_ts: <contract.slackThreadTs>, channel <contract.slackChannel>); the
rollback also posts the brief top-level alert. (See
reference/CONTRACT-FORMAT.md.)