Domain-health timeouts smaller than the lobe runtimes caused false critical infra alerts
hermes · confidence high · status active
tags: hermes domain-health attention timeout false-positive monitor
The attention scan raised infra: TimeoutExpired: Command '['/Users/dwayne/.hermes/scripts/hermes_cmd_status.py']' timed out after 60 seconds as a
critical item. Nothing was broken: the lobe is simply slower than the budget its caller gave
it. hermes_cmd_status.py shells out to hermes_ops_status.py, which ran two hermes CLI
commands back to back; each loads the full config and takes 10 to 80 seconds. Measured
2026-09-12: hermes status alone 20 to 35s, hermes cron status 7 to 77s, so the wrapper ran
in 21 to 106s against a 60s call limit in hermes_domain_health.py. The timeout was recorded
as severity: critical, reason command failed or degraded, and stayed sticky until the next
scan rewrote state.
Two separate defects surfaced:
- The 60s lobe budget in
hermes_domain_health.run()was smaller than the observed runtime of the slowest lobe. Same mismatch existed in every caller:hermes_attention_sentinel.py(120s for a 113s domain pass),hermes_cognitive_cycle.py(120s),hermes_cmd_attention.py(120s), andhermes_cmd_today.py(45s for ops, 20s for the cron lobe). hermes_ops_status.pyran its twohermesCLI calls serially. They are independent, so running them in a thread pool collapses the pass to the slower of the two: measured 19.5s total against 25s serial.
Fix applied 2026-09-12: concurrent CLI calls in hermes_ops_status.py; lobe budget 150s in
hermes_domain_health.py; caller budgets raised to 200s (sentinel, cognitive cycle, attention
command); hermes_cmd_status.py inner timeout 180s with its message no longer hardcoding
120s; hermes_cmd_today.py ops 90s and cron 90s. The sentinel's run() also now catches
exceptions and returns an empty string, so one slow lobe can no longer crash the whole
attention pass. Verified after the change: hermes_cmd_status.py returned health: ok in
23.5s, and a full domain pass returned infra: info - healthy in 102.7s, with the attention
sentinel printing [SILENT].
Rule: when a monitor's timeout is shorter than the runtime of the thing it calls, the monitor
lies. Measure the child's real duration before choosing a budget, set each caller's timeout
above its callee's, and treat TimeoutExpired in a health artifact as a budget defect first
and a service fault second. Independent child processes in a status wrapper should run
concurrently, not in sequence.
Sources:
~/.hermes/scripts/hermes_domain_health.py · ~/.hermes/scripts/hermes_cmd_status.py · ~/.hermes/scripts/hermes_ops_status.py · ~/.hermes/scripts/hermes_attention_sentinel.py · ~/.hermes/ops/state/domain_health.json · ~/.hermes/ops/state/last_alerts.json