Status dots flicker: session-active detection is nondeterministic #20
Labels
No labels
bug
docs
enhancement
good first issue
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
pedromcaraujo/forge#20
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Symptom
The sidebar status dot flips between green (busy) and dim (idle) across
refreshes with nothing actually changing in the channel.
Cause
GET /statusinweb/tmux_ctl.pyderives state from two signals, OR'dtogether in
_classify():tmux capture-pane -p -t <name>grepped foresc to interrupt.~/.claude/projects/<slugged-cwd>/*.jsonlmtime withinBUSY_WINDOW = 45s.Neither is authoritative, and the OR flips:
continuously. A poll landing during a redraw, or while a long tool output
has scrolled the hint out of the visible region, simply misses it — next
poll it's back. This alone produces green -> dim -> green on refresh.
split or background window is invisible to it.
a multi-minute thinking/tool stretch writes nothing and
age > 45,leaving A as the sole signal — see (1). Symmetrically, the dot stays green
for 45s after a turn ends.
cwd light together; a
claude -pfrom any shell in that cwd lights both.So A is precise but unreliably sampled; B is reliably sampled but imprecise.
Fix
Take the state from Claude Code itself via hooks rather than inferring it
from the screen. A hook script brackets the turn (
UserPromptSubmit-> busy,Stop-> idle,PreToolUse/PostToolUseas heartbeat,Notification->idle since a permission prompt is "waiting on you") and writes a per-channel
state file the sidecar reads.
Caveats that keep this a hybrid rather than a pure replacement:
Stopdoes not fire on an Esc interrupt, nor when the session iskilled. So the sidecar still needs liveness guards: pid check for the kill
case, and pane-mark hysteresis (idle only after N consecutive misses) for
the Esc case.
fall back to today's logic.
Hysteresis on the pane signal is worth having regardless — it kills the
redraw-race flicker without changing anything else.