Skip to content

Fix Windows slow startup and multi-minute UI freezes (#7225)#7266

Merged
Jinwoo-H merged 7 commits into
mainfrom
Jinwoo-H/slow-startup-and-ui-freezing-issue-analysis
Jul 3, 2026
Merged

Fix Windows slow startup and multi-minute UI freezes (#7225)#7266
Jinwoo-H merged 7 commits into
mainfrom
Jinwoo-H/slow-startup-and-ui-freezing-issue-analysis

Conversation

@Jinwoo-H

@Jinwoo-H Jinwoo-H commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Fixes #7225 (slow Windows startup + multi-minute "Not Responding" freezes).

Root cause

The reporter's ORCA_STARTUP_DIAGNOSTICS=1 timeline showed two distinct main-thread blocks: ~6.3s between window-created and load-start, and one continuous 127s event-loop stall starting right at first window show. Investigation traced them to synchronous subprocess work on the Electron main thread:

  1. The first getRepos() of a launch spawned processes synchronously. hydrateRepo computed gitUsername per repo via sync git config spawns plus execSync('gh api user') — a network call on the main thread. It fires either inside attachMainWindowServices (warm daemon reattach, i.e. the window-created → load-start gap) or at the renderer's first repos:list (right at window show). Three compounding Windows defects:
    • execSync's 2.5s timeout kills cmd.exe but an orphaned gh.exe grandchild keeps the inherited stdio pipes open, so the call can block until gh gives up — minutes on a network where api.github.com blackholes (the reporter is on a CN network; 127s matches DNS + multi-IP TCP connect retries).
    • The timeout-kill error is not ETIMEDOUT on Windows, so the "skip the second probe" guard never fired and gh auth status ran into the same wall (reproduced: 5.5s stall = 2 × 2.5s + git spawns).
    • gitExecFileSync had no timeout at all, so a repo path on a dead network drive / cloud placeholder could hang a sync git spawn indefinitely.
  2. new Tray() (sync Shell_NotifyIcon, win32) and setupAutoUpdater's sync require('electron-updater') (packaged builds, cold disk + Defender) sat between window-created and load-start.
  3. The renderer startup chain paid the per-repo git worktree list process fan-out twice back-to-back (fetch-worktrees, then worktrees:listLineage recomputing the same scans), plus serialized four independent cheap reads.

Fixes

  • repos:list is now subprocess-free. Hydration serves the cached/persisted username; a background enrichment (mirroring repo-git-remote-identity-enrichment) resolves usernames via the async runners with a hard 8s wall, persists them, and notifies the renderer. Resolution outcomes carry an authoritative flag so a timed-out probe never clobbers a persisted username, while a completed probe can clear a stale one. Timed-out gh probes retry after a 5-minute cooldown instead of pinning '' for the session. The GitHub gate keeps the old candidate-ordered semantics (GitLab-primary repos with a GitHub mirror do not pick up the gh login).
  • Windows-timeout classification fixed (killed/SIGTERM now counts as timeout → single probe).
  • gitExecFileSync gets a 15s default timeout so no sync git spawn can hold the main thread for minutes.
  • Tray + auto-updater setup deferred past ready-to-show, each with a fallback (12s/15s) covering windows revealed via the win32 10s reveal fallback and crash-looping renderers; manual update checks (menu / updater:check) force the pending setup first so they always run configured. New tray-created / updater-setup-done milestones pin any remaining pre-paint cost in future diagnostics.
  • listWorktrees shares one in-flight scan per repo (generation-gated: worktree add/remove/move bumps the generation so post-mutation callers never join a pre-mutation scan; AbortSignal callers keep private scans), and the renderer runs fetch-worktrees + fetch-worktree-lineage concurrently so the two fan-outs coincide and dedupe. The three independent local reads (ui:get, keybindings, onboarding) start early and are awaited in place.

Evidence (Windows 11, medians of 3, tools/benchmarks/startup-time-bench.mjs)

Reproduction: --github-repos 3 seeds repos whose hydration reaches the gh probe; --gh-hang-ms 20000 puts a hanging gh shim on PATH whose child survives the timeout kill holding the stdio pipes.

metric pre-fix, gh hangs post-fix, gh hangs pre-fix, healthy gh post-fix, healthy gh
worst main-thread stall 5.57s 1.20s 3.49s 1.29s
window-created → load-start 4.38s 14ms 2.31s 13ms
total to did-finish-load 7.08s 2.76s 4.98s 2.86s

A 20s-hanging gh now has zero effect on startup (2.76s vs 2.86s healthy — within noise). End-to-end check: launching the built app against the fixture shows tray-created/updater-setup-done landing after first paint, and the background enrichment resolving + persisting the real gh login for all repos (branch-prefixing still works, warm on next launch).

The remaining ~1.2s stall is bundle/require load at boot — pre-existing, tracked as a follow-up.

Not addressed (follow-ups)

  • Rate-limits' window-show listener still runs a synchronous codex-home FS sync (rate-limits/service.tsruntime-home-service.prepareForRateLimitFetch, recursive cpSync); bounded and local, but worth making async separately.
  • Residual ~1.2s main-thread stall during early boot (module loading), predates this change.

Verification

  • pnpm typecheck, pnpm lint clean; test sweep across all touched areas green (the only failures on this Windows machine — repo-detection.test.ts, clipboard-file-copy.test.ts — reproduce identically on unmodified main).
  • Multi-agent code review (high effort) ran on the branch; all confirmed findings addressed in the final commits (GitLab-mirror gate regression, tray/updater fallback gaps, gh negative-cache pinning, stale-username clearing, mid-pass repo drops, scan-sharing mutation race, remote-runtime browser-profile fetch timing).

Jinwoo-H added 5 commits July 3, 2026 16:10
Extend startup-time-bench with an event-loop-stall metric (maxGapMs from
the existing probe), a --github-repos fixture whose repos reach the gh
login probe during hydration, and a --gh-hang-ms PATH shim that hangs
like a blackholed api.github.com while its child holds the inherited
stdio pipes past the probe's timeout kill.
The first getRepos() of a launch ran per-repo sync git config probes and
an execSync 'gh api user' network call on the Electron main thread —
whether triggered by attachMainWindowServices (warm daemon reattach) or
the renderer's startup repos:list. On Windows a timeout-killed gh leaves
a grandchild holding the stdio pipes, and the ETIMEDOUT-only check let a
stuck first probe fall through to a second equally stuck probe, freezing
the app for minutes on blackholed networks.

Repo hydration now serves only the cached/persisted username, and a
background enrichment (mirroring repo-git-remote-identity-enrichment)
resolves usernames async via gitExecFileAsync/ghExecFileAsync with a
hard wall, persists them, and notifies the renderer to re-list. All
former getGitUsername callers await the async resolver.
new Tray() is a synchronous Shell_NotifyIcon call that can block for
seconds when explorer.exe is busy, and setupAutoUpdater's first
getAutoUpdater() synchronously require()s electron-updater in packaged
builds — both sat between window-created and load-start. Move them to
ready-to-show (with a 15s fallback so crash-looping renderers still get
update checks) and add tray-created / updater-setup-done milestones so
ORCA_STARTUP_DIAGNOSTICS pins any remaining pre-paint cost.
…7225)

Cold start listed every repo's worktrees from three paths back-to-back
(renderer worktrees fetch, lineage resolution, boot pty-registry
hydration), each a git process spawn per repo — expensive on Windows.
listWorktrees now shares one in-flight scan per repo, and the renderer
runs the worktrees + lineage fetches concurrently so they coincide. The
four independent cheap reads (ui, keybindings, browser profiles,
onboarding) start early and are awaited in place.

Also bound gitExecFileSync with a 15s default timeout: a repo path on a
dead network drive could otherwise hang a main-thread git spawn for
minutes with no bound at all.
- Restore the candidate-ordered GitHub gate for the gh login (a GitLab-
  primary repo with a secondary GitHub mirror must not pick up the gh
  account as its branch prefix) via an async port of the old logic.
- Timed-out gh probes are non-authoritative: they retry after a 5-min
  cooldown instead of pinning '' for the session (WSL-only gh installs
  can exceed one probe timeout legitimately), and the wall now covers
  ghExecFileAsync's internal retries and WSL fallback.
- Enrichment results carry an authoritative flag so a completed probe
  can clear a stale persisted username while a timed-out one never
  clobbers it; repos added during an in-flight pass queue a follow-up
  pass instead of being dropped.
- Tray creation gains a 12s fallback so windows revealed through
  createMainWindow's win32 10s reveal path (ready-to-show never fires)
  still get their tray icon before close-to-tray can hide the window.
- Manual update checks (app menu / updater:check IPC) force the pending
  deferred updater setup first, so they never run against an
  unconfigured electron-updater (listeners, autoDownload=false).
- listWorktrees scan sharing is generation-gated: worktree add/remove/
  move bumps the repo's generation so post-mutation callers never join
  a pre-mutation scan.
- Browser session profiles are no longer fetched early in the renderer
  chain (remote-runtime RPC may not be connected yet; a failure clears
  the profile list).
- Drop the now-dead getGitUsername mock wiring from dependent suites;
  suites that controlled usernames now mock resolveLocalGitUsername
  explicitly.
@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 8adef87c-27b2-4401-9e86-dc18f5b65484

📥 Commits

Reviewing files that changed from the base of the PR and between 80c1cfc and f9984b8.

📒 Files selected for processing (34)
  • .gitignore
  • src/main/agent-hooks/first-work-branch-rename.test.ts
  • src/main/agent-hooks/first-work-branch-rename.ts
  • src/main/automations/service-precheck.test.ts
  • src/main/automations/service.test.ts
  • src/main/git/git-username.ts
  • src/main/git/repo-username.test.ts
  • src/main/git/repo.ts
  • src/main/git/runner.ts
  • src/main/git/worktree.test.ts
  • src/main/git/worktree.ts
  • src/main/index.ts
  • src/main/ipc/repos-create.test.ts
  • src/main/ipc/repos-picker.test.ts
  • src/main/ipc/repos-remote.test.ts
  • src/main/ipc/repos-sparse-presets.test.ts
  • src/main/ipc/repos.ts
  • src/main/ipc/worktree-remote.ts
  • src/main/ipc/worktrees-windows.test.ts
  • src/main/ipc/worktrees.test.ts
  • src/main/persistence.test.ts
  • src/main/persistence.ts
  • src/main/repo-git-username-enrichment.test.ts
  • src/main/repo-git-username-enrichment.ts
  • src/main/runtime/fit-override-integration.test.ts
  • src/main/runtime/mobile-presence-lock.test.ts
  • src/main/runtime/mobile-subscribe-integration.test.ts
  • src/main/runtime/orca-runtime.test.ts
  • src/main/runtime/orca-runtime.ts
  • src/main/startup/startup-diagnostics.ts
  • src/main/window/attach-main-window-services.test.ts
  • src/main/window/attach-main-window-services.ts
  • src/renderer/src/App.tsx
  • tools/benchmarks/startup-time-bench.mjs
💤 Files with no reviewable changes (6)
  • src/main/ipc/repos-picker.test.ts
  • src/main/ipc/repos-sparse-presets.test.ts
  • src/main/automations/service.test.ts
  • src/main/automations/service-precheck.test.ts
  • src/main/ipc/repos-create.test.ts
  • src/main/ipc/repos-remote.test.ts
✅ Files skipped from review due to trivial changes (1)
  • .gitignore
🚧 Files skipped from review as they are similar to previous changes (26)
  • src/main/repo-git-username-enrichment.test.ts
  • src/main/runtime/orca-runtime.test.ts
  • src/main/runtime/mobile-subscribe-integration.test.ts
  • src/main/ipc/worktrees-windows.test.ts
  • src/main/window/attach-main-window-services.ts
  • src/main/runtime/fit-override-integration.test.ts
  • src/main/git/runner.ts
  • src/main/startup/startup-diagnostics.ts
  • src/main/agent-hooks/first-work-branch-rename.test.ts
  • src/main/repo-git-username-enrichment.ts
  • src/renderer/src/App.tsx
  • src/main/ipc/worktree-remote.ts
  • src/main/agent-hooks/first-work-branch-rename.ts
  • src/main/runtime/mobile-presence-lock.test.ts
  • src/main/window/attach-main-window-services.test.ts
  • src/main/ipc/repos.ts
  • src/main/index.ts
  • src/main/runtime/orca-runtime.ts
  • src/main/persistence.ts
  • src/main/git/worktree.test.ts
  • src/main/git/worktree.ts
  • src/main/ipc/worktrees.test.ts
  • tools/benchmarks/startup-time-bench.mjs
  • src/main/git/repo.ts
  • src/main/git/git-username.ts
  • src/main/git/repo-username.test.ts

📝 Walkthrough

Walkthrough

Changes

This PR replaces synchronous getGitUsername with async resolveLocalGitUsername/resolveLocalGitUsernameDetailed, adding gh CLI login probing with timeouts, caching, and cooldowns, plus background repo-username enrichment persisted via a new Store.setResolvedRepoGitUsername. Worktree scans now share in-flight promises per repo with generation-based invalidation on mutations. Electron startup defers system tray and auto-updater setup until after ready-to-show, and renderer startup overlaps UI/keybindings/onboarding fetches with worktree loading. The startup benchmark tool gains GitHub-repo seeding, a hanging gh shim, and additional metrics.

Sequence Diagram(s)

Diagrams included in the hidden review stack artifact illustrate local git username resolution, background username enrichment, and worktree scan sharing.

Compact metadata

  • Related issues: Startup freeze investigation referenced as Issue #7225 in benchmark tooling comments.
  • Related PRs: None specified.
  • Suggested labels: git, performance, startup, testing
  • Suggested reviewers: None specified.

Poem

A rabbit hops through git's terrain,
No more sync calls to cause us pain,
Async whispers fetch a name,
Tray and updater wait their claim,
Worktrees share one scan in vain—
Benchmarks hum a hare's refrain. 🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is detailed, but it does not follow the required template sections or include the requested screenshots, testing, security, and notes. Reformat it to the template with Summary, Screenshots, Testing, AI Review Report, Security Audit, and Notes, and briefly fill each section.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: fixing Windows startup slowness and UI freezes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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: 6

🧹 Nitpick comments (3)
src/main/git/git-username.ts (1)

204-235: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Consider parallelizing independent git reads in localRepoHasEffectiveGitHubRemote.

remotes, defaultBaseRef (via resolveDefaultBaseRefViaExec), and currentBranch are independent reads but are awaited sequentially, as are the two getConfiguredBranchRemote calls. This function is reachable from resolveLocalGitUsername, which runs on the interactive worktree-create path (createLocalWorktree), not just the background enrichment pass — each sequential local-git round trip adds latency users can feel, especially on a slower filesystem.

♻️ Suggested parallelization
-  const remotes = (await readGitStdout(repoPath, ['remote'])).split('\n').filter(Boolean)
-  const defaultBaseRef = await resolveDefaultBaseRefViaExec((argv) =>
-    gitExecFileAsync(argv, { cwd: repoPath, timeout: LOCAL_GIT_READ_TIMEOUT_MS })
-  )
+  const [remotesRaw, defaultBaseRef, currentBranch] = await Promise.all([
+    readGitStdout(repoPath, ['remote']),
+    resolveDefaultBaseRefViaExec((argv) =>
+      gitExecFileAsync(argv, { cwd: repoPath, timeout: LOCAL_GIT_READ_TIMEOUT_MS })
+    ),
+    readGitStdout(repoPath, ['branch', '--show-current'])
+  ])
+  const remotes = remotesRaw.split('\n').filter(Boolean)
   const defaultBaseRemote = defaultBaseRef ? getRemoteNameFromRef(defaultBaseRef, remotes) : ''
   const defaultBranch = defaultBaseRef
     ? getDefaultBranchName(defaultBaseRef, defaultBaseRemote)
     : null

-  const currentBranch = await readGitStdout(repoPath, ['branch', '--show-current'])
-  const candidateRemotes = [
-    await getConfiguredBranchRemote(repoPath, currentBranch || null),
-    await getConfiguredBranchRemote(repoPath, defaultBranch),
-    defaultBaseRemote,
-    'origin',
-    remotes.length === 1 ? remotes[0] : ''
-  ]
+  const [currentBranchRemote, defaultBranchRemote] = await Promise.all([
+    getConfiguredBranchRemote(repoPath, currentBranch || null),
+    getConfiguredBranchRemote(repoPath, defaultBranch)
+  ])
+  const candidateRemotes = [
+    currentBranchRemote,
+    defaultBranchRemote,
+    defaultBaseRemote,
+    'origin',
+    remotes.length === 1 ? remotes[0] : ''
+  ]
src/main/git/repo-username.test.ts (1)

223-235: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add multi-account coverage for the gh auth status fallback parser.

This test only exercises a single logged-in account. Given the forward-search regex issue flagged in git-username.ts (lines 106-128), please add a test with two accounts in the auth status output — including a case where the first listed account is the inactive one — to lock in correct behavior once fixed.

src/main/ipc/worktree-remote.ts (1)

1876-1876: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Parallelize username and base-ref resolution.

resolveLocalGitUsername is awaited sequentially before baseBranch resolution, but the two are independent — username isn't consumed until the branch-naming loop starts at Line 2007+. When args.baseBranch/repo.worktreeBaseRef are unset, resolveDefaultBaseRefViaExec also does async git I/O, so running both concurrently would shave real latency off worktree creation.

⚡ Proposed parallelization
-  const username = await resolveLocalGitUsername(repo.path)
+  const usernamePromise = resolveLocalGitUsername(repo.path)
   const requestedName = args.name
   const sanitizedName = sanitizeWorktreeName(args.name)
   const requestedDisplayName = args.displayName
     ? sanitizeWorktreeDisplayName(args.displayName)
     : undefined

   // Why: resolve the base before branch/path selection so remote-tracking bases
   // can be refreshed before `git worktree add`. Creating first and repairing
   // later races setup scripts, agents, and user edits.
-  const baseBranch =
+  const [username, baseBranch] = await Promise.all([
+    usernamePromise,
     args.baseBranch ||
     repo.worktreeBaseRef ||
     (await resolveDefaultBaseRefViaExec((argv) => gitExecFileAsync(argv, localGitExecOptions)))
+  ])
   if (!baseBranch) {

Also applies to: 1886-1899


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 8db9a903-55fa-4a98-9f0e-bc2e15b8453c

📥 Commits

Reviewing files that changed from the base of the PR and between d8921a2 and 3af7de7.

📒 Files selected for processing (39)
  • src/main/agent-hooks/first-work-branch-rename.test.ts
  • src/main/agent-hooks/first-work-branch-rename.ts
  • src/main/automations/service-precheck.test.ts
  • src/main/automations/service.test.ts
  • src/main/git/git-username.ts
  • src/main/git/repo-username.test.ts
  • src/main/git/repo.ts
  • src/main/git/runner.ts
  • src/main/git/worktree.test.ts
  • src/main/git/worktree.ts
  • src/main/index.ts
  • src/main/ipc/repos-create.test.ts
  • src/main/ipc/repos-picker.test.ts
  • src/main/ipc/repos-remote.test.ts
  • src/main/ipc/repos-sparse-presets.test.ts
  • src/main/ipc/repos.ts
  • src/main/ipc/worktree-remote.ts
  • src/main/ipc/worktrees-windows.test.ts
  • src/main/ipc/worktrees.test.ts
  • src/main/persistence.test.ts
  • src/main/persistence.ts
  • src/main/repo-git-username-enrichment.test.ts
  • src/main/repo-git-username-enrichment.ts
  • src/main/runtime/fit-override-integration.test.ts
  • src/main/runtime/mobile-presence-lock.test.ts
  • src/main/runtime/mobile-subscribe-integration.test.ts
  • src/main/runtime/orca-runtime.test.ts
  • src/main/runtime/orca-runtime.ts
  • src/main/startup/startup-diagnostics.ts
  • src/main/window/attach-main-window-services.test.ts
  • src/main/window/attach-main-window-services.ts
  • src/renderer/src/App.tsx
  • tools/benchmarks/results/startup-post-fix-final-gh-hang-2026-07-03T20-43-26-589Z.json
  • tools/benchmarks/results/startup-post-fix-final-no-hang-2026-07-03T20-43-49-250Z.json
  • tools/benchmarks/results/startup-post-fix-gh-hang-2026-07-03T20-04-32-823Z.json
  • tools/benchmarks/results/startup-post-fix-no-hang-2026-07-03T20-04-55-906Z.json
  • tools/benchmarks/results/startup-pre-fix-gh-hang-2026-07-03T19-36-38-636Z.json
  • tools/benchmarks/results/startup-pre-fix-no-hang-2026-07-03T19-39-15-435Z.json
  • tools/benchmarks/startup-time-bench.mjs
💤 Files with no reviewable changes (6)
  • src/main/ipc/repos-picker.test.ts
  • src/main/ipc/repos-sparse-presets.test.ts
  • src/main/ipc/repos-create.test.ts
  • src/main/automations/service.test.ts
  • src/main/ipc/repos-remote.test.ts
  • src/main/automations/service-precheck.test.ts

Comment thread src/main/git/git-username.ts
Comment thread src/main/git/git-username.ts
Comment thread tools/benchmarks/results/startup-post-fix-gh-hang-2026-07-03T20-04-32-823Z.json Outdated
Comment thread tools/benchmarks/results/startup-post-fix-no-hang-2026-07-03T20-04-55-906Z.json Outdated
Jinwoo-H added 2 commits July 3, 2026 17:58
- Raise the gh probe wall to 10s so it covers ghExecFileAsync's full
  worst-case retry envelope (3 x 2.5s + 1.25s backoff) — a slow-but-
  recovering gh no longer trips the retry cooldown.
- Parse gh auth status block-wise: each account prints its login line
  before its 'Active account' marker, so the old cross-block regex
  could capture the NEXT account's login on multi-account outputs.
- Keep home-anchored local paths out of committed benchmark results.
@Jinwoo-H
Jinwoo-H force-pushed the Jinwoo-H/slow-startup-and-ui-freezing-issue-analysis branch from 80c1cfc to f9984b8 Compare July 3, 2026 23:33
@Jinwoo-H
Jinwoo-H merged commit 2f3c7e8 into main Jul 3, 2026
1 check passed
@Jinwoo-H
Jinwoo-H deleted the Jinwoo-H/slow-startup-and-ui-freezing-issue-analysis branch July 3, 2026 23:40
AmethystLiang added a commit that referenced this pull request Jul 4, 2026
… (#7306)

* perf: overlap sidebar-scope loads with worktree scan at startup (#7225)

Continues the renderer-chain parallelization proposed in #7225 (proposal 2),
on top of the merged #7266:

- Run project-groups → folder-workspaces concurrently with the per-repo
  `git worktree list` fan-out. Neither reads the repos store nor worktrees,
  so a slow remote host's 15s scope RPCs no longer queue ahead of the scan.
- Raise worktree refresh concurrency 5 → 8 so multi-core machines run fewer
  sequential scan batches, still bounded so one moment can't launch every
  git probe at once.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>

* Test overlapping sidebar scope loads and worktree hydration at startup

Verify that sidebar scope loads and worktree hydration operations run
concurrently before session hydration. This protects against regressions
in startup performance under the perf/startup-lag optimization.

Additionally, document the rationale for the worktree refresh
concurrency limit in the worktrees slice.

* Clarify worktree refresh concurrency comment

---------

Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
Co-authored-by: Jinjing <[email protected]>
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.

Slow startup and UI freezing issue analysis / 启动慢、界面卡顿问题分析

1 participant