Part of #11839 (point 4: undone in one step, under a minute). The tree swapper already keeps the known-good tree and skips its preflight; nothing measures the rollback, so "under a minute" cannot be proven.
Done looks like:
[ ] One migration adds rollback_ms to keeper_release; the rollback path in src/keeper/swapper.ts reports it through the same timed hook the forward swap uses, and src/keeper/record.ts stores it.
[ ] The release card and release_keeper show "rolled back in Ns" for a rolled-back release.
[ ] One test: a rollback with a fake clock advancing 40 s records 40000 and the panel shows it; it fails without the change.
[ ] bun test on the touched tests and bun x tsc --noEmit pass.
Files: one migration, src/keeper/swapper.ts, src/keeper/record.ts, src/web/pages/keeper-panel.ts, one test.
Risks: never touch the release workflow or the chart.
Brief: a Sonnet builder (Mason or Scout).
Part of #11839 (point 4: undone in one step, under a minute). The tree swapper already keeps the known-good tree and skips its preflight; nothing measures the rollback, so "under a minute" cannot be proven.
Done looks like:
rollback_mstokeeper_release; the rollback path insrc/keeper/swapper.tsreports it through the sametimedhook the forward swap uses, andsrc/keeper/record.tsstores it.release_keepershow "rolled back in Ns" for a rolled-back release.bun teston the touched tests andbun x tsc --noEmitpass.Files: one migration, src/keeper/swapper.ts, src/keeper/record.ts, src/web/pages/keeper-panel.ts, one test. Risks: never touch the release workflow or the chart. Brief: a Sonnet builder (Mason or Scout).