poll.py reports STALE-DISPATCH forever on any box that is not the dispatcher's nf-ve0n ← Beads

open priority 2 task unassigned

Twinned from https://github.com/cfsh/ninefold/issues/560 by tools/beads/import_github.py's reconcile pass.

On the WSL office box, poll.py --check reports WAKE: STALE-DISPATCH on every tick, and nothing a session can do will ever clear it.

CLAUDE.md gives that line the top of the table: *"before anything else — Tier-0 review is not completing ticks, so no verdict or label on any PR is current"*, it *"outranks the GAPS ledger"*, it *"holds the cron at 30m"*, and *"a freshly-touched log does NOT clear it"*. So a session here is told, every 30 minutes, that review is frozen — while review is in fact running normally.

It is a false positive, and the reason is structural

Measured here 2026-08-05, immediately after opening #558:

poll.py's liveness check (tools/pr/poll.py, the ~/.ninefold-reviewer heartbeat block) reads machine-local state and reaches the branch *"reviewer state dir exists, no heartbeat has ever been written… The dispatcher is not running. Check the schtasks job."* But the thing it is reporting on is not machine-local — the dispatcher runs on the Windows sandbox box and reaches every PR through GitHub. A stray state dir on any other box is enough to trip it permanently.

The existing guard rails do not help: they were built for the opposite error. #461 taught "never written is NOT evidence of death" and added the log_is_warm corroboration — but that clears to the *informational* ⓘ dispatcher: line only when dispatch.log is warm, and here there is no dispatch.log at all.

Two costs, and the second is the expensive one
  1. The cadence is pinned at 30m forever. POLL_CADENCE is held by the wake, so the idle back-off (hourly → 2h → 4h) can never engage on this box.
  2. An unclearable top-priority alarm trains sessions to ignore it. This is the line that is supposed to mean "stop, nothing you are reading is current". A session that sees it on every tick for a week, correctly diagnoses it as noise, and files it away has been taught to skip the real one.
Shape of a fix (unclaimed, and the call is not mine)

Some direction to pick from — this may want needs:direction:

Filed unclaimed by nf-dev-office-spawn while working #557 (PR #558). Not on my chunk — I hit it setting up this session's poll loop.

Dependencies

None.

Comments

No comments.

Add a comment