From af284dbac7c28e1da93f75be66dbd81c40e4493f Mon Sep 17 00:00:00 2001 From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com> Date: Tue, 28 Apr 2026 14:06:19 -0700 Subject: [PATCH] fix(sidebar): let heuristic 'working' beat retained 'done' in worktree dot (#1228) Co-authored-by: Orca --- .../src/components/sidebar/WorktreeCard.tsx | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/renderer/src/components/sidebar/WorktreeCard.tsx b/src/renderer/src/components/sidebar/WorktreeCard.tsx index e70f7db3d22..07d93a8d676 100644 --- a/src/renderer/src/components/sidebar/WorktreeCard.tsx +++ b/src/renderer/src/components/sidebar/WorktreeCard.tsx @@ -154,10 +154,16 @@ const WorktreeCard = React.memo(function WorktreeCard({ // consulted too so the sky dot keeps glowing after the agent process exits, // matching the dashboard's retention behavior. // - // Priority (highest first): permission (blocked/waiting) > done > heuristic. - // permission wins over done because a newer blocked agent in the same + // Priority (highest first): permission (blocked/waiting) > heuristic + // 'working' > done > other heuristic ('active'/'inactive'). + // permission wins over everything because a newer blocked agent in the same // worktree means the user needs to act now, not admire a previous // completion. + // heuristic 'working' wins over done because a spinner means the user has + // already re-prompted the agent after it reported done — the newer "work + // in progress" signal is more informative than a retained completion dot. + // Only the 'working' heuristic earns this precedence; 'active'/'inactive' + // mean "quiet terminal", which shouldn't drown out a recent done. // Why: collapse live hook entries to booleans inside the selector so the // snapshot is a stable scalar (useShallow compares element identity — an // array of freshly-constructed {state,updatedAt} objects would never hit @@ -217,10 +223,16 @@ const WorktreeCard = React.memo(function WorktreeCard({ if (hasPermission) { return 'permission' } + // Compute the heuristic once so we can let 'working' beat done without + // letting quieter heuristic states ('active'/'inactive') erase a done. + const heuristic = getWorktreeStatus(tabs, browserTabs, runtimePaneTitlesForWorktree) + if (heuristic === 'working') { + return 'working' + } if (hasLiveDone || hasRetainedDone) { return 'done' } - return getWorktreeStatus(tabs, browserTabs, runtimePaneTitlesForWorktree) + return heuristic }, [tabs, browserTabs, runtimePaneTitlesForWorktree, hasPermission, hasLiveDone, hasRetainedDone]) const showPR = cardProps.includes('pr')