- scripts/preflight.sh: app+server tsc, eslint, i18n, vitest; installed as
.githooks/pre-push (scripts/install-hooks.sh) and run by auto-deploy before
Netlify. Failures record preflight-failed and ops-health flags them.
- update-deps.sh: if the blanket npm update fails, restore the lock and retry
patch-level packages one at a time, keeping those that pass a fast gate; the
final npm test + smoke still gates the result, otherwise revert + 3-day retry.
- release.sh/deps set SKIP_PREFLIGHT=1 (they run the full npm test themselves).
The deploy timer can record a dirty-tree skip mid-edit; once the tree is clean
that reason is stale. Verify git status before flagging it (and parse the timer
NEXT row only when it is a real timestamp).
A push seconds before an ops-health run has no skip reason yet — that is
normal, not a problem. Only flag a missing skip reason once the deploy script
hasn't run for >6 min (i.e. the timer really looks stopped).
A non-site-only skip advances the recorded sha without a production deploy,
so 'deployed Nm ago' could read as if that sha was deployed. Say 'last
production deploy Nm ago' instead.
Two failures today were invisible: the ngit/Amber remote signer stalling
mid-push, and the deploy timer skipping while origin/main had moved.
- scripts/auto-deploy.sh records the reason for every skip (and the run time)
to ~/.local/state/skatespots-deploy/{last-skip,last-run}.
- scripts/ops-health.sh reads that back and prints repo/push sync, the skip
reason, the throttle window and timer health; exit 1 when action is needed.
--probe-push runs a bounded real push (the only true signer probe),
--notify desktop-notifies (deduped), --quiet is silent when healthy.
- Periodic watch: skatespots-ops-health.{service,timer} (every 15 min) plus
scripts/install-ops-health-timer.sh.
Docs: AGENTS.md Deploy section.