Repository navigation
fix(status): cover Claude failure, idle and session-switch hooks; add stuck-state fallbacks - #310
Merged
Merged
Conversation
… stuck-state fallbacks Once a hook has been seen, a hook-driven session ignores output cadence entirely, so every turn ending Claude does not report left the session "running" until something else corrected it. This closes the endings the hooks can report and adds two bounded fallbacks for the ones they cannot. Hooks now observed for Claude: - StopFailure, which Claude runs instead of Stop when a turn ends on an API error (rate limit, overload, auth). It completes the turn like Stop; only the error type is forwarded. - SessionEnd and SessionStart, installed with a `clear|resume` matcher so the helper never runs on ordinary startup, compaction or exit. When the pane's own conversation ends by /clear or an in-pane /resume, the session start that follows within 30 s with the matching source is adopted: the native session id, usage tracking (local and the remote reader), subagent rows and the id used by restart and workspace restore all move to the new conversation. Without that pending end, a mismatched session id is still dropped, which is what keeps a nested `claude -p` from driving the pane. - The browser-URL elicitation notification, reported as an elicitation dialog. A parent idle_prompt is now authoritative: Claude only sends it once no background agent is running, so it clears subagents whose SubagentStop never arrived instead of deferring to them forever. Fallbacks, Claude only (Codex behaviour is unchanged): - Silence watchdog: a hook-confirmed running turn with no PTY output and no hook event for two minutes drops to cadence mode and shows waiting. Claude's TUI redraws while it works, so that much silence means the end signal was lost. It does not fire while hooks report a running subagent, because a background agent can work behind a still prompt. - Interrupt hint: a lone Esc or Ctrl+C typed into a running hook-driven pane drops it to cadence mode until the next hook. Claude sends no hook on interrupt. Only the single key byte counts; escape sequences do not. Sessions in either fallback rest at waiting rather than decaying to idle, so the hook that later confirms the pause does not notify a second time. The overlay scrub now also removes Tether-managed entries from event keys this version does not install, and leaves keys without one untouched. Nothing here reads or alters PTY output. The helper stays silent on stdout for every new event (SessionStart stdout is injected into Claude's context), which the helper tests assert. This reverses one previously tested behaviour: a confirmed Claude turn no longer stays running through unlimited total silence. The Codex version of that test is kept. Tests: tsc --noEmit clean; eslint clean on touched files; vitest 2334 passed, 1 failed (src/main/usage/remote-command.test.ts real-POSIX-shell test, which fails on this Windows host independently of this change). Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Summary
Once a hook has been seen, a hook-driven session ignores output cadence entirely, so any turn ending Claude does not report left the session "running" until something else corrected it. This PR closes the endings hooks can report and adds two bounded fallbacks for the ones they cannot. Part 1 of 2 for the status-detection findings in the 2026-11-09 review.
New Claude hooks observed
StopFailure— Claude runs it instead ofStopwhen a turn ends on an API error (rate limit, overload, auth). It completes the turn likeStop. Only the error type is forwarded, nevererror_detailsor the message text.SessionEnd/SessionStart, installed with aclear|resumematcher, so the helper is not spawned on ordinary startup, compaction or exit.elicitation_url_dialognotifications, reported as an elicitation dialog.Following
/clearand in-pane/resumeclearorresume, a session start with a different session id and the matching source is adopted if it arrives within 30 s.claude -porclaude --resume(which inherits the pane's Tether env) from taking over the pane. Adopted ids must be UUID-shaped.Ghost subagents
idle_promptis now authoritative. Claude only sends it once no background agent is running, so it clears subagents whoseSubagentStopnever arrived instead of deferring to them forever.Fallbacks for a stuck "running" (Claude only; Codex is unchanged)
EscorCtrl+Ctyped into a running hook-driven pane drops it to cadence mode until the next hook, because Claude sends no hook on interrupt. Escape sequences (arrows, focus reports, bracketed paste) do not count.Overlay
Boundaries
SessionStarthook's stdout is added to Claude's context); the helper tests assert this.Behaviour change to be aware of
In-app docs updated:
src/docs/sessions.md(session states, resume),src/docs/settings.md(CLI hooks).Test plan
npx tsc --noEmitnpx eslinton the touched source and test filesnpx vitest run— 2334 passed, 1 failed:src/main/usage/remote-command.test.ts(real POSIX shell), which fails the same way on the untouched base on this Windows host/clearin a hooked pane, then send a prompt: status follows the turn, usage shows the new conversation, and restart reopens it/resumeto another conversation in a hooked pane: same checks; then quit and relaunch to confirm restore reopens the conversation you switched toclaude -pfrom a pane's Bash tool: the pane's status and id are unaffected/clearmoves remote usage collection to the new conversationOut of scope
PermissionRequest(instant permission state) and an input-side "permission resolved" hintagent_needs_inputand thequota_auto_resume_*notification types/branchand otherforksession starts: noSessionEndreason identifies them, so the pane is not followed there🤖 Generated with Claude Code