refactor: group workspace cleanup and space diagnostics (#37558)

* refactor: organize workspace diagnostics and cleanup owners

* test: target concrete cleanup and cancellation owners
This commit is contained in:
Neil
2026-11-02 14:16:06 -08:00
committed by GitHub
parent 5e02b47d11
commit c563f68df9
85 changed files with 342 additions and 334 deletions
@@ -39,7 +39,9 @@ export const MAIN_BUILD_ENTRY_POINTS: Record<string, string> = {
),
// Usage scans synchronously walk histories/SQLite; keep them off the main loop.
'usage-scan-worker-entry': resolve('src/main/usage/usage-scan-worker-entry.ts'),
'workspace-space-scan-worker-entry': resolve('src/main/workspace-space-scan-worker-entry.ts'),
'workspace-space-scan-worker-entry': resolve(
'src/main/workspaces/space-analysis/workspace-space-scan-worker-entry.ts'
),
// Why: a first account setup can merge a large history tree with sync fs calls.
'claude-profile-setup-worker-entry': resolve(
'src/main/claude-accounts/claude-profile-setup-worker-entry.ts'
+1 -1
View File
@@ -326,7 +326,7 @@
1 test-no-real-time-wait:src/main/ipc/rebinding-file-watch.test.ts
3 test-no-real-time-wait:src/main/ipc/runtime-environments/runtime-environment-preference.test.ts
5 test-no-real-time-wait:src/main/ipc/runtime-environments/runtime-environment-request-connections.test.ts
2 test-no-real-time-wait:src/main/ipc/workspace-cleanup-snapshot-ipc.test.ts
2 test-no-real-time-wait:src/main/ipc/workspace-cleanup/workspace-cleanup-snapshot-ipc.test.ts
1 test-no-real-time-wait:src/main/ipc/worktree-base-directory-poller-marker-fanout.test.ts
14 test-no-real-time-wait:src/main/ipc/worktree-base-directory-poller.test.ts
6 test-no-real-time-wait:src/main/ipc/worktree-git-common-polling.test.ts
+1 -1
View File
@@ -42,7 +42,7 @@
"src/main/ai-vault/session-scanner-service-entry.ts",
"src/main/native-chat/wsl-transcript-fs-process-entry.ts",
"src/main/usage/usage-scan-worker-entry.ts",
"src/main/workspace-space-scan-worker-entry.ts",
"src/main/workspaces/space-analysis/workspace-space-scan-worker-entry.ts",
"src/main/claude-accounts/claude-profile-setup-worker-entry.ts",
"src/main/persistence/profile-state/profile-state-backup-worker-entry.ts",
"src/main/persistence/profile-state/profile-state-writer-worker-entry.ts",
+3 -3
View File
@@ -15,8 +15,8 @@
1 src/main/ipc/registered-worktree-root-owner.ts
4 src/main/ipc/repos/local-repo-registration.ts
1 src/main/ipc/repos/nested-repo-import-handler.ts
2 src/main/ipc/workspace-cleanup-candidate.ts
1 src/main/ipc/workspace-cleanup-disconnected-ssh.ts
2 src/main/ipc/workspace-cleanup/workspace-cleanup-candidate.ts
1 src/main/ipc/workspace-cleanup/workspace-cleanup-disconnected-ssh.ts
1 src/main/ipc/worktrees-test-metadata-pruning-store.ts
1 src/main/ipc/worktrees/listing/authoritative-local-worktree-metadata-pruning.ts
1 src/main/ipc/worktrees/listing/register-host-catalog-handlers.ts
@@ -43,7 +43,7 @@
3 src/main/runtime/runtime-reference-agents.ts
1 src/main/runtime/runtime-worktree-selection.ts
1 src/main/ssh/targets/ssh-target-orcad-claims.ts
1 src/main/workspace-space-worktree-row.ts
1 src/main/workspaces/space-analysis/workspace-space-worktree-row.ts
1 src/main/worktree-create-base-prefetch.ts
2 src/main/worktree-name-retirement.ts
1 src/shared/endpoint-catalog-adoption.ts
+15 -15
View File
@@ -3382,14 +3382,14 @@
"src/main/ipc/usage-provider-handlers-readiness.test.ts": 506,
"src/main/ipc/watcher-event-root-path-rewrite.test.ts": 48,
"src/main/ipc/watcher-removal-gate.test.ts": 384,
"src/main/ipc/workspace-cleanup-activity.test.ts": 76,
"src/main/ipc/workspace-cleanup-broad-scan.test.ts": 785,
"src/main/ipc/workspace-cleanup-document-lifetime.test.ts": 1130,
"src/main/ipc/workspace-cleanup-execution-host-routing.test.ts": 641,
"src/main/ipc/workspace-cleanup-snapshot-ipc.test.ts": 102,
"src/main/ipc/workspace-cleanup.test.ts": 2580,
"src/main/ipc/workspace-cleanup/workspace-cleanup-activity.test.ts": 76,
"src/main/ipc/workspace-cleanup/workspace-cleanup-broad-scan.test.ts": 785,
"src/main/ipc/workspace-cleanup/workspace-cleanup-document-lifetime.test.ts": 1130,
"src/main/ipc/workspace-cleanup/workspace-cleanup-execution-host-routing.test.ts": 641,
"src/main/ipc/workspace-cleanup/workspace-cleanup-snapshot-ipc.test.ts": 102,
"src/main/ipc/workspace-cleanup/workspace-cleanup.test.ts": 2580,
"src/main/ipc/workspace-ports.test.ts": 101,
"src/main/ipc/workspace-space.test.ts": 60,
"src/main/ipc/workspace-space/workspace-space.test.ts": 60,
"src/main/ipc/worktree-base-directory-event-filter.test.ts": 58,
"src/main/ipc/worktree-base-directory-notifications.test.ts": 65,
"src/main/ipc/worktree-base-directory-poller-marker-fanout.test.ts": 193,
@@ -3576,7 +3576,7 @@
"src/main/local-worktree-path-presence.test.ts": 52,
"src/main/local-worktree-removal-recovery-live.test.ts": 465,
"src/main/local-worktree-removal-recovery.test.ts": 351,
"src/main/localhost-worktree-label-proxy.test.ts": 120,
"src/main/ports/workspace-labels/localhost-worktree-label-proxy.test.ts": 120,
"src/main/macos-full-disk-access-status.test.ts": 42,
"src/main/macos-press-and-hold-default.defaults-domain.test.ts": 76,
"src/main/macos-press-and-hold-default.test.ts": 109,
@@ -7082,14 +7082,14 @@
"src/main/worker-thread-child-process/worker-thread-child-output-flow.test.ts": 158,
"src/main/worker-thread-child-process/worker-thread-child-process.test.ts": 602,
"src/main/worker-thread-request-queue.test.ts": 83,
"src/main/workspace-cleanup-removal-snapshot-prune.test.ts": 60,
"src/main/workspace-cleanup-scan-snapshot.test.ts": 160,
"src/main/workspaces/cleanup/workspace-cleanup-removal-snapshot-prune.test.ts": 60,
"src/main/workspaces/cleanup/workspace-cleanup-scan-snapshot.test.ts": 160,
"src/main/workspace-create-event-fields.test.ts": 265,
"src/main/workspace-space-analysis-capacity.test.ts": 711,
"src/main/workspace-space-analysis-du-timeout.test.ts": 899,
"src/main/workspace-space-analysis-snapshot.test.ts": 151,
"src/main/workspace-space-analysis.test.ts": 592,
"src/main/workspace-space-scan-control.test.ts": 56,
"src/main/workspaces/space-analysis/workspace-space-analysis-capacity.test.ts": 711,
"src/main/workspaces/space-analysis/workspace-space-analysis-du-timeout.test.ts": 899,
"src/main/workspaces/space-analysis/workspace-space-analysis-snapshot.test.ts": 151,
"src/main/workspaces/space-analysis/workspace-space-analysis.test.ts": 592,
"src/main/workspaces/space-analysis/workspace-space-scan-control.test.ts": 56,
"src/main/worktree-background-removal-records.test.ts": 575,
"src/main/worktree-background-removal.test.ts": 400,
"src/main/worktree-create-base-prefetch.test.ts": 284,
+2 -2
View File
@@ -1,7 +1,7 @@
# Hand-built worktree ids (`${repoId}::${path}`) per file, outside src/shared/worktree/id.ts.
# This is a RATCHET: counts may only go DOWN. Compose ids with composeWorktreeId or
# getRepoMainWorktreeId instead. Prune after a fix: pnpm check:worktree-id-composer-ratchet --prune
1 src/main/ipc/workspace-cleanup-scan.ts
1 src/main/ipc/workspace-cleanup/workspace-cleanup-scan.ts
1 src/main/ipc/worktree-folder-rename-target.ts
1 src/main/ipc/worktree-metadata-merge.ts
1 src/main/ipc/worktree-push-target-reconciliation.ts
@@ -14,6 +14,6 @@
1 src/main/runtime/runtime-local-worktree-materialization.ts
1 src/main/runtime/runtime-managed-worktree-queries.ts
1 src/main/runtime/runtime-provisioned-root-adoption.ts
1 src/main/workspace-space-repo-scan.ts
1 src/main/workspaces/space-analysis/workspace-space-repo-scan.ts
1 src/main/worktree-lineage-pruning.ts
1 src/renderer/src/components/sidebar/DeleteNestedWorktreesDialog.tsx
+1 -1
View File
@@ -7,7 +7,7 @@ import {
type LocalhostWorktreeLabelRoute
} from '../../shared/localhost-worktree-labels'
import type { Store } from '../persistence/loading-store/store'
import { localhostWorktreeLabelProxy } from '../localhost-worktree-label-proxy'
import { localhostWorktreeLabelProxy } from '../ports/workspace-labels/localhost-worktree-label-proxy'
import {
getStoreWorkspacePortProbes,
scanWorkspacePortProbes
@@ -174,7 +174,7 @@ vi.mock('../dashboard-popout', () => ({
registerDashboardPopoutHandlers: registerDashboardPopoutHandlersMock
}))
vi.mock('../workspace-space-window', () => ({
vi.mock('../workspace-space/workspace-space-window', () => ({
registerWorkspaceSpaceWindowHandlers: registerWorkspaceSpaceWindowHandlersMock
}))
@@ -250,7 +250,7 @@ vi.mock('../skill-delete/handlers', () => ({
registerSkillDeleteIpcHandlers: registerSkillDeleteIpcHandlersMock
}))
vi.mock('../workspace-space', () => ({
vi.mock('../workspace-space/workspace-space', () => ({
registerWorkspaceSpaceHandlers: registerWorkspaceSpaceHandlersMock
}))
@@ -40,7 +40,7 @@ import { registerNotificationHandlers } from '../notifications'
import { registerNotebookHandlers } from '../notebook'
import { registerOnboardingHandlers } from '../onboarding'
import { registerDashboardPopoutHandlers } from '../dashboard-popout'
import { registerWorkspaceSpaceWindowHandlers } from '../workspace-space-window'
import { registerWorkspaceSpaceWindowHandlers } from '../workspace-space/workspace-space-window'
import { registerTerminalPreviewHandlers } from '../terminal-preview'
import { registerDeveloperPermissionHandlers } from '../developer-permissions'
import { registerComputerUsePermissionHandlers } from '../computer-use-permissions'
@@ -51,7 +51,7 @@ import { registerSettingsHandlers } from '../settings'
import { registerDiagnosticsHandlers } from '../diagnostics'
import { registerSkillsHandlers } from '../skills'
import { registerSkillDeleteIpcHandlers } from '../skill-delete/handlers'
import { registerWorkspaceSpaceHandlers } from '../workspace-space'
import { registerWorkspaceSpaceHandlers } from '../workspace-space/workspace-space'
import { registerWorkspacePortHandlers } from '../workspace-ports'
import { registerLinkPreviewHandlers } from '../link-preview'
import { registerLocalhostWorktreeLabelHandlers } from '../localhost-worktree-labels'
@@ -2,7 +2,7 @@ import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises'
import os from 'node:os'
import path from 'node:path'
import { describe, expect, it, vi } from 'vitest'
import type { Worktree } from '../../shared/worktree/types'
import type { Worktree } from '../../../shared/worktree/types'
import { resolveWorkspaceCleanupActivityWorktree } from './workspace-cleanup-activity'
import type { WorkspaceCleanupGitRoute } from './workspace-cleanup-git-route'
@@ -1,8 +1,8 @@
import { lstat, open, readFile } from 'node:fs/promises'
import path from 'node:path'
import type { Worktree } from '../../shared/worktree/types'
import { resolveGitMetadataPath } from '../../shared/git-metadata-path'
import { getPersistedWorkspaceCleanupActivityAt } from '../../shared/workspace-cleanup'
import type { Worktree } from '../../../shared/worktree/types'
import { resolveGitMetadataPath } from '../../../shared/git-metadata-path'
import { getPersistedWorkspaceCleanupActivityAt } from '../../../shared/workspace-cleanup'
import type { WorkspaceCleanupGitRoute } from './workspace-cleanup-git-route'
type StatPath = (targetPath: string) => Promise<{ mtimeMs: number }>
@@ -1,12 +1,12 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import path from 'node:path'
import type { Store } from '../persistence/loading-store/store'
import type * as RepoWorktreesModule from '../repo-worktrees'
import type { GitStatusResult } from '../../shared/git-status-types'
import type { Repo } from '../../shared/repo-types'
import type { GitWorktreeInfo } from '../../shared/worktree/types'
import type { WorktreeMeta } from '../../shared/worktree/meta-types'
import { WORKSPACE_CLEANUP_TARGET_BATCH_LIMIT } from '../../shared/workspace-cleanup'
import type { Store } from '../../persistence/loading-store/store'
import type * as RepoWorktreesModule from '../../repo-worktrees'
import type { GitStatusResult } from '../../../shared/git-status-types'
import type { Repo } from '../../../shared/repo-types'
import type { GitWorktreeInfo } from '../../../shared/worktree/types'
import type { WorktreeMeta } from '../../../shared/worktree/meta-types'
import { WORKSPACE_CLEANUP_TARGET_BATCH_LIMIT } from '../../../shared/workspace-cleanup'
const {
lstatMock,
@@ -29,23 +29,23 @@ vi.mock('node:fs/promises', () => ({
readFile: readFileMock
}))
vi.mock('../repo-worktrees', async () => {
const actual = await vi.importActual<typeof RepoWorktreesModule>('../repo-worktrees')
vi.mock('../../repo-worktrees', async () => {
const actual = await vi.importActual<typeof RepoWorktreesModule>('../../repo-worktrees')
return {
listRepoWorktrees: listRepoWorktreesMock,
createFolderWorktree: actual.createFolderWorktree
}
})
vi.mock('../git/status', () => ({
vi.mock('../../git/source-control/status-read', () => ({
getStatus: getStatusMock
}))
vi.mock('../git/runner', () => ({
vi.mock('../../git/command-runner/git-exec-file', () => ({
gitExecFileAsync: gitExecFileAsyncMock
}))
vi.mock('../project-runtime-git-options', () => ({
vi.mock('../../project-runtime-git-options', () => ({
getLocalProjectWorktreeGitOptions: getLocalProjectWorktreeGitOptionsMock
}))
@@ -1,7 +1,7 @@
import { isFolderRepo } from '../../shared/repo-kind'
import type { Repo } from '../../shared/repo-types'
import type { Worktree } from '../../shared/worktree/types'
import { getWorktreeExecutionHostId } from '../../shared/execution-host'
import { isFolderRepo } from '../../../shared/repo-kind'
import type { Repo } from '../../../shared/repo-types'
import type { Worktree } from '../../../shared/worktree/types'
import { getWorktreeExecutionHostId } from '../../../shared/execution-host'
import {
applyWorkspaceCleanupPolicy,
createWorkspaceCleanupFingerprint,
@@ -10,7 +10,7 @@ import {
type WorkspaceCleanupBlocker,
type WorkspaceCleanupCandidate,
type WorkspaceCleanupReason
} from '../../shared/workspace-cleanup'
} from '../../../shared/workspace-cleanup'
import {
createEmptyWorkspaceCleanupGitEvidence,
readWorkspaceCleanupGitEvidence
@@ -1,24 +1,27 @@
import { basename } from 'node:path'
import { getRepoExecutionHostId, normalizeExecutionHostId } from '../../shared/execution-host'
import type { Store } from '../persistence/loading-store/store'
import type { Repo } from '../../shared/repo-types'
import type { WorktreeMeta } from '../../shared/worktree/meta-types'
import { getRepoExecutionHostId, normalizeExecutionHostId } from '../../../shared/execution-host'
import type { Store } from '../../persistence/loading-store/store'
import type { Repo } from '../../../shared/repo-types'
import type { WorktreeMeta } from '../../../shared/worktree/meta-types'
import {
applyWorkspaceCleanupPolicy,
createWorkspaceCleanupFingerprint,
type WorkspaceCleanupCandidate
} from '../../shared/workspace-cleanup'
import { splitWorktreeIdForFilesystem } from '../../shared/worktree/id'
} from '../../../shared/workspace-cleanup'
import { splitWorktreeIdForFilesystem } from '../../../shared/worktree/id'
import {
getNewestWorkspaceCleanupDiffCommentAt,
getWorkspaceCleanupInactivityReasonsForWorkspace,
isWorkspaceInactiveForCleanup
} from './workspace-cleanup-candidate'
import { getRepoOwnedWorktreeMeta, isWorktreeMetaOwnedByRepo } from '../worktree-metadata-ownership'
import {
getRepoOwnedWorktreeMeta,
isWorktreeMetaOwnedByRepo
} from '../../worktree-metadata-ownership'
import {
readAllWorktreeMetaForHost,
readWorktreeMetaForHost
} from '../persistence/host-qualified-worktree-meta'
} from '../../persistence/host-qualified-worktree-meta'
export function synthesizeDisconnectedSshCleanupCandidates(
store: Store,
@@ -1,8 +1,8 @@
import { EventEmitter } from 'node:events'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import type { GitStatusResult } from '../../shared/git-status-types'
import type { GitWorktreeInfo } from '../../shared/worktree/types'
import type * as RepoWorktrees from '../repo-worktrees'
import type { GitStatusResult } from '../../../shared/git-status-types'
import type { GitWorktreeInfo } from '../../../shared/worktree/types'
import type * as RepoWorktrees from '../../repo-worktrees'
const boundary = vi.hoisted(() => ({
handlers: new Map<string, (event: unknown, args: unknown) => unknown>(),
@@ -23,20 +23,22 @@ vi.mock('node:fs/promises', () => ({
throw new Error('no gitdir pointer')
})
}))
vi.mock('../repo-worktrees', async (importOriginal) => ({
vi.mock('../../repo-worktrees', async (importOriginal) => ({
...(await importOriginal<typeof RepoWorktrees>()),
listRepoWorktrees: boundary.list
}))
vi.mock('../git/status', () => ({ getStatus: boundary.status }))
vi.mock('../git/runner', () => ({
vi.mock('../../git/source-control/status-read', () => ({ getStatus: boundary.status }))
vi.mock('../../git/command-runner/git-exec-file', () => ({
gitExecFileAsync: vi.fn(async () => ({ stdout: '0\n', stderr: '' }))
}))
vi.mock('../project-runtime-git-options', () => ({ getLocalProjectWorktreeGitOptions: () => ({}) }))
vi.mock('../workspace-cleanup-scan-snapshot', () => ({
vi.mock('../../project-runtime-git-options', () => ({
getLocalProjectWorktreeGitOptions: () => ({})
}))
vi.mock('../../workspaces/cleanup/workspace-cleanup-scan-snapshot', () => ({
persistWorkspaceCleanupScanResult: boundary.persist,
readWorkspaceCleanupScanSnapshot: vi.fn()
}))
vi.mock('../workspace-cleanup-removal-snapshot-prune', () => ({
vi.mock('../../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', () => ({
beginWorkspaceCleanupRemovalSnapshotPruneBatch: vi.fn(),
finishWorkspaceCleanupRemovalSnapshotPruneBatch: vi.fn(),
recordWorkspaceCleanupRemovalSnapshotPrune: vi.fn()
@@ -1,8 +1,8 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import type { Store } from '../persistence/loading-store/store'
import type { GitStatusResult } from '../../shared/git-status-types'
import type { Repo } from '../../shared/repo-types'
import type { WorktreeMeta } from '../../shared/worktree/meta-types'
import type { Store } from '../../persistence/loading-store/store'
import type { GitStatusResult } from '../../../shared/git-status-types'
import type { Repo } from '../../../shared/repo-types'
import type { WorktreeMeta } from '../../../shared/worktree/meta-types'
const {
lstatMock,
@@ -28,15 +28,17 @@ vi.mock('node:fs/promises', () => ({
open: openMock
}))
vi.mock('../repo-worktrees', () => ({
vi.mock('../../repo-worktrees', () => ({
listRepoWorktrees: listRepoWorktreesMock,
createFolderWorktree: vi.fn()
}))
vi.mock('../git/status', () => ({ getStatus: getStatusMock }))
vi.mock('../git/runner', () => ({ gitExecFileAsync: gitExecFileAsyncMock }))
vi.mock('../../git/source-control/status-read', () => ({ getStatus: getStatusMock }))
vi.mock('../../git/command-runner/git-exec-file', () => ({
gitExecFileAsync: gitExecFileAsyncMock
}))
vi.mock('../project-runtime-git-options', () => ({
vi.mock('../../project-runtime-git-options', () => ({
getLocalProjectWorktreeGitOptions: getLocalProjectWorktreeGitOptionsMock
}))
@@ -1,14 +1,14 @@
import type { Store } from '../persistence/loading-store/store'
import { createFolderWorktree } from '../repo-worktrees'
import type { Repo } from '../../shared/repo-types'
import type { Worktree } from '../../shared/worktree/types'
import type { WorktreeMeta } from '../../shared/worktree/meta-types'
import type { Store } from '../../persistence/loading-store/store'
import { createFolderWorktree } from '../../repo-worktrees'
import type { Repo } from '../../../shared/repo-types'
import type { Worktree } from '../../../shared/worktree/types'
import type { WorktreeMeta } from '../../../shared/worktree/meta-types'
import {
FOLDER_WORKSPACE_INSTANCE_SEPARATOR,
getRepoMainWorktreeId
} from '../../shared/worktree/id'
import { mergeWorktree } from './worktree-metadata-merge'
import { getRepoOwnedWorktreeMeta } from '../worktree-metadata-ownership'
} from '../../../shared/worktree/id'
import { mergeWorktree } from '../worktree-metadata-merge'
import { getRepoOwnedWorktreeMeta } from '../../worktree-metadata-ownership'
export function listWorkspaceCleanupFolderWorkspaces(
store: Store,
@@ -1,15 +1,15 @@
import { getStatus } from '../git/status'
import { gitExecFileAsync } from '../git/runner'
import type { GitStatusResult } from '../../shared/git-status-types'
import type { Repo } from '../../shared/repo-types'
import type { Worktree } from '../../shared/worktree/types'
import type { WorkspaceCleanupBlocker } from '../../shared/workspace-cleanup'
import { getStatus } from '../../git/source-control/status-read'
import { gitExecFileAsync } from '../../git/command-runner/git-exec-file'
import type { GitStatusResult } from '../../../shared/git-status-types'
import type { Repo } from '../../../shared/repo-types'
import type { Worktree } from '../../../shared/worktree/types'
import type { WorkspaceCleanupBlocker } from '../../../shared/workspace-cleanup'
import {
WORKSPACE_CLEANUP_GIT_READ_TIMEOUT_MS,
WorkspaceCleanupScanCancelledError,
withWorkspaceCleanupTimeout
} from './workspace-cleanup-scan-primitives'
import { getWorktreeSharedLinkPaths } from '../git/worktree-shared-directories'
import { getWorktreeSharedLinkPaths } from '../../git/worktree-shared-directories'
import {
resolveWorkspaceCleanupWorktreeGitRoute,
type WorkspaceCleanupGitRoute
@@ -6,13 +6,13 @@ import {
getWorktreeExecutionHostId,
LOCAL_EXECUTION_HOST_ID,
type ExecutionHostId
} from '../../shared/execution-host'
import type { Repo } from '../../shared/repo-types'
import type { Worktree } from '../../shared/worktree/types'
} from '../../../shared/execution-host'
import type { Repo } from '../../../shared/repo-types'
import type { Worktree } from '../../../shared/worktree/types'
import {
ExecutionHostNotDispatchableError,
resolveGitRouteForHost
} from '../providers/execution-host-provider-dispatch'
} from '../../providers/execution-host-provider-dispatch'
export type WorkspaceCleanupGitRoute =
| { kind: 'local'; hostId: typeof LOCAL_EXECUTION_HOST_ID }
@@ -2,7 +2,7 @@ import type {
WorkspaceCleanupCandidate,
WorkspaceCleanupScanError,
WorkspaceCleanupScanProgress
} from '../../shared/workspace-cleanup'
} from '../../../shared/workspace-cleanup'
import { appendWorkspaceCleanupItems } from './workspace-cleanup-scan-primitives'
const WORKSPACE_CLEANUP_PROGRESS_EMIT_INTERVAL_MS = 100
@@ -1,5 +1,5 @@
import type { Worktree } from '../../shared/worktree/types'
import { getPersistedWorkspaceCleanupActivityAt } from '../../shared/workspace-cleanup'
import type { Worktree } from '../../../shared/worktree/types'
import { getPersistedWorkspaceCleanupActivityAt } from '../../../shared/workspace-cleanup'
import { isWorkspaceInactiveForCleanup } from './workspace-cleanup-candidate'
/** Preserve suggestion-only broad scans for older clients; full-list coverage requires explicit opt-in. */
@@ -1,7 +1,7 @@
import { basename } from 'node:path'
import { getRepoExecutionHostId } from '../../shared/execution-host'
import type { Repo } from '../../shared/repo-types'
import type { WorkspaceCleanupScanError } from '../../shared/workspace-cleanup'
import { getRepoExecutionHostId } from '../../../shared/execution-host'
import type { Repo } from '../../../shared/repo-types'
import type { WorkspaceCleanupScanError } from '../../../shared/workspace-cleanup'
export const WORKSPACE_CLEANUP_GIT_READ_TIMEOUT_MS = 8_000
@@ -1,8 +1,8 @@
import { splitWorktreeId } from '../../shared/worktree/id'
import { splitWorktreeId } from '../../../shared/worktree/id'
import {
WORKSPACE_CLEANUP_TARGET_BATCH_LIMIT,
type WorkspaceCleanupScanArgs
} from '../../shared/workspace-cleanup'
} from '../../../shared/workspace-cleanup'
export function hasTargetedWorkspaceCleanupScan(args: WorkspaceCleanupScanArgs): boolean {
return typeof args.worktreeId === 'string' || Array.isArray(args.worktreeIds)
@@ -1,15 +1,15 @@
import type { Store } from '../persistence/loading-store/store'
import { isFolderRepo } from '../../shared/repo-kind'
import { readWorktreeMetaForHost } from '../persistence/host-qualified-worktree-meta'
import type { Repo } from '../../shared/repo-types'
import type { GitWorktreeInfo, Worktree } from '../../shared/worktree/types'
import { mergeWorktree } from './worktree-metadata-merge'
import type { Store } from '../../persistence/loading-store/store'
import { isFolderRepo } from '../../../shared/repo-kind'
import { readWorktreeMetaForHost } from '../../persistence/host-qualified-worktree-meta'
import type { Repo } from '../../../shared/repo-types'
import type { GitWorktreeInfo, Worktree } from '../../../shared/worktree/types'
import { mergeWorktree } from '../worktree-metadata-merge'
import type {
WorkspaceCleanupCandidate,
WorkspaceCleanupScanArgs,
WorkspaceCleanupScanError,
WorkspaceCleanupScanResult
} from '../../shared/workspace-cleanup'
} from '../../../shared/workspace-cleanup'
import {
handleRepoWorktreeListError,
listCleanupGitWorktrees
@@ -44,7 +44,7 @@ import {
getTargetWorktreeIdsByRepo,
hasTargetedWorkspaceCleanupScan
} from './workspace-cleanup-scan-targets'
import { isWorktreeMetaOwnedByRepo } from '../worktree-metadata-ownership'
import { isWorktreeMetaOwnedByRepo } from '../../worktree-metadata-ownership'
const WORKTREE_SCAN_CONCURRENCY = 3
// Overlap repo scans to avoid summing SSH listing round-trip latency.
@@ -1,6 +1,6 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { ipcMain } from 'electron'
import type { Store } from '../persistence/loading-store/store'
import type { Store } from '../../persistence/loading-store/store'
const { persistScanResultMock, readScanSnapshotMock, scanWorkspaceCleanupMock } = vi.hoisted(
() => ({
@@ -23,7 +23,7 @@ vi.mock('electron', () => ({
}
}))
vi.mock('../workspace-cleanup-scan-snapshot', () => ({
vi.mock('../../workspaces/cleanup/workspace-cleanup-scan-snapshot', () => ({
persistWorkspaceCleanupScanResult: persistScanResultMock,
readWorkspaceCleanupScanSnapshot: readScanSnapshotMock
}))
@@ -32,7 +32,7 @@ vi.mock('./workspace-cleanup-scan', () => ({
scanWorkspaceCleanup: scanWorkspaceCleanupMock
}))
vi.mock('../workspace-cleanup-removal-snapshot-prune', () => ({
vi.mock('../../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', () => ({
beginWorkspaceCleanupRemovalSnapshotPruneBatch: beginPruneBatchMock,
finishWorkspaceCleanupRemovalSnapshotPruneBatch: finishPruneBatchMock,
recordWorkspaceCleanupRemovalSnapshotPrune: recordPruneMock
@@ -1,24 +1,24 @@
import type { Store } from '../persistence/loading-store/store'
import { listRepoWorktrees, createFolderWorktree } from '../repo-worktrees'
import type { Repo } from '../../shared/repo-types'
import type { GitWorktreeInfo } from '../../shared/worktree/types'
import type { Store } from '../../persistence/loading-store/store'
import { listRepoWorktrees, createFolderWorktree } from '../../repo-worktrees'
import type { Repo } from '../../../shared/repo-types'
import type { GitWorktreeInfo } from '../../../shared/worktree/types'
import type {
WorkspaceCleanupScanError,
WorkspaceCleanupScanResult
} from '../../shared/workspace-cleanup'
} from '../../../shared/workspace-cleanup'
import {
WORKSPACE_CLEANUP_GIT_READ_TIMEOUT_MS,
createWorkspaceCleanupScanError,
toSafeWorkspaceCleanupRepoScanError,
withWorkspaceCleanupTimeout
} from './workspace-cleanup-scan-primitives'
import { ExecutionHostNotDispatchableError } from '../providers/execution-host-provider-dispatch'
import { ExecutionHostNotDispatchableError } from '../../providers/execution-host-provider-dispatch'
import {
isRemoteWorkspaceCleanupHost,
resolveWorkspaceCleanupRepoGitRoute,
type WorkspaceCleanupGitRoute
} from './workspace-cleanup-git-route'
import { getLocalProjectWorktreeGitOptions } from '../project-runtime-git-options'
import { getLocalProjectWorktreeGitOptions } from '../../project-runtime-git-options'
export async function listCleanupGitWorktrees(
store: Store,
@@ -1,13 +1,13 @@
import path from 'node:path'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { ipcMain } from 'electron'
import type { Store } from '../persistence/loading-store/store'
import type { DiffComment } from '../../shared/diff-comment-types'
import type { GitStatusResult } from '../../shared/git-status-types'
import type { Repo } from '../../shared/repo-types'
import type { WorktreeMeta } from '../../shared/worktree/meta-types'
import type { GitWorktreeInfo } from '../../shared/worktree/types'
import type { WorkspaceCleanupScanProgress } from '../../shared/workspace-cleanup'
import type { Store } from '../../persistence/loading-store/store'
import type { DiffComment } from '../../../shared/diff-comment-types'
import type { GitStatusResult } from '../../../shared/git-status-types'
import type { Repo } from '../../../shared/repo-types'
import type { WorktreeMeta } from '../../../shared/worktree/meta-types'
import type { GitWorktreeInfo } from '../../../shared/worktree/types'
import type { WorkspaceCleanupScanProgress } from '../../../shared/workspace-cleanup'
const {
lstatMock,
@@ -39,34 +39,34 @@ vi.mock('electron', () => ({
}
}))
vi.mock('../repo-worktrees', () => ({
vi.mock('../../repo-worktrees', () => ({
listRepoWorktrees: listRepoWorktreesMock,
createFolderWorktree: vi.fn()
}))
vi.mock('../git/status', () => ({
vi.mock('../../git/source-control/status-read', () => ({
getStatus: getStatusMock
}))
vi.mock('../git/runner', () => ({
vi.mock('../../git/command-runner/git-exec-file', () => ({
gitExecFileAsync: gitExecFileAsyncMock
}))
vi.mock('../project-runtime-git-options', () => ({
vi.mock('../../project-runtime-git-options', () => ({
getLocalProjectWorktreeGitOptions: getLocalProjectWorktreeGitOptionsMock
}))
vi.mock('../memory/pty-registry', () => ({
vi.mock('../../memory/pty-registry', () => ({
listRegisteredPtys: listRegisteredPtysMock
}))
// Real snapshot persistence is covered in workspace-cleanup-snapshot-ipc.test.ts.
vi.mock('../workspace-cleanup-scan-snapshot', () => ({
vi.mock('../../workspaces/cleanup/workspace-cleanup-scan-snapshot', () => ({
persistWorkspaceCleanupScanResult: vi.fn(async () => undefined),
readWorkspaceCleanupScanSnapshot: vi.fn(async () => null)
}))
import { scanWorkspaceCleanup } from './workspace-cleanup'
import { scanWorkspaceCleanup } from './workspace-cleanup-scan'
const NOW = 1_700_000_000_000
const REPO: Repo = {
@@ -1,5 +1,5 @@
import { ipcMain } from 'electron'
import type { Store } from '../persistence/loading-store/store'
import type { Store } from '../../persistence/loading-store/store'
import {
WORKSPACE_CLEANUP_CLASSIFIER_VERSION,
type WorkspaceCleanupDismissArgs,
@@ -7,23 +7,21 @@ import {
type WorkspaceCleanupScanResult,
type WorkspaceCleanupSnapshotPruneBatchArgs,
type WorkspaceCleanupSnapshotPruneRecordArgs
} from '../../shared/workspace-cleanup'
import { parseExecutionHostId } from '../../shared/execution-host'
import { getWorkspaceCleanupHostIdentity } from '../../shared/workspace-cleanup-host-identity'
} from '../../../shared/workspace-cleanup'
import { parseExecutionHostId } from '../../../shared/execution-host'
import { getWorkspaceCleanupHostIdentity } from '../../../shared/workspace-cleanup-host-identity'
import { scanWorkspaceCleanup } from './workspace-cleanup-scan'
import { abortWhenRendererGone } from './renderer-lifetime-abort'
import { abortWhenRendererGone } from '../renderer-lifetime-abort'
import { hasTargetedWorkspaceCleanupScan } from './workspace-cleanup-scan-targets'
import {
persistWorkspaceCleanupScanResult,
readWorkspaceCleanupScanSnapshot
} from '../workspace-cleanup-scan-snapshot'
} from '../../workspaces/cleanup/workspace-cleanup-scan-snapshot'
import {
beginWorkspaceCleanupRemovalSnapshotPruneBatch,
finishWorkspaceCleanupRemovalSnapshotPruneBatch,
recordWorkspaceCleanupRemovalSnapshotPrune
} from '../workspace-cleanup-removal-snapshot-prune'
export { scanWorkspaceCleanup }
} from '../../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune'
// Module scope preserves old-window scan cancellation across handler re-registration.
const activeScans = new Map<string, AbortController>()
@@ -1,15 +1,15 @@
import { BrowserWindow, ipcMain } from 'electron'
import { getTrustedUIRendererWebContents, isTrustedUIRenderer } from './ui'
import { getTrustedUIRendererWebContents, isTrustedUIRenderer } from '../ui'
import {
createOrFocusWorkspaceSpaceWindow,
getWorkspaceSpaceWindow,
isWorkspaceSpaceWindowRenderer
} from '../window/workspace-space-window'
import { safelyRevealWindow } from '../window/focus-existing-window'
import { isBackgroundLaunch } from '../window/foreground-activation-policy'
import { normalizeExecutionHostId } from '../../shared/execution-host'
import { isWorkspaceSpaceChange } from '../../shared/workspace-space-change'
import type { Store } from '../persistence/loading-store/store'
} from '../../window/workspace-space-window'
import { safelyRevealWindow } from '../../window/focus-existing-window'
import { isBackgroundLaunch } from '../../window/foreground-activation-policy'
import { normalizeExecutionHostId } from '../../../shared/execution-host'
import { isWorkspaceSpaceChange } from '../../../shared/workspace-space-change'
import type { Store } from '../../persistence/loading-store/store'
export function registerWorkspaceSpaceWindowHandlers(store: Store): void {
for (const channel of [
@@ -3,8 +3,8 @@ import type {
WorkspaceSpaceAnalysis,
WorkspaceSpaceAnalyzeResult,
WorkspaceSpaceScanProgress
} from '../../shared/workspace-space-types'
import type { Store } from '../persistence/loading-store/store'
} from '../../../shared/workspace-space-types'
import type { Store } from '../../persistence/loading-store/store'
const {
handlers,
@@ -36,12 +36,15 @@ vi.mock('electron', () => ({
}
}))
vi.mock('../workspace-space-analysis', () => ({
WorkspaceSpaceScanCancelledError: WorkspaceSpaceScanCancelledErrorMock,
vi.mock('../../workspaces/space-analysis/workspace-space-analysis', () => ({
analyzeWorkspaceSpace: analyzeWorkspaceSpaceMock
}))
vi.mock('../workspace-space-analysis-snapshot', () => ({
vi.mock('../../workspaces/space-analysis/workspace-space-scan-control', () => ({
WorkspaceSpaceScanCancelledError: WorkspaceSpaceScanCancelledErrorMock
}))
vi.mock('../../workspaces/space-analysis/workspace-space-analysis-snapshot', () => ({
persistWorkspaceSpaceAnalysisSnapshot: persistAnalysisSnapshotMock,
readWorkspaceSpaceAnalysisSnapshot: readAnalysisSnapshotMock
}))
@@ -1,19 +1,17 @@
import { ipcMain } from 'electron'
import type { Store } from '../persistence/loading-store/store'
import type { Store } from '../../persistence/loading-store/store'
import type {
WorkspaceSpaceAnalysis,
WorkspaceSpaceAnalyzeResult,
WorkspaceSpaceScanProgress,
WorkspaceSpaceWorktreeMeasurement
} from '../../shared/workspace-space-types'
import {
analyzeWorkspaceSpace,
WorkspaceSpaceScanCancelledError
} from '../workspace-space-analysis'
} from '../../../shared/workspace-space-types'
import { analyzeWorkspaceSpace } from '../../workspaces/space-analysis/workspace-space-analysis'
import { WorkspaceSpaceScanCancelledError } from '../../workspaces/space-analysis/workspace-space-scan-control'
import {
persistWorkspaceSpaceAnalysisSnapshot,
readWorkspaceSpaceAnalysisSnapshot
} from '../workspace-space-analysis-snapshot'
} from '../../workspaces/space-analysis/workspace-space-analysis-snapshot'
const PROGRESS_EMIT_INTERVAL_MS = 100
@@ -85,13 +85,13 @@ vi.mock('../terminal-history-deletion', async () =>
vi.mock('../ports/advertised-url-watcher', async () =>
(await import('./worktrees-test-module-mocks')).advertisedUrlWatcherModuleMock()
)
vi.mock('../workspace-cleanup-scan-snapshot', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-scan-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupScanSnapshotModuleMock()
)
vi.mock('../workspace-space-analysis-snapshot', async () =>
vi.mock('../workspaces/space-analysis/workspace-space-analysis-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceSpaceAnalysisSnapshotModuleMock()
)
vi.mock('../workspace-cleanup-removal-snapshot-prune', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupRemovalSnapshotPruneModuleMock()
)
vi.mock('../local-worktree-path-presence', async (importOriginal) => ({
@@ -67,13 +67,13 @@ vi.mock('../terminal-history-deletion', async () =>
vi.mock('../ports/advertised-url-watcher', async () =>
(await import('./worktrees-test-module-mocks')).advertisedUrlWatcherModuleMock()
)
vi.mock('../workspace-cleanup-scan-snapshot', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-scan-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupScanSnapshotModuleMock()
)
vi.mock('../workspace-space-analysis-snapshot', async () =>
vi.mock('../workspaces/space-analysis/workspace-space-analysis-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceSpaceAnalysisSnapshotModuleMock()
)
vi.mock('../workspace-cleanup-removal-snapshot-prune', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupRemovalSnapshotPruneModuleMock()
)
vi.mock('../runtime/worktree-teardown', async () =>
@@ -73,13 +73,13 @@ vi.mock('../terminal-history-deletion', async () =>
vi.mock('../ports/advertised-url-watcher', async () =>
(await import('./worktrees-test-module-mocks')).advertisedUrlWatcherModuleMock()
)
vi.mock('../workspace-cleanup-scan-snapshot', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-scan-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupScanSnapshotModuleMock()
)
vi.mock('../workspace-space-analysis-snapshot', async () =>
vi.mock('../workspaces/space-analysis/workspace-space-analysis-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceSpaceAnalysisSnapshotModuleMock()
)
vi.mock('../workspace-cleanup-removal-snapshot-prune', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupRemovalSnapshotPruneModuleMock()
)
vi.mock('../runtime/worktree-teardown', async () =>
@@ -73,13 +73,13 @@ vi.mock('../terminal-history-deletion', async () =>
vi.mock('../ports/advertised-url-watcher', async () =>
(await import('./worktrees-test-module-mocks')).advertisedUrlWatcherModuleMock()
)
vi.mock('../workspace-cleanup-scan-snapshot', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-scan-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupScanSnapshotModuleMock()
)
vi.mock('../workspace-space-analysis-snapshot', async () =>
vi.mock('../workspaces/space-analysis/workspace-space-analysis-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceSpaceAnalysisSnapshotModuleMock()
)
vi.mock('../workspace-cleanup-removal-snapshot-prune', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupRemovalSnapshotPruneModuleMock()
)
vi.mock('../runtime/worktree-teardown', async () =>
@@ -78,13 +78,13 @@ vi.mock('../terminal-history-deletion', async () =>
vi.mock('../ports/advertised-url-watcher', async () =>
(await import('./worktrees-test-module-mocks')).advertisedUrlWatcherModuleMock()
)
vi.mock('../workspace-cleanup-scan-snapshot', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-scan-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupScanSnapshotModuleMock()
)
vi.mock('../workspace-space-analysis-snapshot', async () =>
vi.mock('../workspaces/space-analysis/workspace-space-analysis-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceSpaceAnalysisSnapshotModuleMock()
)
vi.mock('../workspace-cleanup-removal-snapshot-prune', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupRemovalSnapshotPruneModuleMock()
)
vi.mock('../runtime/worktree-teardown', async () =>
@@ -122,13 +122,13 @@ vi.mock('../terminal-history-deletion', async () =>
vi.mock('../ports/advertised-url-watcher', async () =>
(await import('./worktrees-test-module-mocks')).advertisedUrlWatcherModuleMock()
)
vi.mock('../workspace-cleanup-scan-snapshot', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-scan-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupScanSnapshotModuleMock()
)
vi.mock('../workspace-space-analysis-snapshot', async () =>
vi.mock('../workspaces/space-analysis/workspace-space-analysis-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceSpaceAnalysisSnapshotModuleMock()
)
vi.mock('../workspace-cleanup-removal-snapshot-prune', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupRemovalSnapshotPruneModuleMock()
)
vi.mock('../runtime/worktree-teardown', async () =>
@@ -62,13 +62,13 @@ vi.mock('../terminal-history-deletion', async () =>
vi.mock('../ports/advertised-url-watcher', async () =>
(await import('./worktrees-test-module-mocks')).advertisedUrlWatcherModuleMock()
)
vi.mock('../workspace-cleanup-scan-snapshot', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-scan-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupScanSnapshotModuleMock()
)
vi.mock('../workspace-space-analysis-snapshot', async () =>
vi.mock('../workspaces/space-analysis/workspace-space-analysis-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceSpaceAnalysisSnapshotModuleMock()
)
vi.mock('../workspace-cleanup-removal-snapshot-prune', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupRemovalSnapshotPruneModuleMock()
)
vi.mock('../runtime/worktree-teardown', async () =>
@@ -72,13 +72,13 @@ vi.mock('../terminal-history-deletion', async () =>
vi.mock('../ports/advertised-url-watcher', async () =>
(await import('./worktrees-test-module-mocks')).advertisedUrlWatcherModuleMock()
)
vi.mock('../workspace-cleanup-scan-snapshot', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-scan-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupScanSnapshotModuleMock()
)
vi.mock('../workspace-space-analysis-snapshot', async () =>
vi.mock('../workspaces/space-analysis/workspace-space-analysis-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceSpaceAnalysisSnapshotModuleMock()
)
vi.mock('../workspace-cleanup-removal-snapshot-prune', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupRemovalSnapshotPruneModuleMock()
)
vi.mock('../runtime/worktree-teardown', async () =>
@@ -71,13 +71,13 @@ vi.mock('../terminal-history-deletion', async () =>
vi.mock('../ports/advertised-url-watcher', async () =>
(await import('./worktrees-test-module-mocks')).advertisedUrlWatcherModuleMock()
)
vi.mock('../workspace-cleanup-scan-snapshot', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-scan-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupScanSnapshotModuleMock()
)
vi.mock('../workspace-space-analysis-snapshot', async () =>
vi.mock('../workspaces/space-analysis/workspace-space-analysis-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceSpaceAnalysisSnapshotModuleMock()
)
vi.mock('../workspace-cleanup-removal-snapshot-prune', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupRemovalSnapshotPruneModuleMock()
)
vi.mock('../runtime/worktree-teardown', async () =>
@@ -62,13 +62,13 @@ vi.mock('../terminal-history-deletion', async () =>
vi.mock('../ports/advertised-url-watcher', async () =>
(await import('./worktrees-test-module-mocks')).advertisedUrlWatcherModuleMock()
)
vi.mock('../workspace-cleanup-scan-snapshot', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-scan-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupScanSnapshotModuleMock()
)
vi.mock('../workspace-space-analysis-snapshot', async () =>
vi.mock('../workspaces/space-analysis/workspace-space-analysis-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceSpaceAnalysisSnapshotModuleMock()
)
vi.mock('../workspace-cleanup-removal-snapshot-prune', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupRemovalSnapshotPruneModuleMock()
)
vi.mock('../runtime/worktree-teardown', async () =>
@@ -67,13 +67,13 @@ vi.mock('../terminal-history-deletion', async () =>
vi.mock('../ports/advertised-url-watcher', async () =>
(await import('./worktrees-test-module-mocks')).advertisedUrlWatcherModuleMock()
)
vi.mock('../workspace-cleanup-scan-snapshot', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-scan-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupScanSnapshotModuleMock()
)
vi.mock('../workspace-space-analysis-snapshot', async () =>
vi.mock('../workspaces/space-analysis/workspace-space-analysis-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceSpaceAnalysisSnapshotModuleMock()
)
vi.mock('../workspace-cleanup-removal-snapshot-prune', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupRemovalSnapshotPruneModuleMock()
)
vi.mock('../runtime/worktree-teardown', async () =>
@@ -83,13 +83,13 @@ vi.mock('../terminal-history-deletion', async () =>
vi.mock('../ports/advertised-url-watcher', async () =>
(await import('./worktrees-test-module-mocks')).advertisedUrlWatcherModuleMock()
)
vi.mock('../workspace-cleanup-scan-snapshot', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-scan-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupScanSnapshotModuleMock()
)
vi.mock('../workspace-space-analysis-snapshot', async () =>
vi.mock('../workspaces/space-analysis/workspace-space-analysis-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceSpaceAnalysisSnapshotModuleMock()
)
vi.mock('../workspace-cleanup-removal-snapshot-prune', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupRemovalSnapshotPruneModuleMock()
)
vi.mock('../runtime/worktree-teardown', async () =>
+3 -3
View File
@@ -77,13 +77,13 @@ vi.mock('../terminal-history-deletion', async () =>
vi.mock('../ports/advertised-url-watcher', async () =>
(await import('./worktrees-test-module-mocks')).advertisedUrlWatcherModuleMock()
)
vi.mock('../workspace-cleanup-scan-snapshot', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-scan-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupScanSnapshotModuleMock()
)
vi.mock('../workspace-space-analysis-snapshot', async () =>
vi.mock('../workspaces/space-analysis/workspace-space-analysis-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceSpaceAnalysisSnapshotModuleMock()
)
vi.mock('../workspace-cleanup-removal-snapshot-prune', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupRemovalSnapshotPruneModuleMock()
)
vi.mock('../runtime/worktree-teardown', async () =>
@@ -66,13 +66,13 @@ vi.mock('../terminal-history-deletion', async () =>
vi.mock('../ports/advertised-url-watcher', async () =>
(await import('./worktrees-test-module-mocks')).advertisedUrlWatcherModuleMock()
)
vi.mock('../workspace-cleanup-scan-snapshot', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-scan-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupScanSnapshotModuleMock()
)
vi.mock('../workspace-space-analysis-snapshot', async () =>
vi.mock('../workspaces/space-analysis/workspace-space-analysis-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceSpaceAnalysisSnapshotModuleMock()
)
vi.mock('../workspace-cleanup-removal-snapshot-prune', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupRemovalSnapshotPruneModuleMock()
)
vi.mock('../runtime/worktree-teardown', async () =>
@@ -66,13 +66,13 @@ vi.mock('../terminal-history-deletion', async () =>
vi.mock('../ports/advertised-url-watcher', async () =>
(await import('./worktrees-test-module-mocks')).advertisedUrlWatcherModuleMock()
)
vi.mock('../workspace-cleanup-scan-snapshot', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-scan-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupScanSnapshotModuleMock()
)
vi.mock('../workspace-space-analysis-snapshot', async () =>
vi.mock('../workspaces/space-analysis/workspace-space-analysis-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceSpaceAnalysisSnapshotModuleMock()
)
vi.mock('../workspace-cleanup-removal-snapshot-prune', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupRemovalSnapshotPruneModuleMock()
)
vi.mock('../runtime/worktree-teardown', async () =>
@@ -65,13 +65,13 @@ vi.mock('../terminal-history-deletion', async () =>
vi.mock('../ports/advertised-url-watcher', async () =>
(await import('./worktrees-test-module-mocks')).advertisedUrlWatcherModuleMock()
)
vi.mock('../workspace-cleanup-scan-snapshot', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-scan-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupScanSnapshotModuleMock()
)
vi.mock('../workspace-space-analysis-snapshot', async () =>
vi.mock('../workspaces/space-analysis/workspace-space-analysis-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceSpaceAnalysisSnapshotModuleMock()
)
vi.mock('../workspace-cleanup-removal-snapshot-prune', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupRemovalSnapshotPruneModuleMock()
)
vi.mock('../runtime/worktree-teardown', async () =>
@@ -70,13 +70,13 @@ vi.mock('../terminal-history-deletion', async () =>
vi.mock('../ports/advertised-url-watcher', async () =>
(await import('./worktrees-test-module-mocks')).advertisedUrlWatcherModuleMock()
)
vi.mock('../workspace-cleanup-scan-snapshot', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-scan-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupScanSnapshotModuleMock()
)
vi.mock('../workspace-space-analysis-snapshot', async () =>
vi.mock('../workspaces/space-analysis/workspace-space-analysis-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceSpaceAnalysisSnapshotModuleMock()
)
vi.mock('../workspace-cleanup-removal-snapshot-prune', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupRemovalSnapshotPruneModuleMock()
)
vi.mock('../runtime/worktree-teardown', async () =>
@@ -87,13 +87,13 @@ vi.mock('../terminal-history-deletion', async () =>
vi.mock('../ports/advertised-url-watcher', async () =>
(await import('./worktrees-test-module-mocks')).advertisedUrlWatcherModuleMock()
)
vi.mock('../workspace-cleanup-scan-snapshot', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-scan-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupScanSnapshotModuleMock()
)
vi.mock('../workspace-space-analysis-snapshot', async () =>
vi.mock('../workspaces/space-analysis/workspace-space-analysis-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceSpaceAnalysisSnapshotModuleMock()
)
vi.mock('../workspace-cleanup-removal-snapshot-prune', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupRemovalSnapshotPruneModuleMock()
)
vi.mock('../runtime/worktree-teardown', async () =>
@@ -65,13 +65,13 @@ vi.mock('../terminal-history-deletion', async () =>
vi.mock('../ports/advertised-url-watcher', async () =>
(await import('./worktrees-test-module-mocks')).advertisedUrlWatcherModuleMock()
)
vi.mock('../workspace-cleanup-scan-snapshot', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-scan-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupScanSnapshotModuleMock()
)
vi.mock('../workspace-space-analysis-snapshot', async () =>
vi.mock('../workspaces/space-analysis/workspace-space-analysis-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceSpaceAnalysisSnapshotModuleMock()
)
vi.mock('../workspace-cleanup-removal-snapshot-prune', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupRemovalSnapshotPruneModuleMock()
)
vi.mock('../runtime/worktree-teardown', async () =>
@@ -69,13 +69,13 @@ vi.mock('../terminal-history-deletion', async () =>
vi.mock('../ports/advertised-url-watcher', async () =>
(await import('./worktrees-test-module-mocks')).advertisedUrlWatcherModuleMock()
)
vi.mock('../workspace-cleanup-scan-snapshot', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-scan-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupScanSnapshotModuleMock()
)
vi.mock('../workspace-space-analysis-snapshot', async () =>
vi.mock('../workspaces/space-analysis/workspace-space-analysis-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceSpaceAnalysisSnapshotModuleMock()
)
vi.mock('../workspace-cleanup-removal-snapshot-prune', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupRemovalSnapshotPruneModuleMock()
)
vi.mock('../runtime/worktree-teardown', async () =>
@@ -73,13 +73,13 @@ vi.mock('../terminal-history-deletion', async () =>
vi.mock('../ports/advertised-url-watcher', async () =>
(await import('./worktrees-test-module-mocks')).advertisedUrlWatcherModuleMock()
)
vi.mock('../workspace-cleanup-scan-snapshot', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-scan-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupScanSnapshotModuleMock()
)
vi.mock('../workspace-space-analysis-snapshot', async () =>
vi.mock('../workspaces/space-analysis/workspace-space-analysis-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceSpaceAnalysisSnapshotModuleMock()
)
vi.mock('../workspace-cleanup-removal-snapshot-prune', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupRemovalSnapshotPruneModuleMock()
)
vi.mock('../runtime/worktree-teardown', async () =>
@@ -102,13 +102,13 @@ vi.mock('../terminal-history-deletion', async () =>
vi.mock('../ports/advertised-url-watcher', async () =>
(await import('./worktrees-test-module-mocks')).advertisedUrlWatcherModuleMock()
)
vi.mock('../workspace-cleanup-scan-snapshot', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-scan-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupScanSnapshotModuleMock()
)
vi.mock('../workspace-space-analysis-snapshot', async () =>
vi.mock('../workspaces/space-analysis/workspace-space-analysis-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceSpaceAnalysisSnapshotModuleMock()
)
vi.mock('../workspace-cleanup-removal-snapshot-prune', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupRemovalSnapshotPruneModuleMock()
)
vi.mock('../runtime/worktree-teardown', async () =>
@@ -78,13 +78,13 @@ vi.mock('../terminal-history-deletion', async () =>
vi.mock('../ports/advertised-url-watcher', async () =>
(await import('./worktrees-test-module-mocks')).advertisedUrlWatcherModuleMock()
)
vi.mock('../workspace-cleanup-scan-snapshot', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-scan-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupScanSnapshotModuleMock()
)
vi.mock('../workspace-space-analysis-snapshot', async () =>
vi.mock('../workspaces/space-analysis/workspace-space-analysis-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceSpaceAnalysisSnapshotModuleMock()
)
vi.mock('../workspace-cleanup-removal-snapshot-prune', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupRemovalSnapshotPruneModuleMock()
)
vi.mock('../runtime/worktree-teardown', async () =>
@@ -73,13 +73,13 @@ vi.mock('../terminal-history-deletion', async () =>
vi.mock('../ports/advertised-url-watcher', async () =>
(await import('./worktrees-test-module-mocks')).advertisedUrlWatcherModuleMock()
)
vi.mock('../workspace-cleanup-scan-snapshot', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-scan-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupScanSnapshotModuleMock()
)
vi.mock('../workspace-space-analysis-snapshot', async () =>
vi.mock('../workspaces/space-analysis/workspace-space-analysis-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceSpaceAnalysisSnapshotModuleMock()
)
vi.mock('../workspace-cleanup-removal-snapshot-prune', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupRemovalSnapshotPruneModuleMock()
)
vi.mock('../runtime/worktree-teardown', async () =>
@@ -70,13 +70,13 @@ vi.mock('../terminal-history-deletion', async () =>
vi.mock('../ports/advertised-url-watcher', async () =>
(await import('./worktrees-test-module-mocks')).advertisedUrlWatcherModuleMock()
)
vi.mock('../workspace-cleanup-scan-snapshot', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-scan-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupScanSnapshotModuleMock()
)
vi.mock('../workspace-space-analysis-snapshot', async () =>
vi.mock('../workspaces/space-analysis/workspace-space-analysis-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceSpaceAnalysisSnapshotModuleMock()
)
vi.mock('../workspace-cleanup-removal-snapshot-prune', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupRemovalSnapshotPruneModuleMock()
)
vi.mock('../runtime/worktree-teardown', async () =>
@@ -63,13 +63,13 @@ vi.mock('../terminal-history-deletion', async () =>
vi.mock('../ports/advertised-url-watcher', async () =>
(await import('./worktrees-test-module-mocks')).advertisedUrlWatcherModuleMock()
)
vi.mock('../workspace-cleanup-scan-snapshot', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-scan-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupScanSnapshotModuleMock()
)
vi.mock('../workspace-space-analysis-snapshot', async () =>
vi.mock('../workspaces/space-analysis/workspace-space-analysis-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceSpaceAnalysisSnapshotModuleMock()
)
vi.mock('../workspace-cleanup-removal-snapshot-prune', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupRemovalSnapshotPruneModuleMock()
)
vi.mock('../runtime/worktree-teardown', async () =>
@@ -77,13 +77,13 @@ vi.mock('../terminal-history-deletion', async () =>
vi.mock('../ports/advertised-url-watcher', async () =>
(await import('./worktrees-test-module-mocks')).advertisedUrlWatcherModuleMock()
)
vi.mock('../workspace-cleanup-scan-snapshot', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-scan-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupScanSnapshotModuleMock()
)
vi.mock('../workspace-space-analysis-snapshot', async () =>
vi.mock('../workspaces/space-analysis/workspace-space-analysis-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceSpaceAnalysisSnapshotModuleMock()
)
vi.mock('../workspace-cleanup-removal-snapshot-prune', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupRemovalSnapshotPruneModuleMock()
)
vi.mock('../runtime/worktree-teardown', async () =>
@@ -93,13 +93,13 @@ vi.mock('../terminal-history-deletion', async () =>
vi.mock('../ports/advertised-url-watcher', async () =>
(await import('./worktrees-test-module-mocks')).advertisedUrlWatcherModuleMock()
)
vi.mock('../workspace-cleanup-scan-snapshot', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-scan-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupScanSnapshotModuleMock()
)
vi.mock('../workspace-space-analysis-snapshot', async () =>
vi.mock('../workspaces/space-analysis/workspace-space-analysis-snapshot', async () =>
(await import('./worktrees-test-module-mocks')).workspaceSpaceAnalysisSnapshotModuleMock()
)
vi.mock('../workspace-cleanup-removal-snapshot-prune', async () =>
vi.mock('../workspaces/cleanup/workspace-cleanup-removal-snapshot-prune', async () =>
(await import('./worktrees-test-module-mocks')).workspaceCleanupRemovalSnapshotPruneModuleMock()
)
vi.mock('../runtime/worktree-teardown', async () =>
@@ -11,8 +11,8 @@ import { isWslUncPath } from '../../../../shared/wsl-paths'
import { agentHookServer } from '../../../agent-hooks/server'
import type { Store } from '../../../persistence/loading-store/store'
import type { NativeLocalWorktreeMetadataScanExpectation } from '../../../persistence/tracking-repos/missing-local-worktree-metadata-pruning'
import { pruneWorkspaceCleanupScanSnapshots } from '../../../workspace-cleanup-scan-snapshot'
import { pruneWorkspaceSpaceAnalysisSnapshots } from '../../../workspace-space-analysis-snapshot'
import { pruneWorkspaceCleanupScanSnapshots } from '../../../workspaces/cleanup/workspace-cleanup-scan-snapshot'
import { pruneWorkspaceSpaceAnalysisSnapshots } from '../../../workspaces/space-analysis/workspace-space-analysis-snapshot'
import { isLocalWorktreeScanGenerationCurrent } from '../../../local-worktree-scan-generation'
import { localWorktreePathsExistOrAreUnverifiable } from '../../../local-worktree-path-presence'
import { worktreeRetentionPathComparisonKey } from '../../../worktree-retention-path-comparison'
@@ -11,8 +11,8 @@ import { isFolderRepo } from '../../../../shared/repo-kind'
import { projectWorktreeLineageWithHostPeers } from '../../../worktree-lineage-host-peers'
import { getRepoIdFromWorktreeId } from '../../../../shared/worktree/id'
import { agentHookServer } from '../../../agent-hooks/server'
import { pruneWorkspaceCleanupScanSnapshots } from '../../../workspace-cleanup-scan-snapshot'
import { pruneWorkspaceSpaceAnalysisSnapshots } from '../../../workspace-space-analysis-snapshot'
import { pruneWorkspaceCleanupScanSnapshots } from '../../../workspaces/cleanup/workspace-cleanup-scan-snapshot'
import { pruneWorkspaceSpaceAnalysisSnapshots } from '../../../workspaces/space-analysis/workspace-space-analysis-snapshot'
import { findExactRepoOwner, hasConflictingStoredWorktreeOwner } from './worktree-host-ownership'
import {
buildDisconnectedDetectedWorktrees,
@@ -6,12 +6,12 @@ import { URL } from 'node:url'
import type {
LocalhostWorktreeLabelResult,
LocalhostWorktreeLabelRoute
} from '../shared/localhost-worktree-labels'
} from '../../../shared/localhost-worktree-labels'
import {
connectableLoopbackHost,
getLocalhostWorktreeHostLabel,
getLocalhostWorktreeRouteKey
} from '../shared/localhost-worktree-labels'
} from '../../../shared/localhost-worktree-labels'
type RegisteredRoute = LocalhostWorktreeLabelRoute & {
label: string
@@ -3,7 +3,7 @@ import type { Store } from '../persistence/loading-store/store'
import { cancelHistoryGc } from '../terminal-history-gc'
import type { registerSshHandlers } from '../ipc/ssh/ssh'
import type { registerDaemonManagementHandlers } from '../ipc/pty/pty-management'
import type { registerWorkspaceCleanupHandlers } from '../ipc/workspace-cleanup'
import type { registerWorkspaceCleanupHandlers } from '../ipc/workspace-cleanup/workspace-cleanup'
import type { startFolderRepoGitUpgradeWatch } from '../ipc/folder-repo-git-upgrade'
import {
createMainWindowServiceStub,
@@ -119,7 +119,7 @@ vi.mock('../ipc/ssh/ssh', () => ({ registerSshHandlers: registerSshHandlersMock
vi.mock('../ipc/pty/pty-management', () => ({
registerDaemonManagementHandlers: registerDaemonManagementHandlersMock
}))
vi.mock('../ipc/workspace-cleanup', () => ({
vi.mock('../ipc/workspace-cleanup/workspace-cleanup', () => ({
registerWorkspaceCleanupHandlers: registerWorkspaceCleanupHandlersMock
}))
vi.mock('../ipc/folder-repo-git-upgrade', () => ({
@@ -11,7 +11,7 @@ import { registerRepoHandlers } from '../ipc/repos'
import { setRepoRemoteClientNotifier } from '../ipc/repos/repos-changed-notification'
import { setWorktreeCatalogRemoteClientNotifier } from '../ipc/watched-worktree-catalog-notification'
import { registerWorktreeHandlers } from '../ipc/worktrees'
import { registerWorkspaceCleanupHandlers } from '../ipc/workspace-cleanup'
import { registerWorkspaceCleanupHandlers } from '../ipc/workspace-cleanup/workspace-cleanup'
import { registerPtyHandlers } from '../ipc/pty/register-handlers'
import type {
CodexHomePtySpawnedLifecycleArgs,
@@ -22,7 +22,7 @@ vi.mock('./workspace-cleanup-scan-snapshot', () => ({
registerWorkspaceCleanupScanSnapshotPruneTombstones: registerCleanupTombstonesMock
}))
vi.mock('./workspace-space-analysis-snapshot', () => ({
vi.mock('../space-analysis/workspace-space-analysis-snapshot', () => ({
finalizeWorkspaceSpaceAnalysisSnapshotPrunes: finalizeSpaceSnapshotsMock,
pruneWorkspaceSpaceAnalysisSnapshots: pruneSpaceSnapshotsMock,
registerWorkspaceSpaceAnalysisSnapshotPruneTombstones: registerSpaceTombstonesMock
@@ -1,7 +1,7 @@
import type {
WorkspaceCleanupSnapshotPruneBatchArgs,
WorkspaceCleanupSnapshotPruneRecordArgs
} from '../shared/workspace-cleanup'
} from '../../../shared/workspace-cleanup'
import {
finalizeWorkspaceCleanupScanSnapshotPrunes,
pruneWorkspaceCleanupScanSnapshots,
@@ -11,7 +11,7 @@ import {
finalizeWorkspaceSpaceAnalysisSnapshotPrunes,
pruneWorkspaceSpaceAnalysisSnapshots,
registerWorkspaceSpaceAnalysisSnapshotPruneTombstones
} from './workspace-space-analysis-snapshot'
} from '../space-analysis/workspace-space-analysis-snapshot'
type SnapshotPruneTarget = Omit<WorkspaceCleanupSnapshotPruneRecordArgs, 'batchId'>
@@ -5,14 +5,14 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import type {
WorkspaceCleanupCandidate,
WorkspaceCleanupScanResult
} from '../shared/workspace-cleanup'
} from '../../../shared/workspace-cleanup'
const { snapshotWriteSpy, userDataDirHolder } = vi.hoisted(() => ({
snapshotWriteSpy: vi.fn(),
userDataDirHolder: { dir: '' }
}))
vi.mock('./sidecar-snapshot-file', async (importOriginal) => {
vi.mock('../../sidecar-snapshot-file', async (importOriginal) => {
const actual = await importOriginal<Record<string, unknown>>()
const writeSidecarSnapshot = actual.writeSidecarSnapshot as (
file: string,
@@ -3,14 +3,14 @@ import {
type WorkspaceCleanupCandidate,
type WorkspaceCleanupScanArgs,
type WorkspaceCleanupScanResult
} from '../shared/workspace-cleanup'
} from '../../../shared/workspace-cleanup'
import {
readSidecarSnapshot,
sidecarSnapshotFile,
withSidecarSnapshotQueue,
writeSidecarSnapshot
} from './sidecar-snapshot-file'
import type { ExecutionHostId } from '../shared/execution-host'
} from '../../sidecar-snapshot-file'
import type { ExecutionHostId } from '../../../shared/execution-host'
import {
activeWorkspaceSnapshotPruneKeys,
registerWorkspaceSnapshotPrunesForFile,
@@ -1,4 +1,4 @@
import type { ExecutionHostId } from '../shared/execution-host'
import type { ExecutionHostId } from '../../../shared/execution-host'
export type WorkspaceSnapshotPruneTarget = {
worktreeId: string
@@ -3,9 +3,9 @@ import { tmpdir } from 'node:os'
import { join } from 'node:path'
import type * as NodeProcess from 'node:process'
import { afterEach, describe, expect, it, vi } from 'vitest'
import type { Repo } from '../shared/repo-types'
import type * as WorkspaceSpaceScanBudgetModule from '../shared/workspace-space-scan-budget'
import type { Store } from './persistence/loading-store/store'
import type { Repo } from '../../../shared/repo-types'
import type * as WorkspaceSpaceScanBudgetModule from '../../../shared/workspace-space-scan-budget'
import type { Store } from '../../persistence/loading-store/store'
const { listRepoWorktreesMock } = vi.hoisted(() => ({
listRepoWorktreesMock: vi.fn()
@@ -16,9 +16,9 @@ vi.mock('node:process', async () => {
return { ...actual, platform: 'win32' }
})
vi.mock('../shared/workspace-space-scan-budget', async () => {
vi.mock('../../../shared/workspace-space-scan-budget', async () => {
const actual = await vi.importActual<typeof WorkspaceSpaceScanBudgetModule>(
'../shared/workspace-space-scan-budget'
'../../../shared/workspace-space-scan-budget'
)
return {
...actual,
@@ -26,7 +26,7 @@ vi.mock('../shared/workspace-space-scan-budget', async () => {
}
})
vi.mock('./repo-worktrees', () => ({
vi.mock('../../repo-worktrees', () => ({
createFolderWorktree: (repo: Repo) => ({
path: repo.path,
head: '',
@@ -4,15 +4,15 @@ import { join } from 'node:path'
import { EventEmitter } from 'node:events'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import type * as NodeProcess from 'node:process'
import type { Repo } from '../shared/repo-types'
import type { Store } from './persistence/loading-store/store'
import type { Repo } from '../../../shared/repo-types'
import type { Store } from '../../persistence/loading-store/store'
const { spawnProcessMock, listRepoWorktreesMock } = vi.hoisted(() => ({
spawnProcessMock: vi.fn(),
listRepoWorktreesMock: vi.fn()
}))
vi.mock('./worker-thread-child-process/worker-thread-child-process', () => ({
vi.mock('../../worker-thread-child-process/worker-thread-child-process', () => ({
spawnProcessOnWorkerThread: spawnProcessMock
}))
@@ -21,7 +21,7 @@ vi.mock('node:process', async () => {
return { ...actual, platform: 'darwin' }
})
vi.mock('./repo-worktrees', () => ({
vi.mock('../../repo-worktrees', () => ({
createFolderWorktree: (repo: Repo) => ({
path: repo.path,
head: '',
@@ -5,14 +5,14 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import type {
WorkspaceSpaceAnalysis,
WorkspaceSpaceWorktree
} from '../shared/workspace-space-types'
} from '../../../shared/workspace-space-types'
const { snapshotWriteSpy, userDataDirHolder } = vi.hoisted(() => ({
snapshotWriteSpy: vi.fn(),
userDataDirHolder: { dir: '' }
}))
vi.mock('./sidecar-snapshot-file', async (importOriginal) => {
vi.mock('../../sidecar-snapshot-file', async (importOriginal) => {
const actual = await importOriginal<Record<string, unknown>>()
const writeSidecarSnapshot = actual.writeSidecarSnapshot as (
file: string,
@@ -1,14 +1,14 @@
import type {
WorkspaceSpaceAnalysis,
WorkspaceSpaceWorktree
} from '../shared/workspace-space-types'
} from '../../../shared/workspace-space-types'
import {
readSidecarSnapshot,
sidecarSnapshotFile,
withSidecarSnapshotQueue,
writeSidecarSnapshot
} from './sidecar-snapshot-file'
import type { ExecutionHostId } from '../shared/execution-host'
} from '../../sidecar-snapshot-file'
import type { ExecutionHostId } from '../../../shared/execution-host'
import {
activeWorkspaceSnapshotPruneKeys,
registerWorkspaceSnapshotPrunesForFile,
@@ -16,7 +16,7 @@ import {
workspaceSnapshotPruneTargetKeys,
type WorkspaceSnapshotPruneTarget,
type WorkspaceSnapshotPruneTombstone
} from './workspace-snapshot-prune-index'
} from '../cleanup/workspace-snapshot-prune-index'
const SNAPSHOT_FILE_NAME = 'orca-workspace-space-analysis.json'
const SNAPSHOT_VERSION = 2
@@ -2,8 +2,8 @@ import { mkdtemp, mkdir, rm, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import type { Repo } from '../shared/repo-types'
import type { Store } from './persistence/loading-store/store'
import type { Repo } from '../../../shared/repo-types'
import type { Store } from '../../persistence/loading-store/store'
const { listRepoWorktreesMock, getLocalProjectWorktreeGitOptionsMock, workerState } = vi.hoisted(
() => ({
@@ -13,7 +13,7 @@ const { listRepoWorktreesMock, getLocalProjectWorktreeGitOptionsMock, workerStat
})
)
vi.mock('./repo-worktrees', () => ({
vi.mock('../../repo-worktrees', () => ({
createFolderWorktree: (repo: Repo) => ({
path: repo.path,
head: '',
@@ -24,11 +24,11 @@ vi.mock('./repo-worktrees', () => ({
listRepoWorktrees: listRepoWorktreesMock
}))
vi.mock('./project-runtime-git-options', () => ({
vi.mock('../../project-runtime-git-options', () => ({
getLocalProjectWorktreeGitOptions: getLocalProjectWorktreeGitOptionsMock
}))
vi.mock('./worker-thread-child-process/worker-thread-child-process', () => ({
vi.mock('../../worker-thread-child-process/worker-thread-child-process', () => ({
spawnProcessOnWorkerThread: () => {
throw new Error('Use portable traversal in this test')
}
@@ -48,7 +48,8 @@ vi.mock('./workspace-space-scan-worker-client', async () => {
}
})
import { analyzeWorkspaceSpace, WorkspaceSpaceScanCancelledError } from './workspace-space-analysis'
import { analyzeWorkspaceSpace } from './workspace-space-analysis'
import { WorkspaceSpaceScanCancelledError } from './workspace-space-scan-control'
function createStore(repos: Repo[], worktreeHostId?: `runtime:${string}`): Store {
return {
@@ -1,10 +1,10 @@
import type { Store } from './persistence/loading-store/store'
import { spawnProcessOnWorkerThread } from './worker-thread-child-process/worker-thread-child-process'
import type { Store } from '../../persistence/loading-store/store'
import { spawnProcessOnWorkerThread } from '../../worker-thread-child-process/worker-thread-child-process'
import type {
WorkspaceSpaceAnalysis,
WorkspaceSpaceScanProgress
} from '../shared/workspace-space-types'
import { mapWithConcurrency } from '../shared/map-with-concurrency'
} from '../../../shared/workspace-space-types'
import { mapWithConcurrency } from '../../../shared/map-with-concurrency'
import {
WorkspaceSpaceScanCancelledError,
createWorkspaceSpaceScanLimiter,
@@ -22,8 +22,6 @@ const LOCAL_WORKTREE_SCAN_CONCURRENCY = 1
const DU_TIMEOUT_MS = 120_000
const DU_MAX_BUFFER_BYTES = 16 * 1024 * 1024
export { WorkspaceSpaceScanCancelledError }
async function readLocalDuDepthOne(rootPath: string, signal?: AbortSignal): Promise<string> {
return new Promise<string>((resolve, reject) => {
let settled = false
@@ -1,21 +1,19 @@
import { lstat, opendir } from 'node:fs/promises'
import { platform } from 'node:process'
import type { Dirent } from 'node:fs'
import type { Repo } from '../shared/repo-types'
import type { Worktree } from '../shared/worktree/types'
import type { WorkspaceSpaceWorktree } from '../shared/workspace-space-types'
import { compactWorkspaceSpaceItems } from '../shared/workspace-space-compaction'
import { escapeRegex } from '../shared/string-utils'
import { mapWithConcurrency } from '../shared/map-with-concurrency'
import {
scanWorkspaceSpaceEntryTree,
type WorkspaceSpaceEntryScan
} from '../shared/workspace-space-entry-traversal'
import type { Repo } from '../../../shared/repo-types'
import type { Worktree } from '../../../shared/worktree/types'
import type { WorkspaceSpaceWorktree } from '../../../shared/workspace-space-types'
import { compactWorkspaceSpaceItems } from '../../../shared/workspace-space-compaction'
import { escapeRegex } from '../../../shared/string-utils'
import { mapWithConcurrency } from '../../../shared/map-with-concurrency'
import { scanWorkspaceSpaceEntryTree } from '../../../shared/workspace-space-entry-traversal'
import type { WorkspaceSpaceEntryScan } from '../../../shared/workspace-space-directory-frame'
import {
collectWorkspaceSpaceDirectoryEntries,
createWorkspaceSpaceScanBudget,
WorkspaceSpaceScanCapacityError
} from '../shared/workspace-space-scan-budget'
} from '../../../shared/workspace-space-scan-budget'
import {
WorkspaceSpaceScanCancelledError,
classifyWorkspaceSpaceError,
@@ -1,25 +1,25 @@
import type { Store } from './persistence/loading-store/store'
import type { Store } from '../../persistence/loading-store/store'
import { platform } from 'node:process'
import { isFolderRepo } from '../shared/repo-kind'
import type { Repo } from '../shared/repo-types'
import type { GitWorktreeInfo, Worktree } from '../shared/worktree/types'
import { isFolderRepo } from '../../../shared/repo-kind'
import type { Repo } from '../../../shared/repo-types'
import type { GitWorktreeInfo, Worktree } from '../../../shared/worktree/types'
import type {
WorkspaceSpaceRepoSummary,
WorkspaceSpaceScanProgress,
WorkspaceSpaceScanStatus,
WorkspaceSpaceWorktree
} from '../shared/workspace-space-types'
import { mapWithConcurrency } from '../shared/map-with-concurrency'
import { getRepoExecutionHostId, LOCAL_EXECUTION_HOST_ID } from '../shared/execution-host'
import { readWorktreeMetaForHost } from './persistence/host-qualified-worktree-meta'
import { getRepoOwnedWorktreeMeta } from './worktree-metadata-ownership'
} from '../../../shared/workspace-space-types'
import { mapWithConcurrency } from '../../../shared/map-with-concurrency'
import { getRepoExecutionHostId, LOCAL_EXECUTION_HOST_ID } from '../../../shared/execution-host'
import { readWorktreeMetaForHost } from '../../persistence/host-qualified-worktree-meta'
import { getRepoOwnedWorktreeMeta } from '../../worktree-metadata-ownership'
import {
resolveFilesystemRouteForHost,
resolveGitRouteForHost
} from './providers/execution-host-provider-dispatch'
import { createFolderWorktree, listRepoWorktrees } from './repo-worktrees'
import { mergeWorktree } from './ipc/worktree-metadata-merge'
import { getLocalProjectWorktreeGitOptions } from './project-runtime-git-options'
} from '../../providers/execution-host-provider-dispatch'
import { createFolderWorktree, listRepoWorktrees } from '../../repo-worktrees'
import { mergeWorktree } from '../../ipc/worktree-metadata-merge'
import { getLocalProjectWorktreeGitOptions } from '../../project-runtime-git-options'
import {
WorkspaceSpaceScanCancelledError,
classifyWorkspaceSpaceError,
@@ -1,5 +1,5 @@
import type { WorkspaceSpaceScanStatus } from '../shared/workspace-space-types'
import { WorkspaceSpaceScanCapacityError } from '../shared/workspace-space-scan-budget'
import type { WorkspaceSpaceScanStatus } from '../../../shared/workspace-space-types'
import { WorkspaceSpaceScanCapacityError } from '../../../shared/workspace-space-scan-budget'
export type AsyncLimiter = <T>(task: () => Promise<T>) => Promise<T>
@@ -1,10 +1,13 @@
import { existsSync } from 'node:fs'
import { Worker } from 'node:worker_threads'
import type { Repo } from '../shared/repo-types'
import type { Worktree } from '../shared/worktree/types'
import type { WorkspaceSpaceWorktree } from '../shared/workspace-space-types'
import { WorkerThreadRequestQueue } from './worker-thread-request-queue'
import { currentWorkerEntryLayout, resolveWorkerThreadEntryPath } from './worker-thread-entry-path'
import type { Repo } from '../../../shared/repo-types'
import type { Worktree } from '../../../shared/worktree/types'
import type { WorkspaceSpaceWorktree } from '../../../shared/workspace-space-types'
import { WorkerThreadRequestQueue } from '../../worker-thread-request-queue'
import {
currentWorkerEntryLayout,
resolveWorkerThreadEntryPath
} from '../../worker-thread-entry-path'
import type {
WorkspaceSpaceScanWorkerRequest,
WorkspaceSpaceScanWorkerResponse
@@ -1,6 +1,6 @@
import type { Repo } from '../shared/repo-types'
import type { Worktree } from '../shared/worktree/types'
import type { WorkspaceSpaceWorktree } from '../shared/workspace-space-types'
import type { Repo } from '../../../shared/repo-types'
import type { Worktree } from '../../../shared/worktree/types'
import type { WorkspaceSpaceWorktree } from '../../../shared/workspace-space-types'
export type WorkspaceSpaceScanWorkerRequest = {
id: number
@@ -1,14 +1,14 @@
import { posix, win32 } from 'node:path'
import type { Repo } from '../shared/repo-types'
import type { Worktree } from '../shared/worktree/types'
import type { Repo } from '../../../shared/repo-types'
import type { Worktree } from '../../../shared/worktree/types'
import type {
WorkspaceSpaceDirectoryScanResult,
WorkspaceSpaceItem,
WorkspaceSpaceScanStatus,
WorkspaceSpaceWorktree
} from '../shared/workspace-space-types'
import type { WorkspaceSpaceEntryScan } from '../shared/workspace-space-entry-traversal'
import { getWorktreeExecutionHostId } from '../shared/execution-host'
} from '../../../shared/workspace-space-types'
import type { WorkspaceSpaceEntryScan } from '../../../shared/workspace-space-directory-frame'
import { getWorktreeExecutionHostId } from '../../../shared/execution-host'
export function basenameWorkspaceFilesystemPath(pathValue: string): string {
return looksLikeWindowsPath(pathValue) ? win32.basename(pathValue) : posix.basename(pathValue)
+4 -4
View File
@@ -1,10 +1,10 @@
import type { ExecutionHostId } from '../shared/execution-host'
import { advertisedUrlWatcher } from './ports/advertised-url-watcher'
import { localhostWorktreeLabelProxy } from './localhost-worktree-label-proxy'
import { localhostWorktreeLabelProxy } from './ports/workspace-labels/localhost-worktree-label-proxy'
import { deleteWorktreeHistoryDir } from './terminal-history-deletion'
import { recordWorkspaceCleanupRemovalSnapshotPrune } from './workspace-cleanup-removal-snapshot-prune'
import { pruneWorkspaceCleanupScanSnapshot } from './workspace-cleanup-scan-snapshot'
import { pruneWorkspaceSpaceAnalysisSnapshot } from './workspace-space-analysis-snapshot'
import { recordWorkspaceCleanupRemovalSnapshotPrune } from './workspaces/cleanup/workspace-cleanup-removal-snapshot-prune'
import { pruneWorkspaceCleanupScanSnapshot } from './workspaces/cleanup/workspace-cleanup-scan-snapshot'
import { pruneWorkspaceSpaceAnalysisSnapshot } from './workspaces/space-analysis/workspace-space-analysis-snapshot'
/** Drop host-blind process state only when no same-ID workspace survives on another host. */
export function dropRemovedWorktreeProcessState(worktreeId: string): void {