Commit Graph
3 Commits
Author SHA1 Message Date
Neil 84584b61d0 perf(git): cache sparse-checkout annotation on worktree listing (#17859)
* perf(git): cache sparse-checkout annotation on worktree listing

`git worktree list` never reports sparse-checkout state, so every listing paid a
per-worktree fs.stat + config read to detect it -- measured at ~9x the cost of
the `git worktree list` call it decorates on a 1000-worktree repo. Cache the
result per worktree path, invalidated by the existing worktree-change
invalidator registry plus explicit remove/move hooks, with a 5-minute
reconcile window bounding the one unwitnessed edge case (external
`git sparse-checkout` toggle with extensions.worktreeConfig off), matching the
precedent already accepted in readRepoWorktreeAdminFingerprint.

* perf(git): normalize/scope sparse-checkout cache keys, add SWR

Address independent-review follow-ups on the sparse-checkout annotation
cache (#17859):

- Extract canonicalWorktreePath() from areWorktreePathsEqual and key/invalidate
  the cache through it on both read and write, closing the disclosed
  path-spelling P2 outright instead of leaving it as a residual risk.
- Scope cache entries and clears by repo path (derived from the invalidator
  registry's repoId via a store lookup, falling back to a full clear when the
  repo can't be resolved), so churn in one repo no longer evicts a sibling
  repo's warm cache.
- Replace the hard 5-minute cutoff with stale-while-revalidate: past the
  window, callers get the cached value immediately while a deduplicated
  background probe corrects it and, on a flip, drives the existing
  worktrees-changed notification -- collapsing visible staleness from the
  full window to one refresh cycle at zero added listing latency.

Also corrects a stale claim in the original PR description: newer Git does
emit a `sparse` porcelain line (which annotateSparseCheckoutStatus already
skips), but Orca's Git 2.25 compatibility baseline predates it, so the
fallback detection this caches remains necessary.

* fix(git): stop background sparse-checkout revalidation resurrecting invalidated entries

Readiness-loop finding: a stale-while-revalidate probe in flight when a
worktree is removed/moved (or a repo's cache is cleared) would still write
its result back afterward, resurrecting an entry that was deliberately
dropped. Guard the write with a presence check so an invalidated key stays
absent until the next real read.

* fix(git): identity-check the sparse-checkout SWR write-back guard

The has()/presence guard from the previous commit only proved some
entry existed at the key, not that it was the one this revalidation
started from. A worktree removed and re-created at the same path while
a background re-detect was in flight would repopulate the key with a
fresh cold read, and the stale in-flight result would then overwrite
it -- exactly the race greptile (P1) and pullfrog both flagged as
still open. Compare the map's current entry by reference to the entry
captured when the revalidation began; a mismatch means something else
(invalidate, clear, or a fresh cold read) replaced it, and the stale
result must not be written back.

Added a regression test that fails against the old has() guard and
passes with the identity check: invalidate and repopulate the key with
a different value mid-flight, then let the stale revalidation settle
and assert the fresh value survives.
2026-09-01 03:44:50 -07:00
Neil a4cd00ed18 fix(wsl): drop the linked-worktree Git route cache after worktree mutations (#17791)
On Windows with a WSL distro configured, `prepareWslLinkedWorktreeGitRouting`
caches for 30s which Git owns a drive-letter checkout, by reading that checkout's
`.git` marker. `git worktree add/move/remove` rewrites exactly that marker, so
the verdict could stay authoritative for up to 30s after it stopped being true.

- Add `invalidateWslLinkedWorktreeGitRouting(cwd)`: drops the cached route and
  the probe retry backoff for that path and for anything under it (a submodule
  inside the worktree derived its route from the same marker walk). Eight calls
  at six sites: `worktree add`, `worktree move` (both paths), `worktree remove`,
  the prepared checkout's add, the finalize move (both paths), and the
  prepared-worktree discard. Five sites invalidate from a `finally`, because a
  Git failure can still have rewritten the marker; the prepared checkout's add
  invalidates on the success path only, since its failure path runs the discard,
  which has its own `finally`.
- Split the parent-directory marker walk into
  `wsl-linked-worktree-git-route-probe.ts` (the routing module was at the
  `max-lines` ceiling) and have it report whether the walk settled. A `.git`
  file with no `gitdir:` line is a half-written marker mid `worktree add`: it is
  now retried under the existing backoff instead of cached for 30s. The route it
  yields is unchanged (distro); only the number of parent walks changes.

An invalidation only drops cached state; a probe already in flight is left to
finish and cache normally, so a mutation landing mid-probe is no worse off than
main's 30s TTL. The cost is that a failed mutation also drops a still-correct
route: `gitExecFileAsync` and `gitStreamStdout` re-resolve the route after their
own `prepareWslLinkedWorktreeGitRouting`, and `gitSpawn` resolves again after the
git-admission wait, so a command already in flight for that path can take the
empty-cache default and run a host-owned checkout under `wsl.exe git`. It fails
once and self-heals on the next command.

Reachable only on win32 + configured WSL distro + drive-letter cwd; every other
platform and configuration never populates this cache, so the new calls scan two
empty maps.
2026-08-31 20:35:49 -07:00
Neil 037cc2e531 Split Git worktree responsibilities (#17253)
* Split speech session lifecycle

* Split terminal output scheduler pipeline

* Split mobile browser pane modules

* Prune resolved max-lines suppressions

* Split pane tree equalization logic

* Extract mobile troubleshoot screen styles

* Split external automation manager

* Split main window service attachments

* Split hosted review creation checks

* Split automation dispatch event handling

* Split settings navigation metadata

* Split daemon initialization lifecycle

* Split GitLab item dialog

* Split relay dispatcher layers

* Split mobile host screen

* Retarget mobile view settings source test

* Split runtime file client layers

* Split ports panel layers

* Split runtime environments pane layers

* Split local PTY provider responsibilities

* Split CDP bridge responsibilities

* Split relay Git handler responsibilities

* Track moved relay Git fetch audit

* Split Linear item drawer responsibilities

* Split telemetry event schema responsibilities

* Split resource usage status responsibilities

* Split remote terminal multiplexer responsibilities

* Split Git worktree responsibilities

* Fix F3-speech for #17123

* Fix F1-cycle for #17131

* Fix F4-navtest for #17157

* Fix F2-allowlist for #17161
2026-08-29 20:20:55 -07:00