Skip to content

Focus queue: prioritize recently-finished agents above running ones (#333) - #338

Open
germanescobar wants to merge 1 commit into
mainfrom
issue-333
Open

Focus queue: prioritize recently-finished agents above running ones (#333)#338
germanescobar wants to merge 1 commit into
mainfrom
issue-333

Conversation

@germanescobar

Copy link
Copy Markdown
Owner

Closes #333.

What changed

The on-radar (focus queue) sidebar used to sort pinned sessions by focusPinnedAt ?? createdAt ascending — i.e. oldest-pin-first. That buried the agent that just stopped on its own — the one that actually needs attention — under long-idle sessions the user forgot to unpin.

Replace the single ascending sort with a partition + two sorts:

  1. Finished (inactive) sessions — most recently finished first (lastActiveAt desc).
  2. Running (active) sessions — oldest running first, so the most recently started running session lands at the very bottom (lastActiveAt asc).

From top to bottom:

1. most recently finished  (lastActiveAt desc)
2. ...
3. oldest finished still on radar
4. oldest still running    (lastActiveAt asc, oldest first)
5. ...
6. newest still running    (lastActiveAt asc → newest at the bottom)

Why this shape

  • The radar-inclusion filter (Boolean(session.focusPinnedAt)) is unchanged, so manually unpinned sessions still don't appear — and userUnpinned === true is server-side only, never reaches the client filter, so it can't regress.
  • focusDoneAt does not enter the sort: sessions marked done clear focusPinnedAt on the server (updateSessionFocus in server/lib/sessions.ts) and the sidebar filter removes them, so they never reach the queue.
  • lastActiveAt already doubles as the "finished-at" timestamp; the server updates it at the locations called out in the issue (reply, agent stream close). No new field needed.
  • The sort is extracted into a small pure helper sortFocusQueue(items) exported from client/src/components/sidebar.tsx so it can be unit-tested in isolation. The useMemo in Sidebar just builds the items and calls the helper.

Acceptance criteria

  • Given a mix of finished and running sessions on the radar, finished sessions appear above all running sessions.
  • Within the finished section, the most recently finished session is at the top; the least recently finished is at the bottom of that section.
  • Within the running section, the most recently started running session is at the very bottom of the queue; older-running sessions stack above it.
  • No regression for sessions where focusPinnedAt is unset (still hidden from radar) or where the user has manually unpinned (userUnpinned === true).
  • Behavior is unchanged on the server side; only the client-side sort changes.

Validation

  • New test file client/src/components/__tests__/sidebar-sort-focus-queue.test.tsx6/6 pass:
    • all-finished → newest-finished on top
    • all-running → newest-running at the bottom
    • mixed → finished block above running block, each internally sorted
    • ties on lastActiveAt → stable-sort fallback to array order (matches the issue's explicit allowance)
    • active-state transition → a session flipping from active to inactive in the same render moves from the bottom of the running pile to the top of the finished pile
    • immutability → input array not mutated
  • Full client test suite: 223/223 pass (no regressions in sidebar-delete-loading, sidebar-help-link, settings-responsive, agents-section, focus-advance-toast, or the lib helpers).
  • node --import tsx smoke-import of sidebar.tsx succeeds (both sortFocusQueue and Sidebar export correctly).

Out of scope

…333)

The on-radar (focus queue) sidebar used to sort pinned sessions by
`focusPinnedAt ?? createdAt` ascending (oldest-pin-first). That buried
the agent that just stopped on its own — the one that actually needs
attention — under long-idle sessions the user forgot to unpin.

Replace the single ascending sort with a partition + two sorts:

  1. Finished (inactive) sessions — most recently finished first
     (`lastActiveAt` desc).
  2. Running (active) sessions — oldest running first, so the most
     recently started running session lands at the very bottom
     (`lastActiveAt` asc).

The radar-inclusion filter (`Boolean(session.focusPinnedAt)`) is
unchanged, so manually unpinned sessions still don't appear. No server
changes; `lastActiveAt` is already updated at the locations called out
in the issue.

Extract the sort into a small pure helper `sortFocusQueue` so it can
be unit-tested in isolation, and add tests covering all-finished,
all-running, mixed, ties on `lastActiveAt`, and the active-state
transition (a session flipping from active to inactive moves from
bottom to top in the same render).

Refs #333.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

On-radar (focus queue): prioritize recently-finished agents above running ones

1 participant