[Bug] Compaction loses track of in-flight agents, causing duplicate work

Status Open
Reported on v2.1.247
Maintainer reply None cached
Activity 1 comment · opened Aug 27, 2026

Environment

  • CLI 2.1.247, macOS darwin-arm64, Max 20x, main loop Opus 5
  • Related: #90034 (a live workflow leaves no record on disk either), #77730 (agent/task IDs stop resolving)

What happens

Compaction rewrites the main window while background agents keep running, untouched. After the rewrite there is no structured record of what is in flight. The compaction summary is free prose, so whether a running agent is mentioned at all depends on whether the model happened to write it down, and in what words.

The consequence is a session that concludes a unit was never started, and dispatches a second agent onto the same output file. Two agents then write the same artifact, and the loser's work is silently overwritten.

The important part is that there is no authoritative place to check. In-memory handles are gone after compaction, and per #90034 the on-disk run record for a workflow is not written until the run finishes. So both the fast path and the fallback path report nothing.

Evidence

Scanning 49 sessions with subagents active in the last 45 days, comparing each subagent transcript's lifespan against compaction timestamps in the parent session:

agent runs alive across a compaction:        11
sessions where that happened:                 2 of 49

session    agent                           agent_ran   compact_fired_at
788ae070   agent-a3a8a423bad0712bf          352.7m         17.2m in
788ae070   agent-a948fe392f0fa5970           14.7m          4.2m in
788ae070   agent-a01cd75272174fe21           14.7m         10.4m in
788ae070   agent-ad7dce89ea0e31397           12.9m          9.6m in
788ae070   agent-a02e54cb34eb80f78           12.2m          2.1m in

The first row is an agent whose transcript spans 5 hours 52 minutes, with a compaction firing 17 minutes into it. The session that launched it spent the remaining 5.5 hours with no in-memory handle on it.

That same session compacted 31 times in roughly 12 hours, so this is not a rare boundary condition on a long-running job. On a heavy day it is the normal operating state.

What I expected to find, and did not

I expected the compaction summaries to have dropped all mention of the running agents. They had not: 30 of the 31 summaries contain phrases like "in flight" or "still running."

That turned out to be evidence for the report rather than against it. Those mentions survive only because this user maintains a hand-rolled convention of writing an IN FLIGHT: <agent> -> <output path> - started <time> line into a file on disk before every dispatch, specifically to survive compaction. The prose in the summary is a description of that manual bookkeeping, not a record the product maintains. It carries no task IDs, so nothing in it can be used to query, wait on, or stop the agent it names.

So the failure is not that the information is always lost. It is that preserving it is left to the user, in prose, with no identifiers.

Ask

Any one of these would close it:

  1. Emit a machine-generated "agents in flight" block into every compaction summary: task ID, agent type, launch time, and target output path if known. Not left to the model to remember.
  2. Keep live agent handles resolvable across a compaction, so ListAgents and TaskOutput still work afterward (this overlaps #77730).
  3. Fix the disk side per #90034, so a compacted session at least has an authoritative place to look.

1 and 3 together would be enough. 1 alone would cover the common case.

Workaround

Write an IN FLIGHT line to a state file on disk before dispatching, and clear it when the output file lands. Check liveness by sampling the size of ~/.claude/projects/<slug>/<session>/subagents/agent-*.jsonl twice, 60 to 90 seconds apart, rather than trusting the transcript. A quiet agent is usually mid-write, not dead: a single long turn can go 5+ minutes with no output.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗