diff --git a/src/main/persistence/migrating-orcad-catalog/orcad-source-workspace-session-eligibility.ts b/src/main/persistence/migrating-orcad-catalog/orcad-source-workspace-session-eligibility.ts index 13a68c8020c..c839cf45aab 100644 --- a/src/main/persistence/migrating-orcad-catalog/orcad-source-workspace-session-eligibility.ts +++ b/src/main/persistence/migrating-orcad-catalog/orcad-source-workspace-session-eligibility.ts @@ -8,6 +8,7 @@ import type { import { orcadMigrationOwnerMatchesScope, orcadMigrationOwnsRepoId, + orcadMigrationScopeOwnsWholeHost, unqualifyOrcadMigrationOwnerKey, type OrcadMigrationSourceScope } from './orcad-source-scope' @@ -29,11 +30,13 @@ export function collectUnsupportedSessionItems( sourceTerminalTabIds: ReadonlySet ): string[] { const owns = (ownerKey: string): boolean => orcadMigrationOwnerMatchesScope(ownerKey, scope) - const matches = (ownerKey: string): boolean => - Boolean(ownerKey) && (sourceHostPartition || owns(ownerKey)) + // A WSL move takes some of host `local`'s projects; the others, and rows a past move retained, + // stay on this desktop untouched, so only the selected projects' rows can refuse it. + const wholeHost = sourceHostPartition && orcadMigrationScopeOwnsWholeHost(scope) + const matches = (ownerKey: string): boolean => Boolean(ownerKey) && (wholeHost || owns(ownerKey)) const items: string[] = [] // Another project's rows in this host's copy stay behind; only an unsaved draft there is work. - if (sourceHostPartition) { + if (wholeHost) { for (const [ownerKey, files] of Object.entries(session.openFilesByWorktree ?? {})) { if (!owns(ownerKey)) { items.push(...unsavedDraftItems(files, ownerKey)) diff --git a/src/main/persistence/moving-wsl-projects/wsl-move-manifest-export.test.ts b/src/main/persistence/moving-wsl-projects/wsl-move-manifest-export.test.ts index 3308a5f5c67..d6490619caa 100644 --- a/src/main/persistence/moving-wsl-projects/wsl-move-manifest-export.test.ts +++ b/src/main/persistence/moving-wsl-projects/wsl-move-manifest-export.test.ts @@ -234,6 +234,58 @@ describe('exportWslMoveManifest', () => { expect(exportWslMoveManifest(storeFor(state), REQUEST).blockers.length).toBeGreaterThan(0) }) + it("is not refused by another project's agent session or unsaved draft", () => { + // On awin, any agent or draft anywhere on this desktop refused every WSL move (D1b-10 run). + const state = sourceState() + const elsewhere: SleepingAgentSessionRecord = { + paneKey: 'windows-shell:missing-leaf', + tabId: 'windows-shell', + worktreeId: OTHER_WORKTREE, + agent: 'codex', + providerSession: { key: 'session_id', id: 'session-2' }, + prompt: 'Saved prompt', + state: 'done', + capturedAt: 1, + updatedAt: 1, + connectionId: null, + origin: 'quit' + } + state.workspaceSession.sleepingAgentSessionsByPaneKey = { [elsewhere.paneKey]: elsewhere } + state.workspaceSession.openFilesByWorktree = { + [OTHER_WORKTREE]: [ + { + filePath: 'C:\\code\\win\\notes.md', + relativePath: 'notes.md', + worktreeId: OTHER_WORKTREE, + language: 'markdown', + dirtyDraftContent: 'unsaved' + } + ] + } + expect(exportWslMoveManifest(storeFor(state), REQUEST).blockers).toEqual([]) + }) + + it("is not refused by a project an earlier move retained, whose agent stays here", () => { + const state = sourceState() + const retainedWorktree = 'old::\\\\wsl.localhost\\Ubuntu\\home\\me\\old' + state.repos.push(repo('old', '\\\\wsl.localhost\\Ubuntu\\home\\me\\old')) + const record: SleepingAgentSessionRecord = { + paneKey: 'old-shell:missing-leaf', + tabId: 'old-shell', + worktreeId: retainedWorktree, + agent: 'claude', + providerSession: { key: 'session_id', id: 'session-3' }, + prompt: 'Saved prompt', + state: 'done', + capturedAt: 1, + updatedAt: 1, + connectionId: null, + origin: 'quit' + } + state.workspaceSession.sleepingAgentSessionsByPaneKey = { [record.paneKey]: record } + expect(exportWslMoveManifest(storeFor(state), REQUEST).blockers).toEqual([]) + }) + it('refuses to sign a scope naming a project that is no longer here', () => { expect(() => exportWslMoveManifest(storeFor(sourceState()), { ...REQUEST, repoIds: ['app', 'gone'] })