Skip to content

feat(sidebar): attach existing worktrees to folder workspaces from the sidebar menu - #26101

Open
wuhaoyujerry wants to merge 5 commits into
stablyai:mainfrom
wuhaoyujerry:feat/attach-worktree-to-folder-workspace
Open

wuhaoyujerry wants to merge 5 commits into
stablyai:mainfrom
wuhaoyujerry:feat/attach-worktree-to-folder-workspace

Conversation

@wuhaoyujerry

@wuhaoyujerry wuhaoyujerry commented Oct 7, 2026 •

Copy link
Copy Markdown

ELI5

You can now take a worktree you already have and tuck it under a folder workspace from the left sidebar: right-click the worktree, choose Attach to Folder Workspace…, and pick the folder. Before, the only way to do that was the CLI. The worktree's files and branch never move; only where it shows up in the sidebar changes.

What Changed

Before: the worktree menu could only set a Git parent. A worktree could be put under a folder workspace only when it was created with the CLI. The menu also had a "Remove from group" item that, despite its name, ungrouped the whole repository, not just the worktree you clicked.

After:

  • Attach to Folder Workspace… (single Git worktree) opens the existing parent picker in a folder mode with search, keyboard navigation and IME support. Picking a folder nests the worktree under it in the sidebar and folds it into the folder card on the Workspace Board. It survives an app restart.
  • A folder-attached worktree shows Remove from Folder Workspace and Change Parent Worktree… (picking a Git parent replaces the folder link). Git parents keep Remove from Parent.
  • Folder-attached children show repo/name as the title (display only; rename still saves just the name) instead of a gray repo line. The branch stays in the hover card.
  • In a folder workspace's PR checks list, clicking a row opens that worktree and its Checks tab; a chevron expands the inline details.
  • Removed Remove from group from the worktree menu. The project header menu keeps it.

Mechanism: the action captures the exact checkout identity and execution owner when the menu opens, sends one worktree.set with the folder:<id> parent to that owner, then re-reads worktree.lineageList and projects only the confirmed edge. A null Git lineage is never read as "no folder parent". A write whose outcome is unknown is never resent or rolled back automatically; a per-checkout guard blocks overlapping parent changes. No new RPC, storage schema or dependency, and no worktree, folder, terminal or agent is created.

This PR incorporates #18199’s backend work by @DominionZA2 and adds the sidebar UI. Since #18199 has been inactive, I’m proposing this combined PR as the path to merge the feature. If #18199 merges first, I’ll rebase to remove the overlapping changes.

Folder import improvements included: Add Project now offers Import folder as group. Repository discovery reports observed exclusions from .gitignore, built-in directory policy, hidden folders, and symbolic links, and distinguishes depth limits, unreadable paths, cancellation, and timeouts. Selecting a Git repository for group import explains why grouping is unavailable and allows opening it as a normal project. Diagnostics are bounded and come from the execution host; older hosts without diagnostics do not invent explanations. This is a separate user-facing importer change, not a prerequisite for attachment, and is included in this PR’s review scope. The CLI guide also explains how to resolve folder-workspace membership before creating children.

Why

The CLI already could attach a worktree to a folder, but users working in the app had no way to do it, and moving a worktree between folders needed a re-create. A separate action, not a combined Git/folder picker, keeps the existing Git-parent behavior and copy unchanged and avoids making folder parents look like Git ancestry. Confirming from authoritative lineage, instead of trusting the write reply, keeps old or unreachable paired hosts from showing a relationship that was not stored.

Linked Issue

Fixes #18198

Visual Proof

Captured from the hidden Electron E2E (disposable repos, light theme).

Before: worktrees only under a Git parent, no folder nesting Menu: new Attach to Folder Workspace…
Folder picker with search After: nested under the folder, repo/name titles
Menu on a folder-attached worktree

There is no screenshot of the pre-change menu (it simply lacks the attach item); the "before" frame is the same fixture before attaching.

Testing

  • I manually tested these changes locally

  • Automated tests added/updated, or explained why not below

  • Hidden-Electron E2E tests/e2e/folder-workspace-nesting.spec.ts (isolated profile, ORCA_BACKGROUND_LAUNCH=1): real right-click → search → select, Git-parent replacement, keyboard selection, Escape cancel, move between folders, detach, board folding, and full app quit/relaunch persistence with unchanged checkout identity.

  • 29 test files touched or added by this change: 279 tests pass (pnpm test <files>), covering candidates, captured identity/owner, mutation guard, rejected/unknown/unverified writes, omitted-vs-empty lineage, menu policy, picker interaction, card title/metadata, and PR-row click.

  • pnpm typecheck: only src/main/acp/acp-structured-host-restore-failed.test.ts(227) fails, and it fails identically on current origin/main. pnpm build stops at that same error.

  • pnpm lint: only mobile/ import-cycle warnings (untouched files) fail --deny-warnings. pnpm run check:code-quality:changed and check:max-lines-ratchet pass.

  • Full pnpm test on my machine has hundreds of failing files (Bun-runner/native/ACP suites). I re-ran a sample on clean origin/main and they fail the same way, so I treat them as environmental, not as caused by this change.

  • Also moved one new SQLite test onto the Node runtime list, and fixed two upstream test fixtures that needed the new workspaceLineageByChildKey argument.

  • Tested on macOS only, local execution. SSH and paired mixed-version hosts are covered by mocked transport tests only; I had no real environment.

AI Disclosure

Written and tested with an AI coding agent (Pi harness) under my direction, including the OpenSpec change, code, tests and this description. I reviewed the behavior in a running app.

Review

AI review summary:

  • Cross-platform: no new shortcuts or paths; UI-only plus one lineage action. Not run on Windows/Linux.
  • SSH / remote / local: the mutation is routed to the captured owner (local, paired runtime, SSH) and never falls back to local. Unreachable or older hosts give an honest unavailable/unknown state, not a fabricated edge. Mocked only.
  • Agents / integrations / git providers: generic folder/worktree logic, no provider-specific branches.
  • Performance: the picker reuses the existing virtualized list; catalog loads once per open; no new hot-path work.
  • UI: uses existing shadcn primitives and tokens; localized in six locales (English fallback for other strings).
  • Security: no new IPC or storage; identity and owner are validated before the write.

Agent skill upstream boundary

  • Not applicable, or this change follows docs/reference/agent-skill-sharing-upstream-boundary.md and copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Notes

  • Mixed-version: older hosts that omit workspace lineage are treated as "unavailable", not "empty".
  • Existing Remove from Parent wording is unchanged for Git parents.

Checklist

  • This PR is small and focused (it carries feat(worktrees): attach existing worktrees to folder workspaces and nest them in the sidebar and board #18199's backend plus a CLI guide change; see What Changed)
  • 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) — blocked locally by pre-existing failures noted under Testing; CI will cover

Add a separate "Attach to Folder Workspace…" action to the left-sidebar
worktree menu. It reuses the parent picker in a folder mode, targets the
exact captured checkout and execution owner, and confirms the result from
authoritative workspace lineage before updating the sidebar. Repository
membership and checkouts are never changed.

- Folder-attached worktrees show "Remove from Folder Workspace" and
  "Change Parent Worktree...", and a display-only "repo/" title prefix
  instead of a gray repo line.
- Drop "Remove from group" from the worktree menu; it ungrouped the whole
  repo.
- Folder workspace PR list: clicking a row opens that worktree and its
  Checks tab; a chevron expands inline details.
- Import folder attachment backend, sidebar nesting, and board folding
  (PR stablyai#18199) and the native workspace scope CLI guide.
- Localize new copy in six locales; record OpenSpec changes and
  validation.
@wuhaoyujerry
wuhaoyujerry marked this pull request as ready for review October 7, 2026 07:05
Copilot AI balanced review requested due to automatic review settings October 7, 2026 07:05

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Host-collision handling, stale-lineage detection, projection failure reporting, accessibility, and unrelated scope issues remain unresolved.

Review effort: Balanced
Findings: 4 Medium severity · 3 Low severity

Open (7)
What changed in this PR

Adds sidebar attachment of existing worktrees to folder workspaces, including host-routed lineage persistence, nested sidebar/board rendering, and parent-management UI. The PR also bundles separate repository-import diagnostics and CLI guidance changes.

Changes:

  • Adds folder-parent selection, mutation guards, lineage projection, nesting, and board integration.
  • Updates titles, context menus, PR-check navigation, localization, and tests.
  • Adds folder-group import diagnostics and workspace-scope documentation.
File Description
tests/​e2e/​folder-setup.spec.ts Tests folder workspace creation.
tests/​e2e/​folder-group-explanations.spec.ts Tests group-import explanations.
src/​shared/​project-group-types.ts Adds scan diagnostic types.
src/​renderer/​src/​store/​slices/​worktrees/​metadata/​worktree-parent-mutation-guard.ts Guards concurrent parent updates.
src/​renderer/​src/​store/​slices/​worktrees/​metadata/​worktree-lineage-refresh.ts Normalizes workspace lineage availability.
src/​renderer/​src/​store/​slices/​worktrees/​metadata/​worktree-lineage-actions.ts Applies guarded lineage mutations.
src/​renderer/​src/​store/​slices/​worktrees/​metadata/​worktree-folder-parent-projection.ts Projects confirmed folder parents.
src/​renderer/​src/​store/​slices/​worktrees.ts Registers folder-parent actions.
src/​renderer/​src/​store/​slices/​worktree-helpers.ts Extends the worktree slice API.
src/​renderer/​src/​i18n/​locales/​zh.json Adds Chinese translations.
src/​renderer/​src/​i18n/​locales/​ko.json Adds Korean translations.
src/​renderer/​src/​i18n/​locales/​ja.json Adds Japanese translations.
src/​renderer/​src/​i18n/​locales/​fr.json Adds French translations.
src/​renderer/​src/​i18n/​locales/​es.json Adds Spanish translations.
src/​renderer/​src/​i18n/​locales/​en.json Adds English UI copy.
src/​renderer/​src/​i18n/​en-runtime-required.json Updates required runtime copy.
src/​renderer/​src/​components/​sidebar/​WorktreeTitleInlineRename.tsx Adds display-only title prefixes.
src/​renderer/​src/​components/​sidebar/​WorktreeParentPickerRow.tsx Renders folder candidates.
src/​renderer/​src/​components/​sidebar/​WorktreeParentMenuItems.tsx Adds parent menu actions.
src/​renderer/​src/​components/​sidebar/​WorktreeList.tsx Passes workspace lineage into rows.
src/​renderer/​src/​components/​sidebar/​WorktreeContextMenuView.tsx Integrates parent menu component.
src/​renderer/​src/​components/​sidebar/​WorktreeContextMenuOverlays.tsx Passes folder picker context.
src/​renderer/​src/​components/​sidebar/​WorktreeContextMenu.test.ts Tests folder-parent labels.
src/​renderer/​src/​components/​sidebar/​WorktreeCard.tsx Passes repository title prefix.
src/​renderer/​src/​components/​sidebar/​WorktreeCard.lineage.test.tsx Tests attached-child titles.
src/​renderer/​src/​components/​sidebar/​worktree-parent-picker-interaction.ts Extracts picker interactions.
src/​renderer/​src/​components/​sidebar/​worktree-parent-picker-filtering.ts Supports custom candidate search.
src/​renderer/​src/​components/​sidebar/​worktree-list/​viewport/​virtual-row-context.ts Exposes lineage toggle handling.
src/​renderer/​src/​components/​sidebar/​worktree-list/​rows/​item-row.tsx Labels folder-attached children.
src/​renderer/​src/​components/​sidebar/​worktree-list/​rows/​folder-row.tsx Adds attached-child collapse controls.
src/​renderer/​src/​components/​sidebar/​worktree-list/​listing/​use-section-rows.ts Supplies workspace lineage to row building.
src/​renderer/​src/​components/​sidebar/​worktree-list/​grouping/​row-types.ts Extends folder row metadata.
src/​renderer/​src/​components/​sidebar/​worktree-list/​grouping/​row-builders.ts Supports nested base depth.
src/​renderer/​src/​components/​sidebar/​worktree-list/​grouping/​recent-project-rank-scan-budget.test.ts Updates grouping fixture.
src/​renderer/​src/​components/​sidebar/​worktree-list/​grouping/​project-group-sections.ts Emits attached folder children.
src/​renderer/​src/​components/​sidebar/​worktree-list/​grouping/​group-sections.ts Integrates folder nesting into lanes.
src/​renderer/​src/​components/​sidebar/​worktree-list/​grouping/​group-keys.ts Adds folder collapse keys.
src/​renderer/​src/​components/​sidebar/​worktree-list/​grouping/​folder-workspace-rows.ts Builds folder and child rows.
src/​renderer/​src/​components/​sidebar/​worktree-list/​grouping/​folder-workspace-attached.ts Resolves attached children.
src/​renderer/​src/​components/​sidebar/​worktree-list/​grouping/​folder-workspace-attached.test.ts Tests attachment resolution.
src/​renderer/​src/​components/​sidebar/​worktree-list/​grouping/​build-rows.ts Removes attached children from ordinary lanes.
src/​renderer/​src/​components/​sidebar/​worktree-context-menu-policy.ts Adds folder-parent menu policy.
src/​renderer/​src/​components/​sidebar/​worktree-card-model.ts Adds repository-origin presentation.
src/​renderer/​src/​components/​sidebar/​worktree-card-meta-row.tsx Adjusts attached-child metadata.
src/​renderer/​src/​components/​sidebar/​worktree-card-header.tsx Prefixes attached-child titles.
src/​renderer/​src/​components/​sidebar/​WorkspaceKanbanDrawer.tsx Adds folders to the board.
src/​renderer/​src/​components/​sidebar/​WorkspaceKanbanDrawer.search.test.tsx Tests board folding.
src/​renderer/​src/​components/​sidebar/​workspace-kanban-folder-workspaces.ts Builds folder-aware board rows.
src/​renderer/​src/​components/​sidebar/​workspace-kanban-folder-workspaces.test.ts Tests board folder projection.
src/​renderer/​src/​components/​sidebar/​useAddRepoServerPathFlow.ts Adds scan-review routing.
src/​renderer/​src/​components/​sidebar/​useAddRepoServerPathFlow.test.ts Tests paired-host review.
src/​renderer/​src/​components/​sidebar/​useAddRepoNestedImportFlow.ts Completes Git-root opening.
src/​renderer/​src/​components/​sidebar/​useAddRepoLocalFolderFlow.ts Adds local scan-review routing.
src/​renderer/​src/​components/​sidebar/​useAddRepoLocalFolderFlow.test.ts Tests group-import intent.
src/​renderer/​src/​components/​sidebar/​use-worktree-parent-picker-transition.ts Captures folder context.
src/​renderer/​src/​components/​sidebar/​use-worktree-parent-picker-transition.test.tsx Tests captured picker ownership.
src/​renderer/​src/​components/​sidebar/​use-worktree-context-menu-model.tsx Wires attachment state and actions.
src/​renderer/​src/​components/​sidebar/​use-worktree-context-menu-commands.ts Removes row-level ungrouping.
src/​renderer/​src/​components/​sidebar/​use-workspace-kanban-board-projection.ts Handles folder visibility.
src/​renderer/​src/​components/​sidebar/​use-workspace-kanban-board-projection.test.tsx Tests folder host filtering.
src/​renderer/​src/​components/​sidebar/​use-folder-workspace-parent-picker.ts Loads and applies folder parents.
src/​renderer/​src/​components/​sidebar/​rendered-sidebar-worktree-order.ts Includes workspace lineage in ordering.
src/​renderer/​src/​components/​sidebar/​nested-repo-scan-review.ts Decides when scan review is shown.
src/​renderer/​src/​components/​sidebar/​host-section-reveal.test.tsx Updates section fixture.
src/​renderer/​src/​components/​sidebar/​folder-workspace-attachment-menu.test.ts Tests attachment menu policy.
src/​renderer/​src/​components/​sidebar/​complete-nested-folder-open.ts Opens reviewed Git roots.
src/​renderer/​src/​components/​sidebar/​complete-nested-folder-open.test.ts Tests reviewed-root handoff.
src/​renderer/​src/​components/​sidebar/​agent-send-picker-collapse.test.tsx Updates section fixture.
src/​renderer/​src/​components/​sidebar/​AddRepoSteps.tsx Adds remote scan-review policy.
src/​renderer/​src/​components/​sidebar/​AddRepoSteps.default-checkout.test.ts Tests SSH group-import review.
src/​renderer/​src/​components/​sidebar/​AddRepoStartSteps.tsx Exposes group-import action.
src/​renderer/​src/​components/​sidebar/​AddRepoNestedImportStep.tsx Displays scan explanations.
src/​renderer/​src/​components/​sidebar/​AddRepoDialogStepContent.tsx Passes group-import callback.
src/​renderer/​src/​components/​sidebar/​AddRepoDialog.tsx Tracks explicit group-import intent.
src/​renderer/​src/​components/​sidebar/​add-repo-local-start-actions.ts Adds group-import menu entry.
src/​renderer/​src/​components/​sidebar/​add-repo-dialog-types.ts Shares review callback types.
src/​renderer/​src/​components/​right-sidebar/​FolderWorkspacePrChecksRow.tsx Separates open and expand actions.
src/​renderer/​src/​components/​right-sidebar/​FolderWorkspacePrChecksRow.test.tsx Updates row fixture.
src/​renderer/​src/​components/​right-sidebar/​FolderWorkspacePrChecksPanel.tsx Opens child Checks tabs.
src/​renderer/​src/​components/​right-sidebar/​FolderWorkspacePrChecksPanel.test.tsx Tests PR-row activation.
src/​renderer/​src/​components/​repo/​NestedRepoScanExplanations.tsx Renders scan diagnostics.
src/​renderer/​src/​components/​repo/​NestedRepoScanExplanations.test.tsx Tests diagnostic rendering.
src/​main/​runtime/​orca-runtime-create-managed-remote-worktree.ts Enables folder-parent resolution.
src/​main/​project-groups/​nested-repo-scan-rules.ts Reports effective exclusion rules.
src/​main/​project-groups/​nested-repo-scan-rules.test.ts Tests exclusion provenance.
src/​main/​project-groups/​nested-repo-discovery.ts Collects bounded diagnostics.
src/​main/​ipc/​repos-nested-scan.test.ts Tests SSH diagnostic transport.
src/​cli/​index.test.ts Updates parent selector help tests.
src/​cli/​help.ts Documents folder selectors for set.
skill-guides/​orca-cli.md Adds workspace-scope guidance.
openspec/​specs/​orca-cli-workspace-scope/​spec.md Defines CLI scope requirements.
openspec/​specs/​.gitkeep Retains specification directory.
openspec/​config.yaml Adds OpenSpec configuration.
openspec/​changes/​archive/​2026-10-06-resolve-folder-workspace-scope-before-discovery/​validation.md Records scope validation.
openspec/​changes/​archive/​2026-10-06-resolve-folder-workspace-scope-before-discovery/​tasks.md Records scope tasks.
openspec/​changes/​archive/​2026-10-06-resolve-folder-workspace-scope-before-discovery/​specs/​orca-cli-workspace-scope/​spec.md Archives scope specification.
openspec/​changes/​archive/​2026-10-06-resolve-folder-workspace-scope-before-discovery/​proposal.md Archives scope proposal.
openspec/​changes/​archive/​2026-10-06-resolve-folder-workspace-scope-before-discovery/​.openspec.yaml Records scope change metadata.
openspec/​changes/​archive/​2026-10-06-attach-worktree-to-folder-workspace-ui/​validation.md Records attachment validation.
openspec/​changes/​archive/​2026-10-06-attach-worktree-to-folder-workspace-ui/​tasks.md Records attachment tasks.
openspec/​changes/​archive/​2026-10-06-attach-worktree-to-folder-workspace-ui/​proposal.md Archives attachment proposal.
openspec/​changes/​archive/​2026-10-06-attach-worktree-to-folder-workspace-ui/​.openspec.yaml Records attachment metadata.
openspec/​changes/​archive/​2026-10-05-explain-folder-group-import-exclusions/​tasks.md Records import-explanation tasks.
openspec/​changes/​archive/​2026-10-05-explain-folder-group-import-exclusions/​proposal.md Archives import-explanation proposal.
openspec/​changes/​archive/​2026-10-05-explain-folder-group-import-exclusions/​.openspec.yaml Records import change metadata.
openspec/​changes/​archive/​.gitkeep Retains archive directory.
config/​scripts/​vitest-sqlite-runtime-files.mjs Adds SQLite test runtime coverage.
config/​scripts/​generate-bundled-skill-guides.test.mjs Tests bundled scope guidance.
.vitest/​json/​output.json Adds a local failed-test artifact.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +80 to +84
<button
type="button"
className="mt-0.5 shrink-0 rounded text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring"
aria-expanded={expanded}
aria-label={toggleDetailsLabel}
Comment on lines +69 to +70
const edge = workspaceLineageByChildKey[worktreeWorkspaceKey(worktree.id)]
return edge ? parseWorkspaceKey(edge.parentWorkspaceKey)?.type === 'folder' : false
Comment on lines +40 to +42
const children = attached.get(parentScope.folderWorkspaceId) ?? []
children.push(worktree)
attached.set(parentScope.folderWorkspaceId, children)
Comment on lines +187 to +189
if (!applied && !findCapturedFolderParentChild(get(), context)) {
throw new Error('Checkout changed before the view could be refreshed.')
}
Comment thread .vitest/json/output.json Outdated
Comment on lines +28 to +32
"success": false,
"testResults": [
{
"assertionResults": [],
"startTime": 1791353209974,
Comment on lines +122 to +126
if (onImportGroup) {
secondaryActions.unshift({
kind: 'group',
icon: FolderTree,
title: translate('repoScan.importGroup', 'Import folder as group'),
Comment thread tests/e2e/folder-setup.spec.ts Outdated
Comment on lines +177 to +181
await expect
.poll(() =>
orcaPage.evaluate(() => {
const state = window.__store!.getState()
const folder = state.folderWorkspaces.find(
@coderabbitai

coderabbitai Bot commented Oct 7, 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: d992c38b-242e-4060-b2e9-32ec57485239
📥 Commits

Reviewing files that changed from the base of the PR and between 4a94591 and f51a10f.

📒 Files selected for processing (5)
  • config/scripts/vitest-sqlite-runtime-files.mjs
  • src/renderer/src/components/sidebar/AddRepoDialog.tsx
  • src/renderer/src/i18n/en-runtime-required.json
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/i18n/locales/es.json
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/renderer/src/i18n/en-runtime-required.json
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/i18n/locales/es.json

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

The changes add bounded diagnostics to nested-repository scans and show scan explanations in repository-import flows. They add folder-workspace parent resolution, attachment, lineage persistence, sidebar nesting, and Workspace Board representation. The sidebar parent picker and context menu support folder attachment. The Orca CLI guide documents folder-wide repository selection, and CLI help shows folder selectors for both worktree creation and parent updates.

Priority: ➖ Normal

Merge Risk: 🔵 Low · up to f51a1

A remote folder workspace can show its attached worktree as a separate Board item when its host is inherited from the project group. The documentation now covers setting an existing worktree's parent; the Board issue is limited to this host-fallback case.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR includes a separate folder-import feature that is not required by #18198. The changes add Import folder as group, nested-repository scan diagnostics and explanations, Git-root import handling, … Remove the folder-import feature and its dedicated diagnostics, UI, localization, and E2E changes from this PR, or move them to a separate PR. Keep the attachment-related changes and the CLI guide/help updates.
Docstring Coverage ⚠️ Warning Docstring coverage is 11.63% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 86 functions across 65 files. (3 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the primary change: attaching existing worktrees to folder workspaces from the sidebar menu.
Description check ✅ Passed The description follows the required template and explains the user-facing change, implementation, rationale, linked issue, visual proof, testing, AI disclosure, review notes, and known validation fai…
Linked Issues check ✅ Passed The changes satisfy the coding requirements in #18198. Existing worktrees can attach to folder workspaces through the folder parent picker and the guarded lineage mutation. The sidebar renders attache…
Full details: Out of Scope Changes check

Explanation

The PR includes a separate folder-import feature that is not required by #18198. The changes add Import folder as group, nested-repository scan diagnostics and explanations, Git-root import handling, and related importer E2E tests and localization. These changes do not attach existing worktrees, render folder children, or fold children into Workspace Board cards. The CLI guide and CLI help changes are connected to the folder-parent workflow and are in scope.

Full details: Docstring Coverage

Explanation

Docstring coverage is 11.63% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 86 functions across 65 files. (3 skipped: 3 unsupported.)

  • Fix all pre-merge checks with AI
  • Autopilot · 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: 4

Caution

Some comments are outside the diff and can’t be posted inline due to GitHub limitations.

⚠️ Outside diff range comments (1)

🟡 Minor · Document folder parents for worktree set. · orca-cli.md:123

skill-guides/orca-cli.md:123
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Document folder parents for worktree set.

This sentence limits folder parent selectors to worktree create, but the PR also supports worktree set --parent-worktree folder:<id> for an existing worktree. Update the guidance to include worktree set; otherwise, the guide incorrectly implies that existing worktrees cannot be attached to folders. The PR objective confirms this behavior.


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 3a4a3fff-5342-4bd1-b845-7708c42a3fd5
📥 Commits

Reviewing files that changed from the base of the PR and between 98e5f5c and c341bbc.

📒 Files selected for processing (105)
  • config/scripts/vitest-sqlite-runtime-files.mjs
  • skill-guides/orca-cli.md
  • src/cli/bundled-skill-guides.ts
  • src/cli/help.ts
  • src/cli/index.test.ts
  • src/main/ipc/repos-nested-scan.test.ts
  • src/main/project-groups/nested-repo-discovery.ts
  • src/main/project-groups/nested-repo-scan-diagnostics.test.ts
  • src/main/project-groups/nested-repo-scan-rules.test.ts
  • src/main/project-groups/nested-repo-scan-rules.ts
  • src/main/runtime/orca-runtime-create-managed-remote-worktree.ts
  • src/main/runtime/runtime-managed-worktree-metadata.folder-store.test.ts
  • src/main/runtime/runtime-managed-worktree-metadata.test.ts
  • src/main/runtime/runtime-managed-worktree-metadata.ts
  • src/renderer/src/components/repo/NestedRepoScanExplanations.test.tsx
  • src/renderer/src/components/repo/NestedRepoScanExplanations.tsx
  • src/renderer/src/components/right-sidebar/FolderWorkspacePrChecksPanel.test.tsx
  • src/renderer/src/components/right-sidebar/FolderWorkspacePrChecksPanel.tsx
  • src/renderer/src/components/right-sidebar/FolderWorkspacePrChecksRow.test.tsx
  • src/renderer/src/components/right-sidebar/FolderWorkspacePrChecksRow.tsx
  • src/renderer/src/components/sidebar/AddRepoDialog.tsx
  • src/renderer/src/components/sidebar/AddRepoDialogStepContent.tsx
  • src/renderer/src/components/sidebar/AddRepoNestedImportStep.tsx
  • src/renderer/src/components/sidebar/AddRepoStartSteps.tsx
  • src/renderer/src/components/sidebar/AddRepoSteps.default-checkout.test.ts
  • src/renderer/src/components/sidebar/AddRepoSteps.tsx
  • src/renderer/src/components/sidebar/WorkspaceKanbanDrawer.search.test.tsx
  • src/renderer/src/components/sidebar/WorkspaceKanbanDrawer.tsx
  • src/renderer/src/components/sidebar/WorktreeCard.lineage.test.tsx
  • src/renderer/src/components/sidebar/WorktreeCard.tsx
  • src/renderer/src/components/sidebar/WorktreeContextMenu.test.ts
  • src/renderer/src/components/sidebar/WorktreeContextMenuOverlays.tsx
  • src/renderer/src/components/sidebar/WorktreeContextMenuView.tsx
  • src/renderer/src/components/sidebar/WorktreeList.tsx
  • src/renderer/src/components/sidebar/WorktreeParentMenuItems.tsx
  • src/renderer/src/components/sidebar/WorktreeParentPickerPopover.tsx
  • src/renderer/src/components/sidebar/WorktreeParentPickerRow.tsx
  • src/renderer/src/components/sidebar/WorktreeTitleInlineRename.tsx
  • src/renderer/src/components/sidebar/add-repo-dialog-types.ts
  • src/renderer/src/components/sidebar/add-repo-local-start-actions.ts
  • src/renderer/src/components/sidebar/agent-send-picker-collapse.test.tsx
  • src/renderer/src/components/sidebar/complete-nested-folder-open.test.ts
  • src/renderer/src/components/sidebar/complete-nested-folder-open.ts
  • src/renderer/src/components/sidebar/folder-workspace-attachment-menu.test.ts
  • src/renderer/src/components/sidebar/folder-workspace-parent-candidates.test.ts
  • src/renderer/src/components/sidebar/folder-workspace-parent-candidates.ts
  • src/renderer/src/components/sidebar/host-section-reveal.test.tsx
  • src/renderer/src/components/sidebar/nested-repo-scan-review.ts
  • src/renderer/src/components/sidebar/rendered-sidebar-worktree-order.ts
  • src/renderer/src/components/sidebar/use-folder-workspace-parent-picker.test.tsx
  • src/renderer/src/components/sidebar/use-folder-workspace-parent-picker.ts
  • src/renderer/src/components/sidebar/use-workspace-kanban-board-projection.test.tsx
  • src/renderer/src/components/sidebar/use-workspace-kanban-board-projection.ts
  • src/renderer/src/components/sidebar/use-worktree-context-menu-commands.ts
  • src/renderer/src/components/sidebar/use-worktree-context-menu-model.tsx
  • src/renderer/src/components/sidebar/use-worktree-parent-picker-transition.test.tsx
  • src/renderer/src/components/sidebar/use-worktree-parent-picker-transition.ts
  • src/renderer/src/components/sidebar/useAddRepoLocalFolderFlow.test.ts
  • src/renderer/src/components/sidebar/useAddRepoLocalFolderFlow.ts
  • src/renderer/src/components/sidebar/useAddRepoNestedImportFlow.ts
  • src/renderer/src/components/sidebar/useAddRepoServerPathFlow.test.ts
  • src/renderer/src/components/sidebar/useAddRepoServerPathFlow.ts
  • src/renderer/src/components/sidebar/workspace-kanban-folder-workspaces.test.ts
  • src/renderer/src/components/sidebar/workspace-kanban-folder-workspaces.ts
  • src/renderer/src/components/sidebar/worktree-card-header.tsx
  • src/renderer/src/components/sidebar/worktree-card-meta-row.tsx
  • src/renderer/src/components/sidebar/worktree-card-model.ts
  • src/renderer/src/components/sidebar/worktree-card-presentation.tsx
  • src/renderer/src/components/sidebar/worktree-context-menu-policy.ts
  • src/renderer/src/components/sidebar/worktree-list/grouping/build-rows.folder-workspace-lanes.test.ts
  • src/renderer/src/components/sidebar/worktree-list/grouping/build-rows.ts
  • src/renderer/src/components/sidebar/worktree-list/grouping/folder-workspace-attached.test.ts
  • src/renderer/src/components/sidebar/worktree-list/grouping/folder-workspace-attached.ts
  • src/renderer/src/components/sidebar/worktree-list/grouping/folder-workspace-rows.ts
  • src/renderer/src/components/sidebar/worktree-list/grouping/group-keys.ts
  • src/renderer/src/components/sidebar/worktree-list/grouping/group-sections.ts
  • src/renderer/src/components/sidebar/worktree-list/grouping/project-group-sections.ts
  • src/renderer/src/components/sidebar/worktree-list/grouping/recent-project-rank-scan-budget.test.ts
  • src/renderer/src/components/sidebar/worktree-list/grouping/row-builders.ts
  • src/renderer/src/components/sidebar/worktree-list/grouping/row-types.ts
  • src/renderer/src/components/sidebar/worktree-list/listing/use-section-rows.ts
  • src/renderer/src/components/sidebar/worktree-list/rows/folder-row.tsx
  • src/renderer/src/components/sidebar/worktree-list/rows/item-row.tsx
  • src/renderer/src/components/sidebar/worktree-list/viewport/virtual-row-context.ts
  • src/renderer/src/components/sidebar/worktree-parent-picker-filtering.ts
  • src/renderer/src/components/sidebar/worktree-parent-picker-interaction.ts
  • src/renderer/src/i18n/en-runtime-required.json
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/i18n/locales/es.json
  • src/renderer/src/i18n/locales/fr.json
  • src/renderer/src/i18n/locales/ja.json
  • src/renderer/src/i18n/locales/ko.json
  • src/renderer/src/i18n/locales/zh.json
  • src/renderer/src/store/slices/worktree-helpers.ts
  • src/renderer/src/store/slices/worktrees-folder-parent-actions.test.ts
  • src/renderer/src/store/slices/worktrees.ts
  • src/renderer/src/store/slices/worktrees/metadata/worktree-folder-parent-actions.ts
  • src/renderer/src/store/slices/worktrees/metadata/worktree-folder-parent-projection.ts
  • src/renderer/src/store/slices/worktrees/metadata/worktree-lineage-actions.ts
  • src/renderer/src/store/slices/worktrees/metadata/worktree-lineage-refresh.ts
  • src/renderer/src/store/slices/worktrees/metadata/worktree-parent-mutation-guard.ts
  • src/shared/project-group-types.ts
  • tests/e2e/folder-group-explanations.spec.ts
  • tests/e2e/folder-setup.spec.ts
  • tests/e2e/folder-workspace-nesting.spec.ts
💤 Files with no reviewable changes (1)
  • src/renderer/src/components/sidebar/use-worktree-context-menu-commands.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/components/repo/NestedRepoScanExplanations.tsx Outdated
Comment thread src/renderer/src/components/sidebar/worktree-card-presentation.tsx
Comment thread src/renderer/src/i18n/locales/en.json Outdated

@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

🧹 Nitpick comments (1)
src/renderer/src/components/right-sidebar/FolderWorkspacePrChecksRow.test.tsx (1)

165-180: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Prefer role-based queries in this test.

The test uses container.querySelectorAll('button') and a positional destructure. A role-based query is more resilient to markup changes. Use getByRole('button', { name: ... }) for the toggle, open, and external-link buttons. The checks for accessible names then become part of the query itself.

Based on learnings: prefer getByRole (role plus name) over container queries in React Testing Library tests.

Source: Learnings


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 795d9dd6-9454-403d-acf0-eec7d3818b95
📥 Commits

Reviewing files that changed from the base of the PR and between c341bbc and 4a94591.

📒 Files selected for processing (29)
  • skill-guides/orca-cli.md
  • src/cli/bundled-skill-guides.ts
  • src/renderer/src/components/repo/NestedRepoScanExplanations.test.tsx
  • src/renderer/src/components/repo/NestedRepoScanExplanations.tsx
  • src/renderer/src/components/right-sidebar/FolderWorkspacePrChecksRow.test.tsx
  • src/renderer/src/components/right-sidebar/FolderWorkspacePrChecksRow.tsx
  • src/renderer/src/components/sidebar/WorktreeCard.lineage.test.tsx
  • src/renderer/src/components/sidebar/folder-workspace-attachment-menu.test.ts
  • src/renderer/src/components/sidebar/workspace-kanban-folder-workspaces.test.ts
  • src/renderer/src/components/sidebar/workspace-kanban-folder-workspaces.ts
  • src/renderer/src/components/sidebar/worktree-card-presentation.tsx
  • src/renderer/src/components/sidebar/worktree-context-menu-policy.ts
  • src/renderer/src/components/sidebar/worktree-list/grouping/build-rows.folder-workspace-lanes.test.ts
  • src/renderer/src/components/sidebar/worktree-list/grouping/build-rows.ts
  • src/renderer/src/components/sidebar/worktree-list/grouping/folder-workspace-attached.test.ts
  • src/renderer/src/components/sidebar/worktree-list/grouping/folder-workspace-attached.ts
  • src/renderer/src/components/sidebar/worktree-list/grouping/folder-workspace-host-isolation.test.ts
  • src/renderer/src/components/sidebar/worktree-list/grouping/folder-workspace-rows.ts
  • src/renderer/src/components/sidebar/worktree-list/grouping/group-sections.ts
  • src/renderer/src/components/sidebar/worktree-list/grouping/project-group-sections.ts
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/i18n/locales/es.json
  • src/renderer/src/i18n/locales/fr.json
  • src/renderer/src/i18n/locales/ja.json
  • src/renderer/src/i18n/locales/ko.json
  • src/renderer/src/i18n/locales/zh.json
  • src/renderer/src/store/slices/worktrees-folder-parent-actions.test.ts
  • src/renderer/src/store/slices/worktrees/metadata/worktree-folder-parent-actions.ts
  • tests/e2e/folder-setup.spec.ts
💤 Files with no reviewable changes (6)
  • src/renderer/src/i18n/locales/fr.json
  • src/renderer/src/i18n/locales/zh.json
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/i18n/locales/ko.json
  • src/renderer/src/i18n/locales/ja.json
  • src/renderer/src/i18n/locales/es.json
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/renderer/src/components/repo/NestedRepoScanExplanations.tsx
  • src/renderer/src/components/sidebar/WorktreeCard.lineage.test.tsx
  • src/renderer/src/components/sidebar/worktree-card-presentation.tsx
  • src/renderer/src/components/repo/NestedRepoScanExplanations.test.tsx

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 on lines +33 to +37
(
attachedByFolderId.get(
composeWorktreeHostIdentity(folderWorkspaceToWorktree(workspace).hostId, workspace.id)
) ?? []
).map(getWorktreeHostIdentity)

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🔎 Supported by static analysis

🏁 Script executed:

#!/bin/bash
rg -nP -C3 'buildWorkspaceBoardWorktrees\s*\(' src/renderer
rg -nP -C3 'connectionId' src/shared/folder-workspace-types.ts

Repository: stablyai/orca

Length of output: 5654


🏁 Script executed:

set -o pipefail
printf '%s\n' '--- board implementation ---'
nl -ba src/renderer/src/components/sidebar/workspace-kanban-folder-workspaces.ts | sed -n '1,180p'
printf '%s\n' '--- drawer caller ---'
nl -ba src/renderer/src/components/sidebar/WorkspaceKanbanDrawer.tsx | sed -n '55,110p'
printf '%s\n' '--- sidebar identity references ---'
rg -n -F -- 'getFolderWorkspaceAttachmentIdentity' src/renderer src/shared
printf '%s\n' '--- attachment helper references ---'
rg -n -F -- 'getAttachedWorktreesByFolderWorkspaceIdentity' src/renderer src/shared
printf '%s\n' '--- identity definitions and folder workspace types ---'
rg -n -C8 -F -- 'function getFolderWorkspaceAttachmentIdentity' src
rg -n -C8 -F -- 'function getAttachedWorktreesByFolderWorkspaceIdentity' src
nl -ba src/shared/folder-workspace-types.ts | sed -n '1,130p'
printf '%s\n' '--- folder workspace conversion and project-group types ---'
rg -n -C8 -F -- 'function folderWorkspaceToWorktree' src
rg -n -C8 -F -- 'projectGroup.connectionId' src/renderer src/shared

Repository: stablyai/orca

Length of output: 26644


🏁 Script executed:

set -o pipefail
nl -ba src/renderer/src/components/sidebar/workspace-kanban-folder-workspaces.ts | sed -n '1,180p'
nl -ba src/renderer/src/components/sidebar/WorkspaceKanbanDrawer.tsx | sed -n '55,110p'
rg -n -C8 -F -- 'getFolderWorkspaceAttachmentIdentity' src/renderer src/shared
rg -n -C8 -F -- 'getAttachedWorktreesByFolderWorkspaceIdentity' src/renderer src/shared
rg -n -C8 -F -- 'function folderWorkspaceToWorktree' src
nl -ba src/shared/folder-workspace-types.ts | sed -n '1,130p'

Repository: stablyai/orca

Length of output: 37993


🏁 Script executed:

set -o pipefail
printf '%s\n' '--- attachment helper ---'
nl -ba src/renderer/src/components/sidebar/worktree-list/grouping/folder-workspace-attached.ts | sed -n '1,125p'
printf '%s\n' '--- renderable folder workspace construction ---'
rg -n -C10 -F -- 'RenderableFolderWorkspace' src/renderer/src/components/sidebar/worktree-list/grouping
printf '%s\n' '--- default host build-rows signature and callers ---'
nl -ba src/renderer/src/components/sidebar/worktree-list/grouping/build-rows.ts | sed -n '45,145p'
rg -n -C8 -F -- 'buildWorktreeRows' src/renderer/src/components/sidebar
printf '%s\n' '--- project group and folder workspace loading/normalization ---'
rg -n -C8 -F -- 'folderWorkspace.projectGroupId' src/renderer src/shared
rg -n -C8 -F -- 'getRenderableFolderWorkspaces' src/renderer/src/components/sidebar

Repository: stablyai/orca

Length of output: 42286


Use one shared helper for the board’s folder identity.

buildWorkspaceBoardWorktrees uses folderWorkspaceToWorktree(workspace).hostId, while the sidebar uses the folder’s executionHostId, its own or project-group connectionId, and defaultHostId. The board also omits defaultHostId when it builds the attachment map.

When a folder inherits an SSH host from its project group, the sidebar uses an SSH key but the board falls back to local. The attached worktree then remains a standalone row instead of being folded into the folder card. Pass the project-group context and defaultHostId into buildWorkspaceBoardWorktrees, and use getFolderWorkspaceAttachmentIdentity for the folder lookup.

This branch has not been deployed

No deployments
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.

[Feature]: Attach existing worktrees to a folder workspace, and nest them under it in the sidebar and Workspace Board

2 participants