feat(discord): systemd user service with a supervised run; brakes exit 3 and are never retried (#1509)
QUEUE row 17, MVP iteration 2. scripts/discord-service.sh renders and installs mosaic-discord@<binding> from packages/discord/systemd/. The unit's main process is `run --supervised`, which applies the new recover policy first: a lock whose owner is gone is cleared and only the STOP written for that is removed; an operator STOP or a held binding refuses with exit 3, which RestartPreventExitStatus never retries. `recover` is also a CLI verb. First cut used ExecStartPre and looped live, since systemd honours the never-retry status only from the main process; replaced and re-verified before any message traffic. Suite 40/40, 95 node tests. Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
@@ -2383,3 +2383,30 @@ node tests.
|
||||
Live check, 19:21 UTC: Jason sent a message in #sage-admin, the eyes reaction
|
||||
appeared on it before the reply, the turn record carries `receipt.ok` true,
|
||||
and a 0600 receipt sits in the private evidence directory. Row 15 done.
|
||||
|
||||
## 2026-09-13 — Discord service unit (#1509, QUEUE row 17)
|
||||
|
||||
Before: the Sage connector ran in a tmux window; a crash or a reboot left a
|
||||
stale `run.lock`, and every rerun after `stop` needed STOP removed by hand.
|
||||
After: `scripts/discord-service.sh install` renders and writes a systemd
|
||||
user unit, `mosaic-discord@<binding>`, whose main process is
|
||||
`discord.sh run <binding> --supervised`. The supervised run first applies
|
||||
the new `recover` policy (also a CLI verb): a lock whose owner is gone is
|
||||
cleared the way `unlock` does and only the STOP written for that is
|
||||
removed; an operator STOP, or a binding held by a live or unverifiable
|
||||
process, refuses with the new exit code 3, which the unit never retries.
|
||||
`systemctl --user stop` is the soft stop (SIGTERM, no STOP); `discord.sh
|
||||
stop` stays the brake. Tests: recover policy (clean, dead lock, no record,
|
||||
operator STOP untouched, own leftover STOP, foreign line, brake written
|
||||
during the unlock wins, live and unknown and invalid owners refuse without
|
||||
writing STOP), CLI exit codes, unit render and install and uninstall,
|
||||
`systemd-analyze verify`. Suite 40/40, 95 node tests. Loosening the STOP
|
||||
ownership rule fails three tests.
|
||||
|
||||
Correction, same day: the first cut used `ExecStartPre=discord.sh recover`.
|
||||
Live, a refused pre-start went into systemd's auto-restart, because
|
||||
`RestartPreventExitStatus` applies to the main process only. Caught on the
|
||||
first start behind a brake, before any message traffic; replaced by the
|
||||
supervised run as the main process and re-verified: SIGKILL recovered in
|
||||
16 s with the dead lock cleared, brake held with no restart, released and
|
||||
READY. The Sage seat now runs under the unit; the tmux session is gone.
|
||||
|
||||
Reference in New Issue
Block a user