Skip to content

Claude Code inbox delivery can get stuck in PENDING due to stale PROCESSING status detection #104

@dongwook-chan

Description

@dongwook-chan

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

  1. Start cao-server
  2. Launch a code_supervisor with --provider claude_code
  3. Ask it to spawn 3 reviewer agents with assign and have each reviewer send results back with send_message
  4. Wait until all reviewers report completion
  5. 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:

  • ccf7ab48

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

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions