Consolidate skill-delete files into dedicated module

Reorganize skill deletion functionality into a modular structure under
`src/main/skills/skill-delete/` with simplified file names. Remove the
redundant `skill-delete-` prefix from file names since they now live in
the dedicated directory. Update all import paths throughout the codebase
to reflect the new structure, including imports from IPC handlers and
RPC methods.
This commit is contained in:
Jinjing
2026-08-24 18:35:12 -07:00
parent 2d4600264b
commit 55a41af75a
23 changed files with 87 additions and 112 deletions
@@ -228,7 +228,7 @@ vi.mock('../skills', () => ({
registerSkillsHandlers: registerSkillsHandlersMock
}))
vi.mock('../skill-delete/skill-delete-ipc-handlers', () => ({
vi.mock('../skill-delete/handlers', () => ({
registerSkillDeleteIpcHandlers: registerSkillDeleteIpcHandlersMock
}))
@@ -39,7 +39,7 @@ import { registerSessionHandlers } from '../session'
import { registerSettingsHandlers } from '../settings'
import { registerDiagnosticsHandlers } from '../diagnostics'
import { registerSkillsHandlers } from '../skills'
import { registerSkillDeleteIpcHandlers } from '../skill-delete/skill-delete-ipc-handlers'
import { registerSkillDeleteIpcHandlers } from '../skill-delete/handlers'
import { registerWorkspaceSpaceHandlers } from '../workspace-space'
import { registerWorkspacePortHandlers } from '../workspace-ports'
import { registerLocalhostWorktreeLabelHandlers } from '../localhost-worktree-labels'
+1 -1
View File
@@ -11,7 +11,7 @@ import {
previewSkillDeleteRequest,
runSkillDeleteRequest,
type SkillDeleteRequestDependencies
} from '../../skills/skill-delete-request-service'
} from '../../skills/skill-delete/request-service'
import { resolveSkillDiscoveryTarget } from '../../skills/skill-discovery-target'
import { handleMainWindowSkillIpc } from '../skill-ipc-main-window'
+1 -1
View File
@@ -6,7 +6,7 @@ import {
previewSkillDeleteRequest,
runSkillDeleteRequest,
type SkillDeleteRequestDependencies
} from '../../../skills/skill-delete-request-service'
} from '../../../skills/skill-delete/request-service'
import { SkillDiscoveryTargetSchema } from '../../../../shared/skills'
import {
SkillInstallPreviewRequestSchema,
+6 -6
View File
@@ -1,10 +1,10 @@
import { posix as pathPosix, win32 as pathWin32 } from 'node:path'
import { skillDirectoryMaxDepth } from '../../shared/skill-discovery-depth'
import type { SkillPathSemantics } from '../../shared/skill-path-containment'
import type { SkillScanRoot } from './skill-discovery-sources'
import type { SkillInstallFilesystem, SkillPathInspection } from './skill-install-filesystem'
import { SKILL_FILE_NAME } from './skill-root-file-walk'
import { isSkillStagingEntryName } from './skill-staging-names'
import { skillDirectoryMaxDepth } from '../../../shared/skill-discovery-depth'
import type { SkillPathSemantics } from '../../../shared/skill-path-containment'
import type { SkillScanRoot } from '..//'
import type { SkillInstallFilesystem, SkillPathInspection } from '..//'
import { SKILL_FILE_NAME } from '..//'
import { isSkillStagingEntryName } from './staging-names'
/** One directory in a discovery root that holds a `SKILL.md`, with everything
* the classifier needs to decide which of the three placement kinds it is. */
+5 -5
View File
@@ -1,16 +1,16 @@
import { posix as pathPosix, win32 as pathWin32 } from 'node:path'
import { skillFileMaxDepth } from '../../shared/skill-discovery-depth'
import { skillFileMaxDepth } from '../../../shared/skill-discovery-depth'
import type {
SkillDeleteBlockReason,
SkillDeletePlacement
} from '../../shared/skill-delete-contract'
} from '../../../shared/skill-delete-contract'
import {
skillPathDepthBelow,
skillPathsEqual,
type SkillPathSemantics
} from '../../shared/skill-path-containment'
import type { SkillScanRoot } from './skill-discovery-sources'
import type { SkillPlacementCandidate } from './skill-delete-enumeration'
} from '../../../shared/skill-path-containment'
import type { SkillScanRoot } from '..//'
import type { SkillPlacementCandidate } from './enumeration'
/**
* Headroom against ordinary clock and read skew, not against WSL's
+3 -3
View File
@@ -2,9 +2,9 @@ import { mkdir, mkdtemp, rm, stat, symlink, utimes, writeFile } from 'node:fs/pr
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { afterEach, describe, expect, it } from 'vitest'
import type { SkillDeleteRequest } from '../../shared/skill-delete-contract'
import { buildSkillDeletePlan } from './skill-delete-plan'
import { nativeSkillInstallFilesystem } from './skill-install-filesystem'
import type { SkillDeleteRequest } from '../../../shared/skill-delete-contract'
import { buildSkillDeletePlan } from './plan'
import { nativeSkillInstallFilesystem } from '..//'
const roots: string[] = []
+12 -12
View File
@@ -1,17 +1,17 @@
import { posix as pathPosix, win32 as pathWin32 } from 'node:path'
import type { Repo } from '../../shared/repo-types'
import type { Repo } from '../../../shared/repo-types'
import type {
SkillDeleteBlockReason,
SkillDeletePlan,
SkillDeletePlanEntry,
SkillDeleteRequest,
SkillDeleteTargetSkill
} from '../../shared/skill-delete-contract'
import { normalizedSkillPath, type SkillPathSemantics } from '../../shared/skill-path-containment'
} from '../../../shared/skill-delete-contract'
import {
enumerateSkillPlacementCandidates,
requireEnumerableFilesystem
} from './skill-delete-enumeration'
normalizedSkillPath,
type SkillPathSemantics
} from '../../../shared/skill-path-containment'
import { enumerateSkillPlacementCandidates, requireEnumerableFilesystem } from './enumeration'
import {
blockedCanonicalReason,
classifySkillPlacement,
@@ -19,12 +19,12 @@ import {
owningSkillRoot,
type ClassifiedPlacement,
type SkillDeleteGuardContext
} from './skill-delete-guards'
import { buildSkillDeleteRootSet } from './skill-delete-roots'
import type { ResolvedSkillDiscoveryTarget } from './skill-discovery-target'
import type { SkillInstallFilesystem } from './skill-install-filesystem'
import type { SkillProviderRootOverrides } from './skill-provider-destinations'
import type { SkillScanRoot } from './skill-discovery-sources'
} from './guards'
import { buildSkillDeleteRootSet } from './roots'
import type { ResolvedSkillDiscoveryTarget } from '..//'
import type { SkillInstallFilesystem } from '..//'
import type { SkillProviderRootOverrides } from '..//'
import type { SkillScanRoot } from '..//'
/** Overlapping roots can reach one directory twice. Staging the same path twice
* would fail the second rename and roll the whole skill back. */
@@ -8,9 +8,9 @@ import {
skillDeleteJournalPath,
writeSkillDeleteJournal,
type SkillDeleteJournalV1
} from './skill-delete-recovery'
import { writeSkillStateFile } from './skill-install-provenance'
import { skillDeleteStagedName } from './skill-staging-names'
} from './recovery'
import { writeSkillStateFile } from '..//'
import { skillDeleteStagedName } from './staging-names'
const roots: string[] = []
+6 -13
View File
@@ -1,21 +1,14 @@
import { rm } from 'node:fs/promises'
import { join, posix as pathPosix, win32 as pathWin32 } from 'node:path'
import { readNodeFileWithinLimit } from '../../shared/node-bounded-file-reader'
import { readNodeFileWithinLimit } from '../../../shared/node-bounded-file-reader'
import {
SKILL_DELETE_PLACEMENT_KINDS,
type SkillDeletePlacementKind
} from '../../shared/skill-delete-contract'
import { nativeSkillPathSemantics, skillPathInside } from '../../shared/skill-path-containment'
import {
nativeSkillInstallFilesystem,
type SkillInstallFilesystem
} from './skill-install-filesystem'
import {
removeSkillInstallReceipt,
skillInstallStateKey,
writeSkillStateFile
} from './skill-install-provenance'
import { isSkillDeleteStagedName } from './skill-staging-names'
} from '../../../shared/skill-delete-contract'
import { nativeSkillPathSemantics, skillPathInside } from '../../../shared/skill-path-containment'
import { nativeSkillInstallFilesystem, type SkillInstallFilesystem } from '..//'
import { removeSkillInstallReceipt, skillInstallStateKey, writeSkillStateFile } from '..//'
import { isSkillDeleteStagedName } from './staging-names'
const JOURNAL_MAX_BYTES = 4 * 1024 * 1024
@@ -1,19 +1,15 @@
import { join } from 'node:path'
import type { Repo } from '../../shared/repo-types'
import type { Repo } from '../../../shared/repo-types'
import type {
SkillDeletePlan,
SkillDeleteRequest,
SkillDeleteResult
} from '../../shared/skill-delete-contract'
import {
deleteSkills,
previewSkillDeletion,
type SkillDeleteServiceInput
} from './skill-delete-service'
import type { ResolvedSkillDiscoveryTarget } from './skill-discovery-target'
import { nativeSkillInstallFilesystem } from './skill-install-filesystem'
import type { SkillProviderRootOverrides } from './skill-provider-destinations'
import { WslSkillInstallFilesystem } from './skill-wsl-install-filesystem'
} from '../../../shared/skill-delete-contract'
import { deleteSkills, previewSkillDeletion, type SkillDeleteServiceInput } from './service'
import type { ResolvedSkillDiscoveryTarget } from '..//'
import { nativeSkillInstallFilesystem } from '..//'
import type { SkillProviderRootOverrides } from '..//'
import { WslSkillInstallFilesystem } from '..//'
/** Assembly shared by the local IPC channel and the runtime RPC method, so both
* transports resolve the same host, roots, and filesystem. */
+6 -6
View File
@@ -1,17 +1,17 @@
import { homedir } from 'node:os'
import { posix as pathPosix } from 'node:path'
import type { Repo } from '../../shared/repo-types'
import type { Repo } from '../../../shared/repo-types'
import {
POSIX_SKILL_PATH_SEMANTICS,
nativeSkillPathSemantics,
type SkillPathSemantics
} from '../../shared/skill-path-containment'
import { toWindowsWslPath } from '../../shared/wsl-paths'
} from '../../../shared/skill-path-containment'
import { toWindowsWslPath } from '../../../shared/wsl-paths'
import { discoverClaudePluginSkillSources } from './claude-plugin-skill-sources'
import { discoverClaudePluginSkillSourcesInWsl } from './claude-plugin-skill-sources-wsl'
import { buildSkillDiscoverySources, type SkillScanRoot } from './skill-discovery-sources'
import type { ResolvedSkillDiscoveryTarget } from './skill-discovery-target'
import type { SkillProviderRootOverrides } from './skill-provider-destinations'
import { buildSkillDiscoverySources, type SkillScanRoot } from '..//'
import type { ResolvedSkillDiscoveryTarget } from '..//'
import type { SkillProviderRootOverrides } from '..//'
/**
* The delete host owns everything about where skills may live, so it rebuilds
+6 -9
View File
@@ -2,15 +2,12 @@ import { lstat, mkdir, mkdtemp, readdir, rm, stat, symlink, writeFile } from 'no
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { afterEach, describe, expect, it, vi } from 'vitest'
import type { SkillDeleteRequest } from '../../shared/skill-delete-contract'
import { deleteSkills } from './skill-delete-service'
import { acquireSkillInstallLock, skillInstallLockPath } from './skill-install-lock'
import {
nativeSkillInstallFilesystem,
type SkillInstallFilesystem
} from './skill-install-filesystem'
import { readSkillInstallReceipt, writeSkillInstallReceipt } from './skill-install-provenance'
import { skillDeleteJournalPath } from './skill-delete-recovery'
import type { SkillDeleteRequest } from '../../../shared/skill-delete-contract'
import { deleteSkills } from './service'
import { acquireSkillInstallLock, skillInstallLockPath } from '..//'
import { nativeSkillInstallFilesystem, type SkillInstallFilesystem } from '..//'
import { readSkillInstallReceipt, writeSkillInstallReceipt } from '..//'
import { skillDeleteJournalPath } from './recovery'
const roots: string[] = []
+12 -15
View File
@@ -1,36 +1,33 @@
import { rm } from 'node:fs/promises'
import { posix as pathPosix, win32 as pathWin32 } from 'node:path'
import type { Repo } from '../../shared/repo-types'
import type { Repo } from '../../../shared/repo-types'
import type {
SkillDeletePlan,
SkillDeletePlanEntry,
SkillDeleteRequest,
SkillDeleteResult,
SkillDeleteResultEntry
} from '../../shared/skill-delete-contract'
import { nativeSkillPathSemantics } from '../../shared/skill-path-containment'
import { buildSkillDeletePlan, type ResolvedSkillDeletePlan } from './skill-delete-plan'
} from '../../../shared/skill-delete-contract'
import { nativeSkillPathSemantics } from '../../../shared/skill-path-containment'
import { buildSkillDeletePlan, type ResolvedSkillDeletePlan } from './plan'
import {
recoverSkillDeleteTransaction,
skillDeleteJournalPath,
writeSkillDeleteJournal,
type SkillDeleteJournalMove,
type SkillDeleteJournalV1
} from './skill-delete-recovery'
} from './recovery'
import {
planSkillDeleteMoves,
removeStagedSkillDeleteMoves,
stageSkillDeleteMoves
} from './skill-delete-staging'
import {
clearSkillDiscoveryCaches,
type ResolvedSkillDiscoveryTarget
} from './skill-discovery-target'
import { acquireSkillInstallLock, skillInstallLockPath } from './skill-install-lock'
import { removeSkillInstallReceipt } from './skill-install-provenance'
import type { SkillInstallFilesystem } from './skill-install-filesystem'
import type { SkillProviderRootOverrides } from './skill-provider-destinations'
import { recordSkillDeleteOperation } from './skill-operation-observability'
} from './staging'
import { clearSkillDiscoveryCaches, type ResolvedSkillDiscoveryTarget } from '..//'
import { acquireSkillInstallLock, skillInstallLockPath } from '..//'
import { removeSkillInstallReceipt } from '..//'
import type { SkillInstallFilesystem } from '..//'
import type { SkillProviderRootOverrides } from '..//'
import { recordSkillDeleteOperation } from '..//'
export type SkillDeleteServiceInput = {
request: SkillDeleteRequest
@@ -5,7 +5,7 @@
* for delete, as a row the user can delete again).
*
* The four conventions in the tree today:
* `.<name>.orca-skill-delete-<uuid>` (skill-delete-service)
* `.<name>.orca-skill-delete-<uuid>` (service)
* `.<name>.orca-remove-backup-<uuid>` (skill-remove-transaction)
* `.<name>.orca-placement-backup-<id>` (skill-placement-transaction-controller)
* `.<name>.orca-placement-staging-<id>` (skill-placement-transaction-controller)
@@ -2,13 +2,9 @@ import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { afterEach, describe, expect, it } from 'vitest'
import { buildWslSkillDiscoveryCommand } from './skill-discovery-wsl'
import { findSkillFiles } from './skill-root-file-walk'
import {
isSkillStagingEntryName,
skillDeleteStagedName,
SKILL_STAGING_GLOB
} from './skill-staging-names'
import { buildWslSkillDiscoveryCommand } from '..//'
import { findSkillFiles } from '..//'
import { isSkillStagingEntryName, skillDeleteStagedName, SKILL_STAGING_GLOB } from './staging-names'
const roots: string[] = []
@@ -17,7 +13,7 @@ afterEach(async () => {
})
async function stagedRoot(stagedName: string): Promise<string> {
const root = await mkdtemp(join(tmpdir(), 'orca-skill-staging-visibility-'))
const root = await mkdtemp(join(tmpdir(), 'orca-staging-visibility-'))
roots.push(root)
const staged = join(root, stagedName)
await mkdir(staged, { recursive: true })
+6 -6
View File
@@ -1,11 +1,11 @@
import { randomUUID } from 'node:crypto'
import { posix as pathPosix, win32 as pathWin32 } from 'node:path'
import type { SkillDeletePlacement } from '../../shared/skill-delete-contract'
import { nativeSkillPathSemantics } from '../../shared/skill-path-containment'
import type { SkillDeleteJournalMove } from './skill-delete-recovery'
import type { SkillInstallFilesystem } from './skill-install-filesystem'
import { SKILL_FILE_NAME } from './skill-root-file-walk'
import { skillDeleteStagedName } from './skill-staging-names'
import type { SkillDeletePlacement } from '../../../shared/skill-delete-contract'
import { nativeSkillPathSemantics } from '../../../shared/skill-path-containment'
import type { SkillDeleteJournalMove } from './recovery'
import type { SkillInstallFilesystem } from '..//'
import { SKILL_FILE_NAME } from '..//'
import { skillDeleteStagedName } from './staging-names'
function api(): typeof pathPosix {
return nativeSkillPathSemantics().sep === '\\' ? pathWin32 : pathPosix
@@ -5,7 +5,7 @@ import {
WslEnumerationProtocolError,
WSL_INSPECT_PATHS_SCRIPT,
WSL_LIST_ENTRIES_SCRIPT
} from './skill-wsl-enumeration-protocol'
} from './wsl-enumeration-protocol'
const NUL = '\0'
@@ -1,8 +1,4 @@
import type {
SkillDirectoryEntry,
SkillFilesystemEntryKind,
SkillPathInspection
} from './skill-install-filesystem'
import type { SkillDirectoryEntry, SkillFilesystemEntryKind, SkillPathInspection } from '..//'
/**
* Guest-side enumeration for path-based skill deletion.
+1 -1
View File
@@ -17,7 +17,7 @@ import {
} from './skill-discovery-sources'
import { discoverClaudePluginSkillSourcesInWsl } from './claude-plugin-skill-sources-wsl'
import type { SkillProviderRootOverrides } from './skill-provider-destinations'
import { SKILL_STAGING_GLOB } from './skill-staging-names'
import { SKILL_STAGING_GLOB } from './skill-delete/staging-names'
import { skillFileMaxDepth } from '../../shared/skill-discovery-depth'
const MAX_MARKDOWN_BYTES = 256 * 1024
+1 -1
View File
@@ -1,7 +1,7 @@
import type { Dirent } from 'node:fs'
import { readdir, realpath, stat } from 'node:fs/promises'
import { isAbsolute, join, relative, sep } from 'node:path'
import { isSkillStagingEntryName } from './skill-staging-names'
import { isSkillStagingEntryName } from './skill-delete/staging-names'
export const SKILL_FILE_NAME = 'SKILL.md'
@@ -22,7 +22,7 @@ import { readSkillPlacementRecoveryJournal } from './skill-placement-recovery-jo
import {
readSkillDeleteRecoveryJournal,
recoverSkillDeleteTransaction
} from './skill-delete-recovery'
} from './skill-delete/recovery'
import { recoverSkillPlacementTransaction } from './skill-placement-transaction'
const MAX_PENDING_TRANSACTION_JOURNALS = 64
@@ -17,7 +17,7 @@ import {
parseWslListEntriesOutput,
WSL_INSPECT_PATHS_SCRIPT,
WSL_LIST_ENTRIES_SCRIPT
} from './skill-wsl-enumeration-protocol'
} from './skill-delete/wsl-enumeration-protocol'
import { SKILL_INSTALL_PROVIDERS } from '../../shared/skill-install-providers'
import type { SkillProviderRootOverrides } from './skill-provider-destinations'
import { runWslProcess } from '../wsl/wsl-runner'