Skip to content

[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

Closed

Description

@mmarabel

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 list scans 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

  1. 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-191 sends worktree.persistSortOrder with every worktree ID on that host.
  2. The host gives every worktree a new sortOrder unless the order is already strictly descending (src/shared/worktree/sort-order-update.ts:20-31). It then calls notifyWorktreesChanged for every repository (src/main/runtime/runtime-managed-worktree-metadata.ts:116-131). That clears each repository's git worktree list scan cache (src/main/runtime/orca-runtime-get-status.ts:270-276) and emits one worktreesChanged event per repository.
  3. For each event the desktop runs worktree.detectedList, which the host answers with a fresh git worktree list because its cache was just cleared. It then runs fetchWorktreeLineage (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.
  4. The refetched rows differ only in sortOrder, but the merge still bumps sortEpoch (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

  1. Pair a desktop to a remote Orca runtime with many repositories (25 here).
  2. Set the sidebar sort to Smart and run agents in a few worktrees, so the order moves.
  3. Watch the runtime connection (for example tcpdump -s 96 on the runtime port), or the host's git.exec trace spans with subcommand worktree.

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 worktreesChanged events (mobile needs them) but don't clear the git worktree list scan cache. sortOrder lives in worktree metadata, which the resolved-worktree cache invalidation already covers.
  • Desktop: fetch a host's lineage once per burst of worktreesChanged events 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

  1. AmethystLiang commented on Oct 12, 2026

    @AmethystLiang
    Contributor

    Thanks for reporting. Looking into it

  2. OrcaWin commented on Oct 15, 2026

    @OrcaWin
    Collaborator

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions