fleetregister

fleetregister <session> <jobid> <pid> [note]

A watcher REGISTERS itself instead of being inferred. fleetwatch then reports a
job watched iff a registered pid is alive (kill -0) -- no cmdline parsing.

Why: inferring watcher-ness from cmdline text is family A of
docs/checks-that-reassure.md -- the check cannot distinguish the watcher from
anything else that merely mentions the job. fleetwatch itself fell into it on
2026-09-12, counting the coordinator as a watcher because a one-shot command
named the job id. Raised by a study session: don't infer, register.

A registration is NOT a ledger entry. A ledger claims "I am watching X" in prose
and nothing can falsify it. This claims {pid, job} and `kill -0` falsifies it
the moment the watcher dies -- which is also how a DEAD watcher gets noticed,
something nothing else here detects.

fleetregister --clear <session> <jobid>

Remove a finished watcher's registration. Refuses while the registered process
is still alive (same pid AND starttime): clearing a live watcher would make its
job read UNWATCHED while it is being watched. Before 2026-09-13 there was no
clear, and sessions deleted registration files by hand.

Exit: 0 everything cleared; 1 no registration matched; 3 something was skipped
because its watcher is live -- a partial clear, which is not a failure and is
not success either.

Usage

# at arm time, from the session that starts the watcher:
fleetregister <session> <jobid> <watcher-pid> ["note"]

# when the job has ended and its result has been read:
fleetregister --clear <session> <jobid>

From a watcher that runs as a systemd-run --user unit, call it by absolute path ($HOME/bin/fleetregister, or wherever install linked it). A unit gets the user manager’s PATH, which after a reboot is only the system directories, so a bare fleetregister there fails with “command not found”, even if the same unit worked before the reboot.

A registration is <state>/watchers/<session>-<jobid>-<pid>.json:

{"session": "...", "job": "...", "pid": 12345, "starttime": "...",
 "armed": "<ISO time>", "note": "..."}

starttime is field 22 of /proc/<pid>/stat. The pair (pid, start time) is the identity fleetwatch checks; a registration without a start time is read as dead.

Registering a pid that is not running fails. --clear refuses while the registered process is still alive (same pid and start time, not a zombie), and fails if nothing is registered for that session and job.