Verifying dsh-phoenix
August 31, 2026 · View on GitHub
This is a reproducible checklist for confirming dsh-phoenix actually does what it claims. Everything below is observable from the dsh journal and a couple of HTTP requests — no debugger needed.
dsh-phoenix's graceful-restart feature assumes the dsh Web runs as a systemd --user service (default unit
dsh-web). On other setups setDSH_PHOENIX_RESTART_CMD(see README) or only the reconnect/re-arm features are active.
0. Load check
# the row is loaded and logs at startup
journalctl --user -u dsh-web -f | grep dsh-phoenix
# expect: [dsh-phoenix] loaded (graceful restart + client reconnect ...)
1. Client auto-reconnect
curl -s http://127.0.0.1:3080/__dsh_health
# => {"token":"<boot-token>"}
# the served index carries the injected heartbeat
curl -s http://127.0.0.1:3080/ | grep -o 'var last=' | head -1
Restart the backend and watch the token change:
systemctl --user restart dsh-web
# the browser page reloads itself because the token changed
2. Graceful restart (idle-aware)
Trigger a real plugin update (e.g. define + run a dynamic plugin via the dsh plugin tools), then watch the journal:
journalctl --user -u dsh-web -f | grep dsh-phoenix
While an agent is running you should see deferring (agent busy). After the
agent goes idle you should see agent idle; executing deferred restart and then
systemd-run ... with a stop → sleep → start sequence.
3. Restart disabled on non-systemd
With no systemd binaries on PATH and no DSH_PHOENIX_RESTART_CMD set, the plugin
logs systemd user services not detected; graceful restart DISABLED and a
cordis_run trigger is skipped (no restart), while reconnect/re-arm still work.
4. Cross-restart goal re-arm
- Create a goal (e.g.
create_goalwith an objective and a round cap). - Point
DSH_PHOENIX_STATE_FILEat a JSON file and setpendingResume: true. - Restart dsh, then watch the journal:
journalctl --user -u dsh-web | grep dsh-phoenix
# expect: [dsh-phoenix] re-armed goal after resume (rev=N)
# and the state file's pendingResume is cleared to false (one-shot)
The re-armed goal then drives the next round automatically.
5. Unit tests
npm test
# 17 tests covering: state-machine transitions, resume at-most-once per generation,
# stale/corrupt checkpoint, restart coalescing, defer soft/hard escalation,
# restart-command failure, resume failure, restart/resume loop prevention