fix(hooks): don't let a background subagent clear the main agent's 'notification' wait#238
Merged
hoangsonww merged 1 commit intoJul 18, 2026
Conversation
Contributor
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
|
✅ All contributors have signed the CLA. Thank you! |
…otification' wait
PreToolUse/PostToolUse cleared awaiting_input_since unconditionally, assuming a
tool event means the human resumed. That breaks when the MAIN agent is blocked
on the user (AskUserQuestion/permission) while a BACKGROUND subagent keeps
firing tool events: the subagent's event wiped the wait, so consumers
(AI-Deck 12s poll, deck-web 5s WS) lost the 'waiting for you' signal — it
oscillated on/off in seconds and the two UIs disagreed.
Reuse the existing subagent-actor heuristic (findDeepestWorkingAgent while main
is 'waiting'): when a subagent is the actor, clear only PASSIVE waits
(stop/session_start/interrupted); preserve a genuine 'notification' wait. When
MAIN is the actor, clear unconditionally as before — keeps the documented
permission-mid-tool clear (PostToolUse) intact. Passive-clear-by-subagent is
retained on purpose: it flips a merely-Stopped session back to active while a
subagent still works ('idle only while no agent works').
Known residual: if the user answers mid-tool while a background subagent runs,
the notification wait can linger until the next Stop/UserPromptSubmit —
self-healing, and cheaper than a missed question.
Regression test in server/__tests__/awaiting-subagent-guard.test.js (proven to
fail on the pre-fix code). Fork patch for the home-network AI-Deck/deck-web
consumers; a focused upstream PR follows.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Doccy008
force-pushed
the
fix/subagent-awaiting-guard
branch
from
July 17, 2026 18:49
d3d75d8 to
0dd7978
Compare
Contributor
Author
|
I have read the CLA Document and I hereby sign the CLA |
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
Problem
PreToolUseandPostToolUseclearawaiting_input_sinceunconditionally, on the assumption that any tool event means the human resumed. That assumption breaks when the main agent is blocked on the user (anAskUserQuestion/ permission prompt) while a background subagent keeps firingPreToolUse/PostToolUse(e.g. WebSearch/WebFetch): the subagent's tool event wipes the wait, even though no human has responded.The flag then oscillates on/off in seconds, so consumers disagree about the same session — a fast poller catches an "on" moment and shows Waiting, a slower one catches "off" and shows active/working.
This is the same class of bug the code already fixed for
SubagentStop(see the comment above the switch: "A subagent or background tool finishing tells us nothing about whether the human has actually responded, so those events must NOT clear the flag.") —PreToolUse/PostToolUsewere simply not covered.Fix
Reuse the existing subagent-actor heuristic (
findDeepestWorkingAgentwhile the main agent iswaiting), which the same two cases already use for event attribution:PostToolUseclears an approved prompt).stop/session_start/interrupted); a genuinenotificationwait is preserved.Passive-clear-by-subagent is intentionally retained: it's what flips a merely-
Stop-ed session back to active while a subagent still works.Known residual (documented)
If the user answers mid-tool while a background subagent is running, the
notificationwait can linger until the nextStop/UserPromptSubmit. It's self-healing, and — since hook events carry no explicit agent id — indistinguishable from a subagent's own tool event without a heuristic. A lingering false "waiting" is cheaper than a missed one.Tests
server/__tests__/awaiting-subagent-guard.test.js— route-level, proven to fail on the pre-fix code:notificationwait across a background subagent'sPreToolUseandPostToolUse;stopwait via subagent activity;notificationwait when the main agent itself resumes (no working subagent).Full server suite green (670 tests).