fix(desktop): show main workspaces in the board's Needs review column
Fixes #7126
Problem
The Workspaces board's Needs review column never showed type: "main" workspaces. deriveBoardColumn rule 7 only routed agentStatus === "review" to the column when workspace.type === "worktree", so a finished agent on a project's main checkout fell through to Idle. The sidebar's green "Ready for review" dot, the dock badge, and the page's own "Ready for review" agent filter all treat that same workspace as review-worthy, so the board (and the list view, which groups with the same helper) disagreed with every other surface.
Fix
Narrow the gate to exclude only session workspaces instead of allowing only worktree ones:
if (workspace.agentStatus === "review" && workspace.type !== "session") {
Why main and session are different. Workspace type is a three-value union: main, worktree, session.
mainandworktreeare both project checkouts a person is driving. There is at most one main checkout per project per host, so it is bounded, and a finished agent there means the same thing it means on a worktree: go look.sessionworkspaces are automation and chat runs with no project checkout (the optional-project work from #6274). They arrive in volume, and routing them to Needs review would bury the real candidates. The original doc comment's "arrives in volume" reasoning applies to them and only them, so they stay excluded.
The doc comment on deriveBoardColumn now names exactly which kind is excluded and why.
Tests
Extended the co-located deriveBoardColumn.test.ts:
- main + review => review
- worktree + review => review
- session + review => idle
- all existing cases unchanged
bun test src/renderer/routes/_authenticated/_dashboard/v2-workspaces/utils/deriveBoardColumn
10 pass, 0 fail
bun run typecheck in apps/desktop exits 0.
Verified over CDP in the dev app
Drove this worktree's dev desktop app (renderer on its own Vite port, CDP on a dedicated port) through the real user journey: open a project's main checkout (mastra-superset), open a terminal, navigate back to the Workspaces board, then fire the agent lifecycle hooks (SessionStart, Stop) at the host-service for that terminal without reopening the pane.
Rule in deriveBoardColumn.ts | Board | Sidebar |
|---|---|---|
main branch (type === "worktree") | mastra-superset main at the top of Idle (Idle 47 / Needs review 9) | green "Ready for review" dot |
this PR (type !== "session") | same card at the top of Needs review (Idle 46 / Needs review 10) | green "Ready for review" dot |
The swap was done in place by checking out the main-branch file and letting Vite hot-reload, then restoring HEAD, with the same agent binding in the host-service the whole time. Screenshots are in the session.
Two things learned along the way, in case anyone repeats this: the board's agent-status query only refetches while the window is focused, so a CDP-driven window needs Page.bringToFront plus focus emulation before it picks up new bindings; and the host-service list only includes bindings for live terminals, so a session workspace whose run has already exited can never reach review through this path in the first place. The session exclusion itself is covered by the unit test.
i18n
No user-facing strings touched. Column labels are unchanged, so no catalog updates.