Skip to content

fix(warp): don't send task-complete while background tasks are still running - #85

Open
neeilya wants to merge 1 commit into
warpdotdev:mainfrom
neeilya:fix/stop-hook-respect-background-tasks
Open

fix(warp): don't send task-complete while background tasks are still running#85
neeilya wants to merge 1 commit into
warpdotdev:mainfrom
neeilya:fix/stop-hook-respect-background-tasks

Conversation

@neeilya

@neeilya neeilya commented Sep 6, 2026

Copy link
Copy Markdown

Problem

on-stop.sh sends the task-complete payload on every Claude Code Stop event. But Stop fires whenever the main agent's turn ends, including:

  1. the turn that launched background sub-agents (Agent tool) or background shells that are still running, and
  2. every short re-invocation turn the harness runs when one of those tasks completes.

So a prompt that fans out to three sub-agents produces four "task complete" banners, three of them while work is still in progress, and Warp's session status flips to Complete and back to Working each time. Reported in #67 and #82.

Fix

Claude Code ≥ 2.1.145 includes a background_tasks array in Stop hook input listing in-flight sub-agents, shells, monitors, workflows and teammates (hooks reference). This is the official signal #82 asked for.

  • New scripts/has-background-work.sh exposes has_background_work "$INPUT", true when any entry has status == "running".
  • on-stop.sh and legacy/on-stop.sh exit silently when it is true. The Stop that fires after the last task completes has an empty array and sends the one real notification.
  • Older Claude Code lacks the field, so behaviour there is unchanged. Only running counts, so an unfamiliar status fails open toward notifying rather than going silent.
  • README updated to describe the new Stop behaviour.

No changes to the payload schema or protocol version.

Testing

  • tests/test-hooks.sh: 66 passed, 0 failed. Adds unit tests for the helper (field absent, empty, running subagent, running shell, non-running entry, malformed input) and a routing test that on-stop.sh emits nothing with a running task and emits the stop terminalSequence once the array is empty.
  • Captured real Stop payloads from Claude Code 2.1.263 with a background shell and a background sub-agent in flight (both status: "running") and ran them through both Stop scripts: suppressed with tasks running, notification sent with the array emptied.
  • Live in Warp v0.2026.09.02.08.27.stable_01 with plugin 2.2.0 (unpatched): a prompt launching three background sub-agents produced four banners, matching the reproduction in Stop hook notifies on every sub-agent completion (<task-notification> re-invocations), spamming a banner per sub-agent #67.

Out of scope

session_crons (scheduled wake-ups from /loop, ScheduleWakeup, CronCreate) is left alone: a session idling between cron fires is arguably done with the current task, so it still notifies.

Closes #67
Closes #82

…running

Claude Code fires `Stop` whenever the main agent's turn ends, including
turns that launched background sub-agents or shells that are still
running, and again each time one of them finishes and wakes the main
agent. `on-stop.sh` sent a task-complete notification on every one of
those, so a prompt that fans out to three sub-agents produced four
banners, three of them while work was still in progress. Warp's session
status also flipped to Complete and back to Working with each one.

Claude Code >= 2.1.145 includes a `background_tasks` array in Stop hook
input listing in-flight sub-agents, shells, monitors, workflows and
teammates. Use it: if any entry has status `running`, exit without
notifying; the Stop that fires once the last task completes sends the
single real notification. Older Claude Code lacks the field, so nothing
changes there. Only `running` counts, so an unknown status fails open
toward notifying rather than going silent.

Applies to both the structured and legacy Stop scripts, and adds unit
tests for the helper plus a routing test for on-stop.sh.

Closes warpdotdev#67
Closes warpdotdev#82
@neeilya
neeilya marked this pull request as ready for review September 6, 2026 11:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant