@iloom/cli 0.3.3 → 0.4.0
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.
- package/README.md +13 -3
- package/dist/{BranchNamingService-A77VI6AI.js → BranchNamingService-TOM2KAUT.js} +4 -3
- package/dist/ClaudeContextManager-VEGJTS5E.js +16 -0
- package/dist/ClaudeService-ICSHJMQ5.js +15 -0
- package/dist/GitHubService-RPM27GWD.js +12 -0
- package/dist/{LoomLauncher-ZV3ZZIBA.js → LoomLauncher-SJBZFZXE.js} +25 -22
- package/dist/LoomLauncher-SJBZFZXE.js.map +1 -0
- package/dist/PromptTemplateManager-2TDZAUC6.js +9 -0
- package/dist/README.md +13 -3
- package/dist/{SettingsManager-I2LRCW2A.js → SettingsManager-FJFU6JJD.js} +7 -3
- package/dist/SettingsMigrationManager-EH3J2TCN.js +10 -0
- package/dist/{chunk-UJL4HI2R.js → chunk-3NFBZRPR.js} +2 -2
- package/dist/chunk-6UIGZD2N.js +20 -0
- package/dist/chunk-6UIGZD2N.js.map +1 -0
- package/dist/{chunk-RIEO2WML.js → chunk-74VMN2KC.js} +26 -2
- package/dist/chunk-74VMN2KC.js.map +1 -0
- package/dist/{chunk-OYF4VIFI.js → chunk-75B2HZZ5.js} +147 -22
- package/dist/chunk-75B2HZZ5.js.map +1 -0
- package/dist/{chunk-PGPI5LR4.js → chunk-ADDNFQJ4.js} +7 -21
- package/dist/chunk-ADDNFQJ4.js.map +1 -0
- package/dist/{chunk-AKUJXDNW.js → chunk-F4J6KEL6.js} +3 -3
- package/dist/{chunk-DLHA5VQ3.js → chunk-HD5SUKI2.js} +36 -179
- package/dist/chunk-HD5SUKI2.js.map +1 -0
- package/dist/chunk-HHDSIE72.js +667 -0
- package/dist/chunk-HHDSIE72.js.map +1 -0
- package/dist/{chunk-OXAM2WVC.js → chunk-HVGQP44L.js} +21 -1
- package/dist/chunk-HVGQP44L.js.map +1 -0
- package/dist/{chunk-RW54ZMBM.js → chunk-JJUPY5MM.js} +2 -2
- package/dist/{chunk-UAN4A3YU.js → chunk-KM3W7YQX.js} +11 -11
- package/dist/{chunk-3RUPPQRG.js → chunk-KO2FOMHL.js} +43 -2
- package/dist/{chunk-3RUPPQRG.js.map → chunk-KO2FOMHL.js.map} +1 -1
- package/dist/{chunk-2MAIX45J.js → chunk-LTNDJMTH.js} +104 -43
- package/dist/chunk-LTNDJMTH.js.map +1 -0
- package/dist/{chunk-2CXREBLZ.js → chunk-M5XUCTTJ.js} +8 -6
- package/dist/chunk-M5XUCTTJ.js.map +1 -0
- package/dist/{chunk-4XIDC3NF.js → chunk-MD6HA5IK.js} +2 -2
- package/dist/chunk-MLS5FAV7.js +189 -0
- package/dist/chunk-MLS5FAV7.js.map +1 -0
- package/dist/{chunk-2IJEMXOB.js → chunk-NFVFVYAP.js} +419 -427
- package/dist/chunk-NFVFVYAP.js.map +1 -0
- package/dist/{chunk-OC4H6HJD.js → chunk-O7WHXLCB.js} +2 -2
- package/dist/{chunk-M7JJCX53.js → chunk-OEGECBFS.js} +20 -20
- package/dist/chunk-OEGECBFS.js.map +1 -0
- package/dist/{chunk-MKWYLDFK.js → chunk-OF7BNW4D.js} +43 -3
- package/dist/chunk-OF7BNW4D.js.map +1 -0
- package/dist/{chunk-SUOXY5WJ.js → chunk-P2WZIDF3.js} +5 -5
- package/dist/chunk-P2WZIDF3.js.map +1 -0
- package/dist/{chunk-PA6Q6AWM.js → chunk-PSFVTBM7.js} +2 -2
- package/dist/chunk-QHA67Q7A.js +281 -0
- package/dist/chunk-QHA67Q7A.js.map +1 -0
- package/dist/{chunk-ZM3CFL5L.js → chunk-QRBOPFAA.js} +3 -3
- package/dist/{chunk-IFB4Z76W.js → chunk-S44CHE3G.js} +13 -12
- package/dist/chunk-S44CHE3G.js.map +1 -0
- package/dist/{chunk-CE26YH2U.js → chunk-SJ2GZ6RF.js} +48 -50
- package/dist/chunk-SJ2GZ6RF.js.map +1 -0
- package/dist/{chunk-SSCQCCJ7.js → chunk-THF25ICZ.js} +2 -2
- package/dist/{chunk-5Q3NDNNV.js → chunk-TR5MC2U6.js} +153 -6
- package/dist/chunk-TR5MC2U6.js.map +1 -0
- package/dist/{chunk-5VK4NRSF.js → chunk-UNXRACJ7.js} +35 -36
- package/dist/chunk-UNXRACJ7.js.map +1 -0
- package/dist/{chunk-GEHQXLEI.js → chunk-UYVWLISQ.js} +18 -35
- package/dist/chunk-UYVWLISQ.js.map +1 -0
- package/dist/{chunk-OSCLCMDG.js → chunk-UYWAESOT.js} +3 -3
- package/dist/{chunk-ZT3YZB4K.js → chunk-VBFDVGAE.js} +12 -12
- package/dist/chunk-VBFDVGAE.js.map +1 -0
- package/dist/{chunk-CDZERT7Z.js → chunk-VWNS6DH5.js} +48 -4
- package/dist/chunk-VWNS6DH5.js.map +1 -0
- package/dist/{chunk-CFFQ2Z7A.js → chunk-WUQQNE63.js} +2 -2
- package/dist/{claude-W52VKI6L.js → claude-X7EBJRB2.js} +8 -5
- package/dist/{cleanup-H4VXU3C3.js → cleanup-7QVPYBJJ.js} +133 -122
- package/dist/cleanup-7QVPYBJJ.js.map +1 -0
- package/dist/cli.js +901 -425
- package/dist/cli.js.map +1 -1
- package/dist/{color-F7RU6B6Z.js → color-ZPIIUADB.js} +3 -3
- package/dist/{contribute-Y7IQV5QY.js → contribute-RZYCYUDX.js} +8 -6
- package/dist/{contribute-Y7IQV5QY.js.map → contribute-RZYCYUDX.js.map} +1 -1
- package/dist/dev-server-LOY7YWCP.js +298 -0
- package/dist/dev-server-LOY7YWCP.js.map +1 -0
- package/dist/{feedback-XTUCKJNT.js → feedback-562KPG5U.js} +13 -12
- package/dist/{feedback-XTUCKJNT.js.map → feedback-562KPG5U.js.map} +1 -1
- package/dist/{git-IYA53VIC.js → git-OXJACVAU.js} +16 -4
- package/dist/hooks/iloom-hook.js +258 -0
- package/dist/{ignite-T74RYXCA.js → ignite-VSIPGKKG.js} +245 -39
- package/dist/ignite-VSIPGKKG.js.map +1 -0
- package/dist/index.d.ts +459 -124
- package/dist/index.js +740 -210
- package/dist/index.js.map +1 -1
- package/dist/init-SCR2LQ4A.js +21 -0
- package/dist/{installation-detector-VARGFFRZ.js → installation-detector-6R6YOFVZ.js} +3 -3
- package/dist/mcp/issue-management-server.js +2 -1
- package/dist/mcp/issue-management-server.js.map +1 -1
- package/dist/neon-helpers-L5CXQ5CT.js +11 -0
- package/dist/{open-UMXANW5S.js → open-CX7HUE26.js} +12 -10
- package/dist/{open-UMXANW5S.js.map → open-CX7HUE26.js.map} +1 -1
- package/dist/projects-6DTNDVLH.js +73 -0
- package/dist/projects-6DTNDVLH.js.map +1 -0
- package/dist/{prompt-QALMYTVC.js → prompt-A7GGRHSY.js} +3 -3
- package/dist/prompts/init-prompt.txt +49 -0
- package/dist/prompts/issue-prompt.txt +110 -8
- package/dist/prompts/regular-prompt.txt +463 -14
- package/dist/prompts/session-summary-prompt.txt +82 -0
- package/dist/{rebase-VJ2VKR6R.js → rebase-55URTXZC.js} +11 -9
- package/dist/{rebase-VJ2VKR6R.js.map → rebase-55URTXZC.js.map} +1 -1
- package/dist/{remote-VUNCQZ6J.js → remote-73TZ2ADI.js} +3 -3
- package/dist/{run-MJYY4PUT.js → run-DP2U2CA2.js} +12 -10
- package/dist/{run-MJYY4PUT.js.map → run-DP2U2CA2.js.map} +1 -1
- package/dist/schema/settings.schema.json +49 -0
- package/dist/summary-J3CJSM7L.js +244 -0
- package/dist/summary-J3CJSM7L.js.map +1 -0
- package/dist/{test-git-IT5EWQ5C.js → test-git-QLAIBJLX.js} +6 -4
- package/dist/{test-git-IT5EWQ5C.js.map → test-git-QLAIBJLX.js.map} +1 -1
- package/dist/{test-prefix-NPWDPUUH.js → test-prefix-6YM2ZOON.js} +6 -4
- package/dist/{test-prefix-NPWDPUUH.js.map → test-prefix-6YM2ZOON.js.map} +1 -1
- package/dist/{test-tabs-PRMRSHKI.js → test-tabs-JGO3VOXJ.js} +4 -4
- package/dist/{test-webserver-DAHONWCS.js → test-webserver-VPNLAFZ3.js} +2 -2
- package/dist/{update-4TDDUR5K.js → update-LETF5ASC.js} +4 -4
- package/dist/{update-notifier-QEX3CJHA.js → update-notifier-H55ZK7NU.js} +3 -3
- package/package.json +6 -6
- package/dist/ClaudeContextManager-BN7RE5ZQ.js +0 -15
- package/dist/ClaudeService-DLYLJUPA.js +0 -14
- package/dist/GitHubService-FZHHBOFG.js +0 -11
- package/dist/LoomLauncher-ZV3ZZIBA.js.map +0 -1
- package/dist/PromptTemplateManager-6HH3PVXV.js +0 -9
- package/dist/SettingsMigrationManager-TJ7UWZG5.js +0 -10
- package/dist/chunk-2CXREBLZ.js.map +0 -1
- package/dist/chunk-2IJEMXOB.js.map +0 -1
- package/dist/chunk-2MAIX45J.js.map +0 -1
- package/dist/chunk-5Q3NDNNV.js.map +0 -1
- package/dist/chunk-5VK4NRSF.js.map +0 -1
- package/dist/chunk-CDZERT7Z.js.map +0 -1
- package/dist/chunk-CE26YH2U.js.map +0 -1
- package/dist/chunk-DLHA5VQ3.js.map +0 -1
- package/dist/chunk-GEHQXLEI.js.map +0 -1
- package/dist/chunk-IFB4Z76W.js.map +0 -1
- package/dist/chunk-M7JJCX53.js.map +0 -1
- package/dist/chunk-MKWYLDFK.js.map +0 -1
- package/dist/chunk-OXAM2WVC.js.map +0 -1
- package/dist/chunk-OYF4VIFI.js.map +0 -1
- package/dist/chunk-PGPI5LR4.js.map +0 -1
- package/dist/chunk-RIEO2WML.js.map +0 -1
- package/dist/chunk-SUOXY5WJ.js.map +0 -1
- package/dist/chunk-ZT3YZB4K.js.map +0 -1
- package/dist/cleanup-H4VXU3C3.js.map +0 -1
- package/dist/ignite-T74RYXCA.js.map +0 -1
- package/dist/init-4FHTAM3F.js +0 -19
- package/dist/logger-MKYH4UDV.js +0 -12
- package/dist/neon-helpers-77PBPGJ5.js +0 -10
- package/dist/update-notifier-QEX3CJHA.js.map +0 -1
- /package/dist/{BranchNamingService-A77VI6AI.js.map → BranchNamingService-TOM2KAUT.js.map} +0 -0
- /package/dist/{ClaudeContextManager-BN7RE5ZQ.js.map → ClaudeContextManager-VEGJTS5E.js.map} +0 -0
- /package/dist/{ClaudeService-DLYLJUPA.js.map → ClaudeService-ICSHJMQ5.js.map} +0 -0
- /package/dist/{GitHubService-FZHHBOFG.js.map → GitHubService-RPM27GWD.js.map} +0 -0
- /package/dist/{PromptTemplateManager-6HH3PVXV.js.map → PromptTemplateManager-2TDZAUC6.js.map} +0 -0
- /package/dist/{SettingsManager-I2LRCW2A.js.map → SettingsManager-FJFU6JJD.js.map} +0 -0
- /package/dist/{SettingsMigrationManager-TJ7UWZG5.js.map → SettingsMigrationManager-EH3J2TCN.js.map} +0 -0
- /package/dist/{chunk-UJL4HI2R.js.map → chunk-3NFBZRPR.js.map} +0 -0
- /package/dist/{chunk-AKUJXDNW.js.map → chunk-F4J6KEL6.js.map} +0 -0
- /package/dist/{chunk-RW54ZMBM.js.map → chunk-JJUPY5MM.js.map} +0 -0
- /package/dist/{chunk-UAN4A3YU.js.map → chunk-KM3W7YQX.js.map} +0 -0
- /package/dist/{chunk-4XIDC3NF.js.map → chunk-MD6HA5IK.js.map} +0 -0
- /package/dist/{chunk-OC4H6HJD.js.map → chunk-O7WHXLCB.js.map} +0 -0
- /package/dist/{chunk-PA6Q6AWM.js.map → chunk-PSFVTBM7.js.map} +0 -0
- /package/dist/{chunk-ZM3CFL5L.js.map → chunk-QRBOPFAA.js.map} +0 -0
- /package/dist/{chunk-SSCQCCJ7.js.map → chunk-THF25ICZ.js.map} +0 -0
- /package/dist/{chunk-OSCLCMDG.js.map → chunk-UYWAESOT.js.map} +0 -0
- /package/dist/{chunk-CFFQ2Z7A.js.map → chunk-WUQQNE63.js.map} +0 -0
- /package/dist/{claude-W52VKI6L.js.map → claude-X7EBJRB2.js.map} +0 -0
- /package/dist/{color-F7RU6B6Z.js.map → color-ZPIIUADB.js.map} +0 -0
- /package/dist/{git-IYA53VIC.js.map → git-OXJACVAU.js.map} +0 -0
- /package/dist/{init-4FHTAM3F.js.map → init-SCR2LQ4A.js.map} +0 -0
- /package/dist/{installation-detector-VARGFFRZ.js.map → installation-detector-6R6YOFVZ.js.map} +0 -0
- /package/dist/{logger-MKYH4UDV.js.map → neon-helpers-L5CXQ5CT.js.map} +0 -0
- /package/dist/{neon-helpers-77PBPGJ5.js.map → prompt-A7GGRHSY.js.map} +0 -0
- /package/dist/{prompt-QALMYTVC.js.map → remote-73TZ2ADI.js.map} +0 -0
- /package/dist/{test-tabs-PRMRSHKI.js.map → test-tabs-JGO3VOXJ.js.map} +0 -0
- /package/dist/{test-webserver-DAHONWCS.js.map → test-webserver-VPNLAFZ3.js.map} +0 -0
- /package/dist/{update-4TDDUR5K.js.map → update-LETF5ASC.js.map} +0 -0
- /package/dist/{remote-VUNCQZ6J.js.map → update-notifier-H55ZK7NU.js.map} +0 -0
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/commands/start.ts","../src/utils/first-run-setup.ts","../src/commands/add-issue.ts","../src/commands/enhance.ts","../src/lib/ValidationRunner.ts","../src/types/index.ts","../src/lib/CommitManager.ts","../src/lib/BuildRunner.ts","../src/lib/PRManager.ts","../src/commands/finish.ts","../src/utils/package-info.ts","../src/utils/loom-formatter.ts"],"sourcesContent":["import { program, Command, Option } from 'commander'\nimport { logger } from './utils/logger.js'\nimport { GitWorktreeManager } from './lib/GitWorktreeManager.js'\nimport { ShellCompletion } from './lib/ShellCompletion.js'\nimport { SettingsManager } from './lib/SettingsManager.js'\nimport { IssueTrackerFactory } from './lib/IssueTrackerFactory.js'\nimport { IssueEnhancementService } from './lib/IssueEnhancementService.js'\nimport { AgentManager } from './lib/AgentManager.js'\nimport { GitHubService } from './lib/GitHubService.js'\nimport { MetadataManager, type LoomMetadata } from './lib/MetadataManager.js'\nimport { StartCommand } from './commands/start.js'\nimport { AddIssueCommand } from './commands/add-issue.js'\nimport { EnhanceCommand } from './commands/enhance.js'\nimport { FinishCommand } from './commands/finish.js'\nimport type { StartOptions, CleanupOptions, FinishOptions } from './types/index.js'\nimport { getPackageInfo } from './utils/package-info.js'\nimport { hasMultipleRemotes } from './utils/remote.js'\nimport { fileURLToPath } from 'url'\nimport { realpathSync } from 'fs'\nimport { formatLoomsForJson } from './utils/loom-formatter.js'\nimport { findMainWorktreePathWithSettings } from './utils/git.js'\n\n// Get package.json for version\nconst __filename = fileURLToPath(import.meta.url)\nconst packageJson = getPackageInfo(__filename)\n\n// Helper function to parse issue identifiers (numeric or alphanumeric)\nfunction parseIssueIdentifier(value: string): string | number {\n const parsed = parseInt(value, 10)\n // Return number if purely numeric, otherwise return string\n return !isNaN(parsed) && String(parsed) === value ? parsed : value\n}\n\nprogram\n .name('iloom')\n .description(packageJson.description)\n .version(packageJson.version)\n .option('--debug', 'Enable debug output (default: based on ILOOM_DEBUG env var)')\n .option('--completion', 'Output shell completion script for current shell')\n .option('--set <key=value>', 'Override any setting using dot notation (repeatable, e.g., --set workflows.issue.startIde=false)')\n .allowUnknownOption() // Allow --set to be used multiple times\n .hook('preAction', async (thisCommand) => {\n // Set debug mode based on flag or environment variable\n const options = thisCommand.opts()\n // Default to environment variable value, then false if not set\n const envDebug = process.env.ILOOM_DEBUG === 'true'\n const debugEnabled = options.debug !== undefined ? options.debug : envDebug\n logger.setDebug(debugEnabled)\n\n // Handle --completion flag\n if (options.completion) {\n const shellCompletion = new ShellCompletion()\n shellCompletion.printCompletionScript()\n process.exit(0)\n }\n\n // Check for updates before command execution for global installations\n try {\n const { checkAndNotifyUpdate } = await import('./utils/update-notifier.js')\n const { detectInstallationMethod } = await import('./utils/installation-detector.js')\n\n // Detect installation method\n const installMethod = detectInstallationMethod(__filename)\n\n // Check and notify (non-blocking, all errors handled internally)\n await checkAndNotifyUpdate(packageJson.version, packageJson.name, installMethod)\n } catch {\n // Silently fail - update check should never break user experience\n }\n\n // Migrate legacy .hatchbox settings to .iloom (BEFORE settings validation)\n try {\n const { SettingsMigrationManager } = await import('./lib/SettingsMigrationManager.js')\n const migrationManager = new SettingsMigrationManager()\n await migrationManager.migrateSettingsIfNeeded()\n } catch (error) {\n // Log warning but don't fail - migration is best-effort\n logger.debug(`Settings migration failed: ${error instanceof Error ? error.message : 'Unknown'}`)\n }\n\n // Validate settings for all commands\n await validateSettingsForCommand(thisCommand)\n\n // Validate GitHub CLI availability for commands that need it\n await validateGhCliForCommand(thisCommand)\n })\n\n// Helper function to validate settings at startup\nasync function validateSettingsForCommand(command: Command): Promise<void> {\n const commandName = command.args[0] ?? ''\n\n // Tier 1: Commands that bypass ALL validation\n const bypassCommands = ['help', 'init', 'update', 'contribute']\n\n if (bypassCommands.includes(commandName)) {\n return\n }\n\n // Tier 2: All other commands require FULL validation (settings + multi-remote)\n // Commands: start, add-issue, enhance, finish, list, cleanup, open, run, etc.\n try {\n const settingsManager = new SettingsManager()\n\n // Attempt to load settings - this will throw on validation errors\n // Missing file is OK (returns {})\n const settings = await settingsManager.loadSettings()\n\n // Check for multi-remote configuration requirement\n const multipleRemotes = await hasMultipleRemotes()\n\n if (multipleRemotes && !settings.issueManagement?.github?.remote) {\n // Auto-launch init command to configure remotes\n // After init completes, function returns and Commander.js continues with original command\n await autoLaunchInitForMultipleRemotes()\n return // Settings now configured, let preAction complete\n }\n } catch (error) {\n logger.error(`Configuration error: ${error instanceof Error ? error.message : 'Unknown error'}`)\n logger.info('Please fix your .iloom/settings.json file and try again.')\n process.exit(1)\n }\n}\n\n// Helper function to validate GitHub CLI availability\n// Exported for testing\nexport async function validateGhCliForCommand(command: Command): Promise<void> {\n const commandName = command.args[0] ?? ''\n\n // Commands that ALWAYS require gh CLI regardless of configuration\n const alwaysRequireGh = ['feedback', 'contribute']\n\n // Commands that require gh CLI when GitHub provider or github-pr merge mode\n const conditionallyRequireGh = ['start', 'finish', 'enhance', 'add-issue', 'ignite', 'spin']\n\n // Commands that only warn if gh CLI is missing (secondary/utility commands)\n const warnOnly = ['init', 'list', 'rebase', 'cleanup', 'run', 'update', 'open']\n\n // Test commands and help bypass this check entirely\n if (commandName.startsWith('test-') || commandName === 'help') {\n return\n }\n\n // Check if gh CLI is available\n const ghAvailable = GitHubService.isCliAvailable()\n\n // Determine if gh CLI is needed based on configuration\n let needsGhCli = alwaysRequireGh.includes(commandName)\n\n // For conditional commands, check provider and merge mode\n if (!needsGhCli && conditionallyRequireGh.includes(commandName)) {\n try {\n const settingsManager = new SettingsManager()\n const settings = await settingsManager.loadSettings()\n\n const provider = IssueTrackerFactory.getProviderName(settings)\n const mergeBehaviorMode = settings.mergeBehavior?.mode\n\n needsGhCli = provider === 'github' || mergeBehaviorMode === 'github-pr'\n } catch {\n // If we can't load settings, assume we might need gh CLI\n needsGhCli = true\n }\n }\n\n // Handle missing gh CLI\n if (!ghAvailable) {\n if (needsGhCli) {\n // ERROR: gh CLI is required for this command\n const errorMessage = alwaysRequireGh.includes(commandName)\n ? `The \"${commandName}\" command requires GitHub CLI (gh) to be installed.`\n : `GitHub CLI (gh) is required when using GitHub as the issue tracker or \"github-pr\" merge mode.`\n\n logger.error(errorMessage)\n logger.info('')\n logger.info('To install GitHub CLI:')\n logger.info(' • macOS: brew install gh')\n logger.info(' • Windows: winget install GitHub.cli')\n logger.info(' • Linux: https://github.com/cli/cli#installation')\n logger.info('')\n logger.info('After installation, authenticate with: gh auth login')\n\n process.exit(1)\n } else if (warnOnly.includes(commandName)) {\n // WARN: gh CLI might be needed for certain configurations\n try {\n const settingsManager = new SettingsManager()\n const settings = await settingsManager.loadSettings()\n\n const provider = IssueTrackerFactory.getProviderName(settings)\n const mergeBehaviorMode = settings.mergeBehavior?.mode\n\n if (provider === 'github' || mergeBehaviorMode === 'github-pr') {\n logger.warn('GitHub CLI (gh) is not installed.')\n logger.warn(\n 'Some features may not work correctly with your current configuration (GitHub provider or github-pr merge mode).'\n )\n logger.info('To install: brew install gh (macOS) or see https://github.com/cli/cli#installation')\n logger.info('')\n }\n } catch {\n // Silently skip warning if we can't load settings\n }\n }\n }\n}\n\n/**\n * Auto-launch init command when multiple remotes are detected but not configured\n * Shows message, waits for keypress, launches interactive Claude configuration,\n * then returns to let Commander.js continue with the original command\n */\nasync function autoLaunchInitForMultipleRemotes(): Promise<void> {\n logger.info('Multiple git remotes detected, but no GitHub remote is configured.')\n logger.info('')\n logger.info('iloom will now launch an interactive configuration session with Claude')\n logger.info('to help you select which remote to use for GitHub operations.')\n logger.info('')\n\n // Wait for keypress to continue\n const { waitForKeypress } = await import('./utils/prompt.js')\n await waitForKeypress('Press any key to start configuration...')\n\n logger.info('')\n\n try {\n // Launch init command with focused initial message\n const { InitCommand } = await import('./commands/init.js')\n const initCommand = new InitCommand()\n\n // Custom initial message that focuses on multi-remote configuration\n 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.'\n\n await initCommand.execute(customInitialMessage)\n\n logger.info('')\n logger.info('Configuration complete! Continuing with your original command...')\n logger.info('')\n\n // Re-validate settings after init to ensure multi-remote is now configured\n const { SettingsManager } = await import('./lib/SettingsManager.js')\n const settingsManager = new SettingsManager()\n const settings = await settingsManager.loadSettings()\n\n const { hasMultipleRemotes } = await import('./utils/remote.js')\n const multipleRemotes = await hasMultipleRemotes()\n\n // Verify the issue is resolved\n if (multipleRemotes && !settings.issueManagement?.github?.remote) {\n logger.error('Configuration incomplete: GitHub remote is still not configured.')\n logger.info('Please run \"iloom init\" again and configure the GitHub remote setting.')\n process.exit(1)\n }\n\n // Configuration verified - simply return to let Commander.js continue\n // with the original command (preAction hook will complete normally)\n return\n\n } catch (error) {\n logger.error(`Failed to configure remotes: ${error instanceof Error ? error.message : 'Unknown error'}`)\n logger.info('You can manually run \"iloom init\" to configure settings.')\n process.exit(1)\n }\n}\n\n// Initialize shell completion (must be after program setup, before parseAsync)\nconst shellCompletion = new ShellCompletion()\nshellCompletion.init()\n\nprogram\n .command('start')\n .alias('new')\n .alias('create')\n .alias('up')\n .description('Create isolated workspace for an issue/PR')\n .argument('[identifier]', 'Issue number, PR number, or branch name (optional - will prompt if not provided)')\n .option('--claude', 'Enable Claude integration (default: true)')\n .option('--no-claude', 'Disable Claude integration')\n .option('--code', 'Enable VSCode (default: true)')\n .option('--no-code', 'Disable VSCode')\n .option('--dev-server', 'Enable dev server in terminal (default: true)')\n .option('--no-dev-server', 'Disable dev server')\n .option('--terminal', 'Enable terminal without dev server (default: false)')\n .option('--no-terminal', 'Disable terminal')\n .option('--child-loom', 'Force create as child loom (skip prompt)')\n .option('--no-child-loom', 'Force create as independent loom (skip prompt)')\n .option('--body <text>', 'Body text for issue (skips AI enhancement)')\n .addOption(\n new Option('--one-shot <mode>', 'One-shot automation mode')\n .choices(['default', 'noReview', 'bypassPermissions'])\n .default('default')\n )\n .action(async (identifier: string | undefined, options: StartOptions) => {\n try {\n let finalIdentifier = identifier\n\n // Interactive prompting when no identifier provided\n if (!finalIdentifier) {\n const { promptInput } = await import('./utils/prompt.js')\n finalIdentifier = await promptInput('Enter issue number, PR number (pr/123), or branch name')\n\n // Validate non-empty after prompting\n if (!finalIdentifier?.trim()) {\n logger.error('Identifier is required')\n process.exit(1)\n }\n }\n\n const settingsManager = new SettingsManager()\n const settings = await settingsManager.loadSettings()\n const issueTracker = IssueTrackerFactory.create(settings)\n const command = new StartCommand(issueTracker, undefined, undefined, settingsManager)\n await command.execute({ identifier: finalIdentifier, options })\n } catch (error) {\n logger.error(`Failed to start workspace: ${error instanceof Error ? error.message : 'Unknown error'}`)\n process.exit(1)\n }\n })\n\nprogram\n .command('add-issue')\n .alias('a')\n .description('Create and enhance GitHub issue without starting workspace')\n .argument('<description>', 'Natural language description of the issue (>50 chars, >2 spaces)')\n .option('--body <text>', 'Body text for issue (skips AI enhancement)')\n .action(async (description: string, options: { body?: string }) => {\n try {\n const settingsManager = new SettingsManager()\n const settings = await settingsManager.loadSettings()\n const issueTracker = IssueTrackerFactory.create(settings)\n const enhancementService = new IssueEnhancementService(issueTracker, new AgentManager(), settingsManager)\n const command = new AddIssueCommand(enhancementService, settingsManager)\n const issueNumber = await command.execute({\n description,\n options: options.body ? { body: options.body } : {}\n })\n logger.success(`Issue #${issueNumber} created successfully`)\n process.exit(0)\n } catch (error) {\n logger.error(`Failed to create issue: ${error instanceof Error ? error.message : 'Unknown error'}`)\n process.exit(1)\n }\n })\n\nprogram\n .command('feedback')\n .alias('f')\n .description('Submit feedback/bug report to iloom-cli repository')\n .argument('<description>', 'Natural language description of feedback (>50 chars, >2 spaces)')\n .option('--body <text>', 'Body text for feedback (added after diagnostics)')\n .action(async (description: string, options: { body?: string }) => {\n try {\n const { FeedbackCommand } = await import('./commands/feedback.js')\n const command = new FeedbackCommand()\n const feedbackOptions: import('./types/index.js').FeedbackOptions = {}\n if (options.body !== undefined) {\n feedbackOptions.body = options.body\n }\n const issueNumber = await command.execute({\n description,\n options: feedbackOptions\n })\n logger.success(`Feedback submitted as issue #${issueNumber} in iloom-cli repository`)\n process.exit(0)\n } catch (error) {\n logger.error(`Failed to submit feedback: ${error instanceof Error ? error.message : 'Unknown error'}`)\n process.exit(1)\n }\n })\n\nprogram\n .command('enhance')\n .description('Apply enhancement agent to existing GitHub issue')\n .argument('<issue-number>', 'GitHub issue identifier to enhance', parseIssueIdentifier)\n .option('--no-browser', 'Skip browser opening prompt')\n .option('--author <username>', 'GitHub username to tag in questions (for CI usage)')\n .action(async (issueNumber: string | number, options: { browser?: boolean; author?: string }) => {\n try {\n const settingsManager = new SettingsManager()\n const settings = await settingsManager.loadSettings()\n const issueTracker = IssueTrackerFactory.create(settings)\n const command = new EnhanceCommand(issueTracker)\n await command.execute({\n issueNumber,\n options: {\n noBrowser: options.browser === false,\n ...(options.author && { author: options.author })\n }\n })\n logger.success(`Enhancement process completed for issue #${issueNumber}`)\n process.exit(0)\n } catch (error) {\n logger.error(`Failed to enhance issue: ${error instanceof Error ? error.message : 'Unknown error'}`)\n process.exit(1)\n }\n })\n\nprogram\n .command('finish')\n .alias('dn')\n .description('Merge work and cleanup workspace')\n .argument('[identifier]', 'Issue number, PR number, or branch name (auto-detected if omitted)')\n .option('-f, --force', 'Skip confirmation prompts')\n .option('-n, --dry-run', 'Preview actions without executing')\n .option('--pr <number>', 'Treat input as PR number', parseFloat)\n .option('--skip-build', 'Skip post-merge build verification')\n .option('--no-browser', 'Skip opening PR in browser (github-pr mode only)')\n .option('--cleanup', 'Clean up worktree after PR creation (github-pr mode only)')\n .option('--no-cleanup', 'Keep worktree after PR creation (github-pr mode only)')\n .action(async (identifier: string | undefined, options: FinishOptions) => {\n try {\n const settingsManager = new SettingsManager()\n const settings = await settingsManager.loadSettings()\n const issueTracker = IssueTrackerFactory.create(settings)\n const command = new FinishCommand(issueTracker)\n await command.execute({ identifier, options })\n } catch (error) {\n logger.error(`Failed to finish workspace: ${error instanceof Error ? error.message : 'Unknown error'}`)\n process.exit(1)\n }\n })\n\nprogram\n .command('rebase')\n .description('Rebase current branch on main with Claude-assisted conflict resolution')\n .option('-f, --force', 'Skip confirmation prompts')\n .option('-n, --dry-run', 'Preview actions without executing')\n .action(async (options: { force?: boolean; dryRun?: boolean }) => {\n try {\n const { RebaseCommand } = await import('./commands/rebase.js')\n const command = new RebaseCommand()\n await command.execute(options)\n } catch (error) {\n logger.error(`Failed to rebase: ${error instanceof Error ? error.message : 'Unknown error'}`)\n process.exit(1)\n }\n })\n\nprogram\n .command('spin')\n .alias('ignite')\n .description('Launch Claude with auto-detected workspace context')\n .addOption(\n new Option('--one-shot <mode>', 'One-shot automation mode')\n .choices(['default', 'noReview', 'bypassPermissions'])\n .default('default')\n )\n .action(async (options: { oneShot?: import('./types/index.js').OneShotMode }) => {\n try {\n const { IgniteCommand } = await import('./commands/ignite.js')\n const command = new IgniteCommand()\n await command.execute(options.oneShot ?? 'default')\n } catch (error) {\n logger.error(`Failed to spin up loom: ${error instanceof Error ? error.message : 'Unknown error'}`)\n process.exit(1)\n }\n })\n\nprogram\n .command('open')\n .description('Open workspace in browser or run CLI tool')\n .argument('[identifier]', 'Issue number, PR number, or branch name (auto-detected if omitted)')\n .allowUnknownOption()\n .action(async (identifier?: string, _options?: Record<string, unknown>, command?: Command) => {\n try {\n // Extract additional arguments - everything after identifier\n const args = command?.args ? command.args.slice(identifier ? 1 : 0) : []\n\n const { OpenCommand } = await import('./commands/open.js')\n const cmd = new OpenCommand()\n const input = identifier ? { identifier, args } : { args }\n await cmd.execute(input)\n } catch (error) {\n logger.error(`Failed to open: ${error instanceof Error ? error.message : 'Unknown error'}`)\n process.exit(1)\n }\n })\n\nprogram\n .command('run')\n .description('Run CLI tool or open workspace in browser')\n .argument('[identifier]', 'Issue number, PR number, or branch name (auto-detected if omitted)')\n .allowUnknownOption()\n .action(async (identifier?: string, _options?: Record<string, unknown>, command?: Command) => {\n try {\n // Extract additional arguments - everything after identifier\n const args = command?.args ? command.args.slice(identifier ? 1 : 0) : []\n\n const { RunCommand } = await import('./commands/run.js')\n const cmd = new RunCommand()\n const input = identifier ? { identifier, args } : { args }\n await cmd.execute(input)\n } catch (error) {\n logger.error(`Failed to run: ${error instanceof Error ? error.message : 'Unknown error'}`)\n process.exit(1)\n }\n })\n\nprogram\n .command('cleanup')\n .alias('remove')\n .alias('clean')\n .description('Remove workspaces')\n .argument('[identifier]', 'Branch name or issue number to cleanup (auto-detected)')\n .option('-l, --list', 'List all worktrees')\n .option('-a, --all', 'Remove all worktrees (interactive confirmation)')\n .option('-i, --issue <number>', 'Cleanup by issue number', parseInt)\n .option('-f, --force', 'Skip confirmations and force removal')\n .option('--dry-run', 'Show what would be done without doing it')\n .action(async (identifier?: string, options?: CleanupOptions) => {\n try {\n const { CleanupCommand } = await import('./commands/cleanup.js')\n const command = new CleanupCommand()\n const input: { identifier?: string; options: CleanupOptions } = {\n options: options ?? {}\n }\n if (identifier) {\n input.identifier = identifier\n }\n await command.execute(input)\n } catch (error) {\n logger.error(`Failed to cleanup worktrees: ${error instanceof Error ? error.message : 'Unknown error'}`)\n process.exit(1)\n }\n })\n\nprogram\n .command('list')\n .description('Show active workspaces')\n .option('--json', 'Output as JSON')\n .action(async (options: { json?: boolean }) => {\n try {\n const manager = new GitWorktreeManager()\n const metadataManager = new MetadataManager()\n const worktrees = await manager.listWorktrees({ porcelain: true })\n\n // Read metadata for all worktrees (spec section 3.2)\n const metadata = new Map<string, LoomMetadata | null>()\n for (const worktree of worktrees) {\n const loomMetadata = await metadataManager.readMetadata(worktree.path)\n metadata.set(worktree.path, loomMetadata)\n }\n\n if (options.json) {\n const mainWorktreePath = await findMainWorktreePathWithSettings()\n console.log(JSON.stringify(formatLoomsForJson(worktrees, mainWorktreePath, metadata), null, 2))\n return\n }\n\n if (worktrees.length === 0) {\n logger.info('No worktrees found')\n return\n }\n\n logger.info('Active workspaces:')\n for (const worktree of worktrees) {\n const formatted = manager.formatWorktree(worktree)\n const loomMetadata = metadata.get(worktree.path)\n logger.info(` ${formatted.title}`)\n if (loomMetadata?.description) {\n logger.info(` Description: ${loomMetadata.description}`)\n }\n logger.info(` Path: ${formatted.path}`)\n logger.info(` Commit: ${formatted.commit}`)\n }\n } catch (error) {\n // Handle \"not a git repository\" gracefully\n if (error instanceof Error && error.message.includes('not a git repository')) {\n if (options.json) {\n console.log('[]')\n } else {\n logger.info('No worktrees found')\n }\n return\n }\n logger.error(`Failed to list worktrees: ${error instanceof Error ? error.message : 'Unknown error'}`)\n process.exit(1)\n }\n })\n\n\nprogram\n .command('init')\n .alias('config')\n .description('Initialize iloom configuration and setup shell autocomplete')\n .argument('[prompt]', 'Custom initial message to send to Claude (defaults to \"Help me configure iloom settings.\")')\n .action(async (prompt?: string) => {\n try {\n const { InitCommand } = await import('./commands/init.js')\n const command = new InitCommand()\n // Pass custom prompt if provided and non-empty\n const trimmedPrompt = prompt?.trim()\n const customPrompt = trimmedPrompt && trimmedPrompt.length > 0 ? trimmedPrompt : undefined\n await command.execute(customPrompt)\n } catch (error) {\n logger.error(`Failed to initialize: ${error instanceof Error ? error.message : 'Unknown error'}`)\n process.exit(1)\n }\n })\n\nprogram\n .command('contribute')\n .description('Set up local development environment for contributing to iloom')\n .action(async () => {\n try {\n const { ContributeCommand } = await import('./commands/contribute.js')\n const command = new ContributeCommand()\n await command.execute()\n } catch (error) {\n logger.error(`Failed to set up contributor environment: ${error instanceof Error ? error.message : 'Unknown error'}`)\n process.exit(1)\n }\n })\n\nprogram\n .command('update')\n .description('Update iloom-cli to the latest version')\n .option('--dry-run', 'Show what would be done without actually updating')\n .action(async (options: { dryRun?: boolean }) => {\n try {\n const { UpdateCommand } = await import('./commands/update.js')\n const command = new UpdateCommand()\n await command.execute(options)\n } catch (error) {\n logger.error(`Failed to update: ${error instanceof Error ? error.message : 'Unknown error'}`)\n process.exit(1)\n }\n })\n\n// Test command for GitHub integration\nprogram\n .command('test-github')\n .description('Test GitHub integration (Issue #3)')\n .argument('<identifier>', 'Issue number or PR number')\n .option('--no-claude', 'Skip Claude for branch name generation')\n .action(async (identifier: string, options: { claude?: boolean }) => {\n try {\n const { GitHubService } = await import('./lib/GitHubService.js')\n const { DefaultBranchNamingService } = await import('./lib/BranchNamingService.js')\n\n logger.info('Testing GitHub Integration\\n')\n\n const service = new GitHubService()\n const branchNaming = new DefaultBranchNamingService({ useClaude: options.claude !== false })\n\n // Test 1: Input detection\n logger.info('Detecting input type...')\n const detection = await service.detectInputType(identifier)\n logger.info(` Type: ${detection.type}`)\n logger.info(` Identifier: ${detection.identifier}`)\n\n if (detection.type === 'unknown') {\n logger.error('Could not detect if input is an issue or PR')\n process.exit(1)\n }\n\n // Test 2: Fetch the issue/PR\n logger.info('Fetching from GitHub...')\n if (detection.type === 'issue') {\n if (!detection.identifier) {\n throw new Error('Issue number not detected')\n }\n const issueNumber = parseInt(detection.identifier, 10)\n const issue = await service.fetchIssue(issueNumber)\n logger.success(` Issue #${issue.number}: ${issue.title}`)\n logger.info(` State: ${issue.state}`)\n logger.info(` Labels: ${issue.labels.join(', ') || 'none'}`)\n logger.info(` URL: ${issue.url}`)\n\n // Test 3: Generate branch name\n\n logger.info('Generating branch name...')\n const branchName = await branchNaming.generateBranchName({\n issueNumber: issue.number,\n title: issue.title\n })\n logger.success(` Branch: ${branchName}`)\n\n // Test 4: Extract context\n \n logger.info('Extracting context for Claude...')\n const context = service.extractContext(issue)\n logger.info(` ${context.split('\\n').join('\\n ')}`)\n\n } else {\n if (!detection.identifier) {\n throw new Error('PR number not detected')\n }\n const prNumber = parseInt(detection.identifier, 10)\n const pr = await service.fetchPR(prNumber)\n logger.success(` PR #${pr.number}: ${pr.title}`)\n logger.info(` State: ${pr.state}`)\n logger.info(` Branch: ${pr.branch}`)\n logger.info(` Base: ${pr.baseBranch}`)\n logger.info(` URL: ${pr.url}`)\n\n // Test 3: Extract context\n \n logger.info('Extracting context for Claude...')\n const context = service.extractContext(pr)\n logger.info(` ${context.split('\\n').join('\\n ')}`)\n }\n\n \n logger.success('All GitHub integration tests passed!')\n\n } catch (error) {\n logger.error(`Test failed: ${error instanceof Error ? error.message : 'Unknown error'}`)\n if (error instanceof Error && error.stack) {\n logger.debug(error.stack)\n }\n process.exit(1)\n }\n })\n\n// Test command for Claude integration\nprogram\n .command('test-claude')\n .description('Test Claude integration (Issue #10)')\n .option('--detect', 'Test Claude CLI detection')\n .option('--version', 'Get Claude CLI version')\n .option('--branch <title>', 'Test branch name generation with given title')\n .option('--issue <number>', 'Issue number for branch generation', '123')\n .option('--launch <prompt>', 'Launch Claude with a prompt (headless)')\n .option('--interactive', 'Launch Claude interactively (requires --launch)')\n .option('--template <name>', 'Test template loading')\n .action(async (options: {\n detect?: boolean\n version?: boolean\n branch?: string\n issue?: string\n launch?: string\n interactive?: boolean\n template?: 'issue' | 'pr' | 'regular'\n }) => {\n try {\n const { detectClaudeCli, getClaudeVersion, generateBranchName, launchClaude } = await import('./utils/claude.js')\n const { PromptTemplateManager } = await import('./lib/PromptTemplateManager.js')\n const { ClaudeService } = await import('./lib/ClaudeService.js')\n const { ClaudeContextManager } = await import('./lib/ClaudeContextManager.js')\n\n logger.info('Testing Claude Integration\\n')\n\n // Test 1: Detection\n if (options.detect) {\n logger.info('Detecting Claude CLI...')\n const isAvailable = await detectClaudeCli()\n if (isAvailable) {\n logger.success(' Claude CLI is available')\n } else {\n logger.error(' Claude CLI not found')\n }\n }\n\n // Test 2: Version\n if (options.version) {\n logger.info('Getting Claude version...')\n const version = await getClaudeVersion()\n if (version) {\n logger.success(` Version: ${version}`)\n } else {\n logger.error(' Could not get version')\n }\n }\n\n // Test 3: Branch name generation\n if (options.branch) {\n logger.info('Generating branch name...')\n const issueNumber = parseInt(options.issue ?? '123')\n logger.info(` Issue #${issueNumber}: ${options.branch}`)\n const branchName = await generateBranchName(options.branch, issueNumber)\n logger.success(` Generated: ${branchName}`)\n }\n\n // Test 4: Launch Claude\n if (options.launch) {\n logger.info('Launching Claude...')\n logger.info(` Prompt: \"${options.launch}\"`)\n logger.info(` Mode: ${options.interactive ? 'Interactive' : 'Headless'}`)\n\n if (options.interactive) {\n logger.info(' Launching Claude in new terminal...')\n await launchClaude(options.launch, { headless: false })\n logger.info(' (Claude should open in a separate process)')\n } else {\n logger.info(' Waiting for response...')\n const result = await launchClaude(options.launch, { headless: true })\n if (result) {\n logger.success(' Response:')\n logger.info(` ${result.split('\\n').join('\\n ')}`)\n }\n }\n }\n\n // Test 5: Template loading\n if (options.template) {\n logger.info('Loading template...')\n logger.info(` Template: ${options.template}`)\n const manager = new PromptTemplateManager()\n try {\n const content = await manager.loadTemplate(options.template)\n logger.success(' Template loaded successfully')\n logger.info(' First 200 chars:')\n logger.info(` ${content.substring(0, 200).split('\\n').join('\\n ')}...`)\n } catch (error) {\n logger.error(` Failed: ${error instanceof Error ? error.message : 'Unknown error'}`)\n }\n }\n\n // Run all tests in sequence when no specific options provided\n if (!options.detect && !options.version && !options.branch && !options.launch && !options.template) {\n logger.info('Running full Claude integration test suite...\\n')\n\n // Test 1: Detection\n logger.info('1. Testing Claude CLI detection...')\n const isAvailable = await detectClaudeCli()\n if (isAvailable) {\n logger.success(' Claude CLI is available')\n } else {\n logger.error(' Claude CLI not found')\n logger.info('\\nSkipping remaining tests since Claude CLI is not available')\n return\n }\n\n // Test 2: Version\n logger.info('\\n2. Getting Claude version...')\n const version = await getClaudeVersion()\n if (version) {\n logger.success(` Version: ${version}`)\n } else {\n logger.error(' Could not get version')\n }\n\n // Test 3: Branch name generation\n logger.info('\\n3. Testing branch name generation...')\n const testIssueNumber = 123\n const testTitle = 'Add user authentication feature'\n logger.info(` Issue #${testIssueNumber}: ${testTitle}`)\n const branchName = await generateBranchName(testTitle, testIssueNumber)\n logger.success(` Generated: ${branchName}`)\n\n // Test 4: Service initialization\n logger.info('\\n4. Testing ClaudeService initialization...')\n new ClaudeService() // Just verify it can be instantiated\n logger.success(' Service initialized')\n\n // Test 5: Context manager\n logger.info('\\n5. Testing ClaudeContextManager...')\n const contextManager = new ClaudeContextManager()\n await contextManager.prepareContext({\n type: 'issue',\n identifier: 123,\n title: 'Test issue',\n workspacePath: process.cwd(),\n port: 3123\n })\n logger.success(' Context prepared')\n\n // Test 6: Template loading\n logger.info('\\n6. Testing template loading...')\n const templateManager = new PromptTemplateManager()\n const templates: Array<'issue' | 'pr' | 'regular'> = ['issue', 'pr', 'regular']\n let templateCount = 0\n for (const template of templates) {\n try {\n await templateManager.loadTemplate(template)\n logger.success(` ${template} template loaded`)\n templateCount++\n } catch {\n logger.warn(` ${template} template not found`)\n }\n }\n logger.info(` Loaded ${templateCount}/${templates.length} templates`)\n\n // Test 7: Launch Claude headless (quick test)\n logger.info('\\n7. Testing Claude launch (headless)...')\n logger.info(' Sending test prompt: \"Say hello\"')\n try {\n const result = await launchClaude('Say hello', { headless: true })\n if (result) {\n logger.success(' Claude responded successfully')\n logger.info(` Response preview: ${result.substring(0, 100)}...`)\n } else {\n logger.warn(' No response received')\n }\n } catch (error) {\n logger.error(` Launch failed: ${error instanceof Error ? error.message : 'Unknown error'}`)\n }\n\n logger.info('\\n' + '='.repeat(50))\n logger.success('All Claude integration tests complete!')\n logger.info('Summary: All core Claude features are working correctly')\n }\n\n } catch (error) {\n logger.error(`Test failed: ${error instanceof Error ? error.message : 'Unknown error'}`)\n if (error instanceof Error && error.stack) {\n logger.debug(error.stack)\n }\n process.exit(1)\n }\n })\n\n// Test command for webserver detection\nprogram\n .command('test-webserver')\n .description('Test if a web server is running on a workspace port')\n .argument('<issue-number>', 'Issue number (port will be calculated as 3000 + issue number)', parseInt)\n .option('--kill', 'Kill the web server if detected')\n .action(async (issueNumber: number, options: { kill?: boolean }) => {\n try {\n const { TestWebserverCommand } = await import('./commands/test-webserver.js')\n const command = new TestWebserverCommand()\n await command.execute({ issueNumber, options })\n } catch (error) {\n logger.error(`Test webserver failed: ${error instanceof Error ? error.message : 'Unknown error'}`)\n if (error instanceof Error && error.stack) {\n logger.debug(error.stack)\n }\n process.exit(1)\n }\n })\n\n// Test command for Git integration\nprogram\n .command('test-git')\n .description('Test Git integration - findMainWorktreePath() function (reads .iloom/settings.json)')\n .action(async () => {\n try {\n const { TestGitCommand } = await import('./commands/test-git.js')\n const command = new TestGitCommand()\n await command.execute()\n } catch (error) {\n logger.error(`Test git failed: ${error instanceof Error ? error.message : 'Unknown error'}`)\n if (error instanceof Error && error.stack) {\n logger.debug(error.stack)\n }\n process.exit(1)\n }\n })\n\n// Test command for iTerm2 dual tab functionality\nprogram\n .command('test-tabs')\n .description('Test iTerm2 dual tab functionality - opens two tabs with test commands')\n .action(async () => {\n try {\n const { TestTabsCommand } = await import('./commands/test-tabs.js')\n const command = new TestTabsCommand()\n await command.execute()\n } catch (error) {\n logger.error(`Test tabs failed: ${error instanceof Error ? error.message : 'Unknown error'}`)\n if (error instanceof Error && error.stack) {\n logger.debug(error.stack)\n }\n process.exit(1)\n }\n })\n\n// Test command for worktree prefix configuration\nprogram\n .command('test-prefix')\n .description('Test worktree prefix configuration - preview worktree paths (reads .iloom/settings.json)')\n .action(async () => {\n try {\n const { TestPrefixCommand } = await import('./commands/test-prefix.js')\n const command = new TestPrefixCommand()\n await command.execute()\n } catch (error) {\n logger.error(`Test prefix failed: ${error instanceof Error ? error.message : 'Unknown error'}`)\n if (error instanceof Error && error.stack) {\n logger.debug(error.stack)\n }\n process.exit(1)\n }\n })\n\n// Test command for Neon integration\nprogram\n .command('test-neon')\n .description('Test Neon integration and debug configuration')\n .action(async () => {\n try {\n const { SettingsManager } = await import('./lib/SettingsManager.js')\n const { createNeonProviderFromSettings } = await import('./utils/neon-helpers.js')\n\n logger.info('Testing Neon Integration\\n')\n\n // Test 1: Settings Configuration\n logger.info('1. Settings Configuration:')\n const settingsManager = new SettingsManager()\n const settings = await settingsManager.loadSettings()\n const neonConfig = settings.databaseProviders?.neon\n logger.info(` projectId: ${neonConfig?.projectId ?? '(not configured)'}`)\n logger.info(` parentBranch: ${neonConfig?.parentBranch ?? '(not configured)'}`)\n\n // Test 2: Create provider and test initialization\n logger.info('\\n2. Creating NeonProvider...')\n try {\n const neonProvider = createNeonProviderFromSettings(settings)\n logger.success(' NeonProvider created successfully')\n\n // Test 3: CLI availability\n logger.info('\\n3. Testing Neon CLI availability...')\n const isAvailable = await neonProvider.isCliAvailable()\n if (isAvailable) {\n logger.success(' Neon CLI is available')\n } else {\n logger.error(' Neon CLI not found')\n logger.info(' Install with: npm install -g @neon/cli')\n return\n }\n\n // Test 4: Authentication\n logger.info('\\n4. Testing Neon CLI authentication...')\n const isAuthenticated = await neonProvider.isAuthenticated()\n if (isAuthenticated) {\n logger.success(' Neon CLI is authenticated')\n } else {\n logger.error(' Neon CLI not authenticated')\n logger.info(' Run: neon auth')\n return\n }\n\n // Test 5: List branches (if config is valid)\n if (neonConfig?.projectId) {\n logger.info('\\n5. Testing branch listing...')\n try {\n const branches = await neonProvider.listBranches()\n logger.success(` Found ${branches.length} branches:`)\n for (const branch of branches.slice(0, 5)) { // Show first 5\n logger.info(` - ${branch}`)\n }\n if (branches.length > 5) {\n logger.info(` ... and ${branches.length - 5} more`)\n }\n } catch (error) {\n logger.error(` Failed to list branches: ${error instanceof Error ? error.message : 'Unknown error'}`)\n }\n } else {\n logger.warn('\\n5. Skipping branch listing (Neon not configured in settings)')\n }\n\n } catch (error) {\n logger.error(` Failed to create NeonProvider: ${error instanceof Error ? error.message : 'Unknown error'}`)\n if (error instanceof Error && error.message.includes('not configured')) {\n logger.info('\\n This is expected if Neon is not configured.')\n logger.info(' Configure databaseProviders.neon in .iloom/settings.json to test fully.')\n }\n }\n\n logger.info('\\n' + '='.repeat(50))\n logger.success('Neon integration test complete!')\n\n } catch (error) {\n logger.error(`Test failed: ${error instanceof Error ? error.message : 'Unknown error'}`)\n if (error instanceof Error && error.stack) {\n logger.debug(error.stack)\n }\n process.exit(1)\n }\n })\n\n// Add custom help command in order to get preAction to run (update check handled by preAction hook)\nprogram\n .command('help')\n .description('Display help information')\n .argument('[command]', 'Show help for specific command')\n .action(async (command?: string) => {\n // Show help (update check already ran in preAction)\n if (command) {\n // Show help for specific command\n const subCommand = program.commands.find(cmd => cmd.name() === command)\n if (subCommand) {\n subCommand.outputHelp()\n } else {\n logger.error(`Unknown command: ${command}`)\n program.outputHelp()\n }\n } else {\n program.outputHelp()\n }\n\n process.exit(0)\n })\n\n// Parse CLI arguments (only when run directly, not when imported for testing)\n// Resolve symlinks to handle npm link and global installs\nconst isRunDirectly = process.argv[1] && ((): boolean => {\n try {\n const scriptPath = realpathSync(process.argv[1])\n const modulePath = fileURLToPath(import.meta.url)\n return scriptPath === modulePath\n } catch {\n // If we can't resolve the path, assume we should run\n return true\n }\n})()\n\nif (isRunDirectly) {\n try {\n await program.parseAsync()\n } catch (error) {\n if (error instanceof Error) {\n logger.error(`Error: ${error.message}`)\n process.exit(1)\n }\n }\n}\n","import path from 'path'\nimport { logger } from '../utils/logger.js'\nimport type { IssueTracker } from '../lib/IssueTracker.js'\nimport { LoomManager } from '../lib/LoomManager.js'\nimport { DefaultBranchNamingService } from '../lib/BranchNamingService.js'\nimport { GitWorktreeManager } from '../lib/GitWorktreeManager.js'\nimport { EnvironmentManager } from '../lib/EnvironmentManager.js'\nimport { ClaudeContextManager } from '../lib/ClaudeContextManager.js'\nimport { ProjectCapabilityDetector } from '../lib/ProjectCapabilityDetector.js'\nimport { CLIIsolationManager } from '../lib/CLIIsolationManager.js'\nimport { SettingsManager } from '../lib/SettingsManager.js'\nimport { AgentManager } from '../lib/AgentManager.js'\nimport { DatabaseManager } from '../lib/DatabaseManager.js'\nimport { findMainWorktreePathWithSettings } from '../utils/git.js'\nimport { loadEnvIntoProcess } from '../utils/env.js'\nimport { extractSettingsOverrides } from '../utils/cli-overrides.js'\nimport { createNeonProviderFromSettings } from '../utils/neon-helpers.js'\nimport { getConfiguredRepoFromSettings, hasMultipleRemotes } from '../utils/remote.js'\nimport { capitalizeFirstLetter } from '../utils/text.js'\nimport type { StartOptions } from '../types/index.js'\nimport { launchFirstRunSetup, needsFirstRunSetup } from '../utils/first-run-setup.js'\nimport { IssueTrackerFactory } from '../lib/IssueTrackerFactory.js'\n\nexport interface StartCommandInput {\n\tidentifier: string\n\toptions: StartOptions\n}\n\nexport interface ParsedInput {\n\ttype: 'issue' | 'pr' | 'branch' | 'description'\n\tnumber?: string | number\n\tbranchName?: string\n\toriginalInput: string\n}\n\nexport class StartCommand {\n\tprivate issueTracker: IssueTracker\n\tprivate loomManager: LoomManager | null = null\n\tprivate settingsManager: SettingsManager\n\tprivate providedLoomManager: LoomManager | undefined\n\n\tconstructor(\n\t\tissueTracker: IssueTracker,\n\t\tloomManager?: LoomManager,\n\t\t_agentManager?: AgentManager, // Kept for API compatibility\n\t\tsettingsManager?: SettingsManager\n\t) {\n\t\tthis.issueTracker = issueTracker\n\t\tthis.settingsManager = settingsManager ?? new SettingsManager()\n\t\t// Store provided LoomManager for testing, but don't initialize yet\n\t\tthis.providedLoomManager = loomManager\n\n\t\t// Load environment variables first\n\t\tconst envResult = loadEnvIntoProcess()\n\t\tif (envResult.error) {\n\t\t\tlogger.debug(`Environment loading warning: ${envResult.error.message}`)\n\t\t}\n\t\tif (envResult.parsed) {\n\t\t\tlogger.debug(`Loaded ${Object.keys(envResult.parsed).length} environment variables`)\n\t\t}\n\t}\n\n\t/**\n\t * Initialize LoomManager with the main worktree path\n\t * Uses lazy initialization to ensure we have the correct path\n\t */\n\tprivate async initializeLoomManager(): Promise<LoomManager> {\n\t\tif (this.loomManager) {\n\t\t\treturn this.loomManager\n\t\t}\n\n\t\tif (this.providedLoomManager) {\n\t\t\tthis.loomManager = this.providedLoomManager\n\t\t\treturn this.loomManager\n\t\t}\n\n\t\t// Find main worktree path\n\t\tconst mainWorktreePath = await findMainWorktreePathWithSettings()\n\n\t\t// Load settings to get database configuration\n\t\tconst settings = await this.settingsManager.loadSettings()\n\n\t\t// Create DatabaseManager with NeonProvider and EnvironmentManager\n\t\tconst environmentManager = new EnvironmentManager()\n\t\tconst neonProvider = createNeonProviderFromSettings(settings)\n\t\tconst databaseUrlEnvVarName = settings.capabilities?.database?.databaseUrlEnvVarName ?? 'DATABASE_URL'\n\n\t\tconst databaseManager = new DatabaseManager(neonProvider, environmentManager, databaseUrlEnvVarName)\n\n\t\t// Create BranchNamingService (defaults to Claude-based strategy)\n\t\tconst branchNaming = new DefaultBranchNamingService({ useClaude: true })\n\n\t\tthis.loomManager = new LoomManager(\n\t\t\tnew GitWorktreeManager(mainWorktreePath),\n\t\t\tthis.issueTracker,\n\t\t\tbranchNaming, // Add branch naming service\n\t\t\tenvironmentManager, // Reuse same instance\n\t\t\tnew ClaudeContextManager(),\n\t\t\tnew ProjectCapabilityDetector(),\n\t\t\tnew CLIIsolationManager(),\n\t\t\tthis.settingsManager, // Use same instance with CLI overrides\n\t\t\tdatabaseManager // Add database manager\n\t\t)\n\n\t\treturn this.loomManager\n\t}\n\n\t/**\n\t * Main entry point for the start command\n\t */\n\tpublic async execute(input: StartCommandInput): Promise<void> {\n\t\ttry {\n\t\t\t// Step 0: Load settings and get configured repo for GitHub operations\n\t\t\tconst initialSettings = await this.settingsManager.loadSettings()\n\n\t\t\tif (process.env.FORCE_FIRST_TIME_SETUP === \"true\" || await needsFirstRunSetup()) {\n\t\t\t\tawait launchFirstRunSetup()\n\t\t\t\t// Reload settings and recreate issueTracker if provider changed during setup\n\t\t\t\tconst newSettings = await this.settingsManager.loadSettings()\n\t\t\t\tconst newProvider = newSettings.issueManagement?.provider ?? 'github'\n\t\t\t\tif (newProvider !== this.issueTracker.providerName) {\n\t\t\t\t\tlogger.debug(`Reinitializing issue tracker: provider changed to \"${newProvider}\"`)\n\t\t\t\t\tthis.issueTracker = IssueTrackerFactory.create(newSettings)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet repo: string | undefined\n\n\t\t\t// Only get repo if we have multiple remotes (prehook already validated config)\n\t\t\tif (this.issueTracker.providerName === 'github' && (await hasMultipleRemotes())) {\n\t\t\t\t// Only relevant for GitHub - Linear doesn't use repo info\n\t\t\t\trepo = await getConfiguredRepoFromSettings(initialSettings)\n\t\t\t\tlogger.info(`Using GitHub repository: ${repo}`)\n\t\t\t}\n\n\t\t\t// Step 0.5: Initialize LoomManager with main worktree path\n\t\t\tconst loomManager = await this.initializeLoomManager()\n\n\t\t\t// Step 0.6: Detect if running from inside an existing loom (for nested loom support)\n\t\t\tlet parentLoom = await this.detectParentLoom(loomManager)\n\n\t\t\t// Step 1: Parse and validate input (pass repo to methods)\n\t\t\tconst parsed = await this.parseInput(input.identifier, repo)\n\n\t\t\t// Step 2: Validate based on type\n\t\t\tawait this.validateInput(parsed, repo)\n\n\t\t\t// Step 2.4: Handle child loom decision\n\t\t\tif (parentLoom) {\n\t\t\t\tconst { isInteractiveEnvironment, promptConfirmation } = await import('../utils/prompt.js')\n\n\t\t\t\t// Format display message based on parent type\n\t\t\t\tconst parentDisplay = parentLoom.type === 'issue'\n\t\t\t\t\t? `issue #${parentLoom.identifier}`\n\t\t\t\t\t: parentLoom.type === 'pr'\n\t\t\t\t\t? `PR #${parentLoom.identifier}`\n\t\t\t\t\t: `branch ${parentLoom.identifier}`\n\n\t\t\t\t// Check for explicit flag first\n\t\t\t\tif (input.options.childLoom === true) {\n\t\t\t\t\t// --child-loom flag: force child loom (no prompt)\n\t\t\t\t\tlogger.info(`Creating as child loom of ${parentDisplay} (--child-loom flag)`)\n\t\t\t\t} else if (input.options.childLoom === false) {\n\t\t\t\t\t// --no-child-loom flag: force independent (no prompt)\n\t\t\t\t\tparentLoom = null\n\t\t\t\t\tlogger.info('Creating as independent loom (--no-child-loom flag)')\n\t\t\t\t} else {\n\t\t\t\t\t// No flag: use existing behavior (prompt or error if non-interactive)\n\t\t\t\t\tlet createAsChild = true // Default for non-interactive\n\t\t\t\t\tif (isInteractiveEnvironment()) {\n\t\t\t\t\t\tcreateAsChild = await promptConfirmation(\n\t\t\t\t\t\t\t`You are not in your main worktree. Create as a child loom of ${parentDisplay}?`,\n\t\t\t\t\t\t\ttrue // Default yes\n\t\t\t\t\t\t)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlogger.error(`Non-interactive environment detected, use either --child-loom or --no-child-loom to specify behavior`)\n\t\t\t\t\t\tprocess.exit(1)\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!createAsChild) {\n\t\t\t\t\t\tparentLoom = null // User declined, proceed as normal loom\n\t\t\t\t\t\tlogger.info('Creating as independent loom')\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (input.options.childLoom === true) {\n\t\t\t\t// --child-loom flag but not in a parent loom - ignore silently (per requirements)\n\t\t\t\tlogger.debug('--child-loom flag provided but not running from inside an existing loom (ignored)')\n\t\t\t}\n\t\t\t// Note: --no-child-loom when no parent is a no-op (already independent)\n\n\t\t\t// Step 2.5: Handle description input - create GitHub issue\n\t\t\tif (parsed.type === 'description') {\n\t\t\t\tlogger.info('Creating GitHub issue from description...')\n\t\t\t\t// Apply first-letter capitalization to title and body\n\t\t\t\tconst title = capitalizeFirstLetter(parsed.originalInput)\n\t\t\t\tconst body = input.options.body ? capitalizeFirstLetter(input.options.body) : \"\"\n\t\t\t\tconst result = await this.issueTracker.createIssue(\n\t\t\t\t\ttitle, // Use capitalized description as title\n\t\t\t\t\tbody // Use capitalized body or empty\n\t\t\t\t)\n\t\t\t\tlogger.success(`Created issue #${result.number}: ${result.url}`)\n\t\t\t\t// Update parsed to be an issue type with the new number\n\t\t\t\tparsed.type = 'issue'\n\t\t\t\tparsed.number = result.number\n\t\t\t}\n\n\t\t\t// Step 2.7: Confirm bypassPermissions mode if applicable\n\t\t\tif (input.options.oneShot === 'bypassPermissions') {\n\t\t\t\tconst { promptConfirmation } = await import('../utils/prompt.js')\n\t\t\t\tconst confirmed = await promptConfirmation(\n\t\t\t\t\t'⚠️ WARNING: bypassPermissions mode will allow Claude to execute all tool calls without confirmation. ' +\n\t\t\t\t\t'This can be dangerous. Do you want to proceed?'\n\t\t\t\t)\n\t\t\t\tif (!confirmed) {\n\t\t\t\t\tlogger.info('Operation cancelled by user')\n\t\t\t\t\tprocess.exit(0)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Step 2.8: Load workflow-specific settings with CLI overrides\n\t\t\tconst cliOverrides = extractSettingsOverrides()\n\t\t\tconst settings = await this.settingsManager.loadSettings(undefined, cliOverrides)\n\t\t\tconst workflowType = parsed.type === 'branch' ? 'regular' : parsed.type\n\t\t\tconst workflowConfig = settings.workflows?.[workflowType]\n\n\t\t\t// Step 2.9: Extract raw --set arguments and executable path for forwarding to spin\n\t\t\tconst { extractRawSetArguments, getExecutablePath } = await import('../utils/cli-overrides.js')\n\t\t\tconst setArguments = extractRawSetArguments()\n\t\t\tconst executablePath = getExecutablePath()\n\n\t\t\t// Step 3: Log success and create loom\n\t\t\tlogger.info(`✅ Validated input: ${this.formatParsedInput(parsed)}`)\n\n\t\t\t// Step 4: Create loom using LoomManager\n\t\t\tconst identifier =\n\t\t\t\tparsed.type === 'branch'\n\t\t\t\t\t? parsed.branchName ?? ''\n\t\t\t\t\t: parsed.number ?? 0\n\n\t\t\t// Apply configuration precedence: CLI flags > workflow config > defaults (true)\n\t\t\tconst enableClaude = input.options.claude ?? workflowConfig?.startAiAgent ?? true\n\t\t\tconst enableCode = input.options.code ?? workflowConfig?.startIde ?? true\n\t\t\tconst enableDevServer = input.options.devServer ?? workflowConfig?.startDevServer ?? true\n\t\t\tconst enableTerminal = input.options.terminal ?? workflowConfig?.startTerminal ?? false\n\n\t\t\tlogger.debug('Final workflow config values:', {\n\t\t\t\tenableClaude,\n\t\t\t\tenableCode,\n\t\t\t\tenableDevServer,\n\t\t\t\tenableTerminal,\n\t\t\t})\n\n\t\t\tconst loom = await loomManager.createIloom({\n\t\t\t\ttype: parsed.type,\n\t\t\t\tidentifier,\n\t\t\t\toriginalInput: parsed.originalInput,\n\t\t\t\t...(parentLoom && { parentLoom }),\n\t\t\t\toptions: {\n\t\t\t\t\tenableClaude,\n\t\t\t\t\tenableCode,\n\t\t\t\t\tenableDevServer,\n\t\t\t\t\tenableTerminal,\n\t\t\t\t\t...(input.options.oneShot && { oneShot: input.options.oneShot }),\n\t\t\t\t\t...(setArguments.length > 0 && { setArguments }),\n\t\t\t\t\t...(executablePath && { executablePath }),\n\t\t\t\t},\n\t\t\t})\n\n\t\t\tlogger.success(`✅ Created loom: ${loom.id} at ${loom.path}`)\n\t\t\tlogger.info(` Branch: ${loom.branch}`)\n\t\t\t// Only show port for web projects\n\t\t\tif (loom.capabilities?.includes('web')) {\n\t\t\t\tlogger.info(` Port: ${loom.port}`)\n\t\t\t}\n\t\t\tif (loom.issueData?.title) {\n\t\t\t\tlogger.info(` Title: ${loom.issueData.title}`)\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error) {\n\t\t\t\tlogger.error(`❌ ${error.message}`)\n\t\t\t} else {\n\t\t\t\tlogger.error('❌ An unknown error occurred')\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t/**\n\t * Parse input to determine type and extract relevant data\n\t */\n\tprivate async parseInput(identifier: string, repo?: string): Promise<ParsedInput> {\n\t\t// Check if user wants to skip capitalization by prefixing with space\n\t\t// We preserve this for description types so capitalizeFirstLetter() can handle it\n\t\tconst hasLeadingSpace = identifier.startsWith(' ')\n\n\t\t// Handle empty input\n\t\tconst trimmedIdentifier = identifier.trim()\n\t\tif (!trimmedIdentifier) {\n\t\t\tthrow new Error('Missing required argument: identifier')\n\t\t}\n\n\t\t// Check for description: >25 chars AND >2 spaces (in trimmed version)\n\t\tconst spaceCount = (trimmedIdentifier.match(/ /g) ?? []).length\n\t\tif (trimmedIdentifier.length > 25 && spaceCount > 2) {\n\t\t\t// Preserve leading space if present so capitalizeFirstLetter() can detect the override\n\t\t\treturn {\n\t\t\t\ttype: 'description',\n\t\t\t\toriginalInput: hasLeadingSpace ? ' ' + trimmedIdentifier : trimmedIdentifier,\n\t\t\t}\n\t\t}\n\n\t\t// Check for PR-specific formats: pr/123, PR-123, PR/123, Pr-123 (case-insensitive)\n\t\tconst prPattern = /^pr[/-](\\d+)$/i\n\t\tconst prMatch = trimmedIdentifier.match(prPattern)\n\t\tif (prMatch?.[1]) {\n\t\t\treturn {\n\t\t\t\ttype: 'pr',\n\t\t\t\tnumber: parseInt(prMatch[1], 10),\n\t\t\t\toriginalInput: trimmedIdentifier,\n\t\t\t}\n\t\t}\n\n\t\t// Check for Linear identifier format (TEAM-NUMBER, e.g., ENG-123, PLAT-456)\n\t\t// Requires at least 2 letters before dash to avoid conflict with PR-123 format\n\t\tconst linearPattern = /^([A-Z]{2,}-\\d+)$/i\n\t\tconst linearMatch = trimmedIdentifier.match(linearPattern)\n\t\tif (linearMatch?.[1]) {\n\t\t\t// Use IssueTracker to validate it exists\n\t\t\tconst detection = await this.issueTracker.detectInputType(\n\t\t\t\ttrimmedIdentifier,\n\t\t\t\trepo\n\t\t\t)\n\n\t\t\tif (detection.type === 'issue' && detection.identifier) {\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'issue',\n\t\t\t\t\tnumber: detection.identifier, // Keep as string for Linear\n\t\t\t\t\toriginalInput: trimmedIdentifier,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Linear identifier format matched but not found\n\t\t\tthrow new Error(\n\t\t\t\t`Could not find Linear issue ${linearMatch[1].toUpperCase()}`\n\t\t\t)\n\t\t}\n\n\t\t// Check for numeric pattern (could be issue or PR)\n\t\tconst numericPattern = /^#?(\\d+)$/\n\t\tconst numericMatch = trimmedIdentifier.match(numericPattern)\n\t\tif (numericMatch?.[1]) {\n\t\t\tconst number = parseInt(numericMatch[1], 10)\n\n\t\t\t// Use IssueTracker to detect if it's a PR or issue\n\t\t\tconst detection = await this.issueTracker.detectInputType(\n\t\t\t\ttrimmedIdentifier,\n\t\t\t\trepo\n\t\t\t)\n\n\t\t\tif (detection.type === 'pr') {\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'pr',\n\t\t\t\t\tnumber: detection.identifier ? parseInt(detection.identifier, 10) : number,\n\t\t\t\t\toriginalInput: trimmedIdentifier,\n\t\t\t\t}\n\t\t\t} else if (detection.type === 'issue') {\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'issue',\n\t\t\t\t\tnumber: detection.identifier ? parseInt(detection.identifier, 10) : number,\n\t\t\t\t\toriginalInput: trimmedIdentifier,\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow new Error(`Could not find issue or PR #${number}`)\n\t\t\t}\n\t\t}\n\n\t\t// Treat as branch name\n\t\treturn {\n\t\t\ttype: 'branch',\n\t\t\tbranchName: trimmedIdentifier,\n\t\t\toriginalInput: trimmedIdentifier,\n\t\t}\n\t}\n\n\t/**\n\t * Validate the parsed input based on its type\n\t */\n\tprivate async validateInput(parsed: ParsedInput, repo?: string): Promise<void> {\n\t\tswitch (parsed.type) {\n\t\t\tcase 'pr': {\n\t\t\t\tif (!parsed.number) {\n\t\t\t\t\tthrow new Error('Invalid PR number')\n\t\t\t\t}\n\t\t\t\t// Check if provider supports PRs before calling PR methods\n\t\t\t\tif (!this.issueTracker.supportsPullRequests || !this.issueTracker.fetchPR || !this.issueTracker.validatePRState) {\n\t\t\t\t\tthrow new Error('Issue tracker does not support pull requests')\n\t\t\t\t}\n\t\t\t\t// Fetch and validate PR state\n\t\t\t\tconst pr = await this.issueTracker.fetchPR(parsed.number, repo)\n\t\t\t\tawait this.issueTracker.validatePRState(pr)\n\t\t\t\tlogger.debug(`Validated PR #${parsed.number}`)\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tcase 'issue': {\n\t\t\t\tif (!parsed.number) {\n\t\t\t\t\tthrow new Error('Invalid issue number')\n\t\t\t\t}\n\t\t\t\t// Fetch and validate issue state\n\t\t\t\tconst issue = await this.issueTracker.fetchIssue(parsed.number, repo)\n\t\t\t\tawait this.issueTracker.validateIssueState(issue)\n\t\t\t\tlogger.debug(`Validated issue #${parsed.number}`)\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tcase 'branch': {\n\t\t\t\tif (!parsed.branchName) {\n\t\t\t\t\tthrow new Error('Invalid branch name')\n\t\t\t\t}\n\t\t\t\t// Validate branch name characters (from bash script line 586)\n\t\t\t\tif (!this.isValidBranchName(parsed.branchName)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t'Invalid branch name. Use only letters, numbers, hyphens, underscores, and slashes'\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tlogger.debug(`Validated branch name: ${parsed.branchName}`)\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tcase 'description': {\n\t\t\t\t// Description inputs are valid - they will be converted to issues\n\t\t\t\tlogger.debug('Detected description input', {\n\t\t\t\t\tlength: parsed.originalInput.length\n\t\t\t\t})\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tconst unknownType = parsed as { type: string }\n\t\t\t\tthrow new Error(`Unknown input type: ${unknownType.type}`)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Validate branch name format\n\t */\n\tprivate isValidBranchName(branch: string): boolean {\n\t\t// Pattern from bash script line 586\n\t\treturn /^[a-zA-Z0-9/_-]+$/.test(branch)\n\t}\n\n\t/**\n\t * Format parsed input for display\n\t */\n\tprivate formatParsedInput(parsed: ParsedInput): string {\n\t\tswitch (parsed.type) {\n\t\t\tcase 'pr':\n\t\t\t\treturn `PR #${parsed.number}`\n\t\t\tcase 'issue':\n\t\t\t\treturn `Issue #${parsed.number}`\n\t\t\tcase 'branch':\n\t\t\t\treturn `Branch '${parsed.branchName}'`\n\t\t\tcase 'description':\n\t\t\t\treturn `Description: ${parsed.originalInput.slice(0, 50)}...`\n\t\t\tdefault:\n\t\t\t\treturn 'Unknown input'\n\t\t}\n\t}\n\n\t/**\n\t * Detect if running from inside an existing loom worktree\n\t * Returns parent loom info if detected, null otherwise\n\t */\n\tprivate async detectParentLoom(loomManager: LoomManager): Promise<{\n\t\ttype: 'issue' | 'pr' | 'branch'\n\t\tidentifier: string | number\n\t\tbranchName: string\n\t\tworktreePath: string\n\t\tdatabaseBranch?: string\n\t} | null> {\n\t\ttry {\n\t\t\tconst cwd = process.cwd()\n\t\t\tconst looms = await loomManager.listLooms()\n\n\t\t\tif (!looms) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\t// Get main worktree path to exclude it from valid parents\n\t\t\tconst mainWorktreePath = await findMainWorktreePathWithSettings()\n\n\t\t\t// Find loom containing current directory\n\t\t\t// Fix #2: Add path.sep check to prevent false positives (e.g., issue-123 vs issue-1234)\n\t\t\t// Exclude main worktree from being a valid parent\n\t\t\tconst parentLoom = looms.find(loom => {\n\t\t\t\t// Skip main worktree - it shouldn't be a parent for child looms\n\t\t\t\tif (loom.path === mainWorktreePath) {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t\t// Either exact match OR cwd starts with loom.path followed by path separator\n\t\t\t\treturn cwd === loom.path || cwd.startsWith(loom.path + path.sep)\n\t\t\t})\n\t\t\tif (!parentLoom) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tlogger.debug(`Detected parent loom: ${parentLoom.type} ${parentLoom.identifier} at ${parentLoom.path}`)\n\n\t\t\tconst result: {\n\t\t\t\ttype: 'issue' | 'pr' | 'branch'\n\t\t\t\tidentifier: string | number\n\t\t\t\tbranchName: string\n\t\t\t\tworktreePath: string\n\t\t\t\tdatabaseBranch?: string\n\t\t\t} = {\n\t\t\t\ttype: parentLoom.type,\n\t\t\t\tidentifier: parentLoom.identifier,\n\t\t\t\tbranchName: parentLoom.branch,\n\t\t\t\tworktreePath: parentLoom.path,\n\t\t\t}\n\n\t\t\t// Only include databaseBranch if it exists (exactOptionalPropertyTypes compatibility)\n\t\t\tif (parentLoom.databaseBranch) {\n\t\t\t\tresult.databaseBranch = parentLoom.databaseBranch\n\t\t\t}\n\n\t\t\t// Try to get database branch from parent's .env file via reverse lookup\n\t\t\tif (!result.databaseBranch) {\n\t\t\t\tconst databaseBranch = await loomManager.getDatabaseBranchForLoom(parentLoom.path)\n\t\t\t\tif (databaseBranch) {\n\t\t\t\t\tresult.databaseBranch = databaseBranch\n\t\t\t\t\tlogger.debug(`Detected parent database branch: ${databaseBranch}`)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn result\n\t\t} catch (error) {\n\t\t\t// If detection fails for any reason, just return null (don't break the start workflow)\n\t\t\tlogger.debug(`Failed to detect parent loom: ${error instanceof Error ? error.message : 'Unknown error'}`)\n\t\t\treturn null\n\t\t}\n\t}\n\n}\n","import { existsSync } from 'fs'\nimport { readFile } from 'fs/promises'\nimport path from 'path'\nimport { logger } from './logger.js'\nimport { FirstRunManager } from './FirstRunManager.js'\nimport { getRepoRoot } from './git.js'\nimport { InitCommand } from '../commands/init.js'\n\n/**\n * Get the project root path for first-run tracking\n * Uses git repo root if available, otherwise falls back to cwd\n * This ensures consistent path resolution regardless of where the CLI is run from\n */\nasync function getProjectRoot(): Promise<string> {\n\tconst repoRoot = await getRepoRoot()\n\tif (repoRoot) {\n\t\tlogger.debug(`getProjectRoot: Using git repo root: ${repoRoot}`)\n\t\treturn repoRoot\n\t}\n\tconst cwd = process.cwd()\n\tlogger.debug(`getProjectRoot: Not in git repo, using cwd: ${cwd}`)\n\treturn cwd\n}\n\n/**\n * Check if project needs first-run setup\n * Returns true if:\n * 1. Project is not tracked as configured globally AND\n * 2. .iloom directory is missing or settings files are empty\n *\n * Also performs fixup for legacy projects that have local config but lack\n * the global marker file (configured before global tracking was implemented)\n *\n * Uses git repo root for path resolution to ensure consistent behavior\n * regardless of whether the CLI is run from a subdirectory or worktree\n */\nexport async function needsFirstRunSetup(): Promise<boolean> {\n\tconst projectRoot = await getProjectRoot()\n\tconst firstRunManager = new FirstRunManager()\n\n\t// Fixup legacy projects that have local config but no global marker\n\t// This also returns whether the project is configured, avoiding duplicate isProjectConfigured() call\n\tconst { isConfigured } = await firstRunManager.fixupLegacyProject(projectRoot)\n\n\t// Check if project is tracked as configured globally\n\tif (isConfigured) {\n\t\tlogger.debug('needsFirstRunSetup: Project is tracked as configured globally')\n\t\treturn false\n\t}\n\n\tconst iloomDir = path.join(projectRoot, '.iloom')\n\n\t// Check if .iloom directory exists\n\tif (!existsSync(iloomDir)) {\n\t\treturn true\n\t}\n\n\t// Check if either settings file has meaningful content\n\tconst settingsPath = path.join(iloomDir, 'settings.json')\n\tconst settingsLocalPath = path.join(iloomDir, 'settings.local.json')\n\n\tconst hasSettings = await hasNonEmptySettings(settingsPath)\n\tconst hasLocalSettings = await hasNonEmptySettings(settingsLocalPath)\n\n\treturn !hasSettings && !hasLocalSettings\n}\n\nasync function hasNonEmptySettings(filePath: string): Promise<boolean> {\n\tif (!existsSync(filePath)) return false\n\ttry {\n\t\tconst content = await readFile(filePath, 'utf-8')\n\t\tconst parsed = JSON.parse(content)\n\t\treturn Object.keys(parsed).length > 0\n\t} catch {\n\t\treturn false\n\t}\n}\n\n/**\n * Launch interactive first-run setup via InitCommand\n */\nexport async function launchFirstRunSetup(): Promise<void> {\n\tlogger.info('First-time project setup detected.')\n\tlogger.info(\n\t\t'iloom will now launch an interactive configuration session with Claude.'\n\t)\n\n\tconst { waitForKeypress } = await import('./prompt.js')\n\tawait waitForKeypress('Press any key to start configuration...')\n\n\tconst initCommand = new InitCommand()\n\tawait initCommand.execute(\n\t\t'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.'\n\t)\n\n\t// Mark project as configured to prevent wizard from re-triggering\n\t// Use the same project root resolution as needsFirstRunSetup() for consistency\n\tconst projectRoot = await getProjectRoot()\n\tlogger.debug(`Marking project as configured at root: ${projectRoot}`)\n\tconst firstRunManager = new FirstRunManager()\n\tawait firstRunManager.markProjectAsConfigured(projectRoot)\n\tlogger.debug(`Project marked as configured at root: ${projectRoot}`)\n\n\tlogger.info('Configuration complete! Continuing with your original command...')\n}\n","import type { AddIssueOptions } from '../types/index.js'\nimport { IssueEnhancementService } from '../lib/IssueEnhancementService.js'\nimport { SettingsManager } from '../lib/SettingsManager.js'\nimport { getConfiguredRepoFromSettings, hasMultipleRemotes } from '../utils/remote.js'\nimport { launchFirstRunSetup, needsFirstRunSetup } from '../utils/first-run-setup.js'\nimport { logger } from '../utils/logger.js'\nimport { capitalizeFirstLetter } from '../utils/text.js'\n\n/**\n * Input structure for AddIssueCommand\n */\nexport interface AddIssueCommandInput {\n\tdescription: string\n\toptions: AddIssueOptions\n}\n\n/**\n * Command to create and enhance GitHub issues without creating workspaces.\n * This separates the \"document the work\" step from the \"start the work\" step.\n */\nexport class AddIssueCommand {\n\tprivate enhancementService: IssueEnhancementService\n\tprivate settingsManager: SettingsManager\n\n\tconstructor(enhancementService: IssueEnhancementService, settingsManager?: SettingsManager) {\n\t\tthis.enhancementService = enhancementService\n\t\tthis.settingsManager = settingsManager ?? new SettingsManager()\n\t}\n\n\t/**\n\t * Execute the add-issue command workflow:\n\t * 1. Validate description format\n\t * 2. Skip enhancement if body provided, otherwise enhance description with Claude Code\n\t * 3. Create GitHub issue\n\t * 4. Wait for keypress and open browser for review\n\t * 5. Return issue number\n\t */\n\tpublic async execute(input: AddIssueCommandInput): Promise<string | number> {\n\t\t// Apply first-letter capitalization to title (description) and body\n\t\tconst description = capitalizeFirstLetter(input.description)\n\t\tconst body = input.options.body ? capitalizeFirstLetter(input.options.body) : undefined\n\n\t\t// Step 0: Check for first-run setup\n\t\tif (process.env.FORCE_FIRST_TIME_SETUP === \"true\" || await needsFirstRunSetup()) {\n\t\t\tawait launchFirstRunSetup()\n\t\t}\n\n\t\t// Step 0.5: Load settings and get configured repo for GitHub operations\n\t\tconst settings = await this.settingsManager.loadSettings()\n\n\t\tlet repo: string | undefined\n\n\t\tif (this.enhancementService.issueTracker.providerName === 'github' && await hasMultipleRemotes()) {\n\t\t\t// Only relevant for GitHub - Linear doesn't use repo info\n\t\t\trepo = await getConfiguredRepoFromSettings(settings)\n\t\t\tlogger.info(`Using GitHub repository: ${repo}`)\n\t\t}\n\n\t\t// Step 1: Validate description format\n\t\tif (!description || !this.enhancementService.validateDescription(description)) {\n\t\t\tthrow new Error('Description is required and must be more than 30 characters with at least 3 words')\n\t\t}\n\n\t\t// Step 2: Skip enhancement if body provided, otherwise enhance description\n\t\tconst issueBody = body ?? await this.enhancementService.enhanceDescription(description)\n\n\t\t// Step 3: Create GitHub issue with original as title, body as body\n\t\tconst result = await this.enhancementService.createEnhancedIssue(\n\t\t\tdescription,\n\t\t\tissueBody,\n\t\t\trepo\n\t\t)\n\n\t\t// Step 4: Wait for keypress and open issue in browser for review\n\t\tawait this.enhancementService.waitForReviewAndOpen(result.number)\n\n\t\t// Step 5: Return issue number for reference\n\t\treturn result.number\n\t}\n}\n","import type { IssueTracker } from '../lib/IssueTracker.js'\nimport type { AgentManager } from '../lib/AgentManager.js'\nimport type { SettingsManager } from '../lib/SettingsManager.js'\nimport { launchClaude } from '../utils/claude.js'\nimport { openBrowser } from '../utils/browser.js'\nimport { waitForKeypress } from '../utils/prompt.js'\nimport { logger } from '../utils/logger.js'\nimport { generateIssueManagementMcpConfig } from '../utils/mcp.js'\nimport { AgentManager as DefaultAgentManager } from '../lib/AgentManager.js'\nimport { SettingsManager as DefaultSettingsManager } from '../lib/SettingsManager.js'\nimport { getConfiguredRepoFromSettings, hasMultipleRemotes } from '../utils/remote.js'\nimport { launchFirstRunSetup, needsFirstRunSetup } from '../utils/first-run-setup.js'\n\nexport interface EnhanceCommandInput {\n\tissueNumber: string | number\n\toptions: EnhanceOptions\n}\n\nexport interface EnhanceOptions {\n\tnoBrowser?: boolean // Skip browser opening prompt\n\tauthor?: string // GitHub username of issue author for tagging\n}\n\n/**\n * Command to enhance existing GitHub issues with AI assistance.\n * Applies the issue enhancer agent to an existing issue, respecting idempotency checks.\n */\nexport class EnhanceCommand {\n\tprivate issueTracker: IssueTracker\n\tprivate agentManager: AgentManager\n\tprivate settingsManager: SettingsManager\n\n\tconstructor(\n\t\tissueTracker: IssueTracker,\n\t\tagentManager?: AgentManager,\n\t\tsettingsManager?: SettingsManager\n\t) {\n\t\tthis.issueTracker = issueTracker\n\t\tthis.agentManager = agentManager ?? new DefaultAgentManager()\n\t\tthis.settingsManager = settingsManager ?? new DefaultSettingsManager()\n\t}\n\n\t/**\n\t * Execute the enhance command workflow:\n\t * 1. Validate issue number\n\t * 2. Fetch issue to verify it exists\n\t * 3. Load agent configurations\n\t * 4. Invoke Claude CLI with enhancer agent\n\t * 5. Parse response to determine outcome\n\t * 6. Handle browser interaction based on outcome\n\t */\n\tpublic async execute(input: EnhanceCommandInput): Promise<void> {\n\t\tconst { issueNumber, options } = input\n\t\tconst { author } = options\n\n\t\t// Step 0: Check for first-run setup\n\t\tif (process.env.FORCE_FIRST_TIME_SETUP === \"true\" || await needsFirstRunSetup()) {\n\t\t\tawait launchFirstRunSetup()\n\t\t}\n\n\t\t// Step 0.5: Load settings and get configured repo for GitHub operations\n\t\tconst settings = await this.settingsManager.loadSettings()\n\n\t\tlet repo: string | undefined\n\n\t\tif (this.issueTracker.providerName === 'github' && (await hasMultipleRemotes())) {\n\t\t\t// Only relevant for GitHub - Linear doesn't use repo info\n\t\t\trepo = await getConfiguredRepoFromSettings(settings)\n\t\t\tlogger.info(`Using GitHub repository: ${repo}`)\n\t\t}\n\n\t\t// Step 1: Validate issue number\n\t\tthis.validateIssueNumber(issueNumber)\n\n\t\t// Step 2: Fetch issue to verify it exists\n\t\tlogger.info(`Fetching issue #${issueNumber}...`)\n\t\tconst issue = await this.issueTracker.fetchIssue(issueNumber, repo)\n\t\tlogger.debug('Issue fetched successfully', { number: issue.number, title: issue.title })\n\n\t\t// Step 3: Load agent configurations\n\t\tlogger.debug('Loading agent configurations...')\n\t\tconst loadedAgents = await this.agentManager.loadAgents(settings)\n\t\tconst agents = this.agentManager.formatForCli(loadedAgents)\n\n\t\t// Step 3.5: Generate MCP config and tool filtering for issue management\n\t\tlet mcpConfig: Record<string, unknown>[] | undefined\n\t\tlet allowedTools: string[] | undefined\n\t\tlet disallowedTools: string[] | undefined\n\n\t\ttry {\n\t\t\tconst provider = this.issueTracker.providerName as 'github' | 'linear'\n\t\t\tmcpConfig = await generateIssueManagementMcpConfig('issue', repo, provider, settings)\n\t\t\tlogger.debug('Generated MCP configuration for issue management:', { mcpConfig })\n\n\t\t\t// Configure tool filtering for issue workflows\n\t\t\tallowedTools = [\n\t\t\t\t'mcp__issue_management__get_issue',\n\t\t\t\t'mcp__issue_management__get_comment',\n\t\t\t\t'mcp__issue_management__create_comment',\n\t\t\t\t'mcp__issue_management__update_comment',\n\t\t\t]\n\t\t\tdisallowedTools = ['Bash(gh api:*)']\n\n\t\t\tlogger.debug('Configured tool filtering for issue workflow', { allowedTools, disallowedTools })\n\t\t} catch (error) {\n\t\t\t// Log warning but continue without MCP\n\t\t\tlogger.warn(`Failed to generate MCP config: ${error instanceof Error ? error.message : 'Unknown error'}`)\n\t\t}\n\n\t\t// Step 4: Invoke Claude CLI with enhancer agent\n\t\tlogger.info('Invoking enhancer agent. This may take a moment...')\n\t\tconst prompt = this.constructPrompt(issueNumber, author)\n\t\tconst response = await launchClaude(prompt, {\n\t\t\theadless: true,\n\t\t\tmodel: 'sonnet',\n\t\t\tagents,\n\t\t\t...(mcpConfig && { mcpConfig }),\n\t\t\t...(allowedTools && { allowedTools }),\n\t\t\t...(disallowedTools && { disallowedTools }),\n\t\t})\n\n\t\t// Step 5: Parse response to determine outcome\n\t\tconst result = this.parseEnhancerResponse(response)\n\n\t\t// Step 6: Handle browser interaction based on outcome\n\t\tif (!result.enhanced) {\n\t\t\tlogger.success('Issue already has thorough description. No enhancement needed.')\n\t\t\treturn\n\t\t}\n\n\t\tlogger.success(`Issue #${issueNumber} enhanced successfully!`)\n\t\tlogger.info(`Enhanced specification available at: ${result.url}`)\n\n\t\t// Prompt to open browser (unless --no-browser flag is set)\n\t\tif (!options.noBrowser && result.url) {\n\t\t\tawait this.promptAndOpenBrowser(result.url)\n\t\t}\n\t}\n\n\t/**\n\t * Validate that issue number is a valid positive integer\n\t */\n\tprivate validateIssueNumber(issueNumber: string | number): void {\n\t\tif (issueNumber === undefined || issueNumber === null) {\n\t\t\tthrow new Error('Issue number is required')\n\t\t}\n\n\t\t// For numeric types, validate as before\n\t\tif (typeof issueNumber === 'number') {\n\t\t\tif (Number.isNaN(issueNumber) || issueNumber <= 0 || !Number.isInteger(issueNumber)) {\n\t\t\t\tthrow new Error('Issue number must be a valid positive integer')\n\t\t\t}\n\t\t}\n\t\t// For string types, validate non-empty\n\t\tif (typeof issueNumber === 'string' && issueNumber.trim().length === 0) {\n\t\t\tthrow new Error('Issue identifier cannot be empty')\n\t\t}\n\t}\n\n\t/**\n\t * Construct the prompt for the orchestrating Claude instance.\n\t * This prompt is very clear about expected output format to ensure reliable parsing.\n\t */\n\tprivate constructPrompt(issueNumber: string | number, author?: string): string {\n\t\tconst authorInstruction = author\n\t\t\t? `\\nIMPORTANT: When you create your analysis comment, tag @${author} in the \"Questions for Reporter\" section if you have questions.\\n`\n\t\t\t: ''\n\n\t\treturn `Execute @agent-iloom-issue-enhancer ${issueNumber}${authorInstruction}\n\n## OUTPUT REQUIREMENTS\n* If the issue was not enhanced, return ONLY: \"No enhancement needed\"\n* If the issue WAS enhanced, return ONLY: <FULL URL OF THE COMMENT INCLUDING COMMENT ID>\n* If you encounter permission/authentication/access errors, return ONLY: \"Permission denied: <specific error description>\"\n* IMPORTANT: Return ONLY one of the above - DO NOT include commentary such as \"I created a comment at <URL>\" or \"I examined the issue and found no enhancement was necessary\"\n* CONTEXT: Your output is going to be parsed programmatically, so adherence to the output requirements is CRITICAL.`\n\t}\n\n\t/**\n\t * Parse the response from the enhancer agent.\n\t * Returns either { enhanced: false } or { enhanced: true, url: \"...\" }\n\t * Throws specific errors for permission issues.\n\t */\n\tprivate parseEnhancerResponse(response: string | void): { enhanced: boolean; url?: string } {\n\t\t// Handle empty or void response\n\t\tif (!response || typeof response !== 'string') {\n\t\t\tthrow new Error('No response from enhancer agent')\n\t\t}\n\n\t\tconst trimmed = response.trim()\n\t\n\t\tlogger.debug(`RESPONSE FROM ENHANCER AGENT: '${trimmed}'`)\n\n\t\t// Check for permission denied errors (case-insensitive)\n\t\tif (trimmed.toLowerCase().startsWith('permission denied:')) {\n\t\t\tconst errorMessage = trimmed.substring('permission denied:'.length).trim()\n\t\t\tthrow new Error(`Permission denied: ${errorMessage}`)\n\t\t}\n\n\t\t// Check for \"No enhancement needed\" (case-insensitive)\n\t\tif (trimmed.toLowerCase().includes('no enhancement needed')) {\n\t\t\treturn { enhanced: false }\n\t\t}\n\n\t\t// Check if response looks like a GitHub comment URL\n\t\tconst urlPattern = /https:\\/\\/github\\.com\\/[^/]+\\/[^/]+\\/issues\\/\\d+#issuecomment-\\d+/\n\t\tconst match = trimmed.match(urlPattern)\n\n\t\tif (match) {\n\t\t\treturn { enhanced: true, url: match[0] }\n\t\t}\n\n\t\t// Unexpected response format\n\t\tthrow new Error(`Unexpected response from enhancer agent: ${trimmed}`)\n\t}\n\n\t/**\n\t * Prompt user and open browser to view enhanced issue.\n\t * Matches the pattern from the issue specification.\n\t */\n\tprivate async promptAndOpenBrowser(commentUrl: string): Promise<void> {\n\t\ttry {\n\t\t\t// Prompt user with custom message\n\t\t\tconst key = await waitForKeypress(\n\t\t\t\t'Press q to quit or any other key to view the enhanced issue in a web browser...'\n\t\t\t)\n\n\t\t\t// Check if user pressed 'q' to quit\n\t\t\tif (key.toLowerCase() === 'q') {\n\t\t\t\tlogger.info('Skipping browser opening')\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Open browser with comment URL\n\t\t\tawait openBrowser(commentUrl)\n\t\t} catch (error) {\n\t\t\t// Browser opening failures should not be fatal\n\t\t\tlogger.warn(`Failed to open browser: ${error instanceof Error ? error.message : 'Unknown error'}`)\n\t\t}\n\t}\n\n}\n","import { logger } from '../utils/logger.js'\nimport { detectPackageManager, runScript } from '../utils/package-manager.js'\nimport { readPackageJson, hasScript } from '../utils/package-json.js'\nimport { detectClaudeCli, launchClaude } from '../utils/claude.js'\nimport type {\n\tValidationOptions,\n\tValidationResult,\n\tValidationStepResult,\n} from '../types/index.js'\n\n/**\n * ValidationRunner orchestrates pre-merge validation pipeline\n * Runs typecheck, lint, and tests in sequence with fail-fast behavior\n */\nexport class ValidationRunner {\n\t/**\n\t * Run all validations in sequence: typecheck → lint → test\n\t * Fails fast on first error\n\t */\n\tasync runValidations(\n\t\tworktreePath: string,\n\t\toptions: ValidationOptions = {}\n\t): Promise<ValidationResult> {\n\t\tconst startTime = Date.now()\n\t\tconst steps: ValidationStepResult[] = []\n\n\t\t// Run typecheck\n\t\tif (!options.skipTypecheck) {\n\t\t\tconst typecheckResult = await this.runTypecheck(\n\t\t\t\tworktreePath,\n\t\t\t\toptions.dryRun ?? false\n\t\t\t)\n\t\t\tsteps.push(typecheckResult)\n\n\t\t\tif (!typecheckResult.passed && !typecheckResult.skipped) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\tsteps,\n\t\t\t\t\ttotalDuration: Date.now() - startTime,\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Run lint\n\t\tif (!options.skipLint) {\n\t\t\tconst lintResult = await this.runLint(worktreePath, options.dryRun ?? false)\n\t\t\tsteps.push(lintResult)\n\n\t\t\tif (!lintResult.passed && !lintResult.skipped) {\n\t\t\t\treturn { success: false, steps, totalDuration: Date.now() - startTime }\n\t\t\t}\n\t\t}\n\n\t\t// Run tests\n\t\tif (!options.skipTests) {\n\t\t\tconst testResult = await this.runTests(\n\t\t\t\tworktreePath,\n\t\t\t\toptions.dryRun ?? false\n\t\t\t)\n\t\t\tsteps.push(testResult)\n\n\t\t\tif (!testResult.passed && !testResult.skipped) {\n\t\t\t\treturn { success: false, steps, totalDuration: Date.now() - startTime }\n\t\t\t}\n\t\t}\n\n\t\treturn { success: true, steps, totalDuration: Date.now() - startTime }\n\t}\n\n\t/**\n\t * Run typecheck validation\n\t */\n\tprivate async runTypecheck(\n\t\tworktreePath: string,\n\t\tdryRun: boolean\n\t): Promise<ValidationStepResult> {\n\t\tconst stepStartTime = Date.now()\n\n\t\ttry {\n\t\t\t// Check if typecheck script exists\n\t\t\tconst pkgJson = await readPackageJson(worktreePath)\n\t\t\tconst hasTypecheckScript = hasScript(pkgJson, 'typecheck')\n\n\t\t\tif (!hasTypecheckScript) {\n\t\t\t\tlogger.debug('Skipping typecheck - no typecheck script found')\n\t\t\t\treturn {\n\t\t\t\t\tstep: 'typecheck',\n\t\t\t\t\tpassed: true,\n\t\t\t\t\tskipped: true,\n\t\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Handle missing package.json - skip validation for non-Node.js projects\n\t\t\tif (error instanceof Error && error.message.includes('package.json not found')) {\n\t\t\t\tlogger.debug('Skipping typecheck - no package.json found (non-Node.js project)')\n\t\t\t\treturn {\n\t\t\t\t\tstep: 'typecheck',\n\t\t\t\t\tpassed: true,\n\t\t\t\t\tskipped: true,\n\t\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Re-throw other errors\n\t\t\tthrow error\n\t\t}\n\n\t\tconst packageManager = await detectPackageManager(worktreePath)\n\n\t\tif (dryRun) {\n\t\t\tconst command =\n\t\t\t\tpackageManager === 'npm'\n\t\t\t\t\t? 'npm run typecheck'\n\t\t\t\t\t: `${packageManager} typecheck`\n\t\t\tlogger.info(`[DRY RUN] Would run: ${command}`)\n\t\t\treturn {\n\t\t\t\tstep: 'typecheck',\n\t\t\t\tpassed: true,\n\t\t\t\tskipped: false,\n\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t}\n\t\t}\n\n\t\tlogger.info('Running typecheck...')\n\n\t\ttry {\n\t\t\tawait runScript('typecheck', worktreePath, [], { quiet: true })\n\t\t\tlogger.success('Typecheck passed')\n\n\t\t\treturn {\n\t\t\t\tstep: 'typecheck',\n\t\t\t\tpassed: true,\n\t\t\t\tskipped: false,\n\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t}\n\t\t} catch {\n\t\t\t// Attempt Claude-assisted fix before failing\n\t\t\tconst fixed = await this.attemptClaudeFix(\n\t\t\t\t'typecheck',\n\t\t\t\tworktreePath,\n\t\t\t\tpackageManager\n\t\t\t)\n\n\t\t\tif (fixed) {\n\t\t\t\t// logger.success('Typecheck passed after Claude auto-fix')\n\t\t\t\treturn {\n\t\t\t\t\tstep: 'typecheck',\n\t\t\t\t\tpassed: true,\n\t\t\t\t\tskipped: false,\n\t\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Claude couldn't fix - throw original error\n\t\t\tconst runCommand =\n\t\t\t\tpackageManager === 'npm'\n\t\t\t\t\t? 'npm run typecheck'\n\t\t\t\t\t: `${packageManager} typecheck`\n\n\t\t\tthrow new Error(\n\t\t\t\t`Error: Typecheck failed.\\n` +\n\t\t\t\t\t`Fix type errors before merging.\\n\\n` +\n\t\t\t\t\t`Run '${runCommand}' to see detailed errors.`\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * Run lint validation\n\t */\n\tprivate async runLint(\n\t\tworktreePath: string,\n\t\tdryRun: boolean\n\t): Promise<ValidationStepResult> {\n\t\tconst stepStartTime = Date.now()\n\n\t\ttry {\n\t\t\t// Check if lint script exists\n\t\t\tconst pkgJson = await readPackageJson(worktreePath)\n\t\t\tconst hasLintScript = hasScript(pkgJson, 'lint')\n\n\t\t\tif (!hasLintScript) {\n\t\t\t\tlogger.debug('Skipping lint - no lint script found')\n\t\t\t\treturn {\n\t\t\t\t\tstep: 'lint',\n\t\t\t\t\tpassed: true,\n\t\t\t\t\tskipped: true,\n\t\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Handle missing package.json - skip validation for non-Node.js projects\n\t\t\tif (error instanceof Error && error.message.includes('package.json not found')) {\n\t\t\t\tlogger.debug('Skipping lint - no package.json found (non-Node.js project)')\n\t\t\t\treturn {\n\t\t\t\t\tstep: 'lint',\n\t\t\t\t\tpassed: true,\n\t\t\t\t\tskipped: true,\n\t\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Re-throw other errors\n\t\t\tthrow error\n\t\t}\n\n\t\tconst packageManager = await detectPackageManager(worktreePath)\n\n\t\tif (dryRun) {\n\t\t\tconst command =\n\t\t\t\tpackageManager === 'npm' ? 'npm run lint' : `${packageManager} lint`\n\t\t\tlogger.info(`[DRY RUN] Would run: ${command}`)\n\t\t\treturn {\n\t\t\t\tstep: 'lint',\n\t\t\t\tpassed: true,\n\t\t\t\tskipped: false,\n\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t}\n\t\t}\n\n\t\tlogger.info('Running lint...')\n\n\t\ttry {\n\t\t\tawait runScript('lint', worktreePath, [], { quiet: true })\n\t\t\tlogger.success('Linting passed')\n\n\t\t\treturn {\n\t\t\t\tstep: 'lint',\n\t\t\t\tpassed: true,\n\t\t\t\tskipped: false,\n\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t}\n\t\t} catch {\n\t\t\t// Attempt Claude-assisted fix before failing\n\t\t\tconst fixed = await this.attemptClaudeFix(\n\t\t\t\t'lint',\n\t\t\t\tworktreePath,\n\t\t\t\tpackageManager\n\t\t\t)\n\n\t\t\tif (fixed) {\n\t\t\t\t// logger.success('Linting passed after Claude auto-fix')\n\t\t\t\treturn {\n\t\t\t\t\tstep: 'lint',\n\t\t\t\t\tpassed: true,\n\t\t\t\t\tskipped: false,\n\t\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Claude couldn't fix - throw original error\n\t\t\tconst runCommand =\n\t\t\t\tpackageManager === 'npm' ? 'npm run lint' : `${packageManager} lint`\n\n\t\t\tthrow new Error(\n\t\t\t\t`Error: Linting failed.\\n` +\n\t\t\t\t\t`Fix linting errors before merging.\\n\\n` +\n\t\t\t\t\t`Run '${runCommand}' to see detailed errors.`\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * Run test validation\n\t */\n\tprivate async runTests(\n\t\tworktreePath: string,\n\t\tdryRun: boolean\n\t): Promise<ValidationStepResult> {\n\t\tconst stepStartTime = Date.now()\n\n\t\ttry {\n\t\t\t// Check if test script exists\n\t\t\tconst pkgJson = await readPackageJson(worktreePath)\n\t\t\tconst hasTestScript = hasScript(pkgJson, 'test')\n\n\t\t\tif (!hasTestScript) {\n\t\t\t\tlogger.debug('Skipping tests - no test script found')\n\t\t\t\treturn {\n\t\t\t\t\tstep: 'test',\n\t\t\t\t\tpassed: true,\n\t\t\t\t\tskipped: true,\n\t\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Handle missing package.json - skip validation for non-Node.js projects\n\t\t\tif (error instanceof Error && error.message.includes('package.json not found')) {\n\t\t\t\tlogger.debug('Skipping tests - no package.json found (non-Node.js project)')\n\t\t\t\treturn {\n\t\t\t\t\tstep: 'test',\n\t\t\t\t\tpassed: true,\n\t\t\t\t\tskipped: true,\n\t\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Re-throw other errors\n\t\t\tthrow error\n\t\t}\n\n\t\tconst packageManager = await detectPackageManager(worktreePath)\n\n\t\tif (dryRun) {\n\t\t\tconst command =\n\t\t\t\tpackageManager === 'npm' ? 'npm run test' : `${packageManager} test`\n\t\t\tlogger.info(`[DRY RUN] Would run: ${command}`)\n\t\t\treturn {\n\t\t\t\tstep: 'test',\n\t\t\t\tpassed: true,\n\t\t\t\tskipped: false,\n\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t}\n\t\t}\n\n\t\tlogger.info('Running tests...')\n\n\t\ttry {\n\t\t\tawait runScript('test', worktreePath, [], { quiet: true })\n\t\t\tlogger.success('Tests passed')\n\n\t\t\treturn {\n\t\t\t\tstep: 'test',\n\t\t\t\tpassed: true,\n\t\t\t\tskipped: false,\n\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t}\n\t\t} catch {\n\t\t\t// Attempt Claude-assisted fix before failing\n\t\t\tconst fixed = await this.attemptClaudeFix(\n\t\t\t\t'test',\n\t\t\t\tworktreePath,\n\t\t\t\tpackageManager\n\t\t\t)\n\n\t\t\tif (fixed) {\n\t\t\t\t// logger.success('Tests passed after Claude auto-fix')\n\t\t\t\treturn {\n\t\t\t\t\tstep: 'test',\n\t\t\t\t\tpassed: true,\n\t\t\t\t\tskipped: false,\n\t\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Claude couldn't fix - throw original error\n\t\t\tconst runCommand =\n\t\t\t\tpackageManager === 'npm' ? 'npm run test' : `${packageManager} test`\n\n\t\t\tthrow new Error(\n\t\t\t\t`Error: Tests failed.\\n` +\n\t\t\t\t\t`Fix test failures before merging.\\n\\n` +\n\t\t\t\t\t`Run '${runCommand}' to see detailed errors.`\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * Attempt to fix validation errors using Claude\n\t * Pattern based on MergeManager.attemptClaudeConflictResolution\n\t *\n\t * @param validationType - Type of validation that failed ('typecheck' | 'lint' | 'test')\n\t * @param worktreePath - Path to the worktree\n\t * @param packageManager - Detected package manager\n\t * @returns true if Claude fixed the issue, false otherwise\n\t */\n\tprivate async attemptClaudeFix(\n\t\tvalidationType: 'typecheck' | 'lint' | 'test',\n\t\tworktreePath: string,\n\t\tpackageManager: string\n\t): Promise<boolean> {\n\t\t// Check if Claude CLI is available\n\t\tconst isClaudeAvailable = await detectClaudeCli()\n\t\tif (!isClaudeAvailable) {\n\t\t\tlogger.debug('Claude CLI not available, skipping auto-fix')\n\t\t\treturn false\n\t\t}\n\n\t\t// Build validation command for the prompt\n\t\tconst validationCommand = this.getValidationCommand(validationType, packageManager)\n\n\t\t// Build prompt based on validation type (matching bash script prompts)\n\t\tconst prompt = this.getClaudePrompt(validationType, validationCommand)\n\n\t\tconst validationTypeCapitalized = validationType.charAt(0).toUpperCase() + validationType.slice(1)\n\t\tlogger.info(`Launching Claude to help fix ${validationTypeCapitalized} errors...`)\n\n\t\ttry {\n\t\t\t// Launch Claude in interactive mode with acceptEdits permission\n\t\t\tawait launchClaude(prompt, {\n\t\t\t\taddDir: worktreePath,\n\t\t\t\theadless: false, // Interactive mode\n\t\t\t\tpermissionMode: 'acceptEdits', // Auto-accept edits\n\t\t\t\tmodel: 'sonnet', // Use Sonnet model\n\t\t\t})\n\n\t\t\t// After Claude completes, re-run validation to verify fix\n\t\t\tlogger.info(`Re-running ${validationTypeCapitalized} after Claude's fixes...`)\n\n\t\t\ttry {\n\t\t\t\tawait runScript(validationType, worktreePath, [], { quiet: true })\n\t\t\t\t// Validation passed after Claude fix\n\t\t\t\tlogger.success(`${validationTypeCapitalized} passed after Claude auto-fix`)\n\t\t\t\treturn true\n\t\t\t} catch {\n\t\t\t\t// Validation still failing after Claude's attempt\n\t\t\t\tlogger.warn(`${validationTypeCapitalized} still failing after Claude's help`)\n\t\t\t\treturn false\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Claude launch failed or crashed\n\t\t\tlogger.warn('Claude auto-fix failed', {\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t})\n\t\t\treturn false\n\t\t}\n\t}\n\n\t/**\n\t * Get validation command string for prompts\n\t */\n\tprivate getValidationCommand(\n\t\tvalidationType: 'typecheck' | 'lint' | 'test',\n\t\tpackageManager: string\n\t): string {\n\t\tif (packageManager === 'npm') {\n\t\t\treturn `npm run ${validationType}`\n\t\t}\n\t\treturn `${packageManager} ${validationType}`\n\t}\n\n\t/**\n\t * Get Claude prompt for specific validation type\n\t * Matches bash script prompts exactly\n\t */\n\tprivate getClaudePrompt(\n\t\tvalidationType: 'typecheck' | 'lint' | 'test',\n\t\tvalidationCommand: string\n\t): string {\n\t\tswitch (validationType) {\n\t\t\tcase 'typecheck':\n\t\t\t\treturn (\n\t\t\t\t\t`There are TypeScript errors in this codebase. ` +\n\t\t\t\t\t`Please analyze the typecheck output, identify all type errors, and fix them. ` +\n\t\t\t\t\t`Run '${validationCommand}' to see the errors, then make the necessary code changes to resolve all type issues. ` +\n\t\t\t\t\t`When you are done, tell the user to quit using /exit to continue the validation process.`\n\t\t\t\t)\n\t\t\tcase 'lint':\n\t\t\t\treturn (\n\t\t\t\t\t`There are ESLint errors in this codebase. ` +\n\t\t\t\t\t`Please analyze the linting output, identify all linting issues, and fix them. ` +\n\t\t\t\t\t`Run '${validationCommand}' to see the errors, then make the necessary code changes to resolve all linting issues. ` +\n\t\t\t\t\t`Focus on code quality, consistency, and following the project's linting rules. ` +\n\t\t\t\t\t`When you are done, tell the user to quit using /exit to continue the validation process.`\n\t\t\t\t)\n\t\t\tcase 'test':\n\t\t\t\treturn (\n\t\t\t\t\t`There are unit test failures in this codebase. ` +\n\t\t\t\t\t`Please analyze the test output to understand what's failing, then fix the issues. ` +\n\t\t\t\t\t`This might involve updating test code, fixing bugs in the source code, or updating tests to match new behavior. ` +\n\t\t\t\t\t`Run '${validationCommand}' to see the detailed test failures, then make the necessary changes to get all tests passing. ` +\n\t\t\t\t\t`When you are done, tell the user to quit using /exit to continue the validation process.`\n\t\t\t\t)\n\t\t}\n\t}\n}\n","// Core types\nexport interface Workspace {\n id: string\n path: string\n branch: string\n issueNumber?: string | number\n prNumber?: number\n port: number\n databaseBranch?: string\n createdAt: Date\n lastAccessed: Date\n}\n\nexport interface WorkspaceInput {\n identifier: string\n type: 'issue' | 'pr' | 'branch'\n skipClaude?: boolean\n}\n\nexport interface WorkspaceSummary {\n id: string\n issueNumber?: string | number\n prNumber?: number\n title: string\n branch: string\n port: number\n status: 'active' | 'stale' | 'error'\n lastAccessed: string\n}\n\n// Git types\nexport interface Worktree {\n path: string\n branch: string\n commit: string\n isPR: boolean\n prNumber?: number\n issueNumber?: string | number\n port?: number\n}\n\nexport interface GitStatus {\n hasUncommittedChanges: boolean\n unstagedFiles: string[]\n stagedFiles: string[]\n currentBranch: string\n isAheadOfRemote: boolean\n isBehindRemote: boolean\n}\n\n// GitHub types\nexport interface Issue {\n number: string | number\n title: string\n body: string\n state: 'open' | 'closed'\n labels: string[]\n assignees: string[]\n url: string\n}\n\nexport interface PullRequest {\n number: number\n title: string\n body: string\n state: 'open' | 'closed' | 'merged'\n branch: string\n baseBranch: string\n url: string\n isDraft: boolean\n}\n\n// Issue Tracker types\n/**\n * Generic input detection result for issue trackers\n * String-based identifier to support non-numeric IDs (e.g., Linear \"ENG-123\")\n */\nexport interface IssueTrackerInputDetection {\n\ttype: 'issue' | 'pr' | 'unknown'\n\tidentifier: string | null\n\trawInput: string\n}\n\n/**\n * Re-export branch naming types from branch-naming module\n * These types are provider-agnostic and support all issue trackers\n */\nexport type { BranchNameStrategy, BranchGenerationOptions } from './branch-naming.js'\n\n// Database types\n\n/**\n * Result of database branch deletion operation\n * Distinguishes between successful deletion, branch not found, and errors\n */\nexport interface DatabaseDeletionResult {\n /** Overall operation succeeded (true even if branch didn't exist) */\n success: boolean\n /** True only if a branch was actually deleted */\n deleted: boolean\n /** True if branch didn't exist (not an error, just nothing to do) */\n notFound: boolean\n /** Error message if operation failed */\n error?: string\n /** User declined deletion (for preview databases) */\n userDeclined?: boolean\n /** Name of the branch that was processed */\n branchName?: string\n}\n\nexport interface DatabaseProvider {\n // Core operations\n createBranch(name: string, fromBranch?: string, cwd?: string): Promise<string>\n deleteBranch(name: string, isPreview?: boolean, cwd?: string): Promise<DatabaseDeletionResult>\n getConnectionString(branch: string, cwd?: string): Promise<string>\n listBranches(cwd?: string): Promise<string[]>\n branchExists(name: string, cwd?: string): Promise<boolean>\n\n // Additional operations for Vercel integration and validation\n findPreviewBranch(branchName: string, cwd?: string): Promise<string | null>\n getBranchNameFromEndpoint(endpointId: string, cwd?: string): Promise<string | null>\n sanitizeBranchName(branchName: string): string\n isAuthenticated(cwd?: string): Promise<boolean>\n isCliAvailable(): Promise<boolean>\n\n // Configuration validation\n isConfigured(): boolean\n}\n\n// Configuration types\nexport interface Config {\n defaultPort: number\n databaseProvider?: 'neon' | 'supabase' | 'planetscale'\n claudeModel?: 'opus' | 'sonnet' | 'haiku'\n skipClaude?: boolean\n customWorkspaceRoot?: string\n}\n\n// One-shot automation mode type\nexport type OneShotMode = 'default' | 'noReview' | 'bypassPermissions'\n\n// Command option types\nexport interface StartOptions {\n // Individual component flags (can be combined)\n claude?: boolean\n code?: boolean\n devServer?: boolean\n terminal?: boolean\n // Child loom control flag\n childLoom?: boolean\n // One-shot automation mode\n oneShot?: OneShotMode\n // Optional body text for issue creation\n body?: string\n}\n\nexport interface AddIssueOptions {\n // Optional body text for issue (skips AI enhancement)\n body?: string\n}\n\nexport interface FeedbackOptions {\n // Optional body text for feedback (added after diagnostics)\n body?: string\n}\n\nexport interface EnhanceOptions {\n noBrowser?: boolean // --no-browser flag - skip browser opening prompt\n}\n\nexport interface FinishOptions {\n force?: boolean // -f, --force - Skip confirmation prompts\n dryRun?: boolean // -n, --dry-run - Preview actions without executing\n pr?: number // --pr <number> - Treat input as PR number\n skipBuild?: boolean // --skip-build - Skip post-merge build verification\n noBrowser?: boolean // --no-browser - Skip opening PR in browser (github-pr mode only)\n cleanup?: boolean // --cleanup / --no-cleanup - Control worktree cleanup after PR creation\n}\n\n/**\n * Options for the cleanup command\n * All flags are optional and can be combined (subject to validation)\n */\nexport interface CleanupOptions {\n /** List all worktrees without removing anything */\n list?: boolean\n /** Remove all worktrees (interactive confirmation required unless --force) */\n all?: boolean\n /** Cleanup by specific issue number */\n issue?: number\n /** Skip confirmations and force removal */\n force?: boolean\n /** Show what would be done without actually doing it */\n dryRun?: boolean\n}\n\nexport interface ListOptions {\n json?: boolean\n}\n\n// Deprecated: Result types - use exception-based error handling instead\n// export type Result<T, E = Error> = { success: true; data: T } | { success: false; error: E }\n\n// Mock factory types for testing\nexport interface MockOptions {\n scenario: 'empty' | 'existing' | 'conflicts' | 'error'\n data?: unknown\n}\n\n// Worktree management types\nexport * from './worktree.js'\n\n// Environment management types\nexport * from './environment.js'\n\n// Loom types\nexport * from './loom.js'\n\n// Cleanup types\nexport * from './cleanup.js'\n\n// Process types (excluding Platform which is already defined above)\nexport type { ProcessInfo } from './process.js'\n\n// Color synchronization types\nexport interface RgbColor {\n\tr: number\n\tg: number\n\tb: number\n}\n\nexport interface ColorData {\n\trgb: RgbColor\n\thex: string\n\tindex: number\n}\n\nexport type Platform = 'darwin' | 'linux' | 'win32' | 'unsupported'\n\n// Validation types\nexport interface ValidationOptions {\n\tdryRun?: boolean\n\tskipTypecheck?: boolean\n\tskipLint?: boolean\n\tskipTests?: boolean\n}\n\nexport interface ValidationStepResult {\n\tstep: 'typecheck' | 'lint' | 'test'\n\tpassed: boolean\n\tskipped: boolean\n\toutput?: string\n\terror?: string\n\tduration?: number\n}\n\nexport interface ValidationResult {\n\tsuccess: boolean\n\tsteps: ValidationStepResult[]\n\ttotalDuration: number\n}\n\n// Commit management types\nexport interface CommitOptions {\n\tdryRun?: boolean\n\tissueNumber?: string | number // For \"Fixes #N\" trailer\n\tmessage?: string // Custom message override\n\tnoReview?: boolean // Skip user review of commit message\n\tskipVerify?: boolean // Skip pre-commit hooks (--no-verify flag)\n}\n\n/**\n * Error thrown when user aborts a commit operation\n * Used by CommitManager when user selects 'abort' at the commit prompt\n */\nexport class UserAbortedCommitError extends Error {\n\tconstructor(message = 'User aborted the commit') {\n\t\tsuper(message)\n\t\tthis.name = 'UserAbortedCommitError'\n\t}\n}\n\n// Merge management types\nexport interface MergeOptions {\n\tdryRun?: boolean // Preview actions without executing\n\tforce?: boolean // Skip confirmation prompts\n\trepoRoot?: string // Repository root path (optional, auto-detected if not provided)\n}\n\nexport interface MergeResult {\n\tsuccess: boolean\n\tbranchName: string\n\tcommitsMerged: number\n\trebaseCompleted: boolean\n\tmergeCompleted: boolean\n}\n\n// Update notification types\nexport interface UpdateCheckCache {\n\tlastCheck: number // Unix timestamp\n\tlatestVersion: string\n}\n\nexport interface UpdateCheckResult {\n\tcurrentVersion: string\n\tlatestVersion: string\n\tupdateAvailable: boolean\n}\n\nexport type InstallationMethod = 'global' | 'local' | 'linked' | 'unknown'\n","import { executeGitCommand } from '../utils/git.js'\nimport { logger } from '../utils/logger.js'\nimport { launchClaude, detectClaudeCli } from '../utils/claude.js'\nimport { promptCommitAction } from '../utils/prompt.js'\nimport { UserAbortedCommitError } from '../types/index.js'\nimport type { GitStatus, CommitOptions } from '../types/index.js'\n\n/**\n * CommitManager handles uncommitted changes detection and auto-commit\n * Ports logic from bash/merge-and-clean.sh lines 610-643\n */\nexport class CommitManager {\n /**\n * Detect uncommitted changes in a worktree\n * Parses git status --porcelain output into structured GitStatus\n */\n async detectUncommittedChanges(worktreePath: string): Promise<GitStatus> {\n // Execute: git status --porcelain\n const porcelainOutput = await executeGitCommand(['status', '--porcelain'], {\n cwd: worktreePath,\n })\n\n // Parse output to get staged and unstaged files\n const { stagedFiles, unstagedFiles } = this.parseGitStatus(porcelainOutput)\n\n // Get current branch name\n const currentBranch = await executeGitCommand(['branch', '--show-current'], {\n cwd: worktreePath,\n })\n\n return {\n hasUncommittedChanges: stagedFiles.length > 0 || unstagedFiles.length > 0,\n unstagedFiles,\n stagedFiles,\n currentBranch: currentBranch.trim(),\n // Defer these to future enhancement\n isAheadOfRemote: false,\n isBehindRemote: false,\n }\n }\n\n\n /**\n * Stage all changes and commit with Claude-generated or simple message\n * Tries Claude first, falls back to simple message if Claude unavailable or fails\n */\n async commitChanges(worktreePath: string, options: CommitOptions): Promise<void> {\n // Step 1: Check dry-run mode\n if (options.dryRun) {\n logger.info('[DRY RUN] Would run: git add -A')\n logger.info('[DRY RUN] Would generate commit message with Claude (if available)')\n const fallbackMessage = this.generateFallbackMessage(options)\n const verifyFlag = options.skipVerify ? ' --no-verify' : ''\n logger.info(`[DRY RUN] Would commit with message${verifyFlag}: ${fallbackMessage}`)\n return\n }\n\n // Step 2: Stage all changes\n await executeGitCommand(['add', '-A'], { cwd: worktreePath })\n\n // Step 3: Generate commit message (try Claude first, fallback to simple)\n let message: string | null = null\n\n // Skip Claude if custom message provided\n if (!options.message) {\n try {\n message = await this.generateClaudeCommitMessage(worktreePath, options.issueNumber)\n } catch (error) {\n logger.debug('Claude commit message generation failed, using fallback', { error })\n }\n }\n\n // Fallback to simple message if Claude failed or unavailable\n message ??= this.generateFallbackMessage(options)\n\n // Step 4: Log warning if --no-verify is configured\n if (options.skipVerify) {\n logger.warn('⚠️ Skipping pre-commit hooks (--no-verify configured in settings)')\n }\n\n // Step 5: Commit with user review via prompt (unless noReview specified)\n try {\n if (options.noReview || options.message) {\n // Direct commit without review (custom message or noReview flag)\n const commitArgs = ['commit', '-m', message]\n if (options.skipVerify) {\n commitArgs.push('--no-verify')\n }\n await executeGitCommand(commitArgs, { cwd: worktreePath })\n } else {\n // Prompt user for action instead of going straight to editor\n const action = await promptCommitAction(message)\n\n if (action === 'abort') {\n throw new UserAbortedCommitError()\n }\n\n if (action === 'accept') {\n // Direct commit with -m flag (no editor)\n const commitArgs = ['commit', '-m', message]\n if (options.skipVerify) {\n commitArgs.push('--no-verify')\n }\n await executeGitCommand(commitArgs, { cwd: worktreePath })\n } else {\n // action === 'edit': Use git editor for user review\n logger.info('Opening git editor for commit message review...')\n const commitArgs = ['commit', '-e', '-m', message]\n if (options.skipVerify) {\n commitArgs.push('--no-verify')\n }\n await executeGitCommand(commitArgs, {\n cwd: worktreePath,\n stdio: 'inherit',\n timeout: 300000 // 5 minutes for interactive editing\n })\n }\n }\n } catch (error) {\n // Re-throw UserAbortedCommitError as-is\n if (error instanceof UserAbortedCommitError) {\n throw error\n }\n // Handle \"nothing to commit\" scenario gracefully\n if (error instanceof Error && error.message.includes('nothing to commit')) {\n logger.info('No changes to commit')\n return\n }\n // Re-throw all other errors (including pre-commit hook failures)\n throw error\n }\n }\n\n\n /**\n * Generate simple fallback commit message when Claude unavailable\n * Used as fallback for Claude-powered commit messages\n */\n private generateFallbackMessage(options: CommitOptions): string {\n // If custom message provided, use it\n if (options.message) {\n return options.message\n }\n\n // Generate WIP message\n if (options.issueNumber) {\n return `WIP: Auto-commit for issue #${options.issueNumber}\\n\\nFixes #${options.issueNumber}`\n } else {\n return 'WIP: Auto-commit uncommitted changes'\n }\n }\n\n /**\n * Parse git status --porcelain output\n * Format: \"XY filename\" where X=index, Y=worktree\n * Examples:\n * \"M file.ts\" - staged modification\n * \" M file.ts\" - unstaged modification\n * \"MM file.ts\" - both staged and unstaged\n * \"?? file.ts\" - untracked\n */\n private parseGitStatus(porcelainOutput: string): {\n stagedFiles: string[]\n unstagedFiles: string[]\n } {\n const stagedFiles: string[] = []\n const unstagedFiles: string[] = []\n\n if (!porcelainOutput.trim()) {\n return { stagedFiles, unstagedFiles }\n }\n\n const lines = porcelainOutput.split('\\n').filter((line) => line.trim())\n\n for (const line of lines) {\n if (line.length < 3) continue\n\n const indexStatus = line[0] // First character - staging area status\n const worktreeStatus = line[1] // Second character - working tree status\n const filename = line.substring(3) // Everything after \"XY \"\n\n // Check if file is staged\n // First char != ' ' and != '?' → staged\n if (indexStatus !== ' ' && indexStatus !== '?') {\n stagedFiles.push(filename)\n }\n\n // Check if file is unstaged\n // Second char != ' ' or line starts with '??' → unstaged\n if (worktreeStatus !== ' ' || line.startsWith('??')) {\n unstagedFiles.push(filename)\n }\n }\n\n return { stagedFiles, unstagedFiles }\n }\n\n /**\n * Generate commit message using Claude Code\n * Claude examines the git repository directly via --add-dir option\n * Returns null if Claude unavailable or fails validation\n */\n private async generateClaudeCommitMessage(\n worktreePath: string,\n issueNumber?: string | number\n ): Promise<string | null> {\n const startTime = Date.now()\n\n logger.info('Starting Claude commit message generation...', {\n worktreePath: worktreePath.split('/').pop(), // Just show the folder name for privacy\n issueNumber\n })\n\n // Check if Claude CLI is available\n logger.debug('Checking Claude CLI availability...')\n const isClaudeAvailable = await detectClaudeCli()\n if (!isClaudeAvailable) {\n logger.info('Claude CLI not available, skipping Claude commit message generation')\n return null\n }\n logger.debug('Claude CLI is available')\n\n // Build XML-based structured prompt\n logger.debug('Building commit message prompt...')\n const prompt = this.buildCommitMessagePrompt(issueNumber)\n logger.debug('Prompt built', { promptLength: prompt.length })\n\n // Debug log the actual prompt content for troubleshooting\n logger.debug('Claude prompt content:', {\n prompt: prompt,\n truncatedPreview: prompt.substring(0, 500) + (prompt.length > 500 ? '...[truncated]' : '')\n })\n\n try {\n logger.info('Calling Claude CLI for commit message generation...')\n const claudeStartTime = Date.now()\n\n // Debug log the Claude call parameters\n const claudeOptions = {\n headless: true,\n addDir: worktreePath,\n model: 'claude-haiku-4-5-20251001', // Fast, cost-effective model\n timeout: 120000, // 120 second timeout\n }\n logger.debug('Claude CLI call parameters:', {\n options: claudeOptions,\n worktreePathForAnalysis: worktreePath,\n addDirContents: 'Will include entire worktree directory for analysis'\n })\n\n // Launch Claude in headless mode with repository access and shorter timeout for commit messages\n const result = await launchClaude(prompt, claudeOptions)\n\n const claudeDuration = Date.now() - claudeStartTime\n logger.debug('Claude API call completed', { duration: `${claudeDuration}ms` })\n\n if (typeof result !== 'string') {\n logger.warn('Claude returned non-string result', { resultType: typeof result })\n return null\n }\n\n logger.debug('Raw Claude output received', {\n outputLength: result.length,\n preview: result.substring(0, 200) + (result.length > 200 ? '...' : '')\n })\n\n\n // Sanitize output - remove meta-commentary and clean formatting\n logger.debug('Sanitizing Claude output...')\n const sanitized = this.sanitizeClaudeOutput(result)\n logger.debug('Output sanitized', {\n originalLength: result.length,\n sanitizedLength: sanitized.length,\n sanitized: sanitized.substring(0, 200) + (sanitized.length > 200 ? '...' : '')\n })\n\n // Ensure empty strings are rejected\n if (!sanitized) {\n logger.warn('Claude returned empty message after sanitization')\n return null\n }\n\n // Append \"Fixes #N\" trailer if issue number provided\n let finalMessage = sanitized\n if (issueNumber) {\n // Add Fixes trailer if not already present\n if (!finalMessage.includes(`Fixes #${issueNumber}`)) {\n finalMessage = `${finalMessage}\\n\\nFixes #${issueNumber}`\n logger.debug(`Added \"Fixes #${issueNumber}\" trailer to commit message`)\n } else {\n logger.debug(`\"Fixes #${issueNumber}\" already present in commit message`)\n }\n }\n\n const totalDuration = Date.now() - startTime\n logger.info('Claude commit message generated successfully', {\n message: finalMessage,\n totalDuration: `${totalDuration}ms`,\n claudeApiDuration: `${claudeDuration}ms`\n })\n\n return finalMessage\n } catch (error) {\n const totalDuration = Date.now() - startTime\n const errorMessage = error instanceof Error ? error.message : 'Unknown error'\n\n if (errorMessage.includes('timed out') || errorMessage.includes('timeout')) {\n logger.warn('Claude commit message generation timed out after 45 seconds', {\n totalDuration: `${totalDuration}ms`,\n worktreePath: worktreePath.split('/').pop()\n })\n } else {\n logger.warn('Failed to generate commit message with Claude', {\n error: errorMessage,\n totalDuration: `${totalDuration}ms`,\n worktreePath: worktreePath.split('/').pop()\n })\n }\n return null\n }\n }\n\n /**\n * Build structured XML prompt for commit message generation\n * Uses XML format for clear task definition and output expectations\n */\n private buildCommitMessagePrompt(issueNumber?: string | number): string {\n const issueContext = issueNumber\n ? `\\n<IssueContext>\nThis commit is associated with GitHub issue #${issueNumber}.\nIf the changes appear to resolve the issue, include \"Fixes #${issueNumber}\" at the end of the first line of commit message.\n</IssueContext>`\n : ''\n\n return `<Task>\nYou are a software engineer writing a commit message for this repository.\nExamine the staged changes in the git repository and generate a concise, meaningful commit message.\n</Task>\n\n<Requirements>\n<Format>The first line must be a brief summary of the changes made as a full sentence. If it references an issue, include \"Fixes #N\" at the end of this line.\n\nAdd 2 newlines, then add a bullet-point form description of the changes made, each change on a new line.</Format>\n<Mood>Use imperative mood (e.g., \"Add feature\" not \"Added feature\")</Mood>\n<Focus>Be specific about what was changed and why</Focus>\n<Conciseness>Keep message under 72 characters for subject line when possible</Conciseness>\n<NoMeta>CRITICAL: Do NOT include ANY explanatory text, analysis, or meta-commentary. Output ONLY the raw commit message.</NoMeta>\n<Examples>\nGood: \"Add user authentication with JWT tokens. Fixes #42\n\n- Implement login and registration endpoints\n- Secure routes with JWT middleware\n- Update user model to store hashed passwords\"\nGood: \"Fix navigation bug in sidebar menu.\"\nBad: \"Based on the changes, I'll create: Add user authentication\"\nBad: \"Looking at the files, this commit should be: Fix navigation bug\"\n</Examples>\n${issueContext}\n</Requirements>\n\n<Output>\nIMPORTANT: Your entire response will be used directly as the git commit message.\nDo not include any explanatory text before or after the commit message.\nStart your response immediately with the commit message text.\n</Output>`\n }\n\n /**\n * Sanitize Claude output to remove meta-commentary and clean formatting\n * Handles cases where Claude includes explanatory text despite instructions\n */\n private sanitizeClaudeOutput(rawOutput: string): string {\n let cleaned = rawOutput.trim()\n\n // Remove common meta-commentary patterns (case-insensitive)\n const metaPatterns = [\n /^.*?based on.*?changes.*?:/i,\n /^.*?looking at.*?files.*?:/i,\n /^.*?examining.*?:/i,\n /^.*?analyzing.*?:/i,\n /^.*?i'll.*?generate.*?:/i,\n /^.*?let me.*?:/i,\n /^.*?the commit message.*?should be.*?:/i,\n /^.*?here.*?is.*?commit.*?message.*?:/i,\n ]\n\n for (const pattern of metaPatterns) {\n cleaned = cleaned.replace(pattern, '').trim()\n }\n\n // Extract content after separators only if it looks like meta-commentary\n // Only split on colons if there's clear meta-commentary before it\n if (cleaned.includes(':')) {\n const colonIndex = cleaned.indexOf(':')\n const beforeColon = cleaned.substring(0, colonIndex).trim().toLowerCase()\n\n // Only split if the text before colon looks like meta-commentary\n const metaIndicators = [\n 'here is the commit message',\n 'commit message',\n 'here is',\n 'the message should be',\n 'i suggest',\n 'my suggestion'\n ]\n\n const isMetaCommentary = metaIndicators.some(indicator => beforeColon.includes(indicator))\n\n if (isMetaCommentary) {\n const afterColon = cleaned.substring(colonIndex + 1).trim()\n if (afterColon && afterColon.length > 10) {\n cleaned = afterColon\n }\n }\n }\n\n // Remove quotes if the entire message is wrapped in them\n if ((cleaned.startsWith('\"') && cleaned.endsWith('\"')) ||\n (cleaned.startsWith(\"'\") && cleaned.endsWith(\"'\"))) {\n cleaned = cleaned.slice(1, -1).trim()\n }\n\n return cleaned\n }\n\n\n}\n","import { logger } from '../utils/logger.js'\nimport { detectPackageManager, runScript } from '../utils/package-manager.js'\nimport { readPackageJson, hasScript } from '../utils/package-json.js'\nimport { ProjectCapabilityDetector } from './ProjectCapabilityDetector.js'\n\nexport interface BuildOptions {\n\tdryRun?: boolean\n}\n\nexport interface BuildResult {\n\tsuccess: boolean\n\tskipped: boolean\n\treason?: string\n\tduration: number\n}\n\n/**\n * BuildRunner handles post-merge build verification for CLI projects\n * Only runs build when project has CLI capabilities (bin field in package.json)\n */\nexport class BuildRunner {\n\tprivate capabilityDetector: ProjectCapabilityDetector\n\n\tconstructor(capabilityDetector?: ProjectCapabilityDetector) {\n\t\tthis.capabilityDetector = capabilityDetector ?? new ProjectCapabilityDetector()\n\t}\n\n\t/**\n\t * Run build verification in the specified directory\n\t * @param buildPath - Path where build should run (typically main worktree path)\n\t * @param options - Build options\n\t */\n\tasync runBuild(buildPath: string, options: BuildOptions = {}): Promise<BuildResult> {\n\t\tconst startTime = Date.now()\n\n\t\ttry {\n\t\t\t// Step 1: Check if build script exists\n\t\t\tconst pkgJson = await readPackageJson(buildPath)\n\t\t\tconst hasBuildScript = hasScript(pkgJson, 'build')\n\n\t\t\tif (!hasBuildScript) {\n\t\t\t\tlogger.debug('Skipping build - no build script found')\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tskipped: true,\n\t\t\t\t\treason: 'No build script found in package.json',\n\t\t\t\t\tduration: Date.now() - startTime,\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Handle missing package.json - skip build for non-Node.js projects\n\t\t\tif (error instanceof Error && error.message.includes('package.json not found')) {\n\t\t\t\tlogger.debug('Skipping build - no package.json found (non-Node.js project)')\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tskipped: true,\n\t\t\t\t\treason: 'No package.json found in project',\n\t\t\t\t\tduration: Date.now() - startTime,\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Re-throw other errors\n\t\t\tthrow error\n\t\t}\n\n\t\t// Step 2: Check if project has CLI capability (bin field)\n\t\tconst capabilities = await this.capabilityDetector.detectCapabilities(buildPath)\n\t\tconst isCLIProject = capabilities.capabilities.includes('cli')\n\n\t\tif (!isCLIProject) {\n\t\t\tlogger.debug('Skipping build - not a CLI project (no bin field)')\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tskipped: true,\n\t\t\t\treason: 'Project is not a CLI project (no bin field in package.json)',\n\t\t\t\tduration: Date.now() - startTime,\n\t\t\t}\n\t\t}\n\n\t\t// Step 3: Detect package manager\n\t\tconst packageManager = await detectPackageManager(buildPath)\n\n\t\t// Step 4: Handle dry-run mode\n\t\tif (options.dryRun) {\n\t\t\tconst command =\n\t\t\t\tpackageManager === 'npm' ? 'npm run build' : `${packageManager} build`\n\t\t\tlogger.info(`[DRY RUN] Would run: ${command}`)\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tskipped: false,\n\t\t\t\tduration: Date.now() - startTime,\n\t\t\t}\n\t\t}\n\n\t\t// Step 5: Execute build\n\t\tlogger.info('Running build...')\n\n\t\ttry {\n\t\t\tawait runScript('build', buildPath, [], { quiet: true })\n\t\t\tlogger.success('Build completed successfully')\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tskipped: false,\n\t\t\t\tduration: Date.now() - startTime,\n\t\t\t}\n\t\t} catch {\n\t\t\t// Step 6: Throw detailed error on failure\n\t\t\tconst runCommand =\n\t\t\t\tpackageManager === 'npm' ? 'npm run build' : `${packageManager} build`\n\n\t\t\tthrow new Error(\n\t\t\t\t`Error: Build failed.\\n` +\n\t\t\t\t\t`Fix build errors before proceeding.\\n\\n` +\n\t\t\t\t\t`Run '${runCommand}' to see detailed errors.`\n\t\t\t)\n\t\t}\n\t}\n}\n","import { executeGhCommand } from '../utils/github.js'\nimport { launchClaude, detectClaudeCli } from '../utils/claude.js'\nimport { getEffectivePRTargetRemote, getConfiguredRepoFromSettings, parseGitRemotes } from '../utils/remote.js'\nimport { openBrowser } from '../utils/browser.js'\nimport { logger } from '../utils/logger.js'\nimport type { IloomSettings } from './SettingsManager.js'\n\ninterface ExistingPR {\n\tnumber: number\n\turl: string\n}\n\ninterface PRCreationResult {\n\turl: string\n\tnumber: number\n\twasExisting: boolean\n}\n\nexport class PRManager {\n\tconstructor(private settings: IloomSettings) {}\n\n\t/**\n\t * Check if a PR already exists for the given branch\n\t * @param branchName - Branch to check\n\t * @param cwd - Working directory\n\t * @returns Existing PR info or null if none found\n\t */\n\tasync checkForExistingPR(branchName: string, cwd?: string): Promise<ExistingPR | null> {\n\t\ttry {\n\t\t\tconst prList = await executeGhCommand<Array<{ number: number; url: string }>>(\n\t\t\t\t['pr', 'list', '--head', branchName, '--state', 'open', '--json', 'number,url'],\n\t\t\t\tcwd ? { cwd } : undefined\n\t\t\t)\n\n\t\t\tif (prList.length > 0) {\n\t\t\t\treturn prList[0] ?? null // Return first match\n\t\t\t}\n\n\t\t\treturn null\n\t\t} catch (error) {\n\t\t\tlogger.debug('Error checking for existing PR', { error })\n\t\t\treturn null\n\t\t}\n\t}\n\n\t/**\n\t * Generate PR body using Claude if available, otherwise use simple template\n\t * @param issueNumber - Issue number to include in body\n\t * @param worktreePath - Path to worktree for context\n\t * @returns PR body markdown\n\t */\n\tasync generatePRBody(issueNumber: string | number | undefined, worktreePath: string): Promise<string> {\n\t\t// Try Claude first for rich body generation\n\t\tconst hasClaudeCli = await detectClaudeCli()\n\n\t\tif (hasClaudeCli) {\n\t\t\ttry {\n\t\t\t\tconst prompt = this.buildPRBodyPrompt(issueNumber)\n\n\t\t\t\tconst body = await launchClaude(prompt, {\n\t\t\t\t\theadless: true,\n\t\t\t\t\taddDir: worktreePath,\n\t\t\t\t\ttimeout: 30000,\n\t\t\t\t})\n\n\t\t\t\tif (body && typeof body === 'string' && body.trim()) {\n\t\t\t\t\tconst sanitized = this.sanitizeClaudeOutput(body)\n\t\t\t\t\tif (sanitized) {\n\t\t\t\t\t\treturn sanitized\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tlogger.debug('Claude PR body generation failed, using template', { error })\n\t\t\t}\n\t\t}\n\n\t\t// Fallback to simple template\n\t\tlet body = 'This PR contains changes from the iloom workflow.\\n\\n'\n\n\t\tif (issueNumber) {\n\t\t\tbody += `Fixes #${issueNumber}`\n\t\t}\n\n\t\treturn body\n\t}\n\n\t/**\n\t * Build structured XML prompt for PR body generation\n\t * Uses XML format for clear task definition and output expectations\n\t */\n\tprivate buildPRBodyPrompt(issueNumber?: string | number): string {\n\t\tconst issueContext = issueNumber\n\t\t\t? `\\n<IssueContext>\nThis PR is associated with GitHub issue #${issueNumber}.\nInclude \"Fixes #${issueNumber}\" at the end of the body on its own line.\n</IssueContext>`\n\t\t\t: ''\n\n\t\treturn `<Task>\nYou are a software engineer writing a pull request body for this repository.\nExamine the changes in the git repository and generate a concise, professional PR description.\n</Task>\n\n<Requirements>\n<Format>Write 2-3 sentences summarizing what was changed and why.${issueNumber ? `\\n\\nEnd with \"Fixes #${issueNumber}\" on its own line.` : ''}</Format>\n<Tone>Professional and concise</Tone>\n<Focus>Summarize the changes and their purpose</Focus>\n<NoMeta>CRITICAL: Do NOT include ANY explanatory text, analysis, or meta-commentary. Output ONLY the raw PR body text.</NoMeta>\n<Examples>\nGood: \"Add user authentication with JWT tokens to secure the API endpoints. This includes login and registration endpoints with proper password hashing.\n\nFixes #42\"\nGood: \"Fix navigation bug in sidebar menu that caused incorrect highlighting on nested routes.\"\nBad: \"Here's the PR body:\\n\\n---\\n\\nAdd user authentication...\"\nBad: \"Based on the changes, I'll write: Fix navigation bug...\"\n</Examples>\n${issueContext}\n</Requirements>\n\n<Output>\nIMPORTANT: Your entire response will be used directly as the GitHub pull request body.\nDo not include any explanatory text, headers, or separators before or after the body.\nStart your response immediately with the PR body text.\n</Output>`\n\t}\n\n\t/**\n\t * Sanitize Claude output to remove meta-commentary and clean formatting\n\t * Handles cases where Claude includes explanatory text despite instructions\n\t */\n\tprivate sanitizeClaudeOutput(rawOutput: string): string {\n\t\tlet cleaned = rawOutput.trim()\n\n\t\t// Remove common meta-commentary patterns (case-insensitive)\n\t\tconst metaPatterns = [\n\t\t\t/^.*?based on.*?changes.*?:/i,\n\t\t\t/^.*?looking at.*?files.*?:/i,\n\t\t\t/^.*?examining.*?:/i,\n\t\t\t/^.*?analyzing.*?:/i,\n\t\t\t/^.*?i'll.*?generate.*?:/i,\n\t\t\t/^.*?let me.*?:/i,\n\t\t\t/^.*?here.*?is.*?(?:the\\s+)?(?:pr|pull request).*?body.*?:/i,\n\t\t\t/^.*?here's.*?(?:the\\s+)?(?:pr|pull request).*?body.*?:/i,\n\t\t]\n\n\t\tfor (const pattern of metaPatterns) {\n\t\t\tcleaned = cleaned.replace(pattern, '').trim()\n\t\t}\n\n\t\t// Remove leading separator lines (---, ===, etc.)\n\t\tcleaned = cleaned.replace(/^[-=]{3,}\\s*/m, '').trim()\n\n\t\t// Extract content after separators only if it looks like meta-commentary\n\t\tif (cleaned.includes(':')) {\n\t\t\tconst colonIndex = cleaned.indexOf(':')\n\t\t\tconst beforeColon = cleaned.substring(0, colonIndex).trim().toLowerCase()\n\n\t\t\t// Only split if the text before colon looks like meta-commentary\n\t\t\tconst metaIndicators = [\n\t\t\t\t'here is the pr body',\n\t\t\t\t'here is the pull request body',\n\t\t\t\t'pr body',\n\t\t\t\t'pull request body',\n\t\t\t\t'here is',\n\t\t\t\t\"here's\",\n\t\t\t\t'the body should be',\n\t\t\t\t'i suggest',\n\t\t\t\t'my suggestion'\n\t\t\t]\n\n\t\t\tconst isMetaCommentary = metaIndicators.some(indicator => beforeColon.includes(indicator))\n\n\t\t\tif (isMetaCommentary) {\n\t\t\t\tconst afterColon = cleaned.substring(colonIndex + 1).trim()\n\t\t\t\t// Remove leading separator after colon\n\t\t\t\tconst afterSeparator = afterColon.replace(/^[-=]{3,}\\s*/m, '').trim()\n\t\t\t\tif (afterSeparator && afterSeparator.length > 10) {\n\t\t\t\t\tcleaned = afterSeparator\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Remove quotes if the entire message is wrapped in them\n\t\tif ((cleaned.startsWith('\"') && cleaned.endsWith('\"')) ||\n\t\t\t(cleaned.startsWith(\"'\") && cleaned.endsWith(\"'\"))) {\n\t\t\tcleaned = cleaned.slice(1, -1).trim()\n\t\t}\n\n\t\treturn cleaned\n\t}\n\n\t/**\n\t * Create a GitHub PR for the branch\n\t * @param branchName - Branch to create PR from (used as --head)\n\t * @param title - PR title\n\t * @param body - PR body\n\t * @param baseBranch - Base branch to target (usually main/master)\n\t * @param cwd - Working directory\n\t * @returns PR URL\n\t */\n\tasync createPR(\n\t\tbranchName: string,\n\t\ttitle: string,\n\t\tbody: string,\n\t\tbaseBranch: string,\n\t\tcwd?: string\n\t): Promise<string> {\n\t\ttry {\n\t\t\t// Get the target remote for the PR\n\t\t\tconst targetRemote = await getEffectivePRTargetRemote(this.settings, cwd)\n\n\t\t\t// Determine the correct --head value\n\t\t\t// For fork workflows (target != origin), we need \"username:branch\" format\n\t\t\t// See: https://github.com/cli/cli/issues/2691\n\t\t\tlet headValue = branchName\n\n\t\t\tif (targetRemote !== 'origin') {\n\t\t\t\t// Fork workflow: need to specify the head as \"owner:branch\"\n\t\t\t\t// Get the owner of the origin remote (where we pushed the branch)\n\t\t\t\tconst remotes = await parseGitRemotes(cwd)\n\t\t\t\tconst originRemote = remotes.find(r => r.name === 'origin')\n\n\t\t\t\tif (originRemote) {\n\t\t\t\t\theadValue = `${originRemote.owner}:${branchName}`\n\t\t\t\t\tlogger.debug(`Fork workflow detected, using head: ${headValue}`)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Build gh pr create command\n\t\t\t// Note: gh pr create returns a plain URL string, not JSON\n\t\t\tconst args = ['pr', 'create', '--head', headValue, '--title', title, '--body', body, '--base', baseBranch]\n\n\t\t\t// If target remote is not 'origin', we need to specify the repo\n\t\t\tif (targetRemote !== 'origin') {\n\t\t\t\tconst repo = await getConfiguredRepoFromSettings(this.settings, cwd)\n\t\t\t\targs.push('--repo', repo)\n\t\t\t}\n\n\t\t\t// gh pr create returns the PR URL as plain text (not JSON)\n\t\t\tconst result = await executeGhCommand<string>(args, cwd ? { cwd } : undefined)\n\n\t\t\t// Result is a string URL like \"https://github.com/owner/repo/pull/123\"\n\t\t\tconst url = typeof result === 'string' ? result.trim() : String(result).trim()\n\n\t\t\tif (!url.includes('github.com') || !url.includes('/pull/')) {\n\t\t\t\tthrow new Error(`Unexpected response from gh pr create: ${url}`)\n\t\t\t}\n\n\t\t\treturn url\n\t\t} catch (error) {\n\t\t\tconst errorMessage = error instanceof Error ? error.message : String(error)\n\n\t\t\t// Provide helpful error message for common GraphQL errors\n\t\t\tif (errorMessage.includes(\"Head sha can't be blank\") || errorMessage.includes(\"No commits between\")) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Failed to create pull request: ${errorMessage}\\n\\n` +\n\t\t\t\t\t`This error typically occurs when:\\n` +\n\t\t\t\t\t` - The branch was not fully pushed to the remote\\n` +\n\t\t\t\t\t` - There's a race condition between push and PR creation\\n` +\n\t\t\t\t\t` - The branch has no commits ahead of the base branch\\n\\n` +\n\t\t\t\t\t`Try running: git push -u origin ${branchName}\\n` +\n\t\t\t\t\t`Then retry: il finish`\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tthrow new Error(`Failed to create pull request: ${errorMessage}`)\n\t\t}\n\t}\n\n\t/**\n\t * Open PR URL in browser\n\t * @param url - PR URL to open\n\t */\n\tasync openPRInBrowser(url: string): Promise<void> {\n\t\ttry {\n\t\t\tawait openBrowser(url)\n\t\t\tlogger.debug('Opened PR in browser', { url })\n\t\t} catch (error) {\n\t\t\t// Don't fail the whole operation if browser opening fails\n\t\t\tlogger.warn('Failed to open PR in browser', { error })\n\t\t}\n\t}\n\n\t/**\n\t * Complete PR workflow: check for existing, create if needed, optionally open in browser\n\t * @param branchName - Branch to create PR from\n\t * @param title - PR title\n\t * @param issueNumber - Optional issue number for body generation\n\t * @param baseBranch - Base branch to target\n\t * @param worktreePath - Path to worktree\n\t * @param openInBrowser - Whether to open PR in browser\n\t * @returns PR creation result\n\t */\n\tasync createOrOpenPR(\n\t\tbranchName: string,\n\t\ttitle: string,\n\t\tissueNumber: string | number | undefined,\n\t\tbaseBranch: string,\n\t\tworktreePath: string,\n\t\topenInBrowser: boolean\n\t): Promise<PRCreationResult> {\n\t\t// Check for existing PR\n\t\tconst existingPR = await this.checkForExistingPR(branchName, worktreePath)\n\n\t\tif (existingPR) {\n\t\t\tlogger.info(`Pull request already exists: ${existingPR.url}`)\n\n\t\t\tif (openInBrowser) {\n\t\t\t\tawait this.openPRInBrowser(existingPR.url)\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\turl: existingPR.url,\n\t\t\t\tnumber: existingPR.number,\n\t\t\t\twasExisting: true,\n\t\t\t}\n\t\t}\n\n\t\t// Generate PR body\n\t\tconst body = await this.generatePRBody(issueNumber, worktreePath)\n\n\t\t// Create new PR\n\t\tlogger.info('Creating pull request...')\n\t\tconst url = await this.createPR(branchName, title, body, baseBranch, worktreePath)\n\n\t\t// Extract PR number from URL\n\t\tconst prNumber = this.extractPRNumberFromUrl(url)\n\n\t\tif (openInBrowser) {\n\t\t\tawait this.openPRInBrowser(url)\n\t\t}\n\n\t\treturn {\n\t\t\turl,\n\t\t\tnumber: prNumber,\n\t\t\twasExisting: false,\n\t\t}\n\t}\n\n\t/**\n\t * Extract PR number from GitHub PR URL\n\t * @param url - PR URL (e.g., https://github.com/owner/repo/pull/123)\n\t * @returns PR number\n\t */\n\tprivate extractPRNumberFromUrl(url: string): number {\n\t\tconst match = url.match(/\\/pull\\/(\\d+)/)\n\t\tif (match?.[1]) {\n\t\t\treturn parseInt(match[1], 10)\n\t\t}\n\t\tthrow new Error(`Could not extract PR number from URL: ${url}`)\n\t}\n}\n","import { logger } from '../utils/logger.js'\nimport type { IssueTracker } from '../lib/IssueTracker.js'\nimport { GitWorktreeManager } from '../lib/GitWorktreeManager.js'\nimport { ValidationRunner } from '../lib/ValidationRunner.js'\nimport { CommitManager } from '../lib/CommitManager.js'\nimport { MergeManager } from '../lib/MergeManager.js'\nimport { IdentifierParser } from '../utils/IdentifierParser.js'\nimport { ResourceCleanup } from '../lib/ResourceCleanup.js'\nimport { ProcessManager } from '../lib/process/ProcessManager.js'\nimport { BuildRunner } from '../lib/BuildRunner.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 { PRManager } from '../lib/PRManager.js'\nimport { LoomManager } from '../lib/LoomManager.js'\nimport { ClaudeContextManager } from '../lib/ClaudeContextManager.js'\nimport { ProjectCapabilityDetector } from '../lib/ProjectCapabilityDetector.js'\nimport { findMainWorktreePathWithSettings, pushBranchToRemote, extractIssueNumber } from '../utils/git.js'\nimport { loadEnvIntoProcess } from '../utils/env.js'\nimport { installDependencies } from '../utils/package-manager.js'\nimport { createNeonProviderFromSettings } from '../utils/neon-helpers.js'\nimport { getConfiguredRepoFromSettings, hasMultipleRemotes } from '../utils/remote.js'\nimport { promptConfirmation } from '../utils/prompt.js'\nimport { UserAbortedCommitError } from '../types/index.js'\nimport type { FinishOptions, GitWorktree, CommitOptions, MergeOptions, PullRequest } from '../types/index.js'\nimport type { ResourceCleanupOptions, CleanupResult } from '../types/cleanup.js'\nimport type { ParsedInput } from './start.js'\nimport path from 'path'\n\nexport interface FinishCommandInput {\n\tidentifier?: string | undefined // Optional - can be auto-detected\n\toptions: FinishOptions\n}\n\nexport interface ParsedFinishInput {\n\ttype: 'issue' | 'pr' | 'branch'\n\tnumber?: string | number // For issues and PRs\n\tbranchName?: string // For branch inputs\n\toriginalInput: string // Raw input for error messages\n\tautoDetected?: boolean // True if detected from current directory\n}\n\nexport class FinishCommand {\n\tprivate issueTracker: IssueTracker\n\tprivate gitWorktreeManager: GitWorktreeManager\n\tprivate validationRunner: ValidationRunner\n\tprivate commitManager: CommitManager\n\tprivate mergeManager: MergeManager\n\tprivate identifierParser: IdentifierParser\n\tprivate resourceCleanup?: ResourceCleanup\n\tprivate buildRunner: BuildRunner\n\tprivate settingsManager: SettingsManager\n\tprivate loomManager?: LoomManager\n\n\tconstructor(\n\t\tissueTracker: IssueTracker,\n\t\tgitWorktreeManager?: GitWorktreeManager,\n\t\tvalidationRunner?: ValidationRunner,\n\t\tcommitManager?: CommitManager,\n\t\tmergeManager?: MergeManager,\n\t\tidentifierParser?: IdentifierParser,\n\t\tresourceCleanup?: ResourceCleanup,\n\t\tbuildRunner?: BuildRunner,\n\t\tsettingsManager?: SettingsManager,\n\t\tloomManager?: LoomManager\n\t) {\n\t\t// Load environment variables first\n\t\tconst envResult = loadEnvIntoProcess()\n\t\tif (envResult.error) {\n\t\t\tlogger.debug(`Environment loading warning: ${envResult.error.message}`)\n\t\t}\n\t\tif (envResult.parsed) {\n\t\t\tlogger.debug(`Loaded ${Object.keys(envResult.parsed).length} environment variables`)\n\t\t}\n\n\t\tthis.issueTracker = issueTracker\n\t\tthis.gitWorktreeManager = gitWorktreeManager ?? new GitWorktreeManager()\n\t\tthis.validationRunner = validationRunner ?? new ValidationRunner()\n\t\tthis.commitManager = commitManager ?? new CommitManager()\n\t\tthis.mergeManager = mergeManager ?? new MergeManager()\n\t\tthis.identifierParser = identifierParser ?? new IdentifierParser(this.gitWorktreeManager)\n\n\t\t// Initialize settingsManager first (needed for ResourceCleanup)\n\t\tthis.settingsManager = settingsManager ?? new SettingsManager()\n\n\t\t// ResourceCleanup will be initialized lazily with proper configuration\n\t\tif (resourceCleanup) {\n\t\t\tthis.resourceCleanup = resourceCleanup\n\t\t}\n\n\t\tthis.buildRunner = buildRunner ?? new BuildRunner()\n\t\t// LoomManager will be initialized lazily if not provided\n\t\tif (loomManager) {\n\t\t\tthis.loomManager = loomManager\n\t\t}\n\t}\n\n\t/**\n\t * Lazy initialization of ResourceCleanup with properly configured DatabaseManager\n\t */\n\tprivate async ensureResourceCleanup(): Promise<void> {\n\t\t// Early return only if both are initialized\n\t\tif (this.resourceCleanup && this.loomManager) {\n\t\t\treturn\n\t\t}\n\n\t\tconst settings = await this.settingsManager.loadSettings()\n\t\tconst databaseUrlEnvVarName = settings.capabilities?.database?.databaseUrlEnvVarName ?? 'DATABASE_URL'\n\n\t\tconst environmentManager = new EnvironmentManager()\n\t\tconst neonProvider = createNeonProviderFromSettings(settings)\n\t\tconst databaseManager = new DatabaseManager(neonProvider, environmentManager, databaseUrlEnvVarName)\n\t\tconst cliIsolationManager = new CLIIsolationManager()\n\n\t\t// Initialize LoomManager if not provided\n\t\tconst { DefaultBranchNamingService } = await import('../lib/BranchNamingService.js')\n\t\tthis.loomManager ??= new LoomManager(\n\t\t\tthis.gitWorktreeManager,\n\t\t\tthis.issueTracker,\n\t\t\tnew DefaultBranchNamingService({ useClaude: true }),\n\t\t\tenvironmentManager,\n\t\t\tnew ClaudeContextManager(),\n\t\t\tnew ProjectCapabilityDetector(),\n\t\t\tcliIsolationManager,\n\t\t\tthis.settingsManager,\n\t\t\tdatabaseManager\n\t\t)\n\n\t\tthis.resourceCleanup ??= new ResourceCleanup(\n\t\t\tthis.gitWorktreeManager,\n\t\t\tnew ProcessManager(),\n\t\t\tdatabaseManager,\n\t\t\tcliIsolationManager\n\t\t)\n\t}\n\n\t/**\n\t * Check for child looms and exit gracefully if any exist\n\t * Always checks the TARGET loom (the one being finished), not the current directory's loom\n\t *\n\t * @param parsed - The parsed input identifying the loom being finished\n\t */\n\tprivate async checkForChildLooms(parsed: ParsedFinishInput): Promise<void> {\n\t\tawait this.ensureResourceCleanup()\n\t\tif (!this.loomManager) {\n\t\t\tthrow new Error('Failed to initialize LoomManager')\n\t\t}\n\n\t\t// Determine which branch is being finished based on parsed input\n\t\tlet targetBranch: string | undefined\n\n\t\tif (parsed.branchName) {\n\t\t\ttargetBranch = parsed.branchName\n\t\t} else if (parsed.type === 'issue' && parsed.number !== undefined) {\n\t\t\t// For issues, try to find the worktree by issue number to get the branch name\n\t\t\tconst worktree = await this.gitWorktreeManager.findWorktreeForIssue(parsed.number)\n\t\t\ttargetBranch = worktree?.branch\n\t\t} else if (parsed.type === 'pr' && parsed.number !== undefined) {\n\t\t\t// For PRs, ensure the number is numeric (PRs are always numeric per GitHub)\n\t\t\tconst prNumber = typeof parsed.number === 'number' ? parsed.number : Number(parsed.number)\n\t\t\tif (isNaN(prNumber) || !isFinite(prNumber)) {\n\t\t\t\tthrow new Error(`Invalid PR number: ${parsed.number}. PR numbers must be numeric.`)\n\t\t\t}\n\t\t\t// For PRs, try to find the worktree by PR number to get the branch name\n\t\t\tconst worktree = await this.gitWorktreeManager.findWorktreeForPR(prNumber, '')\n\t\t\ttargetBranch = worktree?.branch\n\t\t}\n\n\t\t// If we can't determine the target branch, skip the check\n\t\tif (!targetBranch) {\n\t\t\tlogger.debug(`Cannot determine target branch for child loom check`)\n\t\t\treturn\n\t\t}\n\n\t\t// Check if the TARGET loom has any child looms\n\t\tconst hasChildLooms = await this.loomManager.checkAndWarnChildLooms(targetBranch)\n\t\tif (hasChildLooms) {\n\t\t\tlogger.error('Cannot finish loom while child looms exist. Please finish child looms first.')\n\t\t\tprocess.exit(1)\n\t\t}\n\t}\n\n\t/**\n\t * Main entry point for finish command\n\t */\n\tpublic async execute(input: FinishCommandInput): Promise<void> {\n\t\ttry {\n\t\t\t// Step 1: Load settings and get configured repo for GitHub operations\n\t\t\tconst settings = await this.settingsManager.loadSettings()\n\n\t\t\tlet repo: string | undefined\n\n\t\t\t// We need repo info if:\n\t\t\t// 1. Merge mode is github-pr (for creating PRs on GitHub, even with Linear issues)\n\t\t\t// 2. Provider is GitHub (for GitHub issue operations)\n\t\t\tconst needsRepo =\n\t\t\t\tsettings.mergeBehavior?.mode === 'github-pr' || this.issueTracker.providerName === 'github'\n\t\t\tif (needsRepo && (await hasMultipleRemotes())) {\n\t\t\t\trepo = await getConfiguredRepoFromSettings(settings)\n\t\t\t\tlogger.info(`Using GitHub repository: ${repo}`)\n\t\t\t}\n\n\t\t\t// Step 2: Parse input (or auto-detect from current directory)\n\t\t\tconst parsed = await this.parseInput(input.identifier, input.options)\n\n\t\t\t// Step 2.5: Check for child looms AFTER parsing input\n\t\t\t// This ensures we only block when finishing the CURRENT loom (parent), not a child\n\t\t\tawait this.checkForChildLooms(parsed)\n\n\t\t\t// Step 2: Validate based on type and get worktrees\n\t\t\tconst worktrees = await this.validateInput(parsed, input.options, repo)\n\n\t\t\t// Step 3: Log success\n\t\t\tlogger.info(`Validated input: ${this.formatParsedInput(parsed)}`)\n\n\t\t\t// Get worktree for workflow execution\n\t\t\tconst worktree = worktrees[0]\n\t\t\tif (!worktree) {\n\t\t\t\tthrow new Error('No worktree found')\n\t\t\t}\n\n\t\t\t// Step 4: Branch based on input type\n\t\t\tif (parsed.type === 'pr') {\n\t\t\t\t// Fetch PR to get current state\n\t\t\t\tif (!parsed.number) {\n\t\t\t\t\tthrow new Error('Invalid PR number')\n\t\t\t\t}\n\t\t\t\t// Check if provider supports PRs before calling PR methods\n\t\t\t\tif (!this.issueTracker.supportsPullRequests || !this.issueTracker.fetchPR) {\n\t\t\t\t\tthrow new Error('Issue tracker does not support pull requests')\n\t\t\t\t}\n\t\t\t\tconst pr = await this.issueTracker.fetchPR(parsed.number, repo)\n\t\t\t\tawait this.executePRWorkflow(parsed, input.options, worktree, pr)\n\t\t\t} else {\n\t\t\t\t// Execute traditional issue/branch workflow\n\t\t\t\tawait this.executeIssueWorkflow(parsed, input.options, worktree)\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error) {\n\t\t\t\tlogger.error(`${error.message}`)\n\t\t\t} else {\n\t\t\t\tlogger.error('An unknown error occurred')\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t/**\n\t * Parse input to determine type and extract relevant data\n\t * Supports auto-detection from current directory when identifier is undefined\n\t */\n\tprivate async parseInput(\n\t\tidentifier: string | undefined,\n\t\toptions: FinishOptions\n\t): Promise<ParsedFinishInput> {\n\t\t// Priority 1: --pr flag overrides everything\n\t\tif (options.pr !== undefined) {\n\t\t\treturn {\n\t\t\t\ttype: 'pr',\n\t\t\t\tnumber: options.pr,\n\t\t\t\toriginalInput: `--pr ${options.pr}`,\n\t\t\t\tautoDetected: false,\n\t\t\t}\n\t\t}\n\n\t\t// Priority 2: Explicit identifier provided\n\t\tif (identifier?.trim()) {\n\t\t\treturn await this.parseExplicitInput(identifier.trim())\n\t\t}\n\n\t\t// Priority 3: Auto-detect from current directory\n\t\treturn await this.autoDetectFromCurrentDirectory()\n\t}\n\n\t/**\n\t * Parse explicit identifier input using pattern-based detection\n\t * (No GitHub API calls - uses IdentifierParser)\n\t */\n\tprivate async parseExplicitInput(\n\t\tidentifier: string\n\t): Promise<ParsedFinishInput> {\n\t\t// Check for PR-specific formats: pr/123, PR-123, PR/123\n\t\tconst prPattern = /^(?:pr|PR)[/-](\\d+)$/\n\t\tconst prMatch = identifier.match(prPattern)\n\t\tif (prMatch?.[1]) {\n\t\t\treturn {\n\t\t\t\ttype: 'pr',\n\t\t\t\tnumber: parseInt(prMatch[1], 10),\n\t\t\t\toriginalInput: identifier,\n\t\t\t\tautoDetected: false,\n\t\t\t}\n\t\t}\n\n\t\t// Use IdentifierParser for pattern-based detection\n\t\t// (checks existing worktrees, no GitHub API calls)\n\t\tconst parsed = await this.identifierParser.parseForPatternDetection(identifier)\n\n\t\t// Description type should never reach finish command (converted in start)\n\t\tif (parsed.type === 'description') {\n\t\t\tthrow new Error('Description input type is not supported in finish command')\n\t\t}\n\n\t\t// Convert ParsedInput to ParsedFinishInput (add autoDetected field)\n\t\tconst result: ParsedFinishInput = {\n\t\t\ttype: parsed.type,\n\t\t\toriginalInput: parsed.originalInput,\n\t\t\tautoDetected: false,\n\t\t}\n\n\t\t// Add number or branchName based on type\n\t\tif (parsed.number !== undefined) {\n\t\t\tresult.number = parsed.number\n\t\t}\n\t\tif (parsed.branchName !== undefined) {\n\t\t\tresult.branchName = parsed.branchName\n\t\t}\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Auto-detect PR or issue from current directory\n\t * Ports logic from merge-current-issue.sh lines 30-52\n\t */\n\tprivate async autoDetectFromCurrentDirectory(): Promise<ParsedFinishInput> {\n\t\tconst currentDir = path.basename(process.cwd())\n\n\t\t// Check for PR worktree pattern: _pr_N suffix\n\t\t// Pattern: /.*_pr_(\\d+)$/\n\t\tconst prPattern = /_pr_(\\d+)$/\n\t\tconst prMatch = currentDir.match(prPattern)\n\n\t\tif (prMatch?.[1]) {\n\t\t\tconst prNumber = parseInt(prMatch[1], 10)\n\t\t\tlogger.debug(`Auto-detected PR #${prNumber} from directory: ${currentDir}`)\n\t\t\treturn {\n\t\t\t\ttype: 'pr',\n\t\t\t\tnumber: prNumber,\n\t\t\t\toriginalInput: currentDir,\n\t\t\t\tautoDetected: true,\n\t\t\t}\n\t\t}\n\n\t\t// Check for issue pattern in directory or branch name\n\t\tconst issueNumber = extractIssueNumber(currentDir)\n\n\t\tif (issueNumber !== null) {\n\t\t\tlogger.debug(\n\t\t\t\t`Auto-detected issue #${issueNumber} from directory: ${currentDir}`\n\t\t\t)\n\t\t\treturn {\n\t\t\t\ttype: 'issue',\n\t\t\t\tnumber: issueNumber,\n\t\t\t\toriginalInput: currentDir,\n\t\t\t\tautoDetected: true,\n\t\t\t}\n\t\t}\n\n\t\t// Fallback: get current branch name\n\t\tconst repoInfo = await this.gitWorktreeManager.getRepoInfo()\n\t\tconst currentBranch = repoInfo.currentBranch\n\n\t\tif (!currentBranch) {\n\t\t\tthrow new Error(\n\t\t\t\t'Could not auto-detect identifier. Please provide an issue number, PR number, or branch name.\\n' +\n\t\t\t\t\t'Expected directory pattern: feat/issue-XX-description OR worktree with _pr_N suffix'\n\t\t\t)\n\t\t}\n\n\t\t// Try to extract issue from branch name\n\t\tconst branchIssueNumber = extractIssueNumber(currentBranch)\n\t\tif (branchIssueNumber !== null) {\n\t\t\tlogger.debug(\n\t\t\t\t`Auto-detected issue #${branchIssueNumber} from branch: ${currentBranch}`\n\t\t\t)\n\t\t\treturn {\n\t\t\t\ttype: 'issue',\n\t\t\t\tnumber: branchIssueNumber,\n\t\t\t\toriginalInput: currentBranch,\n\t\t\t\tautoDetected: true,\n\t\t\t}\n\t\t}\n\n\t\t// Last resort: use branch name\n\t\treturn {\n\t\t\ttype: 'branch',\n\t\t\tbranchName: currentBranch,\n\t\t\toriginalInput: currentBranch,\n\t\t\tautoDetected: true,\n\t\t}\n\t}\n\n\t/**\n\t * Validate the parsed input based on its type\n\t */\n\tprivate async validateInput(\n\t\tparsed: ParsedFinishInput,\n\t\toptions: FinishOptions,\n\t\trepo?: string\n\t): Promise<GitWorktree[]> {\n\t\tswitch (parsed.type) {\n\t\t\tcase 'pr': {\n\t\t\t\tif (!parsed.number) {\n\t\t\t\t\tthrow new Error('Invalid PR number')\n\t\t\t\t}\n\n\t\t\t\t// Check if provider supports PRs before calling PR methods\n\t\t\t\tif (!this.issueTracker.supportsPullRequests || !this.issueTracker.fetchPR) {\n\t\t\t\t\tthrow new Error('Issue tracker does not support pull requests')\n\t\t\t\t}\n\n\t\t\t\t// Fetch PR from GitHub\n\t\t\t\tconst pr = await this.issueTracker.fetchPR(parsed.number)\n\n\t\t\t\t// For PRs, we allow closed/merged state (cleanup-only mode)\n\t\t\t\t// But we still validate it exists\n\t\t\t\tlogger.debug(`Validated PR #${parsed.number} (state: ${pr.state})`)\n\n\t\t\t\t// Find associated worktree\n\t\t\t\treturn await this.findWorktreeForIdentifier(parsed)\n\t\t\t}\n\n\t\t\tcase 'issue': {\n\t\t\t\tif (!parsed.number) {\n\t\t\t\t\tthrow new Error('Invalid issue number')\n\t\t\t\t}\n\n\t\t\t\t// Fetch issue from GitHub\n\t\t\t\tconst issue = await this.issueTracker.fetchIssue(parsed.number, repo)\n\n\t\t\t\t// Validate issue state (warn if closed unless --force)\n\t\t\t\tif (issue.state === 'closed' && !options.force) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Issue #${parsed.number} is closed. Use --force to finish anyway.`\n\t\t\t\t\t)\n\t\t\t\t}\n\n\t\t\t\tlogger.debug(`Validated issue #${parsed.number} (state: ${issue.state})`)\n\n\t\t\t\t// Find associated worktree\n\t\t\t\treturn await this.findWorktreeForIdentifier(parsed)\n\t\t\t}\n\n\t\t\tcase 'branch': {\n\t\t\t\tif (!parsed.branchName) {\n\t\t\t\t\tthrow new Error('Invalid branch name')\n\t\t\t\t}\n\n\t\t\t\t// Validate branch name format\n\t\t\t\tif (!this.isValidBranchName(parsed.branchName)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t'Invalid branch name. Use only letters, numbers, hyphens, underscores, and slashes'\n\t\t\t\t\t)\n\t\t\t\t}\n\n\t\t\t\tlogger.debug(`Validated branch name: ${parsed.branchName}`)\n\n\t\t\t\t// Find associated worktree\n\t\t\t\treturn await this.findWorktreeForIdentifier(parsed)\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tconst unknownType = parsed as { type: string }\n\t\t\t\tthrow new Error(`Unknown input type: ${unknownType.type}`)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Find worktree for the given identifier using specific methods based on type\n\t * (uses precise pattern matching instead of broad substring matching)\n\t * Throws error if not found\n\t */\n\tprivate async findWorktreeForIdentifier(\n\t\tparsed: ParsedFinishInput\n\t): Promise<GitWorktree[]> {\n\t\tlet worktree: GitWorktree | null = null\n\n\t\t// Use specific finding methods based on parsed type\n\t\tswitch (parsed.type) {\n\t\t\tcase 'pr': {\n\t\t\t\tif (!parsed.number) {\n\t\t\t\t\tthrow new Error('Invalid PR number')\n\t\t\t\t}\n\t\t\t\t// For PRs, ensure the number is numeric (PRs are always numeric per GitHub)\n\t\t\t\tconst prNumber = typeof parsed.number === 'number' ? parsed.number : Number(parsed.number)\n\t\t\t\tif (isNaN(prNumber) || !isFinite(prNumber)) {\n\t\t\t\t\tthrow new Error(`Invalid PR number: ${parsed.number}. PR numbers must be numeric.`)\n\t\t\t\t}\n\t\t\t\t// Pass empty string for branch name since we don't know it yet\n\t\t\t\tworktree = await this.gitWorktreeManager.findWorktreeForPR(\n\t\t\t\t\tprNumber,\n\t\t\t\t\t''\n\t\t\t\t)\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tcase 'issue': {\n\t\t\t\tif (!parsed.number) {\n\t\t\t\t\tthrow new Error('Invalid issue number')\n\t\t\t\t}\n\t\t\t\tworktree = await this.gitWorktreeManager.findWorktreeForIssue(\n\t\t\t\t\tparsed.number\n\t\t\t\t)\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tcase 'branch': {\n\t\t\t\tif (!parsed.branchName) {\n\t\t\t\t\tthrow new Error('Invalid branch name')\n\t\t\t\t}\n\t\t\t\tworktree = await this.gitWorktreeManager.findWorktreeForBranch(\n\t\t\t\t\tparsed.branchName\n\t\t\t\t)\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tconst unknownType = parsed as { type: string }\n\t\t\t\tthrow new Error(`Unknown input type: ${unknownType.type}`)\n\t\t\t}\n\t\t}\n\n\t\tif (!worktree) {\n\t\t\tthrow new Error(\n\t\t\t\t`No worktree found for ${this.formatParsedInput(parsed)}. ` +\n\t\t\t\t\t`Use 'il list' to see available worktrees.`\n\t\t\t)\n\t\t}\n\n\t\tlogger.debug(`Found worktree: ${worktree.path}`)\n\n\t\treturn [worktree]\n\t}\n\n\t/**\n\t * Validate branch name format\n\t */\n\tprivate isValidBranchName(branch: string): boolean {\n\t\t// Pattern from bash script and StartCommand\n\t\treturn /^[a-zA-Z0-9/_-]+$/.test(branch)\n\t}\n\n\t/**\n\t * Format parsed input for display\n\t */\n\tprivate formatParsedInput(parsed: ParsedFinishInput): string {\n\t\tconst autoLabel = parsed.autoDetected ? ' (auto-detected)' : ''\n\n\t\tswitch (parsed.type) {\n\t\t\tcase 'pr':\n\t\t\t\treturn `PR #${parsed.number}${autoLabel}`\n\t\t\tcase 'issue':\n\t\t\t\treturn `Issue #${parsed.number}${autoLabel}`\n\t\t\tcase 'branch':\n\t\t\t\treturn `Branch '${parsed.branchName}'${autoLabel}`\n\t\t\tdefault:\n\t\t\t\treturn 'Unknown input'\n\t\t}\n\t}\n\n\t/**\n\t * Execute workflow for issues and branches (merge into main)\n\t * This is the traditional workflow: validate → commit → rebase → merge → cleanup\n\t */\n\tprivate async executeIssueWorkflow(\n\t\tparsed: ParsedFinishInput,\n\t\toptions: FinishOptions,\n\t\tworktree: GitWorktree\n\t): Promise<void> {\n\t\t// Step 1: Run pre-merge validations FIRST (Sub-Issue #47)\n\t\tif (!options.dryRun) {\n\t\t\tlogger.info('Running pre-merge validations...')\n\n\t\t\tawait this.validationRunner.runValidations(worktree.path, {\n\t\t\t\tdryRun: options.dryRun ?? false,\n\t\t\t})\n\t\t\tlogger.success('All validations passed')\n\t\t} else {\n\t\t\tlogger.info('[DRY RUN] Would run pre-merge validations')\n\t\t}\n\n\t\t// Step 2: Detect uncommitted changes AFTER validation passes\n\t\tconst gitStatus = await this.commitManager.detectUncommittedChanges(worktree.path)\n\n\t\t// Step 3: Commit changes only if validation passed AND changes exist\n\t\tif (gitStatus.hasUncommittedChanges) {\n\t\t\tif (options.dryRun) {\n\t\t\t\tlogger.info('[DRY RUN] Would auto-commit uncommitted changes (validation passed)')\n\t\t\t} else {\n\t\t\t\tlogger.info('Validation passed, auto-committing uncommitted changes...')\n\n\t\t\t\t// Load settings to get skipVerify configuration\n\t\t\t\tconst settings = await this.settingsManager.loadSettings(worktree.path)\n\t\t\t\tconst skipVerify = settings.workflows?.issue?.noVerify ?? false\n\n\t\t\t\tconst commitOptions: CommitOptions = {\n\t\t\t\t\tdryRun: options.dryRun ?? false,\n\t\t\t\t\tskipVerify,\n\t\t\t\t}\n\n\t\t\t\t// Only add issueNumber if it's an issue\n\t\t\t\tif (parsed.type === 'issue' && parsed.number) {\n\t\t\t\t\tcommitOptions.issueNumber = parsed.number\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tawait this.commitManager.commitChanges(worktree.path, commitOptions)\n\t\t\t\t\tlogger.success('Changes committed successfully')\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (error instanceof UserAbortedCommitError) {\n\t\t\t\t\t\tlogger.info('Commit aborted by user')\n\t\t\t\t\t\treturn // Exit workflow gracefully\n\t\t\t\t\t}\n\t\t\t\t\tthrow error // Re-throw other errors\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tlogger.debug('No uncommitted changes found')\n\t\t}\n\n\t\t// Step 3.5: Check merge mode from settings and branch workflow\n\t\tconst settings = await this.settingsManager.loadSettings(worktree.path)\n\t\tconst mergeBehavior = settings.mergeBehavior ?? { mode: 'local' }\n\n\t\tif (mergeBehavior.mode === 'github-pr') {\n\t\t\t// Validate that issue tracker supports pull requests\n\t\t\tif (!this.issueTracker.supportsPullRequests) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`The 'github-pr' merge mode requires a GitHub-compatible issue tracker. ` +\n\t\t\t\t\t`Your current provider (${this.issueTracker.providerName}) does not support pull requests. ` +\n\t\t\t\t\t`Either change mergeBehavior.mode to 'local' in your settings, or use GitHub as your issue tracker.`\n\t\t\t\t)\n\t\t\t}\n\n\t\t\t// Execute github-pr workflow instead of local merge\n\t\t\tawait this.executeGitHubPRWorkflow(parsed, options, worktree, settings)\n\t\t\treturn\n\t\t}\n\n\t\t// Step 4: Rebase branch on main\n\t\tlogger.info('Rebasing branch on main...')\n\n\t\tconst mergeOptions: MergeOptions = {\n\t\t\tdryRun: options.dryRun ?? false,\n\t\t\tforce: options.force ?? false,\n\t\t}\n\n\t\tawait this.mergeManager.rebaseOnMain(worktree.path, mergeOptions)\n\t\tlogger.success('Branch rebased successfully')\n\n\t\t// Step 5: Perform fast-forward merge\n\t\tlogger.info('Performing fast-forward merge...')\n\t\tawait this.mergeManager.performFastForwardMerge(worktree.branch, worktree.path, mergeOptions)\n\t\tlogger.success('Fast-forward merge completed successfully')\n\n\t\t// Step 5.5: Install dependencies in main worktree\n\t\tif (options.dryRun) {\n\t\t\tlogger.info('[DRY RUN] Would install dependencies in main worktree')\n\t\t} else {\n\t\t\tlogger.info('Installing dependencies in main worktree...')\n\t\t\tconst mainWorktreePath = await findMainWorktreePathWithSettings(worktree.path, this.settingsManager)\n\t\t\tawait installDependencies(mainWorktreePath, true, true)\n\t\t}\n\n\t\t// Step 5.6: Run post-merge build verification (CLI projects only)\n\t\tif (!options.skipBuild) {\n\t\t\tawait this.runPostMergeBuild(worktree.path, options)\n\t\t} else {\n\t\t\tlogger.debug('Skipping build verification (--skip-build flag provided)')\n\t\t}\n\n\t\t// Step 6: Post-merge cleanup\n\t\tawait this.performPostMergeCleanup(parsed, options, worktree)\n\t}\n\n\t/**\n\t * Execute workflow for Pull Requests\n\t * Behavior depends on PR state:\n\t * - OPEN: Commit changes, push to remote, keep worktree active\n\t * - CLOSED/MERGED: Skip to cleanup\n\t */\n\tprivate async executePRWorkflow(\n\t\tparsed: ParsedFinishInput,\n\t\toptions: FinishOptions,\n\t\tworktree: GitWorktree,\n\t\tpr: PullRequest\n\t): Promise<void> {\n\t\t// Branch based on PR state\n\t\tif (pr.state === 'closed' || pr.state === 'merged') {\n\t\t\t// Closed/Merged PR workflow\n\t\t\tlogger.info(`PR #${parsed.number} is ${pr.state.toUpperCase()} - skipping to cleanup`)\n\n\t\t\t// Check for uncommitted changes and warn (unless --force)\n\t\t\tconst gitStatus = await this.commitManager.detectUncommittedChanges(worktree.path)\n\t\t\tif (gitStatus.hasUncommittedChanges && !options.force) {\n\t\t\t\tlogger.warn('PR has uncommitted changes')\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'Cannot cleanup PR with uncommitted changes. ' +\n\t\t\t\t\t'Commit or stash changes, then run again with --force to cleanup anyway.'\n\t\t\t\t)\n\t\t\t}\n\n\t\t\t// Call cleanup directly with deleteBranch: true\n\t\t\tawait this.performPRCleanup(parsed, options, worktree)\n\n\t\t\tlogger.success(`PR #${parsed.number} cleanup completed`)\n\t\t} else {\n\t\t\t// Open PR workflow\n\t\t\tlogger.info(`PR #${parsed.number} is OPEN - will push changes and keep worktree active`)\n\n\t\t\t// Step 1: Detect uncommitted changes\n\t\t\tconst gitStatus = await this.commitManager.detectUncommittedChanges(worktree.path)\n\n\t\t\t// Step 2: Commit changes if any exist\n\t\t\tif (gitStatus.hasUncommittedChanges) {\n\t\t\t\tif (options.dryRun) {\n\t\t\t\t\tlogger.info('[DRY RUN] Would commit uncommitted changes')\n\t\t\t\t} else {\n\t\t\t\t\tlogger.info('Committing uncommitted changes...')\n\n\t\t\t\t\t// Load settings to get skipVerify configuration\n\t\t\t\t\tconst settings = await this.settingsManager.loadSettings(worktree.path)\n\t\t\t\t\tconst skipVerify = settings.workflows?.pr?.noVerify ?? false\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.commitManager.commitChanges(worktree.path, {\n\t\t\t\t\t\t\tdryRun: false,\n\t\t\t\t\t\t\tskipVerify,\n\t\t\t\t\t\t\t// Do NOT pass issueNumber for PRs - no \"Fixes #\" trailer needed\n\t\t\t\t\t\t})\n\t\t\t\t\t\tlogger.success('Changes committed')\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (error instanceof UserAbortedCommitError) {\n\t\t\t\t\t\t\tlogger.info('Commit aborted by user')\n\t\t\t\t\t\t\treturn // Exit workflow gracefully\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow error // Re-throw other errors\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlogger.debug('No uncommitted changes found')\n\t\t\t}\n\n\t\t\t// Step 3: Push to remote\n\t\t\tif (options.dryRun) {\n\t\t\t\tlogger.info(`[DRY RUN] Would push changes to origin/${pr.branch}`)\n\t\t\t} else {\n\t\t\t\tlogger.info('Pushing changes to remote...')\n\t\t\t\tawait pushBranchToRemote(pr.branch, worktree.path, {\n\t\t\t\t\tdryRun: false\n\t\t\t\t})\n\t\t\t\tlogger.success(`Changes pushed to PR #${parsed.number}`)\n\t\t\t}\n\n\t\t\t// Step 4: Log success and guidance\n\t\t\tlogger.success(`PR #${parsed.number} updated successfully`)\n\t\t\tlogger.info('Worktree remains active for continued work')\n\t\t\tlogger.info(`To cleanup when done: il cleanup ${parsed.number}`)\n\t\t}\n\t}\n\n\t/**\n\t * Execute workflow for GitHub PR creation (github-pr merge mode)\n\t * Validates → Commits → Pushes → Creates PR → Prompts for cleanup\n\t */\n\tprivate async executeGitHubPRWorkflow(\n\t\tparsed: ParsedFinishInput,\n\t\toptions: FinishOptions,\n\t\tworktree: GitWorktree,\n\t\tsettings: import('../lib/SettingsManager.js').IloomSettings\n\t): Promise<void> {\n\t\t// Step 1: Push branch to origin\n\t\tif (options.dryRun) {\n\t\t\tlogger.info('[DRY RUN] Would push branch to origin')\n\t\t} else {\n\t\t\tlogger.info('Pushing branch to origin...')\n\t\t\tawait pushBranchToRemote(worktree.branch, worktree.path, { dryRun: false })\n\t\t\tlogger.success('Branch pushed successfully')\n\t\t}\n\n\t\t// Step 2: Initialize PRManager with settings\n\t\tconst prManager = new PRManager(settings)\n\n\t\t// Step 3: Generate PR title from issue if available\n\t\tlet prTitle = `Work from ${worktree.branch}`\n\t\tif (parsed.type === 'issue' && parsed.number) {\n\t\t\t// Try to fetch issue title for better PR title\n\t\t\ttry {\n\t\t\t\tconst issue = await this.issueTracker.fetchIssue(parsed.number)\n\t\t\t\tprTitle = issue.title\n\t\t\t} catch (error) {\n\t\t\t\tlogger.debug('Could not fetch issue title, using branch name', { error })\n\t\t\t}\n\t\t}\n\n\t\t// Step 4: Create or open PR\n\t\tif (options.dryRun) {\n\t\t\tlogger.info('[DRY RUN] Would create GitHub PR')\n\t\t\tlogger.info(` Title: ${prTitle}`)\n\t\t\tlogger.info(` Base: ${settings.mainBranch ?? 'main'}`)\n\t\t} else {\n\t\t\tconst baseBranch = settings.mainBranch ?? 'main'\n\t\t\tconst openInBrowser = options.noBrowser !== true\n\n\t\t\tconst result = await prManager.createOrOpenPR(\n\t\t\t\tworktree.branch,\n\t\t\t\tprTitle,\n\t\t\t\tparsed.type === 'issue' ? parsed.number : undefined,\n\t\t\t\tbaseBranch,\n\t\t\t\tworktree.path,\n\t\t\t\topenInBrowser\n\t\t\t)\n\n\t\t\tif (result.wasExisting) {\n\t\t\t\tlogger.success(`Existing pull request: ${result.url}`)\n\t\t\t} else {\n\t\t\t\tlogger.success(`Pull request created: ${result.url}`)\n\t\t\t}\n\n\t\t\t// Step 5: Interactive cleanup prompt (unless flags override)\n\t\t\tawait this.handlePRCleanupPrompt(parsed, options, worktree)\n\t\t}\n\t}\n\n\t/**\n\t * Handle cleanup prompt after PR creation\n\t * Respects --cleanup and --no-cleanup flags, otherwise prompts user\n\t */\n\tprivate async handlePRCleanupPrompt(\n\t\tparsed: ParsedFinishInput,\n\t\toptions: FinishOptions,\n\t\tworktree: GitWorktree\n\t): Promise<void> {\n\t\tif (options.cleanup === true) {\n\t\t\t// Explicit --cleanup flag: perform cleanup\n\t\t\tlogger.info('Cleaning up worktree (--cleanup flag)...')\n\t\t\tawait this.performWorktreeCleanup(parsed, options, worktree)\n\t\t} else if (options.cleanup === false) {\n\t\t\t// Explicit --no-cleanup flag: keep worktree\n\t\t\tlogger.info('Worktree kept active for continued work (--no-cleanup flag)')\n\t\t\tlogger.info(`To cleanup later: il cleanup ${parsed.originalInput}`)\n\t\t} else {\n\t\t\t// No flag: prompt user for decision\n\t\t\tlogger.info('')\n\t\t\tlogger.info('PR created successfully. Would you like to clean up the worktree?')\n\t\t\tlogger.info(` Worktree: ${worktree.path}`)\n\t\t\tlogger.info(` Branch: ${worktree.branch}`)\n\t\t\tlogger.info('')\n\n\t\t\tconst shouldCleanup = await promptConfirmation(\n\t\t\t\t'Clean up worktree now?',\n\t\t\t\tfalse // Default to keeping worktree (safer option)\n\t\t\t)\n\n\t\t\tif (shouldCleanup) {\n\t\t\t\tawait this.performWorktreeCleanup(parsed, options, worktree)\n\t\t\t} else {\n\t\t\t\tlogger.info('Worktree kept active. Run `il cleanup` when ready.')\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Perform worktree cleanup (used by GitHub PR workflow)\n\t * Similar to performPostMergeCleanup but for PR workflow\n\t */\n\tprivate async performWorktreeCleanup(\n\t\tparsed: ParsedFinishInput,\n\t\toptions: FinishOptions,\n\t\tworktree: GitWorktree\n\t): Promise<void> {\n\t\t// Convert ParsedFinishInput to ParsedInput\n\t\tconst cleanupInput: ParsedInput = {\n\t\t\ttype: parsed.type,\n\t\t\toriginalInput: parsed.originalInput,\n\t\t\t...(parsed.number !== undefined && { number: parsed.number }),\n\t\t\t...(parsed.branchName !== undefined && { branchName: parsed.branchName }),\n\t\t}\n\n\t\tconst cleanupOptions: ResourceCleanupOptions = {\n\t\t\tdryRun: options.dryRun ?? false,\n\t\t\tdeleteBranch: false, // Don't delete branch - PR still needs it\n\t\t\tkeepDatabase: false, // Clean up database\n\t\t\tforce: options.force ?? false,\n\t\t}\n\n\t\ttry {\n\t\t\tlogger.info('Starting worktree cleanup...')\n\n\t\t\tawait this.ensureResourceCleanup()\n\t\t\tif (!this.resourceCleanup) {\n\t\t\t\tthrow new Error('Failed to initialize ResourceCleanup')\n\t\t\t}\n\n\t\t\tconst result = await this.resourceCleanup.cleanupWorktree(cleanupInput, cleanupOptions)\n\n\t\t\t// Report cleanup results\n\t\t\tthis.reportCleanupResults(result)\n\n\t\t\tif (!result.success) {\n\t\t\t\tlogger.warn('Some cleanup operations failed - manual cleanup may be required')\n\t\t\t\tthis.showManualCleanupInstructions(worktree)\n\t\t\t} else {\n\t\t\t\tlogger.success('Worktree cleanup completed successfully')\n\t\t\t}\n\n\t\t\t// Warn if running from within the worktree being finished\n\t\t\tif (this.isRunningFromWithinWorktree(worktree.path)) {\n\t\t\t\tthis.showTerminalCloseWarning(worktree)\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst errorMessage = error instanceof Error ? error.message : 'Unknown error'\n\t\t\tlogger.warn(`Cleanup failed: ${errorMessage}`)\n\t\t\tlogger.warn('Manual cleanup may be required')\n\t\t\tthis.showManualCleanupInstructions(worktree)\n\t\t}\n\t}\n\n\t/**\n\t * Perform cleanup for closed/merged PRs\n\t * Similar to performPostMergeCleanup but with different messaging\n\t */\n\tprivate async performPRCleanup(\n\t\tparsed: ParsedFinishInput,\n\t\toptions: FinishOptions,\n\t\tworktree: GitWorktree\n\t): Promise<void> {\n\t\t// Convert to ParsedInput format\n\t\tconst cleanupInput: ParsedInput = {\n\t\t\ttype: parsed.type,\n\t\t\toriginalInput: parsed.originalInput,\n\t\t\t...(parsed.number !== undefined && { number: parsed.number }),\n\t\t\t...(parsed.branchName !== undefined && { branchName: parsed.branchName }),\n\t\t}\n\n\t\tconst cleanupOptions: ResourceCleanupOptions = {\n\t\t\tdryRun: options.dryRun ?? false,\n\t\t\tdeleteBranch: true, // Delete branch for closed/merged PRs\n\t\t\tkeepDatabase: false,\n\t\t\tforce: options.force ?? false,\n\t\t}\n\n\t\ttry {\n\t\t\tawait this.ensureResourceCleanup()\n\t\t\tif (!this.resourceCleanup) {\n\t\t\t\tthrow new Error('Failed to initialize ResourceCleanup')\n\t\t\t}\n\t\t\tconst result = await this.resourceCleanup.cleanupWorktree(cleanupInput, cleanupOptions)\n\n\t\t\tthis.reportCleanupResults(result)\n\n\t\t\tif (!result.success) {\n\t\t\t\tlogger.warn('Some cleanup operations failed - manual cleanup may be required')\n\t\t\t\tthis.showManualCleanupInstructions(worktree)\n\t\t\t} else {\n\t\t\t\t// Warn if running from within the worktree being finished (only on successful cleanup)\n\t\t\t\tif (this.isRunningFromWithinWorktree(worktree.path)) {\n\t\t\t\t\tthis.showTerminalCloseWarning(worktree)\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst errorMessage = error instanceof Error ? error.message : 'Unknown error'\n\t\t\tlogger.warn(`Cleanup failed: ${errorMessage}`)\n\t\t\tthis.showManualCleanupInstructions(worktree)\n\t\t\tthrow error // Re-throw to fail the command\n\t\t}\n\t}\n\n\t/**\n\t * Run post-merge build verification for CLI projects\n\t * Runs in main worktree to verify merged code builds successfully\n\t */\n\tprivate async runPostMergeBuild(\n\t\tworktreePath: string,\n\t\toptions: FinishOptions\n\t): Promise<void> {\n\t\t// Find main worktree path\n\t\tconst mainWorktreePath = await findMainWorktreePathWithSettings(worktreePath, this.settingsManager)\n\n\t\t// Check if dry-run\n\t\tif (options.dryRun) {\n\t\t\tlogger.info('[DRY RUN] Would run post-merge build')\n\t\t\treturn\n\t\t}\n\n\t\tlogger.info('Running post-merge build...')\n\n\t\tconst result = await this.buildRunner.runBuild(mainWorktreePath, {\n\t\t\tdryRun: options.dryRun ?? false,\n\t\t})\n\n\t\tif (result.skipped) {\n\t\t\tlogger.debug(`Build skipped: ${result.reason}`)\n\t\t} else {\n\t\t\tlogger.success('Post-merge build completed successfully')\n\t\t}\n\t}\n\n\t/**\n\t * Perform post-merge cleanup operations\n\t * Converts ParsedFinishInput to ParsedInput and calls ResourceCleanup\n\t * Handles failures gracefully without throwing\n\t */\n\tprivate async performPostMergeCleanup(\n\t\tparsed: ParsedFinishInput,\n\t\toptions: FinishOptions,\n\t\tworktree: GitWorktree\n\t): Promise<void> {\n\t\t// Ensure loomManager is initialized first\n\t\tawait this.ensureResourceCleanup()\n\t\tif (!this.loomManager) {\n\t\t\tthrow new Error('Failed to initialize LoomManager')\n\t\t}\n\n\t\t// Check for child looms again (second check - first was at start of execute)\n\t\t// This is a no-op if child looms were already checked and cleaned up\n\t\tawait this.checkForChildLooms(parsed)\n\n\t\t// Convert ParsedFinishInput to ParsedInput (drop autoDetected field)\n\t\tconst cleanupInput: ParsedInput = {\n\t\t\ttype: parsed.type,\n\t\t\toriginalInput: parsed.originalInput,\n\t\t\t...(parsed.number !== undefined && { number: parsed.number }),\n\t\t\t...(parsed.branchName !== undefined && { branchName: parsed.branchName }),\n\t\t}\n\n\t\tconst cleanupOptions: ResourceCleanupOptions = {\n\t\t\tdryRun: options.dryRun ?? false,\n\t\t\tdeleteBranch: true, // Delete branch after successful merge\n\t\t\tkeepDatabase: false, // Clean up database after merge\n\t\t\tforce: options.force ?? false,\n\t\t}\n\n\t\ttry {\n\t\t\tlogger.info('Starting post-merge cleanup...')\n\n\t\t\tif (!this.resourceCleanup) {\n\t\t\t\tthrow new Error('Failed to initialize ResourceCleanup')\n\t\t\t}\n\t\t\tconst result = await this.resourceCleanup.cleanupWorktree(cleanupInput, cleanupOptions)\n\n\t\t\t// Report cleanup results\n\t\t\tthis.reportCleanupResults(result)\n\n\t\t\tif (!result.success) {\n\t\t\t\tlogger.warn('Some cleanup operations failed - manual cleanup may be required')\n\t\t\t\t// Show helpful recovery message\n\t\t\t\tthis.showManualCleanupInstructions(worktree)\n\t\t\t} else {\n\t\t\t\tlogger.success('Post-merge cleanup completed successfully')\n\t\t\t}\n\n\t\t\t// Warn if running from within the worktree being finished\n\t\t\tif (this.isRunningFromWithinWorktree(worktree.path)) {\n\t\t\t\tthis.showTerminalCloseWarning(worktree)\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Catch cleanup errors to prevent finish command from failing\n\t\t\t// (merge already succeeded - cleanup failures are non-fatal)\n\t\t\tconst errorMessage = error instanceof Error ? error.message : 'Unknown error'\n\t\t\tlogger.warn(`Cleanup failed: ${errorMessage}`)\n\t\t\tlogger.warn('Merge completed successfully, but manual cleanup is required')\n\t\t\tthis.showManualCleanupInstructions(worktree)\n\t\t}\n\t}\n\n\t/**\n\t * Report cleanup operation results to user\n\t */\n\tprivate reportCleanupResults(result: CleanupResult): void {\n\t\tif (result.operations.length === 0) {\n\t\t\treturn\n\t\t}\n\n\t\tlogger.info('Cleanup operations:')\n\t\tfor (const op of result.operations) {\n\t\t\tconst status = op.success ? '✓' : '✗'\n\t\t\tconst message = op.error ? `${op.message}: ${op.error}` : op.message\n\n\t\t\tif (op.success) {\n\t\t\t\tlogger.info(` ${status} ${message}`)\n\t\t\t} else {\n\t\t\t\tlogger.warn(` ${status} ${message}`)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Show manual cleanup instructions when cleanup fails\n\t */\n\tprivate showManualCleanupInstructions(worktree: GitWorktree): void {\n\t\tlogger.info('\\nManual cleanup commands:')\n\t\tlogger.info(` 1. Remove worktree: git worktree remove ${worktree.path}`)\n\t\tlogger.info(` 2. Delete branch: git branch -d ${worktree.branch}`)\n\t\tlogger.info(` 3. Check dev servers: lsof -i :PORT (and kill if needed)`)\n\t}\n\n\t/**\n\t * Check if current working directory is within the target worktree\n\t */\n\tprivate isRunningFromWithinWorktree(worktreePath: string): boolean {\n\t\tconst normalizedCwd = path.normalize(process.cwd())\n\t\tconst normalizedWorktree = path.normalize(worktreePath)\n\t\treturn normalizedCwd.startsWith(normalizedWorktree)\n\t}\n\n\t/**\n\t * Display warning to close terminal/IDE when running from within finished loom\n\t */\n\tprivate showTerminalCloseWarning(worktree: GitWorktree): void {\n\t\tlogger.info('')\n\t\tlogger.info('You are currently in the directory of the loom that was just finished.')\n\t\tlogger.info('Please close this terminal and any IDE/terminal windows using this directory.')\n\t\tlogger.info(`Directory: ${worktree.path}`)\n\t}\n}\n","import { readFileSync } from 'fs'\nimport { fileURLToPath } from 'url'\nimport { dirname, join } from 'path'\n\n/**\n * Package information from package.json\n */\nexport interface PackageInfo {\n name: string\n version: string\n description: string\n [key: string]: unknown\n}\n\n/**\n * Get package.json information\n *\n * @param scriptPath - Optional path to use for finding package.json (defaults to current file location)\n * @returns Parsed package.json contents\n * @throws Error if package.json cannot be read or parsed\n */\nexport function getPackageInfo(scriptPath?: string): PackageInfo {\n try {\n // Determine the base path to use\n let basePath: string\n if (scriptPath) {\n basePath = scriptPath\n } else {\n // Use import.meta.url to get the current file path\n const __filename = fileURLToPath(import.meta.url)\n basePath = __filename\n }\n\n // Navigate from current file to package.json\n // The compiled CLI runs from dist/cli.js, so we need dist/../package.json (one level up)\n const __dirname = dirname(basePath)\n const packageJsonPath = join(__dirname, '..', 'package.json')\n\n // Read and parse package.json\n const packageJsonContent = readFileSync(packageJsonPath, 'utf8')\n const packageJson = JSON.parse(packageJsonContent) as PackageInfo\n\n return packageJson\n } catch (error) {\n throw new Error(\n `Failed to read package.json: ${error instanceof Error ? error.message : 'Unknown error'}`\n )\n }\n}\n","import { extractIssueNumber } from './git.js'\nimport type { GitWorktree } from '../types/worktree.js'\nimport type { LoomMetadata } from '../lib/MetadataManager.js'\n\n/**\n * JSON output schema for il list --json\n */\nexport interface LoomJsonOutput {\n name: string\n worktreePath: string | null\n branch: string | null\n type: 'branch' | 'issue' | 'pr'\n issue_numbers: string[]\n pr_numbers: string[]\n isMainWorktree: boolean\n description?: string | null\n created_at?: string | null\n issueTracker?: string | null\n colorHex?: string | null\n}\n\n/**\n * Determine loom type from branch name and path patterns\n * Priority: PR (from path _pr_N suffix) > issue (from branch) > branch\n */\nfunction determineLoomType(worktree: GitWorktree): 'branch' | 'issue' | 'pr' {\n // Check for PR pattern in path: _pr_N suffix\n // This pattern is added by generateWorktreePath when isPR is true\n const prPathPattern = /_pr_\\d+$/\n if (prPathPattern.test(worktree.path)) {\n return 'pr'\n }\n\n // Check for issue pattern in branch using existing extractIssueNumber\n const issueNumber = extractIssueNumber(worktree.branch)\n if (issueNumber !== null) {\n return 'issue'\n }\n\n // Default to 'branch' type\n return 'branch'\n}\n\n/**\n * Extract PR numbers from worktree path\n * Returns array of string PR numbers extracted from _pr_N suffix\n */\nfunction extractPRNumbers(path: string): string[] {\n if (!path) {\n return []\n }\n\n const prPathPattern = /_pr_(\\d+)$/\n const match = path.match(prPathPattern)\n if (match?.[1]) {\n return [match[1]]\n }\n\n return []\n}\n\n/**\n * Extract issue numbers from branch name\n * Returns array of string identifiers (may include prefixes like PROJ-)\n */\nfunction extractIssueNumbers(branch: string): string[] {\n if (!branch) {\n return []\n }\n\n const issueNumber = extractIssueNumber(branch)\n if (issueNumber === null) {\n return []\n }\n\n // Return as array, already deduplicated by being a single extraction\n return [issueNumber]\n}\n\n/**\n * Format single worktree to JSON schema\n * - When metadata is available, use metadata values for type, issue_numbers, pr_numbers\n * - When metadata is not available, derive values from worktree path/branch\n *\n * @param worktree - The worktree to format\n * @param mainWorktreePath - Optional path to the main worktree for isMainWorktree detection\n * @param metadata - Optional metadata from MetadataManager (preferred source when available)\n */\nexport function formatLoomForJson(\n worktree: GitWorktree,\n mainWorktreePath?: string,\n metadata?: LoomMetadata | null\n): LoomJsonOutput {\n // Use metadata values when available, otherwise derive from worktree\n const loomType = metadata?.issueType ?? determineLoomType(worktree)\n\n // Use metadata arrays when available, otherwise extract from path/branch\n let issueNumbers: string[]\n let prNumbers: string[]\n\n if (metadata) {\n // Use metadata values directly\n issueNumbers = metadata.issue_numbers\n prNumbers = metadata.pr_numbers\n } else {\n // Derive from worktree path/branch\n issueNumbers = []\n prNumbers = []\n if (loomType === 'pr') {\n prNumbers = extractPRNumbers(worktree.path)\n } else if (loomType === 'issue') {\n issueNumbers = extractIssueNumbers(worktree.branch)\n }\n }\n\n // Determine if this is the main worktree by comparing paths\n const isMainWorktree = mainWorktreePath ? worktree.path === mainWorktreePath : false\n\n return {\n name: worktree.branch || worktree.path,\n worktreePath: worktree.bare ? null : worktree.path,\n branch: (metadata?.branchName ?? worktree.branch) || null,\n type: loomType,\n issue_numbers: issueNumbers,\n pr_numbers: prNumbers,\n isMainWorktree,\n description: metadata?.description ?? null,\n created_at: metadata?.created_at ?? null,\n issueTracker: metadata?.issueTracker ?? null,\n colorHex: metadata?.colorHex ?? null\n }\n}\n\n/**\n * Format array of worktrees to JSON schema\n *\n * @param worktrees - Array of worktrees to format\n * @param mainWorktreePath - Optional path to the main worktree for isMainWorktree detection\n * @param metadata - Optional map of worktree paths to metadata\n */\nexport function formatLoomsForJson(\n worktrees: GitWorktree[],\n mainWorktreePath?: string,\n metadata?: Map<string, LoomMetadata | null>\n): LoomJsonOutput[] {\n return worktrees.map(wt => formatLoomForJson(wt, mainWorktreePath, metadata?.get(wt.path)))\n}\n"],"mappings":"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","names":["path","waitForKeypress","promptConfirmation","path","body","path","DefaultBranchNamingService","settings","__filename","packageJson","fileURLToPath","path","fileURLToPath","shellCompletion","waitForKeypress","InitCommand","SettingsManager","hasMultipleRemotes","GitHubService","DefaultBranchNamingService","detectClaudeCli","launchClaude","ClaudeContextManager","createNeonProviderFromSettings"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/commands/start.ts","../src/utils/first-run-setup.ts","../src/commands/add-issue.ts","../src/commands/enhance.ts","../src/lib/ValidationRunner.ts","../src/utils/vscode.ts","../src/types/index.ts","../src/lib/CommitManager.ts","../src/lib/BuildRunner.ts","../src/lib/PRManager.ts","../src/commands/finish.ts","../src/utils/package-info.ts","../src/utils/loom-formatter.ts"],"sourcesContent":["import { program, Command, Option } from 'commander'\nimport { logger, createStderrLogger } from './utils/logger.js'\nimport { withLogger } from './utils/logger-context.js'\nimport { GitWorktreeManager } from './lib/GitWorktreeManager.js'\nimport { ShellCompletion } from './lib/ShellCompletion.js'\nimport { SettingsManager } from './lib/SettingsManager.js'\nimport { IssueTrackerFactory } from './lib/IssueTrackerFactory.js'\nimport { IssueEnhancementService } from './lib/IssueEnhancementService.js'\nimport { AgentManager } from './lib/AgentManager.js'\nimport { GitHubService } from './lib/GitHubService.js'\nimport { MetadataManager, type LoomMetadata } from './lib/MetadataManager.js'\nimport { StartCommand } from './commands/start.js'\nimport { AddIssueCommand } from './commands/add-issue.js'\nimport { EnhanceCommand } from './commands/enhance.js'\nimport { FinishCommand } from './commands/finish.js'\nimport type { StartOptions, CleanupOptions, FinishOptions } from './types/index.js'\nimport { getPackageInfo } from './utils/package-info.js'\nimport { hasMultipleRemotes } from './utils/remote.js'\nimport { fileURLToPath } from 'url'\nimport { realpathSync } from 'fs'\nimport { formatLoomsForJson } from './utils/loom-formatter.js'\nimport { findMainWorktreePathWithSettings } from './utils/git.js'\n\n// Get package.json for version\nconst __filename = fileURLToPath(import.meta.url)\nconst packageJson = getPackageInfo(__filename)\n\n// Helper function to parse issue identifiers (numeric or alphanumeric)\nfunction parseIssueIdentifier(value: string): string | number {\n const parsed = parseInt(value, 10)\n // Return number if purely numeric, otherwise return string\n return !isNaN(parsed) && String(parsed) === value ? parsed : value\n}\n\nprogram\n .name('iloom')\n .description(packageJson.description)\n .version(packageJson.version)\n .option('--debug', 'Enable debug output (default: based on ILOOM_DEBUG env var)')\n .option('--completion', 'Output shell completion script for current shell')\n .option('--set <key=value>', 'Override any setting using dot notation (repeatable, e.g., --set workflows.issue.startIde=false)')\n .allowUnknownOption() // Allow --set to be used multiple times\n .hook('preAction', async (thisCommand) => {\n // Set debug mode based on flag or environment variable\n const options = thisCommand.opts()\n // Default to environment variable value, then false if not set\n const envDebug = process.env.ILOOM_DEBUG === 'true'\n const debugEnabled = options.debug !== undefined ? options.debug : envDebug\n logger.setDebug(debugEnabled)\n\n // Handle --completion flag\n if (options.completion) {\n const shellCompletion = new ShellCompletion()\n shellCompletion.printCompletionScript()\n process.exit(0)\n }\n\n // Check for updates before command execution for global installations\n try {\n const { checkAndNotifyUpdate } = await import('./utils/update-notifier.js')\n const { detectInstallationMethod } = await import('./utils/installation-detector.js')\n\n // Detect installation method\n const installMethod = detectInstallationMethod(__filename)\n\n // Check and notify (non-blocking, all errors handled internally)\n await checkAndNotifyUpdate(packageJson.version, packageJson.name, installMethod)\n } catch {\n // Silently fail - update check should never break user experience\n }\n\n // Migrate legacy .hatchbox settings to .iloom (BEFORE settings validation)\n try {\n const { SettingsMigrationManager } = await import('./lib/SettingsMigrationManager.js')\n const migrationManager = new SettingsMigrationManager()\n await migrationManager.migrateSettingsIfNeeded()\n } catch (error) {\n // Log warning but don't fail - migration is best-effort\n logger.debug(`Settings migration failed: ${error instanceof Error ? error.message : 'Unknown'}`)\n }\n\n // Validate settings for all commands\n await validateSettingsForCommand(thisCommand)\n\n // Validate GitHub CLI availability for commands that need it\n await validateGhCliForCommand(thisCommand)\n })\n\n// Helper function to validate settings at startup\nasync function validateSettingsForCommand(command: Command): Promise<void> {\n const commandName = command.args[0] ?? ''\n\n // Tier 1: Commands that bypass ALL validation\n const bypassCommands = ['help', 'init', 'update', 'contribute']\n\n if (bypassCommands.includes(commandName)) {\n return\n }\n\n // Tier 2: All other commands require FULL validation (settings + multi-remote)\n // Commands: start, add-issue, enhance, finish, list, cleanup, open, run, etc.\n try {\n const settingsManager = new SettingsManager()\n\n // Attempt to load settings - this will throw on validation errors\n // Missing file is OK (returns {})\n const settings = await settingsManager.loadSettings()\n\n // Check for multi-remote configuration requirement\n const multipleRemotes = await hasMultipleRemotes()\n\n if (multipleRemotes && !settings.issueManagement?.github?.remote) {\n // Auto-launch init command to configure remotes\n // After init completes, function returns and Commander.js continues with original command\n await autoLaunchInitForMultipleRemotes()\n return // Settings now configured, let preAction complete\n }\n } catch (error) {\n logger.error(`Configuration error: ${error instanceof Error ? error.message : 'Unknown error'}`)\n logger.info('Please fix your .iloom/settings.json file and try again.')\n process.exit(1)\n }\n}\n\n// Helper function to validate GitHub CLI availability\n// Exported for testing\nexport async function validateGhCliForCommand(command: Command): Promise<void> {\n const commandName = command.args[0] ?? ''\n\n // Commands that ALWAYS require gh CLI regardless of configuration\n const alwaysRequireGh = ['feedback', 'contribute']\n\n // Commands that require gh CLI when GitHub provider or github-pr merge mode\n const conditionallyRequireGh = ['start', 'finish', 'enhance', 'add-issue', 'ignite', 'spin']\n\n // Commands that only warn if gh CLI is missing (secondary/utility commands)\n const warnOnly = ['init', 'list', 'rebase', 'cleanup', 'run', 'update', 'open']\n\n // Test commands and help bypass this check entirely\n if (commandName.startsWith('test-') || commandName === 'help') {\n return\n }\n\n // Check if gh CLI is available\n const ghAvailable = GitHubService.isCliAvailable()\n\n // Determine if gh CLI is needed based on configuration\n let needsGhCli = alwaysRequireGh.includes(commandName)\n\n // For conditional commands, check provider and merge mode\n if (!needsGhCli && conditionallyRequireGh.includes(commandName)) {\n try {\n const settingsManager = new SettingsManager()\n const settings = await settingsManager.loadSettings()\n\n const provider = IssueTrackerFactory.getProviderName(settings)\n const mergeBehaviorMode = settings.mergeBehavior?.mode\n\n needsGhCli = provider === 'github' || mergeBehaviorMode === 'github-pr'\n } catch {\n // If we can't load settings, assume we might need gh CLI\n needsGhCli = true\n }\n }\n\n // Handle missing gh CLI\n if (!ghAvailable) {\n if (needsGhCli) {\n // ERROR: gh CLI is required for this command\n const errorMessage = alwaysRequireGh.includes(commandName)\n ? `The \"${commandName}\" command requires GitHub CLI (gh) to be installed.`\n : `GitHub CLI (gh) is required when using GitHub as the issue tracker or \"github-pr\" merge mode.`\n\n logger.error(errorMessage)\n logger.info('')\n logger.info('To install GitHub CLI:')\n logger.info(' • macOS: brew install gh')\n logger.info(' • Windows: winget install GitHub.cli')\n logger.info(' • Linux: https://github.com/cli/cli#installation')\n logger.info('')\n logger.info('After installation, authenticate with: gh auth login')\n\n process.exit(1)\n } else if (warnOnly.includes(commandName)) {\n // WARN: gh CLI might be needed for certain configurations\n try {\n const settingsManager = new SettingsManager()\n const settings = await settingsManager.loadSettings()\n\n const provider = IssueTrackerFactory.getProviderName(settings)\n const mergeBehaviorMode = settings.mergeBehavior?.mode\n\n if (provider === 'github' || mergeBehaviorMode === 'github-pr') {\n logger.warn('GitHub CLI (gh) is not installed.')\n logger.warn(\n 'Some features may not work correctly with your current configuration (GitHub provider or github-pr merge mode).'\n )\n logger.info('To install: brew install gh (macOS) or see https://github.com/cli/cli#installation')\n logger.info('')\n }\n } catch {\n // Silently skip warning if we can't load settings\n }\n }\n }\n}\n\n/**\n * Auto-launch init command when multiple remotes are detected but not configured\n * Shows message, waits for keypress, launches interactive Claude configuration,\n * then returns to let Commander.js continue with the original command\n */\nasync function autoLaunchInitForMultipleRemotes(): Promise<void> {\n logger.info('Multiple git remotes detected, but no GitHub remote is configured.')\n logger.info('')\n logger.info('iloom will now launch an interactive configuration session with Claude')\n logger.info('to help you select which remote to use for GitHub operations.')\n logger.info('')\n\n // Wait for keypress to continue\n const { waitForKeypress } = await import('./utils/prompt.js')\n await waitForKeypress('Press any key to start configuration...')\n\n logger.info('')\n\n try {\n // Launch init command with focused initial message\n const { InitCommand } = await import('./commands/init.js')\n const initCommand = new InitCommand()\n\n // Custom initial message that focuses on multi-remote configuration\n 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.'\n\n await initCommand.execute(customInitialMessage)\n\n logger.info('')\n logger.info('Configuration complete! Continuing with your original command...')\n logger.info('')\n\n // Re-validate settings after init to ensure multi-remote is now configured\n const { SettingsManager } = await import('./lib/SettingsManager.js')\n const settingsManager = new SettingsManager()\n const settings = await settingsManager.loadSettings()\n\n const { hasMultipleRemotes } = await import('./utils/remote.js')\n const multipleRemotes = await hasMultipleRemotes()\n\n // Verify the issue is resolved\n if (multipleRemotes && !settings.issueManagement?.github?.remote) {\n logger.error('Configuration incomplete: GitHub remote is still not configured.')\n logger.info('Please run \"iloom init\" again and configure the GitHub remote setting.')\n process.exit(1)\n }\n\n // Configuration verified - simply return to let Commander.js continue\n // with the original command (preAction hook will complete normally)\n return\n\n } catch (error) {\n logger.error(`Failed to configure remotes: ${error instanceof Error ? error.message : 'Unknown error'}`)\n logger.info('You can manually run \"iloom init\" to configure settings.')\n process.exit(1)\n }\n}\n\n// Initialize shell completion (must be after program setup, before parseAsync)\nconst shellCompletion = new ShellCompletion()\nshellCompletion.init()\n\nprogram\n .command('start')\n .alias('new')\n .alias('create')\n .alias('up')\n .description('Create isolated workspace for an issue/PR')\n .argument('[identifier]', 'Issue number, PR number, or branch name (optional - will prompt if not provided)')\n .option('--claude', 'Enable Claude integration (default: true)')\n .option('--no-claude', 'Disable Claude integration')\n .option('--code', 'Enable VSCode (default: true)')\n .option('--no-code', 'Disable VSCode')\n .option('--dev-server', 'Enable dev server in terminal (default: true)')\n .option('--no-dev-server', 'Disable dev server')\n .option('--terminal', 'Enable terminal without dev server (default: false)')\n .option('--no-terminal', 'Disable terminal')\n .option('--child-loom', 'Force create as child loom (skip prompt)')\n .option('--no-child-loom', 'Force create as independent loom (skip prompt)')\n .option('--body <text>', 'Body text for issue (skips AI enhancement)')\n .option('--json', 'Output result as JSON')\n .addOption(\n new Option('--one-shot <mode>', 'One-shot automation mode')\n .choices(['default', 'noReview', 'bypassPermissions'])\n .default('default')\n )\n .action(async (identifier: string | undefined, options: StartOptions) => {\n const executeAction = async (): Promise<void> => {\n try {\n let finalIdentifier = identifier\n\n // Interactive prompting when no identifier provided\n if (!finalIdentifier) {\n if (options.json) {\n logger.error('JSON mode requires identifier argument')\n process.exit(1)\n }\n const { promptInput } = await import('./utils/prompt.js')\n finalIdentifier = await promptInput('Enter issue number, PR number (pr/123), or branch name')\n\n // Validate non-empty after prompting\n if (!finalIdentifier?.trim()) {\n logger.error('Identifier is required')\n process.exit(1)\n }\n }\n\n const settingsManager = new SettingsManager()\n const settings = await settingsManager.loadSettings()\n const issueTracker = IssueTrackerFactory.create(settings)\n const command = new StartCommand(issueTracker, undefined, undefined, settingsManager)\n const result = await command.execute({ identifier: finalIdentifier, options })\n\n if (options.json && result) {\n // JSON mode: output structured result and exit\n console.log(JSON.stringify(result, null, 2))\n }\n process.exit(0)\n } catch (error) {\n logger.error(`Failed to start workspace: ${error instanceof Error ? error.message : 'Unknown error'}`)\n process.exit(1)\n }\n }\n\n // Wrap execution in logger context for JSON mode\n if (options.json) {\n const jsonLogger = createStderrLogger()\n await withLogger(jsonLogger, executeAction)\n } else {\n await executeAction()\n }\n })\n\nprogram\n .command('add-issue')\n .alias('a')\n .description('Create and enhance GitHub issue without starting workspace')\n .argument('<description>', 'Natural language description of the issue (>50 chars, >2 spaces)')\n .option('--body <text>', 'Body text for issue (skips AI enhancement)')\n .option('--json', 'Output result as JSON')\n .action(async (description: string, options: { body?: string; json?: boolean }) => {\n const executeAction = async (): Promise<void> => {\n try {\n const settingsManager = new SettingsManager()\n const settings = await settingsManager.loadSettings()\n const issueTracker = IssueTrackerFactory.create(settings)\n const enhancementService = new IssueEnhancementService(issueTracker, new AgentManager(), settingsManager)\n const command = new AddIssueCommand(enhancementService, settingsManager)\n const result = await command.execute({\n description,\n options: {\n ...(options.body && { body: options.body }),\n ...(options.json && { json: options.json })\n }\n })\n\n if (options.json && result) {\n // JSON mode: output structured result and exit\n console.log(JSON.stringify(result, null, 2))\n } else if (result) {\n // Non-JSON mode: display human-readable success message\n const issueNumber = typeof result === 'object' ? result.id : result\n logger.success(`Issue #${issueNumber} created successfully`)\n }\n process.exit(0)\n } catch (error) {\n logger.error(`Failed to create issue: ${error instanceof Error ? error.message : 'Unknown error'}`)\n process.exit(1)\n }\n }\n\n // Wrap execution in logger context for JSON mode\n if (options.json) {\n const jsonLogger = createStderrLogger()\n await withLogger(jsonLogger, executeAction)\n } else {\n await executeAction()\n }\n })\n\nprogram\n .command('feedback')\n .alias('f')\n .description('Submit feedback/bug report to iloom-cli repository')\n .argument('<description>', 'Natural language description of feedback (>50 chars, >2 spaces)')\n .option('--body <text>', 'Body text for feedback (added after diagnostics)')\n .action(async (description: string, options: { body?: string }) => {\n try {\n const { FeedbackCommand } = await import('./commands/feedback.js')\n const command = new FeedbackCommand()\n const feedbackOptions: import('./types/index.js').FeedbackOptions = {}\n if (options.body !== undefined) {\n feedbackOptions.body = options.body\n }\n const issueNumber = await command.execute({\n description,\n options: feedbackOptions\n })\n logger.success(`Feedback submitted as issue #${issueNumber} in iloom-cli repository`)\n process.exit(0)\n } catch (error) {\n logger.error(`Failed to submit feedback: ${error instanceof Error ? error.message : 'Unknown error'}`)\n process.exit(1)\n }\n })\n\nprogram\n .command('enhance')\n .description('Apply enhancement agent to existing GitHub issue')\n .argument('<issue-number>', 'GitHub issue identifier to enhance', parseIssueIdentifier)\n .option('--no-browser', 'Skip browser opening prompt')\n .option('--author <username>', 'GitHub username to tag in questions (for CI usage)')\n .option('--json', 'Output result as JSON')\n .action(async (issueNumber: string | number, options: { browser?: boolean; author?: string; json?: boolean }) => {\n const executeAction = async (): Promise<void> => {\n try {\n const settingsManager = new SettingsManager()\n const settings = await settingsManager.loadSettings()\n const issueTracker = IssueTrackerFactory.create(settings)\n const command = new EnhanceCommand(issueTracker)\n const result = await command.execute({\n issueNumber,\n options: {\n noBrowser: options.browser === false,\n ...(options.author && { author: options.author }),\n ...(options.json && { json: options.json })\n }\n })\n\n if (options.json && result) {\n // JSON mode: output structured result and exit\n console.log(JSON.stringify(result, null, 2))\n } else {\n // Non-JSON mode: display human-readable success message\n logger.success(`Enhancement process completed for issue #${issueNumber}`)\n }\n process.exit(0)\n } catch (error) {\n logger.error(`Failed to enhance issue: ${error instanceof Error ? error.message : 'Unknown error'}`)\n process.exit(1)\n }\n }\n\n // Wrap execution in logger context for JSON mode\n if (options.json) {\n const jsonLogger = createStderrLogger()\n await withLogger(jsonLogger, executeAction)\n } else {\n await executeAction()\n }\n })\n\nprogram\n .command('finish')\n .alias('dn')\n .description('Merge work and cleanup workspace')\n .argument('[identifier]', 'Issue number, PR number, or branch name (auto-detected if omitted)')\n .option('-f, --force', 'Skip confirmation prompts')\n .option('-n, --dry-run', 'Preview actions without executing')\n .option('--pr <number>', 'Treat input as PR number', parseFloat)\n .option('--skip-build', 'Skip post-merge build verification')\n .option('--no-browser', 'Skip opening PR in browser (github-pr mode only)')\n .option('--cleanup', 'Clean up worktree after PR creation (github-pr mode only)')\n .option('--no-cleanup', 'Keep worktree after PR creation (github-pr mode only)')\n .option('--json', 'Output result as JSON')\n .action(async (identifier: string | undefined, options: FinishOptions) => {\n const executeAction = async (): Promise<void> => {\n try {\n const settingsManager = new SettingsManager()\n const settings = await settingsManager.loadSettings()\n const issueTracker = IssueTrackerFactory.create(settings)\n const command = new FinishCommand(issueTracker)\n const result = await command.execute({ identifier, options })\n if (options.json && result) {\n console.log(JSON.stringify(result, null, 2))\n }\n process.exit(0)\n } catch (error) {\n if (options.json) {\n console.log(JSON.stringify({ success: false, error: error instanceof Error ? error.message : 'Unknown error' }, null, 2))\n } else {\n logger.error(`Failed to finish workspace: ${error instanceof Error ? error.message : 'Unknown error'}`)\n }\n process.exit(1)\n }\n }\n\n // Wrap execution in logger context for JSON mode\n if (options.json) {\n const jsonLogger = createStderrLogger()\n await withLogger(jsonLogger, executeAction)\n } else {\n await executeAction()\n }\n })\n\nprogram\n .command('rebase')\n .description('Rebase current branch on main with Claude-assisted conflict resolution')\n .option('-f, --force', 'Skip confirmation prompts')\n .option('-n, --dry-run', 'Preview actions without executing')\n .action(async (options: { force?: boolean; dryRun?: boolean }) => {\n try {\n const { RebaseCommand } = await import('./commands/rebase.js')\n const command = new RebaseCommand()\n await command.execute(options)\n } catch (error) {\n logger.error(`Failed to rebase: ${error instanceof Error ? error.message : 'Unknown error'}`)\n process.exit(1)\n }\n })\n\nprogram\n .command('spin')\n .alias('ignite')\n .description('Launch Claude with auto-detected workspace context')\n .addOption(\n new Option('--one-shot <mode>', 'One-shot automation mode')\n .choices(['default', 'noReview', 'bypassPermissions'])\n .default('default')\n )\n .action(async (options: { oneShot?: import('./types/index.js').OneShotMode }) => {\n try {\n const { IgniteCommand } = await import('./commands/ignite.js')\n const command = new IgniteCommand()\n await command.execute(options.oneShot ?? 'default')\n } catch (error) {\n logger.error(`Failed to spin up loom: ${error instanceof Error ? error.message : 'Unknown error'}`)\n process.exit(1)\n }\n })\n\nprogram\n .command('open')\n .description('Open workspace in browser or run CLI tool')\n .argument('[identifier]', 'Issue number, PR number, or branch name (auto-detected if omitted)')\n .allowUnknownOption()\n .action(async (identifier?: string, _options?: Record<string, unknown>, command?: Command) => {\n try {\n // Extract additional arguments - everything after identifier\n const args = command?.args ? command.args.slice(identifier ? 1 : 0) : []\n\n const { OpenCommand } = await import('./commands/open.js')\n const cmd = new OpenCommand()\n const input = identifier ? { identifier, args } : { args }\n await cmd.execute(input)\n } catch (error) {\n logger.error(`Failed to open: ${error instanceof Error ? error.message : 'Unknown error'}`)\n process.exit(1)\n }\n })\n\nprogram\n .command('run')\n .description('Run CLI tool or open workspace in browser')\n .argument('[identifier]', 'Issue number, PR number, or branch name (auto-detected if omitted)')\n .allowUnknownOption()\n .action(async (identifier?: string, _options?: Record<string, unknown>, command?: Command) => {\n try {\n // Extract additional arguments - everything after identifier\n const args = command?.args ? command.args.slice(identifier ? 1 : 0) : []\n\n const { RunCommand } = await import('./commands/run.js')\n const cmd = new RunCommand()\n const input = identifier ? { identifier, args } : { args }\n await cmd.execute(input)\n } catch (error) {\n logger.error(`Failed to run: ${error instanceof Error ? error.message : 'Unknown error'}`)\n process.exit(1)\n }\n })\n\nprogram\n .command('dev-server')\n .alias('dev')\n .description('Start dev server for workspace (foreground)')\n .argument('[identifier]', 'Issue number, PR number, or branch name (auto-detected if omitted)')\n .option('--json', 'Output as JSON')\n .action(async (identifier?: string, options?: { json?: boolean }) => {\n try {\n const { DevServerCommand } = await import('./commands/dev-server.js')\n const cmd = new DevServerCommand()\n await cmd.execute({ identifier, json: options?.json })\n } catch (error) {\n logger.error(`Failed to start dev server: ${error instanceof Error ? error.message : 'Unknown error'}`)\n process.exit(1)\n }\n })\n\nprogram\n .command('cleanup')\n .alias('remove')\n .alias('clean')\n .description('Remove workspaces')\n .argument('[identifier]', 'Branch name or issue number to cleanup (auto-detected)')\n .option('-l, --list', 'List all worktrees')\n .option('-a, --all', 'Remove all worktrees (interactive confirmation)')\n .option('-i, --issue <number>', 'Cleanup by issue number', parseInt)\n .option('-f, --force', 'Skip confirmations and force removal')\n .option('--dry-run', 'Show what would be done without doing it')\n .option('--json', 'Output result as JSON')\n .action(async (identifier?: string, options?: CleanupOptions) => {\n const executeAction = async (): Promise<void> => {\n try {\n const { CleanupCommand } = await import('./commands/cleanup.js')\n const command = new CleanupCommand()\n const input: { identifier?: string; options: CleanupOptions } = {\n options: options ?? {}\n }\n if (identifier) {\n input.identifier = identifier\n }\n const result = await command.execute(input)\n if (options?.json && result) {\n console.log(JSON.stringify(result, null, 2))\n }\n process.exit(0)\n } catch (error) {\n if (options?.json) {\n console.log(JSON.stringify({ success: false, error: error instanceof Error ? error.message : 'Unknown error' }, null, 2))\n } else {\n // Error message is already well-formatted (e.g., \"Cannot cleanup:\\n\\n...\")\n logger.error(error instanceof Error ? error.message : 'Unknown error')\n }\n process.exit(1)\n }\n }\n\n // Wrap execution in logger context for JSON mode\n if (options?.json) {\n const jsonLogger = createStderrLogger()\n await withLogger(jsonLogger, executeAction)\n } else {\n await executeAction()\n }\n })\n\nprogram\n .command('list')\n .description('Show active workspaces')\n .option('--json', 'Output as JSON')\n .action(async (options: { json?: boolean }) => {\n try {\n const manager = new GitWorktreeManager()\n const metadataManager = new MetadataManager()\n const worktrees = await manager.listWorktrees({ porcelain: true })\n\n // Read metadata for all worktrees (spec section 3.2)\n const metadata = new Map<string, LoomMetadata | null>()\n for (const worktree of worktrees) {\n const loomMetadata = await metadataManager.readMetadata(worktree.path)\n metadata.set(worktree.path, loomMetadata)\n }\n\n if (options.json) {\n const mainWorktreePath = await findMainWorktreePathWithSettings()\n console.log(JSON.stringify(formatLoomsForJson(worktrees, mainWorktreePath, metadata), null, 2))\n return\n }\n\n if (worktrees.length === 0) {\n logger.info('No worktrees found')\n return\n }\n\n logger.info('Active workspaces:')\n for (const worktree of worktrees) {\n const formatted = manager.formatWorktree(worktree)\n const loomMetadata = metadata.get(worktree.path)\n logger.info(` ${formatted.title}`)\n if (loomMetadata?.description) {\n logger.info(` Description: ${loomMetadata.description}`)\n }\n logger.info(` Path: ${formatted.path}`)\n logger.info(` Commit: ${formatted.commit}`)\n }\n } catch (error) {\n // Handle \"not a git repository\" gracefully\n if (error instanceof Error && error.message.includes('not a git repository')) {\n if (options.json) {\n console.log('[]')\n } else {\n logger.info('No worktrees found')\n }\n return\n }\n logger.error(`Failed to list worktrees: ${error instanceof Error ? error.message : 'Unknown error'}`)\n process.exit(1)\n }\n })\n\nprogram\n .command('projects')\n .description('List configured iloom projects')\n .option('--json', 'Output as JSON (default behavior)')\n .action(async (options: { json?: boolean }) => {\n try {\n const { ProjectsCommand } = await import('./commands/projects.js')\n const command = new ProjectsCommand()\n const result = await command.execute(options)\n console.log(JSON.stringify(result, null, 2))\n } catch (error) {\n logger.error(`Failed to list projects: ${error instanceof Error ? error.message : 'Unknown error'}`)\n process.exit(1)\n }\n })\n\nprogram\n .command('init')\n .alias('config')\n .description('Initialize iloom configuration and setup shell autocomplete')\n .argument('[prompt]', 'Custom initial message to send to Claude (defaults to \"Help me configure iloom settings.\")')\n .action(async (prompt?: string) => {\n try {\n const { InitCommand } = await import('./commands/init.js')\n const command = new InitCommand()\n // Pass custom prompt if provided and non-empty\n const trimmedPrompt = prompt?.trim()\n const customPrompt = trimmedPrompt && trimmedPrompt.length > 0 ? trimmedPrompt : undefined\n await command.execute(customPrompt)\n } catch (error) {\n logger.error(`Failed to initialize: ${error instanceof Error ? error.message : 'Unknown error'}`)\n process.exit(1)\n }\n })\n\nprogram\n .command('contribute')\n .description('Set up local development environment for contributing to iloom')\n .action(async () => {\n try {\n const { ContributeCommand } = await import('./commands/contribute.js')\n const command = new ContributeCommand()\n await command.execute()\n } catch (error) {\n logger.error(`Failed to set up contributor environment: ${error instanceof Error ? error.message : 'Unknown error'}`)\n process.exit(1)\n }\n })\n\nprogram\n .command('update')\n .description('Update iloom-cli to the latest version')\n .option('--dry-run', 'Show what would be done without actually updating')\n .action(async (options: { dryRun?: boolean }) => {\n try {\n const { UpdateCommand } = await import('./commands/update.js')\n const command = new UpdateCommand()\n await command.execute(options)\n } catch (error) {\n logger.error(`Failed to update: ${error instanceof Error ? error.message : 'Unknown error'}`)\n process.exit(1)\n }\n })\n\n// Test command for GitHub integration\nprogram\n .command('test-github')\n .description('Test GitHub integration (Issue #3)')\n .argument('<identifier>', 'Issue number or PR number')\n .option('--no-claude', 'Skip Claude for branch name generation')\n .action(async (identifier: string, options: { claude?: boolean }) => {\n try {\n const { GitHubService } = await import('./lib/GitHubService.js')\n const { DefaultBranchNamingService } = await import('./lib/BranchNamingService.js')\n\n logger.info('Testing GitHub Integration\\n')\n\n const service = new GitHubService()\n const branchNaming = new DefaultBranchNamingService({ useClaude: options.claude !== false })\n\n // Test 1: Input detection\n logger.info('Detecting input type...')\n const detection = await service.detectInputType(identifier)\n logger.info(` Type: ${detection.type}`)\n logger.info(` Identifier: ${detection.identifier}`)\n\n if (detection.type === 'unknown') {\n logger.error('Could not detect if input is an issue or PR')\n process.exit(1)\n }\n\n // Test 2: Fetch the issue/PR\n logger.info('Fetching from GitHub...')\n if (detection.type === 'issue') {\n if (!detection.identifier) {\n throw new Error('Issue number not detected')\n }\n const issueNumber = parseInt(detection.identifier, 10)\n const issue = await service.fetchIssue(issueNumber)\n logger.success(` Issue #${issue.number}: ${issue.title}`)\n logger.info(` State: ${issue.state}`)\n logger.info(` Labels: ${issue.labels.join(', ') || 'none'}`)\n logger.info(` URL: ${issue.url}`)\n\n // Test 3: Generate branch name\n\n logger.info('Generating branch name...')\n const branchName = await branchNaming.generateBranchName({\n issueNumber: issue.number,\n title: issue.title\n })\n logger.success(` Branch: ${branchName}`)\n\n // Test 4: Extract context\n \n logger.info('Extracting context for Claude...')\n const context = service.extractContext(issue)\n logger.info(` ${context.split('\\n').join('\\n ')}`)\n\n } else {\n if (!detection.identifier) {\n throw new Error('PR number not detected')\n }\n const prNumber = parseInt(detection.identifier, 10)\n const pr = await service.fetchPR(prNumber)\n logger.success(` PR #${pr.number}: ${pr.title}`)\n logger.info(` State: ${pr.state}`)\n logger.info(` Branch: ${pr.branch}`)\n logger.info(` Base: ${pr.baseBranch}`)\n logger.info(` URL: ${pr.url}`)\n\n // Test 3: Extract context\n \n logger.info('Extracting context for Claude...')\n const context = service.extractContext(pr)\n logger.info(` ${context.split('\\n').join('\\n ')}`)\n }\n\n \n logger.success('All GitHub integration tests passed!')\n\n } catch (error) {\n logger.error(`Test failed: ${error instanceof Error ? error.message : 'Unknown error'}`)\n if (error instanceof Error && error.stack) {\n logger.debug(error.stack)\n }\n process.exit(1)\n }\n })\n\n// Test command for Claude integration\nprogram\n .command('test-claude')\n .description('Test Claude integration (Issue #10)')\n .option('--detect', 'Test Claude CLI detection')\n .option('--version', 'Get Claude CLI version')\n .option('--branch <title>', 'Test branch name generation with given title')\n .option('--issue <number>', 'Issue number for branch generation', '123')\n .option('--launch <prompt>', 'Launch Claude with a prompt (headless)')\n .option('--interactive', 'Launch Claude interactively (requires --launch)')\n .option('--template <name>', 'Test template loading')\n .action(async (options: {\n detect?: boolean\n version?: boolean\n branch?: string\n issue?: string\n launch?: string\n interactive?: boolean\n template?: 'issue' | 'pr' | 'regular'\n }) => {\n try {\n const { detectClaudeCli, getClaudeVersion, generateBranchName, launchClaude } = await import('./utils/claude.js')\n const { PromptTemplateManager } = await import('./lib/PromptTemplateManager.js')\n const { ClaudeService } = await import('./lib/ClaudeService.js')\n const { ClaudeContextManager } = await import('./lib/ClaudeContextManager.js')\n\n logger.info('Testing Claude Integration\\n')\n\n // Test 1: Detection\n if (options.detect) {\n logger.info('Detecting Claude CLI...')\n const isAvailable = await detectClaudeCli()\n if (isAvailable) {\n logger.success(' Claude CLI is available')\n } else {\n logger.error(' Claude CLI not found')\n }\n }\n\n // Test 2: Version\n if (options.version) {\n logger.info('Getting Claude version...')\n const version = await getClaudeVersion()\n if (version) {\n logger.success(` Version: ${version}`)\n } else {\n logger.error(' Could not get version')\n }\n }\n\n // Test 3: Branch name generation\n if (options.branch) {\n logger.info('Generating branch name...')\n const issueNumber = parseInt(options.issue ?? '123')\n logger.info(` Issue #${issueNumber}: ${options.branch}`)\n const branchName = await generateBranchName(options.branch, issueNumber)\n logger.success(` Generated: ${branchName}`)\n }\n\n // Test 4: Launch Claude\n if (options.launch) {\n logger.info('Launching Claude...')\n logger.info(` Prompt: \"${options.launch}\"`)\n logger.info(` Mode: ${options.interactive ? 'Interactive' : 'Headless'}`)\n\n if (options.interactive) {\n logger.info(' Launching Claude in new terminal...')\n await launchClaude(options.launch, { headless: false })\n logger.info(' (Claude should open in a separate process)')\n } else {\n logger.info(' Waiting for response...')\n const result = await launchClaude(options.launch, { headless: true })\n if (result) {\n logger.success(' Response:')\n logger.info(` ${result.split('\\n').join('\\n ')}`)\n }\n }\n }\n\n // Test 5: Template loading\n if (options.template) {\n logger.info('Loading template...')\n logger.info(` Template: ${options.template}`)\n const manager = new PromptTemplateManager()\n try {\n const content = await manager.loadTemplate(options.template)\n logger.success(' Template loaded successfully')\n logger.info(' First 200 chars:')\n logger.info(` ${content.substring(0, 200).split('\\n').join('\\n ')}...`)\n } catch (error) {\n logger.error(` Failed: ${error instanceof Error ? error.message : 'Unknown error'}`)\n }\n }\n\n // Run all tests in sequence when no specific options provided\n if (!options.detect && !options.version && !options.branch && !options.launch && !options.template) {\n logger.info('Running full Claude integration test suite...\\n')\n\n // Test 1: Detection\n logger.info('1. Testing Claude CLI detection...')\n const isAvailable = await detectClaudeCli()\n if (isAvailable) {\n logger.success(' Claude CLI is available')\n } else {\n logger.error(' Claude CLI not found')\n logger.info('\\nSkipping remaining tests since Claude CLI is not available')\n return\n }\n\n // Test 2: Version\n logger.info('\\n2. Getting Claude version...')\n const version = await getClaudeVersion()\n if (version) {\n logger.success(` Version: ${version}`)\n } else {\n logger.error(' Could not get version')\n }\n\n // Test 3: Branch name generation\n logger.info('\\n3. Testing branch name generation...')\n const testIssueNumber = 123\n const testTitle = 'Add user authentication feature'\n logger.info(` Issue #${testIssueNumber}: ${testTitle}`)\n const branchName = await generateBranchName(testTitle, testIssueNumber)\n logger.success(` Generated: ${branchName}`)\n\n // Test 4: Service initialization\n logger.info('\\n4. Testing ClaudeService initialization...')\n new ClaudeService() // Just verify it can be instantiated\n logger.success(' Service initialized')\n\n // Test 5: Context manager\n logger.info('\\n5. Testing ClaudeContextManager...')\n const contextManager = new ClaudeContextManager()\n await contextManager.prepareContext({\n type: 'issue',\n identifier: 123,\n title: 'Test issue',\n workspacePath: process.cwd(),\n port: 3123\n })\n logger.success(' Context prepared')\n\n // Test 6: Template loading\n logger.info('\\n6. Testing template loading...')\n const templateManager = new PromptTemplateManager()\n const templates: Array<'issue' | 'pr' | 'regular'> = ['issue', 'pr', 'regular']\n let templateCount = 0\n for (const template of templates) {\n try {\n await templateManager.loadTemplate(template)\n logger.success(` ${template} template loaded`)\n templateCount++\n } catch {\n logger.warn(` ${template} template not found`)\n }\n }\n logger.info(` Loaded ${templateCount}/${templates.length} templates`)\n\n // Test 7: Launch Claude headless (quick test)\n logger.info('\\n7. Testing Claude launch (headless)...')\n logger.info(' Sending test prompt: \"Say hello\"')\n try {\n const result = await launchClaude('Say hello', { headless: true })\n if (result) {\n logger.success(' Claude responded successfully')\n logger.info(` Response preview: ${result.substring(0, 100)}...`)\n } else {\n logger.warn(' No response received')\n }\n } catch (error) {\n logger.error(` Launch failed: ${error instanceof Error ? error.message : 'Unknown error'}`)\n }\n\n logger.info('\\n' + '='.repeat(50))\n logger.success('All Claude integration tests complete!')\n logger.info('Summary: All core Claude features are working correctly')\n }\n\n } catch (error) {\n logger.error(`Test failed: ${error instanceof Error ? error.message : 'Unknown error'}`)\n if (error instanceof Error && error.stack) {\n logger.debug(error.stack)\n }\n process.exit(1)\n }\n })\n\n// Test command for webserver detection\nprogram\n .command('test-webserver')\n .description('Test if a web server is running on a workspace port')\n .argument('<issue-number>', 'Issue number (port will be calculated as 3000 + issue number)', parseInt)\n .option('--kill', 'Kill the web server if detected')\n .action(async (issueNumber: number, options: { kill?: boolean }) => {\n try {\n const { TestWebserverCommand } = await import('./commands/test-webserver.js')\n const command = new TestWebserverCommand()\n await command.execute({ issueNumber, options })\n } catch (error) {\n logger.error(`Test webserver failed: ${error instanceof Error ? error.message : 'Unknown error'}`)\n if (error instanceof Error && error.stack) {\n logger.debug(error.stack)\n }\n process.exit(1)\n }\n })\n\n// Test command for Git integration\nprogram\n .command('test-git')\n .description('Test Git integration - findMainWorktreePath() function (reads .iloom/settings.json)')\n .action(async () => {\n try {\n const { TestGitCommand } = await import('./commands/test-git.js')\n const command = new TestGitCommand()\n await command.execute()\n } catch (error) {\n logger.error(`Test git failed: ${error instanceof Error ? error.message : 'Unknown error'}`)\n if (error instanceof Error && error.stack) {\n logger.debug(error.stack)\n }\n process.exit(1)\n }\n })\n\n// Test command for iTerm2 dual tab functionality\nprogram\n .command('test-tabs')\n .description('Test iTerm2 dual tab functionality - opens two tabs with test commands')\n .action(async () => {\n try {\n const { TestTabsCommand } = await import('./commands/test-tabs.js')\n const command = new TestTabsCommand()\n await command.execute()\n } catch (error) {\n logger.error(`Test tabs failed: ${error instanceof Error ? error.message : 'Unknown error'}`)\n if (error instanceof Error && error.stack) {\n logger.debug(error.stack)\n }\n process.exit(1)\n }\n })\n\n// Test command for worktree prefix configuration\nprogram\n .command('test-prefix')\n .description('Test worktree prefix configuration - preview worktree paths (reads .iloom/settings.json)')\n .action(async () => {\n try {\n const { TestPrefixCommand } = await import('./commands/test-prefix.js')\n const command = new TestPrefixCommand()\n await command.execute()\n } catch (error) {\n logger.error(`Test prefix failed: ${error instanceof Error ? error.message : 'Unknown error'}`)\n if (error instanceof Error && error.stack) {\n logger.debug(error.stack)\n }\n process.exit(1)\n }\n })\n\n// Command for session summary generation\nprogram\n .command('summary')\n .description('Generate Claude session summary for a loom')\n .argument('[identifier]', 'Issue number, PR number (pr/123), or branch name (auto-detected if omitted)')\n .option('--with-comment', 'Post summary as a comment to the issue/PR')\n .option('--json', 'Output result as JSON')\n .action(async (identifier: string | undefined, options: { withComment?: boolean; json?: boolean }) => {\n const executeAction = async (): Promise<void> => {\n try {\n const { SummaryCommand } = await import('./commands/summary.js')\n const command = new SummaryCommand()\n const result = await command.execute({ identifier, options })\n\n if (options.json && result) {\n // JSON mode: output structured result and exit\n console.log(JSON.stringify(result, null, 2))\n }\n process.exit(0)\n } catch (error) {\n if (options.json) {\n // JSON mode: output error as JSON\n console.log(JSON.stringify({ error: error instanceof Error ? error.message : 'Unknown error' }, null, 2))\n } else {\n logger.error(`Summary failed: ${error instanceof Error ? error.message : 'Unknown error'}`)\n if (error instanceof Error && error.stack) {\n logger.debug(error.stack)\n }\n }\n process.exit(1)\n }\n }\n\n // Wrap execution in logger context for JSON mode\n if (options.json) {\n const jsonLogger = createStderrLogger()\n await withLogger(jsonLogger, executeAction)\n } else {\n await executeAction()\n }\n })\n\n// Test command for Neon integration\nprogram\n .command('test-neon')\n .description('Test Neon integration and debug configuration')\n .action(async () => {\n try {\n const { SettingsManager } = await import('./lib/SettingsManager.js')\n const { createNeonProviderFromSettings } = await import('./utils/neon-helpers.js')\n\n logger.info('Testing Neon Integration\\n')\n\n // Test 1: Settings Configuration\n logger.info('1. Settings Configuration:')\n const settingsManager = new SettingsManager()\n const settings = await settingsManager.loadSettings()\n const neonConfig = settings.databaseProviders?.neon\n logger.info(` projectId: ${neonConfig?.projectId ?? '(not configured)'}`)\n logger.info(` parentBranch: ${neonConfig?.parentBranch ?? '(not configured)'}`)\n\n // Test 2: Create provider and test initialization\n logger.info('\\n2. Creating NeonProvider...')\n try {\n const neonProvider = createNeonProviderFromSettings(settings)\n logger.success(' NeonProvider created successfully')\n\n // Test 3: CLI availability\n logger.info('\\n3. Testing Neon CLI availability...')\n const isAvailable = await neonProvider.isCliAvailable()\n if (isAvailable) {\n logger.success(' Neon CLI is available')\n } else {\n logger.error(' Neon CLI not found')\n logger.info(' Install with: npm install -g @neon/cli')\n return\n }\n\n // Test 4: Authentication\n logger.info('\\n4. Testing Neon CLI authentication...')\n const isAuthenticated = await neonProvider.isAuthenticated()\n if (isAuthenticated) {\n logger.success(' Neon CLI is authenticated')\n } else {\n logger.error(' Neon CLI not authenticated')\n logger.info(' Run: neon auth')\n return\n }\n\n // Test 5: List branches (if config is valid)\n if (neonConfig?.projectId) {\n logger.info('\\n5. Testing branch listing...')\n try {\n const branches = await neonProvider.listBranches()\n logger.success(` Found ${branches.length} branches:`)\n for (const branch of branches.slice(0, 5)) { // Show first 5\n logger.info(` - ${branch}`)\n }\n if (branches.length > 5) {\n logger.info(` ... and ${branches.length - 5} more`)\n }\n } catch (error) {\n logger.error(` Failed to list branches: ${error instanceof Error ? error.message : 'Unknown error'}`)\n }\n } else {\n logger.warn('\\n5. Skipping branch listing (Neon not configured in settings)')\n }\n\n } catch (error) {\n logger.error(` Failed to create NeonProvider: ${error instanceof Error ? error.message : 'Unknown error'}`)\n if (error instanceof Error && error.message.includes('not configured')) {\n logger.info('\\n This is expected if Neon is not configured.')\n logger.info(' Configure databaseProviders.neon in .iloom/settings.json to test fully.')\n }\n }\n\n logger.info('\\n' + '='.repeat(50))\n logger.success('Neon integration test complete!')\n\n } catch (error) {\n logger.error(`Test failed: ${error instanceof Error ? error.message : 'Unknown error'}`)\n if (error instanceof Error && error.stack) {\n logger.debug(error.stack)\n }\n process.exit(1)\n }\n })\n\n// Add custom help command in order to get preAction to run (update check handled by preAction hook)\nprogram\n .command('help')\n .description('Display help information')\n .argument('[command]', 'Show help for specific command')\n .action(async (command?: string) => {\n // Show help (update check already ran in preAction)\n if (command) {\n // Show help for specific command\n const subCommand = program.commands.find(cmd => cmd.name() === command)\n if (subCommand) {\n subCommand.outputHelp()\n } else {\n logger.error(`Unknown command: ${command}`)\n program.outputHelp()\n }\n } else {\n program.outputHelp()\n }\n\n process.exit(0)\n })\n\n// Parse CLI arguments (only when run directly, not when imported for testing)\n// Resolve symlinks to handle npm link and global installs\nconst isRunDirectly = process.argv[1] && ((): boolean => {\n try {\n const scriptPath = realpathSync(process.argv[1])\n const modulePath = fileURLToPath(import.meta.url)\n return scriptPath === modulePath\n } catch {\n // If we can't resolve the path, assume we should run\n return true\n }\n})()\n\nif (isRunDirectly) {\n try {\n await program.parseAsync()\n } catch (error) {\n if (error instanceof Error) {\n logger.error(`Error: ${error.message}`)\n process.exit(1)\n }\n }\n}\n","import path from 'path'\nimport { getLogger } from '../utils/logger-context.js'\nimport type { IssueTracker } from '../lib/IssueTracker.js'\nimport { LoomManager } from '../lib/LoomManager.js'\nimport { DefaultBranchNamingService } from '../lib/BranchNamingService.js'\nimport { GitWorktreeManager } from '../lib/GitWorktreeManager.js'\nimport { EnvironmentManager } from '../lib/EnvironmentManager.js'\nimport { ClaudeContextManager } from '../lib/ClaudeContextManager.js'\nimport { ProjectCapabilityDetector } from '../lib/ProjectCapabilityDetector.js'\nimport { CLIIsolationManager } from '../lib/CLIIsolationManager.js'\nimport { SettingsManager } from '../lib/SettingsManager.js'\nimport { AgentManager } from '../lib/AgentManager.js'\nimport { DatabaseManager } from '../lib/DatabaseManager.js'\nimport { findMainWorktreePathWithSettings } from '../utils/git.js'\nimport { loadEnvIntoProcess } from '../utils/env.js'\nimport { extractSettingsOverrides } from '../utils/cli-overrides.js'\nimport { createNeonProviderFromSettings } from '../utils/neon-helpers.js'\nimport { getConfiguredRepoFromSettings, hasMultipleRemotes } from '../utils/remote.js'\nimport { capitalizeFirstLetter } from '../utils/text.js'\nimport type { StartOptions, StartResult } from '../types/index.js'\nimport { launchFirstRunSetup, needsFirstRunSetup } from '../utils/first-run-setup.js'\nimport { IssueTrackerFactory } from '../lib/IssueTrackerFactory.js'\n\nexport interface StartCommandInput {\n\tidentifier: string\n\toptions: StartOptions\n}\n\nexport interface ParsedInput {\n\ttype: 'issue' | 'pr' | 'branch' | 'description'\n\tnumber?: string | number\n\tbranchName?: string\n\toriginalInput: string\n}\n\nexport class StartCommand {\n\tprivate issueTracker: IssueTracker\n\tprivate loomManager: LoomManager | null = null\n\tprivate settingsManager: SettingsManager\n\tprivate providedLoomManager: LoomManager | undefined\n\n\tconstructor(\n\t\tissueTracker: IssueTracker,\n\t\tloomManager?: LoomManager,\n\t\t_agentManager?: AgentManager, // Kept for API compatibility\n\t\tsettingsManager?: SettingsManager\n\t) {\n\t\tthis.issueTracker = issueTracker\n\t\tthis.settingsManager = settingsManager ?? new SettingsManager()\n\t\t// Store provided LoomManager for testing, but don't initialize yet\n\t\tthis.providedLoomManager = loomManager\n\n\t\t// Load environment variables first\n\t\tconst envResult = loadEnvIntoProcess()\n\t\tif (envResult.error) {\n\t\t\tgetLogger().debug(`Environment loading warning: ${envResult.error.message}`)\n\t\t}\n\t\tif (envResult.parsed) {\n\t\t\tgetLogger().debug(`Loaded ${Object.keys(envResult.parsed).length} environment variables`)\n\t\t}\n\t}\n\n\t/**\n\t * Initialize LoomManager with the main worktree path\n\t * Uses lazy initialization to ensure we have the correct path\n\t */\n\tprivate async initializeLoomManager(): Promise<LoomManager> {\n\t\tif (this.loomManager) {\n\t\t\treturn this.loomManager\n\t\t}\n\n\t\tif (this.providedLoomManager) {\n\t\t\tthis.loomManager = this.providedLoomManager\n\t\t\treturn this.loomManager\n\t\t}\n\n\t\t// Find main worktree path\n\t\tconst mainWorktreePath = await findMainWorktreePathWithSettings()\n\n\t\t// Load settings to get database configuration\n\t\tconst settings = await this.settingsManager.loadSettings()\n\n\t\t// Create DatabaseManager with NeonProvider and EnvironmentManager\n\t\tconst environmentManager = new EnvironmentManager()\n\t\tconst neonProvider = createNeonProviderFromSettings(settings)\n\t\tconst databaseUrlEnvVarName = settings.capabilities?.database?.databaseUrlEnvVarName ?? 'DATABASE_URL'\n\n\t\tconst databaseManager = new DatabaseManager(neonProvider, environmentManager, databaseUrlEnvVarName)\n\n\t\t// Create BranchNamingService (defaults to Claude-based strategy)\n\t\tconst branchNaming = new DefaultBranchNamingService({ useClaude: true })\n\n\t\tthis.loomManager = new LoomManager(\n\t\t\tnew GitWorktreeManager(mainWorktreePath),\n\t\t\tthis.issueTracker,\n\t\t\tbranchNaming, // Add branch naming service\n\t\t\tenvironmentManager, // Reuse same instance\n\t\t\tnew ClaudeContextManager(),\n\t\t\tnew ProjectCapabilityDetector(),\n\t\t\tnew CLIIsolationManager(),\n\t\t\tthis.settingsManager, // Use same instance with CLI overrides\n\t\t\tdatabaseManager // Add database manager\n\t\t)\n\n\t\treturn this.loomManager\n\t}\n\n\t/**\n\t * Main entry point for the start command\n\t */\n\tpublic async execute(input: StartCommandInput): Promise<StartResult | void> {\n\t\tconst isJsonMode = input.options.json === true\n\n\t\ttry {\n\t\t\t// Step 0: Load settings and get configured repo for GitHub operations\n\t\t\tconst initialSettings = await this.settingsManager.loadSettings()\n\n\t\t\t// Skip first-run setup in JSON mode\n\t\t\tif (!isJsonMode && (process.env.FORCE_FIRST_TIME_SETUP === \"true\" || await needsFirstRunSetup())) {\n\t\t\t\tawait launchFirstRunSetup()\n\t\t\t\t// Reload settings and recreate issueTracker if provider changed during setup\n\t\t\t\tconst newSettings = await this.settingsManager.loadSettings()\n\t\t\t\tconst newProvider = newSettings.issueManagement?.provider ?? 'github'\n\t\t\t\tif (newProvider !== this.issueTracker.providerName) {\n\t\t\t\t\tgetLogger().debug(`Reinitializing issue tracker: provider changed to \"${newProvider}\"`)\n\t\t\t\t\tthis.issueTracker = IssueTrackerFactory.create(newSettings)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet repo: string | undefined\n\n\t\t\t// Only get repo if we have multiple remotes (prehook already validated config)\n\t\t\tif (this.issueTracker.providerName === 'github' && (await hasMultipleRemotes())) {\n\t\t\t\t// Only relevant for GitHub - Linear doesn't use repo info\n\t\t\t\trepo = await getConfiguredRepoFromSettings(initialSettings)\n\t\t\t\tgetLogger().info(`Using GitHub repository: ${repo}`)\n\t\t\t}\n\n\t\t\t// Step 0.5: Initialize LoomManager with main worktree path\n\t\t\tconst loomManager = await this.initializeLoomManager()\n\n\t\t\t// Step 0.6: Detect if running from inside an existing loom (for nested loom support)\n\t\t\tlet parentLoom = await this.detectParentLoom(loomManager)\n\n\t\t\t// Step 1: Parse and validate input (pass repo to methods)\n\t\t\tconst parsed = await this.parseInput(input.identifier, repo)\n\n\t\t\t// Step 2: Validate based on type\n\t\t\tawait this.validateInput(parsed, repo)\n\n\t\t\t// Step 2.4: Handle child loom decision\n\t\t\tif (parentLoom) {\n\t\t\t\tconst { isInteractiveEnvironment, promptConfirmation } = await import('../utils/prompt.js')\n\n\t\t\t\t// Format display message based on parent type\n\t\t\t\tconst parentDisplay = parentLoom.type === 'issue'\n\t\t\t\t\t? `issue #${parentLoom.identifier}`\n\t\t\t\t\t: parentLoom.type === 'pr'\n\t\t\t\t\t? `PR #${parentLoom.identifier}`\n\t\t\t\t\t: `branch ${parentLoom.identifier}`\n\n\t\t\t\t// Check for explicit flag first\n\t\t\t\tif (input.options.childLoom === true) {\n\t\t\t\t\t// --child-loom flag: force child loom (no prompt)\n\t\t\t\t\tgetLogger().info(`Creating as child loom of ${parentDisplay} (--child-loom flag)`)\n\t\t\t\t} else if (input.options.childLoom === false) {\n\t\t\t\t\t// --no-child-loom flag: force independent (no prompt)\n\t\t\t\t\tparentLoom = null\n\t\t\t\t\tgetLogger().info('Creating as independent loom (--no-child-loom flag)')\n\t\t\t\t} else {\n\t\t\t\t\t// No flag: use existing behavior (prompt or error if non-interactive)\n\t\t\t\t\t// JSON mode requires explicit flag\n\t\t\t\t\tif (isJsonMode) {\n\t\t\t\t\t\tthrow new Error('JSON mode requires explicit --child-loom or --no-child-loom flag when running from inside a loom')\n\t\t\t\t\t}\n\t\t\t\t\tlet createAsChild = true // Default for non-interactive\n\t\t\t\t\tif (isInteractiveEnvironment()) {\n\t\t\t\t\t\tcreateAsChild = await promptConfirmation(\n\t\t\t\t\t\t\t`You are not in your main worktree. Create as a child loom of ${parentDisplay}?`,\n\t\t\t\t\t\t\ttrue // Default yes\n\t\t\t\t\t\t)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tgetLogger().error(`Non-interactive environment detected, use either --child-loom or --no-child-loom to specify behavior`)\n\t\t\t\t\t\tprocess.exit(1)\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!createAsChild) {\n\t\t\t\t\t\tparentLoom = null // User declined, proceed as normal loom\n\t\t\t\t\t\tgetLogger().info('Creating as independent loom')\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (input.options.childLoom === true) {\n\t\t\t\t// --child-loom flag but not in a parent loom - ignore silently (per requirements)\n\t\t\t\tgetLogger().debug('--child-loom flag provided but not running from inside an existing loom (ignored)')\n\t\t\t}\n\t\t\t// Note: --no-child-loom when no parent is a no-op (already independent)\n\n\t\t\t// Step 2.5: Handle description input - create GitHub issue\n\t\t\tif (parsed.type === 'description') {\n\t\t\t\tgetLogger().info('Creating GitHub issue from description...')\n\t\t\t\t// Apply first-letter capitalization to title and body\n\t\t\t\tconst title = capitalizeFirstLetter(parsed.originalInput)\n\t\t\t\tconst body = input.options.body ? capitalizeFirstLetter(input.options.body) : \"\"\n\t\t\t\tconst result = await this.issueTracker.createIssue(\n\t\t\t\t\ttitle, // Use capitalized description as title\n\t\t\t\t\tbody // Use capitalized body or empty\n\t\t\t\t)\n\t\t\t\tgetLogger().success(`Created issue #${result.number}: ${result.url}`)\n\t\t\t\t// Update parsed to be an issue type with the new number\n\t\t\t\tparsed.type = 'issue'\n\t\t\t\tparsed.number = result.number\n\t\t\t}\n\n\t\t\t// Step 2.7: Confirm bypassPermissions mode if applicable\n\t\t\tif (input.options.oneShot === 'bypassPermissions') {\n\t\t\t\t// JSON mode cannot use bypassPermissions confirmation prompt\n\t\t\t\tif (isJsonMode) {\n\t\t\t\t\tthrow new Error('JSON mode does not support bypassPermissions confirmation prompt')\n\t\t\t\t}\n\t\t\t\tconst { promptConfirmation } = await import('../utils/prompt.js')\n\t\t\t\tconst confirmed = await promptConfirmation(\n\t\t\t\t\t'WARNING: bypassPermissions mode will allow Claude to execute all tool calls without confirmation. ' +\n\t\t\t\t\t'This can be dangerous. Do you want to proceed?'\n\t\t\t\t)\n\t\t\t\tif (!confirmed) {\n\t\t\t\t\tgetLogger().info('Operation cancelled by user')\n\t\t\t\t\tprocess.exit(0)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Step 2.8: Load workflow-specific settings with CLI overrides\n\t\t\tconst cliOverrides = extractSettingsOverrides()\n\t\t\tconst settings = await this.settingsManager.loadSettings(undefined, cliOverrides)\n\t\t\tconst workflowType = parsed.type === 'branch' ? 'regular' : parsed.type\n\t\t\tconst workflowConfig = settings.workflows?.[workflowType]\n\n\t\t\t// Step 2.9: Extract raw --set arguments and executable path for forwarding to spin\n\t\t\tconst { extractRawSetArguments, getExecutablePath } = await import('../utils/cli-overrides.js')\n\t\t\tconst setArguments = extractRawSetArguments()\n\t\t\tconst executablePath = getExecutablePath()\n\n\t\t\t// Step 3: Log success and create loom\n\t\t\tgetLogger().info(`Validated input: ${this.formatParsedInput(parsed)}`)\n\n\t\t\t// Step 4: Create loom using LoomManager\n\t\t\tconst identifier =\n\t\t\t\tparsed.type === 'branch'\n\t\t\t\t\t? parsed.branchName ?? ''\n\t\t\t\t\t: parsed.number ?? 0\n\n\t\t\t// Apply configuration precedence: CLI flags > workflow config > defaults (true)\n\t\t\tconst enableClaude = input.options.claude ?? workflowConfig?.startAiAgent ?? true\n\t\t\tconst enableCode = input.options.code ?? workflowConfig?.startIde ?? true\n\t\t\tconst enableDevServer = input.options.devServer ?? workflowConfig?.startDevServer ?? true\n\t\t\tconst enableTerminal = input.options.terminal ?? workflowConfig?.startTerminal ?? false\n\n\t\t\tgetLogger().debug('Final workflow config values:', {\n\t\t\t\tenableClaude,\n\t\t\t\tenableCode,\n\t\t\t\tenableDevServer,\n\t\t\t\tenableTerminal,\n\t\t\t})\n\n\t\t\tconst loom = await loomManager.createIloom({\n\t\t\t\ttype: parsed.type,\n\t\t\t\tidentifier,\n\t\t\t\toriginalInput: parsed.originalInput,\n\t\t\t\t...(parentLoom && { parentLoom }),\n\t\t\t\toptions: {\n\t\t\t\t\tenableClaude,\n\t\t\t\t\tenableCode,\n\t\t\t\t\tenableDevServer,\n\t\t\t\t\tenableTerminal,\n\t\t\t\t\t...(input.options.oneShot && { oneShot: input.options.oneShot }),\n\t\t\t\t\t...(setArguments.length > 0 && { setArguments }),\n\t\t\t\t\t...(executablePath && { executablePath }),\n\t\t\t\t},\n\t\t\t})\n\n\t\t\tgetLogger().success(`Created loom: ${loom.id} at ${loom.path}`)\n\t\t\tgetLogger().info(` Branch: ${loom.branch}`)\n\t\t\t// Only show port for web projects\n\t\t\tif (loom.capabilities?.includes('web')) {\n\t\t\t\tgetLogger().info(` Port: ${loom.port}`)\n\t\t\t}\n\t\t\tif (loom.issueData?.title) {\n\t\t\t\tgetLogger().info(` Title: ${loom.issueData.title}`)\n\t\t\t}\n\n\t\t\t// Return StartResult in JSON mode\n\t\t\tif (isJsonMode) {\n\t\t\t\treturn {\n\t\t\t\t\tid: loom.id,\n\t\t\t\t\tpath: loom.path,\n\t\t\t\t\tbranch: loom.branch,\n\t\t\t\t\ttype: parsed.type,\n\t\t\t\t\tidentifier: loom.identifier,\n\t\t\t\t\t...(loom.port !== undefined && { port: loom.port }),\n\t\t\t\t\t...(loom.issueData?.title && { title: loom.issueData.title }),\n\t\t\t\t\t...(loom.capabilities && { capabilities: loom.capabilities }),\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error) {\n\t\t\t\tgetLogger().error(`${error.message}`)\n\t\t\t} else {\n\t\t\t\tgetLogger().error('An unknown error occurred')\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t/**\n\t * Parse input to determine type and extract relevant data\n\t */\n\tprivate async parseInput(identifier: string, repo?: string): Promise<ParsedInput> {\n\t\t// Check if user wants to skip capitalization by prefixing with space\n\t\t// We preserve this for description types so capitalizeFirstLetter() can handle it\n\t\tconst hasLeadingSpace = identifier.startsWith(' ')\n\n\t\t// Handle empty input\n\t\tconst trimmedIdentifier = identifier.trim()\n\t\tif (!trimmedIdentifier) {\n\t\t\tthrow new Error('Missing required argument: identifier')\n\t\t}\n\n\t\t// Check for description: >25 chars AND >2 spaces (in trimmed version)\n\t\tconst spaceCount = (trimmedIdentifier.match(/ /g) ?? []).length\n\t\tif (trimmedIdentifier.length > 25 && spaceCount > 2) {\n\t\t\t// Preserve leading space if present so capitalizeFirstLetter() can detect the override\n\t\t\treturn {\n\t\t\t\ttype: 'description',\n\t\t\t\toriginalInput: hasLeadingSpace ? ' ' + trimmedIdentifier : trimmedIdentifier,\n\t\t\t}\n\t\t}\n\n\t\t// Check for PR-specific formats: pr/123, PR-123, PR/123, Pr-123 (case-insensitive)\n\t\tconst prPattern = /^pr[/-](\\d+)$/i\n\t\tconst prMatch = trimmedIdentifier.match(prPattern)\n\t\tif (prMatch?.[1]) {\n\t\t\treturn {\n\t\t\t\ttype: 'pr',\n\t\t\t\tnumber: parseInt(prMatch[1], 10),\n\t\t\t\toriginalInput: trimmedIdentifier,\n\t\t\t}\n\t\t}\n\n\t\t// Check for Linear identifier format (TEAM-NUMBER, e.g., ENG-123, PLAT-456)\n\t\t// Requires at least 2 letters before dash to avoid conflict with PR-123 format\n\t\tconst linearPattern = /^([A-Z]{2,}-\\d+)$/i\n\t\tconst linearMatch = trimmedIdentifier.match(linearPattern)\n\t\tif (linearMatch?.[1]) {\n\t\t\t// Use IssueTracker to validate it exists\n\t\t\tconst detection = await this.issueTracker.detectInputType(\n\t\t\t\ttrimmedIdentifier,\n\t\t\t\trepo\n\t\t\t)\n\n\t\t\tif (detection.type === 'issue' && detection.identifier) {\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'issue',\n\t\t\t\t\tnumber: detection.identifier, // Keep as string for Linear\n\t\t\t\t\toriginalInput: trimmedIdentifier,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Linear identifier format matched but not found\n\t\t\tthrow new Error(\n\t\t\t\t`Could not find Linear issue ${linearMatch[1].toUpperCase()}`\n\t\t\t)\n\t\t}\n\n\t\t// Check for numeric pattern (could be issue or PR)\n\t\tconst numericPattern = /^#?(\\d+)$/\n\t\tconst numericMatch = trimmedIdentifier.match(numericPattern)\n\t\tif (numericMatch?.[1]) {\n\t\t\tconst number = parseInt(numericMatch[1], 10)\n\n\t\t\t// Use IssueTracker to detect if it's a PR or issue\n\t\t\tconst detection = await this.issueTracker.detectInputType(\n\t\t\t\ttrimmedIdentifier,\n\t\t\t\trepo\n\t\t\t)\n\n\t\t\tif (detection.type === 'pr') {\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'pr',\n\t\t\t\t\tnumber: detection.identifier ? parseInt(detection.identifier, 10) : number,\n\t\t\t\t\toriginalInput: trimmedIdentifier,\n\t\t\t\t}\n\t\t\t} else if (detection.type === 'issue') {\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'issue',\n\t\t\t\t\tnumber: detection.identifier ? parseInt(detection.identifier, 10) : number,\n\t\t\t\t\toriginalInput: trimmedIdentifier,\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow new Error(`Could not find issue or PR #${number}`)\n\t\t\t}\n\t\t}\n\n\t\t// Treat as branch name\n\t\treturn {\n\t\t\ttype: 'branch',\n\t\t\tbranchName: trimmedIdentifier,\n\t\t\toriginalInput: trimmedIdentifier,\n\t\t}\n\t}\n\n\t/**\n\t * Validate the parsed input based on its type\n\t */\n\tprivate async validateInput(parsed: ParsedInput, repo?: string): Promise<void> {\n\t\tswitch (parsed.type) {\n\t\t\tcase 'pr': {\n\t\t\t\tif (!parsed.number) {\n\t\t\t\t\tthrow new Error('Invalid PR number')\n\t\t\t\t}\n\t\t\t\t// Check if provider supports PRs before calling PR methods\n\t\t\t\tif (!this.issueTracker.supportsPullRequests || !this.issueTracker.fetchPR || !this.issueTracker.validatePRState) {\n\t\t\t\t\tthrow new Error('Issue tracker does not support pull requests')\n\t\t\t\t}\n\t\t\t\t// Fetch and validate PR state\n\t\t\t\tconst pr = await this.issueTracker.fetchPR(parsed.number, repo)\n\t\t\t\tawait this.issueTracker.validatePRState(pr)\n\t\t\t\tgetLogger().debug(`Validated PR #${parsed.number}`)\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tcase 'issue': {\n\t\t\t\tif (!parsed.number) {\n\t\t\t\t\tthrow new Error('Invalid issue number')\n\t\t\t\t}\n\t\t\t\t// Fetch and validate issue state\n\t\t\t\tconst issue = await this.issueTracker.fetchIssue(parsed.number, repo)\n\t\t\t\tawait this.issueTracker.validateIssueState(issue)\n\t\t\t\tgetLogger().debug(`Validated issue #${parsed.number}`)\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tcase 'branch': {\n\t\t\t\tif (!parsed.branchName) {\n\t\t\t\t\tthrow new Error('Invalid branch name')\n\t\t\t\t}\n\t\t\t\t// Validate branch name characters (from bash script line 586)\n\t\t\t\tif (!this.isValidBranchName(parsed.branchName)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t'Invalid branch name. Use only letters, numbers, hyphens, underscores, and slashes'\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t\tgetLogger().debug(`Validated branch name: ${parsed.branchName}`)\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tcase 'description': {\n\t\t\t\t// Description inputs are valid - they will be converted to issues\n\t\t\t\tgetLogger().debug('Detected description input', {\n\t\t\t\t\tlength: parsed.originalInput.length\n\t\t\t\t})\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tconst unknownType = parsed as { type: string }\n\t\t\t\tthrow new Error(`Unknown input type: ${unknownType.type}`)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Validate branch name format\n\t */\n\tprivate isValidBranchName(branch: string): boolean {\n\t\t// Pattern from bash script line 586\n\t\treturn /^[a-zA-Z0-9/_-]+$/.test(branch)\n\t}\n\n\t/**\n\t * Format parsed input for display\n\t */\n\tprivate formatParsedInput(parsed: ParsedInput): string {\n\t\tswitch (parsed.type) {\n\t\t\tcase 'pr':\n\t\t\t\treturn `PR #${parsed.number}`\n\t\t\tcase 'issue':\n\t\t\t\treturn `Issue #${parsed.number}`\n\t\t\tcase 'branch':\n\t\t\t\treturn `Branch '${parsed.branchName}'`\n\t\t\tcase 'description':\n\t\t\t\treturn `Description: ${parsed.originalInput.slice(0, 50)}...`\n\t\t\tdefault:\n\t\t\t\treturn 'Unknown input'\n\t\t}\n\t}\n\n\t/**\n\t * Detect if running from inside an existing loom worktree\n\t * Returns parent loom info if detected, null otherwise\n\t */\n\tprivate async detectParentLoom(loomManager: LoomManager): Promise<{\n\t\ttype: 'issue' | 'pr' | 'branch'\n\t\tidentifier: string | number\n\t\tbranchName: string\n\t\tworktreePath: string\n\t\tdatabaseBranch?: string\n\t} | null> {\n\t\ttry {\n\t\t\tconst cwd = process.cwd()\n\t\t\tconst looms = await loomManager.listLooms()\n\n\t\t\tif (!looms) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\t// Get main worktree path to exclude it from valid parents\n\t\t\tconst mainWorktreePath = await findMainWorktreePathWithSettings()\n\n\t\t\t// Find loom containing current directory\n\t\t\t// Fix #2: Add path.sep check to prevent false positives (e.g., issue-123 vs issue-1234)\n\t\t\t// Exclude main worktree from being a valid parent\n\t\t\tconst parentLoom = looms.find(loom => {\n\t\t\t\t// Skip main worktree - it shouldn't be a parent for child looms\n\t\t\t\tif (loom.path === mainWorktreePath) {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t\t// Either exact match OR cwd starts with loom.path followed by path separator\n\t\t\t\treturn cwd === loom.path || cwd.startsWith(loom.path + path.sep)\n\t\t\t})\n\t\t\tif (!parentLoom) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tgetLogger().debug(`Detected parent loom: ${parentLoom.type} ${parentLoom.identifier} at ${parentLoom.path}`)\n\n\t\t\tconst result: {\n\t\t\t\ttype: 'issue' | 'pr' | 'branch'\n\t\t\t\tidentifier: string | number\n\t\t\t\tbranchName: string\n\t\t\t\tworktreePath: string\n\t\t\t\tdatabaseBranch?: string\n\t\t\t} = {\n\t\t\t\ttype: parentLoom.type,\n\t\t\t\tidentifier: parentLoom.identifier,\n\t\t\t\tbranchName: parentLoom.branch,\n\t\t\t\tworktreePath: parentLoom.path,\n\t\t\t}\n\n\t\t\t// Only include databaseBranch if it exists (exactOptionalPropertyTypes compatibility)\n\t\t\tif (parentLoom.databaseBranch) {\n\t\t\t\tresult.databaseBranch = parentLoom.databaseBranch\n\t\t\t}\n\n\t\t\t// Try to get database branch from parent's .env file via reverse lookup\n\t\t\tif (!result.databaseBranch) {\n\t\t\t\tconst databaseBranch = await loomManager.getDatabaseBranchForLoom(parentLoom.path)\n\t\t\t\tif (databaseBranch) {\n\t\t\t\t\tresult.databaseBranch = databaseBranch\n\t\t\t\t\tgetLogger().debug(`Detected parent database branch: ${databaseBranch}`)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn result\n\t\t} catch (error) {\n\t\t\t// If detection fails for any reason, just return null (don't break the start workflow)\n\t\t\tgetLogger().debug(`Failed to detect parent loom: ${error instanceof Error ? error.message : 'Unknown error'}`)\n\t\t\treturn null\n\t\t}\n\t}\n\n}\n","import { existsSync } from 'fs'\nimport { readFile } from 'fs/promises'\nimport path from 'path'\nimport { logger } from './logger.js'\nimport { FirstRunManager } from './FirstRunManager.js'\nimport { getRepoRoot } from './git.js'\nimport { InitCommand } from '../commands/init.js'\n\n/**\n * Get the project root path for first-run tracking\n * Uses git repo root if available, otherwise falls back to cwd\n * This ensures consistent path resolution regardless of where the CLI is run from\n */\nasync function getProjectRoot(): Promise<string> {\n\tconst repoRoot = await getRepoRoot()\n\tif (repoRoot) {\n\t\tlogger.debug(`getProjectRoot: Using git repo root: ${repoRoot}`)\n\t\treturn repoRoot\n\t}\n\tconst cwd = process.cwd()\n\tlogger.debug(`getProjectRoot: Not in git repo, using cwd: ${cwd}`)\n\treturn cwd\n}\n\n/**\n * Check if project needs first-run setup\n * Returns true if:\n * 1. Project is not tracked as configured globally AND\n * 2. .iloom directory is missing or settings files are empty\n *\n * Also performs fixup for legacy projects that have local config but lack\n * the global marker file (configured before global tracking was implemented)\n *\n * Uses git repo root for path resolution to ensure consistent behavior\n * regardless of whether the CLI is run from a subdirectory or worktree\n */\nexport async function needsFirstRunSetup(): Promise<boolean> {\n\tconst projectRoot = await getProjectRoot()\n\tconst firstRunManager = new FirstRunManager()\n\n\t// Fixup legacy projects that have local config but no global marker\n\t// This also returns whether the project is configured, avoiding duplicate isProjectConfigured() call\n\tconst { isConfigured } = await firstRunManager.fixupLegacyProject(projectRoot)\n\n\t// Check if project is tracked as configured globally\n\tif (isConfigured) {\n\t\tlogger.debug('needsFirstRunSetup: Project is tracked as configured globally')\n\t\treturn false\n\t}\n\n\tconst iloomDir = path.join(projectRoot, '.iloom')\n\n\t// Check if .iloom directory exists\n\tif (!existsSync(iloomDir)) {\n\t\treturn true\n\t}\n\n\t// Check if either settings file has meaningful content\n\tconst settingsPath = path.join(iloomDir, 'settings.json')\n\tconst settingsLocalPath = path.join(iloomDir, 'settings.local.json')\n\n\tconst hasSettings = await hasNonEmptySettings(settingsPath)\n\tconst hasLocalSettings = await hasNonEmptySettings(settingsLocalPath)\n\n\treturn !hasSettings && !hasLocalSettings\n}\n\nasync function hasNonEmptySettings(filePath: string): Promise<boolean> {\n\tif (!existsSync(filePath)) return false\n\ttry {\n\t\tconst content = await readFile(filePath, 'utf-8')\n\t\tconst parsed = JSON.parse(content)\n\t\treturn Object.keys(parsed).length > 0\n\t} catch {\n\t\treturn false\n\t}\n}\n\n/**\n * Launch interactive first-run setup via InitCommand\n */\nexport async function launchFirstRunSetup(): Promise<void> {\n\tlogger.info('First-time project setup detected.')\n\tlogger.info(\n\t\t'iloom will now launch an interactive configuration session with Claude.'\n\t)\n\n\tconst { waitForKeypress } = await import('./prompt.js')\n\tawait waitForKeypress('Press any key to start configuration...')\n\n\tconst initCommand = new InitCommand()\n\tawait initCommand.execute(\n\t\t'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.'\n\t)\n\n\t// Mark project as configured to prevent wizard from re-triggering\n\t// Use the same project root resolution as needsFirstRunSetup() for consistency\n\tconst projectRoot = await getProjectRoot()\n\tlogger.debug(`Marking project as configured at root: ${projectRoot}`)\n\tconst firstRunManager = new FirstRunManager()\n\tawait firstRunManager.markProjectAsConfigured(projectRoot)\n\tlogger.debug(`Project marked as configured at root: ${projectRoot}`)\n\n\tlogger.info('Configuration complete! Continuing with your original command...')\n}\n","import type { AddIssueOptions, AddIssueResult } from '../types/index.js'\nimport { IssueEnhancementService } from '../lib/IssueEnhancementService.js'\nimport { SettingsManager } from '../lib/SettingsManager.js'\nimport { getConfiguredRepoFromSettings, hasMultipleRemotes } from '../utils/remote.js'\nimport { launchFirstRunSetup, needsFirstRunSetup } from '../utils/first-run-setup.js'\nimport { getLogger } from '../utils/logger-context.js'\nimport { capitalizeFirstLetter } from '../utils/text.js'\n\n/**\n * Input structure for AddIssueCommand\n */\nexport interface AddIssueCommandInput {\n\tdescription: string\n\toptions: AddIssueOptions\n}\n\n/**\n * Command to create and enhance GitHub issues without creating workspaces.\n * This separates the \"document the work\" step from the \"start the work\" step.\n */\nexport class AddIssueCommand {\n\tprivate enhancementService: IssueEnhancementService\n\tprivate settingsManager: SettingsManager\n\n\tconstructor(enhancementService: IssueEnhancementService, settingsManager?: SettingsManager) {\n\t\tthis.enhancementService = enhancementService\n\t\tthis.settingsManager = settingsManager ?? new SettingsManager()\n\t}\n\n\t/**\n\t * Execute the add-issue command workflow:\n\t * 1. Validate description format\n\t * 2. Skip enhancement if body provided, otherwise enhance description with Claude Code\n\t * 3. Create GitHub issue\n\t * 4. Wait for keypress and open browser for review (unless --json mode)\n\t * 5. Return issue number or full result object (when --json)\n\t */\n\tpublic async execute(input: AddIssueCommandInput): Promise<AddIssueResult | string | number> {\n\t\t// Apply first-letter capitalization to title (description) and body\n\t\tconst description = capitalizeFirstLetter(input.description)\n\t\tconst body = input.options.body ? capitalizeFirstLetter(input.options.body) : undefined\n\t\tconst isJsonMode = input.options.json === true\n\n\t\t// Step 0: Check for first-run setup (skip in JSON mode - non-interactive)\n\t\tif (!isJsonMode && (process.env.FORCE_FIRST_TIME_SETUP === \"true\" || await needsFirstRunSetup())) {\n\t\t\tawait launchFirstRunSetup()\n\t\t}\n\n\t\t// Step 0.5: Load settings and get configured repo for GitHub operations\n\t\tconst settings = await this.settingsManager.loadSettings()\n\n\t\tlet repo: string | undefined\n\n\t\tif (this.enhancementService.issueTracker.providerName === 'github' && await hasMultipleRemotes()) {\n\t\t\t// Only relevant for GitHub - Linear doesn't use repo info\n\t\t\trepo = await getConfiguredRepoFromSettings(settings)\n\t\t\tif (!isJsonMode) {\n\t\t\t\tgetLogger().info(`Using GitHub repository: ${repo}`)\n\t\t\t}\n\t\t}\n\n\t\t// Step 1: Validate description format\n\t\tif (!description || !this.enhancementService.validateDescription(description)) {\n\t\t\tthrow new Error('Description is required and must be more than 30 characters with at least 3 words')\n\t\t}\n\n\t\t// Step 2: Skip enhancement if body provided, otherwise enhance description\n\t\tconst issueBody = body ?? await this.enhancementService.enhanceDescription(description)\n\n\t\t// Step 3: Create GitHub issue with original as title, body as body\n\t\tconst result = await this.enhancementService.createEnhancedIssue(\n\t\t\tdescription,\n\t\t\tissueBody,\n\t\t\trepo\n\t\t)\n\n\t\t// Step 4: Prepare result data for JSON mode\n\t\tif (isJsonMode) {\n\t\t\tconst resultData: AddIssueResult = {\n\t\t\t\turl: result.url,\n\t\t\t\tid: typeof result.number === 'string' ? parseInt(result.number, 10) : result.number,\n\t\t\t\ttitle: description,\n\t\t\t\tcreated_at: new Date().toISOString()\n\t\t\t}\n\t\t\treturn resultData\n\t\t}\n\n\t\t// Step 5: Wait for keypress and open issue in browser for review (non-JSON mode)\n\t\tawait this.enhancementService.waitForReviewAndOpen(result.number)\n\n\t\t// Step 6: Return issue number for reference\n\t\treturn result.number\n\t}\n}\n","import type { IssueTracker } from '../lib/IssueTracker.js'\nimport type { AgentManager } from '../lib/AgentManager.js'\nimport type { SettingsManager } from '../lib/SettingsManager.js'\nimport type { EnhanceResult } from '../types/index.js'\nimport { launchClaude } from '../utils/claude.js'\nimport { openBrowser } from '../utils/browser.js'\nimport { waitForKeypress } from '../utils/prompt.js'\nimport { getLogger } from '../utils/logger-context.js'\nimport { generateIssueManagementMcpConfig } from '../utils/mcp.js'\nimport { AgentManager as DefaultAgentManager } from '../lib/AgentManager.js'\nimport { SettingsManager as DefaultSettingsManager } from '../lib/SettingsManager.js'\nimport { getConfiguredRepoFromSettings, hasMultipleRemotes } from '../utils/remote.js'\nimport { launchFirstRunSetup, needsFirstRunSetup } from '../utils/first-run-setup.js'\n\nexport interface EnhanceCommandInput {\n\tissueNumber: string | number\n\toptions: EnhanceOptions\n}\n\nexport interface EnhanceOptions {\n\tnoBrowser?: boolean // Skip browser opening prompt\n\tauthor?: string // GitHub username of issue author for tagging\n\tjson?: boolean // Output result as JSON\n}\n\n/**\n * Command to enhance existing GitHub issues with AI assistance.\n * Applies the issue enhancer agent to an existing issue, respecting idempotency checks.\n */\nexport class EnhanceCommand {\n\tprivate issueTracker: IssueTracker\n\tprivate agentManager: AgentManager\n\tprivate settingsManager: SettingsManager\n\n\tconstructor(\n\t\tissueTracker: IssueTracker,\n\t\tagentManager?: AgentManager,\n\t\tsettingsManager?: SettingsManager\n\t) {\n\t\tthis.issueTracker = issueTracker\n\t\tthis.agentManager = agentManager ?? new DefaultAgentManager()\n\t\tthis.settingsManager = settingsManager ?? new DefaultSettingsManager()\n\t}\n\n\t/**\n\t * Execute the enhance command workflow:\n\t * 1. Validate issue number\n\t * 2. Fetch issue to verify it exists\n\t * 3. Load agent configurations\n\t * 4. Invoke Claude CLI with enhancer agent\n\t * 5. Parse response to determine outcome\n\t * 6. Handle browser interaction based on outcome (unless --json mode)\n\t * 7. Return result object when --json mode\n\t */\n\tpublic async execute(input: EnhanceCommandInput): Promise<EnhanceResult | void> {\n\t\tconst { issueNumber, options } = input\n\t\tconst { author } = options\n\t\tconst isJsonMode = options.json === true\n\n\t\t// Step 0: Check for first-run setup (skip in JSON mode - non-interactive)\n\t\tif (!isJsonMode && (process.env.FORCE_FIRST_TIME_SETUP === \"true\" || await needsFirstRunSetup())) {\n\t\t\tawait launchFirstRunSetup()\n\t\t}\n\n\t\t// Step 0.5: Load settings and get configured repo for GitHub operations\n\t\tconst settings = await this.settingsManager.loadSettings()\n\n\t\tlet repo: string | undefined\n\n\t\tif (this.issueTracker.providerName === 'github' && (await hasMultipleRemotes())) {\n\t\t\t// Only relevant for GitHub - Linear doesn't use repo info\n\t\t\trepo = await getConfiguredRepoFromSettings(settings)\n\t\t\tif (!isJsonMode) {\n\t\t\t\tgetLogger().info(`Using GitHub repository: ${repo}`)\n\t\t\t}\n\t\t}\n\n\t\t// Step 1: Validate issue number\n\t\tthis.validateIssueNumber(issueNumber)\n\n\t\t// Step 2: Fetch issue to verify it exists\n\t\tif (!isJsonMode) {\n\t\t\tgetLogger().info(`Fetching issue #${issueNumber}...`)\n\t\t}\n\t\tconst issue = await this.issueTracker.fetchIssue(issueNumber, repo)\n\t\tgetLogger().debug('Issue fetched successfully', { number: issue.number, title: issue.title })\n\n\t\t// Step 3: Load agent configurations\n\t\tgetLogger().debug('Loading agent configurations...')\n\t\tconst loadedAgents = await this.agentManager.loadAgents(settings)\n\t\tconst agents = this.agentManager.formatForCli(loadedAgents)\n\n\t\t// Step 3.5: Generate MCP config and tool filtering for issue management\n\t\tlet mcpConfig: Record<string, unknown>[] | undefined\n\t\tlet allowedTools: string[] | undefined\n\t\tlet disallowedTools: string[] | undefined\n\n\t\ttry {\n\t\t\tconst provider = this.issueTracker.providerName as 'github' | 'linear'\n\t\t\tmcpConfig = await generateIssueManagementMcpConfig('issue', repo, provider, settings)\n\t\t\tgetLogger().debug('Generated MCP configuration for issue management:', { mcpConfig })\n\n\t\t\t// Configure tool filtering for issue workflows\n\t\t\tallowedTools = [\n\t\t\t\t'mcp__issue_management__get_issue',\n\t\t\t\t'mcp__issue_management__get_comment',\n\t\t\t\t'mcp__issue_management__create_comment',\n\t\t\t\t'mcp__issue_management__update_comment',\n\t\t\t]\n\t\t\tdisallowedTools = ['Bash(gh api:*)']\n\n\t\t\tgetLogger().debug('Configured tool filtering for issue workflow', { allowedTools, disallowedTools })\n\t\t} catch (error) {\n\t\t\t// Log warning but continue without MCP\n\t\t\tgetLogger().warn(`Failed to generate MCP config: ${error instanceof Error ? error.message : 'Unknown error'}`)\n\t\t}\n\n\t\t// Step 4: Invoke Claude CLI with enhancer agent\n\t\tif (!isJsonMode) {\n\t\t\tgetLogger().info('Invoking enhancer agent. This may take a moment...')\n\t\t}\n\t\tconst prompt = this.constructPrompt(issueNumber, author)\n\t\tconst response = await launchClaude(prompt, {\n\t\t\theadless: true,\n\t\t\tmodel: 'sonnet',\n\t\t\tagents,\n\t\t\t...(mcpConfig && { mcpConfig }),\n\t\t\t...(allowedTools && { allowedTools }),\n\t\t\t...(disallowedTools && { disallowedTools }),\n\t\t})\n\n\t\t// Step 5: Parse response to determine outcome\n\t\tconst result = this.parseEnhancerResponse(response)\n\n\t\t// Step 6: Handle JSON mode - return structured result\n\t\tif (isJsonMode) {\n\t\t\tconst commentId = result.url ? this.extractCommentId(result.url) : 0\n\t\t\tconst resultData: EnhanceResult = {\n\t\t\t\turl: result.url ?? issue.url,\n\t\t\t\tid: commentId,\n\t\t\t\ttitle: issue.title,\n\t\t\t\tcreated_at: new Date().toISOString(),\n\t\t\t\tenhanced: result.enhanced\n\t\t\t}\n\t\t\treturn resultData\n\t\t}\n\n\t\t// Step 7: Handle non-JSON mode - browser interaction based on outcome\n\t\tif (!result.enhanced) {\n\t\t\tgetLogger().success('Issue already has thorough description. No enhancement needed.')\n\t\t\treturn\n\t\t}\n\n\t\tgetLogger().success(`Issue #${issueNumber} enhanced successfully!`)\n\t\tgetLogger().info(`Enhanced specification available at: ${result.url}`)\n\n\t\t// Prompt to open browser (unless --no-browser flag is set)\n\t\tif (!options.noBrowser && result.url) {\n\t\t\tawait this.promptAndOpenBrowser(result.url)\n\t\t}\n\t}\n\n\t/**\n\t * Extract comment ID from GitHub comment URL\n\t * @param url - GitHub comment URL (e.g., https://github.com/owner/repo/issues/123#issuecomment-456789)\n\t * @returns Comment ID as number, or 0 if not found\n\t */\n\tprivate extractCommentId(url: string): number {\n\t\tconst match = url.match(/issuecomment-(\\d+)/)\n\t\treturn match?.[1] ? parseInt(match[1], 10) : 0\n\t}\n\n\t/**\n\t * Validate that issue number is a valid positive integer\n\t */\n\tprivate validateIssueNumber(issueNumber: string | number): void {\n\t\tif (issueNumber === undefined || issueNumber === null) {\n\t\t\tthrow new Error('Issue number is required')\n\t\t}\n\n\t\t// For numeric types, validate as before\n\t\tif (typeof issueNumber === 'number') {\n\t\t\tif (Number.isNaN(issueNumber) || issueNumber <= 0 || !Number.isInteger(issueNumber)) {\n\t\t\t\tthrow new Error('Issue number must be a valid positive integer')\n\t\t\t}\n\t\t}\n\t\t// For string types, validate non-empty\n\t\tif (typeof issueNumber === 'string' && issueNumber.trim().length === 0) {\n\t\t\tthrow new Error('Issue identifier cannot be empty')\n\t\t}\n\t}\n\n\t/**\n\t * Construct the prompt for the orchestrating Claude instance.\n\t * This prompt is very clear about expected output format to ensure reliable parsing.\n\t */\n\tprivate constructPrompt(issueNumber: string | number, author?: string): string {\n\t\tconst authorInstruction = author\n\t\t\t? `\\nIMPORTANT: When you create your analysis comment, tag @${author} in the \"Questions for Reporter\" section if you have questions.\\n`\n\t\t\t: ''\n\n\t\treturn `Execute @agent-iloom-issue-enhancer ${issueNumber}${authorInstruction}\n\n## OUTPUT REQUIREMENTS\n* If the issue was not enhanced, return ONLY: \"No enhancement needed\"\n* If the issue WAS enhanced, return ONLY: <FULL URL OF THE COMMENT INCLUDING COMMENT ID>\n* If you encounter permission/authentication/access errors, return ONLY: \"Permission denied: <specific error description>\"\n* IMPORTANT: Return ONLY one of the above - DO NOT include commentary such as \"I created a comment at <URL>\" or \"I examined the issue and found no enhancement was necessary\"\n* CONTEXT: Your output is going to be parsed programmatically, so adherence to the output requirements is CRITICAL.`\n\t}\n\n\t/**\n\t * Parse the response from the enhancer agent.\n\t * Returns either { enhanced: false } or { enhanced: true, url: \"...\" }\n\t * Throws specific errors for permission issues.\n\t */\n\tprivate parseEnhancerResponse(response: string | void): { enhanced: boolean; url?: string } {\n\t\t// Handle empty or void response\n\t\tif (!response || typeof response !== 'string') {\n\t\t\tthrow new Error('No response from enhancer agent')\n\t\t}\n\n\t\tconst trimmed = response.trim()\n\n\t\tgetLogger().debug(`RESPONSE FROM ENHANCER AGENT: '${trimmed}'`)\n\n\t\t// Check for permission denied errors (case-insensitive)\n\t\tif (trimmed.toLowerCase().startsWith('permission denied:')) {\n\t\t\tconst errorMessage = trimmed.substring('permission denied:'.length).trim()\n\t\t\tthrow new Error(`Permission denied: ${errorMessage}`)\n\t\t}\n\n\t\t// Check for \"No enhancement needed\" (case-insensitive)\n\t\tif (trimmed.toLowerCase().includes('no enhancement needed')) {\n\t\t\treturn { enhanced: false }\n\t\t}\n\n\t\t// Check if response looks like a GitHub comment URL\n\t\tconst urlPattern = /https:\\/\\/github\\.com\\/[^/]+\\/[^/]+\\/issues\\/\\d+#issuecomment-\\d+/\n\t\tconst match = trimmed.match(urlPattern)\n\n\t\tif (match) {\n\t\t\treturn { enhanced: true, url: match[0] }\n\t\t}\n\n\t\t// Unexpected response format\n\t\tthrow new Error(`Unexpected response from enhancer agent: ${trimmed}`)\n\t}\n\n\t/**\n\t * Prompt user and open browser to view enhanced issue.\n\t * Matches the pattern from the issue specification.\n\t */\n\tprivate async promptAndOpenBrowser(commentUrl: string): Promise<void> {\n\t\ttry {\n\t\t\t// Prompt user with custom message\n\t\t\tconst key = await waitForKeypress(\n\t\t\t\t'Press q to quit or any other key to view the enhanced issue in a web browser...'\n\t\t\t)\n\n\t\t\t// Check if user pressed 'q' to quit\n\t\t\tif (key.toLowerCase() === 'q') {\n\t\t\t\tgetLogger().info('Skipping browser opening')\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Open browser with comment URL\n\t\t\tawait openBrowser(commentUrl)\n\t\t} catch (error) {\n\t\t\t// Browser opening failures should not be fatal\n\t\t\tgetLogger().warn(`Failed to open browser: ${error instanceof Error ? error.message : 'Unknown error'}`)\n\t\t}\n\t}\n\n}\n","import { getLogger } from '../utils/logger-context.js'\nimport { detectPackageManager, runScript } from '../utils/package-manager.js'\nimport { readPackageJson, hasScript } from '../utils/package-json.js'\nimport { detectClaudeCli, launchClaude } from '../utils/claude.js'\nimport type {\n\tValidationOptions,\n\tValidationResult,\n\tValidationStepResult,\n} from '../types/index.js'\n\n/**\n * ValidationRunner orchestrates pre-merge validation pipeline\n * Runs typecheck, lint, and tests in sequence with fail-fast behavior\n */\nexport class ValidationRunner {\n\tconstructor() {\n\t\t// Uses getLogger() for all logging operations\n\t}\n\n\t/**\n\t * Run all validations in sequence: typecheck → lint → test\n\t * Fails fast on first error\n\t */\n\tasync runValidations(\n\t\tworktreePath: string,\n\t\toptions: ValidationOptions = {}\n\t): Promise<ValidationResult> {\n\t\tconst startTime = Date.now()\n\t\tconst steps: ValidationStepResult[] = []\n\n\t\t// Run typecheck\n\t\tif (!options.skipTypecheck) {\n\t\t\tconst typecheckResult = await this.runTypecheck(\n\t\t\t\tworktreePath,\n\t\t\t\toptions.dryRun ?? false\n\t\t\t)\n\t\t\tsteps.push(typecheckResult)\n\n\t\t\tif (!typecheckResult.passed && !typecheckResult.skipped) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\tsteps,\n\t\t\t\t\ttotalDuration: Date.now() - startTime,\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Run lint\n\t\tif (!options.skipLint) {\n\t\t\tconst lintResult = await this.runLint(worktreePath, options.dryRun ?? false)\n\t\t\tsteps.push(lintResult)\n\n\t\t\tif (!lintResult.passed && !lintResult.skipped) {\n\t\t\t\treturn { success: false, steps, totalDuration: Date.now() - startTime }\n\t\t\t}\n\t\t}\n\n\t\t// Run tests\n\t\tif (!options.skipTests) {\n\t\t\tconst testResult = await this.runTests(\n\t\t\t\tworktreePath,\n\t\t\t\toptions.dryRun ?? false\n\t\t\t)\n\t\t\tsteps.push(testResult)\n\n\t\t\tif (!testResult.passed && !testResult.skipped) {\n\t\t\t\treturn { success: false, steps, totalDuration: Date.now() - startTime }\n\t\t\t}\n\t\t}\n\n\t\treturn { success: true, steps, totalDuration: Date.now() - startTime }\n\t}\n\n\t/**\n\t * Run typecheck validation\n\t * Prefers 'compile' script over 'typecheck' if both exist\n\t */\n\tprivate async runTypecheck(\n\t\tworktreePath: string,\n\t\tdryRun: boolean\n\t): Promise<ValidationStepResult> {\n\t\tconst stepStartTime = Date.now()\n\n\t\tlet scriptToRun: 'compile' | 'typecheck' | null = null\n\n\t\ttry {\n\t\t\t// Check for compile and typecheck scripts - prefer compile if both exist\n\t\t\tconst pkgJson = await readPackageJson(worktreePath)\n\t\t\tconst hasCompileScript = hasScript(pkgJson, 'compile')\n\t\t\tconst hasTypecheckScript = hasScript(pkgJson, 'typecheck')\n\n\t\t\tif (hasCompileScript) {\n\t\t\t\tscriptToRun = 'compile'\n\t\t\t} else if (hasTypecheckScript) {\n\t\t\t\tscriptToRun = 'typecheck'\n\t\t\t}\n\n\t\t\tif (!scriptToRun) {\n\t\t\t\tgetLogger().debug('Skipping typecheck - no compile or typecheck script found')\n\t\t\t\treturn {\n\t\t\t\t\tstep: 'typecheck',\n\t\t\t\t\tpassed: true,\n\t\t\t\t\tskipped: true,\n\t\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Handle missing package.json - skip validation for non-Node.js projects\n\t\t\tif (error instanceof Error && error.message.includes('package.json not found')) {\n\t\t\t\tgetLogger().debug('Skipping typecheck - no package.json found (non-Node.js project)')\n\t\t\t\treturn {\n\t\t\t\t\tstep: 'typecheck',\n\t\t\t\t\tpassed: true,\n\t\t\t\t\tskipped: true,\n\t\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Re-throw other errors\n\t\t\tthrow error\n\t\t}\n\n\t\tconst packageManager = await detectPackageManager(worktreePath)\n\n\t\tif (dryRun) {\n\t\t\tconst command =\n\t\t\t\tpackageManager === 'npm'\n\t\t\t\t\t? `npm run ${scriptToRun}`\n\t\t\t\t\t: `${packageManager} ${scriptToRun}`\n\t\t\tgetLogger().info(`[DRY RUN] Would run: ${command}`)\n\t\t\treturn {\n\t\t\t\tstep: scriptToRun,\n\t\t\t\tpassed: true,\n\t\t\t\tskipped: false,\n\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t}\n\t\t}\n\n\t\tgetLogger().info(`Running ${scriptToRun}...`)\n\n\t\ttry {\n\t\t\tawait runScript(scriptToRun, worktreePath, [], { quiet: true })\n\t\t\tgetLogger().success(`${scriptToRun.charAt(0).toUpperCase() + scriptToRun.slice(1)} passed`)\n\n\t\t\treturn {\n\t\t\t\tstep: scriptToRun,\n\t\t\t\tpassed: true,\n\t\t\t\tskipped: false,\n\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t}\n\t\t} catch {\n\t\t\t// Attempt Claude-assisted fix before failing\n\t\t\tconst fixed = await this.attemptClaudeFix(\n\t\t\t\tscriptToRun,\n\t\t\t\tworktreePath,\n\t\t\t\tpackageManager\n\t\t\t)\n\n\t\t\tif (fixed) {\n\t\t\t\treturn {\n\t\t\t\t\tstep: scriptToRun,\n\t\t\t\t\tpassed: true,\n\t\t\t\t\tskipped: false,\n\t\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Claude couldn't fix - throw original error\n\t\t\tconst runCommand =\n\t\t\t\tpackageManager === 'npm'\n\t\t\t\t\t? `npm run ${scriptToRun}`\n\t\t\t\t\t: `${packageManager} ${scriptToRun}`\n\n\t\t\tconst stepLabel = scriptToRun.charAt(0).toUpperCase() + scriptToRun.slice(1)\n\t\t\tthrow new Error(\n\t\t\t\t`Error: ${stepLabel} failed.\\n` +\n\t\t\t\t\t`Fix type errors before merging.\\n\\n` +\n\t\t\t\t\t`Run '${runCommand}' to see detailed errors.`\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * Run lint validation\n\t */\n\tprivate async runLint(\n\t\tworktreePath: string,\n\t\tdryRun: boolean\n\t): Promise<ValidationStepResult> {\n\t\tconst stepStartTime = Date.now()\n\n\t\ttry {\n\t\t\t// Check if lint script exists\n\t\t\tconst pkgJson = await readPackageJson(worktreePath)\n\t\t\tconst hasLintScript = hasScript(pkgJson, 'lint')\n\n\t\t\tif (!hasLintScript) {\n\t\t\t\tgetLogger().debug('Skipping lint - no lint script found')\n\t\t\t\treturn {\n\t\t\t\t\tstep: 'lint',\n\t\t\t\t\tpassed: true,\n\t\t\t\t\tskipped: true,\n\t\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Handle missing package.json - skip validation for non-Node.js projects\n\t\t\tif (error instanceof Error && error.message.includes('package.json not found')) {\n\t\t\t\tgetLogger().debug('Skipping lint - no package.json found (non-Node.js project)')\n\t\t\t\treturn {\n\t\t\t\t\tstep: 'lint',\n\t\t\t\t\tpassed: true,\n\t\t\t\t\tskipped: true,\n\t\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Re-throw other errors\n\t\t\tthrow error\n\t\t}\n\n\t\tconst packageManager = await detectPackageManager(worktreePath)\n\n\t\tif (dryRun) {\n\t\t\tconst command =\n\t\t\t\tpackageManager === 'npm' ? 'npm run lint' : `${packageManager} lint`\n\t\t\tgetLogger().info(`[DRY RUN] Would run: ${command}`)\n\t\t\treturn {\n\t\t\t\tstep: 'lint',\n\t\t\t\tpassed: true,\n\t\t\t\tskipped: false,\n\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t}\n\t\t}\n\n\t\tgetLogger().info('Running lint...')\n\n\t\ttry {\n\t\t\tawait runScript('lint', worktreePath, [], { quiet: true })\n\t\t\tgetLogger().success('Linting passed')\n\n\t\t\treturn {\n\t\t\t\tstep: 'lint',\n\t\t\t\tpassed: true,\n\t\t\t\tskipped: false,\n\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t}\n\t\t} catch {\n\t\t\t// Attempt Claude-assisted fix before failing\n\t\t\tconst fixed = await this.attemptClaudeFix(\n\t\t\t\t'lint',\n\t\t\t\tworktreePath,\n\t\t\t\tpackageManager\n\t\t\t)\n\n\t\t\tif (fixed) {\n\t\t\t\t// logger.success('Linting passed after Claude auto-fix')\n\t\t\t\treturn {\n\t\t\t\t\tstep: 'lint',\n\t\t\t\t\tpassed: true,\n\t\t\t\t\tskipped: false,\n\t\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Claude couldn't fix - throw original error\n\t\t\tconst runCommand =\n\t\t\t\tpackageManager === 'npm' ? 'npm run lint' : `${packageManager} lint`\n\n\t\t\tthrow new Error(\n\t\t\t\t`Error: Linting failed.\\n` +\n\t\t\t\t\t`Fix linting errors before merging.\\n\\n` +\n\t\t\t\t\t`Run '${runCommand}' to see detailed errors.`\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * Run test validation\n\t */\n\tprivate async runTests(\n\t\tworktreePath: string,\n\t\tdryRun: boolean\n\t): Promise<ValidationStepResult> {\n\t\tconst stepStartTime = Date.now()\n\n\t\ttry {\n\t\t\t// Check if test script exists\n\t\t\tconst pkgJson = await readPackageJson(worktreePath)\n\t\t\tconst hasTestScript = hasScript(pkgJson, 'test')\n\n\t\t\tif (!hasTestScript) {\n\t\t\t\tgetLogger().debug('Skipping tests - no test script found')\n\t\t\t\treturn {\n\t\t\t\t\tstep: 'test',\n\t\t\t\t\tpassed: true,\n\t\t\t\t\tskipped: true,\n\t\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Handle missing package.json - skip validation for non-Node.js projects\n\t\t\tif (error instanceof Error && error.message.includes('package.json not found')) {\n\t\t\t\tgetLogger().debug('Skipping tests - no package.json found (non-Node.js project)')\n\t\t\t\treturn {\n\t\t\t\t\tstep: 'test',\n\t\t\t\t\tpassed: true,\n\t\t\t\t\tskipped: true,\n\t\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Re-throw other errors\n\t\t\tthrow error\n\t\t}\n\n\t\tconst packageManager = await detectPackageManager(worktreePath)\n\n\t\tif (dryRun) {\n\t\t\tconst command =\n\t\t\t\tpackageManager === 'npm' ? 'npm run test' : `${packageManager} test`\n\t\t\tgetLogger().info(`[DRY RUN] Would run: ${command}`)\n\t\t\treturn {\n\t\t\t\tstep: 'test',\n\t\t\t\tpassed: true,\n\t\t\t\tskipped: false,\n\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t}\n\t\t}\n\n\t\tgetLogger().info('Running tests...')\n\n\t\ttry {\n\t\t\tawait runScript('test', worktreePath, [], { quiet: true })\n\t\t\tgetLogger().success('Tests passed')\n\n\t\t\treturn {\n\t\t\t\tstep: 'test',\n\t\t\t\tpassed: true,\n\t\t\t\tskipped: false,\n\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t}\n\t\t} catch {\n\t\t\t// Attempt Claude-assisted fix before failing\n\t\t\tconst fixed = await this.attemptClaudeFix(\n\t\t\t\t'test',\n\t\t\t\tworktreePath,\n\t\t\t\tpackageManager\n\t\t\t)\n\n\t\t\tif (fixed) {\n\t\t\t\t// logger.success('Tests passed after Claude auto-fix')\n\t\t\t\treturn {\n\t\t\t\t\tstep: 'test',\n\t\t\t\t\tpassed: true,\n\t\t\t\t\tskipped: false,\n\t\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Claude couldn't fix - throw original error\n\t\t\tconst runCommand =\n\t\t\t\tpackageManager === 'npm' ? 'npm run test' : `${packageManager} test`\n\n\t\t\tthrow new Error(\n\t\t\t\t`Error: Tests failed.\\n` +\n\t\t\t\t\t`Fix test failures before merging.\\n\\n` +\n\t\t\t\t\t`Run '${runCommand}' to see detailed errors.`\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * Attempt to fix validation errors using Claude\n\t * Pattern based on MergeManager.attemptClaudeConflictResolution\n\t *\n\t * @param validationType - Type of validation that failed ('compile' | 'typecheck' | 'lint' | 'test')\n\t * @param worktreePath - Path to the worktree\n\t * @param packageManager - Detected package manager\n\t * @returns true if Claude fixed the issue, false otherwise\n\t */\n\tprivate async attemptClaudeFix(\n\t\tvalidationType: 'compile' | 'typecheck' | 'lint' | 'test',\n\t\tworktreePath: string,\n\t\tpackageManager: string\n\t): Promise<boolean> {\n\t\t// Check if Claude CLI is available\n\t\tconst isClaudeAvailable = await detectClaudeCli()\n\t\tif (!isClaudeAvailable) {\n\t\t\tgetLogger().debug('Claude CLI not available, skipping auto-fix')\n\t\t\treturn false\n\t\t}\n\n\t\t// Build validation command for the prompt\n\t\tconst validationCommand = this.getValidationCommand(validationType, packageManager)\n\n\t\t// Build prompt based on validation type (matching bash script prompts)\n\t\tconst prompt = this.getClaudePrompt(validationType, validationCommand)\n\n\t\tconst validationTypeCapitalized = validationType.charAt(0).toUpperCase() + validationType.slice(1)\n\t\tgetLogger().info(`Launching Claude to help fix ${validationTypeCapitalized} errors...`)\n\n\t\ttry {\n\t\t\t// Launch Claude in interactive mode with acceptEdits permission\n\t\t\tawait launchClaude(prompt, {\n\t\t\t\taddDir: worktreePath,\n\t\t\t\theadless: false, // Interactive mode\n\t\t\t\tpermissionMode: 'acceptEdits', // Auto-accept edits\n\t\t\t\tmodel: 'sonnet', // Use Sonnet model\n\t\t\t})\n\n\t\t\t// After Claude completes, re-run validation to verify fix\n\t\t\tgetLogger().info(`Re-running ${validationTypeCapitalized} after Claude's fixes...`)\n\n\t\t\ttry {\n\t\t\t\tawait runScript(validationType, worktreePath, [], { quiet: true })\n\t\t\t\t// Validation passed after Claude fix\n\t\t\t\tgetLogger().success(`${validationTypeCapitalized} passed after Claude auto-fix`)\n\t\t\t\treturn true\n\t\t\t} catch {\n\t\t\t\t// Validation still failing after Claude's attempt\n\t\t\t\tgetLogger().warn(`${validationTypeCapitalized} still failing after Claude's help`)\n\t\t\t\treturn false\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Claude launch failed or crashed\n\t\t\tgetLogger().warn('Claude auto-fix failed', {\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t})\n\t\t\treturn false\n\t\t}\n\t}\n\n\t/**\n\t * Get validation command string for prompts\n\t */\n\tprivate getValidationCommand(\n\t\tvalidationType: 'compile' | 'typecheck' | 'lint' | 'test',\n\t\tpackageManager: string\n\t): string {\n\t\tif (packageManager === 'npm') {\n\t\t\treturn `npm run ${validationType}`\n\t\t}\n\t\treturn `${packageManager} ${validationType}`\n\t}\n\n\t/**\n\t * Get Claude prompt for specific validation type\n\t * Matches bash script prompts exactly\n\t */\n\tprivate getClaudePrompt(\n\t\tvalidationType: 'compile' | 'typecheck' | 'lint' | 'test',\n\t\tvalidationCommand: string\n\t): string {\n\t\tswitch (validationType) {\n\t\t\tcase 'compile':\n\t\t\tcase 'typecheck':\n\t\t\t\treturn (\n\t\t\t\t\t`There are TypeScript errors in this codebase. ` +\n\t\t\t\t\t`Please analyze the ${validationType} output, identify all type errors, and fix them. ` +\n\t\t\t\t\t`Run '${validationCommand}' to see the errors, then make the necessary code changes to resolve all type issues. ` +\n\t\t\t\t\t`When you are done, tell the user to quit using /exit to continue the validation process.`\n\t\t\t\t)\n\t\t\tcase 'lint':\n\t\t\t\treturn (\n\t\t\t\t\t`There are ESLint errors in this codebase. ` +\n\t\t\t\t\t`Please analyze the linting output, identify all linting issues, and fix them. ` +\n\t\t\t\t\t`Run '${validationCommand}' to see the errors, then make the necessary code changes to resolve all linting issues. ` +\n\t\t\t\t\t`Focus on code quality, consistency, and following the project's linting rules. ` +\n\t\t\t\t\t`When you are done, tell the user to quit using /exit to continue the validation process.`\n\t\t\t\t)\n\t\t\tcase 'test':\n\t\t\t\treturn (\n\t\t\t\t\t`There are unit test failures in this codebase. ` +\n\t\t\t\t\t`Please analyze the test output to understand what's failing, then fix the issues. ` +\n\t\t\t\t\t`This might involve updating test code, fixing bugs in the source code, or updating tests to match new behavior. ` +\n\t\t\t\t\t`Run '${validationCommand}' to see the detailed test failures, then make the necessary changes to get all tests passing. ` +\n\t\t\t\t\t`When you are done, tell the user to quit using /exit to continue the validation process.`\n\t\t\t\t)\n\t\t}\n\t}\n}\n","import { execa } from 'execa'\nimport { logger } from './logger.js'\n\n/**\n * Check if running inside VSCode's integrated terminal\n * VSCode sets TERM_PROGRAM=vscode in its integrated terminal\n */\nexport function isRunningInVSCode(): boolean {\n\treturn process.env.TERM_PROGRAM === 'vscode'\n}\n\n/**\n * Check if VSCode command-line tool is available\n */\nexport async function isVSCodeAvailable(): Promise<boolean> {\n\ttry {\n\t\tawait execa('command', ['-v', 'code'], {\n\t\t\tshell: true,\n\t\t\ttimeout: 5000,\n\t\t})\n\t\treturn true\n\t} catch (error) {\n\t\tlogger.debug('VSCode CLI not available', { error })\n\t\treturn false\n\t}\n}\n\n/**\n * Open VSCode window for workspace\n * Throws error if VSCode not available\n */\nexport async function openVSCodeWindow(workspacePath: string): Promise<void> {\n\t// Check availability first\n\tconst available = await isVSCodeAvailable()\n\tif (!available) {\n\t\tthrow new Error(\n\t\t\t'VSCode is not available. Please install VSCode and ensure the \"code\" command is in your PATH.\\n' +\n\t\t\t\t'Install command-line tools: Open VSCode > Command Palette > \"Shell Command: Install \\'code\\' command in PATH\"'\n\t\t)\n\t}\n\n\ttry {\n\t\t// Launch VSCode with workspace path\n\t\tawait execa('code', [workspacePath])\n\t\tlogger.debug(`Opened VSCode for workspace: ${workspacePath}`)\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`Failed to open VSCode: ${error instanceof Error ? error.message : 'Unknown error'}`\n\t\t)\n\t}\n}\n","// Core types\nexport interface Workspace {\n id: string\n path: string\n branch: string\n issueNumber?: string | number\n prNumber?: number\n port: number\n databaseBranch?: string\n createdAt: Date\n lastAccessed: Date\n}\n\nexport interface WorkspaceInput {\n identifier: string\n type: 'issue' | 'pr' | 'branch'\n skipClaude?: boolean\n}\n\nexport interface WorkspaceSummary {\n id: string\n issueNumber?: string | number\n prNumber?: number\n title: string\n branch: string\n port: number\n status: 'active' | 'stale' | 'error'\n lastAccessed: string\n}\n\n// Git types\nexport interface Worktree {\n path: string\n branch: string\n commit: string\n isPR: boolean\n prNumber?: number\n issueNumber?: string | number\n port?: number\n}\n\nexport interface GitStatus {\n hasUncommittedChanges: boolean\n unstagedFiles: string[]\n stagedFiles: string[]\n currentBranch: string\n isAheadOfRemote: boolean\n isBehindRemote: boolean\n}\n\n// GitHub types\nexport interface Issue {\n number: string | number\n title: string\n body: string\n state: 'open' | 'closed'\n labels: string[]\n assignees: string[]\n url: string\n}\n\nexport interface PullRequest {\n number: number\n title: string\n body: string\n state: 'open' | 'closed' | 'merged'\n branch: string\n baseBranch: string\n url: string\n isDraft: boolean\n}\n\n// Issue Tracker types\n/**\n * Generic input detection result for issue trackers\n * String-based identifier to support non-numeric IDs (e.g., Linear \"ENG-123\")\n */\nexport interface IssueTrackerInputDetection {\n\ttype: 'issue' | 'pr' | 'unknown'\n\tidentifier: string | null\n\trawInput: string\n}\n\n/**\n * Re-export branch naming types from branch-naming module\n * These types are provider-agnostic and support all issue trackers\n */\nexport type { BranchNameStrategy, BranchGenerationOptions } from './branch-naming.js'\n\n// Database types\n\n/**\n * Result of database branch deletion operation\n * Distinguishes between successful deletion, branch not found, and errors\n */\nexport interface DatabaseDeletionResult {\n /** Overall operation succeeded (true even if branch didn't exist) */\n success: boolean\n /** True only if a branch was actually deleted */\n deleted: boolean\n /** True if branch didn't exist (not an error, just nothing to do) */\n notFound: boolean\n /** Error message if operation failed */\n error?: string\n /** User declined deletion (for preview databases) */\n userDeclined?: boolean\n /** Name of the branch that was processed */\n branchName?: string\n}\n\nexport interface DatabaseProvider {\n // Core operations\n createBranch(name: string, fromBranch?: string, cwd?: string): Promise<string>\n deleteBranch(name: string, isPreview?: boolean, cwd?: string): Promise<DatabaseDeletionResult>\n getConnectionString(branch: string, cwd?: string): Promise<string>\n listBranches(cwd?: string): Promise<string[]>\n branchExists(name: string, cwd?: string): Promise<boolean>\n\n // Additional operations for Vercel integration and validation\n findPreviewBranch(branchName: string, cwd?: string): Promise<string | null>\n getBranchNameFromEndpoint(endpointId: string, cwd?: string): Promise<string | null>\n sanitizeBranchName(branchName: string): string\n isAuthenticated(cwd?: string): Promise<boolean>\n isCliAvailable(): Promise<boolean>\n\n // Configuration validation\n isConfigured(): boolean\n}\n\n// Configuration types\nexport interface Config {\n defaultPort: number\n databaseProvider?: 'neon' | 'supabase' | 'planetscale'\n claudeModel?: 'opus' | 'sonnet' | 'haiku'\n skipClaude?: boolean\n customWorkspaceRoot?: string\n}\n\n// One-shot automation mode type\nexport type OneShotMode = 'default' | 'noReview' | 'bypassPermissions'\n\n// Command option types\nexport interface StartOptions {\n // Individual component flags (can be combined)\n claude?: boolean\n code?: boolean\n devServer?: boolean\n terminal?: boolean\n // Child loom control flag\n childLoom?: boolean\n // One-shot automation mode\n oneShot?: OneShotMode\n // Optional body text for issue creation\n body?: string\n // Output result as JSON\n json?: boolean\n}\n\nexport interface AddIssueOptions {\n // Optional body text for issue (skips AI enhancement)\n body?: string\n // Output result as JSON\n json?: boolean\n}\n\nexport interface FeedbackOptions {\n // Optional body text for feedback (added after diagnostics)\n body?: string\n}\n\nexport interface EnhanceOptions {\n noBrowser?: boolean // --no-browser flag - skip browser opening prompt\n json?: boolean // --json flag - output result as JSON\n}\n\nexport interface FinishOptions {\n force?: boolean // -f, --force - Skip confirmation prompts\n dryRun?: boolean // -n, --dry-run - Preview actions without executing\n pr?: number // --pr <number> - Treat input as PR number\n skipBuild?: boolean // --skip-build - Skip post-merge build verification\n noBrowser?: boolean // --no-browser - Skip opening PR in browser (github-pr mode only)\n cleanup?: boolean // --cleanup / --no-cleanup - Control worktree cleanup after PR creation\n json?: boolean // --json - Output result as JSON\n}\n\n/**\n * Options for the cleanup command\n * All flags are optional and can be combined (subject to validation)\n */\nexport interface CleanupOptions {\n /** List all worktrees without removing anything */\n list?: boolean\n /** Remove all worktrees (interactive confirmation required unless --force) */\n all?: boolean\n /** Cleanup by specific issue number */\n issue?: number\n /** Skip confirmations and force removal */\n force?: boolean\n /** Show what would be done without actually doing it */\n dryRun?: boolean\n /** Output result as JSON */\n json?: boolean\n}\n\nexport interface ListOptions {\n json?: boolean\n}\n\n// JSON output result types for add-issue and enhance commands\nexport interface AddIssueResult {\n url: string\n id: number\n title: string\n created_at: string\n}\n\nexport interface EnhanceResult {\n url: string\n id: number\n title: string\n created_at: string\n enhanced: boolean\n}\n\nexport interface StartResult {\n id: string\n path: string\n branch: string\n port?: number\n type: 'issue' | 'pr' | 'branch'\n identifier: string | number\n title?: string\n capabilities?: string[]\n}\n\nexport interface FinishResult {\n success: boolean\n type: 'issue' | 'pr' | 'branch'\n identifier: string | number\n /** Whether this was a dry-run operation */\n dryRun?: boolean\n operations: Array<{\n type: 'validation' | 'commit' | 'rebase' | 'merge' | 'cleanup' | 'pr-creation' | 'build'\n message: string\n success: boolean\n error?: string\n }>\n prUrl?: string\n cleanupResult?: import('./cleanup.js').CleanupResult\n}\n\nexport interface SummaryResult {\n summary: string\n sessionId: string\n issueNumber?: string | number\n branchName: string\n loomType: 'issue' | 'pr' | 'branch'\n}\n\n// Deprecated: Result types - use exception-based error handling instead\n// export type Result<T, E = Error> = { success: true; data: T } | { success: false; error: E }\n\n// Mock factory types for testing\nexport interface MockOptions {\n scenario: 'empty' | 'existing' | 'conflicts' | 'error'\n data?: unknown\n}\n\n// Worktree management types\nexport * from './worktree.js'\n\n// Environment management types\nexport * from './environment.js'\n\n// Loom types\nexport * from './loom.js'\n\n// Cleanup types\nexport * from './cleanup.js'\n\n// Process types (excluding Platform which is already defined above)\nexport type { ProcessInfo } from './process.js'\n\n// Color synchronization types\nexport interface RgbColor {\n\tr: number\n\tg: number\n\tb: number\n}\n\nexport interface ColorData {\n\trgb: RgbColor\n\thex: string\n\tindex: number\n}\n\nexport type Platform = 'darwin' | 'linux' | 'win32' | 'unsupported'\n\n// Validation types\nexport interface ValidationOptions {\n\tdryRun?: boolean\n\tskipTypecheck?: boolean\n\tskipLint?: boolean\n\tskipTests?: boolean\n}\n\nexport interface ValidationStepResult {\n\tstep: 'typecheck' | 'compile' | 'lint' | 'test'\n\tpassed: boolean\n\tskipped: boolean\n\toutput?: string\n\terror?: string\n\tduration?: number\n}\n\nexport interface ValidationResult {\n\tsuccess: boolean\n\tsteps: ValidationStepResult[]\n\ttotalDuration: number\n}\n\n// Commit management types\nexport interface CommitOptions {\n\tdryRun?: boolean\n\tissueNumber?: string | number // For \"Fixes #N\" trailer\n\tmessage?: string // Custom message override\n\tnoReview?: boolean // Skip user review of commit message\n\tskipVerify?: boolean // Skip pre-commit hooks (--no-verify flag)\n}\n\n/**\n * Error thrown when user aborts a commit operation\n * Used by CommitManager when user selects 'abort' at the commit prompt\n */\nexport class UserAbortedCommitError extends Error {\n\tconstructor(message = 'User aborted the commit') {\n\t\tsuper(message)\n\t\tthis.name = 'UserAbortedCommitError'\n\t}\n}\n\n// Merge management types\nexport interface MergeOptions {\n\tdryRun?: boolean // Preview actions without executing\n\tforce?: boolean // Skip confirmation prompts\n\trepoRoot?: string // Repository root path (optional, auto-detected if not provided)\n}\n\nexport interface MergeResult {\n\tsuccess: boolean\n\tbranchName: string\n\tcommitsMerged: number\n\trebaseCompleted: boolean\n\tmergeCompleted: boolean\n}\n\n// Update notification types\nexport interface UpdateCheckCache {\n\tlastCheck: number // Unix timestamp\n\tlatestVersion: string\n}\n\nexport interface UpdateCheckResult {\n\tcurrentVersion: string\n\tlatestVersion: string\n\tupdateAvailable: boolean\n}\n\nexport type InstallationMethod = 'global' | 'local' | 'linked' | 'unknown'\n","import { executeGitCommand } from '../utils/git.js'\nimport { getLogger } from '../utils/logger-context.js'\nimport { launchClaude, detectClaudeCli } from '../utils/claude.js'\nimport { promptCommitAction } from '../utils/prompt.js'\nimport { isRunningInVSCode, isVSCodeAvailable } from '../utils/vscode.js'\nimport { UserAbortedCommitError } from '../types/index.js'\nimport type { GitStatus, CommitOptions } from '../types/index.js'\nimport { writeFile, readFile, unlink } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { execa } from 'execa'\n\n/**\n * CommitManager handles uncommitted changes detection and auto-commit\n * Ports logic from bash/merge-and-clean.sh lines 610-643\n */\nexport class CommitManager {\n constructor() {\n // Uses getLogger() for all logging operations\n }\n\n /**\n * Detect uncommitted changes in a worktree\n * Parses git status --porcelain output into structured GitStatus\n */\n async detectUncommittedChanges(worktreePath: string): Promise<GitStatus> {\n // Execute: git status --porcelain\n const porcelainOutput = await executeGitCommand(['status', '--porcelain'], {\n cwd: worktreePath,\n })\n\n // Parse output to get staged and unstaged files\n const { stagedFiles, unstagedFiles } = this.parseGitStatus(porcelainOutput)\n\n // Get current branch name\n const currentBranch = await executeGitCommand(['branch', '--show-current'], {\n cwd: worktreePath,\n })\n\n return {\n hasUncommittedChanges: stagedFiles.length > 0 || unstagedFiles.length > 0,\n unstagedFiles,\n stagedFiles,\n currentBranch: currentBranch.trim(),\n // Defer these to future enhancement\n isAheadOfRemote: false,\n isBehindRemote: false,\n }\n }\n\n\n /**\n * Stage all changes and commit with Claude-generated or simple message\n * Tries Claude first, falls back to simple message if Claude unavailable or fails\n */\n async commitChanges(worktreePath: string, options: CommitOptions): Promise<void> {\n // Step 1: Check dry-run mode\n if (options.dryRun) {\n getLogger().info('[DRY RUN] Would run: git add -A')\n getLogger().info('[DRY RUN] Would generate commit message with Claude (if available)')\n const fallbackMessage = this.generateFallbackMessage(options)\n const verifyFlag = options.skipVerify ? ' --no-verify' : ''\n getLogger().info(`[DRY RUN] Would commit with message${verifyFlag}: ${fallbackMessage}`)\n return\n }\n\n // Step 2: Stage all changes\n await executeGitCommand(['add', '-A'], { cwd: worktreePath })\n\n // Step 3: Generate commit message (try Claude first, fallback to simple)\n let message: string | null = null\n\n // Skip Claude if custom message provided\n if (!options.message) {\n try {\n message = await this.generateClaudeCommitMessage(worktreePath, options.issueNumber)\n } catch (error) {\n getLogger().debug('Claude commit message generation failed, using fallback', { error })\n }\n }\n\n // Fallback to simple message if Claude failed or unavailable\n message ??= this.generateFallbackMessage(options)\n\n // Step 4: Log warning if --no-verify is configured\n if (options.skipVerify) {\n getLogger().warn('Skipping pre-commit hooks (--no-verify configured in settings)')\n }\n\n // Step 5: Commit with user review via prompt (unless noReview specified)\n try {\n if (options.noReview || options.message) {\n // Direct commit without review (custom message or noReview flag)\n const commitArgs = ['commit', '-m', message]\n if (options.skipVerify) {\n commitArgs.push('--no-verify')\n }\n await executeGitCommand(commitArgs, { cwd: worktreePath })\n } else {\n // Prompt user for action instead of going straight to editor\n const action = await promptCommitAction(message)\n\n if (action === 'abort') {\n throw new UserAbortedCommitError()\n }\n\n if (action === 'accept') {\n // Direct commit with -m flag (no editor)\n const commitArgs = ['commit', '-m', message]\n if (options.skipVerify) {\n commitArgs.push('--no-verify')\n }\n await executeGitCommand(commitArgs, { cwd: worktreePath })\n } else {\n // action === 'edit': Use git editor for user review\n getLogger().info('Opening editor for commit message review...')\n\n // Use VSCode-specific flow when running in VSCode terminal\n // This opens the file in the current VSCode window instead of a random one\n if (isRunningInVSCode() && await isVSCodeAvailable()) {\n await this.commitWithVSCodeEditor(worktreePath, message, options)\n } else {\n // Standard git editor flow for non-VSCode environments\n const commitArgs = ['commit', '-e', '-m', message]\n if (options.skipVerify) {\n commitArgs.push('--no-verify')\n }\n await executeGitCommand(commitArgs, {\n cwd: worktreePath,\n stdio: 'inherit',\n timeout: 300000 // 5 minutes for interactive editing\n })\n }\n }\n }\n } catch (error) {\n // Re-throw UserAbortedCommitError as-is\n if (error instanceof UserAbortedCommitError) {\n throw error\n }\n // Handle \"nothing to commit\" scenario gracefully\n if (error instanceof Error && error.message.includes('nothing to commit')) {\n getLogger().info('No changes to commit')\n return\n }\n // Re-throw all other errors (including pre-commit hook failures)\n throw error\n }\n }\n\n\n /**\n * Commit with VSCode editor - handles file creation, editing, and commit ourselves\n * to ensure the file opens in the current VSCode window (preserves IPC context)\n */\n private async commitWithVSCodeEditor(\n worktreePath: string,\n message: string,\n options: CommitOptions\n ): Promise<void> {\n // Put the commit message file in the worktree root so VSCode opens it in the correct\n // window (files within a workspace folder open in that workspace's window)\n const commitMsgPath = join(worktreePath, '.COMMIT_EDITMSG')\n\n // Write the initial commit message (with git-style comments)\n const initialContent = `${message}\n\n# Please enter the commit message for your changes. Lines starting\n# with '#' will be ignored, and an empty message aborts the commit.\n#\n# Save and close the file to complete the commit.\n`\n await writeFile(commitMsgPath, initialContent, 'utf-8')\n\n try {\n getLogger().debug(`Opening commit message in VSCode: ${commitMsgPath}`)\n\n // Open the file - since it's in the worktree root, VSCode will open it\n // in the window that has this folder open\n await execa('code', ['--wait', commitMsgPath], {\n cwd: worktreePath,\n stdio: 'inherit'\n })\n\n // Read the edited message\n const editedContent = await readFile(commitMsgPath, 'utf-8')\n\n // Strip comment lines and trim\n const finalMessage = editedContent\n .split('\\n')\n .filter(line => !line.startsWith('#'))\n .join('\\n')\n .trim()\n\n // Check for empty message (user aborted)\n if (!finalMessage) {\n throw new UserAbortedCommitError()\n }\n\n // Commit with the edited message\n const commitArgs = ['commit', '-F', commitMsgPath]\n if (options.skipVerify) {\n commitArgs.push('--no-verify')\n }\n\n // Rewrite the file without comments for git commit -F\n await writeFile(commitMsgPath, finalMessage, 'utf-8')\n await executeGitCommand(commitArgs, { cwd: worktreePath })\n\n } finally {\n // Clean up - git normally handles this but we should be safe\n try {\n await unlink(commitMsgPath)\n } catch {\n // Ignore cleanup errors\n }\n }\n }\n\n /**\n * Generate simple fallback commit message when Claude unavailable\n * Used as fallback for Claude-powered commit messages\n */\n private generateFallbackMessage(options: CommitOptions): string {\n // If custom message provided, use it\n if (options.message) {\n return options.message\n }\n\n // Generate WIP message\n if (options.issueNumber) {\n return `WIP: Auto-commit for issue #${options.issueNumber}\\n\\nFixes #${options.issueNumber}`\n } else {\n return 'WIP: Auto-commit uncommitted changes'\n }\n }\n\n /**\n * Parse git status --porcelain output\n * Format: \"XY filename\" where X=index, Y=worktree\n * Examples:\n * \"M file.ts\" - staged modification\n * \" M file.ts\" - unstaged modification\n * \"MM file.ts\" - both staged and unstaged\n * \"?? file.ts\" - untracked\n */\n private parseGitStatus(porcelainOutput: string): {\n stagedFiles: string[]\n unstagedFiles: string[]\n } {\n const stagedFiles: string[] = []\n const unstagedFiles: string[] = []\n\n if (!porcelainOutput.trim()) {\n return { stagedFiles, unstagedFiles }\n }\n\n const lines = porcelainOutput.split('\\n').filter((line) => line.trim())\n\n for (const line of lines) {\n if (line.length < 3) continue\n\n const indexStatus = line[0] // First character - staging area status\n const worktreeStatus = line[1] // Second character - working tree status\n const filename = line.substring(3) // Everything after \"XY \"\n\n // Check if file is staged\n // First char != ' ' and != '?' → staged\n if (indexStatus !== ' ' && indexStatus !== '?') {\n stagedFiles.push(filename)\n }\n\n // Check if file is unstaged\n // Second char != ' ' or line starts with '??' → unstaged\n if (worktreeStatus !== ' ' || line.startsWith('??')) {\n unstagedFiles.push(filename)\n }\n }\n\n return { stagedFiles, unstagedFiles }\n }\n\n /**\n * Generate commit message using Claude Code\n * Claude examines the git repository directly via --add-dir option\n * Returns null if Claude unavailable or fails validation\n */\n private async generateClaudeCommitMessage(\n worktreePath: string,\n issueNumber?: string | number\n ): Promise<string | null> {\n const startTime = Date.now()\n\n getLogger().info('Starting Claude commit message generation...', {\n worktreePath: worktreePath.split('/').pop(), // Just show the folder name for privacy\n issueNumber\n })\n\n // Check if Claude CLI is available\n getLogger().debug('Checking Claude CLI availability...')\n const isClaudeAvailable = await detectClaudeCli()\n if (!isClaudeAvailable) {\n getLogger().info('Claude CLI not available, skipping Claude commit message generation')\n return null\n }\n getLogger().debug('Claude CLI is available')\n\n // Build XML-based structured prompt\n getLogger().debug('Building commit message prompt...')\n const prompt = this.buildCommitMessagePrompt(issueNumber)\n getLogger().debug('Prompt built', { promptLength: prompt.length })\n\n // Debug log the actual prompt content for troubleshooting\n getLogger().debug('Claude prompt content:', {\n prompt: prompt,\n truncatedPreview: prompt.substring(0, 500) + (prompt.length > 500 ? '...[truncated]' : '')\n })\n\n try {\n getLogger().info('Calling Claude CLI for commit message generation...')\n const claudeStartTime = Date.now()\n\n // Debug log the Claude call parameters\n const claudeOptions = {\n headless: true,\n addDir: worktreePath,\n model: 'claude-haiku-4-5-20251001', // Fast, cost-effective model\n timeout: 120000, // 120 second timeout\n appendSystemPrompt: 'Output only the requested content. Never include preamble, analysis, or meta-commentary. Your response is used verbatim.',\n }\n getLogger().debug('Claude CLI call parameters:', {\n options: claudeOptions,\n worktreePathForAnalysis: worktreePath,\n addDirContents: 'Will include entire worktree directory for analysis'\n })\n\n // Launch Claude in headless mode with repository access and shorter timeout for commit messages\n const result = await launchClaude(prompt, claudeOptions)\n\n const claudeDuration = Date.now() - claudeStartTime\n getLogger().debug('Claude API call completed', { duration: `${claudeDuration}ms` })\n\n if (typeof result !== 'string') {\n getLogger().warn('Claude returned non-string result', { resultType: typeof result })\n return null\n }\n\n getLogger().debug('Raw Claude output received', {\n outputLength: result.length,\n preview: result.substring(0, 200) + (result.length > 200 ? '...' : '')\n })\n\n\n // Sanitize output - remove meta-commentary and clean formatting\n getLogger().debug('Sanitizing Claude output...')\n const sanitized = this.sanitizeClaudeOutput(result)\n getLogger().debug('Output sanitized', {\n originalLength: result.length,\n sanitizedLength: sanitized.length,\n sanitized: sanitized.substring(0, 200) + (sanitized.length > 200 ? '...' : '')\n })\n\n // Ensure empty strings are rejected\n if (!sanitized) {\n getLogger().warn('Claude returned empty message after sanitization')\n return null\n }\n\n // Append \"Fixes #N\" trailer if issue number provided\n let finalMessage = sanitized\n if (issueNumber) {\n // Add Fixes trailer if not already present\n if (!finalMessage.includes(`Fixes #${issueNumber}`)) {\n finalMessage = `${finalMessage}\\n\\nFixes #${issueNumber}`\n getLogger().debug(`Added \"Fixes #${issueNumber}\" trailer to commit message`)\n } else {\n getLogger().debug(`\"Fixes #${issueNumber}\" already present in commit message`)\n }\n }\n\n const totalDuration = Date.now() - startTime\n getLogger().info('Claude commit message generated successfully', {\n message: finalMessage,\n totalDuration: `${totalDuration}ms`,\n claudeApiDuration: `${claudeDuration}ms`\n })\n\n return finalMessage\n } catch (error) {\n const totalDuration = Date.now() - startTime\n const errorMessage = error instanceof Error ? error.message : 'Unknown error'\n\n if (errorMessage.includes('timed out') || errorMessage.includes('timeout')) {\n getLogger().warn('Claude commit message generation timed out after 45 seconds', {\n totalDuration: `${totalDuration}ms`,\n worktreePath: worktreePath.split('/').pop()\n })\n } else {\n getLogger().warn('Failed to generate commit message with Claude', {\n error: errorMessage,\n totalDuration: `${totalDuration}ms`,\n worktreePath: worktreePath.split('/').pop()\n })\n }\n return null\n }\n }\n\n /**\n * Build structured XML prompt for commit message generation\n * Uses XML format for clear task definition and output expectations\n */\n private buildCommitMessagePrompt(issueNumber?: string | number): string {\n const issueContext = issueNumber\n ? `\\n<IssueContext>\nThis commit is associated with GitHub issue #${issueNumber}.\nIf the changes appear to resolve the issue, include \"Fixes #${issueNumber}\" at the end of the first line of commit message.\n</IssueContext>`\n : ''\n\n return `<Task>\nYou are a software engineer writing a commit message for this repository.\nExamine the staged changes in the git repository and generate a concise, meaningful commit message.\n</Task>\n\n<Requirements>\n<Format>The first line must be a brief summary of the changes made as a full sentence. If it references an issue, include \"Fixes #N\" at the end of this line.\n\nAdd 2 newlines, then add a bullet-point form description of the changes made, each change on a new line.</Format>\n<Mood>Use imperative mood (e.g., \"Add feature\" not \"Added feature\")</Mood>\n<Focus>Be specific about what was changed and why</Focus>\n<Conciseness>Keep message under 72 characters for subject line when possible</Conciseness>\n<NoMeta>CRITICAL: Do NOT include ANY explanatory text, analysis, or meta-commentary. Output ONLY the raw commit message.</NoMeta>\n<Examples>\nGood: \"Add user authentication with JWT tokens. Fixes #42\n\n- Implement login and registration endpoints\n- Secure routes with JWT middleware\n- Update user model to store hashed passwords\"\nGood: \"Fix navigation bug in sidebar menu.\"\nBad: \"Based on the changes, I'll create: Add user authentication\"\nBad: \"Looking at the files, this commit should be: Fix navigation bug\"\n</Examples>\n${issueContext}\n</Requirements>\n\n<Output>\nIMPORTANT: Your entire response will be used directly as the git commit message.\nDo not include any explanatory text before or after the commit message.\nStart your response immediately with the commit message text.\n</Output>`\n }\n\n /**\n * Sanitize Claude output to remove meta-commentary and clean formatting\n * Handles cases where Claude includes explanatory text despite instructions\n */\n private sanitizeClaudeOutput(rawOutput: string): string {\n let cleaned = rawOutput.trim()\n\n // Remove common meta-commentary patterns (case-insensitive)\n const metaPatterns = [\n /^.*?based on.*?changes.*?:/i,\n /^.*?looking at.*?files.*?:/i,\n /^.*?examining.*?:/i,\n /^.*?analyzing.*?:/i,\n /^.*?i'll.*?generate.*?:/i,\n /^.*?let me.*?:/i,\n /^.*?the commit message.*?should be.*?:/i,\n /^.*?here.*?is.*?commit.*?message.*?:/i,\n ]\n\n for (const pattern of metaPatterns) {\n cleaned = cleaned.replace(pattern, '').trim()\n }\n\n // Extract content after separators only if it looks like meta-commentary\n // Only split on colons if there's clear meta-commentary before it\n if (cleaned.includes(':')) {\n const colonIndex = cleaned.indexOf(':')\n const beforeColon = cleaned.substring(0, colonIndex).trim().toLowerCase()\n\n // Only split if the text before colon looks like meta-commentary\n const metaIndicators = [\n 'here is the commit message',\n 'commit message',\n 'here is',\n 'the message should be',\n 'i suggest',\n 'my suggestion'\n ]\n\n const isMetaCommentary = metaIndicators.some(indicator => beforeColon.includes(indicator))\n\n if (isMetaCommentary) {\n const afterColon = cleaned.substring(colonIndex + 1).trim()\n if (afterColon && afterColon.length > 10) {\n cleaned = afterColon\n }\n }\n }\n\n // Remove quotes if the entire message is wrapped in them\n if ((cleaned.startsWith('\"') && cleaned.endsWith('\"')) ||\n (cleaned.startsWith(\"'\") && cleaned.endsWith(\"'\"))) {\n cleaned = cleaned.slice(1, -1).trim()\n }\n\n return cleaned\n }\n\n\n}\n","import { getLogger } from '../utils/logger-context.js'\nimport { detectPackageManager, runScript } from '../utils/package-manager.js'\nimport { readPackageJson, hasScript } from '../utils/package-json.js'\nimport { ProjectCapabilityDetector } from './ProjectCapabilityDetector.js'\n\nexport interface BuildOptions {\n\tdryRun?: boolean\n}\n\nexport interface BuildResult {\n\tsuccess: boolean\n\tskipped: boolean\n\treason?: string\n\tduration: number\n}\n\n/**\n * BuildRunner handles post-merge build verification for CLI projects\n * Only runs build when project has CLI capabilities (bin field in package.json)\n */\nexport class BuildRunner {\n\tprivate capabilityDetector: ProjectCapabilityDetector\n\n\tconstructor(capabilityDetector?: ProjectCapabilityDetector) {\n\t\tthis.capabilityDetector = capabilityDetector ?? new ProjectCapabilityDetector()\n\t}\n\n\t/**\n\t * Run build verification in the specified directory\n\t * @param buildPath - Path where build should run (typically main worktree path)\n\t * @param options - Build options\n\t */\n\tasync runBuild(buildPath: string, options: BuildOptions = {}): Promise<BuildResult> {\n\t\tconst startTime = Date.now()\n\n\t\ttry {\n\t\t\t// Step 1: Check if build script exists\n\t\t\tconst pkgJson = await readPackageJson(buildPath)\n\t\t\tconst hasBuildScript = hasScript(pkgJson, 'build')\n\n\t\t\tif (!hasBuildScript) {\n\t\t\tgetLogger().debug('Skipping build - no build script found')\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tskipped: true,\n\t\t\t\t\treason: 'No build script found in package.json',\n\t\t\t\t\tduration: Date.now() - startTime,\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Handle missing package.json - skip build for non-Node.js projects\n\t\t\tif (error instanceof Error && error.message.includes('package.json not found')) {\n\t\t\tgetLogger().debug('Skipping build - no package.json found (non-Node.js project)')\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tskipped: true,\n\t\t\t\t\treason: 'No package.json found in project',\n\t\t\t\t\tduration: Date.now() - startTime,\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Re-throw other errors\n\t\t\tthrow error\n\t\t}\n\n\t\t// Step 2: Check if project has CLI capability (bin field)\n\t\tconst capabilities = await this.capabilityDetector.detectCapabilities(buildPath)\n\t\tconst isCLIProject = capabilities.capabilities.includes('cli')\n\n\t\tif (!isCLIProject) {\n\t\tgetLogger().debug('Skipping build - not a CLI project (no bin field)')\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tskipped: true,\n\t\t\t\treason: 'Project is not a CLI project (no bin field in package.json)',\n\t\t\t\tduration: Date.now() - startTime,\n\t\t\t}\n\t\t}\n\n\t\t// Step 3: Detect package manager\n\t\tconst packageManager = await detectPackageManager(buildPath)\n\n\t\t// Step 4: Handle dry-run mode\n\t\tif (options.dryRun) {\n\t\t\tconst command =\n\t\t\t\tpackageManager === 'npm' ? 'npm run build' : `${packageManager} build`\n\t\tgetLogger().info(`[DRY RUN] Would run: ${command}`)\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tskipped: false,\n\t\t\t\tduration: Date.now() - startTime,\n\t\t\t}\n\t\t}\n\n\t\t// Step 5: Execute build\n\tgetLogger().info('Running build...')\n\n\t\ttry {\n\t\t\tawait runScript('build', buildPath, [], { quiet: true })\n\t\tgetLogger().success('Build completed successfully')\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tskipped: false,\n\t\t\t\tduration: Date.now() - startTime,\n\t\t\t}\n\t\t} catch {\n\t\t\t// Step 6: Throw detailed error on failure\n\t\t\tconst runCommand =\n\t\t\t\tpackageManager === 'npm' ? 'npm run build' : `${packageManager} build`\n\n\t\t\tthrow new Error(\n\t\t\t\t`Error: Build failed.\\n` +\n\t\t\t\t\t`Fix build errors before proceeding.\\n\\n` +\n\t\t\t\t\t`Run '${runCommand}' to see detailed errors.`\n\t\t\t)\n\t\t}\n\t}\n}\n","import { executeGhCommand } from '../utils/github.js'\nimport { launchClaude, detectClaudeCli } from '../utils/claude.js'\nimport { getEffectivePRTargetRemote, getConfiguredRepoFromSettings, parseGitRemotes } from '../utils/remote.js'\nimport { openBrowser } from '../utils/browser.js'\nimport { getLogger } from '../utils/logger-context.js'\nimport type { IloomSettings } from './SettingsManager.js'\n\ninterface ExistingPR {\n\tnumber: number\n\turl: string\n}\n\ninterface PRCreationResult {\n\turl: string\n\tnumber: number\n\twasExisting: boolean\n}\n\nexport class PRManager {\n\tconstructor(private settings: IloomSettings) {\n\t\t// Uses getLogger() for all logging operations\n\t}\n\n\t/**\n\t * Check if a PR already exists for the given branch\n\t * @param branchName - Branch to check\n\t * @param cwd - Working directory\n\t * @returns Existing PR info or null if none found\n\t */\n\tasync checkForExistingPR(branchName: string, cwd?: string): Promise<ExistingPR | null> {\n\t\ttry {\n\t\t\tconst prList = await executeGhCommand<Array<{ number: number; url: string }>>(\n\t\t\t\t['pr', 'list', '--head', branchName, '--state', 'open', '--json', 'number,url'],\n\t\t\t\tcwd ? { cwd } : undefined\n\t\t\t)\n\n\t\t\tif (prList.length > 0) {\n\t\t\t\treturn prList[0] ?? null // Return first match\n\t\t\t}\n\n\t\t\treturn null\n\t\t} catch (error) {\n\t\tgetLogger().debug('Error checking for existing PR', { error })\n\t\t\treturn null\n\t\t}\n\t}\n\n\t/**\n\t * Generate PR body using Claude if available, otherwise use simple template\n\t * @param issueNumber - Issue number to include in body\n\t * @param worktreePath - Path to worktree for context\n\t * @returns PR body markdown\n\t */\n\tasync generatePRBody(issueNumber: string | number | undefined, worktreePath: string): Promise<string> {\n\t\t// Try Claude first for rich body generation\n\t\tconst hasClaudeCli = await detectClaudeCli()\n\n\t\tif (hasClaudeCli) {\n\t\t\ttry {\n\t\t\t\tconst prompt = this.buildPRBodyPrompt(issueNumber)\n\n\t\t\t\tconst body = await launchClaude(prompt, {\n\t\t\t\t\theadless: true,\n\t\t\t\t\taddDir: worktreePath,\n\t\t\t\t\ttimeout: 30000,\n\t\t\t\t})\n\n\t\t\t\tif (body && typeof body === 'string' && body.trim()) {\n\t\t\t\t\tconst sanitized = this.sanitizeClaudeOutput(body)\n\t\t\t\t\tif (sanitized) {\n\t\t\t\t\t\treturn sanitized\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\tgetLogger().debug('Claude PR body generation failed, using template', { error })\n\t\t\t}\n\t\t}\n\n\t\t// Fallback to simple template\n\t\tlet body = 'This PR contains changes from the iloom workflow.\\n\\n'\n\n\t\tif (issueNumber) {\n\t\t\tbody += `Fixes #${issueNumber}`\n\t\t}\n\n\t\treturn body\n\t}\n\n\t/**\n\t * Build structured XML prompt for PR body generation\n\t * Uses XML format for clear task definition and output expectations\n\t */\n\tprivate buildPRBodyPrompt(issueNumber?: string | number): string {\n\t\tconst issueContext = issueNumber\n\t\t\t? `\\n<IssueContext>\nThis PR is associated with GitHub issue #${issueNumber}.\nInclude \"Fixes #${issueNumber}\" at the end of the body on its own line.\n</IssueContext>`\n\t\t\t: ''\n\n\t\treturn `<Task>\nYou are a software engineer writing a pull request body for this repository.\nExamine the changes in the git repository and generate a concise, professional PR description.\n</Task>\n\n<Requirements>\n<Format>Write 2-3 sentences summarizing what was changed and why.${issueNumber ? `\\n\\nEnd with \"Fixes #${issueNumber}\" on its own line.` : ''}</Format>\n<Tone>Professional and concise</Tone>\n<Focus>Summarize the changes and their purpose</Focus>\n<NoMeta>CRITICAL: Do NOT include ANY explanatory text, analysis, or meta-commentary. Output ONLY the raw PR body text.</NoMeta>\n<Examples>\nGood: \"Add user authentication with JWT tokens to secure the API endpoints. This includes login and registration endpoints with proper password hashing.\n\nFixes #42\"\nGood: \"Fix navigation bug in sidebar menu that caused incorrect highlighting on nested routes.\"\nBad: \"Here's the PR body:\\n\\n---\\n\\nAdd user authentication...\"\nBad: \"Based on the changes, I'll write: Fix navigation bug...\"\n</Examples>\n${issueContext}\n</Requirements>\n\n<Output>\nIMPORTANT: Your entire response will be used directly as the GitHub pull request body.\nDo not include any explanatory text, headers, or separators before or after the body.\nStart your response immediately with the PR body text.\n</Output>`\n\t}\n\n\t/**\n\t * Sanitize Claude output to remove meta-commentary and clean formatting\n\t * Handles cases where Claude includes explanatory text despite instructions\n\t */\n\tprivate sanitizeClaudeOutput(rawOutput: string): string {\n\t\tlet cleaned = rawOutput.trim()\n\n\t\t// Remove common meta-commentary patterns (case-insensitive)\n\t\tconst metaPatterns = [\n\t\t\t/^.*?based on.*?changes.*?:/i,\n\t\t\t/^.*?looking at.*?files.*?:/i,\n\t\t\t/^.*?examining.*?:/i,\n\t\t\t/^.*?analyzing.*?:/i,\n\t\t\t/^.*?i'll.*?generate.*?:/i,\n\t\t\t/^.*?let me.*?:/i,\n\t\t\t/^.*?here.*?is.*?(?:the\\s+)?(?:pr|pull request).*?body.*?:/i,\n\t\t\t/^.*?here's.*?(?:the\\s+)?(?:pr|pull request).*?body.*?:/i,\n\t\t]\n\n\t\tfor (const pattern of metaPatterns) {\n\t\t\tcleaned = cleaned.replace(pattern, '').trim()\n\t\t}\n\n\t\t// Remove leading separator lines (---, ===, etc.)\n\t\tcleaned = cleaned.replace(/^[-=]{3,}\\s*/m, '').trim()\n\n\t\t// Extract content after separators only if it looks like meta-commentary\n\t\tif (cleaned.includes(':')) {\n\t\t\tconst colonIndex = cleaned.indexOf(':')\n\t\t\tconst beforeColon = cleaned.substring(0, colonIndex).trim().toLowerCase()\n\n\t\t\t// Only split if the text before colon looks like meta-commentary\n\t\t\tconst metaIndicators = [\n\t\t\t\t'here is the pr body',\n\t\t\t\t'here is the pull request body',\n\t\t\t\t'pr body',\n\t\t\t\t'pull request body',\n\t\t\t\t'here is',\n\t\t\t\t\"here's\",\n\t\t\t\t'the body should be',\n\t\t\t\t'i suggest',\n\t\t\t\t'my suggestion'\n\t\t\t]\n\n\t\t\tconst isMetaCommentary = metaIndicators.some(indicator => beforeColon.includes(indicator))\n\n\t\t\tif (isMetaCommentary) {\n\t\t\t\tconst afterColon = cleaned.substring(colonIndex + 1).trim()\n\t\t\t\t// Remove leading separator after colon\n\t\t\t\tconst afterSeparator = afterColon.replace(/^[-=]{3,}\\s*/m, '').trim()\n\t\t\t\tif (afterSeparator && afterSeparator.length > 10) {\n\t\t\t\t\tcleaned = afterSeparator\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Remove quotes if the entire message is wrapped in them\n\t\tif ((cleaned.startsWith('\"') && cleaned.endsWith('\"')) ||\n\t\t\t(cleaned.startsWith(\"'\") && cleaned.endsWith(\"'\"))) {\n\t\t\tcleaned = cleaned.slice(1, -1).trim()\n\t\t}\n\n\t\treturn cleaned\n\t}\n\n\t/**\n\t * Create a GitHub PR for the branch\n\t * @param branchName - Branch to create PR from (used as --head)\n\t * @param title - PR title\n\t * @param body - PR body\n\t * @param baseBranch - Base branch to target (usually main/master)\n\t * @param cwd - Working directory\n\t * @returns PR URL\n\t */\n\tasync createPR(\n\t\tbranchName: string,\n\t\ttitle: string,\n\t\tbody: string,\n\t\tbaseBranch: string,\n\t\tcwd?: string\n\t): Promise<string> {\n\t\ttry {\n\t\t\t// Get the target remote for the PR\n\t\t\tconst targetRemote = await getEffectivePRTargetRemote(this.settings, cwd)\n\n\t\t\t// Determine the correct --head value\n\t\t\t// For fork workflows (target != origin), we need \"username:branch\" format\n\t\t\t// See: https://github.com/cli/cli/issues/2691\n\t\t\tlet headValue = branchName\n\n\t\t\tif (targetRemote !== 'origin') {\n\t\t\t\t// Fork workflow: need to specify the head as \"owner:branch\"\n\t\t\t\t// Get the owner of the origin remote (where we pushed the branch)\n\t\t\t\tconst remotes = await parseGitRemotes(cwd)\n\t\t\t\tconst originRemote = remotes.find(r => r.name === 'origin')\n\n\t\t\t\tif (originRemote) {\n\t\t\t\t\theadValue = `${originRemote.owner}:${branchName}`\n\t\t\t\tgetLogger().debug(`Fork workflow detected, using head: ${headValue}`)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Build gh pr create command\n\t\t\t// Note: gh pr create returns a plain URL string, not JSON\n\t\t\tconst args = ['pr', 'create', '--head', headValue, '--title', title, '--body', body, '--base', baseBranch]\n\n\t\t\t// If target remote is not 'origin', we need to specify the repo\n\t\t\tif (targetRemote !== 'origin') {\n\t\t\t\tconst repo = await getConfiguredRepoFromSettings(this.settings, cwd)\n\t\t\t\targs.push('--repo', repo)\n\t\t\t}\n\n\t\t\t// gh pr create returns the PR URL as plain text (not JSON)\n\t\t\tconst result = await executeGhCommand<string>(args, cwd ? { cwd } : undefined)\n\n\t\t\t// Result is a string URL like \"https://github.com/owner/repo/pull/123\"\n\t\t\tconst url = typeof result === 'string' ? result.trim() : String(result).trim()\n\n\t\t\tif (!url.includes('github.com') || !url.includes('/pull/')) {\n\t\t\t\tthrow new Error(`Unexpected response from gh pr create: ${url}`)\n\t\t\t}\n\n\t\t\treturn url\n\t\t} catch (error) {\n\t\t\tconst errorMessage = error instanceof Error ? error.message : String(error)\n\n\t\t\t// Provide helpful error message for common GraphQL errors\n\t\t\tif (errorMessage.includes(\"Head sha can't be blank\") || errorMessage.includes(\"No commits between\")) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Failed to create pull request: ${errorMessage}\\n\\n` +\n\t\t\t\t\t`This error typically occurs when:\\n` +\n\t\t\t\t\t` - The branch was not fully pushed to the remote\\n` +\n\t\t\t\t\t` - There's a race condition between push and PR creation\\n` +\n\t\t\t\t\t` - The branch has no commits ahead of the base branch\\n\\n` +\n\t\t\t\t\t`Try running: git push -u origin ${branchName}\\n` +\n\t\t\t\t\t`Then retry: il finish`\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tthrow new Error(`Failed to create pull request: ${errorMessage}`)\n\t\t}\n\t}\n\n\t/**\n\t * Open PR URL in browser\n\t * @param url - PR URL to open\n\t */\n\tasync openPRInBrowser(url: string): Promise<void> {\n\t\ttry {\n\t\t\tawait openBrowser(url)\n\t\tgetLogger().debug('Opened PR in browser', { url })\n\t\t} catch (error) {\n\t\t\t// Don't fail the whole operation if browser opening fails\n\t\tgetLogger().warn('Failed to open PR in browser', { error })\n\t\t}\n\t}\n\n\t/**\n\t * Complete PR workflow: check for existing, create if needed, optionally open in browser\n\t * @param branchName - Branch to create PR from\n\t * @param title - PR title\n\t * @param issueNumber - Optional issue number for body generation\n\t * @param baseBranch - Base branch to target\n\t * @param worktreePath - Path to worktree\n\t * @param openInBrowser - Whether to open PR in browser\n\t * @returns PR creation result\n\t */\n\tasync createOrOpenPR(\n\t\tbranchName: string,\n\t\ttitle: string,\n\t\tissueNumber: string | number | undefined,\n\t\tbaseBranch: string,\n\t\tworktreePath: string,\n\t\topenInBrowser: boolean\n\t): Promise<PRCreationResult> {\n\t\t// Check for existing PR\n\t\tconst existingPR = await this.checkForExistingPR(branchName, worktreePath)\n\n\t\tif (existingPR) {\n\t\tgetLogger().info(`Pull request already exists: ${existingPR.url}`)\n\n\t\t\tif (openInBrowser) {\n\t\t\t\tawait this.openPRInBrowser(existingPR.url)\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\turl: existingPR.url,\n\t\t\t\tnumber: existingPR.number,\n\t\t\t\twasExisting: true,\n\t\t\t}\n\t\t}\n\n\t\t// Generate PR body\n\t\tconst body = await this.generatePRBody(issueNumber, worktreePath)\n\n\t\t// Create new PR\n\tgetLogger().info('Creating pull request...')\n\t\tconst url = await this.createPR(branchName, title, body, baseBranch, worktreePath)\n\n\t\t// Extract PR number from URL\n\t\tconst prNumber = this.extractPRNumberFromUrl(url)\n\n\t\tif (openInBrowser) {\n\t\t\tawait this.openPRInBrowser(url)\n\t\t}\n\n\t\treturn {\n\t\t\turl,\n\t\t\tnumber: prNumber,\n\t\t\twasExisting: false,\n\t\t}\n\t}\n\n\t/**\n\t * Extract PR number from GitHub PR URL\n\t * @param url - PR URL (e.g., https://github.com/owner/repo/pull/123)\n\t * @returns PR number\n\t */\n\tprivate extractPRNumberFromUrl(url: string): number {\n\t\tconst match = url.match(/\\/pull\\/(\\d+)/)\n\t\tif (match?.[1]) {\n\t\t\treturn parseInt(match[1], 10)\n\t\t}\n\t\tthrow new Error(`Could not extract PR number from URL: ${url}`)\n\t}\n}\n","import { getLogger } from '../utils/logger-context.js'\nimport type { IssueTracker } from '../lib/IssueTracker.js'\nimport { GitWorktreeManager } from '../lib/GitWorktreeManager.js'\nimport { ValidationRunner } from '../lib/ValidationRunner.js'\nimport { CommitManager } from '../lib/CommitManager.js'\nimport { MergeManager } from '../lib/MergeManager.js'\nimport { IdentifierParser } from '../utils/IdentifierParser.js'\nimport { ResourceCleanup } from '../lib/ResourceCleanup.js'\nimport { ProcessManager } from '../lib/process/ProcessManager.js'\nimport { BuildRunner } from '../lib/BuildRunner.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 { PRManager } from '../lib/PRManager.js'\nimport { LoomManager } from '../lib/LoomManager.js'\nimport { ClaudeContextManager } from '../lib/ClaudeContextManager.js'\nimport { ProjectCapabilityDetector } from '../lib/ProjectCapabilityDetector.js'\nimport { SessionSummaryService } from '../lib/SessionSummaryService.js'\nimport { findMainWorktreePathWithSettings, pushBranchToRemote, extractIssueNumber } from '../utils/git.js'\nimport { loadEnvIntoProcess } from '../utils/env.js'\nimport { installDependencies } from '../utils/package-manager.js'\nimport { createNeonProviderFromSettings } from '../utils/neon-helpers.js'\nimport { getConfiguredRepoFromSettings, hasMultipleRemotes } from '../utils/remote.js'\nimport { promptConfirmation } from '../utils/prompt.js'\nimport { UserAbortedCommitError, type FinishResult } from '../types/index.js'\nimport type { FinishOptions, GitWorktree, CommitOptions, MergeOptions, PullRequest } from '../types/index.js'\nimport type { ResourceCleanupOptions, CleanupResult } from '../types/cleanup.js'\nimport type { ParsedInput } from './start.js'\nimport path from 'path'\n\nexport interface FinishCommandInput {\n\tidentifier?: string | undefined // Optional - can be auto-detected\n\toptions: FinishOptions\n}\n\nexport interface ParsedFinishInput {\n\ttype: 'issue' | 'pr' | 'branch'\n\tnumber?: string | number // For issues and PRs\n\tbranchName?: string // For branch inputs\n\toriginalInput: string // Raw input for error messages\n\tautoDetected?: boolean // True if detected from current directory\n}\n\nexport class FinishCommand {\n\tprivate issueTracker: IssueTracker\n\tprivate gitWorktreeManager: GitWorktreeManager\n\tprivate validationRunner: ValidationRunner\n\tprivate commitManager: CommitManager\n\tprivate mergeManager: MergeManager\n\tprivate identifierParser: IdentifierParser\n\tprivate resourceCleanup?: ResourceCleanup\n\tprivate buildRunner: BuildRunner\n\tprivate settingsManager: SettingsManager\n\tprivate loomManager?: LoomManager\n\tprivate sessionSummaryService?: SessionSummaryService\n\n\tconstructor(\n\t\tissueTracker: IssueTracker,\n\t\tgitWorktreeManager?: GitWorktreeManager,\n\t\tvalidationRunner?: ValidationRunner,\n\t\tcommitManager?: CommitManager,\n\t\tmergeManager?: MergeManager,\n\t\tidentifierParser?: IdentifierParser,\n\t\tresourceCleanup?: ResourceCleanup,\n\t\tbuildRunner?: BuildRunner,\n\t\tsettingsManager?: SettingsManager,\n\t\tloomManager?: LoomManager\n\t) {\n\t\t// Load environment variables first\n\t\tconst envResult = loadEnvIntoProcess()\n\t\tif (envResult.error) {\n\t\t\tgetLogger().debug(`Environment loading warning: ${envResult.error.message}`)\n\t\t}\n\t\tif (envResult.parsed) {\n\t\t\tgetLogger().debug(`Loaded ${Object.keys(envResult.parsed).length} environment variables`)\n\t\t}\n\n\t\tthis.issueTracker = issueTracker\n\t\tthis.gitWorktreeManager = gitWorktreeManager ?? new GitWorktreeManager()\n\t\tthis.validationRunner = validationRunner ?? new ValidationRunner()\n\t\tthis.commitManager = commitManager ?? new CommitManager()\n\t\tthis.mergeManager = mergeManager ?? new MergeManager()\n\t\tthis.identifierParser = identifierParser ?? new IdentifierParser(this.gitWorktreeManager)\n\n\t\t// Initialize settingsManager first (needed for ResourceCleanup)\n\t\tthis.settingsManager = settingsManager ?? new SettingsManager()\n\n\t\t// ResourceCleanup will be initialized lazily with proper configuration\n\t\tif (resourceCleanup) {\n\t\t\tthis.resourceCleanup = resourceCleanup\n\t\t}\n\n\t\tthis.buildRunner = buildRunner ?? new BuildRunner()\n\t\t// LoomManager will be initialized lazily if not provided\n\t\tif (loomManager) {\n\t\t\tthis.loomManager = loomManager\n\t\t}\n\t}\n\n\t/**\n\t * Lazy initialization of ResourceCleanup with properly configured DatabaseManager\n\t */\n\tprivate async ensureResourceCleanup(): Promise<void> {\n\t\t// Early return only if both are initialized\n\t\tif (this.resourceCleanup && this.loomManager) {\n\t\t\treturn\n\t\t}\n\n\t\tconst settings = await this.settingsManager.loadSettings()\n\t\tconst databaseUrlEnvVarName = settings.capabilities?.database?.databaseUrlEnvVarName ?? 'DATABASE_URL'\n\n\t\tconst environmentManager = new EnvironmentManager()\n\t\tconst neonProvider = createNeonProviderFromSettings(settings)\n\t\tconst databaseManager = new DatabaseManager(neonProvider, environmentManager, databaseUrlEnvVarName)\n\t\tconst cliIsolationManager = new CLIIsolationManager()\n\n\t\t// Initialize LoomManager if not provided\n\t\tconst { DefaultBranchNamingService } = await import('../lib/BranchNamingService.js')\n\t\tthis.loomManager ??= new LoomManager(\n\t\t\tthis.gitWorktreeManager,\n\t\t\tthis.issueTracker,\n\t\t\tnew DefaultBranchNamingService({ useClaude: true }),\n\t\t\tenvironmentManager,\n\t\t\tnew ClaudeContextManager(),\n\t\t\tnew ProjectCapabilityDetector(),\n\t\t\tcliIsolationManager,\n\t\t\tthis.settingsManager,\n\t\t\tdatabaseManager\n\t\t)\n\n\t\tthis.resourceCleanup ??= new ResourceCleanup(\n\t\t\tthis.gitWorktreeManager,\n\t\t\tnew ProcessManager(),\n\t\t\tdatabaseManager,\n\t\t\tcliIsolationManager\n\t\t)\n\t}\n\n\t/**\n\t * Check for child looms and exit gracefully if any exist\n\t * Always checks the TARGET loom (the one being finished), not the current directory's loom\n\t *\n\t * @param parsed - The parsed input identifying the loom being finished\n\t */\n\tprivate async checkForChildLooms(parsed: ParsedFinishInput): Promise<void> {\n\t\tawait this.ensureResourceCleanup()\n\t\tif (!this.loomManager) {\n\t\t\tthrow new Error('Failed to initialize LoomManager')\n\t\t}\n\n\t\t// Determine which branch is being finished based on parsed input\n\t\tlet targetBranch: string | undefined\n\n\t\tif (parsed.branchName) {\n\t\t\ttargetBranch = parsed.branchName\n\t\t} else if (parsed.type === 'issue' && parsed.number !== undefined) {\n\t\t\t// For issues, try to find the worktree by issue number to get the branch name\n\t\t\tconst worktree = await this.gitWorktreeManager.findWorktreeForIssue(parsed.number)\n\t\t\ttargetBranch = worktree?.branch\n\t\t} else if (parsed.type === 'pr' && parsed.number !== undefined) {\n\t\t\t// For PRs, ensure the number is numeric (PRs are always numeric per GitHub)\n\t\t\tconst prNumber = typeof parsed.number === 'number' ? parsed.number : Number(parsed.number)\n\t\t\tif (isNaN(prNumber) || !isFinite(prNumber)) {\n\t\t\t\tthrow new Error(`Invalid PR number: ${parsed.number}. PR numbers must be numeric.`)\n\t\t\t}\n\t\t\t// For PRs, try to find the worktree by PR number to get the branch name\n\t\t\tconst worktree = await this.gitWorktreeManager.findWorktreeForPR(prNumber, '')\n\t\t\ttargetBranch = worktree?.branch\n\t\t}\n\n\t\t// If we can't determine the target branch, skip the check\n\t\tif (!targetBranch) {\n\t\t\tgetLogger().debug(`Cannot determine target branch for child loom check`)\n\t\t\treturn\n\t\t}\n\n\t\t// Check if the TARGET loom has any child looms\n\t\tconst hasChildLooms = await this.loomManager.checkAndWarnChildLooms(targetBranch)\n\t\tif (hasChildLooms) {\n\t\t\tgetLogger().error('Cannot finish loom while child looms exist. Please \\'finish\\' or \\'cleanup\\' child looms first.')\n\t\t\tprocess.exit(1)\n\t\t}\n\t}\n\n\t/**\n\t * Main entry point for finish command\n\t */\n\tpublic async execute(input: FinishCommandInput): Promise<FinishResult | void> {\n\t\tconst isJsonMode = input.options.json === true\n\n\t\t// Initialize result object for JSON mode\n\t\tconst result: FinishResult = {\n\t\t\tsuccess: false,\n\t\t\ttype: 'issue',\n\t\t\tidentifier: '',\n\t\t\tdryRun: input.options.dryRun ?? false,\n\t\t\toperations: [],\n\t\t}\n\n\t\t// JSON mode validation - require explicit flags for interactive prompts\n\t\tif (isJsonMode) {\n\t\t\tconst settings = await this.settingsManager.loadSettings()\n\t\t\t// In github-pr mode, require explicit --cleanup or --no-cleanup\n\t\t\tif (settings.mergeBehavior?.mode === 'github-pr' && input.options.cleanup === undefined) {\n\t\t\t\tthrow new Error('JSON mode with github-pr workflow requires --cleanup or --no-cleanup flag. Use: il finish --json --cleanup <identifier>')\n\t\t\t}\n\t\t}\n\n\t\t// Step 1: Load settings and get configured repo for GitHub operations\n\t\tconst settings = await this.settingsManager.loadSettings()\n\n\t\tlet repo: string | undefined\n\n\t\t// We need repo info if:\n\t\t// 1. Merge mode is github-pr (for creating PRs on GitHub, even with Linear issues)\n\t\t// 2. Provider is GitHub (for GitHub issue operations)\n\t\tconst needsRepo =\n\t\t\tsettings.mergeBehavior?.mode === 'github-pr' || this.issueTracker.providerName === 'github'\n\t\tif (needsRepo && (await hasMultipleRemotes())) {\n\t\t\trepo = await getConfiguredRepoFromSettings(settings)\n\t\t\tgetLogger().info(`Using GitHub repository: ${repo}`)\n\t\t}\n\n\t\t// Step 2: Parse input (or auto-detect from current directory)\n\t\tconst parsed = await this.parseInput(input.identifier, input.options)\n\n\t\t// Update result with parsed type and identifier\n\t\tresult.type = parsed.type\n\t\tresult.identifier = parsed.number ?? parsed.branchName ?? ''\n\n\t\t// Step 2.5: Check for child looms AFTER parsing input\n\t\t// This ensures we only block when finishing the CURRENT loom (parent), not a child\n\t\tawait this.checkForChildLooms(parsed)\n\n\t\t// Step 2: Validate based on type and get worktrees\n\t\tconst worktrees = await this.validateInput(parsed, input.options, repo)\n\n\t\t// Step 3: Log success\n\t\tgetLogger().info(`Validated input: ${this.formatParsedInput(parsed)}`)\n\n\t\t// Get worktree for workflow execution\n\t\tconst worktree = worktrees[0]\n\t\tif (!worktree) {\n\t\t\tthrow new Error('No worktree found')\n\t\t}\n\n\t\t// Step 4: Branch based on input type\n\t\tif (parsed.type === 'pr') {\n\t\t\t// Fetch PR to get current state\n\t\t\tif (!parsed.number) {\n\t\t\t\tthrow new Error('Invalid PR number')\n\t\t\t}\n\t\t\t// Check if provider supports PRs before calling PR methods\n\t\t\tif (!this.issueTracker.supportsPullRequests || !this.issueTracker.fetchPR) {\n\t\t\t\tthrow new Error('Issue tracker does not support pull requests')\n\t\t\t}\n\t\t\tconst pr = await this.issueTracker.fetchPR(parsed.number, repo)\n\t\t\tawait this.executePRWorkflow(parsed, input.options, worktree, pr, result)\n\t\t} else {\n\t\t\t// Execute traditional issue/branch workflow\n\t\t\tawait this.executeIssueWorkflow(parsed, input.options, worktree, result)\n\t\t}\n\n\t\t// Mark overall success if we got here without throwing\n\t\tresult.success = true\n\n\t\t// Return result in JSON mode\n\t\tif (isJsonMode) {\n\t\t\treturn result\n\t\t}\n\t}\n\n\t/**\n\t * Parse input to determine type and extract relevant data\n\t * Supports auto-detection from current directory when identifier is undefined\n\t */\n\tprivate async parseInput(\n\t\tidentifier: string | undefined,\n\t\toptions: FinishOptions\n\t): Promise<ParsedFinishInput> {\n\t\t// Priority 1: --pr flag overrides everything\n\t\tif (options.pr !== undefined) {\n\t\t\treturn {\n\t\t\t\ttype: 'pr',\n\t\t\t\tnumber: options.pr,\n\t\t\t\toriginalInput: `--pr ${options.pr}`,\n\t\t\t\tautoDetected: false,\n\t\t\t}\n\t\t}\n\n\t\t// Priority 2: Explicit identifier provided\n\t\tif (identifier?.trim()) {\n\t\t\treturn await this.parseExplicitInput(identifier.trim())\n\t\t}\n\n\t\t// Priority 3: Auto-detect from current directory\n\t\treturn await this.autoDetectFromCurrentDirectory()\n\t}\n\n\t/**\n\t * Parse explicit identifier input using pattern-based detection\n\t * (No GitHub API calls - uses IdentifierParser)\n\t */\n\tprivate async parseExplicitInput(\n\t\tidentifier: string\n\t): Promise<ParsedFinishInput> {\n\t\t// Check for PR-specific formats: pr/123, PR-123, PR/123\n\t\tconst prPattern = /^(?:pr|PR)[/-](\\d+)$/\n\t\tconst prMatch = identifier.match(prPattern)\n\t\tif (prMatch?.[1]) {\n\t\t\treturn {\n\t\t\t\ttype: 'pr',\n\t\t\t\tnumber: parseInt(prMatch[1], 10),\n\t\t\t\toriginalInput: identifier,\n\t\t\t\tautoDetected: false,\n\t\t\t}\n\t\t}\n\n\t\t// Use IdentifierParser for pattern-based detection\n\t\t// (checks existing worktrees, no GitHub API calls)\n\t\tconst parsed = await this.identifierParser.parseForPatternDetection(identifier)\n\n\t\t// Description type should never reach finish command (converted in start)\n\t\tif (parsed.type === 'description') {\n\t\t\tthrow new Error('Description input type is not supported in finish command')\n\t\t}\n\n\t\t// Convert ParsedInput to ParsedFinishInput (add autoDetected field)\n\t\tconst result: ParsedFinishInput = {\n\t\t\ttype: parsed.type,\n\t\t\toriginalInput: parsed.originalInput,\n\t\t\tautoDetected: false,\n\t\t}\n\n\t\t// Add number or branchName based on type\n\t\tif (parsed.number !== undefined) {\n\t\t\tresult.number = parsed.number\n\t\t}\n\t\tif (parsed.branchName !== undefined) {\n\t\t\tresult.branchName = parsed.branchName\n\t\t}\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Auto-detect PR or issue from current directory\n\t * Ports logic from merge-current-issue.sh lines 30-52\n\t */\n\tprivate async autoDetectFromCurrentDirectory(): Promise<ParsedFinishInput> {\n\t\tconst currentDir = path.basename(process.cwd())\n\n\t\t// Check for PR worktree pattern: _pr_N suffix\n\t\t// Pattern: /.*_pr_(\\d+)$/\n\t\tconst prPattern = /_pr_(\\d+)$/\n\t\tconst prMatch = currentDir.match(prPattern)\n\n\t\tif (prMatch?.[1]) {\n\t\t\tconst prNumber = parseInt(prMatch[1], 10)\n\t\t\tgetLogger().debug(`Auto-detected PR #${prNumber} from directory: ${currentDir}`)\n\t\t\treturn {\n\t\t\t\ttype: 'pr',\n\t\t\t\tnumber: prNumber,\n\t\t\t\toriginalInput: currentDir,\n\t\t\t\tautoDetected: true,\n\t\t\t}\n\t\t}\n\n\t\t// Check for issue pattern in directory or branch name\n\t\tconst issueNumber = extractIssueNumber(currentDir)\n\n\t\tif (issueNumber !== null) {\n\t\t\tgetLogger().debug(\n\t\t\t\t`Auto-detected issue #${issueNumber} from directory: ${currentDir}`\n\t\t\t)\n\t\t\treturn {\n\t\t\t\ttype: 'issue',\n\t\t\t\tnumber: issueNumber,\n\t\t\t\toriginalInput: currentDir,\n\t\t\t\tautoDetected: true,\n\t\t\t}\n\t\t}\n\n\t\t// Fallback: get current branch name\n\t\tconst repoInfo = await this.gitWorktreeManager.getRepoInfo()\n\t\tconst currentBranch = repoInfo.currentBranch\n\n\t\tif (!currentBranch) {\n\t\t\tthrow new Error(\n\t\t\t\t'Could not auto-detect identifier. Please provide an issue number, PR number, or branch name.\\n' +\n\t\t\t\t\t'Expected directory pattern: feat/issue-XX-description OR worktree with _pr_N suffix'\n\t\t\t)\n\t\t}\n\n\t\t// Try to extract issue from branch name\n\t\tconst branchIssueNumber = extractIssueNumber(currentBranch)\n\t\tif (branchIssueNumber !== null) {\n\t\t\tgetLogger().debug(\n\t\t\t\t`Auto-detected issue #${branchIssueNumber} from branch: ${currentBranch}`\n\t\t\t)\n\t\t\treturn {\n\t\t\t\ttype: 'issue',\n\t\t\t\tnumber: branchIssueNumber,\n\t\t\t\toriginalInput: currentBranch,\n\t\t\t\tautoDetected: true,\n\t\t\t}\n\t\t}\n\n\t\t// Last resort: use branch name\n\t\treturn {\n\t\t\ttype: 'branch',\n\t\t\tbranchName: currentBranch,\n\t\t\toriginalInput: currentBranch,\n\t\t\tautoDetected: true,\n\t\t}\n\t}\n\n\t/**\n\t * Validate the parsed input based on its type\n\t */\n\tprivate async validateInput(\n\t\tparsed: ParsedFinishInput,\n\t\toptions: FinishOptions,\n\t\trepo?: string\n\t): Promise<GitWorktree[]> {\n\t\tswitch (parsed.type) {\n\t\t\tcase 'pr': {\n\t\t\t\tif (!parsed.number) {\n\t\t\t\t\tthrow new Error('Invalid PR number')\n\t\t\t\t}\n\n\t\t\t\t// Check if provider supports PRs before calling PR methods\n\t\t\t\tif (!this.issueTracker.supportsPullRequests || !this.issueTracker.fetchPR) {\n\t\t\t\t\tthrow new Error('Issue tracker does not support pull requests')\n\t\t\t\t}\n\n\t\t\t\t// Fetch PR from GitHub\n\t\t\t\tconst pr = await this.issueTracker.fetchPR(parsed.number)\n\n\t\t\t\t// For PRs, we allow closed/merged state (cleanup-only mode)\n\t\t\t\t// But we still validate it exists\n\t\t\t\tgetLogger().debug(`Validated PR #${parsed.number} (state: ${pr.state})`)\n\n\t\t\t\t// Find associated worktree\n\t\t\t\treturn await this.findWorktreeForIdentifier(parsed)\n\t\t\t}\n\n\t\t\tcase 'issue': {\n\t\t\t\tif (!parsed.number) {\n\t\t\t\t\tthrow new Error('Invalid issue number')\n\t\t\t\t}\n\n\t\t\t\t// Fetch issue from GitHub\n\t\t\t\tconst issue = await this.issueTracker.fetchIssue(parsed.number, repo)\n\n\t\t\t\t// Validate issue state (warn if closed unless --force)\n\t\t\t\tif (issue.state === 'closed' && !options.force) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Issue #${parsed.number} is closed. Use --force to finish anyway.`\n\t\t\t\t\t)\n\t\t\t\t}\n\n\t\t\t\tgetLogger().debug(`Validated issue #${parsed.number} (state: ${issue.state})`)\n\n\t\t\t\t// Find associated worktree\n\t\t\t\treturn await this.findWorktreeForIdentifier(parsed)\n\t\t\t}\n\n\t\t\tcase 'branch': {\n\t\t\t\tif (!parsed.branchName) {\n\t\t\t\t\tthrow new Error('Invalid branch name')\n\t\t\t\t}\n\n\t\t\t\t// Validate branch name format\n\t\t\t\tif (!this.isValidBranchName(parsed.branchName)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t'Invalid branch name. Use only letters, numbers, hyphens, underscores, and slashes'\n\t\t\t\t\t)\n\t\t\t\t}\n\n\t\t\t\tgetLogger().debug(`Validated branch name: ${parsed.branchName}`)\n\n\t\t\t\t// Find associated worktree\n\t\t\t\treturn await this.findWorktreeForIdentifier(parsed)\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tconst unknownType = parsed as { type: string }\n\t\t\t\tthrow new Error(`Unknown input type: ${unknownType.type}`)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Find worktree for the given identifier using specific methods based on type\n\t * (uses precise pattern matching instead of broad substring matching)\n\t * Throws error if not found\n\t */\n\tprivate async findWorktreeForIdentifier(\n\t\tparsed: ParsedFinishInput\n\t): Promise<GitWorktree[]> {\n\t\tlet worktree: GitWorktree | null = null\n\n\t\t// Use specific finding methods based on parsed type\n\t\tswitch (parsed.type) {\n\t\t\tcase 'pr': {\n\t\t\t\tif (!parsed.number) {\n\t\t\t\t\tthrow new Error('Invalid PR number')\n\t\t\t\t}\n\t\t\t\t// For PRs, ensure the number is numeric (PRs are always numeric per GitHub)\n\t\t\t\tconst prNumber = typeof parsed.number === 'number' ? parsed.number : Number(parsed.number)\n\t\t\t\tif (isNaN(prNumber) || !isFinite(prNumber)) {\n\t\t\t\t\tthrow new Error(`Invalid PR number: ${parsed.number}. PR numbers must be numeric.`)\n\t\t\t\t}\n\t\t\t\t// Pass empty string for branch name since we don't know it yet\n\t\t\t\tworktree = await this.gitWorktreeManager.findWorktreeForPR(\n\t\t\t\t\tprNumber,\n\t\t\t\t\t''\n\t\t\t\t)\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tcase 'issue': {\n\t\t\t\tif (!parsed.number) {\n\t\t\t\t\tthrow new Error('Invalid issue number')\n\t\t\t\t}\n\t\t\t\tworktree = await this.gitWorktreeManager.findWorktreeForIssue(\n\t\t\t\t\tparsed.number\n\t\t\t\t)\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tcase 'branch': {\n\t\t\t\tif (!parsed.branchName) {\n\t\t\t\t\tthrow new Error('Invalid branch name')\n\t\t\t\t}\n\t\t\t\tworktree = await this.gitWorktreeManager.findWorktreeForBranch(\n\t\t\t\t\tparsed.branchName\n\t\t\t\t)\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tdefault: {\n\t\t\t\tconst unknownType = parsed as { type: string }\n\t\t\t\tthrow new Error(`Unknown input type: ${unknownType.type}`)\n\t\t\t}\n\t\t}\n\n\t\tif (!worktree) {\n\t\t\tthrow new Error(\n\t\t\t\t`No worktree found for ${this.formatParsedInput(parsed)}. ` +\n\t\t\t\t\t`Use 'il list' to see available worktrees.`\n\t\t\t)\n\t\t}\n\n\t\tgetLogger().debug(`Found worktree: ${worktree.path}`)\n\n\t\treturn [worktree]\n\t}\n\n\t/**\n\t * Validate branch name format\n\t */\n\tprivate isValidBranchName(branch: string): boolean {\n\t\t// Pattern from bash script and StartCommand\n\t\treturn /^[a-zA-Z0-9/_-]+$/.test(branch)\n\t}\n\n\t/**\n\t * Format parsed input for display\n\t */\n\tprivate formatParsedInput(parsed: ParsedFinishInput): string {\n\t\tconst autoLabel = parsed.autoDetected ? ' (auto-detected)' : ''\n\n\t\tswitch (parsed.type) {\n\t\t\tcase 'pr':\n\t\t\t\treturn `PR #${parsed.number}${autoLabel}`\n\t\t\tcase 'issue':\n\t\t\t\treturn `Issue #${parsed.number}${autoLabel}`\n\t\t\tcase 'branch':\n\t\t\t\treturn `Branch '${parsed.branchName}'${autoLabel}`\n\t\t\tdefault:\n\t\t\t\treturn 'Unknown input'\n\t\t}\n\t}\n\n\t/**\n\t * Execute workflow for issues and branches (merge into main)\n\t * This is the traditional workflow: validate → commit → rebase → merge → cleanup\n\t */\n\tprivate async executeIssueWorkflow(\n\t\tparsed: ParsedFinishInput,\n\t\toptions: FinishOptions,\n\t\tworktree: GitWorktree,\n\t\tresult: FinishResult\n\t): Promise<void> {\n\t\t// Step 1: Run pre-merge validations FIRST (Sub-Issue #47)\n\t\tif (!options.dryRun) {\n\t\t\tgetLogger().info('Running pre-merge validations...')\n\n\t\t\tawait this.validationRunner.runValidations(worktree.path, {\n\t\t\t\tdryRun: options.dryRun ?? false,\n\t\t\t})\n\t\t\tgetLogger().success('All validations passed')\n\t\t\tresult.operations.push({\n\t\t\t\ttype: 'validation',\n\t\t\t\tmessage: 'Pre-merge validations passed',\n\t\t\t\tsuccess: true,\n\t\t\t})\n\t\t} else {\n\t\t\tgetLogger().info('[DRY RUN] Would run pre-merge validations')\n\t\t\tresult.operations.push({\n\t\t\t\ttype: 'validation',\n\t\t\t\tmessage: 'Would run pre-merge validations (dry-run)',\n\t\t\t\tsuccess: true,\n\t\t\t})\n\t\t}\n\n\t\t// Step 2: Detect uncommitted changes AFTER validation passes\n\t\tconst gitStatus = await this.commitManager.detectUncommittedChanges(worktree.path)\n\n\t\t// Step 3: Commit changes only if validation passed AND changes exist\n\t\tif (gitStatus.hasUncommittedChanges) {\n\t\t\tif (options.dryRun) {\n\t\t\t\tgetLogger().info('[DRY RUN] Would auto-commit uncommitted changes (validation passed)')\n\t\t\t\tresult.operations.push({\n\t\t\t\t\ttype: 'commit',\n\t\t\t\t\tmessage: 'Would auto-commit uncommitted changes (dry-run)',\n\t\t\t\t\tsuccess: true,\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\tgetLogger().info('Validation passed, auto-committing uncommitted changes...')\n\n\t\t\t\t// Load settings to get skipVerify configuration\n\t\t\t\tconst settings = await this.settingsManager.loadSettings(worktree.path)\n\t\t\t\tconst skipVerify = settings.workflows?.issue?.noVerify ?? false\n\n\t\t\t\tconst commitOptions: CommitOptions = {\n\t\t\t\t\tdryRun: options.dryRun ?? false,\n\t\t\t\t\tskipVerify,\n\t\t\t\t}\n\n\t\t\t\t// Only add issueNumber if it's an issue\n\t\t\t\tif (parsed.type === 'issue' && parsed.number) {\n\t\t\t\t\tcommitOptions.issueNumber = parsed.number\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tawait this.commitManager.commitChanges(worktree.path, commitOptions)\n\t\t\t\t\tgetLogger().success('Changes committed successfully')\n\t\t\t\t\tresult.operations.push({\n\t\t\t\t\t\ttype: 'commit',\n\t\t\t\t\t\tmessage: 'Changes committed successfully',\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t})\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (error instanceof UserAbortedCommitError) {\n\t\t\t\t\t\tgetLogger().info('Commit aborted by user')\n\t\t\t\t\t\tresult.operations.push({\n\t\t\t\t\t\t\ttype: 'commit',\n\t\t\t\t\t\t\tmessage: 'Commit aborted by user',\n\t\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\t})\n\t\t\t\t\t\treturn // Exit workflow gracefully\n\t\t\t\t\t}\n\t\t\t\t\tthrow error // Re-throw other errors\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tgetLogger().debug('No uncommitted changes found')\n\t\t}\n\n\t\t// Step 3.5: Check merge mode from settings and branch workflow\n\t\tconst settings = await this.settingsManager.loadSettings(worktree.path)\n\t\tconst mergeBehavior = settings.mergeBehavior ?? { mode: 'local' }\n\n\t\tif (mergeBehavior.mode === 'github-pr') {\n\t\t\t// Validate that issue tracker supports pull requests\n\t\t\tif (!this.issueTracker.supportsPullRequests) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`The 'github-pr' merge mode requires a GitHub-compatible issue tracker. ` +\n\t\t\t\t\t`Your current provider (${this.issueTracker.providerName}) does not support pull requests. ` +\n\t\t\t\t\t`Either change mergeBehavior.mode to 'local' in your settings, or use GitHub as your issue tracker.`\n\t\t\t\t)\n\t\t\t}\n\n\t\t\t// Execute github-pr workflow instead of local merge\n\t\t\tawait this.executeGitHubPRWorkflow(parsed, options, worktree, settings, result)\n\t\t\treturn\n\t\t}\n\n\t\t// Step 4: Rebase branch on main\n\t\tgetLogger().info('Rebasing branch on main...')\n\n\t\tconst mergeOptions: MergeOptions = {\n\t\t\tdryRun: options.dryRun ?? false,\n\t\t\tforce: options.force ?? false,\n\t\t}\n\n\t\tawait this.mergeManager.rebaseOnMain(worktree.path, mergeOptions)\n\t\tgetLogger().success('Branch rebased successfully')\n\t\tresult.operations.push({\n\t\t\ttype: 'rebase',\n\t\t\tmessage: 'Branch rebased on main',\n\t\t\tsuccess: true,\n\t\t})\n\n\t\t// Step 5: Perform fast-forward merge\n\t\tgetLogger().info('Performing fast-forward merge...')\n\t\tawait this.mergeManager.performFastForwardMerge(worktree.branch, worktree.path, mergeOptions)\n\t\tgetLogger().success('Fast-forward merge completed successfully')\n\t\tresult.operations.push({\n\t\t\ttype: 'merge',\n\t\t\tmessage: 'Fast-forward merge completed',\n\t\t\tsuccess: true,\n\t\t})\n\n\t\t// Step 5.5: Install dependencies in main worktree\n\t\tif (options.dryRun) {\n\t\t\tgetLogger().info('[DRY RUN] Would install dependencies in main worktree')\n\t\t} else {\n\t\t\tgetLogger().info('Installing dependencies in main worktree...')\n\t\t\tconst mainWorktreePath = await findMainWorktreePathWithSettings(worktree.path, this.settingsManager)\n\t\t\tawait installDependencies(mainWorktreePath, true, true)\n\t\t}\n\n\t\t// Step 5.6: Run post-merge build verification (CLI projects only)\n\t\tif (!options.skipBuild) {\n\t\t\tawait this.runPostMergeBuild(worktree.path, options, result)\n\t\t} else {\n\t\t\tgetLogger().debug('Skipping build verification (--skip-build flag provided)')\n\t\t}\n\n\t\t// Step 5.7: Generate session summary (non-blocking, preview-only in dry-run)\n\t\tawait this.generateSessionSummaryIfConfigured(parsed, worktree, options)\n\n\t\t// Step 6: Post-merge cleanup\n\t\tawait this.performPostMergeCleanup(parsed, options, worktree, result)\n\t}\n\n\t/**\n\t * Execute workflow for Pull Requests\n\t * Behavior depends on PR state:\n\t * - OPEN: Commit changes, push to remote, keep worktree active\n\t * - CLOSED/MERGED: Skip to cleanup\n\t */\n\tprivate async executePRWorkflow(\n\t\tparsed: ParsedFinishInput,\n\t\toptions: FinishOptions,\n\t\tworktree: GitWorktree,\n\t\tpr: PullRequest,\n\t\tresult: FinishResult\n\t): Promise<void> {\n\t\t// Branch based on PR state\n\t\tif (pr.state === 'closed' || pr.state === 'merged') {\n\t\t\t// Closed/Merged PR workflow\n\t\t\tgetLogger().info(`PR #${parsed.number} is ${pr.state.toUpperCase()} - skipping to cleanup`)\n\n\t\t\t// Check for uncommitted changes and warn (unless --force)\n\t\t\tconst gitStatus = await this.commitManager.detectUncommittedChanges(worktree.path)\n\t\t\tif (gitStatus.hasUncommittedChanges && !options.force) {\n\t\t\t\tgetLogger().warn('PR has uncommitted changes')\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'Cannot cleanup PR with uncommitted changes. ' +\n\t\t\t\t\t'Commit or stash changes, then run again with --force to cleanup anyway.'\n\t\t\t\t)\n\t\t\t}\n\n\t\t\t// Call cleanup directly with deleteBranch: true\n\t\t\t// Pass PR state to enable appropriate safety checks:\n\t\t\t// - merged: skip checks (work is in main)\n\t\t\t// - closed: enable checks (may have unpushed commits)\n\t\t\tawait this.performPRCleanup(parsed, options, worktree, pr.state as 'closed' | 'merged', result)\n\n\t\t\tgetLogger().success(`PR #${parsed.number} cleanup completed`)\n\t\t\tresult.operations.push({\n\t\t\t\ttype: 'cleanup',\n\t\t\t\tmessage: `PR #${parsed.number} cleanup completed`,\n\t\t\t\tsuccess: true,\n\t\t\t})\n\t\t} else {\n\t\t\t// Open PR workflow\n\t\t\tgetLogger().info(`PR #${parsed.number} is OPEN - will push changes and keep worktree active`)\n\n\t\t\t// Step 1: Detect uncommitted changes\n\t\t\tconst gitStatus = await this.commitManager.detectUncommittedChanges(worktree.path)\n\n\t\t\t// Step 2: Commit changes if any exist\n\t\t\tif (gitStatus.hasUncommittedChanges) {\n\t\t\t\tif (options.dryRun) {\n\t\t\t\t\tgetLogger().info('[DRY RUN] Would commit uncommitted changes')\n\t\t\t\t\tresult.operations.push({\n\t\t\t\t\t\ttype: 'commit',\n\t\t\t\t\t\tmessage: 'Would commit uncommitted changes (dry-run)',\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t})\n\t\t\t\t} else {\n\t\t\t\t\tgetLogger().info('Committing uncommitted changes...')\n\n\t\t\t\t\t// Load settings to get skipVerify configuration\n\t\t\t\t\tconst settings = await this.settingsManager.loadSettings(worktree.path)\n\t\t\t\t\tconst skipVerify = settings.workflows?.pr?.noVerify ?? false\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.commitManager.commitChanges(worktree.path, {\n\t\t\t\t\t\t\tdryRun: false,\n\t\t\t\t\t\t\tskipVerify,\n\t\t\t\t\t\t\t// Do NOT pass issueNumber for PRs - no \"Fixes #\" trailer needed\n\t\t\t\t\t\t})\n\t\t\t\t\t\tgetLogger().success('Changes committed')\n\t\t\t\t\t\tresult.operations.push({\n\t\t\t\t\t\t\ttype: 'commit',\n\t\t\t\t\t\t\tmessage: 'Changes committed successfully',\n\t\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\t})\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tif (error instanceof UserAbortedCommitError) {\n\t\t\t\t\t\t\tgetLogger().info('Commit aborted by user')\n\t\t\t\t\t\t\tresult.operations.push({\n\t\t\t\t\t\t\t\ttype: 'commit',\n\t\t\t\t\t\t\t\tmessage: 'Commit aborted by user',\n\t\t\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\treturn // Exit workflow gracefully\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthrow error // Re-throw other errors\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tgetLogger().debug('No uncommitted changes found')\n\t\t\t}\n\n\t\t\t// Step 3: Push to remote\n\t\t\tif (options.dryRun) {\n\t\t\t\tgetLogger().info(`[DRY RUN] Would push changes to origin/${pr.branch}`)\n\t\t\t} else {\n\t\t\t\tgetLogger().info('Pushing changes to remote...')\n\t\t\t\tawait pushBranchToRemote(pr.branch, worktree.path, {\n\t\t\t\t\tdryRun: false\n\t\t\t\t})\n\t\t\t\tgetLogger().success(`Changes pushed to PR #${parsed.number}`)\n\t\t\t}\n\n\t\t\t// Step 4: Log success and guidance\n\t\t\tgetLogger().success(`PR #${parsed.number} updated successfully`)\n\t\t\tgetLogger().info('Worktree remains active for continued work')\n\t\t\tgetLogger().info(`To cleanup when done: il cleanup ${parsed.number}`)\n\n\t\t\t// Set PR URL in result\n\t\t\tresult.prUrl = pr.url\n\t\t}\n\t}\n\n\t/**\n\t * Execute workflow for GitHub PR creation (github-pr merge mode)\n\t * Validates → Commits → Pushes → Creates PR → Prompts for cleanup\n\t */\n\tprivate async executeGitHubPRWorkflow(\n\t\tparsed: ParsedFinishInput,\n\t\toptions: FinishOptions,\n\t\tworktree: GitWorktree,\n\t\tsettings: import('../lib/SettingsManager.js').IloomSettings,\n\t\tfinishResult: FinishResult\n\t): Promise<void> {\n\t\t// Step 1: Push branch to origin\n\t\tif (options.dryRun) {\n\t\t\tgetLogger().info('[DRY RUN] Would push branch to origin')\n\t\t} else {\n\t\t\tgetLogger().info('Pushing branch to origin...')\n\t\t\tawait pushBranchToRemote(worktree.branch, worktree.path, { dryRun: false })\n\t\t\tgetLogger().success('Branch pushed successfully')\n\t\t}\n\n\t\t// Step 2: Initialize PRManager with settings\n\t\tconst prManager = new PRManager(settings)\n\n\t\t// Step 3: Generate PR title from issue if available\n\t\tlet prTitle = `Work from ${worktree.branch}`\n\t\tif (parsed.type === 'issue' && parsed.number) {\n\t\t\t// Try to fetch issue title for better PR title\n\t\t\ttry {\n\t\t\t\tconst issue = await this.issueTracker.fetchIssue(parsed.number)\n\t\t\t\tprTitle = issue.title\n\t\t\t} catch (error) {\n\t\t\t\tgetLogger().debug('Could not fetch issue title, using branch name', { error })\n\t\t\t}\n\t\t}\n\n\t\t// Step 4: Create or open PR\n\t\tif (options.dryRun) {\n\t\t\tgetLogger().info('[DRY RUN] Would create GitHub PR')\n\t\t\tgetLogger().info(` Title: ${prTitle}`)\n\t\t\tgetLogger().info(` Base: ${settings.mainBranch ?? 'main'}`)\n\t\t\tfinishResult.operations.push({\n\t\t\t\ttype: 'pr-creation',\n\t\t\t\tmessage: 'Would create GitHub PR (dry-run)',\n\t\t\t\tsuccess: true,\n\t\t\t})\n\t\t} else {\n\t\t\tconst baseBranch = settings.mainBranch ?? 'main'\n\t\t\tconst openInBrowser = options.noBrowser !== true\n\n\t\t\tconst prResult = await prManager.createOrOpenPR(\n\t\t\t\tworktree.branch,\n\t\t\t\tprTitle,\n\t\t\t\tparsed.type === 'issue' ? parsed.number : undefined,\n\t\t\t\tbaseBranch,\n\t\t\t\tworktree.path,\n\t\t\t\topenInBrowser\n\t\t\t)\n\n\t\t\tif (prResult.wasExisting) {\n\t\t\t\tgetLogger().success(`Existing pull request: ${prResult.url}`)\n\t\t\t\tfinishResult.operations.push({\n\t\t\t\t\ttype: 'pr-creation',\n\t\t\t\t\tmessage: `Found existing pull request`,\n\t\t\t\t\tsuccess: true,\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\tgetLogger().success(`Pull request created: ${prResult.url}`)\n\t\t\t\tfinishResult.operations.push({\n\t\t\t\t\ttype: 'pr-creation',\n\t\t\t\t\tmessage: `Pull request created`,\n\t\t\t\t\tsuccess: true,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\t// Set PR URL in result\n\t\t\tfinishResult.prUrl = prResult.url\n\n\t\t\t// Step 4.5: Generate session summary (non-blocking, preview-only in dry-run)\n\t\t\tawait this.generateSessionSummaryIfConfigured(parsed, worktree, options)\n\n\t\t\t// Step 5: Interactive cleanup prompt (unless flags override)\n\t\t\tawait this.handlePRCleanupPrompt(parsed, options, worktree, finishResult)\n\t\t}\n\t}\n\n\t/**\n\t * Handle cleanup prompt after PR creation\n\t * Respects --cleanup and --no-cleanup flags, otherwise prompts user\n\t */\n\tprivate async handlePRCleanupPrompt(\n\t\tparsed: ParsedFinishInput,\n\t\toptions: FinishOptions,\n\t\tworktree: GitWorktree,\n\t\tfinishResult: FinishResult\n\t): Promise<void> {\n\t\tif (options.cleanup === true) {\n\t\t\t// Explicit --cleanup flag: perform cleanup\n\t\t\tgetLogger().info('Cleaning up worktree (--cleanup flag)...')\n\t\t\tawait this.performWorktreeCleanup(parsed, options, worktree, finishResult)\n\t\t} else if (options.cleanup === false) {\n\t\t\t// Explicit --no-cleanup flag: keep worktree\n\t\t\tgetLogger().info('Worktree kept active for continued work (--no-cleanup flag)')\n\t\t\tgetLogger().info(`To cleanup later: il cleanup ${parsed.originalInput}`)\n\t\t} else {\n\t\t\t// No flag: prompt user for decision\n\t\t\tgetLogger().info('')\n\t\t\tgetLogger().info('PR created successfully. Would you like to clean up the worktree?')\n\t\t\tgetLogger().info(` Worktree: ${worktree.path}`)\n\t\t\tgetLogger().info(` Branch: ${worktree.branch}`)\n\t\t\tgetLogger().info('')\n\n\t\t\tconst shouldCleanup = await promptConfirmation(\n\t\t\t\t'Clean up worktree now?',\n\t\t\t\tfalse // Default to keeping worktree (safer option)\n\t\t\t)\n\n\t\t\tif (shouldCleanup) {\n\t\t\t\tawait this.performWorktreeCleanup(parsed, options, worktree, finishResult)\n\t\t\t} else {\n\t\t\t\tgetLogger().info('Worktree kept active. Run `il cleanup` when ready.')\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Perform worktree cleanup (used by GitHub PR workflow)\n\t * Similar to performPostMergeCleanup but for PR workflow\n\t */\n\tprivate async performWorktreeCleanup(\n\t\tparsed: ParsedFinishInput,\n\t\toptions: FinishOptions,\n\t\tworktree: GitWorktree,\n\t\tfinishResult: FinishResult\n\t): Promise<void> {\n\t\t// Convert ParsedFinishInput to ParsedInput\n\t\tconst cleanupInput: ParsedInput = {\n\t\t\ttype: parsed.type,\n\t\t\toriginalInput: parsed.originalInput,\n\t\t\t...(parsed.number !== undefined && { number: parsed.number }),\n\t\t\t...(parsed.branchName !== undefined && { branchName: parsed.branchName }),\n\t\t}\n\n\t\tconst cleanupOptions: ResourceCleanupOptions = {\n\t\t\tdryRun: options.dryRun ?? false,\n\t\t\tdeleteBranch: false, // Don't delete branch - PR still needs it\n\t\t\tkeepDatabase: false, // Clean up database\n\t\t\tforce: options.force ?? false,\n\t\t}\n\n\t\ttry {\n\t\t\tgetLogger().info('Starting worktree cleanup...')\n\n\t\t\tawait this.ensureResourceCleanup()\n\t\t\tif (!this.resourceCleanup) {\n\t\t\t\tthrow new Error('Failed to initialize ResourceCleanup')\n\t\t\t}\n\n\t\t\tconst cleanupResult = await this.resourceCleanup.cleanupWorktree(cleanupInput, cleanupOptions)\n\n\t\t\t// Report cleanup results\n\t\t\tthis.reportCleanupResults(cleanupResult)\n\n\t\t\t// Add cleanup result to finish result\n\t\t\tfinishResult.cleanupResult = cleanupResult\n\n\t\t\tif (!cleanupResult.success) {\n\t\t\t\tgetLogger().warn('Some cleanup operations failed - manual cleanup may be required')\n\t\t\t\tthis.showManualCleanupInstructions(worktree)\n\t\t\t\tfinishResult.operations.push({\n\t\t\t\t\ttype: 'cleanup',\n\t\t\t\t\tmessage: 'Worktree cleanup partially failed',\n\t\t\t\t\tsuccess: false,\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\tgetLogger().success('Worktree cleanup completed successfully')\n\t\t\t\tfinishResult.operations.push({\n\t\t\t\t\ttype: 'cleanup',\n\t\t\t\t\tmessage: 'Worktree cleanup completed',\n\t\t\t\t\tsuccess: true,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\t// Warn if running from within the worktree being finished\n\t\t\tif (this.isRunningFromWithinWorktree(worktree.path)) {\n\t\t\t\tthis.showTerminalCloseWarning(worktree)\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst errorMessage = error instanceof Error ? error.message : 'Unknown error'\n\t\t\tgetLogger().warn(`Cleanup failed: ${errorMessage}`)\n\t\t\tgetLogger().warn('Manual cleanup may be required')\n\t\t\tthis.showManualCleanupInstructions(worktree)\n\t\t\tfinishResult.operations.push({\n\t\t\t\ttype: 'cleanup',\n\t\t\t\tmessage: 'Worktree cleanup failed',\n\t\t\t\tsuccess: false,\n\t\t\t\terror: errorMessage,\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Perform cleanup for closed/merged PRs\n\t * Similar to performPostMergeCleanup but with different messaging\n\t *\n\t * Safety check behavior differs based on PR state:\n\t * - MERGED: Skip safety checks - work is safely in main branch\n\t * - CLOSED (not merged): Enable safety checks - PR was rejected/abandoned,\n\t * local commits may not exist anywhere else\n\t *\n\t * @param parsed - Parsed input identifying the PR\n\t * @param options - Finish options\n\t * @param worktree - The worktree to clean up\n\t * @param prState - The PR state ('closed' or 'merged')\n\t * @param finishResult - Result object to populate\n\t */\n\tprivate async performPRCleanup(\n\t\tparsed: ParsedFinishInput,\n\t\toptions: FinishOptions,\n\t\tworktree: GitWorktree,\n\t\tprState: 'closed' | 'merged',\n\t\tfinishResult: FinishResult\n\t): Promise<void> {\n\t\t// Convert to ParsedInput format\n\t\tconst cleanupInput: ParsedInput = {\n\t\t\ttype: parsed.type,\n\t\t\toriginalInput: parsed.originalInput,\n\t\t\t...(parsed.number !== undefined && { number: parsed.number }),\n\t\t\t...(parsed.branchName !== undefined && { branchName: parsed.branchName }),\n\t\t}\n\n\t\t// Safety checks depend on PR state:\n\t\t// - MERGED PR: Work is safely in main - skip all safety checks\n\t\t// - CLOSED PR: Work may NOT be on GitHub (PR was rejected/abandoned) - check for unpushed commits\n\t\tconst isMerged = prState === 'merged'\n\n\t\tconst cleanupOptions: ResourceCleanupOptions = {\n\t\t\tdryRun: options.dryRun ?? false,\n\t\t\tdeleteBranch: true, // Delete branch for closed/merged PRs\n\t\t\tkeepDatabase: false,\n\t\t\tforce: options.force ?? false,\n\t\t\t// For merged PRs: skip merge check (work is in main)\n\t\t\t// For closed PRs: enable merge check (may have unpushed local commits)\n\t\t\tcheckMergeSafety: !isMerged,\n\t\t\t// Skip remote branch check for MERGED PRs because:\n\t\t\t// 1. The PR is merged - the work is safely in main\n\t\t\t// 2. GitHub may have auto-deleted the branch after merge\n\t\t\t// 3. The user may have manually deleted the remote branch post-merge\n\t\t\t//\n\t\t\t// For CLOSED PRs, we rely on checkMergeSafety to verify no unpushed commits\n\t\t\t// rather than checkRemoteBranch, since the remote branch may still exist\n\t\t\t// but local may have additional commits\n\t\t\tcheckRemoteBranch: false,\n\t\t}\n\n\t\ttry {\n\t\t\tawait this.ensureResourceCleanup()\n\t\t\tif (!this.resourceCleanup) {\n\t\t\t\tthrow new Error('Failed to initialize ResourceCleanup')\n\t\t\t}\n\t\t\tconst cleanupResult = await this.resourceCleanup.cleanupWorktree(cleanupInput, cleanupOptions)\n\n\t\t\tthis.reportCleanupResults(cleanupResult)\n\t\t\tfinishResult.cleanupResult = cleanupResult\n\n\t\t\tif (!cleanupResult.success) {\n\t\t\t\tgetLogger().warn('Some cleanup operations failed - manual cleanup may be required')\n\t\t\t\tthis.showManualCleanupInstructions(worktree)\n\t\t\t} else {\n\t\t\t\t// Warn if running from within the worktree being finished (only on successful cleanup)\n\t\t\t\tif (this.isRunningFromWithinWorktree(worktree.path)) {\n\t\t\t\t\tthis.showTerminalCloseWarning(worktree)\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst errorMessage = error instanceof Error ? error.message : 'Unknown error'\n\t\t\tgetLogger().warn(`Cleanup failed: ${errorMessage}`)\n\t\t\tthis.showManualCleanupInstructions(worktree)\n\t\t\tthrow error // Re-throw to fail the command\n\t\t}\n\t}\n\n\t/**\n\t * Generate and post session summary if configured\n\t *\n\t * Non-blocking: Catches all errors and logs warnings instead of throwing\n\t * This ensures the finish workflow continues even if summary generation fails\n\t *\n\t * In dry-run mode: generates summary and shows preview, but doesn't post\n\t */\n\tprivate async generateSessionSummaryIfConfigured(\n\t\tparsed: ParsedFinishInput,\n\t\tworktree: GitWorktree,\n\t\toptions: FinishOptions\n\t): Promise<void> {\n\t\t// Skip for branch type (no issue to comment on)\n\t\tif (parsed.type === 'branch') {\n\t\t\treturn\n\t\t}\n\n\t\t// Initialize SessionSummaryService lazily\n\t\tthis.sessionSummaryService ??= new SessionSummaryService(\n\t\t\tundefined, // Use default PromptTemplateManager\n\t\t\tundefined, // Use default MetadataManager\n\t\t\tthis.settingsManager\n\t\t)\n\n\t\tif (options.dryRun) {\n\t\t\t// In dry-run mode: generate but don't post, show preview\n\t\t\ttry {\n\t\t\t\tconst result = await this.sessionSummaryService.generateSummary(\n\t\t\t\t\tworktree.path,\n\t\t\t\t\tworktree.branch,\n\t\t\t\t\tparsed.type,\n\t\t\t\t\tparsed.number\n\t\t\t\t)\n\t\t\t\tconst preview = result.summary.slice(0, 100).replace(/\\n/g, ' ')\n\t\t\t\tgetLogger().info(`[DRY RUN] Would post session summary: \"${preview}...\"`)\n\t\t\t} catch (error) {\n\t\t\t\tconst errorMessage = error instanceof Error ? error.message : String(error)\n\t\t\t\tgetLogger().warn(`[DRY RUN] Session summary generation failed: ${errorMessage}`)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\t// Generate and post summary (non-blocking)\n\t\tawait this.sessionSummaryService.generateAndPostSummary({\n\t\t\tworktreePath: worktree.path,\n\t\t\tissueNumber: parsed.number ?? 0,\n\t\t\tbranchName: worktree.branch,\n\t\t\tloomType: parsed.type,\n\t\t})\n\t}\n\n\t/**\n\t * Run post-merge build verification for CLI projects\n\t * Runs in main worktree to verify merged code builds successfully\n\t */\n\tprivate async runPostMergeBuild(\n\t\tworktreePath: string,\n\t\toptions: FinishOptions,\n\t\tfinishResult: FinishResult\n\t): Promise<void> {\n\t\t// Find main worktree path\n\t\tconst mainWorktreePath = await findMainWorktreePathWithSettings(worktreePath, this.settingsManager)\n\n\t\t// Check if dry-run\n\t\tif (options.dryRun) {\n\t\t\tgetLogger().info('[DRY RUN] Would run post-merge build')\n\t\t\tfinishResult.operations.push({\n\t\t\t\ttype: 'build',\n\t\t\t\tmessage: 'Would run post-merge build (dry-run)',\n\t\t\t\tsuccess: true,\n\t\t\t})\n\t\t\treturn\n\t\t}\n\n\t\tgetLogger().info('Running post-merge build...')\n\n\t\tconst buildResult = await this.buildRunner.runBuild(mainWorktreePath, {\n\t\t\tdryRun: options.dryRun ?? false,\n\t\t})\n\n\t\tif (buildResult.skipped) {\n\t\t\tgetLogger().debug(`Build skipped: ${buildResult.reason}`)\n\t\t\tfinishResult.operations.push({\n\t\t\t\ttype: 'build',\n\t\t\t\tmessage: `Build skipped: ${buildResult.reason}`,\n\t\t\t\tsuccess: true,\n\t\t\t})\n\t\t} else {\n\t\t\tgetLogger().success('Post-merge build completed successfully')\n\t\t\tfinishResult.operations.push({\n\t\t\t\ttype: 'build',\n\t\t\t\tmessage: 'Post-merge build completed',\n\t\t\t\tsuccess: true,\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Perform post-merge cleanup operations\n\t * Converts ParsedFinishInput to ParsedInput and calls ResourceCleanup\n\t * Handles failures gracefully without throwing\n\t */\n\tprivate async performPostMergeCleanup(\n\t\tparsed: ParsedFinishInput,\n\t\toptions: FinishOptions,\n\t\tworktree: GitWorktree,\n\t\tfinishResult: FinishResult\n\t): Promise<void> {\n\t\t// Ensure loomManager is initialized first\n\t\tawait this.ensureResourceCleanup()\n\t\tif (!this.loomManager) {\n\t\t\tthrow new Error('Failed to initialize LoomManager')\n\t\t}\n\n\t\t// Check for child looms again (second check - first was at start of execute)\n\t\t// This is a no-op if child looms were already checked and cleaned up\n\t\tawait this.checkForChildLooms(parsed)\n\n\t\t// Convert ParsedFinishInput to ParsedInput (drop autoDetected field)\n\t\tconst cleanupInput: ParsedInput = {\n\t\t\ttype: parsed.type,\n\t\t\toriginalInput: parsed.originalInput,\n\t\t\t...(parsed.number !== undefined && { number: parsed.number }),\n\t\t\t...(parsed.branchName !== undefined && { branchName: parsed.branchName }),\n\t\t}\n\n\t\tconst cleanupOptions: ResourceCleanupOptions = {\n\t\t\tdryRun: options.dryRun ?? false,\n\t\t\tdeleteBranch: true, // Delete branch after successful merge\n\t\t\tkeepDatabase: false, // Clean up database after merge\n\t\t\tforce: options.force ?? false,\n\t\t}\n\n\t\ttry {\n\t\t\tgetLogger().info('Starting post-merge cleanup...')\n\n\t\t\tif (!this.resourceCleanup) {\n\t\t\t\tthrow new Error('Failed to initialize ResourceCleanup')\n\t\t\t}\n\t\t\tconst cleanupResult = await this.resourceCleanup.cleanupWorktree(cleanupInput, cleanupOptions)\n\n\t\t\t// Report cleanup results\n\t\t\tthis.reportCleanupResults(cleanupResult)\n\t\t\tfinishResult.cleanupResult = cleanupResult\n\n\t\t\tif (!cleanupResult.success) {\n\t\t\t\tgetLogger().warn('Some cleanup operations failed - manual cleanup may be required')\n\t\t\t\t// Show helpful recovery message\n\t\t\t\tthis.showManualCleanupInstructions(worktree)\n\t\t\t\tfinishResult.operations.push({\n\t\t\t\t\ttype: 'cleanup',\n\t\t\t\t\tmessage: 'Post-merge cleanup partially failed',\n\t\t\t\t\tsuccess: false,\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\tgetLogger().success('Post-merge cleanup completed successfully')\n\t\t\t\tfinishResult.operations.push({\n\t\t\t\t\ttype: 'cleanup',\n\t\t\t\t\tmessage: 'Post-merge cleanup completed',\n\t\t\t\t\tsuccess: true,\n\t\t\t\t})\n\t\t\t}\n\n\t\t\t// Warn if running from within the worktree being finished\n\t\t\tif (this.isRunningFromWithinWorktree(worktree.path)) {\n\t\t\t\tthis.showTerminalCloseWarning(worktree)\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Catch cleanup errors to prevent finish command from failing\n\t\t\t// (merge already succeeded - cleanup failures are non-fatal)\n\t\t\tconst errorMessage = error instanceof Error ? error.message : 'Unknown error'\n\t\t\tgetLogger().warn(`Cleanup failed: ${errorMessage}`)\n\t\t\tgetLogger().warn('Merge completed successfully, but manual cleanup is required')\n\t\t\tthis.showManualCleanupInstructions(worktree)\n\t\t\tfinishResult.operations.push({\n\t\t\t\ttype: 'cleanup',\n\t\t\t\tmessage: 'Post-merge cleanup failed',\n\t\t\t\tsuccess: false,\n\t\t\t\terror: errorMessage,\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Report cleanup operation results to user\n\t */\n\tprivate reportCleanupResults(result: CleanupResult): void {\n\t\tif (result.operations.length === 0) {\n\t\t\treturn\n\t\t}\n\n\t\tgetLogger().info('Cleanup operations:')\n\t\tfor (const op of result.operations) {\n\t\t\tconst status = op.success ? '✓' : '✗'\n\t\t\tconst message = op.error ? `${op.message}: ${op.error}` : op.message\n\n\t\t\tif (op.success) {\n\t\t\t\tgetLogger().info(` ${status} ${message}`)\n\t\t\t} else {\n\t\t\t\tgetLogger().warn(` ${status} ${message}`)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Show manual cleanup instructions when cleanup fails\n\t */\n\tprivate showManualCleanupInstructions(worktree: GitWorktree): void {\n\t\tgetLogger().info('\\nManual cleanup commands:')\n\t\tgetLogger().info(` 1. Remove worktree: git worktree remove ${worktree.path}`)\n\t\tgetLogger().info(` 2. Delete branch: git branch -d ${worktree.branch}`)\n\t\tgetLogger().info(` 3. Check dev servers: lsof -i :PORT (and kill if needed)`)\n\t}\n\n\t/**\n\t * Check if current working directory is within the target worktree\n\t */\n\tprivate isRunningFromWithinWorktree(worktreePath: string): boolean {\n\t\tconst normalizedCwd = path.normalize(process.cwd())\n\t\tconst normalizedWorktree = path.normalize(worktreePath)\n\t\treturn normalizedCwd.startsWith(normalizedWorktree)\n\t}\n\n\t/**\n\t * Display warning to close terminal/IDE when running from within finished loom\n\t */\n\tprivate showTerminalCloseWarning(worktree: GitWorktree): void {\n\t\tgetLogger().info('')\n\t\tgetLogger().info('You are currently in the directory of the loom that was just finished.')\n\t\tgetLogger().info('Please close this terminal and any IDE/terminal windows using this directory.')\n\t\tgetLogger().info(`Directory: ${worktree.path}`)\n\t}\n}\n","import { readFileSync } from 'fs'\nimport { fileURLToPath } from 'url'\nimport { dirname, join } from 'path'\n\n/**\n * Package information from package.json\n */\nexport interface PackageInfo {\n name: string\n version: string\n description: string\n [key: string]: unknown\n}\n\n/**\n * Get package.json information\n *\n * @param scriptPath - Optional path to use for finding package.json (defaults to current file location)\n * @returns Parsed package.json contents\n * @throws Error if package.json cannot be read or parsed\n */\nexport function getPackageInfo(scriptPath?: string): PackageInfo {\n try {\n // Determine the base path to use\n let basePath: string\n if (scriptPath) {\n basePath = scriptPath\n } else {\n // Use import.meta.url to get the current file path\n const __filename = fileURLToPath(import.meta.url)\n basePath = __filename\n }\n\n // Navigate from current file to package.json\n // The compiled CLI runs from dist/cli.js, so we need dist/../package.json (one level up)\n const __dirname = dirname(basePath)\n const packageJsonPath = join(__dirname, '..', 'package.json')\n\n // Read and parse package.json\n const packageJsonContent = readFileSync(packageJsonPath, 'utf8')\n const packageJson = JSON.parse(packageJsonContent) as PackageInfo\n\n return packageJson\n } catch (error) {\n throw new Error(\n `Failed to read package.json: ${error instanceof Error ? error.message : 'Unknown error'}`\n )\n }\n}\n","import { extractIssueNumber } from './git.js'\nimport type { GitWorktree } from '../types/worktree.js'\nimport type { LoomMetadata } from '../lib/MetadataManager.js'\n\n/**\n * JSON output schema for il list --json\n */\nexport interface LoomJsonOutput {\n name: string\n worktreePath: string | null\n branch: string | null\n type: 'branch' | 'issue' | 'pr'\n issue_numbers: string[]\n pr_numbers: string[]\n isMainWorktree: boolean\n description?: string | null\n created_at?: string | null\n issueTracker?: string | null\n colorHex?: string | null\n}\n\n/**\n * Determine loom type from branch name and path patterns\n * Priority: PR (from path _pr_N suffix) > issue (from branch) > branch\n */\nfunction determineLoomType(worktree: GitWorktree): 'branch' | 'issue' | 'pr' {\n // Check for PR pattern in path: _pr_N suffix\n // This pattern is added by generateWorktreePath when isPR is true\n const prPathPattern = /_pr_\\d+$/\n if (prPathPattern.test(worktree.path)) {\n return 'pr'\n }\n\n // Check for issue pattern in branch using existing extractIssueNumber\n const issueNumber = extractIssueNumber(worktree.branch)\n if (issueNumber !== null) {\n return 'issue'\n }\n\n // Default to 'branch' type\n return 'branch'\n}\n\n/**\n * Extract PR numbers from worktree path\n * Returns array of string PR numbers extracted from _pr_N suffix\n */\nfunction extractPRNumbers(path: string): string[] {\n if (!path) {\n return []\n }\n\n const prPathPattern = /_pr_(\\d+)$/\n const match = path.match(prPathPattern)\n if (match?.[1]) {\n return [match[1]]\n }\n\n return []\n}\n\n/**\n * Extract issue numbers from branch name\n * Returns array of string identifiers (may include prefixes like PROJ-)\n */\nfunction extractIssueNumbers(branch: string): string[] {\n if (!branch) {\n return []\n }\n\n const issueNumber = extractIssueNumber(branch)\n if (issueNumber === null) {\n return []\n }\n\n // Return as array, already deduplicated by being a single extraction\n return [issueNumber]\n}\n\n/**\n * Format single worktree to JSON schema\n * - When metadata is available, use metadata values for type, issue_numbers, pr_numbers\n * - When metadata is not available, derive values from worktree path/branch\n *\n * @param worktree - The worktree to format\n * @param mainWorktreePath - Optional path to the main worktree for isMainWorktree detection\n * @param metadata - Optional metadata from MetadataManager (preferred source when available)\n */\nexport function formatLoomForJson(\n worktree: GitWorktree,\n mainWorktreePath?: string,\n metadata?: LoomMetadata | null\n): LoomJsonOutput {\n // Use metadata values when available, otherwise derive from worktree\n const loomType = metadata?.issueType ?? determineLoomType(worktree)\n\n // Use metadata arrays when available, otherwise extract from path/branch\n let issueNumbers: string[]\n let prNumbers: string[]\n\n if (metadata) {\n // Use metadata values directly\n issueNumbers = metadata.issue_numbers\n prNumbers = metadata.pr_numbers\n } else {\n // Derive from worktree path/branch\n issueNumbers = []\n prNumbers = []\n if (loomType === 'pr') {\n prNumbers = extractPRNumbers(worktree.path)\n } else if (loomType === 'issue') {\n issueNumbers = extractIssueNumbers(worktree.branch)\n }\n }\n\n // Determine if this is the main worktree by comparing paths\n const isMainWorktree = mainWorktreePath ? worktree.path === mainWorktreePath : false\n\n return {\n name: worktree.branch || worktree.path,\n worktreePath: worktree.bare ? null : worktree.path,\n branch: (metadata?.branchName ?? worktree.branch) || null,\n type: loomType,\n issue_numbers: issueNumbers,\n pr_numbers: prNumbers,\n isMainWorktree,\n description: metadata?.description ?? null,\n created_at: metadata?.created_at ?? null,\n issueTracker: metadata?.issueTracker ?? null,\n colorHex: metadata?.colorHex ?? null\n }\n}\n\n/**\n * Format array of worktrees to JSON schema\n *\n * @param worktrees - Array of worktrees to format\n * @param mainWorktreePath - Optional path to the main worktree for isMainWorktree detection\n * @param metadata - Optional map of worktree paths to metadata\n */\nexport function formatLoomsForJson(\n worktrees: GitWorktree[],\n mainWorktreePath?: string,\n metadata?: Map<string, LoomMetadata | null>\n): LoomJsonOutput[] {\n return worktrees.map(wt => formatLoomForJson(wt, mainWorktreePath, metadata?.get(wt.path)))\n}\n"],"mappings":"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","names":["path","waitForKeypress","promptConfirmation","path","readFile","execa","body","path","DefaultBranchNamingService","settings","join","__filename","packageJson","fileURLToPath","path","fileURLToPath","shellCompletion","waitForKeypress","InitCommand","SettingsManager","hasMultipleRemotes","GitHubService","DefaultBranchNamingService","detectClaudeCli","launchClaude","ClaudeContextManager","createNeonProviderFromSettings"]}
|