harness: clear stale needs-login sentinel on healthy boot (#682)

The mara: 'many agents stuck at needs login? seem to do turns fine, no
needs login on agent page. dash shows needs login tho'.

Diagnosed: hive-ag3nt::events::Bus::emit_status writes
{state_dir}/hyperhive-needs-login when status flips to needs_login_idle
and only removes it when status flips to online. But the boot flow only
emits 'online' if the harness was previously parked in wait_for_login —
the LoginState::Online branch went straight into serve() without
touching emit_status. So a sentinel written on a prior boot (e.g. a
401-triggered park) survived a healthy re-spawn, and the dashboard's
auth_failed_sentinel(name) read it as still-needing-login forever after.

Fix: add bus.emit_status('online') at the top of the LoginState::Online
boot branch in both hive-ag3nt.rs (sub-agent) and hive-m1nd.rs (manager).
Idempotent — emit_status is a one-line write/remove on a tiny empty
file; calling it for an already-clean state is a no-op.

This addresses one half of #682. The other half (claude_has_session()
may EACCES on the agent's 0700-perm ~/.claude dir post-#658 root drop)
is c0re-side and tracked separately in the issue thread for damocles.

refs #682
This commit is contained in:
iris 2026-05-31 01:36:16 +02:00 committed by Mara
commit 1a236a4119
2 changed files with 19 additions and 0 deletions

View file

@ -95,6 +95,16 @@ async fn main() -> Result<()> {
));
match initial {
LoginState::Online => {
// #682: clear any stale `hyperhive-needs-login`
// sentinel from a prior boot that parked in
// `wait_for_login`. Without this the
// dashboard's `needs_login` chip would survive a
// healthy re-spawn since the `Online` branch goes
// straight into `serve()` and `emit_status("online")`
// — the only callsite that removes the sentinel — is
// never invoked on this path. Idempotent: when no
// sentinel exists the inner `remove_file` is a no-op.
bus.emit_status("online");
serve(
&cli.socket,
Duration::from_millis(poll_ms),

View file

@ -85,6 +85,15 @@ async fn main() -> Result<()> {
tokio::spawn(hive_ag3nt::forge_notify::run(cli.socket.clone(), true));
match initial {
LoginState::Online => {
// #682: clear any stale `hyperhive-needs-login`
// sentinel from a prior boot that parked in
// `wait_for_login`. Same bug as the sub-agent
// binary — without this the dashboard's
// `needs_login` chip survives a healthy re-spawn
// because the `Online` branch never invokes
// `emit_status("online")`. Mirror of the fix in
// `hive-ag3nt.rs`. Idempotent.
bus.emit_status("online");
serve(
&cli.socket,
Duration::from_millis(poll_ms),