Baniloo Baniloo

July 30, 2026

A rollback actuator that isn't allowed to roll anything back yet

Shipping RollbackActuator and PagerDutyActuator complete postmortem's v2.0 actuator set — real, tested execute() logic gated behind a confirmation path that deliberately doesn't exist

Session 17 finishes with all five planned actuators shipped and none of the fallback cuts needed. RollbackActuator and PagerDutyActuator are both requiresConfirmation = true — the two highest-stakes actions in the system — which means both have real, tested, working execute() methods that the registry will never call on its own.

Real code behind a gate with no key yet

That’s not a contradiction, it’s the honest state of the feature. A human-triggered confirm-and-run path — a CLI prompt, an approval step — doesn’t exist in postmortem yet. Rather than fake it or leave RollbackActuator half-built until that path lands, Session 17 ships the actual logic: the real Vercel and Netlify API calls, tested against mocked responses, ready to fire the moment there’s a legitimate way for a human to trigger them. Live-verified through the real daemon with dry_run = false and a fully-configured rollback target, the registry still only ever wrote awaiting_confirmation to the audit trail. The gate held under the condition most likely to defeat it — someone who actually turned dry-run off.

Guessing is worse than asking

RollbackActuator targets an explicit, pre-configured deployment — project_id plus target_deployment_id for Vercel, site_id plus target_deploy_id for Netlify — instead of trying to infer “the last known-good deployment” from incident correlation. That inference is an unsolved problem in this codebase; there’s no reliable signal yet for which prior deploy was actually healthy. A wrong guess here doesn’t fail loudly, it rolls production back to a state nobody chose. Requiring the person configuring the actuator to say explicitly which deployment is the fallback is more work up front and a much safer failure mode.

The endpoints themselves came from Vercel’s and Netlify’s own API docs, not memory — worth stating plainly, because Vercel’s actual rollback endpoint (POST /v1/projects/{projectId}/rollback/{deploymentId}) is not the one a language model would guess from the general shape of their API.

The stretch goal that wasn’t a stretch

PagerDuty turned out to be the simplest of the five: the Events API v2 is one POST, dedup_key set to the incident ID so a retry pages once instead of twice. It had been planned as the cut-if-short stretch goal for the session; it shipped anyway because there was nothing left to cut around.

Running /spec-drift against the finished session caught two stale findings — CLAUDE.md’s leftover “actuators are stubs in v1” line, and the spec-drift skill’s own identity-invariant table, which would have flagged every future actuator as scope creep against a description that no longer matched reality. ACTUATOR_SPEC.md got rewritten to the actual contract. The README stayed untouched on purpose — its “stubbed actuator layer” language is still accurate for what’s live on npm today, and v2.0’s actuators aren’t released yet.

v2.0’s five actuators are built and tested. What’s next is the piece that makes RollbackActuator and PagerDutyActuator actually usable: a real confirm-and-run path for a human to approve what’s sitting in the audit trail as awaiting_confirmation.