Skip to content

perf(worktrees): saving the Smart order no longer refetches every repo and its lineage from a remote host - #27271

Closed
mmarabel wants to merge 3 commits into
stablyai:mainfrom
mmarabel:mmarabel/slow-remote-terminals
Closed

mmarabel wants to merge 3 commits into
stablyai:mainfrom
mmarabel:mmarabel/slow-remote-terminals

Conversation

@mmarabel

@mmarabel mmarabel commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Why this fits #27143

  • Free: no visible, wire or behaviour change. The sidebar order, the events the host sends, and what mobile and older desktops receive all stay the same. Only repeated work behind a Smart-order save goes away.
  • Substantial: on a host with 25 repositories and about 105 worktrees, each Smart save drops from about 1.4 MB downloaded (1,404,460 B and 1,339,362 B measured) to about 0.3 MB, and from 25 git worktree list runs on the host to none. On that host, full 25-repository sweeps like the one a save causes ran 40–74 times an hour during a working day.
  • The gains apply to paired remote hosts with many repositories. A desktop that uses only local repositories sees no change.

ELI5

When the sidebar is on Smart sort, the desktop saves the new order to each host. On a paired remote host with many repositories, that one small save made the desktop download about 1.4 MB, mostly the same "which worktree belongs to which" list fetched once per repository. The host also re-ran git worktree list in every repository. Now a save downloads about a fifth of that, fetches the shared list once, and runs no git scans on the host.

What Changed

Before, on a host with 25 repositories and about 105 worktrees, each Smart save sent 12.7 KB up and brought back about 1.4 MB. Two consecutive saves measured 1,404,460 B and 1,339,362 B. That took about 3 s per save on a link that tops out near 450 KB/s. Replies share one queue per connection, so a terminal reveal clicked during a save waited behind it. On the host, full 25-repository git worktree list scans ran 40–74 times an hour during a working day.

After:

  • Host: an order-only save still emits worktreesChanged for each repository, but no longer clears the git worktree list scan caches. sortOrder lives in worktree metadata, and the resolved-worktree cache invalidation the save already does covers it. This matches the local desktop path, which writes sortOrder and clears nothing. The desktop window notifier still runs its own invalidators, so a desktop-hosted runtime behaves as before.
  • Desktop: worktreesChanged handling fetches a host's lineage once per burst instead of once per event. It tracks the repo listings in flight on that host and starts one lineage fetch when they have all landed, even when they land at different times. A caller that arrives while a fetch is running gets the next one, so every caller's fetch still starts after its own listing: 1 fetch instead of 25.
    On a host running this build, a save now costs the 25 small events, 25 worktree listings answered from cache (~0.27 MB on that host), and one lineage reply. The refetched rows still prompt Smart to re-sort, as today, but that re-sort saves again only when the order really changed: an unchanged order is never re-saved.

Why

Each piece removes repeated work from a save while keeping the event that mobile relies on. Mobile ranks its workspace list by sortOrder and refreshes on worktreesChanged, so the host can't simply stop notifying. The lineage coalescing is client-side, so it also helps against hosts that haven't updated yet. #13638 already collapsed the same per-repository lineage duplication for the reposChanged project refresh; this covers the worktreesChanged path it left out.

Alternatives considered:

Linked Issue

Fixes #27268

Visual Proof

N/A: no visual change. The sidebar order is unchanged. The fix removes redundant network traffic and git worktree list runs behind a save. The before numbers come from header-only captures of the paired connection, and the issue has the full measurement.

Testing

  • I manually tested these changes locally
  • Automated tests added/updated, or explained why not below

Each new test fails without its fix and passes with it:

  • lineage-and-scan-cache-part-03.spec.ts: an order-only save still emits worktreesChanged, keeps the git scan (git worktree list runs once, not twice), and the next listing returns the new order.
  • worktree-event-lineage-refresh.test.ts: 25 worktreesChanged events whose listings land one by one, with lineage replies settling instantly in between, fetch lineage once, not 25 times. A caller arriving during a fetch waits for the next one, a failed listing still releases the others, and separate hosts and the forced-local target don't share a fetch.

Ran on Linux: pnpm tc, pnpm lint (full), the changed-code quality gate against upstream/main, oxfmt --check, and vitest over orca-runtime.test.ts, the worktree store slices, src/renderer/src/hooks and the sidebar (599 files, 6,196 tests passed and 1 skipped on the latest head). pnpm build was not run locally. Not yet run against the production host: the before numbers come from captures of a 1.4.224 desktop paired to a 1.4.223 runtime.

AI Disclosure

Claude Opus 5.5 (claude-opus-5-5, xhigh thinking) in the Pi coding agent measured the traffic, traced the cause, wrote the change and the tests, and drafted this description.

Review

  • Cross-platform / SSH / remote: no paths, shell calls or platform checks. The host change applies to any runtime; on a desktop-hosted runtime the window notifier still clears its caches, as before. SSH repositories go through the same merge and event path.
  • Mobile and backwards compatibility: no wire change. The host still emits the same worktreesChanged event per repository, so mobile and older desktops refresh exactly as before. Newer desktops paired to older hosts get the client-side savings.
  • Folder workspaces: unaffected. The change only touches order saves and lineage fetching after change events.
  • Performance: per save, from ~1.4 MB and 25 git worktree list runs to ~0.3 MB and none.
  • Security: none affected.

Agent skill upstream boundary

  • Not applicable, or this change copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

Possible follow-up: in Smart mode, skip the re-sort when a refetch changes only sortOrder. Live Smart ranking ignores sortOrder, so that re-sort is usually wasted, and when the time-based ranking has moved it starts another (now much cheaper) save. It's left out here because 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.

The Agents panel has a separate, larger cost that this PR does not change: at History depth 1000, each scoped aiVault.listSessions refresh is one ~2.7 MB reply and is re-sent even when nothing changed. That's tracked in #27277.

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)

…o and its lineage from a remote host

A Smart sort save made a headless host clear every repository's git
worktree scan and emit one worktreesChanged event per repository; the
desktop answered each event with a worktree listing plus a host-wide
lineage fetch, and the refetched sortOrder values re-armed the sort.

- host: an order-only save keeps the events (mobile re-ranks on them)
  but leaves the git worktree scan caches alone
- desktop: one lineage fetch per host per burst of change events
- desktop: in Smart mode a sortOrder-only refetch does not bump sortEpoch

Fixes stablyai#27268
@coderabbitai

coderabbitai Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 3643436f-99be-4055-8a3d-8d86bb43ae77





📥 Commits

Reviewing files that changed from the base of the PR and between 92c849b and 0034ae8.






📒 Files selected for processing (3)
  • src/renderer/src/hooks/ipc-events/worktree-event-lineage-refresh.test.ts
  • src/renderer/src/hooks/ipc-events/worktree-event-lineage-refresh.ts
  • src/renderer/src/hooks/ipc-events/worktree-event-runtime.ts





🚧 Files skipped from review as they are similar to previous changes (2)
  • src/renderer/src/hooks/ipc-events/worktree-event-lineage-refresh.ts
  • src/renderer/src/hooks/ipc-events/worktree-event-runtime.ts





Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.







📝 Walkthrough
📝 Walkthrough
📝 Walkthrough
📝 Walkthrough
📝 Walkthrough

Walkthrough

Runtime sort-order saves notify clients without invalidating Git worktree-list scan caches. The renderer coordinates lineage refreshes by target during worktree events. In Smart sorting, a refresh that changes only sortOrder does not increment sortEpoch. Tests cover scan reuse, lineage refresh coordination, and sort-epoch updates.












Priority: ➖ Normal

Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to 0034a

The reported burst of worktree changes now produces one lineage refresh for the shared host. No issue identified here prevents merging after normal checks.

Pre-merge checks | Passed 4 | Failed 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 9 functions across 9 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check Passed The PR meets the coding requirements in #27268. The host uses notifyWorktreeSortOrderChanged for order-only saves, so it keeps worktreesChanged events without clearing Git scan caches. The desktop…
Out of Scope Changes check Passed The production changes implement the three mechanisms requested by #27268. The tests directly verify those mechanisms. No unrelated wire change, platform-specific behavior, queue-priority work, genera…
Title check Passed The title clearly summarizes the primary change: Smart-order saves no longer trigger redundant remote repository and lineage refetches. It is specific and related to the changeset.
Description check Passed The description includes all required sections, links issue #27268, explains the user impact and implementation, documents testing and limitations, and addresses compatibility, performance, security, …

  • Fix all pre-merge checks with AI
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: b4f1a89e-6f00-4b62-b391-166509d25bd7
📥 Commits

Reviewing files that changed from the base of the PR and between 5b67677 and 92c849b.

📒 Files selected for processing (9)
  • src/main/runtime/orca-runtime-create-managed-remote-worktree.ts
  • src/main/runtime/orca-runtime-get-status.ts
  • src/main/runtime/orca-runtime-tests/lineage-and-scan-cache-part-03.spec.ts
  • src/renderer/src/hooks/ipc-events/worktree-event-lineage-refresh.test.ts
  • src/renderer/src/hooks/ipc-events/worktree-event-lineage-refresh.ts
  • src/renderer/src/hooks/ipc-events/worktree-event-runtime.ts
  • src/renderer/src/store/slices/worktrees-fetch-listing-merge.test.ts
  • src/renderer/src/store/slices/worktrees/listing/fetched-worktree-merge.ts
  • src/renderer/src/store/slices/worktrees/listing/worktree-catalog-visibility.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

Comment thread src/renderer/src/hooks/ipc-events/worktree-event-runtime.ts Outdated
…ngs land

Repository listings in a worktreesChanged burst finish at different
times, so a fast lineage reply could settle between them and the keyed
runner would start a new fetch for each straggler. Track the listings in
flight per host and start one lineage fetch once they have all landed;
a caller that arrives during a fetch joins the next one.
Drop the Smart-mode sortEpoch skip for refetches whose rows differ only
in sortOrder. It wasn't free: a desktop whose Smart sort has no live
signal yet would stop following another client's saved order right
away, and its effect was never measured. The host and lineage changes
already cut the cost of each save; skipping the echo re-sort can be a
separate follow-up.

Refs stablyai#27268
@mmarabel

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor
⚠️ Action not completed

Already reviewed the last commit. Use @coderabbitai full review to rerun a review of the entire changeset.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@nwparker

Copy link
Copy Markdown
Contributor

Superseded by #27343, crediting @mmarabel. The replacement takes only the tiny host change that preserves Git scan caches for an order-only metadata save; existing events and freshness remain. The renderer coalescer here delays unrelated rename/cleanup behind another repo listing, so it was excluded. The replacement has regression count proof, full typecheck and quality checks. Closing this original in favor of the narrower reviewed change.

@nwparker nwparker closed this Oct 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[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

2 participants