[BUG] Background session stays "working" after its turn ends when the reply's last sentence starts with "I'll"

Status Open
Reported on v2.1.296
Maintainer reply None cached
Activity 0 comments · opened Oct 12, 2026

What happens

A background session (claude --bg) finishes its turn and sits idle at its prompt, but its job
state stays working indefinitely. claude agents --json shows it as status: "idle" with
state: "working", and every view that reads the job state shows it as still working. It only
corrects itself on the session's next turn.

The job's own state file shows the contradiction:

{
  "state": "working",
  "detail": "I'll go through the failures one by one.",
  "tempo": "idle",
  "inFlight": { "tasks": 0, "queued": 0, "kinds": [], "drainableMonitors": 0 }
}

tempo is idle and nothing is in flight, but state is working, and detail is the reply's
last sentence verbatim (not a summary).

Reproduction

In a background session, get a final reply that makes a conditional promise across two sentences,
e.g.:

When the test run finishes, paste the log here. I'll go through the failures one by one.

After the turn ends, claude agents --json shows "status": "idle", "state": "working" for the
session, and it stays that way.

Cause (from reading the 2.1.296 bundle)

The end-of-turn classifier runs a regex pre-classification before the LLM classifier, and when
the regex pass returns a result, the LLM classifier is skipped. One of its rules ("working-verb")
takes the last sentence of the reply (split on the last . , ! , ? or newline in the final
800 characters) and returns state: "working" if it starts with Let me, I'll, I will,
I'm going to, Checking, Running, etc., unless an exclusion regex matches. The exclusion
covers exactly this case (when the, once you, after it, if you, check back, ...), but it
is tested against the last sentence only. Here the condition ("When the test run finishes")
is in the sentence before, so the exclusion misses and the turn is classified as working.

Replaying the bundle's own regexes on the reply above: the working-verb regex matches the last
sentence, the exclusion does not match it, and the exclusion does match the last two sentences
together.

Related: interrupted turns

A turn interrupted by the user (Esc, [Request interrupted by user]) gets no end-of-turn
classification at all, so the job keeps its last mid-turn working (a tool step's detail) with
tempo: "idle" and an empty inFlight. Same symptom.

Suggested fixes

Any of these would do:

  1. Test the exclusion regex against the last two sentences, not only the last one.
  2. Don't let the regex pass return working when the turn has ended with nothing in flight

(inFlight.tasks === 0 && inFlight.queued === 0); fall through to the LLM classifier instead.

  1. When writing the turn-end state (the step that flips tempo from active to idle and records

inFlight), downgrade working to a settled state if nothing is in flight. This would also
cover interrupted turns.

Impact

The session is reported as working when it's waiting for the user, so anything that reads job
state (agent view, claude agents --json, status bars built on it) shows a finished session as
busy. The registry status (idle) is the only contradicting signal, and it would go away if the
worker were retired, leaving working as the only state on record.

Environment

  • Claude Code 2.1.296 (Homebrew cask), macOS 26 (Darwin 25.6.0), Apple Silicon
  • Background session via the daemon backend

View original on GitHub ↗