row 185 (#1683): every activate backs up the stopped store

stack-release.sh activate now backs up the stopped store under its activation id on every run
with a store file, before any migration. Before this, backup_store ran only when the schemas
differed, so a same-schema activate took no backup and rollback --restore had nothing to name.
store-newer and migration-needs-flag still roll back before the backup, since those runs never
touch the store, and a missing store takes no backup.

BACKUP and TAKEN now mean two things. BACKUP is set by every backup, so the log line names it and
from_log backup finds it. TAKEN is set only right before a migration, so a gate failure after a
same-schema activate puts back the units and the wrapper and leaves the store as the failed run
left it. activate --plan prints a backup line, or "backup: none" with no store file. Rollback and
pm-on are unchanged; a same-schema rollback --restore already works through the row 181 guard.
docs/TOOLS.md "Pinned stack update" steps 5-7 say so.

stack-release.test.mjs updates T5, T11, T26 and T29 and adds T47-T51, with one fixture fault
(start-writes-row-<copy>). The three brief mutants are killed, and Filbert's two more (the backup
ahead of the schema checks, the plan line on a rollback) are killed by T6, T9 and T50.

This is the precondition for mos-0928 Part A, the re-pin from 89af38a83.

Filbert approved round 1 in #1683 comment 29404, with two non-blocking notes.
This commit is contained in:
darkwing authored and Jason Woltje committed 2026-10-20 02:09:49 -05:00
1 parent 6c88bc666f
commit 490e2771d3
3 files changed
+121 -16

No files matched your search

+14 -7
View File
@@ -420,22 +420,29 @@ refuses `capture-failed` before it stops anything. Adopt uses the same rule.
saves the unit files, drop-ins and wrapper under
`state/stack-rollback/<activation>/`, stops the Console then the bus, and
reads the stopped store. A `-wal` or `-shm` beside it refuses
`store-unclean` and leaves the store alone. A migration takes an
owner-only backup under `<dataRoot>/backups/stack/<activation>/` first.
`store-unclean` and leaves the store alone. Every activate then takes an
owner-only backup of the stopped store under
`<dataRoot>/backups/stack/<activation>/`, before any migration (row 185),
and the log line names it. A missing store file takes no backup. A store
outside the target's chain (`store-newer`) or a migration without
`--migrate` rolls back before the backup.
It installs the bus, the Console and the wrapper from the pointer's flags,
starts the bus then the Console, and runs the gate: both units active, a
live bus host for this start, Console `/healthz`, `stack-copy.sh check`
and, with `--pm`, exactly one `launched` journal line for a live run of
this start. A pass writes the pointer.
6. A gate failure puts back the saved units and wrapper, restores the backup
when a migration ran, keeps the store it replaced as
`bus.post-attempt-<stamp>`, where the stamp is the activation's second and
its suffix if it has one, starts the old copy and gates it. If that gate
6. A gate failure puts back the saved units and wrapper. The backup is
taken on every activate, but it is restored only when a migration ran.
A restore keeps the store it replaced as `bus.post-attempt-<stamp>`, where
the stamp is the activation's second and its suffix if it has one. After
a same-schema activate the store stays as the failed run left it. Then it
starts the old copy and gates it. If that gate
fails too, both units stay stopped, the log says `rollback-failed`, and
Jason or Mos settles it from the rollback set the message names.
7. `rollback BUSINESS` returns to the copy before the pointer's, taken from
the log. When the schemas differ it needs `--restore ACTIVATION`, with or
without a `-1` to `-9` suffix. Rows written after that backup need
without a `-1` to `-9` suffix. A same-schema rollback can take
`--restore` too, with the backup the activate took. Rows written after that backup need
`--events N`, and Jason decides first. The count covers events and every
table in `COUNTED` (row 181), the tables a bus writer fills without an
event. The `post-backup-events` refusal prints one count per table with