@iloom/cli 0.1.14
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/LICENSE +33 -0
- package/README.md +711 -0
- package/dist/ClaudeContextManager-XOSXQ67R.js +13 -0
- package/dist/ClaudeContextManager-XOSXQ67R.js.map +1 -0
- package/dist/ClaudeService-YSZ6EXWP.js +12 -0
- package/dist/ClaudeService-YSZ6EXWP.js.map +1 -0
- package/dist/GitHubService-F7Z3XJOS.js +11 -0
- package/dist/GitHubService-F7Z3XJOS.js.map +1 -0
- package/dist/LoomLauncher-MODG2SEM.js +263 -0
- package/dist/LoomLauncher-MODG2SEM.js.map +1 -0
- package/dist/NeonProvider-PAGPUH7F.js +12 -0
- package/dist/NeonProvider-PAGPUH7F.js.map +1 -0
- package/dist/PromptTemplateManager-7FINLRDE.js +9 -0
- package/dist/PromptTemplateManager-7FINLRDE.js.map +1 -0
- package/dist/SettingsManager-VAZF26S2.js +19 -0
- package/dist/SettingsManager-VAZF26S2.js.map +1 -0
- package/dist/SettingsMigrationManager-MTQIMI54.js +146 -0
- package/dist/SettingsMigrationManager-MTQIMI54.js.map +1 -0
- package/dist/add-issue-22JBNOML.js +54 -0
- package/dist/add-issue-22JBNOML.js.map +1 -0
- package/dist/agents/iloom-issue-analyze-and-plan.md +580 -0
- package/dist/agents/iloom-issue-analyzer.md +290 -0
- package/dist/agents/iloom-issue-complexity-evaluator.md +224 -0
- package/dist/agents/iloom-issue-enhancer.md +266 -0
- package/dist/agents/iloom-issue-implementer.md +262 -0
- package/dist/agents/iloom-issue-planner.md +358 -0
- package/dist/agents/iloom-issue-reviewer.md +63 -0
- package/dist/chunk-2ZPFJQ3B.js +63 -0
- package/dist/chunk-2ZPFJQ3B.js.map +1 -0
- package/dist/chunk-37DYYFVK.js +29 -0
- package/dist/chunk-37DYYFVK.js.map +1 -0
- package/dist/chunk-BLCTGFZN.js +121 -0
- package/dist/chunk-BLCTGFZN.js.map +1 -0
- package/dist/chunk-CP2NU2JC.js +545 -0
- package/dist/chunk-CP2NU2JC.js.map +1 -0
- package/dist/chunk-CWR2SANQ.js +39 -0
- package/dist/chunk-CWR2SANQ.js.map +1 -0
- package/dist/chunk-F3XBU2R7.js +110 -0
- package/dist/chunk-F3XBU2R7.js.map +1 -0
- package/dist/chunk-GEHQXLEI.js +130 -0
- package/dist/chunk-GEHQXLEI.js.map +1 -0
- package/dist/chunk-GYCR2LOU.js +143 -0
- package/dist/chunk-GYCR2LOU.js.map +1 -0
- package/dist/chunk-GZP4UGGM.js +48 -0
- package/dist/chunk-GZP4UGGM.js.map +1 -0
- package/dist/chunk-H4E4THUZ.js +55 -0
- package/dist/chunk-H4E4THUZ.js.map +1 -0
- package/dist/chunk-HPJJSYNS.js +644 -0
- package/dist/chunk-HPJJSYNS.js.map +1 -0
- package/dist/chunk-JBH2ZYYZ.js +220 -0
- package/dist/chunk-JBH2ZYYZ.js.map +1 -0
- package/dist/chunk-JNKJ7NJV.js +78 -0
- package/dist/chunk-JNKJ7NJV.js.map +1 -0
- package/dist/chunk-JQ7VOSTC.js +437 -0
- package/dist/chunk-JQ7VOSTC.js.map +1 -0
- package/dist/chunk-KQDEK2ZW.js +199 -0
- package/dist/chunk-KQDEK2ZW.js.map +1 -0
- package/dist/chunk-O2QWO64Z.js +179 -0
- package/dist/chunk-O2QWO64Z.js.map +1 -0
- package/dist/chunk-OC4H6HJD.js +248 -0
- package/dist/chunk-OC4H6HJD.js.map +1 -0
- package/dist/chunk-PR7FKQBG.js +120 -0
- package/dist/chunk-PR7FKQBG.js.map +1 -0
- package/dist/chunk-PXZBAC2M.js +250 -0
- package/dist/chunk-PXZBAC2M.js.map +1 -0
- package/dist/chunk-QEPVTTHD.js +383 -0
- package/dist/chunk-QEPVTTHD.js.map +1 -0
- package/dist/chunk-RSRO7564.js +203 -0
- package/dist/chunk-RSRO7564.js.map +1 -0
- package/dist/chunk-SJUQ2NDR.js +146 -0
- package/dist/chunk-SJUQ2NDR.js.map +1 -0
- package/dist/chunk-SPYPLHMK.js +177 -0
- package/dist/chunk-SPYPLHMK.js.map +1 -0
- package/dist/chunk-SSCQCCJ7.js +75 -0
- package/dist/chunk-SSCQCCJ7.js.map +1 -0
- package/dist/chunk-SSR5AVRJ.js +41 -0
- package/dist/chunk-SSR5AVRJ.js.map +1 -0
- package/dist/chunk-T7QPXANZ.js +315 -0
- package/dist/chunk-T7QPXANZ.js.map +1 -0
- package/dist/chunk-U3WU5OWO.js +203 -0
- package/dist/chunk-U3WU5OWO.js.map +1 -0
- package/dist/chunk-W3DQTW63.js +124 -0
- package/dist/chunk-W3DQTW63.js.map +1 -0
- package/dist/chunk-WKEWRSDB.js +151 -0
- package/dist/chunk-WKEWRSDB.js.map +1 -0
- package/dist/chunk-Y7SAGNUT.js +66 -0
- package/dist/chunk-Y7SAGNUT.js.map +1 -0
- package/dist/chunk-YETJNRQM.js +39 -0
- package/dist/chunk-YETJNRQM.js.map +1 -0
- package/dist/chunk-YYSKGAZT.js +384 -0
- package/dist/chunk-YYSKGAZT.js.map +1 -0
- package/dist/chunk-ZZZWQGTS.js +169 -0
- package/dist/chunk-ZZZWQGTS.js.map +1 -0
- package/dist/claude-7LUVDZZ4.js +17 -0
- package/dist/claude-7LUVDZZ4.js.map +1 -0
- package/dist/cleanup-3LUWPSM7.js +412 -0
- package/dist/cleanup-3LUWPSM7.js.map +1 -0
- package/dist/cli-overrides-XFZWY7CM.js +16 -0
- package/dist/cli-overrides-XFZWY7CM.js.map +1 -0
- package/dist/cli.js +603 -0
- package/dist/cli.js.map +1 -0
- package/dist/color-ZVALX37U.js +21 -0
- package/dist/color-ZVALX37U.js.map +1 -0
- package/dist/enhance-XJIQHVPD.js +166 -0
- package/dist/enhance-XJIQHVPD.js.map +1 -0
- package/dist/env-MDFL4ZXL.js +23 -0
- package/dist/env-MDFL4ZXL.js.map +1 -0
- package/dist/feedback-23CLXKFT.js +158 -0
- package/dist/feedback-23CLXKFT.js.map +1 -0
- package/dist/finish-CY4CIH6O.js +1608 -0
- package/dist/finish-CY4CIH6O.js.map +1 -0
- package/dist/git-LVRZ57GJ.js +43 -0
- package/dist/git-LVRZ57GJ.js.map +1 -0
- package/dist/ignite-WXEF2ID5.js +359 -0
- package/dist/ignite-WXEF2ID5.js.map +1 -0
- package/dist/index.d.ts +1341 -0
- package/dist/index.js +3058 -0
- package/dist/index.js.map +1 -0
- package/dist/init-RHACUR4E.js +123 -0
- package/dist/init-RHACUR4E.js.map +1 -0
- package/dist/installation-detector-VARGFFRZ.js +11 -0
- package/dist/installation-detector-VARGFFRZ.js.map +1 -0
- package/dist/logger-MKYH4UDV.js +12 -0
- package/dist/logger-MKYH4UDV.js.map +1 -0
- package/dist/mcp/chunk-6SDFJ42P.js +62 -0
- package/dist/mcp/chunk-6SDFJ42P.js.map +1 -0
- package/dist/mcp/claude-YHHHLSXH.js +249 -0
- package/dist/mcp/claude-YHHHLSXH.js.map +1 -0
- package/dist/mcp/color-QS5BFCNN.js +168 -0
- package/dist/mcp/color-QS5BFCNN.js.map +1 -0
- package/dist/mcp/github-comment-server.js +165 -0
- package/dist/mcp/github-comment-server.js.map +1 -0
- package/dist/mcp/terminal-SDCMDVD7.js +202 -0
- package/dist/mcp/terminal-SDCMDVD7.js.map +1 -0
- package/dist/open-X6BTENPV.js +278 -0
- package/dist/open-X6BTENPV.js.map +1 -0
- package/dist/prompt-ANTQWHUF.js +13 -0
- package/dist/prompt-ANTQWHUF.js.map +1 -0
- package/dist/prompts/issue-prompt.txt +230 -0
- package/dist/prompts/pr-prompt.txt +35 -0
- package/dist/prompts/regular-prompt.txt +14 -0
- package/dist/run-2JCPQAX3.js +278 -0
- package/dist/run-2JCPQAX3.js.map +1 -0
- package/dist/schema/settings.schema.json +221 -0
- package/dist/start-LWVRBJ6S.js +982 -0
- package/dist/start-LWVRBJ6S.js.map +1 -0
- package/dist/terminal-3D6TUAKJ.js +16 -0
- package/dist/terminal-3D6TUAKJ.js.map +1 -0
- package/dist/test-git-XPF4SZXJ.js +52 -0
- package/dist/test-git-XPF4SZXJ.js.map +1 -0
- package/dist/test-prefix-XGFXFAYN.js +68 -0
- package/dist/test-prefix-XGFXFAYN.js.map +1 -0
- package/dist/test-tabs-JRKY3QMM.js +69 -0
- package/dist/test-tabs-JRKY3QMM.js.map +1 -0
- package/dist/test-webserver-M2I3EV4J.js +62 -0
- package/dist/test-webserver-M2I3EV4J.js.map +1 -0
- package/dist/update-3ZT2XX2G.js +79 -0
- package/dist/update-3ZT2XX2G.js.map +1 -0
- package/dist/update-notifier-QSSEB5KC.js +11 -0
- package/dist/update-notifier-QSSEB5KC.js.map +1 -0
- package/package.json +113 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/ValidationRunner.ts","../src/lib/CommitManager.ts","../src/lib/MergeManager.ts","../src/lib/BuildRunner.ts","../src/commands/finish.ts"],"sourcesContent":["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 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 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 to continue the validation process.`\n\t\t\t\t)\n\t\t}\n\t}\n}\n","import { executeGitCommand } from '../utils/git.js'\nimport { logger } from '../utils/logger.js'\nimport { launchClaude, detectClaudeCli } from '../utils/claude.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 git editor (unless noReview specified)\n try {\n if (options.noReview || options.message) {\n // Direct commit without editor review\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 // Use git editor for user review - pre-populate message and open editor\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 } catch (error) {\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 AI\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?: 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?: 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 { executeGitCommand, findMainWorktreePathWithSettings } from '../utils/git.js'\nimport { logger } from '../utils/logger.js'\nimport { detectClaudeCli, launchClaude } from '../utils/claude.js'\nimport { SettingsManager } from './SettingsManager.js'\nimport type { MergeOptions } from '../types/index.js'\n\n/**\n * MergeManager handles Git rebase and fast-forward merge operations\n * Implements fail-fast behavior for conflicts (Phase 1 - no Claude assistance)\n *\n * Ports bash/merge-and-clean.sh lines 781-1090\n */\nexport class MergeManager {\n\tprivate settingsManager: SettingsManager\n\n\tconstructor(settingsManager?: SettingsManager) {\n\t\tthis.settingsManager = settingsManager ?? new SettingsManager()\n\t}\n\n\t/**\n\t * Get the main branch name from settings (defaults to 'main')\n\t * @private\n\t */\n\tprivate async getMainBranch(): Promise<string> {\n\t\tconst settings = await this.settingsManager.loadSettings()\n\t\treturn settings.mainBranch ?? 'main'\n\t}\n\n\t/**\n\t * Rebase current branch on main with fail-fast on conflicts\n\t * Ports bash/merge-and-clean.sh lines 781-913\n\t *\n\t * @param worktreePath - Path to the worktree\n\t * @param options - Merge options (dryRun, force)\n\t * @throws Error if main branch doesn't exist, uncommitted changes exist, or conflicts occur\n\t */\n\tasync rebaseOnMain(worktreePath: string, options: MergeOptions = {}): Promise<void> {\n\t\tconst { dryRun = false, force = false } = options\n\t\tconst mainBranch = await this.getMainBranch()\n\n\t\tlogger.info(`Starting rebase on ${mainBranch} branch...`)\n\n\t\t// Step 1: Check if main branch exists\n\t\ttry {\n\t\t\tawait executeGitCommand(['show-ref', '--verify', '--quiet', `refs/heads/${mainBranch}`], {\n\t\t\t\tcwd: worktreePath,\n\t\t\t})\n\t\t} catch {\n\t\t\tthrow new Error(\n\t\t\t\t`Main branch \"${mainBranch}\" does not exist. Cannot rebase.\\n` +\n\t\t\t\t\t`Ensure the repository has a \"${mainBranch}\" branch or create it first.`\n\t\t\t)\n\t\t}\n\n\t\t// Step 2: Check for uncommitted changes (defensive check)\n\t\tconst statusOutput = await executeGitCommand(['status', '--porcelain'], {\n\t\t\tcwd: worktreePath,\n\t\t})\n\n\t\tif (statusOutput.trim()) {\n\t\t\tthrow new Error(\n\t\t\t\t'Uncommitted changes detected. Please commit or stash changes before rebasing.\\n' +\n\t\t\t\t\t'Run: git status to see uncommitted changes\\n' +\n\t\t\t\t\t'Or: il finish will automatically commit them for you'\n\t\t\t)\n\t\t}\n\n\t\t// Step 3: Check if rebase is needed by comparing merge-base with main HEAD\n\t\tconst mergeBase = await executeGitCommand(['merge-base', mainBranch, 'HEAD'], {\n\t\t\tcwd: worktreePath,\n\t\t})\n\n\t\tconst mainHead = await executeGitCommand(['rev-parse', mainBranch], {\n\t\t\tcwd: worktreePath,\n\t\t})\n\n\t\tconst mergeBaseTrimmed = mergeBase.trim()\n\t\tconst mainHeadTrimmed = mainHead.trim()\n\n\t\t// If merge-base matches main HEAD, branch is already up to date\n\t\tif (mergeBaseTrimmed === mainHeadTrimmed) {\n\t\t\tlogger.success(`Branch is already up to date with ${mainBranch}. No rebase needed.`)\n\t\t\treturn\n\t\t}\n\n\t\t// Step 4: Show commits to be rebased (for informational purposes)\n\t\tconst commitsOutput = await executeGitCommand(['log', '--oneline', `${mainBranch}..HEAD`], {\n\t\t\tcwd: worktreePath,\n\t\t})\n\n\t\tconst commits = commitsOutput.trim()\n\t\tconst commitLines = commits ? commits.split('\\n') : []\n\n\t\tif (commits) {\n\t\t\t// Show commits that will be rebased\n\t\t\tlogger.info(`Found ${commitLines.length} commit(s) to rebase:`)\n\t\t\tcommitLines.forEach((commit) => logger.info(` ${commit}`))\n\t\t} else {\n\t\t\t// Main has moved forward but branch has no new commits\n\t\t\tlogger.info(`${mainBranch} branch has moved forward. Rebasing to update branch...`)\n\t\t}\n\n\t\t// Step 5: User confirmation (unless force mode or dry-run)\n\t\tif (!force && !dryRun) {\n\t\t\t// TODO: Implement interactive prompt for confirmation\n\t\t\t// For now, proceeding automatically (use --force to skip this message)\n\t\t\tlogger.info('Proceeding with rebase... (use --force to skip confirmations)')\n\t\t}\n\n\t\t// Step 6: Execute rebase (unless dry-run)\n\t\tif (dryRun) {\n\t\t\tlogger.info(`[DRY RUN] Would execute: git rebase ${mainBranch}`)\n\t\t\tif (commitLines.length > 0) {\n\t\t\t\tlogger.info(`[DRY RUN] This would rebase ${commitLines.length} commit(s)`)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\t// Execute rebase\n\t\ttry {\n\t\t\tawait executeGitCommand(['rebase', mainBranch], { cwd: worktreePath })\n\t\t\tlogger.success('Rebase completed successfully!')\n\t\t} catch (error) {\n\t\t\t// Detect conflicts\n\t\t\tconst conflictedFiles = await this.detectConflictedFiles(worktreePath)\n\n\t\t\tif (conflictedFiles.length > 0) {\n\t\t\t\t// Try Claude-assisted resolution first\n\t\t\t\tlogger.info('Merge conflicts detected, attempting Claude-assisted resolution...')\n\n\t\t\t\tconst resolved = await this.attemptClaudeConflictResolution(\n\t\t\t\t\tworktreePath,\n\t\t\t\t\tconflictedFiles\n\t\t\t\t)\n\n\t\t\t\tif (resolved) {\n\t\t\t\t\tlogger.success('Conflicts resolved with Claude assistance, rebase completed')\n\t\t\t\t\treturn // Continue with successful rebase\n\t\t\t\t}\n\n\t\t\t\t// Claude couldn't resolve or not available - fail fast\n\t\t\t\tconst conflictError = this.formatConflictError(conflictedFiles)\n\t\t\t\tthrow new Error(conflictError)\n\t\t\t}\n\n\t\t\t// If not a conflict, re-throw the original error\n\t\t\tthrow new Error(\n\t\t\t\t`Rebase failed: ${error instanceof Error ? error.message : String(error)}\\n` +\n\t\t\t\t\t'Run: git status for more details\\n' +\n\t\t\t\t\t'Or: git rebase --abort to cancel the rebase'\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * Validate that fast-forward merge is possible\n\t * Ports bash/merge-and-clean.sh lines 957-968\n\t *\n\t * @param branchName - Name of the branch to merge\n\t * @param mainWorktreePath - Path where main branch is checked out\n\t * @throws Error if fast-forward is not possible\n\t */\n\tasync validateFastForwardPossible(branchName: string, mainWorktreePath: string): Promise<void> {\n\t\tconst mainBranch = await this.getMainBranch()\n\n\t\t// Step 1: Get merge-base between main and branch\n\t\tconst mergeBase = await executeGitCommand(['merge-base', mainBranch, branchName], {\n\t\t\tcwd: mainWorktreePath,\n\t\t})\n\n\t\t// Step 2: Get current HEAD of main\n\t\tconst mainHead = await executeGitCommand(['rev-parse', mainBranch], {\n\t\t\tcwd: mainWorktreePath,\n\t\t})\n\n\t\t// Step 3: Compare - they must match for fast-forward\n\t\tconst mergeBaseTrimmed = mergeBase.trim()\n\t\tconst mainHeadTrimmed = mainHead.trim()\n\n\t\tif (mergeBaseTrimmed !== mainHeadTrimmed) {\n\t\t\tthrow new Error(\n\t\t\t\t'Cannot perform fast-forward merge.\\n' +\n\t\t\t\t\t`The ${mainBranch} branch has moved forward since this branch was created.\\n` +\n\t\t\t\t\t`Merge base: ${mergeBaseTrimmed}\\n` +\n\t\t\t\t\t`Main HEAD: ${mainHeadTrimmed}\\n\\n` +\n\t\t\t\t\t'To fix this:\\n' +\n\t\t\t\t\t` 1. Rebase the branch on ${mainBranch}: git rebase ${mainBranch}\\n` +\n\t\t\t\t\t` 2. Or use: il finish to automatically rebase and merge\\n`\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * Perform fast-forward only merge\n\t * Ports bash/merge-and-clean.sh lines 938-994\n\t *\n\t * @param branchName - Name of the branch to merge\n\t * @param worktreePath - Path to the worktree\n\t * @param options - Merge options (dryRun, force)\n\t * @throws Error if checkout, validation, or merge fails\n\t */\n\tasync performFastForwardMerge(\n\t\tbranchName: string,\n\t\tworktreePath: string,\n\t\toptions: MergeOptions = {}\n\t): Promise<void> {\n\t\tconst { dryRun = false, force = false } = options\n\t\tconst mainBranch = await this.getMainBranch()\n\n\t\tlogger.info('Starting fast-forward merge...')\n\n\t\t// Step 1: Find where main branch is checked out\n\t\t// This copies the bash script approach: find main worktree, run commands from there\n\t\tconst mainWorktreePath = options.repoRoot ??\n\t\t\tawait findMainWorktreePathWithSettings(worktreePath, this.settingsManager)\n\n\t\t// Step 3: No need to checkout main - it's already checked out in mainWorktreePath\n\t\tlogger.debug(`Using ${mainBranch} branch location: ${mainWorktreePath}`)\n\n\t\t// Step 4: Verify on main branch\n\t\tconst currentBranch = await executeGitCommand(['branch', '--show-current'], {\n\t\t\tcwd: mainWorktreePath,\n\t\t})\n\n\t\tif (currentBranch.trim() !== mainBranch) {\n\t\t\tthrow new Error(\n\t\t\t\t`Expected ${mainBranch} branch but found: ${currentBranch.trim()}\\n` +\n\t\t\t\t\t`At location: ${mainWorktreePath}\\n` +\n\t\t\t\t\t'This indicates the main worktree detection failed.'\n\t\t\t)\n\t\t}\n\n\t\t// Step 5: Validate fast-forward is possible\n\t\tawait this.validateFastForwardPossible(branchName, mainWorktreePath)\n\n\t\t// Step 6: Show commits to be merged\n\t\tconst commitsOutput = await executeGitCommand(['log', '--oneline', `${mainBranch}..${branchName}`], {\n\t\t\tcwd: mainWorktreePath,\n\t\t})\n\n\t\tconst commits = commitsOutput.trim()\n\n\t\t// If no commits, branch is already merged\n\t\tif (!commits) {\n\t\t\tlogger.success(`Branch is already merged into ${mainBranch}. No merge needed.`)\n\t\t\treturn\n\t\t}\n\n\t\t// Show commits that will be merged\n\t\tconst commitLines = commits.split('\\n')\n\t\tlogger.info(`Found ${commitLines.length} commit(s) to merge:`)\n\t\tcommitLines.forEach((commit) => logger.info(` ${commit}`))\n\n\t\t// Step 7: User confirmation (unless force mode or dry-run)\n\t\tif (!force && !dryRun) {\n\t\t\t// TODO: Implement interactive prompt for confirmation\n\t\t\t// For now, proceeding automatically (use --force to skip this message)\n\t\t\tlogger.info('Proceeding with fast-forward merge... (use --force to skip confirmations)')\n\t\t}\n\n\t\t// Step 8: Execute merge (unless dry-run)\n\t\tif (dryRun) {\n\t\t\tlogger.info(`[DRY RUN] Would execute: git merge --ff-only ${branchName}`)\n\t\t\tlogger.info(`[DRY RUN] This would merge ${commitLines.length} commit(s)`)\n\t\t\treturn\n\t\t}\n\n\t\t// Execute fast-forward merge\n\t\ttry {\n\t\t\tawait executeGitCommand(['merge', '--ff-only', branchName], { cwd: mainWorktreePath })\n\t\t\tlogger.success(`Fast-forward merge completed! Merged ${commitLines.length} commit(s).`)\n\t\t} catch (error) {\n\t\t\tthrow new Error(\n\t\t\t\t`Fast-forward merge failed: ${error instanceof Error ? error.message : String(error)}\\n\\n` +\n\t\t\t\t\t'To recover:\\n' +\n\t\t\t\t\t' 1. Check merge status: git status\\n' +\n\t\t\t\t\t' 2. Abort merge if needed: git merge --abort\\n' +\n\t\t\t\t\t' 3. Verify branch is rebased: git rebase main\\n' +\n\t\t\t\t\t' 4. Try merge again: il finish'\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * Helper: Detect conflicted files after failed rebase\n\t * @private\n\t */\n\tprivate async detectConflictedFiles(worktreePath: string): Promise<string[]> {\n\t\ttry {\n\t\t\tconst output = await executeGitCommand(['diff', '--name-only', '--diff-filter=U'], {\n\t\t\t\tcwd: worktreePath,\n\t\t\t})\n\n\t\t\treturn output\n\t\t\t\t.trim()\n\t\t\t\t.split('\\n')\n\t\t\t\t.filter((file) => file.length > 0)\n\t\t} catch {\n\t\t\t// If command fails, return empty array (might not be a conflict)\n\t\t\treturn []\n\t\t}\n\t}\n\n\t/**\n\t * Helper: Format conflict error message with manual resolution steps\n\t * @private\n\t */\n\tprivate formatConflictError(conflictedFiles: string[]): string {\n\t\tconst fileList = conflictedFiles.map((file) => ` • ${file}`).join('\\n')\n\n\t\treturn (\n\t\t\t'Rebase failed - merge conflicts detected in:\\n' +\n\t\t\tfileList +\n\t\t\t'\\n\\n' +\n\t\t\t'To resolve manually:\\n' +\n\t\t\t' 1. Fix conflicts in the files above\\n' +\n\t\t\t' 2. Stage resolved files: git add <files>\\n' +\n\t\t\t' 3. Continue rebase: git rebase --continue\\n' +\n\t\t\t' 4. Or abort rebase: git rebase --abort\\n' +\n\t\t\t' 5. Then re-run: il finish <issue-number>'\n\t\t)\n\t}\n\n\t/**\n\t * Attempt to resolve conflicts using Claude\n\t * Ports bash/merge-and-clean.sh lines 839-894\n\t *\n\t * @param worktreePath - Path to the worktree\n\t * @param conflictedFiles - List of files with conflicts\n\t * @returns true if conflicts resolved, false otherwise\n\t * @private\n\t */\n\tprivate async attemptClaudeConflictResolution(\n\t\tworktreePath: string,\n\t\tconflictedFiles: 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 conflict resolution')\n\t\t\treturn false\n\t\t}\n\n\t\tlogger.info(`Launching Claude to resolve conflicts in ${conflictedFiles.length} file(s)...`)\n\n\t\t// Hard-coded prompt matching bash script line 844\n\t\t// No templates, no complexity - just the essential instruction\n\t\tconst prompt =\n\t\t\t`Please help resolve the git rebase conflicts in this repository. ` +\n\t\t\t`Analyze the conflicted files, understand the changes from both branches, ` +\n\t\t\t`fix the conflicts, then run 'git add .' to stage the resolved files, ` +\n\t\t\t`and finally run 'git rebase --continue' to continue the rebase process. ` +\n\t\t\t`Handle the entire workflow for me.`\n\n\t\ttry {\n\t\t\t// Launch Claude interactively in current terminal\n\t\t\t// User will interact directly with Claude to resolve conflicts\n\t\t\tawait launchClaude(prompt, {\n\t\t\t\taddDir: worktreePath,\n\t\t\t\theadless: false, // Interactive - runs in current terminal with stdio: inherit\n\t\t\t})\n\n\t\t\t// After Claude interaction completes, check if conflicts resolved\n\t\t\tconst remainingConflicts = await this.detectConflictedFiles(worktreePath)\n\n\t\t\tif (remainingConflicts.length > 0) {\n\t\t\t\tlogger.warn(\n\t\t\t\t\t`Conflicts still exist in ${remainingConflicts.length} file(s) after Claude assistance`\n\t\t\t\t)\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\t// Check if rebase completed or still in progress\n\t\t\tconst rebaseInProgress = await this.isRebaseInProgress(worktreePath)\n\n\t\t\tif (rebaseInProgress) {\n\t\t\t\tlogger.warn('Rebase still in progress after Claude assistance')\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\t// Success: no conflicts, rebase completed\n\t\t\tlogger.success('Claude successfully resolved conflicts and completed rebase')\n\t\t\treturn true\n\t\t} catch (error) {\n\t\t\tlogger.warn('Claude conflict resolution 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 * Check if a git rebase is currently in progress\n\t * Checks for .git/rebase-merge or .git/rebase-apply directories\n\t * Ports bash script logic from lines 853-856\n\t *\n\t * @param worktreePath - Path to the worktree\n\t * @returns true if rebase in progress, false otherwise\n\t * @private\n\t */\n\tprivate async isRebaseInProgress(worktreePath: string): Promise<boolean> {\n\t\tconst fs = await import('node:fs/promises')\n\t\tconst path = await import('node:path')\n\n\t\tconst rebaseMergePath = path.join(worktreePath, '.git', 'rebase-merge')\n\t\tconst rebaseApplyPath = path.join(worktreePath, '.git', 'rebase-apply')\n\n\t\t// Check for rebase-merge directory\n\t\ttry {\n\t\t\tawait fs.access(rebaseMergePath)\n\t\t\treturn true\n\t\t} catch {\n\t\t\t// Directory doesn't exist, continue checking\n\t\t}\n\n\t\t// Check for rebase-apply directory\n\t\ttry {\n\t\t\tawait fs.access(rebaseApplyPath)\n\t\t\treturn true\n\t\t} catch {\n\t\t\t// Directory doesn't exist\n\t\t}\n\n\t\treturn false\n\t}\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 { logger } from '../utils/logger.js'\nimport { GitHubService } from '../lib/GitHubService.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 { NeonProvider } from '../lib/providers/NeonProvider.js'\nimport { EnvironmentManager } from '../lib/EnvironmentManager.js'\nimport { CLIIsolationManager } from '../lib/CLIIsolationManager.js'\nimport { SettingsManager } from '../lib/SettingsManager.js'\nimport { findMainWorktreePathWithSettings } from '../utils/git.js'\nimport { loadEnvIntoProcess } from '../utils/env.js'\nimport { installDependencies } from '../utils/package-manager.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?: 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 gitHubService: GitHubService\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\n\tconstructor(\n\t\tgitHubService?: GitHubService,\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) {\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\t// Dependency injection for testing\n\t\tthis.gitHubService = gitHubService ?? new GitHubService()\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}\n\n\t/**\n\t * Lazy initialization of ResourceCleanup with properly configured DatabaseManager\n\t */\n\tprivate async ensureResourceCleanup(): Promise<void> {\n\t\tif (this.resourceCleanup) {\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 = new NeonProvider({\n\t\t\tprojectId: process.env.NEON_PROJECT_ID ?? '',\n\t\t\tparentBranch: process.env.NEON_PARENT_BRANCH ?? '',\n\t\t})\n\t\tconst databaseManager = new DatabaseManager(neonProvider, environmentManager, databaseUrlEnvVarName)\n\t\tconst cliIsolationManager = new CLIIsolationManager()\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 * 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: 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: Validate based on type and get worktrees\n\t\t\tconst worktrees = await this.validateInput(parsed, input.options)\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\tconst pr = await this.gitHubService.fetchPR(parsed.number)\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\t// Pattern: /issue-(\\d+)/\n\t\tconst issuePattern = /issue-(\\d+)/\n\t\tconst issueMatch = currentDir.match(issuePattern)\n\n\t\tif (issueMatch?.[1]) {\n\t\t\tconst issueNumber = parseInt(issueMatch[1], 10)\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 branchIssueMatch = currentBranch.match(issuePattern)\n\t\tif (branchIssueMatch?.[1]) {\n\t\t\tconst issueNumber = parseInt(branchIssueMatch[1], 10)\n\t\t\tlogger.debug(\n\t\t\t\t`Auto-detected issue #${issueNumber} from branch: ${currentBranch}`\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: 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): 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// Fetch PR from GitHub\n\t\t\t\tconst pr = await this.gitHubService.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.gitHubService.fetchIssue(parsed.number)\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// 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\tparsed.number,\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\tawait this.commitManager.commitChanges(worktree.path, commitOptions)\n\n\t\t\t\tlogger.success('Changes committed successfully')\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 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)\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\tawait this.commitManager.commitChanges(worktree.path, {\n\t\t\t\t\t\tdryRun: false,\n\t\t\t\t\t\tskipVerify,\n\t\t\t\t\t\t// Do NOT pass issueNumber for PRs - no \"Fixes #\" trailer needed\n\t\t\t\t\t})\n\t\t\t\t\tlogger.success('Changes committed')\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\tconst { pushBranchToRemote } = await import('../utils/git.js')\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 * 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}\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// 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\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\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\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"],"mappings":"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","names":["path"]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
branchExists,
|
|
4
|
+
ensureRepositoryHasCommits,
|
|
5
|
+
executeGitCommand,
|
|
6
|
+
extractPRNumber,
|
|
7
|
+
findAllBranchesForIssue,
|
|
8
|
+
findMainWorktreePath,
|
|
9
|
+
findMainWorktreePathWithSettings,
|
|
10
|
+
generateWorktreePath,
|
|
11
|
+
getCurrentBranch,
|
|
12
|
+
getDefaultBranch,
|
|
13
|
+
getRepoRoot,
|
|
14
|
+
hasUncommittedChanges,
|
|
15
|
+
isEmptyRepository,
|
|
16
|
+
isPRBranch,
|
|
17
|
+
isValidGitRepo,
|
|
18
|
+
isWorktreePath,
|
|
19
|
+
parseWorktreeList,
|
|
20
|
+
pushBranchToRemote
|
|
21
|
+
} from "./chunk-JQ7VOSTC.js";
|
|
22
|
+
import "./chunk-GEHQXLEI.js";
|
|
23
|
+
export {
|
|
24
|
+
branchExists,
|
|
25
|
+
ensureRepositoryHasCommits,
|
|
26
|
+
executeGitCommand,
|
|
27
|
+
extractPRNumber,
|
|
28
|
+
findAllBranchesForIssue,
|
|
29
|
+
findMainWorktreePath,
|
|
30
|
+
findMainWorktreePathWithSettings,
|
|
31
|
+
generateWorktreePath,
|
|
32
|
+
getCurrentBranch,
|
|
33
|
+
getDefaultBranch,
|
|
34
|
+
getRepoRoot,
|
|
35
|
+
hasUncommittedChanges,
|
|
36
|
+
isEmptyRepository,
|
|
37
|
+
isPRBranch,
|
|
38
|
+
isValidGitRepo,
|
|
39
|
+
isWorktreePath,
|
|
40
|
+
parseWorktreeList,
|
|
41
|
+
pushBranchToRemote
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=git-LVRZ57GJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|