- Capture the docker compose ps status before testing its output, and
scan the Litestream log with grep's status read explicitly: 0 is a
logged error, 1 is no match, anything else fails the verification.
- Run both clean-ups on exit whatever happens, keep any failure, and
print the pre-deploy restore point only after every check and both
clean-ups succeeded.
- State that the live snapshot expects the existing -wal and -shm, list
their ownership after the snapshot, and say to stop and check the
service state if a root-owned sidecar appears.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The pre-deploy verification and the rollback migration check copied the
live mealquest.db and its WAL as separate files while the app and
Litestream ran, so a checkpoint between the copies could leave an older,
readable state: the rollback check could print "none" while the live
database held a migration the older SHA does not know.
Both now read the live database through /tmp/mqsnap.py, written once in
"Count check": SQLite's online backup API from a read-only connection,
then PRAGMA integrity_check, exiting nonzero unless it is ok. The
pre-deploy verification runs as one fail-fast subshell (set -eu, an EXIT
trap that cleans /tmp/mqcheck and the scratch restore while keeping the
status), diffs the replica and live count checks, and prints the restore
point only after every step has passed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Run the check in a set -eu subshell so a failed cd, copy, git ls-tree
or comparison stops it before any verdict is printed, and remove the
scratch directory from an EXIT trap that preserves the check's status.
Spell out the reading rule: none, listed versions, or stop on error.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The rollback check diffed all of migrations/, so a change to the sqlc
queries in migrations/queries/ sent the operator down the restore path and
discarded household changes made since the pre-deploy point. Compare the
versions in the live database's schema_migrations with the top-level *.sql
files at the previous SHA instead, the rule internal/store/migrate.go
enforces at start-up.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Write /tmp/mqcount.py from the Count check section with one heredoc
command, and give rollbacks that cross a migration an ordered
restore-then-start procedure separate from the plain restart.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
RUNBOOK: the deploy steps now verify, before the restart that applies
migrations, that Litestream replication is current and its replica
restores to the live data, and record the pre-deploy restore point; if
not, do not restart. The rollback section restores to that recorded point.
ARCHITECTURE: the rotation_check schedule that calls MarkTried is planned
(Feature 20); this release ships MarkTried and the rotation review read and
decide APIs only.
Task: 008c0a8a-2242-429b-a1fd-69346bc1d414
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>