Repository navigation
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (6)
🚧 Files skipped from review as they are similar to previous changes (5)
Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review. 📝 WalkthroughWalkthroughManual-order rank collection now excludes worktrees without a defined 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
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 |
A manual reorder persisted manualOrder only for the dragged row(s); every other visible row kept falling back to the mutable sortOrder in the manual comparator, so the next agent activity jumped unmoved rows to the front and undid the user's order. Backfill manualOrder for every visible row whenever a manual reorder leaves a non-moved row without one, and feed the ranker real manualOrder ranks only (not the sortOrder stand-in that masked the holes). The comparator is unchanged, so legacy manual mode (no manualOrder yet) still restores the familiar sortOrder snapshot. Fixes stablyai#13847 Co-Authored-By: Claude <noreply@anthropic.com>
faeda9f to
88beb90
Compare
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
|
Thanks for this, @blade035 — keeping manual worktree order stable across agent activity was a real bug. A more complete version already landed on This note is from an automated scan of open PRs whose issue already shipped in a later merge. If that's wrong, please reopen and say so. |
ELI5
When you manually drag workspaces into a custom order in the sidebar, rows you never touched were still ranked by an old activity snapshot (
sortOrder). Whenever that snapshot got rewritten — a pass through the "Agent Activity" sort, a newly created workspace, a paired remote client pushing ranks — those rows re-ranked and your arrangement was lost. Manual ordering now sticks until you change it again.What Changed
buildSparseManualOrderUpdatesnow backfills amanualOrderfor every visible row in a reordered group whenever any non-moved row still lacks one, instead of persisting a rank for only the dragged row(s).buildRankByWorktreeIdhelper for the list drag + cross-status drop (worktree-list/drag/use-status-mutations.ts:20-35), the board drawer (WorkspaceKanbanDrawer.tsx:420-425), and the kanban sidebar drop helper (workspace-kanban-sidebar-drop.ts:239-244) — now feed the ranker realmanualOrderranks only — notmanualOrder ?? sortOrder— so a row lackingmanualOrderis detected as a hole and backfilled, rather than masked by the mutablesortOrder.smart-sort.ts) is unchanged.Why
A manual drag persisted
manualOrderonly for the moved row(s). Every other visible row keptmanualOrder = undefinedand the manual comparator ranked it bysortOrder. That fallback is the problem:sortOrderis written in three ways, none of which respect a manual arrangement —sortBy === 'smart'(worktree-list/listing/use-sort-order.ts:212-219);Date.now()(src/main/persistence/loading-store/store.ts:3915, the default worktree-meta base);worktree.persistSortOrderat any time, mode-agnostic (src/main/runtime/rpc/methods/worktree.ts:174).So staying inside Manual mode does not rewrite
sortOrderon activity by itself — agent activity there writes onlylastActivityAt/isUnread, which the manual comparator ignores. But any Smart episode ("Agent Activity" — the mode users pass through) rewrites every fallback rank, and rows sitting on the two mixed scales re-rank on return to Manual or on reload. That is what users experience as "agent activity broke my manual order" (issue #13847 has the fuller analysis). Mixing the scales also corrupted drag-time rank seeding, since the call sites seeded ranks withmanualOrder ?? sortOrder, masking exactly the rows the sparse ranker's neighbour hole-check was meant to catch.Backfilling every visible row on reorder means the
?? sortOrderfallback no longer drives any row after a drag, so the order survives Smart episodes, reloads, meta-row minting, and remote pushes. Legacy manual mode (a user who has never reordered — nomanualOrderanywhere) is unchanged: it still restores the familiarsortOrdersnapshot.Linked Issue
Fixes #13847
Visual Proof
No visual/layout change — the fix is to ordering stability (an interaction behavior), not appearance. Repro in Testing; a short screen recording of the repro can be attached.
Testing
Automated tests added/updated
I manually tested these changes locally
worktree-manual-order.test.ts— new test: a reorder backfillsmanualOrderfor every visible row when an unmoved row lacks one (previously only the moved row was updated).workspace-kanban-sidebar-drop.test.ts— updated the cross-lane manual-drop case: with no priormanualOrder, the drop now backfills every visible row (doing-a > dropped > doing-b) instead of sparse-ranking only the dropped row ontosortOrder.Full sidebar + worktree-store + sort-order-persistence suites pass (4733 tests) on the pre-rebase tree.
pnpm typecheck:web,oxlint, andoxfmtclean on the changed files.Rebased onto
mainon 2026-08-23 after the refactor(sidebar): group worktree-list files by domain #14486 worktree-list reorg: the two formerWorktreeList.tsxseeding sites now live inbuildRankByWorktreeId(worktree-list/drag/use-status-mutations.ts:20-35). Re-verified on the rebased tree: targeted suites (manual-order, kanban sidebar drop, sort-order persistence + host split — 47 tests),pnpm typecheck:web,oxlint,oxfmtall clean.Repro a reviewer can follow (desktop sidebar):
(Staying in Manual and waiting for activity shows no before/after on a single desktop — nothing rewrites
sortOrderin that mode; see Why. Newly created workspaces and remotepersistSortOrderpushes hit the same fallback pre-fix.)AI Disclosure
Developed with assistance from Claude (Anthropic). Root-cause analysis, approach, and tests reviewed by the contributor.
Review
manualOrder(legacy) still see the restoredsortOrdersnapshot. After the first manual reorder, all visible rows gain a stablemanualOrder.manualOrder); full backfill only runs when a hole exists (typically the first reorder). Cheap metadata writes only.Checklist
N/Awith reasonpnpm lint,pnpm typecheck, and in-scopepnpm testpass (CI covers the full suite)Author