Files
hermes-agent/gateway
teknium1 953b6f6f08 fix(update): never disarm the host restart obligation, and never discharge unknown terms
Review findings on the host-scoped update→restart obligation.

- update_cmd_fleet: an unwritable host state dir (read-only HERMES_GATEWAY_LOCK_DIR,
  container UID that does not own $HOME) made write_host_obligation return False and the
  caller ignored it, so an interrupted update left ZERO obligation — stale code, no
  warning, no catch-up restart. The return is now propagated: the legacy per-home marker
  (still read by every reader) carries it, and a host that can write neither says so.
- update_cmd_fleet::_obligation_fields: a PRESENT but unparseable/foreign-versioned host
  record no longer falls through to the legacy marker; terms nobody can read cannot be
  discharged by another record's terms.
- update_cmd_fleet::_restart_identity_sha: zip/pip/Docker installs resolve no checkout
  SHA, so the restart-once stamp was "" and could never match — every profile's update
  re-killed the one shared multiplexer. Falls back to the record's expected_sha, then the
  receipt's post-update identity.
- update_host_obligation: any main_pid probe error is unproven identity (keep its own
  restart), never an aborted restart pass.
- run_notifications: the online notice dedupes per home CHAT, so two served profiles
  sharing one chat get one message (accounting stays per profile); transport resolution is
  isolated per profile, so one broken adapter no longer starves the rest of the fan-out.
- run_adapters / run_profile_reconcile: _profile_configs is pruned with the served set, so
  a failed or removed profile no longer owes a notice nothing can deliver and
  .restart_pending.json is unlinked.

Tests cover the new format's own hazards: unwritable record dir, foreign-version record
with a legacy marker present, non-git install, shared home chat, broken adapter, pruned
config, plus a parity test for the duplicated host-state-dir resolver.
2026-09-21 07:14:37 -07:00
..
…