Appearance
Host lifecycle
A Host moves through a small, well-defined set of states. The state is recorded in <host-home>/host.status.json and the durable on-disk record is the source of truth — process liveness is checked against host.pid on read.
States
The IHostStatus.status field (projects/matrix-3/packages/host-service/src/types.ts:124) is one of:
"starting"—MatrixHostService.start()is running, NATS sibling has been spawned (or external NATS verified), but supervisor control has not yet bound. Brief; if you see it persist, look for a stuck NATS handshake."running"— supervisor control is bound onhost.supervisor.PID-<pid>.$inbox, auto-start runtimes are being launched or are running. Steady state."stopping"—MatrixHostService.stop()has begun. Runtimes are being asked to shut down via theircontrolMountthen SIGTERM'd if they don't acknowledge."stopped"— written briefly duringstop()thenhost.status.jsonis removed. If you see this on disk it means the Host crashed mid-stop.
isLiveStatus in projects/matrix-3/packages/host-service/src/host-state-store.ts:1207-1209 treats "starting", "running", and "stopping" as live.
Install -> start -> run
text
1. hivecast install --home <home>
- mkdir <home>; drop bundled nats binary; seed system package store
- generate host.json, credentials/hivecast-install.json
- register default runtime targets (manual or auto per --no-start)
- if not --no-start: hivecast start
2. hivecast start --home <home>
- acquire host.start.lock (cli.ts:1031-1057)
- if status="running" already, refuse: { ok: true, alreadyRunning: true }
- start NATS sibling (or verify external NATS reachable)
- recover orphaned auto runtime records
(matrix-host-service.ts:578-622)
- write host.status.json with status="running"
- bind supervisor control on host.supervisor.PID-<pid>.$inbox
- auto-start runtimes whose record has startup="auto", in priority order
(matrix-host-service.ts:494-541)
3. running
- supervisor watches every runtime child; on exit,
- record final status (stopped|failed) atomically
- if restart policy applies, schedule a restart 1s later
(matrix-host-service.ts:484-489)
- host-control runtime publishes device.heartbeat every 15s
4. hivecast stop --home <home>
- cli.ts:140-143 -> stopRunningHost
- try host.supervisor "shutdown" RPC first (graceful)
- on timeout, SIGTERM the host pid
- on second timeout, SIGKILL
- finally, stop NATS siblingCrash recovery
Two recovery codepaths matter:
1. Orphaned auto-start runtimes
If the Host process crashes while live runtimes are still running, the next MatrixHostService.start() calls _recoverOrphanedAutoRuntimeRecordsBeforeStart (projects/matrix-3/packages/host-service/src/matrix-host-service.ts:578-622):
- For every runtime record with
startup: "auto"and a live status:- If the recorded
pidis still alive but its commandline / cwd no longer matches the record, mark it failed with astaleReason. - Otherwise, SIGTERM the orphan, then SIGKILL after 2s. Mark the record
stoppedwithorphanRecoveredAtmetadata.
- If the recorded
- If any orphan refuses to die, refuse to start. The Host will not auto-spawn duplicates of a runtime whose old process is still consuming its mount.
2. Corrupt runtime records
Before this work, a single zero-byte runtime.json would crash start. Now HostStateStore.listRuntimeRecordsAndCorrupt (projects/matrix-3/packages/host-service/src/host-state-store.ts:106-142) parses-and-skips: returns the healthy records and the corrupt list separately. hivecast seed reports the corrupt list honestly. Auto-start re-seeds the record on the next start. See WORKSTREAMS/launch-readiness-atomic-writes-and-bootstrap/ for the full work — atomic writes (every Host JSON file goes through atomicWriteJson), parse-and-skip recovery, journald cap, and unit hardening (StartLimitBurst=5, StartLimitIntervalSec=60).
State transitions diagram
mermaid
stateDiagram-v2
[*] --> installed: hivecast install
installed --> starting: hivecast start
starting --> running: NATS up + supervisor bound
starting --> failed: NATS or supervisor refused
running --> stopping: hivecast stop / SIGTERM
stopping --> stopped: graceful or signal-driven shutdown
stopped --> [*]
running --> running: runtime crash + restart policy
failed --> starting: human re-runs hivecast startfailed is not a host.status.json value — it is what an operator sees from hivecast doctor when bootstrap returned an error.