Repository navigation
fix: never surface coding-agent scratch worktrees in the sidebar - #9535
brennanb2025 merged 5 commits into
Conversation
Sub-agent runs (e.g. Claude Code worktree isolation) create throwaway git worktrees at tool-internal paths like <repo>/.claude/worktrees/. These showed up as workspace rows for repos whose non-Orca worktree visibility is 'show', and would otherwise ping the discovery card and new-worktrees inbox on every fan-out. Classify them as 'agent-scratch' via a curated path-segment matcher and suppress them unconditionally: sidebar, discovery card, inbox, dialog counts, add-handoff reveal trigger, and the metadata fallback. Selected checkouts and explicitly imported paths still win. Fixes #9388
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds detection for CLI-created agent scratch worktrees and extends ownership types with 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: b401e916-18c7-4d0f-be7f-2895893e878d
📒 Files selected for processing (5)
src/renderer/src/components/sidebar/WorktreeVisibilityDialog.tsxsrc/shared/agent-scratch-worktrees.test.tssrc/shared/agent-scratch-worktrees.tssrc/shared/worktree-ownership.test.tssrc/shared/worktree-ownership.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- src/shared/agent-scratch-worktrees.test.ts
- src/shared/worktree-ownership.test.ts
- src/shared/worktree-ownership.ts
…more-obvious-guide-for-hiding-non-orca-w # Conflicts: # src/main/ipc/worktrees.ts
There was a problem hiding this comment.
Actionable comments posted: 1
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 36843417-abfd-4ce3-b9d9-262c0ddc715c
📒 Files selected for processing (11)
src/main/ipc/worktrees.test.tssrc/main/ipc/worktrees.tssrc/main/runtime/orca-runtime.test.tssrc/main/runtime/orca-runtime.tssrc/renderer/src/components/sidebar/WorktreeVisibilityDialog.tsxsrc/shared/agent-scratch-worktrees.test.tssrc/shared/agent-scratch-worktrees.tssrc/shared/external-worktree-inbox.test.tssrc/shared/external-worktree-inbox.tssrc/shared/worktree-ownership.test.tssrc/shared/worktree-ownership.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- src/shared/agent-scratch-worktrees.test.ts
- src/shared/worktree-ownership.ts
- src/shared/worktree-ownership.test.ts
Agent scratch worktrees (.claude/worktrees, .gsd-workspaces) have been hidden unconditionally since stablyai#9535. The suppression reaches every surface that could report it — sidebar, discovery card, inbox, and the Non-Orca worktrees dialog counts — so a worktree created by `claude -w` vanishes with no way to see that it exists or to get it back. Setting the repo to show non-Orca worktrees has no effect, because shouldShowWorktree returns on the agent-scratch branch before it reaches that check, and the only field that can override the gate (importedExternalWorktreePaths) is writable solely through an inbox that also excludes scratch. Add a per-repo agentWorktreeVisibility opt-in, default hide, so stablyai#9388's fan-out protection stays the default. Read it from the single scratch branch in shouldShowWorktree, and give the visibility dialog a second row that counts scratch worktrees and toggles the field. The row names the containing directory, or a location count when the worktrees span more than one, since that path is the diagnostic payload. Once a repo has opted in the row stays visible even at zero, so the opt-in is always reversible. isUserFacingExternalWorktree is deliberately untouched, so the discovery card and the new-worktree inbox keep excluding scratch; two sibling accessors serve the dialog instead. Adds an accounting invariant test: every worktree git reports is either unconditionally visible (selected checkout, explicit import, or orca-managed) or counted in exactly one accessor bucket. It catches a worktree being dropped from every bucket — the failure mode this fixes — and is what should stop a future path-list change from reintroducing it. The new row is localized in all five catalogs, so it reads in the same language as the non-Orca row directly above it. Verified against the running app with a real `.claude/worktrees/` worktree: hidden by default with no sidebar row, named in the dialog, revealed on Show without closing it, and persisted. That run is also what caught the path overflowing the dialog — DialogContent is a single-column grid, so the row needed min-w-0 for the path to truncate instead of inflating the shared column. Refs stablyai#9388, stablyai#9535
…blyai#9535) * fix: never surface coding-agent scratch worktrees in the sidebar Sub-agent runs (e.g. Claude Code worktree isolation) create throwaway git worktrees at tool-internal paths like <repo>/.claude/worktrees/. These showed up as workspace rows for repos whose non-Orca worktree visibility is 'show', and would otherwise ping the discovery card and new-worktrees inbox on every fan-out. Classify them as 'agent-scratch' via a curated path-segment matcher and suppress them unconditionally: sidebar, discovery card, inbox, dialog counts, add-handoff reveal trigger, and the metadata fallback. Selected checkouts and explicitly imported paths still win. Fixes stablyai#9388 * fix: preserve scratch worktree visibility boundaries * fix: hide scratch worktrees from linked checkouts * docs: explain scratch root normalization
Fixes #9388
Summary
Coding-agent CLIs create throwaway Git worktrees for sub-agent isolation at fixed tool-internal paths, most commonly
.claude/worktrees/agent-<id>and.gsd-workspaces/<id>. Orca previously surfaced these as workspace rows whenever non-Orca worktrees were shown.This PR classifies those checkouts as
agent-scratchand excludes them from automatic discovery, sidebar rows, inbox notifications, visibility-dialog counts, add-project visibility handoff, and metadata-fallback reveal behavior. The matcher recognizes scratch worktrees created from the default checkout or any linked checkout belonging to the repo. Selected checkouts and explicitly imported paths remain usable escape hatches.Screenshots
No visual change. This changes which Git worktrees feed the existing sidebar and visibility controls.
Testing
pnpm lint— changed-file oxlint and max-lines ratchet pass; the full switch-exhaustiveness command still fails on the pre-existingskill-freshness-group.tsxcases.pnpm typecheckpnpm test— 31,999 passed; 43 unrelated failures under local Node 26 (the project requires Node 24), primarily unavailablelocalStorageplus inherited Git environment assertions.pnpm build— not run; no build-system or dependency changes.AI Review Report
Reviewed the ownership and visibility pipeline end to end across authoritative Git scans, disconnected metadata fallbacks, desktop IPC, runtime/CLI listing, renderer discovery cards, inbox notifications, dialog counts, and add-project handoff.
The review found and fixed two meaningful gaps:
Performance review confirmed that the change adds no polling, subprocesses, provider fan-out, or cache invalidation. Matching is an in-memory set lookup with path-length work per row, and the runtime regression proves detected and visible listing share a single Git scan.
Cross-platform review covered case-sensitive POSIX paths, case-insensitive native Windows paths, WSL UNC aliases/casing, SSH metadata fallback, and path-boundary false positives. No shortcuts, labels, shell commands, or Electron platform behavior changed.
Security Audit
No new command execution, dependency, authentication, secret, IPC authority, or filesystem mutation was added. Worktree paths continue to originate from Orca's existing Git/provider scans. Classification normalizes paths and requires a curated tool prefix directly below a checkout already reported for the same repo, preventing broad dot-directory matching from hiding arbitrary user worktrees. Strong Orca provenance metadata remains authoritative.
Notes
.worktreeslayouts or tool-looking paths outside a known checkout.Live before/after (real end-to-end QA)
Repro method — no fixtures: in a fresh demo repo (
podcast-app, one user-created worktreefix/podcast-retry-show-notes), a realclaudeCLI session was asked to fan out 3 sub-agents with worktree isolation. It created exactly the artifact from the reports:.claude/worktrees/agent-<hex>worktrees onworktree-agent-<hex>branches, each with uncommitted changes so the CLI's auto-cleanup leaves them behind. The repo was then added to a dev build with non-Orca worktree visibility set toshow— the state affected users are in.Before (
main, pre-fix): the 3 sub-agent scratch worktrees populate the sidebar alongside the user's real worktree.After (this branch, same app profile, repo still in
showmode): scratch rows are gone;mainand the user'sfix/podcast-retry-show-notesremain. Store state confirms the mechanism: the 3 worktrees classify asownership: 'agent-scratch',visible: false, while both real checkouts stayexternal/visible.