Skip to content

vscode: builder briefly appears under 'Uncategorized' area group after cleanup before disappearing #907

@amrmelsayed

Description

@amrmelsayed

Symptom

When a builder is terminated (via afx cleanup -p <id>, the right-click Cleanup Builder action, or any other removal path), the Builders tree shows a transient intermediate state for several seconds:

  1. Builder is in its correct area group (e.g. VSCODE or TOWER) — normal state
  2. afx cleanup runs → builder's worktree directory is removed, terminal killed, etc.
  3. For ~2-5 seconds: the builder reappears under the UNCATEGORIZED group at the bottom of the Builders tree
  4. Eventually disappears entirely from the tree

The intermediate UNCATEGORIZED appearance reads as a real reclassification event to the user — they may briefly wonder "why did this builder lose its area?" — when in fact the builder is just being cleaned up.

When it started

After #818 (Builders area grouping) merged. Before #818, builders rendered as a flat list, so a cleanup-in-progress builder briefly appeared in the flat list before disappearing — no surprising classification jump. After #818, the area-grouping projection means cleanup-in-progress builders with missing/empty areas[] get dropped into Uncategorized until they're fully gone.

Plausible root causes (for investigation)

The builder should pick one of these via reproduction with logging, before fixing:

  1. Stale overview data during cleanup window — The overview cache returns a OverviewBuilder record where areas: [] for the cleanup-in-progress builder. The groupByArea helper in packages/core/src/area-grouping.ts correctly puts areas: [] into Uncategorized. Fix would be to either filter out cleanup-in-progress builders from the projection, or preserve the original areas[] until the builder is fully removed.

  2. Cleanup-induced wire-payload partial stateafx cleanup may emit overview SSE events where the cleanup-in-progress builder has been partially mutated (some fields cleared, others not yet). If areas[] gets cleared first while the builder is still in the overview list, it briefly classifies as Uncategorized.

  3. Race between afx cleanup's removal phasesafx cleanup does several things in sequence (kill terminal, remove worktree, drop state.db row). The overview cache refreshes via SSE at various points. A refresh that fires AFTER the worktree directory is removed but BEFORE the OverviewBuilder record is dropped from overview would have areas[] empty (no labels available because the underlying issue lookup may key off the worktree's existence).

  4. discoverBuilders disk-scan source skipping areas population during cleanup — Per the pir-883 fix that switched the diff source to disk-scan, discoverBuilders reads .builders/<id>/ to enumerate active builders. If the directory is being removed, discoverBuilders might emit a record with empty areas[] because the underlying issue lookup fails for a partially-cleaned-up builder.

Acceptance criteria

  • Root cause identified via reproduction with logging — not just a plausible hypothesis
  • No intermediate Uncategorized appearance during cleanup — cleanup-in-progress builders should either stay in their original area group until they fully disappear, OR disappear immediately without the intermediate state
  • Reproduce locally: spawn a builder against an issue with a clear area label (e.g. area/vscode), wait for it to appear in the VSCODE area group, then afx cleanup -p <id>. The builder should NOT briefly jump to UNCATEGORIZED before disappearing
  • Visual verification in running VSCode session — unit tests on the projection helper alone won't catch this timing-dependent UX bug
  • No regression: builders without any area/* labels still correctly classify into Uncategorized in their normal lifecycle (not a side effect of fixing the transient state)
  • Regression test if the fix is unit-testable (e.g. simulate a cleanup-in-progress OverviewBuilder shape and assert the projection handles it correctly)

Fix options (pick after diagnosing the cause)

Depending on which root cause is identified:

If the cause is... Likely fix
Stale overview data Filter cleanup-in-progress builders from the projection (need a cleanupPending field on OverviewBuilder, or a similar signal)
Partial wire payload Ensure overview SSE events don't emit half-mutated records; mutations should be atomic from the wire's perspective
Race between cleanup phases Suppress overview refreshes during the cleanup window, OR have discoverBuilders skip directories that are mid-removal
discoverBuilders issue lookup race Fall back to the previous areas[] value when the current lookup fails (cache last-known-good)

Out of scope

  • Animating the transition (fade out from area, etc.) — over-engineering for v1; just suppress the intermediate state
  • Persistence of builder metadata after cleanup — cleanup means cleanup; the builder should disappear, not linger
  • Cleanup performance optimization — separate concern; this issue is about the UX during the window, not making the window shorter

Why BUGFIX (not PIR)

  • Symptom is clear (transient Uncategorized appearance), root cause is investigatable via logs/timing analysis
  • Multiple plausible causes listed — investigation phase resolves which is real
  • Fix surface is small (likely <50 LOC at the actual race/data-shape fix site)
  • Visual verification at PR time is sufficient — no need for a separate dev-approval gate on the running worktree before PR (BUGFIX assumes the reviewer + CMAP can verify the fix in the diff)

Related

Discovered while

Observing the Builders view during routine cleanup operations on 2026-05-28 after #818 + #885 + #895 area-grouping work landed.

Metadata

Metadata

Assignees

Labels

area/vscodeArea: VS Code extensionbugSomething isn't working

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions