Skip to content

fix(worktrees): keep each same-path copy on its own host branch - #33428

Merged
nwparker merged 27 commits into
mainfrom
nwparker/fix-32918-same-path-hosts
Oct 25, 2026
Merged

nwparker merged 27 commits into
mainfrom
nwparker/fix-32918-same-path-hosts

Conversation

@nwparker

@nwparker nwparker commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor
Files Added Deleted Net
Test 18 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​922 $\color{#cf222e}{\Huge{\mathbf{−}}}$​150 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​772
Prod 28 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​676 $\color{#cf222e}{\Huge{\mathbf{−}}}$​163 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​513

ELI5

Orca names a workspace by its project and folder path. That name has no machine in it. When the same project sits at the same path on two machines, both copies can end up with the same name (a "same-id twin"). Orca then mixed the two up:

  • the branch check could run on the wrong machine, and its answer was written onto both copies;
  • a branch switch on one copy could clear the other copy's linked PR.

That's why both rows showed master. Now every branch read and write names the exact copy it's for.

What Changed

  • Before: with the same project at the same path on two hosts, both sidebar rows could show one host's branch and title. The branch check for an SSH copy could even run locally.
  • After: each copy keeps its own branch. The git status check runs on the copy's own host and updates only that copy. Review links and push targets are cleared only on the copy that switched branch.

Mechanism, one resolver and one rule:

  • resolveWorktreeGitCopy (new, src/renderer/src/lib/worktree-git-copy.ts) resolves the transport, the SSH connection and the host of the same copy in one step.
    • It uses the selected copy, or a host the caller captured earlier.
    • For a twin, the bare-id connection lookup answers "unknown", which callers used to turn into a local git status of the SSH copy's path. The resolver looks up the connection for the named copy instead (getConnectionIdForWorktreeCopy).
  • Every path that writes git identity back now gets its host from this resolver:
    • the git status poll;
    • the Checks panel, both the effect and the manual refresh (the latter captures the host in the same render as its transport);
    • Source Control refresh, including callbacks that run after a mutation, which keep the host captured when they were created;
    • PR generation (the copy and its transport are captured in its context);
    • Create PR intent: the run pins the copy and transport resolved at start and never re-resolves them. If that copy didn't resolve, every call in the run refuses rather than committing or pushing on a twin's checkout.
    • The push target used by Create PR and by the post-generation refresh is read from that copy's row (worktreeCopyPushTarget). It no longer comes from the id-keyed worktree map, which could hold the other copy's remote and branch.
  • An ambiguous twin with no selection stays unplaced, so its calls refuse instead of guessing. A resolved local connection (null) is final, and only "unknown" falls through to the copy lookup.
  • updateWorktreeGitIdentity requires ownerHostId, so the compiler rejects a call without one.
    • An id that only one host has is patched as before.
    • For a twin, only the copy on that host is patched, via selectWorkspaceByHostTarget. With no host named, neither copy is patched.
    • "Twin" means rows that differ by host or by the paired server that published them.
  • Review-clear tombstones are always keyed by id plus the copy's owner. They never use the bare id.
    • A guard can't rewrite a twin that shows up later.
    • Both copies keep their own guard, and it survives renames.
    • Relinking one copy keeps its sibling's guard.
    • Listing rows are stamped with their owner before they're checked.
    • The deferred clear saves to the answering host (persistWorktreeMeta with the host), falling back to the row's stamp.

Why

A worktree id is not unique across hosts. Fixing each reported path on its own kept missing others. Review found the transport, the connection, the tombstones and the save each still keyed by bare id. So the design changed:

  • one resolver produces the host, the connection and the transport together;
  • one required host parameter on the single function that writes branch identity;
  • one owner-keyed tombstone rule.

Same-id twins are an existing state. Listings, sidebar activity, GitHub (#33257) and Linear (#33270) were already made host-aware the same way.

Known follow-up: the review-clear tombstone rules now carry stamp normalization for legacy and partially stamped rows. A later PR should simplify them, for example by keying guards with getWorktreeHostIdentity once every listing path stamps rows the same way.

Not changed here: the active-workspace git status maps (gitStatusByWorktree) are still keyed by bare id. They drive the active panels only, not the sidebar.

Linked Issue

Part of #32918. This fixes the "both projects show master" symptom for same-id twins. It does not address the profile-state revision conflict or the pairing error in that report.

Thanks to @shainisinha-wtg for the detailed report, screenshot and log bundle.

Visual Proof

N/A: no new UI. Each row shows its own host's branch. Tests and the live lane below cover it.

Testing

  • I manually tested these changes locally

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

  • git-status-twin-copy.test.ts (poll level, real app store): a local copy and an SSH copy at the same path, with the SSH copy selected.

    • git:status must go out with connectionId: 'box-b'.
    • Only the SSH copy is patched.
  • worktrees-git-identity-twin-host.test.ts covers twin patching:

    • only the answering copy is patched; with no host, neither is;
    • a paired server's SSH checkout is reached through its runtime alias, and a twin published by another paired server under the same SSH id is left alone.
  • The same file covers review clears and tombstones:

    • each copy's push target and link are cleared and saved on its own host;
    • tombstones are per copy, survive renames and outlive the sibling;
    • relinking one copy keeps the other's guard;
    • a lone copy's guard never touches a later twin.
  • The slice-level twin tests fail on origin/main.

  • src/renderer/src/store/slices, src/renderer/src/lib, src/renderer/src/hooks and src/renderer/src/components/right-sidebar pass single-worker (1690 files).

  • The full local static job (every step of pr.yml "static analysis and typecheck") passes.

  • Docker managed-orcad lane: dispatched on CI for this head (two Docker SSH hosts with a shared home, explorer host selection, terminal journeys). The harness can't produce a same-id twin. Two independent hosts, and two hosts sharing a home (each gets its own server under hosts/<machine>), mint different repo ids. So that lane checks the same-path, two-host paths for regressions but can't show this bug.

Review

Focus on:

  • resolveWorktreeGitCopy: the connection must come from the same copy as the transport;
  • gitIdentityTargets in worktree-git-identity-update.ts;
  • the owner-keyed tombstone rules in hosted-review-link-mutation.ts and worktree-copy-review-clear.ts.

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

  • Behaviour changes for non-twin worktrees:

    • the git transport is now resolved with the copy's host named (runtimeTargetForWorkspaceOwner with hostId);
    • the branch-switch review-clear save now sends executionHostId when a host is known. Main already uses it to pick the matching metadata row.
  • Review-clear guards are keyed by the stamp the row's next listing gives it, filling in only missing parts:

    • a local row stays unstamped, so local and unset share one key;
    • a runtime: host is its own server, so backfilled provenance never changes its key;
    • an SSH row lacking provenance gets its sole repo registration's server.
      This way legacy and partially stamped rows keep their guard across their first stamped listing, and a relink of the still-unstamped row matches it too.
  • Remote and mixed versions: renderer-only. No wire, RPC or persisted-shape changes.

  • Folder workspaces: git identity is written only for git worktrees. Folder paths keep their existing per-folder connection lookup.

  • Mobile: phones read the host's sidebar feed, which already keys rows by host. Unaffected.

  • Cross-platform: no path or process changes.

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)

@coderabbitai

coderabbitai Bot commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 927dda58-bf30-446a-a7be-79a0af79866a
Commits

Reviewing files that changed from the base of the PR and between 26671fa and 2029752.

Files selected for processing: 4
  • src/renderer/src/components/right-sidebar/git-status-twin-copy.test.ts
  • src/renderer/src/lib/worktree-git-copy.ts
  • src/renderer/src/store/slices/worktrees-git-identity-twin-host.test.ts
  • src/renderer/src/store/slices/worktrees/metadata/worktree-git-identity-update.ts

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

Walkthrough

Git status refreshes now resolve a worktree copy and use its host, transport, and connection information. Git identity updates and hosted-review link clears can target individual copies when host ownership is available. Pull-request generation and create-PR flows carry owner host IDs through their contexts. Tests cover twin worktrees, copy-scoped review-link clearing, and updated refresh calls. Workspace-record read baselines for two metadata modules decrease.

Priority: Normal

Merge Risk: Moderate · up to 20297

PR generation can run against the wrong host when a same-path worktree copy is ambiguous. Prevent generation until a copy is resolved before merging.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 44.64% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 56 functions across 45 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title clearly identifies the main change: keeping same-path worktree copies isolated by host branch.
Description check Passed The description is complete and directly addresses the template. It explains the problem, user-visible behavior, implementation, rationale, linked issue, visual proof, testing, review focus, compatibi…
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.
Full details: Description check

Explanation

The description is complete and directly addresses the template. It explains the problem, user-visible behavior, implementation, rationale, linked issue, visual proof, testing, review focus, compatibility notes, and checklist status.

Finishing Touches: 💡 2
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
⚔️ Resolve merge conflicts: 💡
  • Resolve merge conflict in branch nwparker/fix-32918-same-path-hosts
  • 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
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 99b24510-b39d-4d78-9dfc-491e3d09ba3e
Commits

Reviewing files that changed from the base of the PR and between cc2b6fe and 2544a3b.

Files selected for processing: 23
  • config/workspace-record-read-baseline.txt
  • src/renderer/src/components/right-sidebar/checks-panel/use-checks-panel-git-status-effects.tsx
  • src/renderer/src/components/right-sidebar/checks-panel/use-checks-panel-manual-refresh.tsx
  • src/renderer/src/components/right-sidebar/git-status-refresh-branch-line-total.test.ts
  • src/renderer/src/components/right-sidebar/git-status-refresh.test.ts
  • src/renderer/src/components/right-sidebar/git-status-refresh.ts
  • src/renderer/src/components/right-sidebar/push-target-upstream-refresh-cache.test.ts
  • src/renderer/src/components/right-sidebar/source-control/review/use-create-pr-intent-probes.ts
  • src/renderer/src/components/right-sidebar/source-control/sync/use-status-refresh.ts
  • src/renderer/src/components/right-sidebar/useGitStatusPolling.test.ts
  • src/renderer/src/components/right-sidebar/useGitStatusPolling.ts
  • src/renderer/src/components/right-sidebar/worktree-git-owner-target.ts
  • src/renderer/src/hooks/worktree-head-identity-apply.test.ts
  • src/renderer/src/hooks/worktree-head-identity-apply.ts
  • src/renderer/src/store/slices/worktree-helpers.ts
  • src/renderer/src/store/slices/worktree-listing-branch-switch.test.ts
  • src/renderer/src/store/slices/worktree-listing-branch-switch.ts
  • src/renderer/src/store/slices/worktrees-fetch-listing-merge.test.ts
  • src/renderer/src/store/slices/worktrees-git-identity-branch-title.test.ts
  • src/renderer/src/store/slices/worktrees-git-identity-review-clear-persistence.test.ts
  • src/renderer/src/store/slices/worktrees-git-identity-twin-host.test.ts
  • src/renderer/src/store/slices/worktrees-identity-migration.test.ts
  • src/renderer/src/store/slices/worktrees/metadata/worktree-git-identity-update.ts

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

@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: 3


Review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 641dfd86-79be-462b-b7f9-e15de2ec9096
Commits

Reviewing files that changed from the base of the PR and between 2544a3b and bfd892c.

Files selected for processing: 28
  • config/workspace-record-read-baseline.txt
  • src/renderer/src/components/right-sidebar/checks-panel/manual-refresh-dependencies.ts
  • src/renderer/src/components/right-sidebar/checks-panel/use-checks-panel-controller-state.tsx
  • src/renderer/src/components/right-sidebar/checks-panel/use-checks-panel-generation.tsx
  • src/renderer/src/components/right-sidebar/checks-panel/use-checks-panel-git-status-effects.test.tsx
  • src/renderer/src/components/right-sidebar/checks-panel/use-checks-panel-git-status-effects.tsx
  • src/renderer/src/components/right-sidebar/checks-panel/use-checks-panel-manual-refresh.test.tsx
  • src/renderer/src/components/right-sidebar/checks-panel/use-checks-panel-manual-refresh.tsx
  • src/renderer/src/components/right-sidebar/git-status-twin-copy.test.ts
  • src/renderer/src/components/right-sidebar/source-control/listing/operation-target.ts
  • src/renderer/src/components/right-sidebar/source-control/review/create-pr-intent-flow.ts
  • src/renderer/src/components/right-sidebar/source-control/review/use-create-pr-intent-probes.ts
  • src/renderer/src/components/right-sidebar/source-control/review/use-create-pr-intent-run.ts
  • src/renderer/src/components/right-sidebar/source-control/review/use-create-pr-intent-target.ts
  • src/renderer/src/components/right-sidebar/source-control/review/use-pull-request-generation.ts
  • src/renderer/src/components/right-sidebar/source-control/sync/use-status-refresh.ts
  • src/renderer/src/components/right-sidebar/useGitStatusPolling.test.ts
  • src/renderer/src/components/right-sidebar/useGitStatusPolling.ts
  • src/renderer/src/lib/connection-owner-resolution.ts
  • src/renderer/src/lib/worktree-git-copy.ts
  • src/renderer/src/store/slices/pull-request-generation-state.ts
  • src/renderer/src/store/slices/worktree-listing-branch-switch.ts
  • src/renderer/src/store/slices/worktrees-git-identity-twin-host.test.ts
  • src/renderer/src/store/slices/worktrees/listing/detected-worktree-host-merge.ts
  • src/renderer/src/store/slices/worktrees/metadata/hosted-review-link-mutation.ts
  • src/renderer/src/store/slices/worktrees/metadata/update-worktree-meta.ts
  • src/renderer/src/store/slices/worktrees/metadata/worktree-copy-review-clear.ts
  • src/renderer/src/store/slices/worktrees/metadata/worktree-git-identity-update.ts

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

for (const worktreeId of worktreeIds) {
hostedReviewLinkMutationGenerationByWorktreeId.delete(worktreeId)
hostedReviewLinkClearTombstonesByWorktreeId.delete(worktreeId)
deleteCopyTombstones(hostedReviewLinkClearTombstonesByCopy, worktreeId)

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.

Minor · Functional Correctness · Quick win

🔎 Supported by static analysis

Script executed:

#!/bin/bash
rg -n -C 6 'pruneHostedReviewLinkMutationGenerations\(' src/renderer/src --glob '!**/*.test.ts'

Repository: stablyai/orca

Length of output: 4764


Script executed:

set -u
echo "== deleteCopyTombstones definition =="
rg -n -F -e 'function deleteCopyTombstones' -e 'deleteCopyTombstones(' -- src/renderer/src/store/slices/worktrees/metadata/hosted-review-link-mutation.ts || test "$?" -eq 1
echo "== remove-worktree.ts 230-290 =="
sed -n '230,290p' src/renderer/src/store/slices/worktrees/teardown/remove-worktree.ts | cat -n
echo "== worktree-purge-state.ts 55-96 =="
sed -n '55,96p' src/renderer/src/store/slices/worktrees/teardown/worktree-purge-state.ts | cat -n

Repository: stablyai/orca

Length of output: 5030


Script executed:

set -u
rg -n -F -e 'deleteCopyTombstones' -- src/renderer/src || test "$?" -eq 1
echo "== hosted-review-link-mutation.ts imports and 60-100 =="
sed -n '1,30p' src/renderer/src/store/slices/worktrees/metadata/hosted-review-link-mutation.ts | cat -n
sed -n '60,100p' src/renderer/src/store/slices/worktrees/metadata/hosted-review-link-mutation.ts | cat -n

Repository: stablyai/orca

Length of output: 4280


Script executed:

set -u
echo "== worktree-copy-review-clear.ts 1-70 =="
sed -n '1,70p' src/renderer/src/store/slices/worktrees/metadata/worktree-copy-review-clear.ts | cat -n
echo "== consumers of the copy tombstone map =="
rg -n -F -e 'hostedReviewLinkClearTombstonesByCopy' -e 'reviewClearTombstoneKey(' -- src/renderer/src --glob '!**/*.test.ts' || test "$?" -eq 1

Repository: stablyai/orca

Length of output: 5720


Scope the removal prune to the removed copy.

remove-worktree.ts calls pruneHostedReviewLinkMutationGenerations([worktreeId]) after it removes one host's copy. That call drops the review-clear tombstones and the shared generation for every copy with the same worktree ID. A same-path twin on another host can lose its clear tombstone, and with it the stale-refetch guard that the copy-keyed design adds. The removal path should prune only the removed copy's tombstone. The ID-wide cleanup should run only when no sibling copy remains.

Comment on lines +280 to +296
worktreeId: string,
copy: { owner: string; hostId: ExecutionHostId | undefined }
): void {
set((s) => {
const nextWorktrees = applyWorktreeUpdates(
s.worktreesByRepo,
worktreeId,
CLEARED_HOSTED_REVIEW_LINK_UPDATES
)
const byRepo = s.worktreesByRepo
const nextWorktrees = clearCopyReviewLinks(byRepo, worktreeId, copy.owner)
const nextDetectedWorktrees = applyDetectedWorktreeUpdates(
s.detectedWorktreesByRepo,
worktreeId,
CLEARED_HOSTED_REVIEW_LINK_UPDATES
CLEARED_HOSTED_REVIEW_LINK_UPDATES,
copy.hostId
)
if (
nextWorktrees === s.worktreesByRepo &&
nextDetectedWorktrees === s.detectedWorktreesByRepo
) {
if (nextWorktrees === byRepo && nextDetectedWorktrees === s.detectedWorktreesByRepo) {
return s
}
return {
...(nextWorktrees !== s.worktreesByRepo
...(nextWorktrees !== byRepo

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.

Minor · Functional Correctness · Quick win

Match detected rows by copy owner.

When the branch-switch identity update rereads a same-ID copy, applyHostedReviewLinkClear can receive the selected copy while applyDetectedWorktreeUpdates matches only hostId. Two copies with the same host and different runtimeOwnerEnvironmentId can therefore cause the sibling's detected review link to be cleared. Host-scoping the async reread and save does not fix this detected-row mutation.

Pass the captured owner to detected-row matching while preserving host-only behavior for existing callers.

Suggested fix
diff --git a/src/renderer/src/store/slices/worktrees/listing/worktree-meta-host-match.ts b/src/renderer/src/store/slices/worktrees/listing/worktree-meta-host-match.ts
@@
 import {
   LOCAL_EXECUTION_HOST_ID,
   type ExecutionHostId
 } from '../../../../../../shared/execution-host'
+import { worktreeCopyOwnerKey } from '../metadata/worktree-copy-review-clear'
@@
 export function worktreeRowMatchesMetaHost(
-  worktree: { hostId?: ExecutionHostId },
-  executionHostId: ExecutionHostId | undefined
+  worktree: { hostId?: ExecutionHostId; runtimeOwnerEnvironmentId?: string },
+  executionHostId: ExecutionHostId | undefined,
+  copyOwner?: string
 ): boolean {
+  if (copyOwner !== undefined) {
+    return worktreeCopyOwnerKey(worktree) === copyOwner
+  }
   return (
     executionHostId === undefined ||
     worktree.hostId === executionHostId ||
diff --git a/src/renderer/src/store/slices/worktrees/listing/detected-worktree-meta.ts b/src/renderer/src/store/slices/worktrees/listing/detected-worktree-meta.ts
@@
   worktreeId: string,
   rawUpdates: Partial<WorktreeMeta>,
-  executionHostId?: ExecutionHostId
+  executionHostId?: ExecutionHostId,
+  copyOwner?: string
 ): AppState['detectedWorktreesByRepo'] {
@@
-      if (worktree.id !== worktreeId || !worktreeRowMatchesMetaHost(worktree, executionHostId)) {
+      if (
+        worktree.id !== worktreeId ||
+        !worktreeRowMatchesMetaHost(worktree, executionHostId, copyOwner)
+      ) {
         return worktree
       }
diff --git a/src/renderer/src/store/slices/worktrees/metadata/hosted-review-link-mutation.ts b/src/renderer/src/store/slices/worktrees/metadata/hosted-review-link-mutation.ts
@@
       worktreeId,
       CLEARED_HOSTED_REVIEW_LINK_UPDATES,
-      copy.hostId
+      copy.hostId,
+      copy.owner
     )

@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: 2


Review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 5084da53-c677-4b01-9f11-df81d2655e5d
Commits

Reviewing files that changed from the base of the PR and between bfd892c and 7fdb180.

Files selected for processing: 12
  • src/renderer/src/components/right-sidebar/checks-panel/use-checks-panel-generation.tsx
  • src/renderer/src/components/right-sidebar/git-status-twin-copy.test.ts
  • src/renderer/src/components/right-sidebar/source-control/review/create-pr-intent-flow.ts
  • src/renderer/src/components/right-sidebar/source-control/review/create-pr-intent-operation-target.test.ts
  • src/renderer/src/components/right-sidebar/source-control/review/use-create-pr-intent-run.ts
  • src/renderer/src/components/right-sidebar/source-control/review/use-create-pr-intent-target.ts
  • src/renderer/src/components/right-sidebar/source-control/review/use-pull-request-generation.ts
  • src/renderer/src/lib/worktree-git-copy.ts
  • src/renderer/src/store/slices/worktrees-git-identity-twin-host.test.ts
  • src/renderer/src/store/slices/worktrees/metadata/hosted-review-link-mutation.ts
  • src/renderer/src/store/slices/worktrees/metadata/worktree-copy-review-clear.ts
  • src/renderer/src/store/slices/worktrees/metadata/worktree-git-identity-update.ts
Files skipped from review as they are similar to previous changes: 2
  • src/renderer/src/store/slices/worktrees-git-identity-twin-host.test.ts
  • src/renderer/src/store/slices/worktrees/metadata/worktree-git-identity-update.ts

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

repoId: activeRepo.id,
branch: branchName,
runtimeTarget: activeRepoTarget
runtimeTarget: copy?.transport ?? activeRepoTarget

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.

Minor · Functional Correctness · Quick win

Refuse generation when no copy resolves. Do not fall back to activeRepoTarget.

resolveWorktreeGitCopyNow returns null for an unselected same-ID twin. The git-status code and the Create PR path both refuse in that case. This code instead falls back to activeRepoTarget and getConnectionId(...).

For an ambiguous twin, getConnectionId returns undefined. The generation then runs with the repo target and no connection ID, so it can run against the local twin's checkout. The comment on Line 108 says the result must not land on a twin.

Return undefined early when activeWorktreeId is set and copy is null. Then use copy.transport and copy.connectionId without a fallback.

…me-path-hosts

# Conflicts:
#	src/renderer/src/components/right-sidebar/checks-panel/use-checks-panel-git-status-effects.tsx
#	src/renderer/src/components/right-sidebar/checks-panel/use-checks-panel-manual-refresh.tsx
#	src/renderer/src/components/right-sidebar/git-status-refresh.ts
#	src/renderer/src/components/right-sidebar/source-control/review/use-create-pr-intent-run.ts
#	src/renderer/src/components/right-sidebar/source-control/review/use-create-pr-intent-target.ts
#	src/renderer/src/components/right-sidebar/source-control/sync/use-status-refresh.ts
@nwparker
nwparker merged commit e03786f into main Oct 25, 2026
34 checks passed
audichuang added a commit to audichuang/orca that referenced this pull request Oct 26, 2026
Upstream stablyai#33428 makes refreshGitStatusForWorktree require ownerHostId so a
same-path twin on another host never gets this copy's transport. Resolve the
copy once, as useGitStatusPolling does, and pass its host, connection and
transport; the test pins that all three reach the refresh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
audichuang added a commit to audichuang/orca that referenced this pull request Oct 27, 2026
Upstream stablyai#33428 makes refreshGitStatusForWorktree require ownerHostId so a
same-path twin on another host never gets this copy's transport. Resolve the
copy once, as useGitStatusPolling does, and pass its host, connection and
transport; the test pins that all three reach the refresh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
audichuang added a commit to audichuang/orca that referenced this pull request Oct 28, 2026
Upstream stablyai#33428 makes refreshGitStatusForWorktree require ownerHostId so a
same-path twin on another host never gets this copy's transport. Resolve the
copy once, as useGitStatusPolling does, and pass its host, connection and
transport; the test pins that all three reach the refresh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
audichuang added a commit to audichuang/orca that referenced this pull request Oct 29, 2026
Upstream stablyai#33428 makes refreshGitStatusForWorktree require ownerHostId so a
same-path twin on another host never gets this copy's transport. Resolve the
copy once, as useGitStatusPolling does, and pass its host, connection and
transport; the test pins that all three reach the refresh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
audichuang added a commit to audichuang/orca that referenced this pull request Oct 30, 2026
Upstream stablyai#33428 makes refreshGitStatusForWorktree require ownerHostId so a
same-path twin on another host never gets this copy's transport. Resolve the
copy once, as useGitStatusPolling does, and pass its host, connection and
transport; the test pins that all three reach the refresh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
audichuang added a commit to audichuang/orca that referenced this pull request Nov 2, 2026
Upstream stablyai#33428 makes refreshGitStatusForWorktree require ownerHostId so a
same-path twin on another host never gets this copy's transport. Resolve the
copy once, as useGitStatusPolling does, and pass its host, connection and
transport; the test pins that all three reach the refresh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
audichuang added a commit to audichuang/orca that referenced this pull request Nov 3, 2026
Upstream stablyai#33428 makes refreshGitStatusForWorktree require ownerHostId so a
same-path twin on another host never gets this copy's transport. Resolve the
copy once, as useGitStatusPolling does, and pass its host, connection and
transport; the test pins that all three reach the refresh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
audichuang added a commit to audichuang/orca that referenced this pull request Nov 4, 2026
Upstream stablyai#33428 makes refreshGitStatusForWorktree require ownerHostId so a
same-path twin on another host never gets this copy's transport. Resolve the
copy once, as useGitStatusPolling does, and pass its host, connection and
transport; the test pins that all three reach the refresh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
audichuang added a commit to audichuang/orca that referenced this pull request Nov 5, 2026
Upstream stablyai#33428 makes refreshGitStatusForWorktree require ownerHostId so a
same-path twin on another host never gets this copy's transport. Resolve the
copy once, as useGitStatusPolling does, and pass its host, connection and
transport; the test pins that all three reach the refresh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
audichuang added a commit to audichuang/orca that referenced this pull request Nov 5, 2026
Upstream stablyai#33428 makes refreshGitStatusForWorktree require ownerHostId so a
same-path twin on another host never gets this copy's transport. Resolve the
copy once, as useGitStatusPolling does, and pass its host, connection and
transport; the test pins that all three reach the refresh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
audichuang added a commit to audichuang/orca that referenced this pull request Nov 6, 2026
Upstream stablyai#33428 makes refreshGitStatusForWorktree require ownerHostId so a
same-path twin on another host never gets this copy's transport. Resolve the
copy once, as useGitStatusPolling does, and pass its host, connection and
transport; the test pins that all three reach the refresh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
audichuang added a commit to audichuang/orca that referenced this pull request Nov 7, 2026
Upstream stablyai#33428 makes refreshGitStatusForWorktree require ownerHostId so a
same-path twin on another host never gets this copy's transport. Resolve the
copy once, as useGitStatusPolling does, and pass its host, connection and
transport; the test pins that all three reach the refresh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
audichuang added a commit to audichuang/orca that referenced this pull request Nov 8, 2026
Upstream stablyai#33428 makes refreshGitStatusForWorktree require ownerHostId so a
same-path twin on another host never gets this copy's transport. Resolve the
copy once, as useGitStatusPolling does, and pass its host, connection and
transport; the test pins that all three reach the refresh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
audichuang added a commit to audichuang/orca that referenced this pull request Nov 8, 2026
Upstream stablyai#33428 makes refreshGitStatusForWorktree require ownerHostId so a
same-path twin on another host never gets this copy's transport. Resolve the
copy once, as useGitStatusPolling does, and pass its host, connection and
transport; the test pins that all three reach the refresh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

1 participant