ctx.onRowPointerDown(event, folderWorktree, folderWorktree.id)}
+ onPointerDown={(event) => ctx.onRowPointerDown(event, folderWorktree, folderWorktreeIdentity)}
>
ctx.onSelectionGesture(event, folderWorktree)}
onContextMenuSelect={ctx.onContextMenuSelect}
statusPrDisplay={folderPrDisplay}
diff --git a/src/renderer/src/components/sidebar/worktree-list/viewport/virtual-row-context.ts b/src/renderer/src/components/sidebar/worktree-list/viewport/virtual-row-context.ts
index 5def1862ec1..5219db4cfa2 100644
--- a/src/renderer/src/components/sidebar/worktree-list/viewport/virtual-row-context.ts
+++ b/src/renderer/src/components/sidebar/worktree-list/viewport/virtual-row-context.ts
@@ -140,6 +140,7 @@ export function buildWorktreeVirtualRowContext(args: BuildArgs): WorktreeVirtual
newCardStyle: args.newCardStyle,
settings: args.settings,
activeWorktreeId: props.activeWorktreeId,
+ activeWorkspaceExecutionHostId: props.activeWorkspaceExecutionHostId,
currentWorktreeId: props.currentWorktreeId,
selectedWorktreeIds: props.selectedWorktreeIds,
repoMap: props.repoMap,
diff --git a/src/shared/folder-workspace-worktree.test.ts b/src/shared/folder-workspace-worktree.test.ts
index 70e64e0e342..023db6c2ea6 100644
--- a/src/shared/folder-workspace-worktree.test.ts
+++ b/src/shared/folder-workspace-worktree.test.ts
@@ -4,6 +4,7 @@ import type { WorkspaceAttachment } from './worktree/types'
import { getWorkspaceAttachments } from './workspace-attachments'
import {
folderWorkspaceRepoId,
+ getFolderWorkspaceHostIdentity,
folderWorkspaceToWorktree,
projectGroupIdFromRepoId
} from './folder-workspace-worktree'
@@ -30,6 +31,22 @@ function makeFolderWorkspace(overrides: Partial = {}): FolderWo
}
describe('folderWorkspaceToWorktree', () => {
+ it.each([
+ [{}, 'local|folder:folder-workspace-1'],
+ [{ connectionId: 'ssh host' }, 'ssh:ssh%20host|folder:folder-workspace-1'],
+ [
+ { executionHostId: 'runtime:host' as const, connectionId: 'ignored' },
+ 'runtime:host|folder:folder-workspace-1'
+ ],
+ [
+ { executionHostId: 'local' as const, connectionId: 'ignored' },
+ 'local|folder:folder-workspace-1'
+ ]
+ ])('keeps folder row identity on its explicit or legacy host %j', (fields, identity) => {
+ const workspace = makeFolderWorkspace(fields)
+ expect(getFolderWorkspaceHostIdentity(workspace)).toBe(identity)
+ expect(folderWorkspaceToWorktree(workspace).hostId).toBe(identity.split('|')[0])
+ })
it('preserves multiple attachments and projects a bare Linear task without enabling review checks', () => {
const linkedItems: WorkspaceAttachment[] = [
{ provider: 'github', type: 'pr', number: 7 },
diff --git a/src/shared/folder-workspace-worktree.ts b/src/shared/folder-workspace-worktree.ts
index 38b6e18d1fe..903f4f9b92a 100644
--- a/src/shared/folder-workspace-worktree.ts
+++ b/src/shared/folder-workspace-worktree.ts
@@ -1,7 +1,8 @@
import type { FolderWorkspace } from './folder-workspace-types'
import type { Worktree } from './worktree/types'
import { folderWorkspaceKey } from './workspace-scope'
-import { parseExecutionHostId, toSshExecutionHostId } from './execution-host'
+import { parseExecutionHostId, toSshExecutionHostId, type ExecutionHostId } from './execution-host'
+import { composeWorktreeHostIdentity } from './worktree/host-qualified-identity'
import { normalizeWorkspaceCreatorProvenance } from './workspace-creator-provenance'
import { getWorkspaceAttachments } from './workspace-attachments'
import { normalizeWorkspaceAttachment } from './workspace-attachment-normalization'
@@ -28,6 +29,24 @@ export function projectGroupIdFromRepoId(repoId: string | null | undefined): str
return projectGroupId === '' ? null : projectGroupId
}
+function getFolderWorkspaceWorktreeHostId(
+ workspace: Pick
+): ExecutionHostId {
+ return (
+ workspace.executionHostId ??
+ (workspace.connectionId ? toSshExecutionHostId(workspace.connectionId) : 'local')
+ )
+}
+
+export function getFolderWorkspaceHostIdentity(
+ workspace: Pick
+): string {
+ return composeWorktreeHostIdentity(
+ getFolderWorkspaceWorktreeHostId(workspace),
+ folderWorkspaceKey(workspace.id)
+ )
+}
+
export function folderWorkspaceToWorktree(folderWorkspace: FolderWorkspace): Worktree {
const linkedTask = folderWorkspace.linkedTask
const selectedTask = linkedTask
@@ -36,9 +55,7 @@ export function folderWorkspaceToWorktree(folderWorkspace: FolderWorkspace): Wor
linkedItems: folderWorkspace.linkedItems
}).find((item) => item.type === 'issue')
const creatorProvenance = normalizeWorkspaceCreatorProvenance(folderWorkspace.creatorProvenance)
- const hostId =
- folderWorkspace.executionHostId ??
- (folderWorkspace.connectionId ? toSshExecutionHostId(folderWorkspace.connectionId) : 'local')
+ const hostId = getFolderWorkspaceWorktreeHostId(folderWorkspace)
const parsedHost = parseExecutionHostId(hostId)
return {
id: folderWorkspaceKey(folderWorkspace.id),