diff --git a/CLAUDE.md b/CLAUDE.md index c0b3e50b..4fe5940d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -237,6 +237,10 @@ read them à la carte. - **Rate-limit sentinel:** `{state_dir}/hyperhive-rate-limited` is written by the harness on 429 and cleared on retry. `ContainerView.rate_limited` reads it for the dashboard badge. +- **Auth-failed sentinel:** `{state_dir}/hyperhive-needs-login` + is written on a 401 mid-turn (OAuth credentials expired). + Harness requeues the inflight message and parks in + `wait_for_login` until the operator re-auths via the web UI. - **Context window:** defaults are in `services.hive-c0re.contextWindowTokens` (host nix, affects all agents). Per-agent default model via `hyperhive.model` in `agent.nix`. Watermarks are 75%/50% of the diff --git a/docs/turn-loop.md b/docs/turn-loop.md index 0bb9cd5a..db0aca0e 100644 --- a/docs/turn-loop.md +++ b/docs/turn-loop.md @@ -29,7 +29,15 @@ Each agent harness (`hive-ag3nt serve` or `hive-m1nd serve`) runs: (`Bus::emit_status("rate_limited")`), sleeps `HIVE_RATE_LIMIT_SLEEP_SECS` (default 300), then retries. The dashboard and per-agent page show a `⊘ rate limited` badge - while the harness is parked. + while the harness is parked. **Auth-failed detection** (closes + #419): both stdout and stderr pumps also match + `AUTH_FAIL_MARKERS` (`"authentication_failed"`, `401`, etc.). + On match the harness writes `{state_dir}/hyperhive-needs-login`, + emits `needs_login_idle` status, requeues the inflight message + (so it replays after re-auth), and parks in `wait_for_login` — + the same path used at boot. The operator re-authenticates via + the per-agent web UI login flow; on success the sentinel is + cleared and the queued message drives the next turn normally. 7. Emit `LiveEvent::TurnEnd { ok, note }`. Sleep `poll_ms` to avoid tight loops on transient failures.