After an ungraceful shutdown removePidFile never runs, so a stale
run/openchamber-<port>.pid outlives the process. The kernel can recycle that
PID to an unrelated process, and a liveness-only `process.kill(pid, 0)` check
then reports OpenChamber as "already running" and aborts startup — an infinite
crashloop under systemd Restart=always while the port is actually free
(issue #1721).
Verify identity, not just liveness, but only where it belongs:
- Add isOpenchamberProcessRunning(pid) = liveness + command-line identity, and
use it ONLY at the two sites that validate a PID read from a pid file (the
"already running" guard and the stale pid-file cleanup sweep). isProcessRunning
stays liveness-only for PIDs we know are ours (a freshly spawned daemon child,
processes we are stopping), so those paths cannot get a false negative.
- Identity works on Linux (/proc/<pid>/cmdline) and macOS (ps -o command=); on
Windows or where the command line can't be read it falls back to liveness, so
behaviour is unchanged there with no false negatives.
- Match the "openchamber" install-path segment (present for both @openchamber/web
and a source checkout, foreground and daemon entrypoints alike) so a recycled
stranger such as npm-cli.js or agentmemory is not mistaken for us.
- Clear the stale pid file once its recorded PID is no longer our process.
Adds unit tests for isOpenchamberCmdline and isOpenchamberProcessRunning,
covering the recycled-PID cases and a live non-OpenChamber process.