Repository navigation
vscode: re-bucket Builders tree — actively-communicated blocked builders sort below active, truly-blocked stays on top #798
Copy link
Copy link
Open
Labels
area/vscodeArea: VS Code extensionArea: VS Code extensionprojectNew project or featureNew project or feature
Description
Problem
The Builders tree treats every gate-blocked builder as equally urgent — they all sort to the top with a bell icon and a wait-time suffix. In practice, "blocked" splits into two very different cases:
- Truly blocked — the builder hit a gate (e.g.
plan-approval) and nobody has touched it since. This is the one that wants attention. - Blocked while the architect is actively in dialog with it — the gate is open but the engineer is mid-conversation, sending messages, iterating. Surfacing this row at the top with the same urgency as a truly-stuck builder is noise; the engineer already knows it's there because they're typing to it right now.
The current top-bucket placement makes the second case feel like an alarm that won't quiet.
Current state
- Sort order in
packages/vscode/src/views/builders.ts:23–28(orderForDisplay):blocked(anyb.blockedtruthy), sorted byblockedSinceascending.idleWaiting(isIdleWaiting(b, now)).active(everything else).
OverviewBuilder.lastDataAt(@cluesmith/codev-types, exposed viaoverview.ts:73) already tracks when Tower last received output from the builder's shell — updated whenever the architect's input echoes back or the agent emits anything.isIdleWaiting(b)(packages/core/src/builder-helpers.ts:30) returns true for non-blocked, non-complete builders silent pastIDLE_WAITING_THRESHOLD_MS = 5 minutes(line 19). The same threshold is the natural cut-off for "actively communicating" applied to blocked builders.
Proposed behavior
1. New predicate
Add isActivelyCommBlocked(b, now) in packages/core/src/builder-helpers.ts:
export function isActivelyCommBlocked(b: OverviewBuilder, now: number = Date.now()): boolean {
if (!b.blocked) return false;
if (!b.lastDataAt) return false;
return now - new Date(b.lastDataAt).getTime() <= IDLE_WAITING_THRESHOLD_MS;
}Co-located with isIdleWaiting so the threshold policy stays in one place.
2. New four-bucket sort order
Top-down:
- Truly blocked —
b.blocked && !isActivelyCommBlocked(b). Sorted longest-blockedSincefirst. - Idle waiting —
isIdleWaiting(b)(unchanged). - Active — everything that doesn't match the others (unchanged).
- Actively-comm blocked —
isActivelyCommBlocked(b). Sorted most-recent-lastDataAtfirst (so the one you're typing into right now is at the bottom-most slot — close to where the input cursor sits in the terminal pane).
3. Visual treatment
- Truly blocked: existing bell icon + wait-time suffix; unchanged.
- Actively-comm blocked: distinct icon (e.g.
$(comment-discussion)instead of$(bell)) and the row label still surfaces the gate (blocked on <gate>) so the user remembers which gate is in play — but the visual weight is de-emphasised (no wait-time scream). - Idle-waiting and active: unchanged.
4. Threshold reuse
Use the existing IDLE_WAITING_THRESHOLD_MS = 5 minutes — no new tunable. A blocked builder you haven't typed to in >5 minutes promotes itself back to "truly blocked" (top bucket), which matches user intent: dialog has stalled, the gate is now really blocking.
Acceptance criteria
-
isActivelyCommBlocked()predicate added topackages/core/src/builder-helpers.ts, alongsideisIdleWaiting. -
orderForDisplayinviews/builders.tsreturns four buckets in the order above. - Truly-blocked rows render unchanged (bell icon, wait-time suffix).
- Actively-comm-blocked rows render with a distinct icon and no wait-time suffix; gate label preserved.
- Sort ordering reactively updates as
lastDataAtticks past the threshold (no extra polling — relies on existing SSE refresh cadence). - No additional Tower instrumentation needed; uses existing
lastDataAt.
Out of scope
- A separate threshold for "actively communicating" different from
IDLE_WAITING_THRESHOLD_MS(intentionally — one threshold, one policy). - Manual "I'm working on this" flag.
- Auto-collapse / auto-pin of the actively-comm group.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
area/vscodeArea: VS Code extensionArea: VS Code extensionprojectNew project or featureNew project or feature
Activity