@iloom/cli 0.10.0 → 0.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +2 -2
  3. package/dist/{BranchNamingService-ECJHBB67.js → BranchNamingService-4OP6LOH6.js} +2 -2
  4. package/dist/ClaudeContextManager-ZKTUVQB2.js +14 -0
  5. package/dist/ClaudeService-TRWOYQ6O.js +13 -0
  6. package/dist/{LoomLauncher-L64HHS3T.js → LoomLauncher-FRECYMXS.js} +6 -6
  7. package/dist/{PromptTemplateManager-DULSVRRE.js → PromptTemplateManager-YOE2SIPG.js} +2 -2
  8. package/dist/README.md +2 -2
  9. package/dist/{SettingsManager-BQDQA3FK.js → SettingsManager-FNKCOZMQ.js} +2 -2
  10. package/dist/{build-5GO3XW26.js → build-VHGEMXBA.js} +6 -6
  11. package/dist/{chunk-ZW2LKWWE.js → chunk-2VEWSM34.js} +3 -3
  12. package/dist/{chunk-LXLMMXXY.js → chunk-2YZCWAVZ.js} +17 -12
  13. package/dist/chunk-2YZCWAVZ.js.map +1 -0
  14. package/dist/{chunk-UD3WJDIV.js → chunk-3F27M7ZD.js} +11 -774
  15. package/dist/chunk-3F27M7ZD.js.map +1 -0
  16. package/dist/chunk-4E7LCFUG.js +24 -0
  17. package/dist/chunk-4E7LCFUG.js.map +1 -0
  18. package/dist/{chunk-MNHZB4Z2.js → chunk-4FGEGQW4.js} +3 -3
  19. package/dist/{chunk-WY4QBK43.js → chunk-63QWFWH3.js} +2 -2
  20. package/dist/{chunk-YYAKPQBT.js → chunk-7VHJNVLF.js} +19 -9
  21. package/dist/chunk-7VHJNVLF.js.map +1 -0
  22. package/dist/chunk-BFHDVFSK.js +651 -0
  23. package/dist/chunk-BFHDVFSK.js.map +1 -0
  24. package/dist/{chunk-FB47TIJG.js → chunk-BFLMCE2U.js} +4 -23
  25. package/dist/chunk-BFLMCE2U.js.map +1 -0
  26. package/dist/{chunk-SN3SQCFK.js → chunk-BU53XIGY.js} +4 -4
  27. package/dist/{chunk-SF2P22EE.js → chunk-C6HNNJIV.js} +2 -2
  28. package/dist/{chunk-5MWV33NN.js → chunk-CVCTIDDK.js} +2 -2
  29. package/dist/{chunk-ZEWU5PZK.js → chunk-G5V75JD5.js} +2 -2
  30. package/dist/{chunk-ZHPNZC75.js → chunk-HYGUPUV5.js} +26 -21
  31. package/dist/chunk-HYGUPUV5.js.map +1 -0
  32. package/dist/{chunk-VGGST52X.js → chunk-I5T677EA.js} +2 -2
  33. package/dist/{chunk-VECNX6VX.js → chunk-KIK2ZFAL.js} +2 -2
  34. package/dist/{chunk-3D7WQM7I.js → chunk-LLHXQS3C.js} +2 -2
  35. package/dist/{chunk-Y4YZTHZE.js → chunk-LUKXJSRI.js} +2 -2
  36. package/dist/{chunk-ONQYPICO.js → chunk-PZ5WSR5Z.js} +63 -9
  37. package/dist/chunk-PZ5WSR5Z.js.map +1 -0
  38. package/dist/{chunk-J5S7DFYC.js → chunk-QFTDZ5E3.js} +2 -2
  39. package/dist/chunk-RJ3VBUFK.js +781 -0
  40. package/dist/chunk-RJ3VBUFK.js.map +1 -0
  41. package/dist/{chunk-UWGVCXRF.js → chunk-SKSYYBCU.js} +23 -1
  42. package/dist/chunk-SKSYYBCU.js.map +1 -0
  43. package/dist/{chunk-JO2LZ6EQ.js → chunk-SWSJWA2S.js} +2 -2
  44. package/dist/{chunk-4WJNIR5O.js → chunk-UUEW5KWB.js} +1 -1
  45. package/dist/chunk-UUEW5KWB.js.map +1 -0
  46. package/dist/{chunk-6EU6TCF6.js → chunk-V3SVMFDQ.js} +5 -5
  47. package/dist/{chunk-NRSWLOAZ.js → chunk-WXIM2WS7.js} +4 -4
  48. package/dist/{chunk-RYWFS37M.js → chunk-XE4BDRZD.js} +2 -2
  49. package/dist/{ignite-CGOV3TD4.js → chunk-ZGM2FE2R.js} +105 -73
  50. package/dist/chunk-ZGM2FE2R.js.map +1 -0
  51. package/dist/{claude-P3NQR6IJ.js → claude-LN7OWVNI.js} +2 -2
  52. package/dist/{cleanup-6UCPVMFG.js → cleanup-4ZM2AJDC.js} +19 -17
  53. package/dist/{cleanup-6UCPVMFG.js.map → cleanup-4ZM2AJDC.js.map} +1 -1
  54. package/dist/cli.js +167 -614
  55. package/dist/cli.js.map +1 -1
  56. package/dist/{commit-L3EPY5QG.js → commit-4CFLXRZ3.js} +12 -10
  57. package/dist/commit-4CFLXRZ3.js.map +1 -0
  58. package/dist/{compile-ZS4HYRX5.js → compile-7ALJHZ4N.js} +6 -6
  59. package/dist/{contribute-ORDDQGSL.js → contribute-5GKLK3BQ.js} +3 -3
  60. package/dist/{dev-server-FYZ2AQIH.js → dev-server-7SMIB7OF.js} +8 -8
  61. package/dist/{feedback-TMBXSCM5.js → feedback-EZWF5CAL.js} +10 -8
  62. package/dist/{feedback-TMBXSCM5.js.map → feedback-EZWF5CAL.js.map} +1 -1
  63. package/dist/{git-ET64COO3.js → git-GTLKAZRJ.js} +3 -3
  64. package/dist/ignite-MQETGFNA.js +34 -0
  65. package/dist/ignite-MQETGFNA.js.map +1 -0
  66. package/dist/index.d.ts +113 -18
  67. package/dist/index.js +180 -15
  68. package/dist/index.js.map +1 -1
  69. package/dist/{init-GFQ5W7GK.js → init-ZB2RITW6.js} +8 -8
  70. package/dist/install-deps-RLSGSHH7.js +43 -0
  71. package/dist/install-deps-RLSGSHH7.js.map +1 -0
  72. package/dist/{issues-T4ZZSPEG.js → issues-4UUAQ5K6.js} +3 -3
  73. package/dist/{lint-6TQXDZ3T.js → lint-AAN2NZWG.js} +6 -6
  74. package/dist/mcp/harness-server.js +140 -0
  75. package/dist/mcp/harness-server.js.map +1 -0
  76. package/dist/mcp/issue-management-server.js +140 -18
  77. package/dist/mcp/issue-management-server.js.map +1 -1
  78. package/dist/{open-5QZGXQRF.js → open-FXWW3VI4.js} +8 -8
  79. package/dist/{plan-U7ZQWLFY.js → plan-D3KSN5MU.js} +338 -36
  80. package/dist/plan-D3KSN5MU.js.map +1 -0
  81. package/dist/prompts/CLAUDE.md +2 -2
  82. package/dist/prompts/init-prompt.txt +102 -27
  83. package/dist/prompts/issue-prompt.txt +46 -0
  84. package/dist/prompts/plan-prompt.txt +59 -19
  85. package/dist/prompts/swarm-orchestrator-prompt.txt +121 -80
  86. package/dist/{rebase-DWIB77KV.js → rebase-62FDLIH4.js} +17 -8
  87. package/dist/rebase-62FDLIH4.js.map +1 -0
  88. package/dist/{recap-MX63HAKV.js → recap-OMBOKJST.js} +6 -6
  89. package/dist/{run-O3TFNQFC.js → run-BBXLRIZB.js} +8 -8
  90. package/dist/schema/settings.schema.json +36 -2
  91. package/dist/{shell-G6VC2CYR.js → shell-RF7LTND5.js} +5 -5
  92. package/dist/{summary-FWHAX55O.js → summary-YZI25KW4.js} +9 -9
  93. package/dist/{test-F7JNJZYP.js → test-SGO6I5Z7.js} +6 -6
  94. package/dist/{test-git-BTAOIUE2.js → test-git-XM4TM65W.js} +3 -3
  95. package/dist/{test-jira-CHYNV33F.js → test-jira-LDTOYFSD.js} +3 -3
  96. package/dist/{test-prefix-Q6TFSU6F.js → test-prefix-GBO37XCN.js} +3 -3
  97. package/dist/{test-webserver-EONCG7E7.js → test-webserver-NZ3JTVLL.js} +5 -5
  98. package/dist/{vscode-VA5X4P25.js → vscode-6XUGHJKL.js} +5 -5
  99. package/package.json +1 -1
  100. package/dist/ClaudeContextManager-QXX6ZFST.js +0 -14
  101. package/dist/ClaudeService-NJNK2SUH.js +0 -13
  102. package/dist/chunk-4WJNIR5O.js.map +0 -1
  103. package/dist/chunk-FB47TIJG.js.map +0 -1
  104. package/dist/chunk-LXLMMXXY.js.map +0 -1
  105. package/dist/chunk-ONQYPICO.js.map +0 -1
  106. package/dist/chunk-UD3WJDIV.js.map +0 -1
  107. package/dist/chunk-UVD4CZKS.js +0 -101
  108. package/dist/chunk-UVD4CZKS.js.map +0 -1
  109. package/dist/chunk-UWGVCXRF.js.map +0 -1
  110. package/dist/chunk-YYAKPQBT.js.map +0 -1
  111. package/dist/chunk-ZHPNZC75.js.map +0 -1
  112. package/dist/commit-L3EPY5QG.js.map +0 -1
  113. package/dist/ignite-CGOV3TD4.js.map +0 -1
  114. package/dist/plan-U7ZQWLFY.js.map +0 -1
  115. package/dist/rebase-DWIB77KV.js.map +0 -1
  116. /package/dist/{BranchNamingService-ECJHBB67.js.map → BranchNamingService-4OP6LOH6.js.map} +0 -0
  117. /package/dist/{ClaudeContextManager-QXX6ZFST.js.map → ClaudeContextManager-ZKTUVQB2.js.map} +0 -0
  118. /package/dist/{ClaudeService-NJNK2SUH.js.map → ClaudeService-TRWOYQ6O.js.map} +0 -0
  119. /package/dist/{LoomLauncher-L64HHS3T.js.map → LoomLauncher-FRECYMXS.js.map} +0 -0
  120. /package/dist/{PromptTemplateManager-DULSVRRE.js.map → PromptTemplateManager-YOE2SIPG.js.map} +0 -0
  121. /package/dist/{SettingsManager-BQDQA3FK.js.map → SettingsManager-FNKCOZMQ.js.map} +0 -0
  122. /package/dist/{build-5GO3XW26.js.map → build-VHGEMXBA.js.map} +0 -0
  123. /package/dist/{chunk-ZW2LKWWE.js.map → chunk-2VEWSM34.js.map} +0 -0
  124. /package/dist/{chunk-MNHZB4Z2.js.map → chunk-4FGEGQW4.js.map} +0 -0
  125. /package/dist/{chunk-WY4QBK43.js.map → chunk-63QWFWH3.js.map} +0 -0
  126. /package/dist/{chunk-SN3SQCFK.js.map → chunk-BU53XIGY.js.map} +0 -0
  127. /package/dist/{chunk-SF2P22EE.js.map → chunk-C6HNNJIV.js.map} +0 -0
  128. /package/dist/{chunk-5MWV33NN.js.map → chunk-CVCTIDDK.js.map} +0 -0
  129. /package/dist/{chunk-ZEWU5PZK.js.map → chunk-G5V75JD5.js.map} +0 -0
  130. /package/dist/{chunk-VGGST52X.js.map → chunk-I5T677EA.js.map} +0 -0
  131. /package/dist/{chunk-VECNX6VX.js.map → chunk-KIK2ZFAL.js.map} +0 -0
  132. /package/dist/{chunk-3D7WQM7I.js.map → chunk-LLHXQS3C.js.map} +0 -0
  133. /package/dist/{chunk-Y4YZTHZE.js.map → chunk-LUKXJSRI.js.map} +0 -0
  134. /package/dist/{chunk-J5S7DFYC.js.map → chunk-QFTDZ5E3.js.map} +0 -0
  135. /package/dist/{chunk-JO2LZ6EQ.js.map → chunk-SWSJWA2S.js.map} +0 -0
  136. /package/dist/{chunk-6EU6TCF6.js.map → chunk-V3SVMFDQ.js.map} +0 -0
  137. /package/dist/{chunk-NRSWLOAZ.js.map → chunk-WXIM2WS7.js.map} +0 -0
  138. /package/dist/{chunk-RYWFS37M.js.map → chunk-XE4BDRZD.js.map} +0 -0
  139. /package/dist/{claude-P3NQR6IJ.js.map → claude-LN7OWVNI.js.map} +0 -0
  140. /package/dist/{compile-ZS4HYRX5.js.map → compile-7ALJHZ4N.js.map} +0 -0
  141. /package/dist/{contribute-ORDDQGSL.js.map → contribute-5GKLK3BQ.js.map} +0 -0
  142. /package/dist/{dev-server-FYZ2AQIH.js.map → dev-server-7SMIB7OF.js.map} +0 -0
  143. /package/dist/{git-ET64COO3.js.map → git-GTLKAZRJ.js.map} +0 -0
  144. /package/dist/{init-GFQ5W7GK.js.map → init-ZB2RITW6.js.map} +0 -0
  145. /package/dist/{issues-T4ZZSPEG.js.map → issues-4UUAQ5K6.js.map} +0 -0
  146. /package/dist/{lint-6TQXDZ3T.js.map → lint-AAN2NZWG.js.map} +0 -0
  147. /package/dist/{open-5QZGXQRF.js.map → open-FXWW3VI4.js.map} +0 -0
  148. /package/dist/{recap-MX63HAKV.js.map → recap-OMBOKJST.js.map} +0 -0
  149. /package/dist/{run-O3TFNQFC.js.map → run-BBXLRIZB.js.map} +0 -0
  150. /package/dist/{shell-G6VC2CYR.js.map → shell-RF7LTND5.js.map} +0 -0
  151. /package/dist/{summary-FWHAX55O.js.map → summary-YZI25KW4.js.map} +0 -0
  152. /package/dist/{test-F7JNJZYP.js.map → test-SGO6I5Z7.js.map} +0 -0
  153. /package/dist/{test-git-BTAOIUE2.js.map → test-git-XM4TM65W.js.map} +0 -0
  154. /package/dist/{test-jira-CHYNV33F.js.map → test-jira-LDTOYFSD.js.map} +0 -0
  155. /package/dist/{test-prefix-Q6TFSU6F.js.map → test-prefix-GBO37XCN.js.map} +0 -0
  156. /package/dist/{test-webserver-EONCG7E7.js.map → test-webserver-NZ3JTVLL.js.map} +0 -0
  157. /package/dist/{vscode-VA5X4P25.js.map → vscode-6XUGHJKL.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/ResourceCleanup.ts"],"sourcesContent":["import path from 'path'\nimport { GitWorktreeManager } from './GitWorktreeManager.js'\nimport { DatabaseManager } from './DatabaseManager.js'\nimport { ProcessManager } from './process/ProcessManager.js'\nimport { CLIIsolationManager } from './CLIIsolationManager.js'\nimport { SettingsManager } from './SettingsManager.js'\nimport { MetadataManager } from './MetadataManager.js'\nimport { getLogger } from '../utils/logger-context.js'\nimport { hasUncommittedChanges, executeGitCommand, findMainWorktreePathWithSettings, extractIssueNumber, isBranchMergedIntoMain, checkRemoteBranchStatus, getMergeTargetBranch, findWorktreeForBranch, type RemoteBranchStatus } from '../utils/git.js'\nimport { calculatePortFromIdentifier } from '../utils/port.js'\nimport { archiveRecap } from '../utils/recap-archiver.js'\n\nimport type {\n\tResourceCleanupOptions,\n\tCleanupResult,\n\tOperationResult,\n\tSafetyCheck,\n\tBranchDeleteOptions,\n} from '../types/cleanup.js'\nimport type { GitWorktree } from '../types/worktree.js'\nimport type { ParsedInput } from '../commands/start.js'\n\n/**\n * Manages resource cleanup for worktrees\n * Provides shared cleanup functionality for finish and cleanup commands\n */\nexport class ResourceCleanup {\n\tprivate settingsManager: SettingsManager\n\tprivate metadataManager: MetadataManager\n\n\tconstructor(\n\t\tprivate gitWorktree: GitWorktreeManager,\n\t\tprivate processManager: ProcessManager,\n\t\tprivate database?: DatabaseManager,\n\t\tprivate cliIsolation?: CLIIsolationManager,\n\t\tsettingsManager?: SettingsManager\n\t) {\n\t\tthis.settingsManager = settingsManager ?? new SettingsManager()\n\t\tthis.metadataManager = new MetadataManager()\n\t}\n\n\t/**\n\t * Cleanup a worktree and associated resources\n\t * Main orchestration method\n\t *\n\t * @param parsed - ParsedInput from IdentifierParser with type information\n\t * @param options - Cleanup options\n\t */\n\tasync cleanupWorktree(\n\t\tparsed: ParsedInput,\n\t\toptions: ResourceCleanupOptions = {}\n\t): Promise<CleanupResult> {\n\t\tconst operations: OperationResult[] = []\n\t\tconst errors: Error[] = []\n\n\t\tconst displayIdentifier = parsed.branchName ?? parsed.number?.toString() ?? parsed.originalInput\n\t\tgetLogger().info(`Starting cleanup for: ${displayIdentifier}`)\n\n\t\t// Extract number from ParsedInput for port calculation\n\t\tconst number = parsed.number\n\n\t\t// Step 1: Terminate dev server if applicable\n\t\tif (number !== undefined) {\n\t\t\t// Load settings to get basePort\n\t\t\tconst settings = await this.settingsManager.loadSettings()\n\t\t\tconst basePort = settings?.capabilities?.web?.basePort ?? 3000\n\t\t\tconst port = calculatePortFromIdentifier(number, basePort)\n\n\t\t\tif (options.dryRun) {\n\t\t\t\toperations.push({\n\t\t\t\t\ttype: 'dev-server',\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tmessage: `[DRY RUN] Would check for dev server on port ${port}`,\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tconst terminated = await this.terminateDevServer(port)\n\t\t\t\t\toperations.push({\n\t\t\t\t\t\ttype: 'dev-server',\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\tmessage: terminated\n\t\t\t\t\t\t\t? `Dev server on port ${port} terminated`\n\t\t\t\t\t\t\t: `No dev server running on port ${port}`,\n\t\t\t\t\t})\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst err = error instanceof Error ? error : new Error('Unknown error')\n\t\t\t\t\terrors.push(err)\n\t\t\t\t\toperations.push({\n\t\t\t\t\t\ttype: 'dev-server',\n\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\tmessage: `Failed to terminate dev server`,\n\t\t\t\t\t\terror: err.message,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Step 2: Find worktree using specific methods based on type\n\t\tlet worktree: GitWorktree | null = null\n\t\ttry {\n\t\t\t// Use pre-resolved worktree if provided (skips the search step)\n\t\t\tif (options.worktree) {\n\t\t\t\tworktree = {\n\t\t\t\t\tpath: options.worktree.path,\n\t\t\t\t\tbranch: options.worktree.branch,\n\t\t\t\t\tcommit: '',\n\t\t\t\t\tbare: false,\n\t\t\t\t\tdetached: false,\n\t\t\t\t\tlocked: false,\n\t\t\t\t}\n\t\t\t\tgetLogger().debug(`Using pre-resolved worktree: path=\"${worktree.path}\", branch=\"${worktree.branch}\"`)\n\t\t\t} else {\n\t\t\t\t// Use specific finding methods based on parsed type for precision\n\t\t\t\tif (parsed.type === 'pr' && parsed.number !== undefined) {\n\t\t\t\t\t// For PRs, ensure the number is numeric (PRs are always numeric per GitHub)\n\t\t\t\t\tconst prNumber = typeof parsed.number === 'number' ? parsed.number : Number(parsed.number)\n\t\t\t\t\tif (isNaN(prNumber) || !isFinite(prNumber)) {\n\t\t\t\t\t\tthrow new Error(`Invalid PR number: ${parsed.number}. PR numbers must be numeric.`)\n\t\t\t\t\t}\n\t\t\t\t\t// For PRs, pass empty string for branchName since we're detecting from path pattern\n\t\t\t\t\tworktree = await this.gitWorktree.findWorktreeForPR(prNumber, '')\n\t\t\t\t} else if (parsed.type === 'issue' && parsed.number !== undefined) {\n\t\t\t\t\tworktree = await this.gitWorktree.findWorktreeForIssue(parsed.number)\n\t\t\t\t} else if (parsed.type === 'branch' && parsed.branchName) {\n\t\t\t\t\tworktree = await this.gitWorktree.findWorktreeForBranch(parsed.branchName)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!worktree) {\n\t\t\t\tthrow new Error(`No worktree found for identifier: ${displayIdentifier}`)\n\t\t\t}\n\n\t\t\tgetLogger().debug(`Found worktree: path=\"${worktree.path}\", branch=\"${worktree.branch}\"`)\n\t\t} catch (error) {\n\t\t\tconst err = error instanceof Error ? error : new Error('Unknown error')\n\t\t\terrors.push(err)\n\n\t\t\treturn {\n\t\t\t\tidentifier: displayIdentifier,\n\t\t\t\tsuccess: false,\n\t\t\t\toperations,\n\t\t\t\terrors,\n\t\t\t\trollbackRequired: false,\n\t\t\t}\n\t\t}\n\n\t\t// Step 2.5: Validate safety before proceeding with cleanup (unless force flag is set)\n\t\t// Check merge safety if: deleteBranch is true AND checkMergeSafety is not explicitly false\n\t\t// This prevents the scenario where worktree is deleted but branch deletion fails\n\t\tlet safetyCheckPassed = false\n\t\tif (!options.force) {\n\t\t\tconst shouldCheckMergeSafety = options.checkMergeSafety ?? (options.deleteBranch === true)\n\t\t\tconst shouldCheckRemoteBranch = options.checkRemoteBranch ?? false\n\t\t\tconst safety = await this.validateWorktreeSafety(worktree, parsed.originalInput, shouldCheckMergeSafety, shouldCheckRemoteBranch)\n\n\t\t\tif (!safety.isSafe) {\n\t\t\t\t// Format blocker messages for error output\n\t\t\t\tconst blockerMessage = safety.blockers.join('\\n\\n')\n\t\t\t\tthrow new Error(`Cannot cleanup:\\n\\n${blockerMessage}`)\n\t\t\t}\n\n\t\t\tsafetyCheckPassed = true\n\n\t\t\t// Log warnings if any\n\t\t\tif (safety.warnings.length > 0) {\n\t\t\t\tsafety.warnings.forEach(warning => {\n\t\t\t\t\tgetLogger().warn(warning)\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\t// Step 3: Pre-fetch database configuration before worktree removal\n\t\t// This config is used AFTER worktree deletion when env file no longer exists\n\t\tlet databaseConfig: { shouldCleanup: boolean; envFilePath: string } | null = null\n\t\tif (!options.keepDatabase && worktree) {\n\t\t\tconst envFilePath = path.join(worktree.path, '.env')\n\t\t\ttry {\n\t\t\t\t// Pre-check if database cleanup should happen by reading .env file now\n\t\t\t\tconst shouldCleanup = this.database\n\t\t\t\t\t? await this.database.shouldUseDatabaseBranching(envFilePath)\n\t\t\t\t\t: false\n\t\t\t\tdatabaseConfig = { shouldCleanup, envFilePath }\n\t\t\t} catch (error) {\n\t\t\t\t// If we can't read the config, we'll skip database cleanup\n\t\t\tgetLogger().warn(\n\t\t\t\t\t`Failed to read database config from ${envFilePath}, skipping database cleanup: ${\n\t\t\t\t\t\terror instanceof Error ? error.message : String(error)\n\t\t\t\t\t}`\n\t\t\t\t)\n\t\t\t\tdatabaseConfig = { shouldCleanup: false, envFilePath }\n\t\t\t}\n\t\t}\n\n\t\t// Step 3.5: Find main worktree path before deletion (needed for branch and database operations)\n\t\tlet mainWorktreePath: string | null = null\n\t\tif (!options.dryRun) {\n\t\t\ttry {\n\t\t\t\tmainWorktreePath = await findMainWorktreePathWithSettings(worktree.path, this.settingsManager)\n\t\t\t} catch (error) {\n\t\t\tgetLogger().warn(\n\t\t\t\t\t`Failed to find main worktree path: ${error instanceof Error ? error.message : String(error)}`\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\n\t\t// Step 3.6: Pre-fetch merge target branch before worktree deletion\n\t\t// This is needed because deleteBranch() needs to know the merge target (parent branch for child looms)\n\t\t// but the worktree metadata won't be readable after deletion in Step 4\n\t\tlet mergeTargetBranch: string | null = null\n\t\tif (options.deleteBranch && worktree && !options.dryRun) {\n\t\t\ttry {\n\t\t\t\tmergeTargetBranch = await getMergeTargetBranch(worktree.path, {\n\t\t\t\t\tsettingsManager: this.settingsManager,\n\t\t\t\t\tmetadataManager: this.metadataManager,\n\t\t\t\t})\n\t\t\t\tgetLogger().debug(`Pre-fetched merge target branch: ${mergeTargetBranch}`)\n\t\t\t} catch (error) {\n\t\t\t\tgetLogger().warn(\n\t\t\t\t\t`Failed to pre-fetch merge target branch: ${error instanceof Error ? error.message : String(error)}`\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\n\t\t// Step 4: Remove worktree\n\t\tif (options.dryRun) {\n\t\t\toperations.push({\n\t\t\t\ttype: 'worktree',\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage: `[DRY RUN] Would remove worktree: ${worktree.path}`,\n\t\t\t})\n\t\t} else {\n\t\t\ttry {\n\t\t\t\tconst worktreeOptions: { force?: boolean; removeDirectory: true; removeBranch: false } =\n\t\t\t\t\t{\n\t\t\t\t\t\tremoveDirectory: true,\n\t\t\t\t\t\tremoveBranch: false, // Handle branch separately\n\t\t\t\t\t}\n\t\t\t\tif (options.force !== undefined) {\n\t\t\t\t\tworktreeOptions.force = options.force\n\t\t\t\t}\n\t\t\t\tawait this.gitWorktree.removeWorktree(worktree.path, worktreeOptions)\n\n\t\t\t\toperations.push({\n\t\t\t\t\ttype: 'worktree',\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tmessage: `Worktree removed: ${worktree.path}`,\n\t\t\t\t})\n\t\t\t} catch (error) {\n\t\t\t\tconst err = error instanceof Error ? error : new Error('Unknown error')\n\t\t\t\terrors.push(err)\n\t\t\t\toperations.push({\n\t\t\t\t\ttype: 'worktree',\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\tmessage: `Failed to remove worktree`,\n\t\t\t\t\terror: err.message,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\t// Step 4.5: Archive recap file\n\t\tif (worktree) {\n\t\t\tif (options.dryRun) {\n\t\t\t\toperations.push({\n\t\t\t\t\ttype: 'recap',\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tmessage: `[DRY RUN] Would archive recap file for: ${worktree.path}`,\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tawait archiveRecap(worktree.path)\n\t\t\t\t\toperations.push({\n\t\t\t\t\t\ttype: 'recap',\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\tmessage: `Recap file archived`,\n\t\t\t\t\t})\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// Non-fatal: log warning but don't add to errors\n\t\t\t\t\tconst err = error instanceof Error ? error : new Error('Unknown error')\n\t\t\t\t\tgetLogger().warn(`Recap archival failed: ${err.message}`)\n\t\t\t\t\toperations.push({\n\t\t\t\t\t\ttype: 'recap',\n\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\tmessage: 'Recap archival failed (non-fatal)',\n\t\t\t\t\t\terror: err.message,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Step 5: Delete branch if requested\n\t\tif (options.deleteBranch && worktree) {\n\t\t\tif (options.dryRun) {\n\t\t\t\toperations.push({\n\t\t\t\t\ttype: 'branch',\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tmessage: `[DRY RUN] Would delete branch: ${worktree.branch}`,\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tconst branchOptions: BranchDeleteOptions = {\n\t\t\t\t\t\tdryRun: false,\n\t\t\t\t\t\tsafetyVerified: safetyCheckPassed,\n\t\t\t\t\t}\n\t\t\t\t\t// Pass pre-fetched merge target (fetched in Step 3.6 before worktree deletion)\n\t\t\t\t\tif (mergeTargetBranch !== null) {\n\t\t\t\t\t\tbranchOptions.mergeTargetBranch = mergeTargetBranch\n\t\t\t\t\t}\n\t\t\t\t\tif (options.force !== undefined) {\n\t\t\t\t\t\tbranchOptions.force = options.force\n\t\t\t\t\t}\n\t\t\t\t\t// Pass main worktree path to ensure we can execute git commands\n\t\t\t\t\tawait this.deleteBranch(worktree.branch, branchOptions, mainWorktreePath ?? undefined)\n\n\t\t\t\t\toperations.push({\n\t\t\t\t\t\ttype: 'branch',\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\tmessage: `Branch deleted: ${worktree.branch}`,\n\t\t\t\t\t})\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst err = error instanceof Error ? error : new Error('Unknown error')\n\t\t\t\t\terrors.push(err)\n\t\t\t\t\toperations.push({\n\t\t\t\t\t\ttype: 'branch',\n\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\tmessage: `Failed to delete branch`,\n\t\t\t\t\t\terror: err.message,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Step 5.5: Cleanup CLI symlinks if CLI isolation is available\n\t\t// Derive identifier from parsed input (number for issue/PR, branchName for branch)\n\t\tconst cliIdentifier = parsed.number ?? parsed.branchName\n\t\tif (this.cliIsolation && cliIdentifier !== undefined) {\n\t\t\tif (options.dryRun) {\n\t\t\t\toperations.push({\n\t\t\t\t\ttype: 'cli-symlinks',\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tmessage: `[DRY RUN] Would cleanup CLI symlinks for: ${cliIdentifier}`,\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tconst removed = await this.cliIsolation.cleanupVersionedExecutables(cliIdentifier)\n\t\t\t\t\toperations.push({\n\t\t\t\t\t\ttype: 'cli-symlinks',\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\tmessage: removed.length > 0\n\t\t\t\t\t\t\t? `CLI symlinks removed: ${removed.length}`\n\t\t\t\t\t\t\t: 'No CLI symlinks to cleanup',\n\t\t\t\t\t})\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// Log warning but don't fail\n\t\t\t\t\tconst err = error instanceof Error ? error : new Error('Unknown error')\n\t\t\t\t\terrors.push(err)\n\t\t\t\tgetLogger().warn(\n\t\t\t\t\t\t`CLI symlink cleanup failed: ${err.message}`\n\t\t\t\t\t)\n\t\t\t\t\toperations.push({\n\t\t\t\t\t\ttype: 'cli-symlinks',\n\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\tmessage: 'CLI symlink cleanup failed (non-fatal)',\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Step 6: Cleanup database after worktree and branch removal (using pre-read config)\n\t\tif (databaseConfig && worktree) {\n\t\t\tif (options.dryRun) {\n\t\t\t\toperations.push({\n\t\t\t\t\ttype: 'database',\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tmessage: `[DRY RUN] Would cleanup database branch for: ${worktree.branch}`,\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tif (databaseConfig.shouldCleanup && this.database) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Call database deletion with pre-fetched shouldCleanup value and main worktree path\n\t\t\t\t\t\t\t// This avoids reading the already-deleted env file and running commands from deleted directories\n\t\t\t\t\t\t\tconst deletionResult = await this.database.deleteBranchIfConfigured(\n\t\t\t\t\t\t\t\tworktree.branch,\n\t\t\t\t\t\t\t\tdatabaseConfig.shouldCleanup,\n\t\t\t\t\t\t\t\tfalse, // isPreview\n\t\t\t\t\t\t\t\tmainWorktreePath ?? undefined\n\t\t\t\t\t\t\t)\n\n\t\t\t\t\t\t\t// Create operation result based on what actually happened\n\t\t\t\t\t\t\tif (deletionResult.deleted) {\n\t\t\t\t\t\t\t\t// Branch was actually deleted\n\t\t\t\t\t\t\tgetLogger().info(`Database branch deleted: ${worktree.branch}`)\n\t\t\t\t\t\t\t\toperations.push({\n\t\t\t\t\t\t\t\t\ttype: 'database',\n\t\t\t\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\t\t\t\tmessage: `Database branch deleted`,\n\t\t\t\t\t\t\t\t\tdeleted: true,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t} else if (deletionResult.notFound) {\n\t\t\t\t\t\t\t\t// Branch didn't exist - not an error, just nothing to delete\n\t\t\t\t\t\t\tgetLogger().debug(`No database branch found for: ${worktree.branch}`)\n\t\t\t\t\t\t\t\toperations.push({\n\t\t\t\t\t\t\t\t\ttype: 'database',\n\t\t\t\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\t\t\t\tmessage: `No database branch found (skipped)`,\n\t\t\t\t\t\t\t\t\tdeleted: false,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t} else if (deletionResult.userDeclined) {\n\t\t\t\t\t\t\t\t// User declined preview database deletion\n\t\t\t\t\t\t\tgetLogger().info('Preview database deletion declined by user')\n\t\t\t\t\t\t\t\toperations.push({\n\t\t\t\t\t\t\t\t\ttype: 'database',\n\t\t\t\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\t\t\t\tmessage: `Database cleanup skipped (user declined)`,\n\t\t\t\t\t\t\t\t\tdeleted: false,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t} else if (!deletionResult.success) {\n\t\t\t\t\t\t\t\t// Deletion failed with error\n\t\t\t\t\t\t\t\tconst errorMsg = deletionResult.error ?? 'Unknown error'\n\t\t\t\t\t\t\t\terrors.push(new Error(errorMsg))\n\t\t\t\t\t\t\tgetLogger().warn(`Database cleanup failed: ${errorMsg}`)\n\t\t\t\t\t\t\t\toperations.push({\n\t\t\t\t\t\t\t\t\ttype: 'database',\n\t\t\t\t\t\t\t\t\tsuccess: false, // Non-fatal, but report error\n\t\t\t\t\t\t\t\t\tmessage: `Database cleanup failed`,\n\t\t\t\t\t\t\t\t\terror: errorMsg,\n\t\t\t\t\t\t\t\t\tdeleted: false,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// Unexpected state - log for debugging\n\t\t\t\t\t\t\t\terrors.push(new Error('Database cleanup in an unknown state'))\n\t\t\t\t\t\t\tgetLogger().warn('Database deletion returned unexpected result state')\n\t\t\t\t\t\t\t\toperations.push({\n\t\t\t\t\t\t\t\t\ttype: 'database',\n\t\t\t\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\t\t\t\tmessage: `Database cleanup in an unknown state`,\n\t\t\t\t\t\t\t\t\tdeleted: false,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\t// Unexpected exception (shouldn't happen with result object pattern)\n\t\t\t\t\t\t\terrors.push(error instanceof Error ? error : new Error(String(error)))\n\t\t\t\t\t\tgetLogger().warn(\n\t\t\t\t\t\t\t\t`Unexpected database cleanup exception: ${error instanceof Error ? error.message : String(error)}`\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\toperations.push({\n\t\t\t\t\t\t\t\ttype: 'database',\n\t\t\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\t\t\tmessage: `Database cleanup failed`,\n\t\t\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t\t\t\tdeleted: false,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Database manager not available or not configured\n\t\t\t\t\t\toperations.push({\n\t\t\t\t\t\t\ttype: 'database',\n\t\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\t\tmessage: `Database cleanup skipped (not available)`,\n\t\t\t\t\t\t\tdeleted: false,\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// This catch block is for any unexpected errors in the outer logic\n\t\t\t\t\tconst err = error instanceof Error ? error : new Error('Unknown error')\n\t\t\t\t\terrors.push(err)\n\t\t\t\t\toperations.push({\n\t\t\t\t\t\ttype: 'database',\n\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\tmessage: `Database cleanup failed`,\n\t\t\t\t\t\terror: err.message,\n\t\t\t\t\t\tdeleted: false,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Step 7: Delete or archive metadata file\n\t\tif (worktree) {\n\t\t\tif (options.dryRun) {\n\t\t\t\tconst action = options.archive ? 'archive' : 'delete'\n\t\t\t\toperations.push({\n\t\t\t\t\ttype: 'metadata',\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tmessage: `[DRY RUN] Would ${action} metadata for worktree: ${worktree.path}`,\n\t\t\t\t})\n\t\t\t} else if (options.archive) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.metadataManager.archiveMetadata(worktree.path)\n\t\t\t\t\tgetLogger().info(`Metadata archived for worktree: ${worktree.path}`)\n\t\t\t\t\toperations.push({\n\t\t\t\t\t\ttype: 'metadata',\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\tmessage: 'Metadata archived',\n\t\t\t\t\t})\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst err = error instanceof Error ? error : new Error(String(error))\n\t\t\t\t\terrors.push(err)\n\t\t\t\t\tgetLogger().warn(`Metadata archival failed: ${err.message}`)\n\t\t\t\t\toperations.push({\n\t\t\t\t\t\ttype: 'metadata',\n\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\tmessage: 'Metadata archival failed (non-fatal)',\n\t\t\t\t\t\terror: err.message,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.metadataManager.deleteMetadata(worktree.path)\n\t\t\t\t\tgetLogger().info(`Metadata deleted for worktree: ${worktree.path}`)\n\t\t\t\t\toperations.push({\n\t\t\t\t\t\ttype: 'metadata',\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\tmessage: 'Metadata deleted',\n\t\t\t\t\t})\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst err = error instanceof Error ? error : new Error(String(error))\n\t\t\t\t\terrors.push(err)\n\t\t\t\t\tgetLogger().warn(`Metadata deletion failed: ${err.message}`)\n\t\t\t\t\toperations.push({\n\t\t\t\t\t\ttype: 'metadata',\n\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\tmessage: 'Metadata deletion failed (non-fatal)',\n\t\t\t\t\t\terror: err.message,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Calculate overall success\n\t\tconst success = errors.length === 0\n\n\t\treturn {\n\t\t\tidentifier: displayIdentifier,\n\t\t\tbranchName: worktree?.branch,\n\t\t\tsuccess,\n\t\t\toperations,\n\t\t\terrors,\n\t\t\trollbackRequired: false, // Cleanup operations are generally not reversible\n\t\t}\n\t}\n\n\t/**\n\t * Terminate dev server on specified port\n\t */\n\tasync terminateDevServer(port: number): Promise<boolean> {\n\tgetLogger().debug(`Checking for dev server on port ${port}`)\n\n\t\tconst processInfo = await this.processManager.detectDevServer(port)\n\n\t\tif (!processInfo) {\n\t\tgetLogger().debug(`No process found on port ${port}`)\n\t\t\treturn false\n\t\t}\n\n\t\tif (!processInfo.isDevServer) {\n\t\tgetLogger().warn(\n\t\t\t\t`Process on port ${port} (${processInfo.name}) doesn't appear to be a dev server, skipping`\n\t\t\t)\n\t\t\treturn false\n\t\t}\n\n\tgetLogger().info(`Terminating dev server: ${processInfo.name} (PID: ${processInfo.pid})`)\n\n\t\tawait this.processManager.terminateProcess(processInfo.pid)\n\n\t\t// Verify termination\n\t\tconst isFree = await this.processManager.verifyPortFree(port)\n\t\tif (!isFree) {\n\t\t\tthrow new Error(`Dev server may still be running on port ${port}`)\n\t\t}\n\n\t\treturn true\n\t}\n\n\t/**\n\t * Delete a Git branch with safety checks\n\t *\n\t * @param branchName - Name of the branch to delete\n\t * @param options - Delete options (force, dryRun)\n\t * @param cwd - Working directory to execute git command from (defaults to finding main worktree)\n\t */\n\tasync deleteBranch(\n\t\tbranchName: string,\n\t\toptions: BranchDeleteOptions = {},\n\t\tcwd?: string\n\t): Promise<boolean> {\n\t\t// Get protected branches list from centralized method\n\t\tconst protectedBranches = await this.settingsManager.getProtectedBranches(cwd)\n\n\t\t// Check for protected branches\n\t\tif (protectedBranches.includes(branchName)) {\n\t\t\tthrow new Error(`Cannot delete protected branch: ${branchName}`)\n\t\t}\n\n\t\t// Use provided cwd, or find main worktree path as fallback\n\t\t// This ensures we're not running git commands from a deleted directory\n\t\tconst workingDir = cwd ?? await findMainWorktreePathWithSettings(undefined, this.settingsManager)\n\n\t\t// Check if branch exists before attempting deletion (idempotent behavior)\n\t\ttry {\n\t\t\tawait executeGitCommand(['rev-parse', '--verify', `refs/heads/${branchName}`], {\n\t\t\t\tcwd: workingDir\n\t\t\t})\n\t\t} catch {\n\t\t\t// Branch doesn't exist - already deleted, return success\n\t\tgetLogger().debug(`Branch ${branchName} does not exist, skipping deletion`)\n\t\t\treturn true\n\t\t}\n\n\t\tif (options.dryRun) {\n\t\tgetLogger().info(`[DRY RUN] Would delete branch: ${branchName}`)\n\t\t\treturn true\n\t\t}\n\n\t\t// Execute git branch deletion\n\t\t// deleteCwd is declared outside try so it's accessible in the catch block for safetyVerified retry\n\t\tlet deleteCwd = workingDir // Default: main worktree\n\t\ttry {\n\t\t\t// Determine the correct delete flag and working directory\n\t\t\tlet deleteFlag = '-d' // Default: safe delete\n\n\t\t\tif (options.force) {\n\t\t\t\t// User explicitly requested force delete\n\t\t\t\tdeleteFlag = '-D'\n\t\t\t} else if (options.mergeTargetBranch) {\n\t\t\t\t// Use pre-fetched merge target (from Step 3.6, fetched before worktree deletion)\n\t\t\t\t// For child looms, git branch -d checks against HEAD, which may not be the correct target\n\t\t\t\t// Instead of using -D (force), we run git branch -d from the worktree where the\n\t\t\t\t// parent branch is checked out. This lets git do its own safety verification.\n\t\t\t\tconst mergeTarget = options.mergeTargetBranch\n\n\t\t\t\t// Find the worktree where the merge target (parent branch) is checked out\n\t\t\t\ttry {\n\t\t\t\t\tconst targetWorktreePath = await findWorktreeForBranch(mergeTarget, workingDir)\n\t\t\t\t\t// Run git branch -d from that worktree - HEAD will be the correct branch\n\t\t\t\t\t// and git will correctly verify the merge itself\n\t\t\t\t\tgetLogger().debug(`Running branch delete from worktree where '${mergeTarget}' is checked out: ${targetWorktreePath}`)\n\t\t\t\t\tdeleteCwd = targetWorktreePath\n\t\t\t\t} catch {\n\t\t\t\t\t// If we can't find the worktree for the target branch, fall back to checking merge status\n\t\t\t\t\t// and using -D if merged (the previous behavior)\n\t\t\t\t\tgetLogger().debug(`Could not find worktree for branch '${mergeTarget}', falling back to merge check`)\n\t\t\t\t\tconst isMerged = await isBranchMergedIntoMain(branchName, mergeTarget, workingDir)\n\n\t\t\t\t\tif (isMerged) {\n\t\t\t\t\t\tgetLogger().debug(`Branch '${branchName}' verified merged into '${mergeTarget}', using force delete`)\n\t\t\t\t\t\tdeleteFlag = '-D'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (options.worktreePath) {\n\t\t\t\t// DEPRECATED: Fall back to reading from worktree path if mergeTargetBranch not provided\n\t\t\t\t// This path should not be used when called from cleanupWorktree() since the worktree\n\t\t\t\t// has already been deleted by the time deleteBranch() is called\n\t\t\t\tgetLogger().warn('deleteBranch called with worktreePath but no mergeTargetBranch - this may fail if worktree was deleted')\n\t\t\t\ttry {\n\t\t\t\t\tconst mergeTarget = await getMergeTargetBranch(options.worktreePath, {\n\t\t\t\t\t\tsettingsManager: this.settingsManager,\n\t\t\t\t\t\tmetadataManager: this.metadataManager,\n\t\t\t\t\t})\n\n\t\t\t\t\t// Find the worktree where the merge target (parent branch) is checked out\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst targetWorktreePath = await findWorktreeForBranch(mergeTarget, workingDir)\n\t\t\t\t\t\tgetLogger().debug(`Running branch delete from worktree where '${mergeTarget}' is checked out: ${targetWorktreePath}`)\n\t\t\t\t\t\tdeleteCwd = targetWorktreePath\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tgetLogger().debug(`Could not find worktree for branch '${mergeTarget}', falling back to merge check`)\n\t\t\t\t\t\tconst isMerged = await isBranchMergedIntoMain(branchName, mergeTarget, workingDir)\n\n\t\t\t\t\t\tif (isMerged) {\n\t\t\t\t\t\t\tgetLogger().debug(`Branch '${branchName}' verified merged into '${mergeTarget}', using force delete`)\n\t\t\t\t\t\t\tdeleteFlag = '-D'\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// If we can't read the merge target (e.g., worktree deleted), just use safe delete\n\t\t\t\t\tgetLogger().debug(`Could not read merge target from worktreePath: ${error instanceof Error ? error.message : String(error)}`)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tawait executeGitCommand(['branch', deleteFlag, branchName], {\n\t\t\t\tcwd: deleteCwd\n\t\t\t})\n\n\t\tgetLogger().info(`Branch deleted: ${branchName}`)\n\t\t\treturn true\n\t\t} catch (error) {\n\t\t\tconst errorMessage = error instanceof Error ? error.message : String(error)\n\n\t\t\t// Handle \"branch not found\" - may occur in race conditions\n\t\t\tif (errorMessage.includes('not found') || errorMessage.includes('does not exist')) {\n\t\t\tgetLogger().debug(`Branch ${branchName} already deleted`)\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t\tif (options.force) {\n\t\t\t\tthrow error\n\t\t\t}\n\n\t\t\t// Git error for unmerged branch typically contains \"not fully merged\"\n\t\t\tif (errorMessage.includes('not fully merged')) {\n\t\t\t\tif (options.safetyVerified) {\n\t\t\t\t\t// Safety check already confirmed no data loss - retry with force delete\n\t\t\t\t\tgetLogger().info(`Branch '${branchName}' not merged into HEAD but safety verified - using force delete`)\n\t\t\t\t\tawait executeGitCommand(['branch', '-D', branchName], { cwd: deleteCwd })\n\t\t\t\t\tgetLogger().info(`Branch deleted: ${branchName}`)\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Cannot delete unmerged branch '${branchName}'. Use --force to delete anyway.`\n\t\t\t\t)\n\t\t\t}\n\n\t\t\t// For other errors, show the actual git error\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t/**\n\t * Cleanup database branch\n\t * Gracefully handles missing DatabaseManager\n\t *\n\t * @deprecated This method is deprecated and should not be used for post-deletion cleanup.\n\t * Use the pre-fetch mechanism in cleanupWorktree() instead.\n\t * This method will fail if called after worktree deletion because\n\t * it attempts to read the .env file which has been deleted.\n\t *\n\t * @param branchName - Name of the branch to delete\n\t * @param worktreePath - Path to worktree (must still exist with .env file)\n\t */\n\tasync cleanupDatabase(branchName: string, worktreePath: string): Promise<boolean> {\n\t\tif (!this.database) {\n\t\tgetLogger().debug('Database manager not available, skipping database cleanup')\n\t\t\treturn false\n\t\t}\n\n\t\ttry {\n\t\t\t// Pre-fetch configuration before deletion\n\t\t\tconst envFilePath = path.join(worktreePath, '.env')\n\t\t\tconst shouldCleanup = await this.database.shouldUseDatabaseBranching(envFilePath)\n\n\t\t\t// Find main worktree path to avoid running commands from potentially deleted directories\n\t\t\tlet cwd: string | undefined\n\t\t\ttry {\n\t\t\t\tcwd = await findMainWorktreePathWithSettings(worktreePath, this.settingsManager)\n\t\t\t} catch (error) {\n\t\t\t\t// If we can't find main worktree, commands will run from current directory\n\t\t\tgetLogger().debug(\n\t\t\t\t\t`Could not find main worktree path, using current directory: ${error instanceof Error ? error.message : String(error)}`\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tconst result = await this.database.deleteBranchIfConfigured(\n\t\t\t\tbranchName,\n\t\t\t\tshouldCleanup,\n\t\t\t\tfalse, // isPreview\n\t\t\t\tcwd\n\t\t\t)\n\n\t\t\t// Only return true if deletion actually occurred\n\t\t\tif (result.deleted) {\n\t\t\tgetLogger().info(`Database branch deleted: ${branchName}`)\n\t\t\t\treturn true\n\t\t\t} else if (result.notFound) {\n\t\t\tgetLogger().debug(`No database branch found for: ${branchName}`)\n\t\t\t\treturn false\n\t\t\t} else if (result.userDeclined) {\n\t\t\tgetLogger().info('Preview database deletion declined by user')\n\t\t\t\treturn false\n\t\t\t} else if (!result.success) {\n\t\t\tgetLogger().warn(`Database cleanup failed: ${result.error ?? 'Unknown error'}`)\n\t\t\t\treturn false\n\t\t\t} else {\n\t\t\t\t// Unexpected state\n\t\t\tgetLogger().debug('Database deletion returned unexpected result')\n\t\t\t\treturn false\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Unexpected exception\n\t\tgetLogger().warn(\n\t\t\t\t`Unexpected database cleanup error: ${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 * Cleanup multiple worktrees\n\t */\n\tasync cleanupMultipleWorktrees(\n\t\tidentifiers: string[],\n\t\toptions: ResourceCleanupOptions = {}\n\t): Promise<CleanupResult[]> {\n\t\tconst results: CleanupResult[] = []\n\n\t\tfor (const identifier of identifiers) {\n\t\t\t// Parse the identifier to get ParsedInput format\n\t\t\tconst parsed = this.parseIdentifier(identifier)\n\t\t\tconst result = await this.cleanupWorktree(parsed, options)\n\t\t\tresults.push(result)\n\t\t}\n\n\t\treturn results\n\t}\n\n\t/**\n\t * Validate worktree safety given a worktree object\n\t * Private method used internally when worktree is already known\n\t *\n\t * @param worktree - The worktree to validate\n\t * @param identifier - The original identifier used (for error messages)\n\t * @param checkBranchMerge - Whether to check if branch is merged into main (for branch deletion)\n\t * @param checkRemoteBranch - Whether to check if branch exists on remote (for GitHub-PR mode)\n\t */\n\tprivate async validateWorktreeSafety(\n\t\tworktree: GitWorktree,\n\t\tidentifier: string,\n\t\tcheckBranchMerge: boolean = false,\n\t\tcheckRemoteBranch: boolean = false\n\t): Promise<SafetyCheck> {\n\t\tconst warnings: string[] = []\n\t\tconst blockers: string[] = []\n\n\t\t// Check if main worktree\n\t\tconst isMain = await this.gitWorktree.isMainWorktree(worktree, this.settingsManager)\n\t\tif (isMain) {\n\t\t\tblockers.push(`Cannot cleanup main worktree: \"${worktree.branch}\" @ \"${worktree.path}\"`)\n\t\t}\n\n\t\t// Check for uncommitted changes\n\t\tconst hasChanges = await hasUncommittedChanges(worktree.path)\n\t\tif (hasChanges) {\n\t\t\t// Create simple blocker message with actionable guidance\n\t\t\tconst blockerMessage =\n\t\t\t\t`Worktree has uncommitted changes.\\n\\n` +\n\t\t\t\t`Please resolve before cleanup - you have some options:\\n` +\n\t\t\t\t` • Commit changes: cd ${worktree.path} && git commit -am \"message\"\\n` +\n\t\t\t\t` • Stash changes: cd ${worktree.path} && git stash\\n` +\n\t\t\t\t` • Force cleanup: il cleanup ${identifier} --force (WARNING: will discard changes)`\n\n\t\t\tblockers.push(blockerMessage)\n\t\t}\n\n\t\t// 5-point safety check for branch deletion\n\t\t// The key insight: we care about DATA LOSS, not about remote state\n\t\t// - Remote ahead of local is SAFE (commits exist on remote, no data loss)\n\t\t// - Local ahead of remote is DANGEROUS (unpushed commits would be lost)\n\t\t//\n\t\t// 1. Network error -> BLOCK (can't verify safety)\n\t\t// 2. Remote ahead of local -> OK (no data loss - commits exist on remote)\n\t\t// 3. Local ahead of remote (unpushed commits) -> BLOCK (data loss risk)\n\t\t// 4. No remote, merged to main -> OK (work is in main)\n\t\t// 5. No remote, NOT merged to main -> BLOCK (unmerged work would be lost)\n\t\tif ((checkBranchMerge || checkRemoteBranch) && worktree.branch) {\n\t\t\t// Use shared utility to get merge target (parent branch for child looms, main for others)\n\t\t\tconst mainBranch = await getMergeTargetBranch(worktree.path, {\n\t\t\t\tsettingsManager: this.settingsManager,\n\t\t\t\tmetadataManager: this.metadataManager,\n\t\t\t})\n\n\t\t\t// Check remote branch status\n\t\t\tconst remoteStatus: RemoteBranchStatus = await checkRemoteBranchStatus(worktree.branch, worktree.path)\n\n\t\t\t// Scenario 1: Network error checking remote -> Block\n\t\t\tif (remoteStatus.networkError) {\n\t\t\t\tconst blockerMessage =\n\t\t\t\t\t`Cannot verify remote branch status due to network error.\\n\\n` +\n\t\t\t\t\t`Error: ${remoteStatus.errorMessage ?? 'Unknown network error'}\\n\\n` +\n\t\t\t\t\t`Unable to determine if branch '${worktree.branch}' is safely backed up.\\n` +\n\t\t\t\t\t`Use --force to proceed without verification.`\n\n\t\t\t\tblockers.push(blockerMessage)\n\t\t\t}\n\t\t\t// Scenario 3: Local ahead of remote (unpushed commits) -> Block (data loss risk)\n\t\t\telse if (remoteStatus.exists && remoteStatus.localAhead) {\n\t\t\t\tconst blockerMessage =\n\t\t\t\t\t`Branch '${worktree.branch}' has unpushed commits that would be lost.\\n` +\n\t\t\t\t\t`The remote branch exists but your local branch is ahead.\\n\\n` +\n\t\t\t\t\t`Please resolve before cleanup:\\n` +\n\t\t\t\t\t` • Push your commits: git push origin ${worktree.branch}\\n` +\n\t\t\t\t\t` • Force cleanup: il cleanup ${identifier} --force (WARNING: will lose commits)`\n\n\t\t\t\tblockers.push(blockerMessage)\n\t\t\t}\n\t\t\t// Scenario 2: Remote ahead of local OR same commits -> Safe (work is on remote)\n\t\t\telse if (remoteStatus.exists && !remoteStatus.localAhead) {\n\t\t\t\t// Work is safely on remote (either remote is ahead or same commits)\n\t\t\t\t// No blocker needed\n\t\t\t}\n\t\t\t// Remote doesn't exist - need to check merge status\n\t\t\telse if (!remoteStatus.exists) {\n\t\t\t\tconst isMerged = await isBranchMergedIntoMain(worktree.branch, mainBranch, worktree.path)\n\n\t\t\t\tif (isMerged) {\n\t\t\t\t\t// Scenario 4: Remote doesn't exist, but merged to main -> Safe\n\t\t\t\t\t// No blocker needed\n\t\t\t\t} else {\n\t\t\t\t\t// Scenario 5: Remote doesn't exist AND not merged to main -> Block\n\t\t\t\t\tconst blockerMessage =\n\t\t\t\t\t\t`Branch '${worktree.branch}' has not been pushed to remote and is not merged into '${mainBranch}'.\\n` +\n\t\t\t\t\t\t`Deleting this branch would result in data loss.\\n\\n` +\n\t\t\t\t\t\t`Please resolve before cleanup - you have some options:\\n` +\n\t\t\t\t\t\t` • Push to remote: git push -u origin ${worktree.branch}\\n` +\n\t\t\t\t\t\t` • Merge to ${mainBranch}: git checkout ${mainBranch} && git merge ${worktree.branch}\\n` +\n\t\t\t\t\t\t` • Force cleanup: il cleanup ${identifier} --force (WARNING: will lose commits)`\n\n\t\t\t\t\tblockers.push(blockerMessage)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tisSafe: blockers.length === 0,\n\t\t\twarnings,\n\t\t\tblockers,\n\t\t}\n\t}\n\n\t/**\n\t * Validate cleanup safety\n\t */\n\tasync validateCleanupSafety(identifier: string): Promise<SafetyCheck> {\n\t\tconst warnings: string[] = []\n\t\tconst blockers: string[] = []\n\n\t\t// Find worktree\n\t\tconst worktrees = await this.gitWorktree.findWorktreesByIdentifier(identifier)\n\n\t\tif (worktrees.length === 0) {\n\t\t\tblockers.push(`No worktree found for: ${identifier}`)\n\t\t\treturn { isSafe: false, warnings, blockers }\n\t\t}\n\n\t\tconst worktree = worktrees[0]\n\t\tif (!worktree) {\n\t\t\tblockers.push(`No worktree found for: ${identifier}`)\n\t\t\treturn { isSafe: false, warnings, blockers }\n\t\t}\n\n\t\t// Delegate to private method that validates the worktree\n\t\treturn await this.validateWorktreeSafety(worktree, identifier)\n\t}\n\n\t/**\n\t * Parse identifier to determine type and extract number\n\t * Helper method for port calculation\n\t */\n\tprivate parseIdentifier(identifier: string): ParsedInput {\n\t\t// Check for issue pattern\n\t\tconst issueId = extractIssueNumber(identifier)\n\t\tif (issueId !== null) {\n\t\t\treturn {\n\t\t\t\ttype: 'issue',\n\t\t\t\tnumber: issueId,\n\t\t\t\toriginalInput: identifier\n\t\t\t}\n\t\t}\n\n\t\t// Check for PR pattern\n\t\tconst prMatch = identifier.match(/(?:pr|PR)[/-](\\d+)/)\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}\n\t\t}\n\n\t\t// Check for numeric identifier\n\t\tconst numericMatch = identifier.match(/^#?(\\d+)$/)\n\t\tif (numericMatch?.[1]) {\n\t\t\t// Assume issue for numeric identifiers\n\t\t\treturn {\n\t\t\t\ttype: 'issue',\n\t\t\t\tnumber: parseInt(numericMatch[1], 10),\n\t\t\t\toriginalInput: identifier\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: identifier,\n\t\t\toriginalInput: identifier\n\t\t}\n\t}\n}\n"],"mappings":"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","names":[]}
@@ -149,6 +149,27 @@ function generateRecapMcpConfig(loomPath, loomMetadata) {
149
149
  }
150
150
  ];
151
151
  }
152
+ function generateHarnessMcpConfig(socketPath) {
153
+ const harnessServerJsPath = path.resolve(
154
+ path.join(
155
+ path.dirname(new globalThis.URL(import.meta.url).pathname),
156
+ "../dist/mcp/harness-server.js"
157
+ )
158
+ );
159
+ logger.debug("Generated MCP config for harness server", { socketPath });
160
+ return [
161
+ {
162
+ mcpServers: {
163
+ harness: {
164
+ transport: "stdio",
165
+ command: "node",
166
+ args: [harnessServerJsPath],
167
+ env: { ILOOM_HARNESS_SOCKET: socketPath }
168
+ }
169
+ }
170
+ }
171
+ ];
172
+ }
152
173
  function getMcpConfigsDir() {
153
174
  return path.join(os.homedir(), ".config", "iloom-ai", "mcp-configs");
154
175
  }
@@ -202,6 +223,7 @@ async function generateAndWriteMcpConfigFile(loomPath, loomMetadata, provider =
202
223
  export {
203
224
  generateIssueManagementMcpConfig,
204
225
  generateRecapMcpConfig,
226
+ generateHarnessMcpConfig,
205
227
  generateAndWriteMcpConfigFile
206
228
  };
207
- //# sourceMappingURL=chunk-UWGVCXRF.js.map
229
+ //# sourceMappingURL=chunk-SKSYYBCU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/mcp.ts"],"sourcesContent":["import path from 'path'\nimport os from 'os'\nimport fs from 'fs-extra'\nimport { getRepoInfo } from './github.js'\nimport { logger } from './logger.js'\nimport type { IloomSettings } from '../lib/SettingsManager.js'\nimport type { LoomMetadata } from '../lib/MetadataManager.js'\n\n/**\n * Generate MCP configuration for issue management\n * Uses a single server that can handle both issues and pull requests\n * Returns array of MCP server config objects\n * @param contextType - Optional context type (issue or pr)\n * @param repo - Optional repo in \"owner/repo\" format. If not provided, will auto-detect from git.\n * @param provider - Issue management provider (default: 'github')\n * @param settings - Optional settings to extract Linear API token from\n * @param draftPrNumber - Optional draft PR number for github-draft-pr mode (routes comments to PR)\n */\nexport async function generateIssueManagementMcpConfig(\n\tcontextType?: 'issue' | 'pr',\n\trepo?: string,\n\tprovider: 'github' | 'linear' | 'jira' = 'github',\n\tsettings?: IloomSettings,\n\tdraftPrNumber?: number\n): Promise<Record<string, unknown>[]> {\n\t// When draftPrNumber is provided (github-draft-pr mode), force contextType to 'pr'\n\t// This ensures agents route comments to the draft PR instead of the issue\n\tconst effectiveContextType = draftPrNumber ? 'pr' : contextType\n\n\t// Build provider-specific environment variables\n\tlet envVars: Record<string, string> = {\n\t\tISSUE_PROVIDER: provider,\n\t}\n\n\t// Add draft PR number to env vars if provided\n\tif (draftPrNumber) {\n\t\tenvVars.DRAFT_PR_NUMBER = String(draftPrNumber)\n\t}\n\n\tif (provider === 'github') {\n\t\t// Get repository information for GitHub - either from provided repo string or auto-detect\n\t\tlet owner: string\n\t\tlet name: string\n\n\t\tif (repo) {\n\t\t\tconst parts = repo.split('/')\n\t\t\tif (parts.length !== 2 || !parts[0] || !parts[1]) {\n\t\t\t\tthrow new Error(`Invalid repo format: ${repo}. Expected \"owner/repo\"`)\n\t\t\t}\n\t\t\towner = parts[0]\n\t\t\tname = parts[1]\n\t\t} else {\n\t\t\tconst repoInfo = await getRepoInfo()\n\t\t\towner = repoInfo.owner\n\t\t\tname = repoInfo.name\n\t\t}\n\n\t\t// Map logical types to GitHub's webhook event names (handle GitHub's naming quirk here)\n\t\t// Use effectiveContextType which may be overridden by draftPrNumber\n\t\tconst githubEventName = effectiveContextType === 'issue' ? 'issues' : effectiveContextType === 'pr' ? 'pull_request' : undefined\n\n\t\tenvVars = {\n\t\t\t...envVars,\n\t\t\tREPO_OWNER: owner,\n\t\t\tREPO_NAME: name,\n\t\t\tGITHUB_API_URL: 'https://api.github.com/',\n\t\t\t...(githubEventName && { GITHUB_EVENT_NAME: githubEventName }),\n\t\t}\n\n\t\tlogger.debug('Generated MCP config for GitHub issue management', {\n\t\t\tprovider,\n\t\t\trepoOwner: owner,\n\t\t\trepoName: name,\n\t\t\tcontextType: effectiveContextType ?? 'auto-detect',\n\t\t\tgithubEventName: githubEventName ?? 'auto-detect',\n\t\t\tdraftPrNumber: draftPrNumber ?? undefined,\n\t\t})\n\t} else if (provider === 'linear') {\n\t\t// Linear needs API token passed through\n\t\tconst apiToken = settings?.issueManagement?.linear?.apiToken ?? process.env.LINEAR_API_TOKEN\n\n\t\tif (apiToken) {\n\t\t\tenvVars.LINEAR_API_TOKEN = apiToken\n\t\t}\n\n\t\t// Pass through LINEAR_TEAM_KEY from settings (primary) or env var (fallback)\n\t\t// Settings teamId is the preferred source as it's configured via `il init`\n\t\tconst teamKey = settings?.issueManagement?.linear?.teamId ?? process.env.LINEAR_TEAM_KEY\n\t\tif (teamKey) {\n\t\t\tenvVars.LINEAR_TEAM_KEY = teamKey\n\t\t}\n\n\t\tlogger.debug('Generated MCP config for Linear issue management', {\n\t\t\tprovider,\n\t\t\thasApiToken: !!apiToken,\n\t\t\thasTeamKey: !!teamKey,\n\t\t\tcontextType: contextType ?? 'auto-detect',\n\t\t})\n\t} else if (provider === 'jira') {\n\t\t// Jira configuration - pass credentials via environment variables\n\t\tconst jiraSettings = settings?.issueManagement?.jira\n\n\t\tif (jiraSettings?.host) {\n\t\t\tenvVars.JIRA_HOST = jiraSettings.host\n\t\t}\n\t\tif (jiraSettings?.username) {\n\t\t\tenvVars.JIRA_USERNAME = jiraSettings.username\n\t\t}\n\t\tif (jiraSettings?.apiToken) {\n\t\t\tenvVars.JIRA_API_TOKEN = jiraSettings.apiToken\n\t\t}\n\t\tif (jiraSettings?.projectKey) {\n\t\t\tenvVars.JIRA_PROJECT_KEY = jiraSettings.projectKey\n\t\t}\n\t\tif (jiraSettings?.transitionMappings) {\n\t\t\tenvVars.JIRA_TRANSITION_MAPPINGS = JSON.stringify(jiraSettings.transitionMappings)\n\t\t}\n\t\tif (jiraSettings?.defaultIssueType) {\n\t\t\tenvVars.JIRA_DEFAULT_ISSUE_TYPE = jiraSettings.defaultIssueType\n\t\t}\n\t\tif (jiraSettings?.defaultSubtaskType) {\n\t\t\tenvVars.JIRA_DEFAULT_SUBTASK_TYPE = jiraSettings.defaultSubtaskType\n\t\t}\n\n\t\tlogger.debug('Generated MCP config for Jira issue management', {\n\t\t\tprovider,\n\t\t\thasApiToken: !!jiraSettings?.apiToken,\n\t\t\tprojectKey: jiraSettings?.projectKey,\n\t\t\tcontextType: contextType ?? 'auto-detect',\n\t\t})\n\t}\n\n\t// Compute absolute path to the MCP server JS file\n\tconst serverJsPath = path.join(path.dirname(new globalThis.URL(import.meta.url).pathname), '../dist/mcp/issue-management-server.js')\n\tconst resolvedServerJsPath = path.resolve(serverJsPath)\n\n\t// Generate single MCP server config\n\tconst mcpServerConfig = {\n\t\tmcpServers: {\n\t\t\tissue_management: {\n\t\t\t\ttransport: 'stdio',\n\t\t\t\tcommand: 'node',\n\t\t\t\targs: [resolvedServerJsPath],\n\t\t\t\tenv: envVars,\n\t\t\t},\n\t\t},\n\t}\n\n\treturn [mcpServerConfig]\n}\n\n/**\n * Reuse MetadataManager.slugifyPath() algorithm for recap file naming\n *\n * Algorithm:\n * 1. Trim trailing slashes\n * 2. Replace all path separators (/ or \\) with ___ (triple underscore)\n * 3. Replace any other non-alphanumeric characters (except _ and -) with -\n * 4. Append .json\n */\nexport function slugifyPath(loomPath: string): string {\n\tlet slug = loomPath.replace(/[/\\\\]+$/, '')\n\tslug = slug.replace(/[/\\\\]/g, '___')\n\tslug = slug.replace(/[^a-zA-Z0-9_-]/g, '-')\n\treturn `${slug}.json`\n}\n\n/**\n * Generate MCP configuration for recap server\n *\n * The recap server captures session context (goal, decisions, insights, risks, assumptions)\n * for the VS Code Loom Context Panel.\n *\n * @param loomPath - Absolute path to the loom workspace\n * @param loomMetadata - The loom metadata object (will be stringified as JSON)\n */\nexport function generateRecapMcpConfig(\n\tloomPath: string,\n\tloomMetadata: LoomMetadata\n): Record<string, unknown>[] {\n\t// Compute recap file path using slugifyPath algorithm (same as MetadataManager)\n\tconst recapsDir = path.join(os.homedir(), '.config', 'iloom-ai', 'recaps')\n\tconst recapFilePath = path.join(recapsDir, slugifyPath(loomPath))\n\n\t// Compute metadata file path (same directory/naming as MetadataManager)\n\tconst loomsDir = path.join(os.homedir(), '.config', 'iloom-ai', 'looms')\n\tconst metadataFilePath = path.join(loomsDir, slugifyPath(loomPath))\n\n\t// Pass env vars:\n\t// - RECAP_FILE_PATH: where to read/write recap data\n\t// - LOOM_METADATA_JSON: stringified loom metadata (parsed by MCP using LoomMetadata type)\n\t// - METADATA_FILE_PATH: path to loom metadata file (for state transition tools)\n\tconst envVars = {\n\t\tRECAP_FILE_PATH: recapFilePath,\n\t\tLOOM_METADATA_JSON: JSON.stringify(loomMetadata),\n\t\tMETADATA_FILE_PATH: metadataFilePath,\n\t}\n\n\tlogger.debug('Generated MCP config for recap server', {\n\t\tloomPath,\n\t\trecapFilePath,\n\t\tloomMetadataDescription: loomMetadata.description,\n\t})\n\n\t// Compute absolute path to the recap MCP server JS file\n\tconst recapServerJsPath = path.resolve(\n\t\tpath.join(\n\t\t\tpath.dirname(new globalThis.URL(import.meta.url).pathname),\n\t\t\t'../dist/mcp/recap-server.js'\n\t\t)\n\t)\n\n\treturn [\n\t\t{\n\t\t\tmcpServers: {\n\t\t\t\trecap: {\n\t\t\t\t\ttransport: 'stdio',\n\t\t\t\t\tcommand: 'node',\n\t\t\t\t\targs: [recapServerJsPath],\n\t\t\t\t\tenv: envVars,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t]\n}\n\n/**\n * Generate MCP configuration for the harness server\n *\n * The harness server provides Claude with a `signal` tool to send structured\n * messages to the iloom harness process via Unix domain socket.\n *\n * @param socketPath - Absolute path to the harness Unix domain socket\n */\nexport function generateHarnessMcpConfig(socketPath: string): Record<string, unknown>[] {\n\tconst harnessServerJsPath = path.resolve(\n\t\tpath.join(\n\t\t\tpath.dirname(new globalThis.URL(import.meta.url).pathname),\n\t\t\t'../dist/mcp/harness-server.js'\n\t\t)\n\t)\n\n\tlogger.debug('Generated MCP config for harness server', { socketPath })\n\n\treturn [\n\t\t{\n\t\t\tmcpServers: {\n\t\t\t\tharness: {\n\t\t\t\t\ttransport: 'stdio',\n\t\t\t\t\tcommand: 'node',\n\t\t\t\t\targs: [harnessServerJsPath],\n\t\t\t\t\tenv: { ILOOM_HARNESS_SOCKET: socketPath },\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t]\n}\n\n/**\n * Get the MCP configs directory path\n */\nexport function getMcpConfigsDir(): string {\n\treturn path.join(os.homedir(), '.config', 'iloom-ai', 'mcp-configs')\n}\n\n/**\n * Get the MCP config file path for a given loom path\n */\nexport function getMcpConfigFilePath(loomPath: string): string {\n\treturn path.join(getMcpConfigsDir(), slugifyPath(loomPath))\n}\n\n/**\n * Generate and write a per-loom MCP config file to ~/.config/iloom-ai/mcp-configs/<loom-slug>.json\n *\n * Merges issue management and recap MCP server configs into a single file.\n * Used by swarm workers to pass --mcp-config <path> to claude -p commands.\n *\n * @param loomPath - Absolute path to the loom workspace\n * @param loomMetadata - The loom metadata object\n * @param provider - Issue tracker provider name\n * @param settings - Optional settings for provider configuration\n * @returns The absolute path to the written MCP config file\n */\nexport async function generateAndWriteMcpConfigFile(\n\tloomPath: string,\n\tloomMetadata: LoomMetadata,\n\tprovider: 'github' | 'linear' | 'jira' = 'github',\n\tsettings?: IloomSettings,\n): Promise<string> {\n\tconst mcpConfigs: Record<string, unknown>[] = []\n\n\t// Generate issue management MCP config\n\ttry {\n\t\tconst issueMcpConfigs = await generateIssueManagementMcpConfig(\n\t\t\t'issue',\n\t\t\tundefined,\n\t\t\tprovider,\n\t\t\tsettings,\n\t\t)\n\t\tmcpConfigs.push(...issueMcpConfigs)\n\t} catch (error) {\n\t\tlogger.warn(`Failed to generate issue management MCP config for loom: ${error instanceof Error ? error.message : 'Unknown error'}`)\n\t}\n\n\t// Generate recap MCP config\n\ttry {\n\t\tconst recapMcpConfigs = generateRecapMcpConfig(loomPath, loomMetadata)\n\t\tmcpConfigs.push(...recapMcpConfigs)\n\t} catch (error) {\n\t\tlogger.warn(`Failed to generate recap MCP config for loom: ${error instanceof Error ? error.message : 'Unknown error'}`)\n\t}\n\n\t// Merge all mcpServers into a single config object\n\tconst mergedServers: Record<string, unknown> = {}\n\tfor (const config of mcpConfigs) {\n\t\tif ('mcpServers' in config && typeof config.mcpServers === 'object') {\n\t\t\tObject.assign(mergedServers, config.mcpServers)\n\t\t}\n\t}\n\n\tconst mergedConfig = { mcpServers: mergedServers }\n\n\t// Verify MCP server JS files exist before writing config\n\tfor (const [serverName, serverConfig] of Object.entries(mergedServers)) {\n\t\tconst config = serverConfig as { args?: string[] }\n\t\tconst jsPath = config.args?.[0]\n\t\tif (jsPath) {\n\t\t\tconst exists = await fs.pathExists(jsPath)\n\t\t\tif (!exists) {\n\t\t\t\tlogger.warn(`MCP server JS file not found: ${serverName} -> ${jsPath}`)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Write to file\n\tconst configDir = getMcpConfigsDir()\n\tawait fs.ensureDir(configDir, { mode: 0o755 })\n\n\tconst configFilePath = getMcpConfigFilePath(loomPath)\n\tawait fs.writeFile(configFilePath, JSON.stringify(mergedConfig, null, 2), { mode: 0o644 })\n\n\treturn configFilePath\n}"],"mappings":"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","names":[]}
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-4232AHNQ.js";
5
5
  import {
6
6
  SettingsManager
7
- } from "./chunk-YYAKPQBT.js";
7
+ } from "./chunk-7VHJNVLF.js";
8
8
  import {
9
9
  JiraIssueTracker,
10
10
  createLinearChildIssue,
@@ -1433,4 +1433,4 @@ var IssueManagementProviderFactory = class {
1433
1433
  export {
1434
1434
  IssueManagementProviderFactory
1435
1435
  };
1436
- //# sourceMappingURL=chunk-JO2LZ6EQ.js.map
1436
+ //# sourceMappingURL=chunk-SWSJWA2S.js.map
@@ -128,4 +128,4 @@ export {
128
128
  buildReviewTemplateVariables,
129
129
  PromptTemplateManager
130
130
  };
131
- //# sourceMappingURL=chunk-4WJNIR5O.js.map
131
+ //# sourceMappingURL=chunk-UUEW5KWB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/PromptTemplateManager.ts"],"sourcesContent":["import { readFile } from 'fs/promises'\nimport { accessSync } from 'fs'\nimport path from 'path'\nimport { fileURLToPath } from 'url'\nimport Handlebars from 'handlebars'\nimport { logger } from '../utils/logger.js'\nimport type { AgentSettings } from './SettingsManager.js'\n\n// Register raw helper to handle content with curly braces (e.g., JSON)\n// Usage: {{{{raw}}}}{{VARIABLE}}{{{{/raw}}}}\n// This outputs the variable content as-is without Handlebars parsing its curly braces\nHandlebars.registerHelper('raw', function (this: unknown, options: Handlebars.HelperOptions) {\n\treturn options.fn(this)\n})\n\nexport interface TemplateVariables {\n\tISSUE_NUMBER?: string | number\n\tPR_NUMBER?: number\n\tISSUE_TITLE?: string\n\tPR_TITLE?: string\n\tWORKSPACE_PATH?: string\n\tPORT?: number\n\tONE_SHOT_MODE?: boolean\n\tINTERACTIVE_MODE?: boolean\n\tSETTINGS_SCHEMA?: string\n\tSETTINGS_GLOBAL_JSON?: string\n\tSETTINGS_JSON?: string\n\tSETTINGS_LOCAL_JSON?: string\n\tSHELL_TYPE?: string\n\tSHELL_CONFIG_PATH?: string\n\tSHELL_CONFIG_CONTENT?: string\n\tREMOTES_INFO?: string\n\tMULTIPLE_REMOTES?: string\n\tSINGLE_REMOTE?: string\n\tSINGLE_REMOTE_NAME?: string\n\tSINGLE_REMOTE_URL?: string\n\tNO_REMOTES?: string\n\tREADME_CONTENT?: string\n\tSETTINGS_SCHEMA_CONTENT?: string\n\tFIRST_TIME_USER?: boolean\n\tVSCODE_SETTINGS_GITIGNORED?: string\n\t// Session summary template variables\n\tSESSION_CONTEXT?: string // Session ID for Claude to reference its conversation\n\tBRANCH_NAME?: string // Branch being finished\n\tLOOM_TYPE?: string // 'issue' or 'pr'\n\tCOMPACT_SUMMARIES?: string // Extracted compact summaries from session transcript\n\tRECAP_DATA?: string // Formatted recap data (goal, complexity, entries, artifacts)\n\t// Draft PR mode variables - mutually exclusive with standard issue mode\n\tDRAFT_PR_NUMBER?: number // PR number for draft PR workflow\n\tDRAFT_PR_URL?: string // Full URL of the draft PR (e.g., https://github.com/owner/repo/pull/123)\n\tDRAFT_PR_MODE?: boolean // True when using github-draft-pr merge mode\n\tAUTO_COMMIT_PUSH?: boolean // True when auto-commit/push is enabled for draft PR mode\n\tSTANDARD_ISSUE_MODE?: boolean // True when using standard issue commenting (not draft PR)\n\tSTANDARD_BRANCH_MODE?: boolean // True when using standard branch mode (not draft PR)\n\t// Direct prompt mode - agent enhances raw text without issue context or MCP tools\n\tDIRECT_PROMPT_MODE?: boolean\n\t// VS Code environment detection\n\tIS_VSCODE_MODE?: boolean // True when ILOOM_VSCODE=1 environment variable is set\n\t// Multi-language support variables - mutually exclusive\n\tHAS_PACKAGE_JSON?: boolean // True when project has package.json\n\tNO_PACKAGE_JSON?: boolean // True when project does not have package.json (non-Node.js projects)\n\t// Review agent configuration variables (code reviewer)\n\tREVIEW_ENABLED?: boolean // True if review is enabled (defaults to true)\n\tREVIEW_CLAUDE_MODEL?: string // Claude model if configured (defaults to 'sonnet')\n\tREVIEW_GEMINI_MODEL?: string // Gemini model if configured\n\tREVIEW_CODEX_MODEL?: string // Codex model if configured\n\tHAS_REVIEW_CLAUDE?: boolean // True if claude provider configured (defaults to true)\n\tHAS_REVIEW_GEMINI?: boolean // True if gemini provider configured\n\tHAS_REVIEW_CODEX?: boolean // True if codex provider configured\n\t// Artifact reviewer configuration variables\n\tARTIFACT_REVIEW_ENABLED?: boolean // True if artifact review is enabled (defaults to true)\n\tARTIFACT_REVIEW_CLAUDE_MODEL?: string // Claude model if configured (defaults to 'sonnet')\n\tARTIFACT_REVIEW_GEMINI_MODEL?: string // Gemini model if configured\n\tARTIFACT_REVIEW_CODEX_MODEL?: string // Codex model if configured\n\tHAS_ARTIFACT_REVIEW_CLAUDE?: boolean // True if claude provider configured (defaults to true)\n\tHAS_ARTIFACT_REVIEW_GEMINI?: boolean // True if gemini provider configured\n\tHAS_ARTIFACT_REVIEW_CODEX?: boolean // True if codex provider configured\n\t// Per-agent review flags (whether artifacts should be reviewed before posting)\n\tENHANCER_REVIEW_ENABLED?: boolean // True if enhancer artifacts should be reviewed\n\tANALYZER_REVIEW_ENABLED?: boolean // True if analyzer artifacts should be reviewed\n\tPLANNER_REVIEW_ENABLED?: boolean // True if planner artifacts should be reviewed\n\tANALYZE_AND_PLAN_REVIEW_ENABLED?: boolean // True if analyze-and-plan artifacts should be reviewed\n\tIMPLEMENTER_REVIEW_ENABLED?: boolean // True if implementer artifacts should be reviewed\n\tCOMPLEXITY_REVIEW_ENABLED?: boolean // True if complexity evaluator artifacts should be reviewed\n\t// Planning mode variables - mutually exclusive\n\tEXISTING_ISSUE_MODE?: boolean // True when decomposing an existing issue (il plan 42)\n\tFRESH_PLANNING_MODE?: boolean // True when starting fresh planning session (il plan \"feature idea\")\n\t// Issue context for decomposition mode\n\tPARENT_ISSUE_NUMBER?: string | undefined // Issue number being decomposed\n\tPARENT_ISSUE_TITLE?: string | undefined // Title of issue being decomposed\n\tPARENT_ISSUE_BODY?: string | undefined // Body of issue being decomposed\n\t// Existing children and dependencies context for decomposition mode\n\tPARENT_ISSUE_CHILDREN?: string | undefined // Formatted list of existing child issues (if any)\n\tPARENT_ISSUE_DEPENDENCIES?: string | undefined // Formatted list of existing dependencies (if any)\n\t// Multi-AI provider support for plan command\n\tPLANNER?: 'claude' | 'gemini' | 'codex'\n\tREVIEWER?: 'claude' | 'gemini' | 'codex' | 'none'\n\tUSE_CLAUDE_PLANNER?: boolean\n\tUSE_GEMINI_PLANNER?: boolean\n\tUSE_CODEX_PLANNER?: boolean\n\tUSE_CLAUDE_REVIEWER?: boolean\n\tUSE_GEMINI_REVIEWER?: boolean\n\tUSE_CODEX_REVIEWER?: boolean\n\tHAS_REVIEWER?: boolean\n\t// Git remote configuration\n\tGIT_REMOTE?: string // Remote name for push (defaults to 'origin')\n\t// Swarm orchestrator variables\n\tEPIC_ISSUE_NUMBER?: string | number\n\tEPIC_WORKTREE_PATH?: string\n\tEPIC_METADATA_PATH?: string // Path to the epic's metadata JSON file\n\tCHILD_ISSUES?: string // JSON stringified array of child issues with worktree paths\n\tDEPENDENCY_MAP?: string // JSON stringified dependency map\n\tSWARM_MODE?: boolean // True when rendering agents in swarm mode\n\tAUTO_SWARM_MODE?: boolean // True when plan command launched with --auto-swarm flag\n\tSWARM_AGENT_METADATA?: string // JSON string mapping agent names to { model, tools } for claude -p commands\n\tSWARM_SUB_AGENT_TIMEOUT_MS?: number // Timeout in milliseconds for sub-agent claude -p Bash tool calls (default: 600000 = 10 minutes)\n\tNO_CLEANUP?: boolean // True when child loom cleanup should be skipped (e.g., manual cleanup later)\n\tISSUE_PREFIX?: string // \"#\" for GitHub, \"\" for Linear/Jira — used in commit message templates\n}\n\n/**\n * Build review-related template variables from settings.\n * Used by both the ignite command (for prompt templates) and AgentManager (for agent prompts).\n */\nexport function buildReviewTemplateVariables(agents?: Record<string, AgentSettings> | null): Partial<TemplateVariables> {\n\tconst variables: Partial<TemplateVariables> = {}\n\n\t// Code reviewer configuration\n\tconst reviewerSettings = agents?.['iloom-code-reviewer']\n\tconst reviewEnabled = reviewerSettings?.enabled !== false // Default to true\n\tvariables.REVIEW_ENABLED = reviewEnabled\n\n\tif (reviewEnabled) {\n\t\tconst providers = reviewerSettings?.providers ?? {}\n\t\tconst hasAnyProvider = Object.keys(providers).length > 0\n\n\t\tconst claudeModel = providers.claude ?? (hasAnyProvider ? undefined : 'sonnet')\n\t\tif (claudeModel) {\n\t\t\tvariables.REVIEW_CLAUDE_MODEL = claudeModel\n\t\t}\n\t\tif (providers.gemini) {\n\t\t\tvariables.REVIEW_GEMINI_MODEL = providers.gemini\n\t\t}\n\t\tif (providers.codex) {\n\t\t\tvariables.REVIEW_CODEX_MODEL = providers.codex\n\t\t}\n\t\tvariables.HAS_REVIEW_CLAUDE = !!claudeModel\n\t\tvariables.HAS_REVIEW_GEMINI = !!providers.gemini\n\t\tvariables.HAS_REVIEW_CODEX = !!providers.codex\n\t}\n\n\t// Artifact reviewer configuration\n\tconst artifactReviewerSettings = agents?.['iloom-artifact-reviewer']\n\tconst artifactReviewEnabled = artifactReviewerSettings?.enabled !== false // Default to true\n\tvariables.ARTIFACT_REVIEW_ENABLED = artifactReviewEnabled\n\n\tif (artifactReviewEnabled) {\n\t\tconst artifactProviders = artifactReviewerSettings?.providers ?? {}\n\t\tconst hasAnyArtifactProvider = Object.keys(artifactProviders).length > 0\n\n\t\tconst artifactClaudeModel = artifactProviders.claude ?? (hasAnyArtifactProvider ? undefined : 'sonnet')\n\t\tif (artifactClaudeModel) {\n\t\t\tvariables.ARTIFACT_REVIEW_CLAUDE_MODEL = artifactClaudeModel\n\t\t}\n\t\tif (artifactProviders.gemini) {\n\t\t\tvariables.ARTIFACT_REVIEW_GEMINI_MODEL = artifactProviders.gemini\n\t\t}\n\t\tif (artifactProviders.codex) {\n\t\t\tvariables.ARTIFACT_REVIEW_CODEX_MODEL = artifactProviders.codex\n\t\t}\n\t\tvariables.HAS_ARTIFACT_REVIEW_CLAUDE = !!artifactClaudeModel\n\t\tvariables.HAS_ARTIFACT_REVIEW_GEMINI = !!artifactProviders.gemini\n\t\tvariables.HAS_ARTIFACT_REVIEW_CODEX = !!artifactProviders.codex\n\t}\n\n\t// Per-agent review flags (defaults to false for each)\n\tvariables.ENHANCER_REVIEW_ENABLED = agents?.['iloom-issue-enhancer']?.review === true\n\tvariables.ANALYZER_REVIEW_ENABLED = agents?.['iloom-issue-analyzer']?.review === true\n\tvariables.PLANNER_REVIEW_ENABLED = agents?.['iloom-issue-planner']?.review === true\n\tvariables.ANALYZE_AND_PLAN_REVIEW_ENABLED = agents?.['iloom-issue-analyze-and-plan']?.review === true\n\tvariables.IMPLEMENTER_REVIEW_ENABLED = agents?.['iloom-issue-implementer']?.review === true\n\tvariables.COMPLEXITY_REVIEW_ENABLED = agents?.['iloom-issue-complexity-evaluator']?.review === true\n\n\treturn variables\n}\n\nexport class PromptTemplateManager {\n\tprivate templateDir: string\n\n\tconstructor(templateDir?: string) {\n\t\tif (templateDir) {\n\t\t\tthis.templateDir = templateDir\n\t\t} else {\n\t\t\t// Find templates relative to the package installation\n\t\t\t// When running from dist/, templates are copied to dist/prompts/\n\t\t\tconst currentFileUrl = import.meta.url\n\t\t\tconst currentFilePath = fileURLToPath(currentFileUrl)\n\t\t\tconst distDir = path.dirname(currentFilePath) // dist directory (may be chunked file location)\n\n\t\t\t// Walk up to find the dist directory (in case of chunked files)\n\t\t\tlet templateDir = path.join(distDir, 'prompts')\n\t\t\tlet currentDir = distDir\n\n\t\t\t// Try to find the prompts directory by walking up\n\t\t\twhile (currentDir !== path.dirname(currentDir)) {\n\t\t\t\tconst candidatePath = path.join(currentDir, 'prompts')\n\t\t\t\ttry {\n\t\t\t\t\t// Check if this directory exists (sync check for constructor)\n\t\t\t\t\taccessSync(candidatePath)\n\t\t\t\t\ttemplateDir = candidatePath\n\t\t\t\t\tbreak\n\t\t\t\t} catch {\n\t\t\t\t\tcurrentDir = path.dirname(currentDir)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.templateDir = templateDir\n\t\t\tlogger.debug('PromptTemplateManager initialized', {\n\t\t\t\tcurrentFilePath,\n\t\t\t\tdistDir,\n\t\t\t\ttemplateDir: this.templateDir\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Load a template file by name\n\t */\n\tasync loadTemplate(templateName: 'issue' | 'pr' | 'regular' | 'init' | 'session-summary' | 'plan' | 'swarm-orchestrator'): Promise<string> {\n\t\tconst templatePath = path.join(this.templateDir, `${templateName}-prompt.txt`)\n\n\t\tlogger.debug('Loading template', {\n\t\t\ttemplateName,\n\t\t\ttemplateDir: this.templateDir,\n\t\t\ttemplatePath\n\t\t})\n\n\t\ttry {\n\t\t\treturn await readFile(templatePath, 'utf-8')\n\t\t} catch (error) {\n\t\t\tlogger.error('Failed to load template', { templateName, templatePath, error })\n\t\t\tthrow new Error(`Template not found: ${templatePath}`)\n\t\t}\n\t}\n\n\t/**\n\t * Substitute variables in a template string using Handlebars\n\t */\n\tsubstituteVariables(template: string, variables: TemplateVariables): string {\n\t\tconst compiled = Handlebars.compile(template, { noEscape: true })\n\t\treturn compiled(variables)\n\t}\n\n\t/**\n\t * Get a fully processed prompt for a workflow type\n\t */\n\tasync getPrompt(\n\t\ttype: 'issue' | 'pr' | 'regular' | 'init' | 'session-summary' | 'plan' | 'swarm-orchestrator',\n\t\tvariables: TemplateVariables\n\t): Promise<string> {\n\t\tconst template = await this.loadTemplate(type)\n\t\treturn this.substituteVariables(template, variables)\n\t}\n}\n"],"mappings":"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","names":["templateDir"]}
@@ -4,20 +4,20 @@ import {
4
4
  } from "./chunk-NXMDEL3F.js";
5
5
  import {
6
6
  IssueManagementProviderFactory
7
- } from "./chunk-JO2LZ6EQ.js";
7
+ } from "./chunk-SWSJWA2S.js";
8
8
  import {
9
9
  hasMultipleRemotes
10
10
  } from "./chunk-FXDYIV3K.js";
11
11
  import {
12
12
  generateDeterministicSessionId,
13
13
  launchClaude
14
- } from "./chunk-ONQYPICO.js";
14
+ } from "./chunk-PZ5WSR5Z.js";
15
15
  import {
16
16
  PromptTemplateManager
17
- } from "./chunk-4WJNIR5O.js";
17
+ } from "./chunk-UUEW5KWB.js";
18
18
  import {
19
19
  SettingsManager
20
- } from "./chunk-YYAKPQBT.js";
20
+ } from "./chunk-7VHJNVLF.js";
21
21
  import {
22
22
  MetadataManager
23
23
  } from "./chunk-KB64WNBZ.js";
@@ -369,4 +369,4 @@ var SessionSummaryService = class {
369
369
  export {
370
370
  SessionSummaryService
371
371
  };
372
- //# sourceMappingURL=chunk-6EU6TCF6.js.map
372
+ //# sourceMappingURL=chunk-V3SVMFDQ.js.map
@@ -4,16 +4,16 @@ import {
4
4
  } from "./chunk-WWKOVDWC.js";
5
5
  import {
6
6
  IdentifierParser
7
- } from "./chunk-WY4QBK43.js";
7
+ } from "./chunk-63QWFWH3.js";
8
8
  import {
9
9
  GitWorktreeManager
10
- } from "./chunk-VGGST52X.js";
10
+ } from "./chunk-I5T677EA.js";
11
11
  import {
12
12
  getPackageScripts
13
13
  } from "./chunk-YQ57ORTV.js";
14
14
  import {
15
15
  extractIssueNumber
16
- } from "./chunk-MNHZB4Z2.js";
16
+ } from "./chunk-4FGEGQW4.js";
17
17
  import {
18
18
  logger
19
19
  } from "./chunk-VT4PDUYT.js";
@@ -156,4 +156,4 @@ var ScriptCommandBase = class {
156
156
  export {
157
157
  ScriptCommandBase
158
158
  };
159
- //# sourceMappingURL=chunk-NRSWLOAZ.js.map
159
+ //# sourceMappingURL=chunk-WXIM2WS7.js.map
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ClaudeService
4
- } from "./chunk-SN3SQCFK.js";
4
+ } from "./chunk-BU53XIGY.js";
5
5
  import {
6
6
  logger
7
7
  } from "./chunk-VT4PDUYT.js";
@@ -63,4 +63,4 @@ var ClaudeContextManager = class {
63
63
  export {
64
64
  ClaudeContextManager
65
65
  };
66
- //# sourceMappingURL=chunk-RYWFS37M.js.map
66
+ //# sourceMappingURL=chunk-XE4BDRZD.js.map