Skip to content

fix(sidebar): show folder workspaces under Status and PR grouping - #9708

Closed
atiakr wants to merge 6 commits into
stablyai:mainfrom
atiakr:fix/sidebar-folder-workspaces
Closed

atiakr wants to merge 6 commits into
stablyai:mainfrom
atiakr:fix/sidebar-folder-workspaces

Conversation

@atiakr

@atiakr atiakr commented Jul 21, 2026 •

Copy link
Copy Markdown

Summary

When the left sidebar is grouped by Status or PR, folder workspaces disappear from the list. They only showed up when grouping by repo.

Folder workspaces now render in the right group under every grouping mode.
Header counts, sort order, host/sleeping filters, and Pinned all behave the same as they do for git worktrees.

Screenshots

before
스크린샷 2026-07-21 오후 12 08 37

after
스크린샷 2026-07-21 오후 12 04 11

Testing

  • pnpm lint — oxlint clean for the changed dirs (sidebar, store/slices/worktrees.ts). Full pnpm lint fails only on pre-existing switch-exhaustiveness errors in unrelated files (skill-freshness-group.tsx:101, daemon-server.ts:672) that this PR does not touch.
  • pnpm typecheck
  • pnpm test — the 6 changed sidebar test files pass (221 tests). Full suite: 33,206 passed; the 50 failures are all pre-existing and unrelated to this change (terminal IME composition tests, likely Node-24-vs-26 environment), in subsystems this PR does not touch.
  • pnpm build — build:desktop (typecheck + electron-vite + web) succeeds. Full pnpm build fails only at the native macOS build:computer-use (Swift lipo) step, an unrelated native toolchain issue outside this renderer change.
  • Added or updated high-quality tests that would catch regressions, or explained why tests were not needed

Additional validation (all passing):

  • worktree-list-groups.test.ts — folder rows in None/Status/PR lanes, Pinned emission + counts, duplicate-in-groups, mixed-host counts, sort interleaving
  • visible-worktrees.test.ts — computeVisibleFolderWorkspaces: archived always dropped, sleeping filter, live-agent keep, host-scope filter
  • worktree-list-folder-reveal.test.ts — reveal keys for Pinned/single-location, natural-lane under duplicate-in-groups, flat-lane in non-repo groupings, project headers in repo grouping
  • worktree-sidebar-row-preference.test.ts — isWorkspaceRowIdentityRendered, natural-copy dedupe/order
  • host-section-rows.test.ts — folder rows counted in host sections without double-counting pinned duplicates

AI Review Report

The AI code review checked the following risks:

  • Count consistency — header counts match the actual rendered row count once folder rows are included (Pinned/None/Status/PR headers), and per-host counts on mixed-host headers are not double-counted.
  • Row identity collisions — under the duplicate-in-groups policy the Pinned copy and the natural copy of one folder workspace don't share a virtualized row key / DOM id (resolved via a distinct row.key), and the active surface (primary/secondary) stays on the clicked copy only.
  • Sort consistency — folder rows sort with the same comparator as git worktrees instead of being appended at the end of a lane, including the Smart cold-start and live-attention merge paths.
  • Filter consistency — host-scope and sleeping filters apply to folder rows the same way computeVisibleWorktreeIds applies them, and archived workspaces are always dropped first.
  • Eligibility — stale/manual project-group references without a parentPath stay hidden (unchanged behavior).

Cross-platform: This change is pure renderer (React) sidebar logic. It does not touch file paths, keyboard shortcuts, shell execution, or Electron platform branches, so behavior is identical on macOS, Linux, and Windows.

Security Audit

No changes to input handling, command execution, path handling, auth, secrets, dependencies, or IPC. This only changes renderer-side list composition logic and adds no new dependencies.

Notes

  • Pinned policy interaction: under duplicate-in-groups a pinned folder renders in both Pinned and its natural lane; under single-location it renders once.
  • Reveal timing: after toggling a folder's pin, reveal waits for the meta round-trip to settle so the scroll lands on the row's new (pinned) position.
  • Follow-up: full pnpm lint / pnpm test / pnpm build still to be confirmed in CI.

ELI5

Folder workspaces vanished from the sidebar when grouped by Status or PR; they only showed under repo grouping. They now appear in the right group for every grouping mode, with the same filters and counts as git worktrees.

@atiakr
atiakr force-pushed the fix/sidebar-folder-workspaces branch from f3a02d6 to c708f8f Compare July 21, 2026 07:00
@coderabbitai

coderabbitai Bot commented Jul 21, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Folder workspaces are integrated into sidebar visibility filtering, host routing, grouped and pinned row construction, status-based sorting, and reveal-target calculation. Rendered row keys now identify folder workspace copies across virtual rows, DOM options, activation, rename, and active-surface selection. Duplicate folder rows are deduplicated in sidebar ordering. Folder pin metadata updates are awaited before revealing the corresponding sidebar row. Tests cover visibility, host routing, grouping, identity, reveal keys, and deferred pinning.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.92% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: showing folder workspaces under Status and PR grouping in the sidebar.
Description check ✅ Passed The description follows the template well, with Summary, Screenshots, Testing, AI Review Report, Security Audit, and Notes all present.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/renderer/src/components/sidebar/WorktreeList.tsx (1)

5661-5691: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Stabilize visibleFolderWorkspacesForRows identity across agentStatusEpoch bumps.

This memo now depends on agentStatusEpoch, so when sleeping workspaces are hidden it recomputes to a brand-new array on every epoch bump even when the visible set is unchanged. It feeds both folderWorkspaceSortComparator and the rows useMemo dependency list, so a fresh identity churns the entire rows/sectionRows/renderedWorktrees chain per epoch — the exact churn the sibling visibleWorktrees avoids via useReusedArrayIdentity (see the comment at Line 5557).

Consider wrapping the result the same way for consistency.

♻️ Proposed change
-  const visibleFolderWorkspacesForRows = useMemo(() => {
+  const recomputedVisibleFolderWorkspacesForRows = useMemo(() => {
     // Why agentStatusEpoch: sleeping-state membership must update immediately
     // without subscribing to the full agent-status map (same as worktrees).
     void agentStatusEpoch
     return computeVisibleFolderWorkspaces(folderWorkspaces, {
@@
   }, [
     agentStatusEpoch,
     browserTabsByWorktree,
     defaultHostId,
     folderWorkspaces,
     projectGroups,
     ptyIdsByTabId,
     showSleepingWorkspaces,
     tabsByWorktree,
     visibleHostIdSet
   ])
+  const visibleFolderWorkspacesForRows = useReusedArrayIdentity(
+    recomputedVisibleFolderWorkspacesForRows
+  )

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: fab14ea5-5a65-4fb0-bff9-4d1908e30110

📥 Commits

Reviewing files that changed from the base of the PR and between 42bff5e and f3a02d6f0153867917a1fa34164aa282bc3d8963.

📒 Files selected for processing (15)
  • src/renderer/src/components/sidebar/WorktreeList.lineage-child-card.test.ts
  • src/renderer/src/components/sidebar/WorktreeList.tsx
  • src/renderer/src/components/sidebar/host-section-folder-workspace-rows.test.ts
  • src/renderer/src/components/sidebar/host-section-rows.test.ts
  • src/renderer/src/components/sidebar/host-section-rows.ts
  • src/renderer/src/components/sidebar/visible-worktrees.test.ts
  • src/renderer/src/components/sidebar/visible-worktrees.ts
  • src/renderer/src/components/sidebar/worktree-list-folder-reveal.test.ts
  • src/renderer/src/components/sidebar/worktree-list-folder-reveal.ts
  • src/renderer/src/components/sidebar/worktree-list-groups.test.ts
  • src/renderer/src/components/sidebar/worktree-list-groups.ts
  • src/renderer/src/components/sidebar/worktree-sidebar-row-preference.test.ts
  • src/renderer/src/components/sidebar/worktree-sidebar-row-preference.ts
  • src/renderer/src/store/slices/worktrees.test.ts
  • src/renderer/src/store/slices/worktrees.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/renderer/src/components/sidebar/WorktreeList.tsx (1)

5706-5708: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove redundant array allocation.

recomputedVisibleFolderWorkspacesForRows is already a newly evaluated array. Spreading it again creates an unnecessary array allocation before identity reuse.

♻️ Proposed refactor
-  const visibleFolderWorkspacesForRows = useReusedArrayIdentity([
-    ...recomputedVisibleFolderWorkspacesForRows
-  ])
+  const visibleFolderWorkspacesForRows = useReusedArrayIdentity(
+    recomputedVisibleFolderWorkspacesForRows
+  )

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 36ef0e3c-4385-4ac0-b09c-4c4abd096c3b

📥 Commits

Reviewing files that changed from the base of the PR and between 1e271cb and 25f7762.

📒 Files selected for processing (4)
  • src/renderer/src/components/sidebar/WorktreeList.card-memo-stability.test.tsx
  • src/renderer/src/components/sidebar/WorktreeList.tsx
  • src/renderer/src/store/slices/worktrees.test.ts
  • src/renderer/src/store/slices/worktrees.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/renderer/src/store/slices/worktrees.test.ts
  • src/renderer/src/store/slices/worktrees.ts

@nwparker nwparker added the bug Something isn't working label Jul 27, 2026
Conflict resolution notes:
- visible-worktrees.test.ts: main moved the sidebar-filter tests to
  sidebar-filter-state.test.ts; keep that split and retain only this
  branch's folder-workspace visibility tests.
- WorktreeList: use main's extracted filterProjectGroupsForVisibleHosts,
  and keep computeVisibleFolderWorkspaces (a superset of main's
  filterFolderWorkspacesForVisibleHosts: archived + sleeping filters).
- navigateWorktree: adopt main's rendered-rows cycling
  (getCyclableWorktreeIds / resolveCycledWorktreeId) instead of the
  rebuilt all-expanded layout, and extend it to folder-workspace rows so
  arrow keys and Cmd+1-9 stay on the same order. Folder keys dispatch
  through activateAndRevealWorkspace for the path-status gate.
- visible-worktrees.ts: split computeVisibleFolderWorkspaces into
  visible-folder-workspaces.ts; both sides grew the file past max-lines.
@nwparker

Copy link
Copy Markdown
Contributor

Thanks for this, @atiakr, and for the before/after screenshots! main already fixed it in #15404 (1272406), which closed #15362: folder-workspace membership is now decided above the Group by switch, so folder workspaces render under Status, PR status and None too (including folder-only flat lists and collapsed lane headers). It shipped in v1.4.187. Closing as superseded — please reopen if you see a grouping mode where they still go missing.

@nwparker nwparker closed this Oct 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants