feat(sidebar,git): thread folders, worktree labels, git sync control, CI status#4207
Conversation
… CI status Re-submits four previously reviewed features, rebuilt on current main after the sidebar refactor. Replaces pingdotgg#3069, pingdotgg#3070, pingdotgg#3071, pingdotgg#3075 and pingdotgg#3088, which were closed during backlog cleanup while stale. - sidebar: user-defined thread folders with drag reorder - web: custom display labels for worktrees - git-sync: VS Code-style publish/pull/push/sync control - composer: CI status next to the PR pill The multi-select thread context menu now composes both the folder move submenu and the upstream archive action: mark unread / move to folder / archive / delete.
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 3 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit c20e433. Configure here.
| @@ -74,9 +74,19 @@ export async function archiveSelectedThreadEntries< | |||
| export function buildMultiSelectThreadContextMenuItems(input: { | |||
There was a problem hiding this comment.
🟡 Medium components/Sidebar.logic.ts:74
When the global selection spans multiple projects, the "Move to folder" submenu applies the chosen folder to every selected thread, including threads whose projectKey differs from the clicked project. moveThreadsToGroup receives all selected keys, so cross-project threads are removed from their existing folders and assigned to a folder in the wrong project — they then silently disappear from that folder because its layout only renders threads for the target project. The submenu should either restrict the move to threads in the clicked project or disable the action when the selection is cross-project.
🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/components/Sidebar.logic.ts around line 74:
When the global selection spans multiple projects, the "Move to folder" submenu applies the chosen folder to every selected thread, including threads whose `projectKey` differs from the clicked project. `moveThreadsToGroup` receives all selected keys, so cross-project threads are removed from their existing folders and assigned to a folder in the wrong project — they then silently disappear from that folder because its layout only renders threads for the target project. The submenu should either restrict the move to threads in the clicked project or disable the action when the selection is cross-project.
There was a problem hiding this comment.
Fixed in 985513a. The move now applies only to selected threads in the clicked project, the label shows that count, and the entry is hidden when nothing in the selection belongs to the project.
There was a problem hiding this comment.
Sorry, I'm unable to act on this request because you do not have permissions within this repository.
| event.stopPropagation(); | ||
| return; | ||
| } | ||
| if (suppressThreadClickAfterDragRef.current) { |
There was a problem hiding this comment.
🟡 Medium components/Sidebar.tsx:538
After a drag is cancelled (e.g. via Escape, window resize, or tab visibility change), the next thread click is silently ignored instead of navigating or selecting. handleRowClick bails out when suppressThreadClickAfterDragRef.current is set, but that flag is only reset on a completed drop — the drag-cancel path never clears it. @dnd-kit/core 6.3.1 can cancel an active pointer drag without producing the trailing click this guard expects, so the flag stays true indefinitely and the first post-cancel click is swallowed.
🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/components/Sidebar.tsx around line 538:
After a drag is cancelled (e.g. via Escape, window resize, or tab visibility change), the next thread click is silently ignored instead of navigating or selecting. `handleRowClick` bails out when `suppressThreadClickAfterDragRef.current` is set, but that flag is only reset on a completed drop — the drag-cancel path never clears it. `@dnd-kit/core` 6.3.1 can cancel an active pointer drag without producing the trailing click this guard expects, so the flag stays `true` indefinitely and the first post-cancel click is swallowed.
There was a problem hiding this comment.
Fixed in 985513a (same root cause as Bugbot's finding on the cancel handler); both suppression flags are cleared on drag cancel.
There was a problem hiding this comment.
Sorry, I'm unable to act on this request because you do not have permissions within this repository.
ApprovabilityVerdict: Needs human review 2 blocking correctness issues found. Large feature PR introducing thread folders with drag-and-drop, worktree labels, git sync controls, and CI status display. Multiple new components, RPC endpoints, and complex state management warrant human review. Two unresolved comments also identify functional bugs in folder assignment and drag handling. You can customize Macroscope's approvability policy. Learn more. |
- clear click-suppression flags on drag cancel so the next click is not swallowed - close the diverged toast before starting Rebase & sync to prevent stacked retries - make digit-jump hints and ctrl+arrow traversal folder-aware so shortcuts match the rendered order (folders first, then the ungrouped list) - scope multi-select folder moves to threads in the clicked project and hide the entry for cross-project-only selections - persist ungrouped reorder against the full (uncapped) list and include newly ungrouped dragged threads so the drop position applies
- guard the folder GC against empty bootstrap/disconnect snapshots, both at the sidebar effect and inside syncThreadGroups, so a reload can no longer wipe persisted folders and manual order - treat GitHub's STALE check conclusion as failing; a stale required check still blocks merging - keep sortThreads deterministic in manual mode by sorting on recency; the sidebar still layers the user-defined order via orderItemsByPreferredIds, and latest-thread pickers no longer depend on input array order

Re-submits four features that were closed during the backlog cleanup on 2026-07-20 (#3069, #3070, #3071, #3075, #3088). Per that request, this is a current diff rebuilt on top of today's main rather than a reopen: the old branches predated the sidebar refactor and no longer applied.
Grouped into one PR to keep it to a single review rather than five. Happy to split it back out if you'd prefer.
Thread folders + drag reorder
User-defined folders in the sidebar, with drag to reorder threads.
Custom worktree labels
Display-only label for a worktree, shared by every thread on it. Does not move the worktree on disk.
Git sync control
VS Code-style publish/pull/push/sync in the branch toolbar, driven by upstream state.
CI status next to the PR pill
Check status surfaced on the composer PR pill (server-side plumbing in
GitHubCli/gitHubPullRequests).Note on the multi-select context menu
The one real conflict with current main was in
Sidebar.tsx, where this work and the upstream archive action both changed the multi-select menu. Both are kept, andbuildMultiSelectThreadContextMenuItemsnow takes optional folder children so the menu composes rather than one replacing the other:Verification
pnpm typecheck: 0 errorspnpm lint: 0 errorspnpm test: green, exceptMessagesTimeline.test.tsx, which fails the same way on pristine main under full parallel load and is untouched hereThe desktop prod-staging dependency commits from my local branch are deliberately left out of this PR; they are unrelated and can go separately if wanted.
Note
Medium Risk
New git fetch/push/sync and rebase paths can mutate remotes and local history; sidebar folder state is persisted locally with GC tied to live snapshots, so bugs could affect ordering or membership until refresh.
Overview
Adds four user-facing capabilities: sidebar thread folders, cosmetic worktree labels, a branch-toolbar git sync control, and PR CI status in the composer.
Sidebar gains per-project thread folders with create/rename/delete, context-menu and bulk Move to folder, and drag-and-drop to reorder folders, move threads into folders, reorder ungrouped threads, or drop on “Remove from folder.” Folder membership, folder order, collapse state, and manual ungrouped order persist in
uiStateStore(with snapshot GC so empty bootstrap does not wipe data). Keyboard traversal and multi-select menus follow the rendered folder layout.Worktree labels are display-only names keyed by worktree path (
worktreeLabelByPath), editable via double-click/right-click on the workspace selector and a globalWorktreeRenameDialog; labels clear when a worktree is removed.Git adds server
fetchCurrentBranch/syncCurrentBranch(ff pull, push, publish without upstream, optional rebase on divergence →GitDivergedError) and wiresvcs.fetch/vcs.push/vcs.syncthroughGitWorkflowServiceandws. The webGitSyncControldrives fetch/pull/push/sync with toasts (including rebase on diverged sync) and blocks branch picker changes while sync ops run.CI requests
statusCheckRollupfromgh prJSON, derivesChangeRequestChecksingitHubPullRequests, and surfaces checks on VCS/change-request payloads and the branch toolbar PR pill (chip + open checks URL).Reviewed by Cursor Bugbot for commit 6f3cfd3. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Add thread folders, worktree labels, and Git fetch/push/sync controls to the sidebar
GitSyncControlcomponent to the branch toolbar that exposes one-click fetch, pull, push/publish, and sync with toast notifications; ref switching is disabled while a sync is running.statusCheckRollupis fetched from GitHub, rolled up into a passing/pending/failing summary, and shown as a colored chip next to the PR in the branch toolbar.uiStateStore; users can set or clear labels by double-clicking or right-clicking the workspace selector, and labels appear in the branch toolbar and delete-confirmation dialogs.GitVcsDriverimplementations forvcsFetch,vcsPush, andvcsSync, withGitDivergedErrorsurfaced when sync cannot fast-forward.Macroscope summarized 6f3cfd3.