A single Claude Code or Codex logo looks simple until several sessions run together. One thread may need an answer, another may be stalled, and a third may still be working. If the monitor represents the provider with whichever transcript changed most recently, low-value activity can hide the one session that actually needs the user.
The correct reduction has two stages: classify every session independently, then rank those states by user urgency. Recency belongs only inside a tie between equally urgent states.
Why newest-first aggregation fails
Modification time answers which session wrote last. It does not answer which session deserves attention. A background worker can append routine progress after another thread has stopped at a permission prompt. A recently acknowledged handoff can also remain in a needs-you window while a sibling resumes useful work.
Three common failure modes follow from a recency-only rule:
- a working session masks an unanswered question in an older thread;
- an acknowledged handoff freezes the provider icon even though another session is running;
- a normal idle write hides a stalled session that should be investigated.
Use an explicit priority table
Agent Island v1.7.1 applies the same ordering in its released macOS and Windows activity monitors:
unacknowledged needs-you = 4
stalled = 3
working = 2
acknowledged needs-you = 1
idle / auth / rate limit = 0
An unanswered handoff wins because the next useful action belongs to the user. A stalled session comes next because an anomaly should not disappear behind normal activity. Working stays visible when there is no more urgent state. An acknowledged handoff drops below working: it is still part of the thread's history, but it must not pin the provider indicator after the user has dealt with it.
Idle, authentication, and rate-limit states use the base aggregation priority in this particular selector. Their detailed presentation and error signaling are handled elsewhere; the table should not be read as a universal severity taxonomy.
Let recency break ties, not set policy
After priority is assigned, the monitor sorts by priority and then by modification time. The newest session wins only when both candidates carry the same actionability. This keeps the result deterministic without letting timestamps redefine meaning.
ranked = sessions
.filter(provider)
.map(session => (session, priority(session)))
.sort(priority descending, modified descending)
providerState = ranked.first
The distinction matters for tests. A test suite should vary state and time independently: an older unanswered handoff must beat a newer working session, while the newer of two working sessions should win their tie.
Do not reduce the reminder queue to one session
The provider indicator and the alert queue solve different problems. A logo needs one representative state. Reminders need to preserve every open handoff. Agent Island therefore selects one best session for display but separately collects every needs-you thread, newest first.
That separation prevents one thread's acknowledgement from cancelling another thread's alarm. The reminder identity includes the provider, session, and turn, so two waiting threads remain two independent obligations even though the menu bar shows one aggregate state.
A compact multi-session test matrix
- Older unanswered needs-you plus newer working: show needs-you.
- Older stalled plus newer working: show stalled.
- Acknowledged needs-you plus working: show working.
- Two working sessions: choose the newer modification time.
- Two unanswered handoffs: choose the newer one for display, retain both reminders.
- Acknowledging one of two handoffs: keep the other reminder actionable.
- No sessions for a provider: return idle with no selected thread.
What the aggregate state does not prove
The selected state is a display decision, not evidence that other sessions stopped existing. It should never overwrite the per-thread records used for deep links, reminders, or diagnostics. A monitor that keeps the full set can change its presentation policy later without losing the underlying truth.
The priority implementation described here is visible in the tagged v1.7.1 release source for both platforms. The larger design principle applies to any developer tool that compresses concurrent workers into one status surface: aggregate by actionability, retain per-worker identity, and use recency only to settle equals.
