Before submitting
Area
apps/server
Steps to reproduce
- Start a thread with the Claude provider and keep working until the context fills up enough that Claude Code compacts on its own (do not type
/compact).
- Watch the thread status in the web client while that compaction runs.
Expected behavior
Automatic compaction surfaces the same Compacting… state that #9293 added for the manual command, so it is obvious the agent is compacting rather than stalled.
Actual behavior
The thread just says Thinking (and Working for N) for the entire compaction, which can run for minutes with no output. It is indistinguishable from a stuck or looping turn.
The Compacting… state added by #9293 is gated entirely on an explicit /compact user message:
apps/web/src/components/ChatView.tsx:661 — isCompactCommandMessage matches a user message whose text is exactly /compact with no attachments
apps/web/src/components/ChatView.tsx:2945 — isCompacting is derived from that message plus turn timestamps
Automatic compaction produces no such message, and Claude's own start signal is discarded before any client can see it:
apps/server/src/provider/Layers/ClaudeAdapter.ts:3411 — SDKStatusMessage status:"compacting" is flattened into the generic waiting session state
apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts:261-279 — orchestrationSessionStatusFromRuntimeState collapses waiting into running
So by the time the orchestration session reaches the client, "compacting" and "running a normal turn" are the same value. compact_boundary only arrives after compaction, so the completed divider and token counts do render — but nothing marks the interval while it is running.
This is the case #7652 originally described (it names ClaudeAdapter's status:"compacting" → waiting flattening as the root cause). #7652 was closed as fixed by #9293, and #7714 — which did implement the automatic path via an optional statusDetail: "compacting" / compactingSince on OrchestrationSession, fed by Claude's status:"compacting", Codex's contextCompaction item, and OpenCode's session.time.compacting — was closed as superseded at the same time. #9293 only shipped the manual /compact command path, so the automatic case is still unhandled on main.
Impact
Minor bug or occasional failure
(Cosmetic in mechanism, but it reliably reads as a hung agent: users cancel turns and waste tokens because a multi-minute silent Thinking looks broken.)
Version or commit
main @ 6c58362 (line numbers above verified against that commit; originally observed on a fork tracking upstream 299404a)
Environment
Linux, web client served from source (apps/server + apps/web), Node 24.15, Claude provider.
Logs or stack traces
n/a — no error is produced; the status label is simply generic.
Workaround
None for automatic compaction. Typing /compact manually does show Compacting…, but that only covers the case that already works.
Before submitting
Area
apps/server
Steps to reproduce
/compact).Expected behavior
Automatic compaction surfaces the same
Compacting…state that #9293 added for the manual command, so it is obvious the agent is compacting rather than stalled.Actual behavior
The thread just says
Thinking(andWorking for N) for the entire compaction, which can run for minutes with no output. It is indistinguishable from a stuck or looping turn.The
Compacting…state added by #9293 is gated entirely on an explicit/compactuser message:apps/web/src/components/ChatView.tsx:661—isCompactCommandMessagematches a user message whose text is exactly/compactwith no attachmentsapps/web/src/components/ChatView.tsx:2945—isCompactingis derived from that message plus turn timestampsAutomatic compaction produces no such message, and Claude's own start signal is discarded before any client can see it:
apps/server/src/provider/Layers/ClaudeAdapter.ts:3411—SDKStatusMessagestatus:"compacting"is flattened into the genericwaitingsession stateapps/server/src/orchestration/Layers/ProviderRuntimeIngestion.ts:261-279—orchestrationSessionStatusFromRuntimeStatecollapseswaitingintorunningSo by the time the orchestration session reaches the client, "compacting" and "running a normal turn" are the same value.
compact_boundaryonly arrives after compaction, so the completed divider and token counts do render — but nothing marks the interval while it is running.This is the case #7652 originally described (it names
ClaudeAdapter'sstatus:"compacting"→waitingflattening as the root cause). #7652 was closed as fixed by #9293, and #7714 — which did implement the automatic path via an optionalstatusDetail: "compacting"/compactingSinceonOrchestrationSession, fed by Claude'sstatus:"compacting", Codex'scontextCompactionitem, and OpenCode'ssession.time.compacting— was closed as superseded at the same time. #9293 only shipped the manual/compactcommand path, so the automatic case is still unhandled onmain.Impact
Minor bug or occasional failure
(Cosmetic in mechanism, but it reliably reads as a hung agent: users cancel turns and waste tokens because a multi-minute silent
Thinkinglooks broken.)Version or commit
main @ 6c58362 (line numbers above verified against that commit; originally observed on a fork tracking upstream 299404a)
Environment
Linux, web client served from source (
apps/server+apps/web), Node 24.15, Claude provider.Logs or stack traces
n/a — no error is produced; the status label is simply generic.Workaround
None for automatic compaction. Typing
/compactmanually does showCompacting…, but that only covers the case that already works.