Repository navigation
[Bug]: Each Smart-sort save on a paired remote host refetches every repository and its lineage (~1.4 MB), and can trigger the next save #27268
Description
Operating system
macOS (desktop client) paired to a remote Orca runtime on Linux
Orca version
Desktop 1.4.224 paired to a 1.4.223 runtime (orca serve). Code read at main ba1474f; every file below is unchanged since v1.4.224.
Details
Summary
With the sidebar on Smart sort and a paired remote host that has many repositories, every change in the Smart order is saved to the host. That one save makes the desktop download about 1.4 MB from the host, and the host runs git worktree list once per repository. The download shares the queue with every other reply on that connection, so a terminal reveal or any other click made at that moment waits behind it. The refetched rows also carry new sortOrder values, which schedules another Smart re-sort 3 s later, so a save can trigger the next one.
Measured on a host with 25 repositories and about 105 worktrees, over a link that tops out near 450 KB/s:
- One save sends 12.7 KB up and brings back 1,404,460 B (first save) and 1,339,362 B (second save). On this link that is about 3 s each.
- The second save started 3.06 s after the first one's last reply, with no user action in between.
- On the host, full 25-repository
git worktree listscans ran 40–74 times an hour during a working day.
Every request was matched by size: worktree.persistSortOrder (12.7 KB), 25 × worktree.detectedList (328 B each; the replies matched a read-only replay to the byte), and 25–26 × worktree.lineageList (252 B each, ~44 KB replies).
What happens
- Smart sort re-sorts 3 s after the last sort-relevant change (
src/renderer/src/store/settled-sort-epoch.ts:15). If the order differs,src/renderer/src/components/sidebar/worktree-list/listing/use-sort-order.ts:184-191sendsworktree.persistSortOrderwith every worktree ID on that host. - The host gives every worktree a new
sortOrderunless the order is already strictly descending (src/shared/worktree/sort-order-update.ts:20-31). It then callsnotifyWorktreesChangedfor every repository (src/main/runtime/runtime-managed-worktree-metadata.ts:116-131). That clears each repository'sgit worktree listscan cache (src/main/runtime/orca-runtime-get-status.ts:270-276) and emits oneworktreesChangedevent per repository. - For each event the desktop runs
worktree.detectedList, which the host answers with a freshgit worktree listbecause its cache was just cleared. It then runsfetchWorktreeLineage(src/renderer/src/hooks/ipc-events/worktree-event-runtime.ts:63-82). Lineage covers the whole host, so 25 events fetch 25 identical copies. Lineage is about 80% of the bytes. - The refetched rows differ only in
sortOrder, but the merge still bumpssortEpoch(src/renderer/src/store/slices/worktrees/listing/fetched-worktree-merge.ts:226-254). Three seconds later Smart re-sorts with a fresh clock. Its ranking moves over time (src/renderer/src/components/sidebar/smart-sort.ts:115-142), so the order can differ again and the cycle repeats.
#13638 collapsed this per-repository lineage duplication for the reposChanged project refresh, but not for a burst of worktreesChanged events. The local desktop path (src/main/ipc/worktrees/metadata/register-worktree-metadata-handlers.ts:92-103) writes sortOrder without notifying anything. The runtime event is still needed, though: mobile ranks its workspace list by sortOrder and refreshes on worktreesChanged.
Steps to reproduce
- Pair a desktop to a remote Orca runtime with many repositories (25 here).
- Set the sidebar sort to Smart and run agents in a few worktrees, so the order moves.
- Watch the runtime connection (for example
tcpdump -s 96on the runtime port), or the host'sgit.exectrace spans with subcommandworktree.
Expected: saving the order costs roughly the size of the save, and a save does not schedule another save.
Actual: each save costs about 1.4 MB down and 25 git worktree list runs on the host, and saves can chain every few seconds while agents are active.
Proposed fix (#27271):
- Host: for an order-only save, keep the
worktreesChangedevents (mobile needs them) but don't clear thegit worktree listscan cache.sortOrderlives in worktree metadata, which the resolved-worktree cache invalidation already covers. - Desktop: fetch a host's lineage once per burst of
worktreesChangedevents instead of once per event, as perf(runtime): coalesce project lineage refreshes #13638 does for project refreshes.
With both, a save costs about 0.3 MB and no git worktree list runs. A save can still lead to another one when the re-sort produces a different order, but each one is now cheap.
Possible follow-up (not in #27271): when a refetch changes nothing but sortOrder, store the rows without bumping sortEpoch, so a save can't schedule the next re-sort. It isn't free: a desktop still in Smart's cold start (no live terminal yet) would no longer pick up another client's new order right away, and its effect hasn't been measured.
Related: #22151 (overall bandwidth of the paired link), #6160 (background lane for event-driven refresh), #13631 (refresh concurrency), #24085 (git worktree list cache on the host).
Activity
perf(worktrees): keep re-sorting Smart on a sortOrder-only refetch
AmethystLiang commentedon Oct 12, 2026
Thanks for reporting. Looking into it
OrcaWin commentedon Oct 15, 2026
Partly fixed by #27343 (#27343, v1.4.225): a sort-order save no longer re-runs git worktree list on every repository on the host. The desktop's refetch of all rows and lineage after each save (~1.4 MB here), and the follow-up Smart re-save it can trigger, are not addressed yet.
perf(worktrees): a Smart-sort save on a paired host no longer refetch…
perf(worktrees): a Smart-sort save on a paired host no longer refetch…