@iloom/cli 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/README.md +228 -905
  2. package/dist/{BranchNamingService-3OQPRSWT.js → BranchNamingService-OMWKUYMM.js} +2 -2
  3. package/dist/ClaudeContextManager-3VXA6UPR.js +13 -0
  4. package/dist/ClaudeService-6CPK43N4.js +12 -0
  5. package/dist/{LoomLauncher-FLEMBCSQ.js → LoomLauncher-JF7JZMTZ.js} +5 -5
  6. package/dist/README.md +228 -905
  7. package/dist/{SettingsManager-WHHFGSL7.js → SettingsManager-ZCWJ56WP.js} +2 -2
  8. package/dist/{chunk-MAVL6PJF.js → chunk-4BGK7T6X.js} +3 -3
  9. package/dist/{chunk-VAYCCUXW.js → chunk-4E4LD3QR.js} +2 -2
  10. package/dist/{chunk-5EF7Z346.js → chunk-HBYZH6GD.js} +11 -9
  11. package/dist/chunk-HBYZH6GD.js.map +1 -0
  12. package/dist/{chunk-3KATJIKO.js → chunk-INW24J2W.js} +2 -2
  13. package/dist/chunk-INW24J2W.js.map +1 -0
  14. package/dist/{chunk-AWOFAD5O.js → chunk-IXKLYTWO.js} +4 -4
  15. package/dist/{chunk-ML3NRPNB.js → chunk-O5OH5MRX.js} +3 -3
  16. package/dist/chunk-O5OH5MRX.js.map +1 -0
  17. package/dist/{chunk-4HHRTA7Q.js → chunk-TSKY3JI7.js} +3 -3
  18. package/dist/{chunk-4HHRTA7Q.js.map → chunk-TSKY3JI7.js.map} +1 -1
  19. package/dist/{chunk-FIAT22G7.js → chunk-U5QDY7ZD.js} +3 -3
  20. package/dist/{chunk-C5QCTEQK.js → chunk-XPKDPZ5D.js} +2 -2
  21. package/dist/{chunk-47KSHUCR.js → chunk-ZBQVSHVT.js} +4 -4
  22. package/dist/chunk-ZBQVSHVT.js.map +1 -0
  23. package/dist/{chunk-XXV3UFZL.js → chunk-ZWFBBPJI.js} +5 -5
  24. package/dist/{chunk-XXV3UFZL.js.map → chunk-ZWFBBPJI.js.map} +1 -1
  25. package/dist/{claude-GOP6PFC7.js → claude-LUZ35IMK.js} +2 -2
  26. package/dist/{cleanup-7RWLBSLE.js → cleanup-3MONU4PU.js} +10 -10
  27. package/dist/{cleanup-7RWLBSLE.js.map → cleanup-3MONU4PU.js.map} +1 -1
  28. package/dist/cli.js +32 -32
  29. package/dist/cli.js.map +1 -1
  30. package/dist/{contribute-BS2L4FZR.js → contribute-UWJAGIG7.js} +2 -2
  31. package/dist/{feedback-N4ECWIPF.js → feedback-W3BXTGIM.js} +4 -4
  32. package/dist/{git-TDXKRTXM.js → git-34Z6QVDS.js} +2 -2
  33. package/dist/{ignite-VM64QO3J.js → ignite-KVJEFXNO.js} +5 -5
  34. package/dist/index.js +3 -3
  35. package/dist/index.js.map +1 -1
  36. package/dist/{init-G3T64SC4.js → init-L55Q73H4.js} +5 -5
  37. package/dist/{open-KXDXEKRZ.js → open-LNRZL3UU.js} +4 -4
  38. package/dist/prompts/init-prompt.txt +3 -3
  39. package/dist/{rebase-Q7GMM7EI.js → rebase-C4WNCVGM.js} +6 -6
  40. package/dist/{run-PAWJJCSX.js → run-IOGNIOYN.js} +4 -4
  41. package/dist/schema/settings.schema.json +3 -3
  42. package/dist/{test-git-3WDLNQCA.js → test-git-J7I5MFYH.js} +3 -3
  43. package/dist/{test-prefix-EVGAWAJW.js → test-prefix-ZCONBCBX.js} +3 -3
  44. package/package.json +2 -2
  45. package/dist/ClaudeContextManager-MUQSDY2E.js +0 -13
  46. package/dist/ClaudeService-HG4VQ7AW.js +0 -12
  47. package/dist/chunk-3KATJIKO.js.map +0 -1
  48. package/dist/chunk-47KSHUCR.js.map +0 -1
  49. package/dist/chunk-5EF7Z346.js.map +0 -1
  50. package/dist/chunk-ML3NRPNB.js.map +0 -1
  51. /package/dist/{BranchNamingService-3OQPRSWT.js.map → BranchNamingService-OMWKUYMM.js.map} +0 -0
  52. /package/dist/{ClaudeContextManager-MUQSDY2E.js.map → ClaudeContextManager-3VXA6UPR.js.map} +0 -0
  53. /package/dist/{ClaudeService-HG4VQ7AW.js.map → ClaudeService-6CPK43N4.js.map} +0 -0
  54. /package/dist/{LoomLauncher-FLEMBCSQ.js.map → LoomLauncher-JF7JZMTZ.js.map} +0 -0
  55. /package/dist/{SettingsManager-WHHFGSL7.js.map → SettingsManager-ZCWJ56WP.js.map} +0 -0
  56. /package/dist/{chunk-MAVL6PJF.js.map → chunk-4BGK7T6X.js.map} +0 -0
  57. /package/dist/{chunk-VAYCCUXW.js.map → chunk-4E4LD3QR.js.map} +0 -0
  58. /package/dist/{chunk-AWOFAD5O.js.map → chunk-IXKLYTWO.js.map} +0 -0
  59. /package/dist/{chunk-FIAT22G7.js.map → chunk-U5QDY7ZD.js.map} +0 -0
  60. /package/dist/{chunk-C5QCTEQK.js.map → chunk-XPKDPZ5D.js.map} +0 -0
  61. /package/dist/{claude-GOP6PFC7.js.map → claude-LUZ35IMK.js.map} +0 -0
  62. /package/dist/{contribute-BS2L4FZR.js.map → contribute-UWJAGIG7.js.map} +0 -0
  63. /package/dist/{feedback-N4ECWIPF.js.map → feedback-W3BXTGIM.js.map} +0 -0
  64. /package/dist/{git-TDXKRTXM.js.map → git-34Z6QVDS.js.map} +0 -0
  65. /package/dist/{ignite-VM64QO3J.js.map → ignite-KVJEFXNO.js.map} +0 -0
  66. /package/dist/{init-G3T64SC4.js.map → init-L55Q73H4.js.map} +0 -0
  67. /package/dist/{open-KXDXEKRZ.js.map → open-LNRZL3UU.js.map} +0 -0
  68. /package/dist/{rebase-Q7GMM7EI.js.map → rebase-C4WNCVGM.js.map} +0 -0
  69. /package/dist/{run-PAWJJCSX.js.map → run-IOGNIOYN.js.map} +0 -0
  70. /package/dist/{test-git-3WDLNQCA.js.map → test-git-J7I5MFYH.js.map} +0 -0
  71. /package/dist/{test-prefix-EVGAWAJW.js.map → test-prefix-ZCONBCBX.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/cleanup.ts"],"sourcesContent":["import { logger } from '../utils/logger.js'\nimport { GitWorktreeManager } from '../lib/GitWorktreeManager.js'\nimport { ResourceCleanup } from '../lib/ResourceCleanup.js'\nimport { ProcessManager } from '../lib/process/ProcessManager.js'\nimport { DatabaseManager } from '../lib/DatabaseManager.js'\nimport { EnvironmentManager } from '../lib/EnvironmentManager.js'\nimport { CLIIsolationManager } from '../lib/CLIIsolationManager.js'\nimport { SettingsManager } from '../lib/SettingsManager.js'\nimport { promptConfirmation } from '../utils/prompt.js'\nimport { IdentifierParser } from '../utils/IdentifierParser.js'\nimport { loadEnvIntoProcess } from '../utils/env.js'\nimport { createNeonProviderFromSettings } from '../utils/neon-helpers.js'\nimport { LoomManager } from '../lib/LoomManager.js'\nimport type { CleanupOptions } from '../types/index.js'\nimport type { CleanupResult } from '../types/cleanup.js'\nimport type { ParsedInput } from './start.js'\n\n/**\n * Input structure for CleanupCommand.execute()\n */\nexport interface CleanupCommandInput {\n identifier?: string\n options: CleanupOptions\n}\n\n/**\n * Parsed and validated cleanup command input\n * Mode determines which cleanup operation to perform\n */\nexport interface ParsedCleanupInput {\n mode: 'list' | 'single' | 'issue' | 'all'\n identifier?: string\n issueNumber?: string | number\n branchName?: string\n originalInput?: string\n options: CleanupOptions\n}\n\n/**\n * Manages cleanup command execution with option parsing and validation\n * Follows the command pattern established by StartCommand\n *\n * This implementation handles ONLY parsing, validation, and mode determination.\n * Actual cleanup operations are deferred to subsequent sub-issues.\n */\nexport class CleanupCommand {\n private readonly gitWorktreeManager: GitWorktreeManager\n private resourceCleanup?: ResourceCleanup\n private loomManager?: import('../lib/LoomManager.js').LoomManager\n private readonly identifierParser: IdentifierParser\n\n constructor(\n gitWorktreeManager?: GitWorktreeManager,\n resourceCleanup?: ResourceCleanup\n ) {\n // Load environment variables first\n const envResult = loadEnvIntoProcess()\n if (envResult.error) {\n logger.debug(`Environment loading warning: ${envResult.error.message}`)\n }\n if (envResult.parsed) {\n logger.debug(`Loaded ${Object.keys(envResult.parsed).length} environment variables`)\n }\n\n this.gitWorktreeManager = gitWorktreeManager ?? new GitWorktreeManager()\n\n // Initialize ResourceCleanup with DatabaseManager and CLIIsolationManager\n // ResourceCleanup will be initialized lazily with proper configuration\n if (resourceCleanup) {\n this.resourceCleanup = resourceCleanup\n }\n\n // Initialize IdentifierParser for pattern-based detection\n this.identifierParser = new IdentifierParser(this.gitWorktreeManager)\n }\n\n /**\n * Lazy initialization of ResourceCleanup and LoomManager with properly configured DatabaseManager\n */\n private async ensureResourceCleanup(): Promise<void> {\n if (this.resourceCleanup && this.loomManager) {\n return\n }\n\n const settingsManager = new SettingsManager()\n const settings = await settingsManager.loadSettings()\n const databaseUrlEnvVarName = settings.capabilities?.database?.databaseUrlEnvVarName ?? 'DATABASE_URL'\n\n const environmentManager = new EnvironmentManager()\n const neonProvider = createNeonProviderFromSettings(settings)\n const databaseManager = new DatabaseManager(neonProvider, environmentManager, databaseUrlEnvVarName)\n const cliIsolationManager = new CLIIsolationManager()\n\n this.resourceCleanup ??= new ResourceCleanup(\n this.gitWorktreeManager,\n new ProcessManager(),\n databaseManager,\n cliIsolationManager\n )\n\n // Initialize LoomManager if not provided (for child loom detection)\n if (!this.loomManager) {\n const { GitHubService } = await import('../lib/GitHubService.js')\n const { ClaudeContextManager } = await import('../lib/ClaudeContextManager.js')\n const { ProjectCapabilityDetector } = await import('../lib/ProjectCapabilityDetector.js')\n const { DefaultBranchNamingService } = await import('../lib/BranchNamingService.js')\n\n this.loomManager = new LoomManager(\n this.gitWorktreeManager,\n new GitHubService(),\n new DefaultBranchNamingService({ useClaude: true }),\n environmentManager,\n new ClaudeContextManager(),\n new ProjectCapabilityDetector(),\n cliIsolationManager,\n settingsManager,\n databaseManager\n )\n }\n }\n\n /**\n * Check for child looms and exit gracefully if any exist\n * Always checks the TARGET loom (the one being cleaned up), not the current directory's loom\n *\n * @param parsed - The parsed input identifying the loom being cleaned up\n */\n private async checkForChildLooms(parsed: ParsedCleanupInput): Promise<void> {\n await this.ensureResourceCleanup()\n if (!this.loomManager) {\n throw new Error('Failed to initialize LoomManager')\n }\n\n // Determine which branch is being cleaned up based on parsed input\n let targetBranch: string | undefined\n\n if (parsed.branchName) {\n targetBranch = parsed.branchName\n } else if (parsed.mode === 'issue' && parsed.issueNumber !== undefined) {\n // For issues, try to find the worktree by issue number to get the branch name\n const worktree = await this.gitWorktreeManager.findWorktreeForIssue(parsed.issueNumber)\n targetBranch = worktree?.branch\n }\n\n // If we can't determine the target branch, skip the check\n if (!targetBranch) {\n logger.debug(`Cannot determine target branch for child loom check`)\n return\n }\n\n // Check if the TARGET loom has any child looms\n const hasChildLooms = await this.loomManager.checkAndWarnChildLooms(targetBranch)\n if (hasChildLooms) {\n logger.error('Cannot cleanup loom while child looms exist. Please finish child looms first.')\n process.exit(1)\n }\n }\n\n /**\n * Main entry point for the cleanup command\n * Parses input, validates options, and determines operation mode\n */\n public async execute(input: CleanupCommandInput): Promise<void> {\n try {\n // Step 1: Parse input and determine mode\n const parsed = this.parseInput(input)\n\n // Step 2: Validate option combinations\n this.validateInput(parsed)\n\n // Step 2.5: Check for child looms AFTER parsing input\n // This ensures we only block when cleaning the CURRENT loom (parent), not a child\n await this.checkForChildLooms(parsed)\n\n // Step 3: Execute based on mode\n logger.info(`Cleanup mode: ${parsed.mode}`)\n\n if (parsed.mode === 'single') {\n await this.executeSingleCleanup(parsed)\n } else if (parsed.mode === 'list') {\n logger.info('Would list all worktrees') // TODO: Implement in Sub-issue #2\n logger.success('Command parsing and validation successful')\n } else if (parsed.mode === 'all') {\n logger.info('Would remove all worktrees') // TODO: Implement in Sub-issue #5\n logger.success('Command parsing and validation successful')\n } else if (parsed.mode === 'issue') {\n await this.executeIssueCleanup(parsed)\n }\n } catch (error) {\n if (error instanceof Error) {\n logger.error(`${error.message}`)\n } else {\n logger.error('An unknown error occurred')\n }\n throw error\n }\n }\n\n /**\n * Parse input to determine cleanup mode and extract relevant data\n * Implements auto-detection: numeric input = issue number, non-numeric = branch name\n *\n * @private\n */\n private parseInput(input: CleanupCommandInput): ParsedCleanupInput {\n const { identifier, options } = input\n\n // Trim identifier if present\n const trimmedIdentifier = identifier?.trim() ?? undefined\n\n // Mode: List (takes priority - it's informational only)\n if (options.list) {\n const result: ParsedCleanupInput = {\n mode: 'list',\n options\n }\n if (trimmedIdentifier) {\n result.identifier = trimmedIdentifier\n }\n return result\n }\n\n // Mode: All (remove everything)\n if (options.all) {\n const result: ParsedCleanupInput = {\n mode: 'all',\n options\n }\n if (trimmedIdentifier) {\n result.identifier = trimmedIdentifier\n }\n if (options.issue !== undefined) {\n result.issueNumber = options.issue\n }\n return result\n }\n\n // Mode: Explicit issue number via --issue flag\n if (options.issue !== undefined) {\n // Need to determine if identifier is branch or numeric to set branchName\n if (trimmedIdentifier) {\n const numericPattern = /^[0-9]+$/\n if (!numericPattern.test(trimmedIdentifier)) {\n // Identifier is a branch name with explicit --issue flag\n return {\n mode: 'issue',\n issueNumber: options.issue,\n branchName: trimmedIdentifier,\n identifier: trimmedIdentifier,\n originalInput: trimmedIdentifier,\n options\n }\n }\n }\n const result: ParsedCleanupInput = {\n mode: 'issue',\n issueNumber: options.issue,\n options\n }\n if (trimmedIdentifier) {\n result.identifier = trimmedIdentifier\n }\n return result\n }\n\n // Mode: Auto-detect from identifier\n if (!trimmedIdentifier) {\n throw new Error('Missing required argument: identifier. Use --all to remove all worktrees or --list to list them.')\n }\n\n // Auto-detection: Check if identifier is purely numeric\n // Pattern from bash script line 364: ^[0-9]+$\n const numericPattern = /^[0-9]+$/\n if (numericPattern.test(trimmedIdentifier)) {\n // Numeric input = issue number\n return {\n mode: 'issue',\n issueNumber: parseInt(trimmedIdentifier, 10),\n identifier: trimmedIdentifier,\n originalInput: trimmedIdentifier,\n options\n }\n } else {\n // Non-numeric = branch name\n return {\n mode: 'single',\n branchName: trimmedIdentifier,\n identifier: trimmedIdentifier,\n originalInput: trimmedIdentifier,\n options\n }\n }\n }\n\n /**\n * Validate parsed input for option conflicts\n * Throws descriptive errors for invalid option combinations\n *\n * @private\n */\n private validateInput(parsed: ParsedCleanupInput): void {\n const { mode, options, branchName } = parsed\n\n // Conflict: --list is informational only, incompatible with destructive operations\n if (mode === 'list') {\n if (options.all) {\n throw new Error('Cannot use --list with --all (list is informational only)')\n }\n if (options.issue !== undefined) {\n throw new Error('Cannot use --list with --issue (list is informational only)')\n }\n if (parsed.identifier) {\n throw new Error('Cannot use --list with a specific identifier (list shows all worktrees)')\n }\n }\n\n // Conflict: --all removes everything, can't combine with specific identifier or --issue\n if (mode === 'all') {\n if (parsed.identifier) {\n throw new Error('Cannot use --all with a specific identifier. Use one or the other.')\n }\n if (parsed.issueNumber !== undefined) {\n throw new Error('Cannot use --all with a specific identifier. Use one or the other.')\n }\n }\n\n // Conflict: explicit --issue flag with branch name identifier\n // (This prevents confusion when user provides both)\n if (options.issue !== undefined && branchName) {\n throw new Error('Cannot use --issue flag with branch name identifier. Use numeric identifier or --issue flag alone.')\n }\n\n // Note: --force and --dry-run are compatible with all modes (no conflicts)\n }\n\n /**\n * Execute cleanup for single worktree\n * Implements two-stage confirmation: worktree removal, then branch deletion\n * Uses IdentifierParser for pattern-based detection without GitHub API calls\n */\n private async executeSingleCleanup(parsed: ParsedCleanupInput): Promise<void> {\n const identifier = parsed.branchName ?? parsed.identifier ?? ''\n if (!identifier) {\n throw new Error('No identifier found for cleanup')\n }\n const { force, dryRun } = parsed.options\n\n // Step 1: Parse identifier using pattern-based detection\n let parsedInput: ParsedInput = await this.identifierParser.parseForPatternDetection(identifier)\n\n // If type is 'branch', try to extract issue number for CLI symlink cleanup\n if (parsedInput.type === 'branch' && parsedInput.branchName) {\n const { extractIssueNumber } = await import('../utils/git.js')\n const extractedNumber = extractIssueNumber(parsedInput.branchName)\n if (extractedNumber !== null) {\n parsedInput = {\n ...parsedInput,\n number: extractedNumber // Add number for CLI symlink cleanup\n }\n }\n }\n\n // Step 2: Display worktree details\n logger.info(`Preparing to cleanup worktree: ${identifier}`)\n\n // Step 3: Confirmation - worktree removal\n if (!force) {\n const confirmWorktree = await promptConfirmation('Remove this worktree?', true)\n if (!confirmWorktree) {\n logger.info('Cleanup cancelled')\n return\n }\n }\n\n // Step 4: Execute worktree cleanup (includes safety validation)\n // With --force, delete branch automatically; otherwise handle separately\n await this.ensureResourceCleanup()\n if (!this.resourceCleanup) {\n throw new Error('Failed to initialize ResourceCleanup')\n }\n const cleanupResult = await this.resourceCleanup.cleanupWorktree(parsedInput, {\n dryRun: dryRun ?? false,\n force: force ?? false,\n deleteBranch: force ?? false, // Delete branch immediately if --force, otherwise prompt later\n keepDatabase: false,\n })\n\n // Step 5: Report cleanup results\n this.reportCleanupResults(cleanupResult)\n\n // Step 6: Second confirmation - branch deletion (only if not forced and worktree cleanup succeeded)\n if (cleanupResult.success && !force && cleanupResult.branchName) {\n const confirmBranch = await promptConfirmation('Also delete the git branch?', true)\n if (confirmBranch) {\n await this.deleteBranchForCleanup(cleanupResult.branchName, { force: force ?? false, dryRun: dryRun ?? false })\n }\n }\n\n // Final success message\n if (cleanupResult.success) {\n logger.success('Cleanup completed successfully')\n } else {\n logger.warn('Cleanup completed with errors - see details above')\n }\n }\n\n /**\n * Delete branch as part of cleanup operation\n */\n private async deleteBranchForCleanup(\n branchName: string,\n options: { force?: boolean; dryRun?: boolean }\n ): Promise<void> {\n try {\n await this.ensureResourceCleanup()\n if (!this.resourceCleanup) {\n throw new Error('Failed to initialize ResourceCleanup')\n }\n await this.resourceCleanup.deleteBranch(branchName, options)\n logger.success(`Branch deleted: ${branchName}`)\n } catch (error) {\n if (error instanceof Error) {\n logger.error(`Failed to delete branch: ${error.message}`)\n }\n // Don't throw - branch deletion is optional/secondary operation\n }\n }\n\n /**\n * Report cleanup operation results to user\n */\n private reportCleanupResults(result: CleanupResult): void {\n logger.info('Cleanup operations:')\n\n result.operations.forEach(op => {\n const status = op.success ? '✓' : '✗'\n const message = op.error ? `${op.message}: ${op.error}` : op.message\n\n if (op.success) {\n logger.info(` ${status} ${message}`)\n } else {\n logger.error(` ${status} ${message}`)\n }\n })\n\n if (result.errors.length > 0) {\n logger.warn(`${result.errors.length} error(s) occurred during cleanup`)\n }\n }\n\n /**\n * Execute cleanup for all worktrees associated with an issue or PR number\n * Searches for worktrees by their path patterns (e.g., issue-25, pr-25, 25-feature, _pr_25)\n * Implements bash cleanup-worktree.sh remove_worktrees_by_issue() (lines 157-242)\n */\n private async executeIssueCleanup(parsed: ParsedCleanupInput): Promise<void> {\n const issueNumber = parsed.issueNumber\n if (issueNumber === undefined) {\n throw new Error('No issue/PR number provided for cleanup')\n }\n\n const { force, dryRun } = parsed.options\n\n logger.info(`Finding worktrees related to GitHub issue/PR #${issueNumber}...`)\n\n // Step 1: Get all worktrees and filter by path pattern\n const worktrees = await this.gitWorktreeManager.listWorktrees()\n const matchingWorktrees = worktrees.filter(wt => {\n const path = wt.path.toLowerCase()\n const numStr = String(issueNumber)\n\n // Check if path contains the number with proper word boundaries\n // Matches: issue-25, pr-25, 25-feature, _pr_25, etc.\n // Does NOT match: issue-250, 125-feature (where 25 is part of a larger number)\n const pattern = new RegExp(`(?<!\\\\d)${numStr}(?!\\\\d)`)\n return pattern.test(path)\n })\n\n if (matchingWorktrees.length === 0) {\n logger.warn(`No worktrees found for GitHub issue/PR #${issueNumber}`)\n logger.info(`Searched for worktree paths containing: ${issueNumber}, _pr_${issueNumber}, issue-${issueNumber}, etc.`)\n return\n }\n\n // Step 2: Build targets list from matching worktrees\n const targets: Array<{ branchName: string; hasWorktree: boolean; worktreePath?: string }> =\n matchingWorktrees.map(wt => ({\n branchName: wt.branch,\n hasWorktree: true,\n worktreePath: wt.path\n }))\n\n // Step 3: Display preview\n logger.info(`Found ${targets.length} worktree(s) related to issue/PR #${issueNumber}:`)\n for (const target of targets) {\n logger.info(` 🌿 ${target.branchName} (${target.worktreePath})`)\n }\n\n // Step 4: Batch confirmation (unless --force)\n if (!force) {\n const confirmCleanup = await promptConfirmation(\n `Remove ${targets.length} worktree(s)?`,\n true\n )\n if (!confirmCleanup) {\n logger.info('Cleanup cancelled')\n return\n }\n }\n\n // Step 5: Process each target sequentially\n let worktreesRemoved = 0\n let branchesDeleted = 0\n const databaseBranchesDeletedList: string[] = []\n let failed = 0\n\n for (const target of targets) {\n logger.info(`Processing worktree: ${target.branchName}`)\n\n // Cleanup worktree using ResourceCleanup with ParsedInput\n try {\n // Use the known issue number directly instead of parsing from branch name\n // This ensures CLI symlinks (created with issue number) are properly cleaned up\n const parsedInput: ParsedInput = {\n type: 'issue',\n number: issueNumber, // Use the known issue number, not parsed from branch\n branchName: target.branchName,\n originalInput: String(issueNumber)\n }\n\n await this.ensureResourceCleanup()\n if (!this.resourceCleanup) {\n throw new Error('Failed to initialize ResourceCleanup')\n }\n const result = await this.resourceCleanup.cleanupWorktree(parsedInput, {\n dryRun: dryRun ?? false,\n force: force ?? false,\n deleteBranch: false, // Handle branch deletion separately\n keepDatabase: false\n })\n\n if (result.success) {\n worktreesRemoved++\n logger.success(` Worktree removed: ${target.branchName}`)\n\n // Check if database branch was actually deleted (use explicit deleted field)\n const dbOperation = result.operations.find(op => op.type === 'database')\n if (dbOperation?.deleted) {\n // Get branch name from result or use the target branch name\n const deletedBranchName = target.branchName\n databaseBranchesDeletedList.push(deletedBranchName)\n }\n } else {\n failed++\n logger.error(` Failed to remove worktree: ${target.branchName}`)\n }\n } catch (error) {\n failed++\n const errMsg = error instanceof Error ? error.message : 'Unknown error'\n logger.error(` Failed to remove worktree: ${errMsg}`)\n continue // Continue with next worktree even if this one failed\n }\n\n // Step 6: Delete branch\n try {\n await this.ensureResourceCleanup()\n if (!this.resourceCleanup) {\n throw new Error('Failed to initialize ResourceCleanup')\n }\n await this.resourceCleanup.deleteBranch(target.branchName, {\n force: force ?? false,\n dryRun: dryRun ?? false\n })\n branchesDeleted++\n logger.success(` Branch deleted: ${target.branchName}`)\n } catch (error) {\n // Don't count unmerged branch as failure - it's a safety feature\n const errMsg = error instanceof Error ? error.message : String(error)\n if (errMsg.includes('not fully merged')) {\n logger.warn(` Branch not fully merged, skipping deletion`)\n logger.warn(` Use --force to delete anyway`)\n } else {\n // Other errors are real failures\n logger.error(` Failed to delete branch: ${errMsg}`)\n }\n }\n }\n\n // Step 7: Report statistics\n logger.success(`Completed cleanup for issue/PR #${issueNumber}:`)\n logger.info(` 📁 Worktrees removed: ${worktreesRemoved}`)\n logger.info(` 🌿 Branches deleted: ${branchesDeleted}`)\n if (databaseBranchesDeletedList.length > 0) {\n // Display branch names in the format requested\n logger.info(` 🗂️ Database branches deleted: ${databaseBranchesDeletedList.join(', ')}`)\n }\n if (failed > 0) {\n logger.warn(` ❌ Failed operations: ${failed}`)\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CO,IAAM,iBAAN,MAAqB;AAAA,EAM1B,YACE,oBACA,iBACA;AAEA,UAAM,YAAY,mBAAmB;AACrC,QAAI,UAAU,OAAO;AACnB,aAAO,MAAM,gCAAgC,UAAU,MAAM,OAAO,EAAE;AAAA,IACxE;AACA,QAAI,UAAU,QAAQ;AACpB,aAAO,MAAM,UAAU,OAAO,KAAK,UAAU,MAAM,EAAE,MAAM,wBAAwB;AAAA,IACrF;AAEA,SAAK,qBAAqB,sBAAsB,IAAI,mBAAmB;AAIvE,QAAI,iBAAiB;AACnB,WAAK,kBAAkB;AAAA,IACzB;AAGA,SAAK,mBAAmB,IAAI,iBAAiB,KAAK,kBAAkB;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,wBAAuC;AA/EvD;AAgFI,QAAI,KAAK,mBAAmB,KAAK,aAAa;AAC5C;AAAA,IACF;AAEA,UAAM,kBAAkB,IAAI,gBAAgB;AAC5C,UAAM,WAAW,MAAM,gBAAgB,aAAa;AACpD,UAAM,0BAAwB,oBAAS,iBAAT,mBAAuB,aAAvB,mBAAiC,0BAAyB;AAExF,UAAM,qBAAqB,IAAI,mBAAmB;AAClD,UAAM,eAAe,+BAA+B,QAAQ;AAC5D,UAAM,kBAAkB,IAAI,gBAAgB,cAAc,oBAAoB,qBAAqB;AACnG,UAAM,sBAAsB,IAAI,oBAAoB;AAEpD,SAAK,oBAAoB,IAAI;AAAA,MAC3B,KAAK;AAAA,MACL,IAAI,eAAe;AAAA,MACnB;AAAA,MACA;AAAA,IACF;AAGA,QAAI,CAAC,KAAK,aAAa;AACrB,YAAM,EAAE,cAAc,IAAI,MAAM,OAAO,6BAAyB;AAChE,YAAM,EAAE,qBAAqB,IAAI,MAAM,OAAO,oCAAgC;AAC9E,YAAM,EAAE,0BAA0B,IAAI,MAAM,OAAO,yCAAqC;AACxF,YAAM,EAAE,2BAA2B,IAAI,MAAM,OAAO,mCAA+B;AAEnF,WAAK,cAAc,IAAI;AAAA,QACrB,KAAK;AAAA,QACL,IAAI,cAAc;AAAA,QAClB,IAAI,2BAA2B,EAAE,WAAW,KAAK,CAAC;AAAA,QAClD;AAAA,QACA,IAAI,qBAAqB;AAAA,QACzB,IAAI,0BAA0B;AAAA,QAC9B;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,mBAAmB,QAA2C;AAC1E,UAAM,KAAK,sBAAsB;AACjC,QAAI,CAAC,KAAK,aAAa;AACrB,YAAM,IAAI,MAAM,kCAAkC;AAAA,IACpD;AAGA,QAAI;AAEJ,QAAI,OAAO,YAAY;AACrB,qBAAe,OAAO;AAAA,IACxB,WAAW,OAAO,SAAS,WAAW,OAAO,gBAAgB,QAAW;AAEtE,YAAM,WAAW,MAAM,KAAK,mBAAmB,qBAAqB,OAAO,WAAW;AACtF,qBAAe,qCAAU;AAAA,IAC3B;AAGA,QAAI,CAAC,cAAc;AACjB,aAAO,MAAM,qDAAqD;AAClE;AAAA,IACF;AAGA,UAAM,gBAAgB,MAAM,KAAK,YAAY,uBAAuB,YAAY;AAChF,QAAI,eAAe;AACjB,aAAO,MAAM,+EAA+E;AAC5F,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAa,QAAQ,OAA2C;AAC9D,QAAI;AAEF,YAAM,SAAS,KAAK,WAAW,KAAK;AAGpC,WAAK,cAAc,MAAM;AAIzB,YAAM,KAAK,mBAAmB,MAAM;AAGpC,aAAO,KAAK,iBAAiB,OAAO,IAAI,EAAE;AAE1C,UAAI,OAAO,SAAS,UAAU;AAC5B,cAAM,KAAK,qBAAqB,MAAM;AAAA,MACxC,WAAW,OAAO,SAAS,QAAQ;AACjC,eAAO,KAAK,0BAA0B;AACtC,eAAO,QAAQ,2CAA2C;AAAA,MAC5D,WAAW,OAAO,SAAS,OAAO;AAChC,eAAO,KAAK,4BAA4B;AACxC,eAAO,QAAQ,2CAA2C;AAAA,MAC5D,WAAW,OAAO,SAAS,SAAS;AAClC,cAAM,KAAK,oBAAoB,MAAM;AAAA,MACvC;AAAA,IACF,SAAS,OAAO;AACd,UAAI,iBAAiB,OAAO;AAC1B,eAAO,MAAM,GAAG,MAAM,OAAO,EAAE;AAAA,MACjC,OAAO;AACL,eAAO,MAAM,2BAA2B;AAAA,MAC1C;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,WAAW,OAAgD;AACjE,UAAM,EAAE,YAAY,QAAQ,IAAI;AAGhC,UAAM,qBAAoB,yCAAY,WAAU;AAGhD,QAAI,QAAQ,MAAM;AAChB,YAAM,SAA6B;AAAA,QACjC,MAAM;AAAA,QACN;AAAA,MACF;AACA,UAAI,mBAAmB;AACrB,eAAO,aAAa;AAAA,MACtB;AACA,aAAO;AAAA,IACT;AAGA,QAAI,QAAQ,KAAK;AACf,YAAM,SAA6B;AAAA,QACjC,MAAM;AAAA,QACN;AAAA,MACF;AACA,UAAI,mBAAmB;AACrB,eAAO,aAAa;AAAA,MACtB;AACA,UAAI,QAAQ,UAAU,QAAW;AAC/B,eAAO,cAAc,QAAQ;AAAA,MAC/B;AACA,aAAO;AAAA,IACT;AAGA,QAAI,QAAQ,UAAU,QAAW;AAE/B,UAAI,mBAAmB;AACrB,cAAMA,kBAAiB;AACvB,YAAI,CAACA,gBAAe,KAAK,iBAAiB,GAAG;AAE3C,iBAAO;AAAA,YACL,MAAM;AAAA,YACN,aAAa,QAAQ;AAAA,YACrB,YAAY;AAAA,YACZ,YAAY;AAAA,YACZ,eAAe;AAAA,YACf;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,YAAM,SAA6B;AAAA,QACjC,MAAM;AAAA,QACN,aAAa,QAAQ;AAAA,QACrB;AAAA,MACF;AACA,UAAI,mBAAmB;AACrB,eAAO,aAAa;AAAA,MACtB;AACA,aAAO;AAAA,IACT;AAGA,QAAI,CAAC,mBAAmB;AACtB,YAAM,IAAI,MAAM,kGAAkG;AAAA,IACpH;AAIA,UAAM,iBAAiB;AACvB,QAAI,eAAe,KAAK,iBAAiB,GAAG;AAE1C,aAAO;AAAA,QACL,MAAM;AAAA,QACN,aAAa,SAAS,mBAAmB,EAAE;AAAA,QAC3C,YAAY;AAAA,QACZ,eAAe;AAAA,QACf;AAAA,MACF;AAAA,IACF,OAAO;AAEL,aAAO;AAAA,QACL,MAAM;AAAA,QACN,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ,eAAe;AAAA,QACf;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,cAAc,QAAkC;AACtD,UAAM,EAAE,MAAM,SAAS,WAAW,IAAI;AAGtC,QAAI,SAAS,QAAQ;AACnB,UAAI,QAAQ,KAAK;AACf,cAAM,IAAI,MAAM,2DAA2D;AAAA,MAC7E;AACA,UAAI,QAAQ,UAAU,QAAW;AAC/B,cAAM,IAAI,MAAM,6DAA6D;AAAA,MAC/E;AACA,UAAI,OAAO,YAAY;AACrB,cAAM,IAAI,MAAM,yEAAyE;AAAA,MAC3F;AAAA,IACF;AAGA,QAAI,SAAS,OAAO;AAClB,UAAI,OAAO,YAAY;AACrB,cAAM,IAAI,MAAM,oEAAoE;AAAA,MACtF;AACA,UAAI,OAAO,gBAAgB,QAAW;AACpC,cAAM,IAAI,MAAM,oEAAoE;AAAA,MACtF;AAAA,IACF;AAIA,QAAI,QAAQ,UAAU,UAAa,YAAY;AAC7C,YAAM,IAAI,MAAM,oGAAoG;AAAA,IACtH;AAAA,EAGF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,qBAAqB,QAA2C;AAC5E,UAAM,aAAa,OAAO,cAAc,OAAO,cAAc;AAC7D,QAAI,CAAC,YAAY;AACf,YAAM,IAAI,MAAM,iCAAiC;AAAA,IACnD;AACA,UAAM,EAAE,OAAO,OAAO,IAAI,OAAO;AAGjC,QAAI,cAA2B,MAAM,KAAK,iBAAiB,yBAAyB,UAAU;AAG9F,QAAI,YAAY,SAAS,YAAY,YAAY,YAAY;AAC3D,YAAM,EAAE,mBAAmB,IAAI,MAAM,OAAO,mBAAiB;AAC7D,YAAM,kBAAkB,mBAAmB,YAAY,UAAU;AACjE,UAAI,oBAAoB,MAAM;AAC5B,sBAAc;AAAA,UACZ,GAAG;AAAA,UACH,QAAQ;AAAA;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAGA,WAAO,KAAK,kCAAkC,UAAU,EAAE;AAG1D,QAAI,CAAC,OAAO;AACV,YAAM,kBAAkB,MAAM,mBAAmB,yBAAyB,IAAI;AAC9E,UAAI,CAAC,iBAAiB;AACpB,eAAO,KAAK,mBAAmB;AAC/B;AAAA,MACF;AAAA,IACF;AAIA,UAAM,KAAK,sBAAsB;AACjC,QAAI,CAAC,KAAK,iBAAiB;AACzB,YAAM,IAAI,MAAM,sCAAsC;AAAA,IACxD;AACA,UAAM,gBAAgB,MAAM,KAAK,gBAAgB,gBAAgB,aAAa;AAAA,MAC5E,QAAQ,UAAU;AAAA,MAClB,OAAO,SAAS;AAAA,MAChB,cAAc,SAAS;AAAA;AAAA,MACvB,cAAc;AAAA,IAChB,CAAC;AAGD,SAAK,qBAAqB,aAAa;AAGvC,QAAI,cAAc,WAAW,CAAC,SAAS,cAAc,YAAY;AAC/D,YAAM,gBAAgB,MAAM,mBAAmB,+BAA+B,IAAI;AAClF,UAAI,eAAe;AACjB,cAAM,KAAK,uBAAuB,cAAc,YAAY,EAAE,OAAO,SAAS,OAAO,QAAQ,UAAU,MAAM,CAAC;AAAA,MAChH;AAAA,IACF;AAGA,QAAI,cAAc,SAAS;AACzB,aAAO,QAAQ,gCAAgC;AAAA,IACjD,OAAO;AACL,aAAO,KAAK,mDAAmD;AAAA,IACjE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,uBACZ,YACA,SACe;AACf,QAAI;AACF,YAAM,KAAK,sBAAsB;AACjC,UAAI,CAAC,KAAK,iBAAiB;AACzB,cAAM,IAAI,MAAM,sCAAsC;AAAA,MACxD;AACA,YAAM,KAAK,gBAAgB,aAAa,YAAY,OAAO;AAC3D,aAAO,QAAQ,mBAAmB,UAAU,EAAE;AAAA,IAChD,SAAS,OAAO;AACd,UAAI,iBAAiB,OAAO;AAC1B,eAAO,MAAM,4BAA4B,MAAM,OAAO,EAAE;AAAA,MAC1D;AAAA,IAEF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAAqB,QAA6B;AACxD,WAAO,KAAK,qBAAqB;AAEjC,WAAO,WAAW,QAAQ,QAAM;AAC9B,YAAM,SAAS,GAAG,UAAU,WAAM;AAClC,YAAM,UAAU,GAAG,QAAQ,GAAG,GAAG,OAAO,KAAK,GAAG,KAAK,KAAK,GAAG;AAE7D,UAAI,GAAG,SAAS;AACd,eAAO,KAAK,KAAK,MAAM,IAAI,OAAO,EAAE;AAAA,MACtC,OAAO;AACL,eAAO,MAAM,KAAK,MAAM,IAAI,OAAO,EAAE;AAAA,MACvC;AAAA,IACF,CAAC;AAED,QAAI,OAAO,OAAO,SAAS,GAAG;AAC5B,aAAO,KAAK,GAAG,OAAO,OAAO,MAAM,mCAAmC;AAAA,IACxE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,oBAAoB,QAA2C;AAC3E,UAAM,cAAc,OAAO;AAC3B,QAAI,gBAAgB,QAAW;AAC7B,YAAM,IAAI,MAAM,yCAAyC;AAAA,IAC3D;AAEA,UAAM,EAAE,OAAO,OAAO,IAAI,OAAO;AAEjC,WAAO,KAAK,iDAAiD,WAAW,KAAK;AAG7E,UAAM,YAAY,MAAM,KAAK,mBAAmB,cAAc;AAC9D,UAAM,oBAAoB,UAAU,OAAO,QAAM;AAC/C,YAAM,OAAO,GAAG,KAAK,YAAY;AACjC,YAAM,SAAS,OAAO,WAAW;AAKjC,YAAM,UAAU,IAAI,OAAO,WAAW,MAAM,SAAS;AACrD,aAAO,QAAQ,KAAK,IAAI;AAAA,IAC1B,CAAC;AAED,QAAI,kBAAkB,WAAW,GAAG;AAClC,aAAO,KAAK,2CAA2C,WAAW,EAAE;AACpE,aAAO,KAAK,2CAA2C,WAAW,SAAS,WAAW,WAAW,WAAW,QAAQ;AACpH;AAAA,IACF;AAGA,UAAM,UACJ,kBAAkB,IAAI,SAAO;AAAA,MAC3B,YAAY,GAAG;AAAA,MACf,aAAa;AAAA,MACb,cAAc,GAAG;AAAA,IACnB,EAAE;AAGJ,WAAO,KAAK,SAAS,QAAQ,MAAM,qCAAqC,WAAW,GAAG;AACtF,eAAW,UAAU,SAAS;AAC5B,aAAO,KAAK,eAAQ,OAAO,UAAU,KAAK,OAAO,YAAY,GAAG;AAAA,IAClE;AAGA,QAAI,CAAC,OAAO;AACV,YAAM,iBAAiB,MAAM;AAAA,QAC3B,UAAU,QAAQ,MAAM;AAAA,QACxB;AAAA,MACF;AACA,UAAI,CAAC,gBAAgB;AACnB,eAAO,KAAK,mBAAmB;AAC/B;AAAA,MACF;AAAA,IACF;AAGA,QAAI,mBAAmB;AACvB,QAAI,kBAAkB;AACtB,UAAM,8BAAwC,CAAC;AAC/C,QAAI,SAAS;AAEb,eAAW,UAAU,SAAS;AAC5B,aAAO,KAAK,wBAAwB,OAAO,UAAU,EAAE;AAGvD,UAAI;AAGF,cAAM,cAA2B;AAAA,UAC/B,MAAM;AAAA,UACN,QAAQ;AAAA;AAAA,UACR,YAAY,OAAO;AAAA,UACnB,eAAe,OAAO,WAAW;AAAA,QACnC;AAEA,cAAM,KAAK,sBAAsB;AACjC,YAAI,CAAC,KAAK,iBAAiB;AACzB,gBAAM,IAAI,MAAM,sCAAsC;AAAA,QACxD;AACA,cAAM,SAAS,MAAM,KAAK,gBAAgB,gBAAgB,aAAa;AAAA,UACrE,QAAQ,UAAU;AAAA,UAClB,OAAO,SAAS;AAAA,UAChB,cAAc;AAAA;AAAA,UACd,cAAc;AAAA,QAChB,CAAC;AAED,YAAI,OAAO,SAAS;AAClB;AACA,iBAAO,QAAQ,uBAAuB,OAAO,UAAU,EAAE;AAGzD,gBAAM,cAAc,OAAO,WAAW,KAAK,QAAM,GAAG,SAAS,UAAU;AACvE,cAAI,2CAAa,SAAS;AAExB,kBAAM,oBAAoB,OAAO;AACjC,wCAA4B,KAAK,iBAAiB;AAAA,UACpD;AAAA,QACF,OAAO;AACL;AACA,iBAAO,MAAM,gCAAgC,OAAO,UAAU,EAAE;AAAA,QAClE;AAAA,MACF,SAAS,OAAO;AACd;AACA,cAAM,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AACxD,eAAO,MAAM,gCAAgC,MAAM,EAAE;AACrD;AAAA,MACF;AAGA,UAAI;AACF,cAAM,KAAK,sBAAsB;AACjC,YAAI,CAAC,KAAK,iBAAiB;AACzB,gBAAM,IAAI,MAAM,sCAAsC;AAAA,QACxD;AACA,cAAM,KAAK,gBAAgB,aAAa,OAAO,YAAY;AAAA,UACzD,OAAO,SAAS;AAAA,UAChB,QAAQ,UAAU;AAAA,QACpB,CAAC;AACD;AACA,eAAO,QAAQ,qBAAqB,OAAO,UAAU,EAAE;AAAA,MACzD,SAAS,OAAO;AAEd,cAAM,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACpE,YAAI,OAAO,SAAS,kBAAkB,GAAG;AACvC,iBAAO,KAAK,8CAA8C;AAC1D,iBAAO,KAAK,gCAAgC;AAAA,QAC9C,OAAO;AAEL,iBAAO,MAAM,8BAA8B,MAAM,EAAE;AAAA,QACrD;AAAA,MACF;AAAA,IACF;AAGA,WAAO,QAAQ,mCAAmC,WAAW,GAAG;AAChE,WAAO,KAAK,mCAA4B,gBAAgB,EAAE;AAC1D,WAAO,KAAK,kCAA2B,eAAe,EAAE;AACxD,QAAI,4BAA4B,SAAS,GAAG;AAE1C,aAAO,KAAK,iDAAqC,4BAA4B,KAAK,IAAI,CAAC,EAAE;AAAA,IAC3F;AACA,QAAI,SAAS,GAAG;AACd,aAAO,KAAK,gCAA2B,MAAM,EAAE;AAAA,IACjD;AAAA,EACF;AACF;","names":["numericPattern"]}
1
+ {"version":3,"sources":["../src/commands/cleanup.ts"],"sourcesContent":["import { logger } from '../utils/logger.js'\nimport { GitWorktreeManager } from '../lib/GitWorktreeManager.js'\nimport { ResourceCleanup } from '../lib/ResourceCleanup.js'\nimport { ProcessManager } from '../lib/process/ProcessManager.js'\nimport { DatabaseManager } from '../lib/DatabaseManager.js'\nimport { EnvironmentManager } from '../lib/EnvironmentManager.js'\nimport { CLIIsolationManager } from '../lib/CLIIsolationManager.js'\nimport { SettingsManager } from '../lib/SettingsManager.js'\nimport { promptConfirmation } from '../utils/prompt.js'\nimport { IdentifierParser } from '../utils/IdentifierParser.js'\nimport { loadEnvIntoProcess } from '../utils/env.js'\nimport { createNeonProviderFromSettings } from '../utils/neon-helpers.js'\nimport { LoomManager } from '../lib/LoomManager.js'\nimport type { CleanupOptions } from '../types/index.js'\nimport type { CleanupResult } from '../types/cleanup.js'\nimport type { ParsedInput } from './start.js'\n\n/**\n * Input structure for CleanupCommand.execute()\n */\nexport interface CleanupCommandInput {\n identifier?: string\n options: CleanupOptions\n}\n\n/**\n * Parsed and validated cleanup command input\n * Mode determines which cleanup operation to perform\n */\nexport interface ParsedCleanupInput {\n mode: 'list' | 'single' | 'issue' | 'all'\n identifier?: string\n issueNumber?: string | number\n branchName?: string\n originalInput?: string\n options: CleanupOptions\n}\n\n/**\n * Manages cleanup command execution with option parsing and validation\n * Follows the command pattern established by StartCommand\n *\n * This implementation handles ONLY parsing, validation, and mode determination.\n * Actual cleanup operations are deferred to subsequent sub-issues.\n */\nexport class CleanupCommand {\n private readonly gitWorktreeManager: GitWorktreeManager\n private resourceCleanup?: ResourceCleanup\n private loomManager?: import('../lib/LoomManager.js').LoomManager\n private readonly identifierParser: IdentifierParser\n\n constructor(\n gitWorktreeManager?: GitWorktreeManager,\n resourceCleanup?: ResourceCleanup\n ) {\n // Load environment variables first\n const envResult = loadEnvIntoProcess()\n if (envResult.error) {\n logger.debug(`Environment loading warning: ${envResult.error.message}`)\n }\n if (envResult.parsed) {\n logger.debug(`Loaded ${Object.keys(envResult.parsed).length} environment variables`)\n }\n\n this.gitWorktreeManager = gitWorktreeManager ?? new GitWorktreeManager()\n\n // Initialize ResourceCleanup with DatabaseManager and CLIIsolationManager\n // ResourceCleanup will be initialized lazily with proper configuration\n if (resourceCleanup) {\n this.resourceCleanup = resourceCleanup\n }\n\n // Initialize IdentifierParser for pattern-based detection\n this.identifierParser = new IdentifierParser(this.gitWorktreeManager)\n }\n\n /**\n * Lazy initialization of ResourceCleanup and LoomManager with properly configured DatabaseManager\n */\n private async ensureResourceCleanup(): Promise<void> {\n if (this.resourceCleanup && this.loomManager) {\n return\n }\n\n const settingsManager = new SettingsManager()\n const settings = await settingsManager.loadSettings()\n const databaseUrlEnvVarName = settings.capabilities?.database?.databaseUrlEnvVarName ?? 'DATABASE_URL'\n\n const environmentManager = new EnvironmentManager()\n const neonProvider = createNeonProviderFromSettings(settings)\n const databaseManager = new DatabaseManager(neonProvider, environmentManager, databaseUrlEnvVarName)\n const cliIsolationManager = new CLIIsolationManager()\n\n this.resourceCleanup ??= new ResourceCleanup(\n this.gitWorktreeManager,\n new ProcessManager(),\n databaseManager,\n cliIsolationManager\n )\n\n // Initialize LoomManager if not provided (for child loom detection)\n if (!this.loomManager) {\n const { GitHubService } = await import('../lib/GitHubService.js')\n const { ClaudeContextManager } = await import('../lib/ClaudeContextManager.js')\n const { ProjectCapabilityDetector } = await import('../lib/ProjectCapabilityDetector.js')\n const { DefaultBranchNamingService } = await import('../lib/BranchNamingService.js')\n\n this.loomManager = new LoomManager(\n this.gitWorktreeManager,\n new GitHubService(),\n new DefaultBranchNamingService({ useClaude: true }),\n environmentManager,\n new ClaudeContextManager(),\n new ProjectCapabilityDetector(),\n cliIsolationManager,\n settingsManager,\n databaseManager\n )\n }\n }\n\n /**\n * Check for child looms and exit gracefully if any exist\n * Always checks the TARGET loom (the one being cleaned up), not the current directory's loom\n *\n * @param parsed - The parsed input identifying the loom being cleaned up\n */\n private async checkForChildLooms(parsed: ParsedCleanupInput): Promise<void> {\n await this.ensureResourceCleanup()\n if (!this.loomManager) {\n throw new Error('Failed to initialize LoomManager')\n }\n\n // Determine which branch is being cleaned up based on parsed input\n let targetBranch: string | undefined\n\n if (parsed.branchName) {\n targetBranch = parsed.branchName\n } else if (parsed.mode === 'issue' && parsed.issueNumber !== undefined) {\n // For issues, try to find the worktree by issue number to get the branch name\n const worktree = await this.gitWorktreeManager.findWorktreeForIssue(parsed.issueNumber)\n targetBranch = worktree?.branch\n }\n\n // If we can't determine the target branch, skip the check\n if (!targetBranch) {\n logger.debug(`Cannot determine target branch for child loom check`)\n return\n }\n\n // Check if the TARGET loom has any child looms\n const hasChildLooms = await this.loomManager.checkAndWarnChildLooms(targetBranch)\n if (hasChildLooms) {\n logger.error('Cannot cleanup loom while child looms exist. Please finish child looms first.')\n process.exit(1)\n }\n }\n\n /**\n * Main entry point for the cleanup command\n * Parses input, validates options, and determines operation mode\n */\n public async execute(input: CleanupCommandInput): Promise<void> {\n try {\n // Step 1: Parse input and determine mode\n const parsed = this.parseInput(input)\n\n // Step 2: Validate option combinations\n this.validateInput(parsed)\n\n // Step 2.5: Check for child looms AFTER parsing input\n // This ensures we only block when cleaning the CURRENT loom (parent), not a child\n await this.checkForChildLooms(parsed)\n\n // Step 3: Execute based on mode\n logger.info(`Cleanup mode: ${parsed.mode}`)\n\n if (parsed.mode === 'single') {\n await this.executeSingleCleanup(parsed)\n } else if (parsed.mode === 'list') {\n logger.info('Would list all worktrees') // TODO: Implement in Sub-issue #2\n logger.success('Command parsing and validation successful')\n } else if (parsed.mode === 'all') {\n logger.info('Would remove all worktrees') // TODO: Implement in Sub-issue #5\n logger.success('Command parsing and validation successful')\n } else if (parsed.mode === 'issue') {\n await this.executeIssueCleanup(parsed)\n }\n } catch (error) {\n if (error instanceof Error) {\n logger.error(`${error.message}`)\n } else {\n logger.error('An unknown error occurred')\n }\n throw error\n }\n }\n\n /**\n * Parse input to determine cleanup mode and extract relevant data\n * Implements auto-detection: numeric input = issue number, non-numeric = branch name\n *\n * @private\n */\n private parseInput(input: CleanupCommandInput): ParsedCleanupInput {\n const { identifier, options } = input\n\n // Trim identifier if present\n const trimmedIdentifier = identifier?.trim() ?? undefined\n\n // Mode: List (takes priority - it's informational only)\n if (options.list) {\n const result: ParsedCleanupInput = {\n mode: 'list',\n options\n }\n if (trimmedIdentifier) {\n result.identifier = trimmedIdentifier\n }\n return result\n }\n\n // Mode: All (remove everything)\n if (options.all) {\n const result: ParsedCleanupInput = {\n mode: 'all',\n options\n }\n if (trimmedIdentifier) {\n result.identifier = trimmedIdentifier\n }\n if (options.issue !== undefined) {\n result.issueNumber = options.issue\n }\n return result\n }\n\n // Mode: Explicit issue number via --issue flag\n if (options.issue !== undefined) {\n // Need to determine if identifier is branch or numeric to set branchName\n if (trimmedIdentifier) {\n const numericPattern = /^[0-9]+$/\n if (!numericPattern.test(trimmedIdentifier)) {\n // Identifier is a branch name with explicit --issue flag\n return {\n mode: 'issue',\n issueNumber: options.issue,\n branchName: trimmedIdentifier,\n identifier: trimmedIdentifier,\n originalInput: trimmedIdentifier,\n options\n }\n }\n }\n const result: ParsedCleanupInput = {\n mode: 'issue',\n issueNumber: options.issue,\n options\n }\n if (trimmedIdentifier) {\n result.identifier = trimmedIdentifier\n }\n return result\n }\n\n // Mode: Auto-detect from identifier\n if (!trimmedIdentifier) {\n throw new Error('Missing required argument: identifier. Use --all to remove all worktrees or --list to list them.')\n }\n\n // Auto-detection: Check if identifier is purely numeric\n // Pattern from bash script line 364: ^[0-9]+$\n const numericPattern = /^[0-9]+$/\n if (numericPattern.test(trimmedIdentifier)) {\n // Numeric input = issue number\n return {\n mode: 'issue',\n issueNumber: parseInt(trimmedIdentifier, 10),\n identifier: trimmedIdentifier,\n originalInput: trimmedIdentifier,\n options\n }\n } else {\n // Non-numeric = branch name\n return {\n mode: 'single',\n branchName: trimmedIdentifier,\n identifier: trimmedIdentifier,\n originalInput: trimmedIdentifier,\n options\n }\n }\n }\n\n /**\n * Validate parsed input for option conflicts\n * Throws descriptive errors for invalid option combinations\n *\n * @private\n */\n private validateInput(parsed: ParsedCleanupInput): void {\n const { mode, options, branchName } = parsed\n\n // Conflict: --list is informational only, incompatible with destructive operations\n if (mode === 'list') {\n if (options.all) {\n throw new Error('Cannot use --list with --all (list is informational only)')\n }\n if (options.issue !== undefined) {\n throw new Error('Cannot use --list with --issue (list is informational only)')\n }\n if (parsed.identifier) {\n throw new Error('Cannot use --list with a specific identifier (list shows all worktrees)')\n }\n }\n\n // Conflict: --all removes everything, can't combine with specific identifier or --issue\n if (mode === 'all') {\n if (parsed.identifier) {\n throw new Error('Cannot use --all with a specific identifier. Use one or the other.')\n }\n if (parsed.issueNumber !== undefined) {\n throw new Error('Cannot use --all with a specific identifier. Use one or the other.')\n }\n }\n\n // Conflict: explicit --issue flag with branch name identifier\n // (This prevents confusion when user provides both)\n if (options.issue !== undefined && branchName) {\n throw new Error('Cannot use --issue flag with branch name identifier. Use numeric identifier or --issue flag alone.')\n }\n\n // Note: --force and --dry-run are compatible with all modes (no conflicts)\n }\n\n /**\n * Execute cleanup for single worktree\n * Implements two-stage confirmation: worktree removal, then branch deletion\n * Uses IdentifierParser for pattern-based detection without GitHub API calls\n */\n private async executeSingleCleanup(parsed: ParsedCleanupInput): Promise<void> {\n const identifier = parsed.branchName ?? parsed.identifier ?? ''\n if (!identifier) {\n throw new Error('No identifier found for cleanup')\n }\n const { force, dryRun } = parsed.options\n\n // Step 1: Parse identifier using pattern-based detection\n let parsedInput: ParsedInput = await this.identifierParser.parseForPatternDetection(identifier)\n\n // If type is 'branch', try to extract issue number for CLI symlink cleanup\n if (parsedInput.type === 'branch' && parsedInput.branchName) {\n const { extractIssueNumber } = await import('../utils/git.js')\n const extractedNumber = extractIssueNumber(parsedInput.branchName)\n if (extractedNumber !== null) {\n parsedInput = {\n ...parsedInput,\n number: extractedNumber // Add number for CLI symlink cleanup\n }\n }\n }\n\n // Step 2: Display worktree details\n logger.info(`Preparing to cleanup worktree: ${identifier}`)\n\n // Step 3: Confirmation - worktree removal\n if (!force) {\n const confirmWorktree = await promptConfirmation('Remove this worktree?', true)\n if (!confirmWorktree) {\n logger.info('Cleanup cancelled')\n return\n }\n }\n\n // Step 4: Execute worktree cleanup (includes safety validation)\n // With --force, delete branch automatically; otherwise handle separately\n await this.ensureResourceCleanup()\n if (!this.resourceCleanup) {\n throw new Error('Failed to initialize ResourceCleanup')\n }\n const cleanupResult = await this.resourceCleanup.cleanupWorktree(parsedInput, {\n dryRun: dryRun ?? false,\n force: force ?? false,\n deleteBranch: force ?? false, // Delete branch immediately if --force, otherwise prompt later\n keepDatabase: false,\n })\n\n // Step 5: Report cleanup results\n this.reportCleanupResults(cleanupResult)\n\n // Step 6: Second confirmation - branch deletion (only if not forced and worktree cleanup succeeded)\n if (cleanupResult.success && !force && cleanupResult.branchName) {\n const confirmBranch = await promptConfirmation('Also delete the git branch?', true)\n if (confirmBranch) {\n await this.deleteBranchForCleanup(cleanupResult.branchName, { force: force ?? false, dryRun: dryRun ?? false })\n }\n }\n\n // Final success message\n if (cleanupResult.success) {\n logger.success('Cleanup completed successfully')\n } else {\n logger.warn('Cleanup completed with errors - see details above')\n }\n }\n\n /**\n * Delete branch as part of cleanup operation\n */\n private async deleteBranchForCleanup(\n branchName: string,\n options: { force?: boolean; dryRun?: boolean }\n ): Promise<void> {\n try {\n await this.ensureResourceCleanup()\n if (!this.resourceCleanup) {\n throw new Error('Failed to initialize ResourceCleanup')\n }\n await this.resourceCleanup.deleteBranch(branchName, options)\n logger.success(`Branch deleted: ${branchName}`)\n } catch (error) {\n if (error instanceof Error) {\n logger.error(`Failed to delete branch: ${error.message}`)\n }\n // Don't throw - branch deletion is optional/secondary operation\n }\n }\n\n /**\n * Report cleanup operation results to user\n */\n private reportCleanupResults(result: CleanupResult): void {\n logger.info('Cleanup operations:')\n\n result.operations.forEach(op => {\n const status = op.success ? '✓' : '✗'\n const message = op.error ? `${op.message}: ${op.error}` : op.message\n\n if (op.success) {\n logger.info(` ${status} ${message}`)\n } else {\n logger.error(` ${status} ${message}`)\n }\n })\n\n if (result.errors.length > 0) {\n logger.warn(`${result.errors.length} error(s) occurred during cleanup`)\n }\n }\n\n /**\n * Execute cleanup for all worktrees associated with an issue or PR number\n * Searches for worktrees by their path patterns (e.g., issue-25, pr-25, 25-feature, _pr_25)\n * Implements bash cleanup-worktree.sh remove_worktrees_by_issue() (lines 157-242)\n */\n private async executeIssueCleanup(parsed: ParsedCleanupInput): Promise<void> {\n const issueNumber = parsed.issueNumber\n if (issueNumber === undefined) {\n throw new Error('No issue/PR number provided for cleanup')\n }\n\n const { force, dryRun } = parsed.options\n\n logger.info(`Finding worktrees related to GitHub issue/PR #${issueNumber}...`)\n\n // Step 1: Get all worktrees and filter by path pattern\n const worktrees = await this.gitWorktreeManager.listWorktrees()\n const matchingWorktrees = worktrees.filter(wt => {\n const path = wt.path.toLowerCase()\n // Lowercase for case-insensitive matching (Linear IDs are uppercase like MARK-1)\n const idStr = String(issueNumber).toLowerCase()\n\n // Check if path contains the identifier with proper word boundaries\n // Matches: issue-25, pr-25, 25-feature, _pr_25, issue-mark-1, etc.\n // Uses word boundary or common separators (-, _, /) for alphanumeric IDs\n const pattern = new RegExp(`(?:^|[/_-])${idStr}(?:[/_-]|$)`)\n return pattern.test(path)\n })\n\n if (matchingWorktrees.length === 0) {\n logger.warn(`No worktrees found for GitHub issue/PR #${issueNumber}`)\n logger.info(`Searched for worktree paths containing: ${issueNumber}, _pr_${issueNumber}, issue-${issueNumber}, etc.`)\n return\n }\n\n // Step 2: Build targets list from matching worktrees\n const targets: Array<{ branchName: string; hasWorktree: boolean; worktreePath?: string }> =\n matchingWorktrees.map(wt => ({\n branchName: wt.branch,\n hasWorktree: true,\n worktreePath: wt.path\n }))\n\n // Step 3: Display preview\n logger.info(`Found ${targets.length} worktree(s) related to issue/PR #${issueNumber}:`)\n for (const target of targets) {\n logger.info(` 🌿 ${target.branchName} (${target.worktreePath})`)\n }\n\n // Step 4: Batch confirmation (unless --force)\n if (!force) {\n const confirmCleanup = await promptConfirmation(\n `Remove ${targets.length} worktree(s)?`,\n true\n )\n if (!confirmCleanup) {\n logger.info('Cleanup cancelled')\n return\n }\n }\n\n // Step 5: Process each target sequentially\n let worktreesRemoved = 0\n let branchesDeleted = 0\n const databaseBranchesDeletedList: string[] = []\n let failed = 0\n\n for (const target of targets) {\n logger.info(`Processing worktree: ${target.branchName}`)\n\n // Cleanup worktree using ResourceCleanup with ParsedInput\n try {\n // Use the known issue number directly instead of parsing from branch name\n // This ensures CLI symlinks (created with issue number) are properly cleaned up\n const parsedInput: ParsedInput = {\n type: 'issue',\n number: issueNumber, // Use the known issue number, not parsed from branch\n branchName: target.branchName,\n originalInput: String(issueNumber)\n }\n\n await this.ensureResourceCleanup()\n if (!this.resourceCleanup) {\n throw new Error('Failed to initialize ResourceCleanup')\n }\n const result = await this.resourceCleanup.cleanupWorktree(parsedInput, {\n dryRun: dryRun ?? false,\n force: force ?? false,\n deleteBranch: false, // Handle branch deletion separately\n keepDatabase: false\n })\n\n if (result.success) {\n worktreesRemoved++\n logger.success(` Worktree removed: ${target.branchName}`)\n\n // Check if database branch was actually deleted (use explicit deleted field)\n const dbOperation = result.operations.find(op => op.type === 'database')\n if (dbOperation?.deleted) {\n // Get branch name from result or use the target branch name\n const deletedBranchName = target.branchName\n databaseBranchesDeletedList.push(deletedBranchName)\n }\n } else {\n failed++\n logger.error(` Failed to remove worktree: ${target.branchName}`)\n }\n } catch (error) {\n failed++\n const errMsg = error instanceof Error ? error.message : 'Unknown error'\n logger.error(` Failed to remove worktree: ${errMsg}`)\n continue // Continue with next worktree even if this one failed\n }\n\n // Step 6: Delete branch\n try {\n await this.ensureResourceCleanup()\n if (!this.resourceCleanup) {\n throw new Error('Failed to initialize ResourceCleanup')\n }\n await this.resourceCleanup.deleteBranch(target.branchName, {\n force: force ?? false,\n dryRun: dryRun ?? false\n })\n branchesDeleted++\n logger.success(` Branch deleted: ${target.branchName}`)\n } catch (error) {\n // Don't count unmerged branch as failure - it's a safety feature\n const errMsg = error instanceof Error ? error.message : String(error)\n if (errMsg.includes('not fully merged')) {\n logger.warn(` Branch not fully merged, skipping deletion`)\n logger.warn(` Use --force to delete anyway`)\n } else {\n // Other errors are real failures\n logger.error(` Failed to delete branch: ${errMsg}`)\n }\n }\n }\n\n // Step 7: Report statistics\n logger.success(`Completed cleanup for issue/PR #${issueNumber}:`)\n logger.info(` 📁 Worktrees removed: ${worktreesRemoved}`)\n logger.info(` 🌿 Branches deleted: ${branchesDeleted}`)\n if (databaseBranchesDeletedList.length > 0) {\n // Display branch names in the format requested\n logger.info(` 🗂️ Database branches deleted: ${databaseBranchesDeletedList.join(', ')}`)\n }\n if (failed > 0) {\n logger.warn(` ❌ Failed operations: ${failed}`)\n }\n }\n}\n"],"mappings":"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","names":["numericPattern"]}
package/dist/cli.js CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  EnvironmentManager,
10
10
  LoomManager,
11
11
  ResourceCleanup
12
- } from "./chunk-5EF7Z346.js";
12
+ } from "./chunk-HBYZH6GD.js";
13
13
  import {
14
14
  IdentifierParser,
15
15
  loadEnvIntoProcess
@@ -22,7 +22,7 @@ import {
22
22
  } from "./chunk-JQFO7QQN.js";
23
23
  import {
24
24
  ShellCompletion
25
- } from "./chunk-VAYCCUXW.js";
25
+ } from "./chunk-4E4LD3QR.js";
26
26
  import {
27
27
  getConfiguredRepoFromSettings,
28
28
  getEffectivePRTargetRemote,
@@ -31,7 +31,7 @@ import {
31
31
  } from "./chunk-PA6Q6AWM.js";
32
32
  import {
33
33
  IssueEnhancementService
34
- } from "./chunk-47KSHUCR.js";
34
+ } from "./chunk-ZBQVSHVT.js";
35
35
  import {
36
36
  AgentManager
37
37
  } from "./chunk-OC4H6HJD.js";
@@ -40,10 +40,10 @@ import {
40
40
  } from "./chunk-YETJNRQM.js";
41
41
  import {
42
42
  MergeManager
43
- } from "./chunk-AWOFAD5O.js";
43
+ } from "./chunk-IXKLYTWO.js";
44
44
  import {
45
45
  GitWorktreeManager
46
- } from "./chunk-4HHRTA7Q.js";
46
+ } from "./chunk-TSKY3JI7.js";
47
47
  import {
48
48
  detectPackageManager,
49
49
  installDependencies,
@@ -51,16 +51,16 @@ import {
51
51
  } from "./chunk-ZT3YZB4K.js";
52
52
  import {
53
53
  ClaudeContextManager
54
- } from "./chunk-C5QCTEQK.js";
55
- import "./chunk-FIAT22G7.js";
54
+ } from "./chunk-XPKDPZ5D.js";
55
+ import "./chunk-U5QDY7ZD.js";
56
56
  import {
57
57
  detectClaudeCli,
58
58
  launchClaude
59
- } from "./chunk-XXV3UFZL.js";
59
+ } from "./chunk-ZWFBBPJI.js";
60
60
  import "./chunk-WEN5C5DM.js";
61
61
  import {
62
62
  DefaultBranchNamingService
63
- } from "./chunk-3KATJIKO.js";
63
+ } from "./chunk-INW24J2W.js";
64
64
  import {
65
65
  ProjectCapabilityDetector
66
66
  } from "./chunk-EBISESAP.js";
@@ -73,13 +73,13 @@ import {
73
73
  } from "./chunk-GYCR2LOU.js";
74
74
  import {
75
75
  SettingsManager
76
- } from "./chunk-ML3NRPNB.js";
76
+ } from "./chunk-O5OH5MRX.js";
77
77
  import {
78
78
  executeGitCommand,
79
79
  extractIssueNumber,
80
80
  findMainWorktreePathWithSettings,
81
81
  pushBranchToRemote
82
- } from "./chunk-MAVL6PJF.js";
82
+ } from "./chunk-4BGK7T6X.js";
83
83
  import "./chunk-G2IEYOLQ.js";
84
84
  import {
85
85
  executeGhCommand
@@ -131,7 +131,7 @@ async function launchFirstRunSetup() {
131
131
  );
132
132
  const { waitForKeypress: waitForKeypress2 } = await import("./prompt-7INJ7YRU.js");
133
133
  await waitForKeypress2("Press any key to start configuration...");
134
- const { InitCommand } = await import("./init-G3T64SC4.js");
134
+ const { InitCommand } = await import("./init-L55Q73H4.js");
135
135
  const initCommand = new InitCommand();
136
136
  await initCommand.execute(
137
137
  "Help me configure iloom settings for this project. This is my first time using iloom here. Note: Your iloom command will execute once we are done with configuration changes."
@@ -520,7 +520,7 @@ var AddIssueCommand = class {
520
520
  /**
521
521
  * Execute the add-issue command workflow:
522
522
  * 1. Validate description format
523
- * 2. Enhance description with Claude AI
523
+ * 2. Enhance description with Claude Code
524
524
  * 3. Create GitHub issue
525
525
  * 4. Wait for keypress and open browser for review
526
526
  * 5. Return issue number
@@ -1154,7 +1154,7 @@ Fixes #${options.issueNumber}`;
1154
1154
  return { stagedFiles, unstagedFiles };
1155
1155
  }
1156
1156
  /**
1157
- * Generate commit message using Claude AI
1157
+ * Generate commit message using Claude Code
1158
1158
  * Claude examines the git repository directly via --add-dir option
1159
1159
  * Returns null if Claude unavailable or fails validation
1160
1160
  */
@@ -1719,7 +1719,7 @@ var FinishCommand = class {
1719
1719
  const neonProvider = createNeonProviderFromSettings(settings);
1720
1720
  const databaseManager = new DatabaseManager(neonProvider, environmentManager, databaseUrlEnvVarName);
1721
1721
  const cliIsolationManager = new CLIIsolationManager();
1722
- const { DefaultBranchNamingService: DefaultBranchNamingService2 } = await import("./BranchNamingService-3OQPRSWT.js");
1722
+ const { DefaultBranchNamingService: DefaultBranchNamingService2 } = await import("./BranchNamingService-OMWKUYMM.js");
1723
1723
  this.loomManager ??= new LoomManager(
1724
1724
  this.gitWorktreeManager,
1725
1725
  this.issueTracker,
@@ -2524,14 +2524,14 @@ async function autoLaunchInitForMultipleRemotes() {
2524
2524
  await waitForKeypress2("Press any key to start configuration...");
2525
2525
  logger.info("");
2526
2526
  try {
2527
- const { InitCommand } = await import("./init-G3T64SC4.js");
2527
+ const { InitCommand } = await import("./init-L55Q73H4.js");
2528
2528
  const initCommand = new InitCommand();
2529
2529
  const customInitialMessage = "Help me configure which git remote iloom should use for GitHub operations. I have multiple remotes and need to select the correct one.";
2530
2530
  await initCommand.execute(customInitialMessage);
2531
2531
  logger.info("");
2532
2532
  logger.info("Configuration complete! Continuing with your original command...");
2533
2533
  logger.info("");
2534
- const { SettingsManager: SettingsManager2 } = await import("./SettingsManager-WHHFGSL7.js");
2534
+ const { SettingsManager: SettingsManager2 } = await import("./SettingsManager-ZCWJ56WP.js");
2535
2535
  const settingsManager = new SettingsManager2();
2536
2536
  const settings = await settingsManager.loadSettings();
2537
2537
  const { hasMultipleRemotes: hasMultipleRemotes2 } = await import("./remote-VUNCQZ6J.js");
@@ -2593,7 +2593,7 @@ program.command("add-issue").alias("a").description("Create and enhance GitHub i
2593
2593
  });
2594
2594
  program.command("feedback").alias("f").description("Submit feedback/bug report to iloom-cli repository").argument("<description>", "Natural language description of feedback (>50 chars, >2 spaces)").option("--body <text>", "Body text for feedback (added after diagnostics)").action(async (description, options) => {
2595
2595
  try {
2596
- const { FeedbackCommand } = await import("./feedback-N4ECWIPF.js");
2596
+ const { FeedbackCommand } = await import("./feedback-W3BXTGIM.js");
2597
2597
  const command = new FeedbackCommand();
2598
2598
  const feedbackOptions = {};
2599
2599
  if (options.body !== void 0) {
@@ -2644,7 +2644,7 @@ program.command("finish").alias("dn").description("Merge work and cleanup worksp
2644
2644
  });
2645
2645
  program.command("rebase").description("Rebase current branch on main with Claude-assisted conflict resolution").option("-f, --force", "Skip confirmation prompts").option("-n, --dry-run", "Preview actions without executing").action(async (options) => {
2646
2646
  try {
2647
- const { RebaseCommand } = await import("./rebase-Q7GMM7EI.js");
2647
+ const { RebaseCommand } = await import("./rebase-C4WNCVGM.js");
2648
2648
  const command = new RebaseCommand();
2649
2649
  await command.execute(options);
2650
2650
  } catch (error) {
@@ -2656,7 +2656,7 @@ program.command("spin").alias("ignite").description("Launch Claude with auto-det
2656
2656
  new Option("--one-shot <mode>", "One-shot automation mode").choices(["default", "noReview", "bypassPermissions"]).default("default")
2657
2657
  ).action(async (options) => {
2658
2658
  try {
2659
- const { IgniteCommand } = await import("./ignite-VM64QO3J.js");
2659
+ const { IgniteCommand } = await import("./ignite-KVJEFXNO.js");
2660
2660
  const command = new IgniteCommand();
2661
2661
  await command.execute(options.oneShot ?? "default");
2662
2662
  } catch (error) {
@@ -2667,7 +2667,7 @@ program.command("spin").alias("ignite").description("Launch Claude with auto-det
2667
2667
  program.command("open").description("Open workspace in browser or run CLI tool").argument("[identifier]", "Issue number, PR number, or branch name (auto-detected if omitted)").allowUnknownOption().action(async (identifier, _options, command) => {
2668
2668
  try {
2669
2669
  const args = (command == null ? void 0 : command.args) ? command.args.slice(identifier ? 1 : 0) : [];
2670
- const { OpenCommand } = await import("./open-KXDXEKRZ.js");
2670
+ const { OpenCommand } = await import("./open-LNRZL3UU.js");
2671
2671
  const cmd = new OpenCommand();
2672
2672
  const input = identifier ? { identifier, args } : { args };
2673
2673
  await cmd.execute(input);
@@ -2679,7 +2679,7 @@ program.command("open").description("Open workspace in browser or run CLI tool")
2679
2679
  program.command("run").description("Run CLI tool or open workspace in browser").argument("[identifier]", "Issue number, PR number, or branch name (auto-detected if omitted)").allowUnknownOption().action(async (identifier, _options, command) => {
2680
2680
  try {
2681
2681
  const args = (command == null ? void 0 : command.args) ? command.args.slice(identifier ? 1 : 0) : [];
2682
- const { RunCommand } = await import("./run-PAWJJCSX.js");
2682
+ const { RunCommand } = await import("./run-IOGNIOYN.js");
2683
2683
  const cmd = new RunCommand();
2684
2684
  const input = identifier ? { identifier, args } : { args };
2685
2685
  await cmd.execute(input);
@@ -2690,7 +2690,7 @@ program.command("run").description("Run CLI tool or open workspace in browser").
2690
2690
  });
2691
2691
  program.command("cleanup").description("Remove workspaces").argument("[identifier]", "Branch name or issue number to cleanup (auto-detected)").option("-l, --list", "List all worktrees").option("-a, --all", "Remove all worktrees (interactive confirmation)").option("-i, --issue <number>", "Cleanup by issue number", parseInt).option("-f, --force", "Skip confirmations and force removal").option("--dry-run", "Show what would be done without doing it").action(async (identifier, options) => {
2692
2692
  try {
2693
- const { CleanupCommand } = await import("./cleanup-7RWLBSLE.js");
2693
+ const { CleanupCommand } = await import("./cleanup-3MONU4PU.js");
2694
2694
  const command = new CleanupCommand();
2695
2695
  const input = {
2696
2696
  options: options ?? {}
@@ -2738,7 +2738,7 @@ program.command("list").description("Show active workspaces").option("--json", "
2738
2738
  });
2739
2739
  program.command("init").alias("config").description("Initialize iloom configuration and setup shell autocomplete").argument("[prompt]", 'Custom initial message to send to Claude (defaults to "Help me configure iloom settings.")').action(async (prompt) => {
2740
2740
  try {
2741
- const { InitCommand } = await import("./init-G3T64SC4.js");
2741
+ const { InitCommand } = await import("./init-L55Q73H4.js");
2742
2742
  const command = new InitCommand();
2743
2743
  const trimmedPrompt = prompt == null ? void 0 : prompt.trim();
2744
2744
  const customPrompt = trimmedPrompt && trimmedPrompt.length > 0 ? trimmedPrompt : void 0;
@@ -2750,7 +2750,7 @@ program.command("init").alias("config").description("Initialize iloom configurat
2750
2750
  });
2751
2751
  program.command("contribute").description("Set up local development environment for contributing to iloom").action(async () => {
2752
2752
  try {
2753
- const { ContributeCommand } = await import("./contribute-BS2L4FZR.js");
2753
+ const { ContributeCommand } = await import("./contribute-UWJAGIG7.js");
2754
2754
  const command = new ContributeCommand();
2755
2755
  await command.execute();
2756
2756
  } catch (error) {
@@ -2771,7 +2771,7 @@ program.command("update").description("Update iloom-cli to the latest version").
2771
2771
  program.command("test-github").description("Test GitHub integration (Issue #3)").argument("<identifier>", "Issue number or PR number").option("--no-claude", "Skip Claude for branch name generation").action(async (identifier, options) => {
2772
2772
  try {
2773
2773
  const { GitHubService } = await import("./GitHubService-EBOETDIW.js");
2774
- const { DefaultBranchNamingService: DefaultBranchNamingService2 } = await import("./BranchNamingService-3OQPRSWT.js");
2774
+ const { DefaultBranchNamingService: DefaultBranchNamingService2 } = await import("./BranchNamingService-OMWKUYMM.js");
2775
2775
  logger.info("Testing GitHub Integration\n");
2776
2776
  const service = new GitHubService();
2777
2777
  const branchNaming = new DefaultBranchNamingService2({ useClaude: options.claude !== false });
@@ -2829,10 +2829,10 @@ program.command("test-github").description("Test GitHub integration (Issue #3)")
2829
2829
  });
2830
2830
  program.command("test-claude").description("Test Claude integration (Issue #10)").option("--detect", "Test Claude CLI detection").option("--version", "Get Claude CLI version").option("--branch <title>", "Test branch name generation with given title").option("--issue <number>", "Issue number for branch generation", "123").option("--launch <prompt>", "Launch Claude with a prompt (headless)").option("--interactive", "Launch Claude interactively (requires --launch)").option("--template <name>", "Test template loading").action(async (options) => {
2831
2831
  try {
2832
- const { detectClaudeCli: detectClaudeCli2, getClaudeVersion, generateBranchName, launchClaude: launchClaude2 } = await import("./claude-GOP6PFC7.js");
2832
+ const { detectClaudeCli: detectClaudeCli2, getClaudeVersion, generateBranchName, launchClaude: launchClaude2 } = await import("./claude-LUZ35IMK.js");
2833
2833
  const { PromptTemplateManager } = await import("./PromptTemplateManager-A52RUAMS.js");
2834
- const { ClaudeService } = await import("./ClaudeService-HG4VQ7AW.js");
2835
- const { ClaudeContextManager: ClaudeContextManager2 } = await import("./ClaudeContextManager-MUQSDY2E.js");
2834
+ const { ClaudeService } = await import("./ClaudeService-6CPK43N4.js");
2835
+ const { ClaudeContextManager: ClaudeContextManager2 } = await import("./ClaudeContextManager-3VXA6UPR.js");
2836
2836
  logger.info("Testing Claude Integration\n");
2837
2837
  if (options.detect) {
2838
2838
  logger.info("Detecting Claude CLI...");
@@ -2980,7 +2980,7 @@ program.command("test-webserver").description("Test if a web server is running o
2980
2980
  });
2981
2981
  program.command("test-git").description("Test Git integration - findMainWorktreePath() function (reads .iloom/settings.json)").action(async () => {
2982
2982
  try {
2983
- const { TestGitCommand } = await import("./test-git-3WDLNQCA.js");
2983
+ const { TestGitCommand } = await import("./test-git-J7I5MFYH.js");
2984
2984
  const command = new TestGitCommand();
2985
2985
  await command.execute();
2986
2986
  } catch (error) {
@@ -3006,7 +3006,7 @@ program.command("test-tabs").description("Test iTerm2 dual tab functionality - o
3006
3006
  });
3007
3007
  program.command("test-prefix").description("Test worktree prefix configuration - preview worktree paths (reads .iloom/settings.json)").action(async () => {
3008
3008
  try {
3009
- const { TestPrefixCommand } = await import("./test-prefix-EVGAWAJW.js");
3009
+ const { TestPrefixCommand } = await import("./test-prefix-ZCONBCBX.js");
3010
3010
  const command = new TestPrefixCommand();
3011
3011
  await command.execute();
3012
3012
  } catch (error) {
@@ -3020,7 +3020,7 @@ program.command("test-prefix").description("Test worktree prefix configuration -
3020
3020
  program.command("test-neon").description("Test Neon integration and debug configuration").action(async () => {
3021
3021
  var _a;
3022
3022
  try {
3023
- const { SettingsManager: SettingsManager2 } = await import("./SettingsManager-WHHFGSL7.js");
3023
+ const { SettingsManager: SettingsManager2 } = await import("./SettingsManager-ZCWJ56WP.js");
3024
3024
  const { createNeonProviderFromSettings: createNeonProviderFromSettings2 } = await import("./neon-helpers-WPUACUVC.js");
3025
3025
  logger.info("Testing Neon Integration\n");
3026
3026
  logger.info("1. Settings Configuration:");