Summary
send_message results can remain stuck in PENDING for Claude Code supervisors even after worker agents have finished and the supervisor is visibly idle.
The immediate symptom is that reviewer workers report successful completion and send_message, but the supervisor never receives those messages in-context.
Impact
- Parallel review / assign workflows can deadlock at the aggregation step
- Inbox messages accumulate in the DB as
PENDING
- The supervisor asks the user to manually paste worker outputs even though the workers already sent them
Reproduction
- Start
cao-server
- Launch a
code_supervisor with --provider claude_code
- Ask it to spawn 3 reviewer agents with
assign and have each reviewer send results back with send_message
- Wait until all reviewers report completion
- Observe that the supervisor is at an idle prompt, but the queued inbox messages are still not delivered
In my run, the 3 worker terminal IDs were:
d5ec8488
f3c39f1c
91bd4a56
The supervisor terminal was:
The inbox table showed all three messages still in PENDING for the supervisor:
select id,sender_id,receiver_id,status
from inbox
where receiver_id='ccf7ab48';
Root Cause
ClaudeCodeProvider.get_status() can incorrectly return PROCESSING when the terminal is actually idle.
The issue appears to be that the provider scans a large tmux scrollback buffer and checks PROCESSING_PATTERN before considering whether a newer idle prompt is already present. Old spinner lines left in scrollback (for example from terminal creation / send-input progress) can keep matching the processing regex even after the current terminal state has returned to IDLE.
That breaks inbox delivery because inbox_service.check_and_send_pending_messages() only delivers when the destination status is IDLE or COMPLETED.
Expected Behavior
If the latest visible terminal state is the Claude idle prompt, get_status() should return IDLE even when older spinner lines remain in scrollback.
Suggested Fix
When both processing and idle markers exist in the captured history, compare their latest positions and let the more recent marker decide the current state.
That should prevent stale spinner text in scrollback from masking the current idle prompt.
Notes
- This was observed on commit
2c66773700f3778e3f77332c2545f2fdca70ca6d
- Repository:
awslabs/cli-agent-orchestrator
Summary
send_messageresults can remain stuck inPENDINGfor Claude Code supervisors even after worker agents have finished and the supervisor is visibly idle.The immediate symptom is that reviewer workers report successful completion and
send_message, but the supervisor never receives those messages in-context.Impact
PENDINGReproduction
cao-servercode_supervisorwith--provider claude_codeassignand have each reviewer send results back withsend_messageIn my run, the 3 worker terminal IDs were:
d5ec8488f3c39f1c91bd4a56The supervisor terminal was:
ccf7ab48The inbox table showed all three messages still in
PENDINGfor the supervisor:Root Cause
ClaudeCodeProvider.get_status()can incorrectly returnPROCESSINGwhen the terminal is actually idle.The issue appears to be that the provider scans a large tmux scrollback buffer and checks
PROCESSING_PATTERNbefore considering whether a newer idle prompt is already present. Old spinner lines left in scrollback (for example from terminal creation / send-input progress) can keep matching the processing regex even after the current terminal state has returned toIDLE.That breaks inbox delivery because
inbox_service.check_and_send_pending_messages()only delivers when the destination status isIDLEorCOMPLETED.Expected Behavior
If the latest visible terminal state is the Claude idle prompt,
get_status()should returnIDLEeven when older spinner lines remain in scrollback.Suggested Fix
When both processing and idle markers exist in the captured history, compare their latest positions and let the more recent marker decide the current state.
That should prevent stale spinner text in scrollback from masking the current idle prompt.
Notes
2c66773700f3778e3f77332c2545f2fdca70ca6dawslabs/cli-agent-orchestrator