feat(sidebar): sync pinned thread order - #5528
Conversation
|
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 Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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.
One finding: the new web reorder path reuses ThreadPinningUnsupportedError, whose caller-visible message describes pinning rather than pin reordering. Everything else (namespace subpath imports in the new migration, decider/projector event handling, contracts schema additions) follows the service conventions.
Posted via Macroscope — Effect Service Conventions
ApprovabilityVerdict: Needs human review This PR introduces a new feature (synced pinned thread order) with schema changes, new API commands/events, complex sorting algorithms, and cross-platform UI additions. An unresolved review comment also identifies a concurrency bug in the web implementation. New features of this scope warrant human review. You can customize Macroscope's approvability policy. Learn more. |
70e50e6 to
2ae2873
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 138c1d8. Configure here.
| })(); | ||
| }, | ||
| [orderedPinnedThreads, pinnedOrderingFullyVisible, reorderPinnedThread, serverConfigs], | ||
| ); |
There was a problem hiding this comment.
Web reorder lacks in-flight lock
Medium Severity
movePinnedThread never guards against overlapping reorders. Mobile blocks with pinnedReorderInFlightRef, but web can start another drag or move-up/down while prior reorderPinnedThread calls and pendingPinnedOrderByKey updates are still in flight, so concurrent moves can compute ranks from a stale list and leave the synced order wrong.
Reviewed by Cursor Bugbot for commit 138c1d8. Configure here.
…le Move up/down Review fixes and cherry-picks from the parallel implementation (#5528): - The optimistic drag override now releases on ANY pinned-membership change (new pin, unpin, snooze/wake) instead of only exact sequence match, so a pin landing mid-drag can no longer freeze the override and launder a stale order into later drags. - attemptPin anchors the new pin's key against the DISPLAYED order, and every pin path (chat header, context menus, mobile) now sends a top-of-run orderKey, so the same action never places differently. - Pin-order key math moved to client-runtime (state/thread-sort) and is shared by web and mobile instead of mirrored. - Mobile: Move up / Move down actions in the pinned row menu, computed against the canonical arranged order so search or project scoping never disables or misdirects a move. - Docs: user page on organizing threads. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>


Pinned threads are global, but their order was fixed by creation time. This adds manual ordering that is stored by the server and follows the user across connected clients.
What changed
thread.pin.reordercommand andthread.pin-reorderedeventScreenshots
The integrated browser pass moved “Review API changes” from third to first with the keyboard-accessible drag control, confirmed that only the moved thread received a persisted order, and verified the same order after a full reload.
Verification
Related to #698.
Built with GPT-5 Codex in the Codex desktop harness.
Note
Medium Risk
Touches orchestration commands, persistence, and multi-client sync with optimistic UI and multi-thread compaction when rational gaps run out; gated by capability but mixed server versions can block reorder until updated.
Overview
Pinned threads used to sort by creation time only. This PR adds server-backed manual order that syncs across web, desktop, and mobile.
Backend: New
PinnedThreadOrderrational positions,thread.pin.reorder/thread.pin-reordered,pinned_orderon projections (migration 038), and a separatethreadPinReorderingcapability so older pinning servers are not sent reorder commands. Unpin clearspinnedOrder. Client-runtime addssortPinnedThreadsand move helpers (mediant between neighbors, full-list compaction when gaps are exhausted).Web: Sidebar v2 uses @dnd-kit drag on pinned rows (grip handle), context-menu move up/down, optimistic pending orders, parallel commands with rollback, and toasts when compaction needs all servers updated.
Mobile: Move up / Move down in the pinned thread overflow menu with the same ordering logic, in-flight guard, sequential apply/rollback, and alerts for unsupported environments.
Docs: New user guide for organizing threads; list rendering switches from creation-order sort to synced pinned order (with compatibility fallback).
Reviewed by Cursor Bugbot for commit 138c1d8. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Add synced pinned thread reordering via drag-and-drop and context menu
PinnedThreadOrderrational-fraction type (e.g.3/7) stored in theprojection_threadstable and carried through contracts, projections, and client state to represent an explicit server-synced pin position.sortPinnedThreads,pinnedThreadOrderForMove, andpinnedThreadOrderUpdatesForMoveutilities inthreadSort.tsto compute new orders using mediants, with full-list compaction as a fallback when no representable value fits.threadPinReorderingserver capability flag; mixed-capability environments show an alert and unsupported environments return a typedThreadPinReorderingUnsupportedError.pinned_ordercolumn toprojection_threads.Macroscope summarized 138c1d8.