@iloom/cli 0.9.1 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (222) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +179 -41
  3. package/dist/{BranchNamingService-K6XNWQ6C.js → BranchNamingService-ECJHBB67.js} +2 -2
  4. package/dist/ClaudeContextManager-QXX6ZFST.js +14 -0
  5. package/dist/ClaudeService-NJNK2SUH.js +13 -0
  6. package/dist/{GitHubService-O7T6CFAJ.js → GitHubService-MEHKHUQP.js} +4 -4
  7. package/dist/IssueTrackerFactory-NG53YX5S.js +14 -0
  8. package/dist/{LoomLauncher-3I47SUPV.js → LoomLauncher-L64HHS3T.js} +9 -9
  9. package/dist/{MetadataManager-W3C54UYT.js → MetadataManager-5QZSTKNN.js} +2 -2
  10. package/dist/{ProjectCapabilityDetector-N5L7T4IY.js → ProjectCapabilityDetector-5KSYUTBJ.js} +3 -3
  11. package/dist/{PromptTemplateManager-36YLQRHP.js → PromptTemplateManager-DULSVRRE.js} +2 -2
  12. package/dist/README.md +179 -41
  13. package/dist/{SettingsManager-QR7V2IW2.js → SettingsManager-BQDQA3FK.js} +4 -2
  14. package/dist/agents/iloom-artifact-reviewer.md +11 -0
  15. package/dist/agents/iloom-code-reviewer.md +14 -0
  16. package/dist/agents/iloom-issue-analyze-and-plan.md +55 -12
  17. package/dist/agents/iloom-issue-analyzer.md +49 -6
  18. package/dist/agents/iloom-issue-complexity-evaluator.md +47 -6
  19. package/dist/agents/iloom-issue-enhancer.md +86 -7
  20. package/dist/agents/iloom-issue-implementer.md +48 -7
  21. package/dist/agents/iloom-issue-planner.md +115 -62
  22. package/dist/{build-IC4CJRMP.js → build-5GO3XW26.js} +9 -9
  23. package/dist/{chunk-USSL2X4A.js → chunk-3D7WQM7I.js} +2 -2
  24. package/dist/chunk-4232AHNQ.js +35 -0
  25. package/dist/chunk-4232AHNQ.js.map +1 -0
  26. package/dist/{chunk-QN47QVBX.js → chunk-4WJNIR5O.js} +1 -1
  27. package/dist/chunk-4WJNIR5O.js.map +1 -0
  28. package/dist/{chunk-2JPXGGP4.js → chunk-5MWV33NN.js} +4 -4
  29. package/dist/{chunk-POU2UMWN.js → chunk-6EU6TCF6.js} +10 -10
  30. package/dist/chunk-6EU6TCF6.js.map +1 -0
  31. package/dist/{chunk-Y5O2ALDZ.js → chunk-FB47TIJG.js} +29 -11
  32. package/dist/chunk-FB47TIJG.js.map +1 -0
  33. package/dist/chunk-HEXKPKCK.js +1396 -0
  34. package/dist/chunk-HEXKPKCK.js.map +1 -0
  35. package/dist/{chunk-KAYXR544.js → chunk-J5S7DFYC.js} +2 -2
  36. package/dist/{chunk-OK7LUTRW.js → chunk-JO2LZ6EQ.js} +476 -5
  37. package/dist/chunk-JO2LZ6EQ.js.map +1 -0
  38. package/dist/{chunk-KBEIQP4G.js → chunk-KB64WNBZ.js} +43 -3
  39. package/dist/chunk-KB64WNBZ.js.map +1 -0
  40. package/dist/{chunk-Y5HSSIK2.js → chunk-KXDRI47U.js} +71 -13
  41. package/dist/chunk-KXDRI47U.js.map +1 -0
  42. package/dist/{chunk-HZXBHMVM.js → chunk-LXLMMXXY.js} +54 -14
  43. package/dist/chunk-LXLMMXXY.js.map +1 -0
  44. package/dist/{chunk-H6ST2TGP.js → chunk-MNHZB4Z2.js} +4 -4
  45. package/dist/{chunk-TL72BGP6.js → chunk-MORRVYPT.js} +2 -2
  46. package/dist/{chunk-TGRK3CHF.js → chunk-NRSWLOAZ.js} +8 -8
  47. package/dist/chunk-NRSWLOAZ.js.map +1 -0
  48. package/dist/{chunk-FO5GGFOV.js → chunk-ONQYPICO.js} +13 -5
  49. package/dist/chunk-ONQYPICO.js.map +1 -0
  50. package/dist/{chunk-7ZEHSSUP.js → chunk-P4O6EH46.js} +4 -4
  51. package/dist/chunk-QZWEJVWV.js +207 -0
  52. package/dist/chunk-QZWEJVWV.js.map +1 -0
  53. package/dist/chunk-RSYT7MVI.js +202 -0
  54. package/dist/chunk-RSYT7MVI.js.map +1 -0
  55. package/dist/{chunk-OAVJR4PM.js → chunk-RYWFS37M.js} +6 -6
  56. package/dist/chunk-RYWFS37M.js.map +1 -0
  57. package/dist/{chunk-B7U6OKUR.js → chunk-SF2P22EE.js} +11 -3
  58. package/dist/chunk-SF2P22EE.js.map +1 -0
  59. package/dist/{chunk-MZPRBNYC.js → chunk-SN3SQCFK.js} +10 -8
  60. package/dist/{chunk-MZPRBNYC.js.map → chunk-SN3SQCFK.js.map} +1 -1
  61. package/dist/{chunk-4ZIHFUPN.js → chunk-UD3WJDIV.js} +145 -107
  62. package/dist/chunk-UD3WJDIV.js.map +1 -0
  63. package/dist/{chunk-3P6J4IZZ.js → chunk-UKBAJ2QQ.js} +61 -7
  64. package/dist/chunk-UKBAJ2QQ.js.map +1 -0
  65. package/dist/{chunk-RD7OPXZK.js → chunk-UVD4CZKS.js} +3 -3
  66. package/dist/chunk-UWGVCXRF.js +207 -0
  67. package/dist/chunk-UWGVCXRF.js.map +1 -0
  68. package/dist/{chunk-JT5LZRMI.js → chunk-VECNX6VX.js} +2 -2
  69. package/dist/{chunk-TRUMP4DA.js → chunk-VG45TUYK.js} +75 -6
  70. package/dist/chunk-VG45TUYK.js.map +1 -0
  71. package/dist/{chunk-4GAJJUYS.js → chunk-VGGST52X.js} +2 -2
  72. package/dist/{chunk-4LKGCFGG.js → chunk-WWKOVDWC.js} +2 -2
  73. package/dist/{chunk-2HZX6AMR.js → chunk-WY4QBK43.js} +7 -7
  74. package/dist/chunk-WY4QBK43.js.map +1 -0
  75. package/dist/chunk-Y4YZTHZE.js +73 -0
  76. package/dist/chunk-Y4YZTHZE.js.map +1 -0
  77. package/dist/{chunk-VOGGLPG5.js → chunk-YQ57ORTV.js} +14 -1
  78. package/dist/chunk-YQ57ORTV.js.map +1 -0
  79. package/dist/{chunk-XFEK2X2D.js → chunk-YYAKPQBT.js} +73 -20
  80. package/dist/chunk-YYAKPQBT.js.map +1 -0
  81. package/dist/{chunk-NTTSUAVM.js → chunk-ZEWU5PZK.js} +2 -2
  82. package/dist/{chunk-5LVVQGB3.js → chunk-ZHPNZC75.js} +17 -17
  83. package/dist/chunk-ZHPNZC75.js.map +1 -0
  84. package/dist/{chunk-I3HMNWQQ.js → chunk-ZW2LKWWE.js} +9 -9
  85. package/dist/chunk-ZW2LKWWE.js.map +1 -0
  86. package/dist/{claude-TP2QO3BU.js → claude-P3NQR6IJ.js} +2 -2
  87. package/dist/{cleanup-D3CSRBBZ.js → cleanup-6UCPVMFG.js} +81 -32
  88. package/dist/cleanup-6UCPVMFG.js.map +1 -0
  89. package/dist/cli.js +640 -350
  90. package/dist/cli.js.map +1 -1
  91. package/dist/{commit-IWGT42XN.js → commit-L3EPY5QG.js} +23 -21
  92. package/dist/commit-L3EPY5QG.js.map +1 -0
  93. package/dist/{compile-EOWJORKO.js → compile-ZS4HYRX5.js} +9 -9
  94. package/dist/{contribute-WSJTV2RX.js → contribute-ORDDQGSL.js} +14 -6
  95. package/dist/contribute-ORDDQGSL.js.map +1 -0
  96. package/dist/{dev-server-Q6M62ATG.js → dev-server-FYZ2AQIH.js} +29 -15
  97. package/dist/dev-server-FYZ2AQIH.js.map +1 -0
  98. package/dist/{feedback-QPNDZQRV.js → feedback-TMBXSCM5.js} +15 -15
  99. package/dist/{git-W3XUIFTR.js → git-ET64COO3.js} +4 -4
  100. package/dist/hooks/iloom-hook.js +15 -0
  101. package/dist/ignite-CGOV3TD4.js +1393 -0
  102. package/dist/ignite-CGOV3TD4.js.map +1 -0
  103. package/dist/index.d.ts +397 -53
  104. package/dist/index.js +1178 -40
  105. package/dist/index.js.map +1 -1
  106. package/dist/{init-ALYWKNWG.js → init-GFQ5W7GK.js} +57 -21
  107. package/dist/init-GFQ5W7GK.js.map +1 -0
  108. package/dist/issues-T4ZZSPEG.js +179 -0
  109. package/dist/issues-T4ZZSPEG.js.map +1 -0
  110. package/dist/{lint-IHUH45OC.js → lint-6TQXDZ3T.js} +9 -9
  111. package/dist/mcp/issue-management-server.js +2472 -257
  112. package/dist/mcp/issue-management-server.js.map +1 -1
  113. package/dist/mcp/recap-server.js +144 -21
  114. package/dist/mcp/recap-server.js.map +1 -1
  115. package/dist/{neon-helpers-VVFFTLXE.js → neon-helpers-CQN2PB4S.js} +3 -3
  116. package/dist/neon-helpers-CQN2PB4S.js.map +1 -0
  117. package/dist/{open-KWOV2OFO.js → open-5QZGXQRF.js} +15 -15
  118. package/dist/open-5QZGXQRF.js.map +1 -0
  119. package/dist/{plan-BRJBFJHF.js → plan-U7ZQWLFY.js} +41 -25
  120. package/dist/plan-U7ZQWLFY.js.map +1 -0
  121. package/dist/{projects-LH362JZQ.js → projects-2UOXFLNZ.js} +4 -4
  122. package/dist/prompts/CLAUDE.md +62 -0
  123. package/dist/prompts/init-prompt.txt +386 -47
  124. package/dist/prompts/issue-prompt.txt +427 -54
  125. package/dist/prompts/plan-prompt.txt +97 -16
  126. package/dist/prompts/pr-prompt.txt +44 -1
  127. package/dist/prompts/regular-prompt.txt +42 -1
  128. package/dist/prompts/session-summary-prompt.txt +14 -0
  129. package/dist/prompts/swarm-orchestrator-prompt.txt +437 -0
  130. package/dist/{rebase-AJOJOZUG.js → rebase-DWIB77KV.js} +10 -10
  131. package/dist/{recap-GKJXMDXW.js → recap-MX63HAKV.js} +47 -19
  132. package/dist/recap-MX63HAKV.js.map +1 -0
  133. package/dist/{run-QEUVZF7J.js → run-O3TFNQFC.js} +15 -15
  134. package/dist/run-O3TFNQFC.js.map +1 -0
  135. package/dist/schema/package-iloom.schema.json +58 -0
  136. package/dist/schema/settings.schema.json +130 -15
  137. package/dist/{shell-DAAVG4YN.js → shell-G6VC2CYR.js} +14 -7
  138. package/dist/shell-G6VC2CYR.js.map +1 -0
  139. package/dist/{summary-ZKOA35PT.js → summary-FWHAX55O.js} +27 -25
  140. package/dist/summary-FWHAX55O.js.map +1 -0
  141. package/dist/{test-5GPWWO3P.js → test-F7JNJZYP.js} +9 -9
  142. package/dist/{test-git-EJUKDB7F.js → test-git-BTAOIUE2.js} +4 -4
  143. package/dist/test-jira-CHYNV33F.js +96 -0
  144. package/dist/test-jira-CHYNV33F.js.map +1 -0
  145. package/dist/{test-prefix-23TOBUXY.js → test-prefix-Q6TFSU6F.js} +4 -4
  146. package/dist/{test-webserver-CKROHFBQ.js → test-webserver-EONCG7E7.js} +6 -6
  147. package/dist/{vscode-6TOLFCI2.js → vscode-VA5X4P25.js} +7 -7
  148. package/package.json +5 -1
  149. package/dist/ClaudeContextManager-X2Y72GRL.js +0 -14
  150. package/dist/ClaudeService-7P32TTES.js +0 -13
  151. package/dist/chunk-2HZX6AMR.js.map +0 -1
  152. package/dist/chunk-3P6J4IZZ.js.map +0 -1
  153. package/dist/chunk-4ZIHFUPN.js.map +0 -1
  154. package/dist/chunk-5LVVQGB3.js.map +0 -1
  155. package/dist/chunk-B7U6OKUR.js.map +0 -1
  156. package/dist/chunk-ENGCJIYQ.js +0 -520
  157. package/dist/chunk-ENGCJIYQ.js.map +0 -1
  158. package/dist/chunk-FO5GGFOV.js.map +0 -1
  159. package/dist/chunk-HZXBHMVM.js.map +0 -1
  160. package/dist/chunk-I3HMNWQQ.js.map +0 -1
  161. package/dist/chunk-J7FJ6PUT.js +0 -121
  162. package/dist/chunk-J7FJ6PUT.js.map +0 -1
  163. package/dist/chunk-KBEIQP4G.js.map +0 -1
  164. package/dist/chunk-OAVJR4PM.js.map +0 -1
  165. package/dist/chunk-OK7LUTRW.js.map +0 -1
  166. package/dist/chunk-POU2UMWN.js.map +0 -1
  167. package/dist/chunk-QN47QVBX.js.map +0 -1
  168. package/dist/chunk-TGRK3CHF.js.map +0 -1
  169. package/dist/chunk-TRUMP4DA.js.map +0 -1
  170. package/dist/chunk-VOGGLPG5.js.map +0 -1
  171. package/dist/chunk-XFEK2X2D.js.map +0 -1
  172. package/dist/chunk-Y5HSSIK2.js.map +0 -1
  173. package/dist/chunk-Y5O2ALDZ.js.map +0 -1
  174. package/dist/cleanup-D3CSRBBZ.js.map +0 -1
  175. package/dist/commit-IWGT42XN.js.map +0 -1
  176. package/dist/contribute-WSJTV2RX.js.map +0 -1
  177. package/dist/dev-server-Q6M62ATG.js.map +0 -1
  178. package/dist/ignite-OPO6EDYT.js +0 -784
  179. package/dist/ignite-OPO6EDYT.js.map +0 -1
  180. package/dist/init-ALYWKNWG.js.map +0 -1
  181. package/dist/issues-L7TBUPXT.js +0 -116
  182. package/dist/issues-L7TBUPXT.js.map +0 -1
  183. package/dist/open-KWOV2OFO.js.map +0 -1
  184. package/dist/plan-BRJBFJHF.js.map +0 -1
  185. package/dist/recap-GKJXMDXW.js.map +0 -1
  186. package/dist/run-QEUVZF7J.js.map +0 -1
  187. package/dist/shell-DAAVG4YN.js.map +0 -1
  188. package/dist/summary-ZKOA35PT.js.map +0 -1
  189. /package/dist/{BranchNamingService-K6XNWQ6C.js.map → BranchNamingService-ECJHBB67.js.map} +0 -0
  190. /package/dist/{ClaudeContextManager-X2Y72GRL.js.map → ClaudeContextManager-QXX6ZFST.js.map} +0 -0
  191. /package/dist/{ClaudeService-7P32TTES.js.map → ClaudeService-NJNK2SUH.js.map} +0 -0
  192. /package/dist/{GitHubService-O7T6CFAJ.js.map → GitHubService-MEHKHUQP.js.map} +0 -0
  193. /package/dist/{MetadataManager-W3C54UYT.js.map → IssueTrackerFactory-NG53YX5S.js.map} +0 -0
  194. /package/dist/{LoomLauncher-3I47SUPV.js.map → LoomLauncher-L64HHS3T.js.map} +0 -0
  195. /package/dist/{ProjectCapabilityDetector-N5L7T4IY.js.map → MetadataManager-5QZSTKNN.js.map} +0 -0
  196. /package/dist/{PromptTemplateManager-36YLQRHP.js.map → ProjectCapabilityDetector-5KSYUTBJ.js.map} +0 -0
  197. /package/dist/{SettingsManager-QR7V2IW2.js.map → PromptTemplateManager-DULSVRRE.js.map} +0 -0
  198. /package/dist/{claude-TP2QO3BU.js.map → SettingsManager-BQDQA3FK.js.map} +0 -0
  199. /package/dist/{build-IC4CJRMP.js.map → build-5GO3XW26.js.map} +0 -0
  200. /package/dist/{chunk-USSL2X4A.js.map → chunk-3D7WQM7I.js.map} +0 -0
  201. /package/dist/{chunk-2JPXGGP4.js.map → chunk-5MWV33NN.js.map} +0 -0
  202. /package/dist/{chunk-KAYXR544.js.map → chunk-J5S7DFYC.js.map} +0 -0
  203. /package/dist/{chunk-H6ST2TGP.js.map → chunk-MNHZB4Z2.js.map} +0 -0
  204. /package/dist/{chunk-TL72BGP6.js.map → chunk-MORRVYPT.js.map} +0 -0
  205. /package/dist/{chunk-7ZEHSSUP.js.map → chunk-P4O6EH46.js.map} +0 -0
  206. /package/dist/{chunk-RD7OPXZK.js.map → chunk-UVD4CZKS.js.map} +0 -0
  207. /package/dist/{chunk-JT5LZRMI.js.map → chunk-VECNX6VX.js.map} +0 -0
  208. /package/dist/{chunk-4GAJJUYS.js.map → chunk-VGGST52X.js.map} +0 -0
  209. /package/dist/{chunk-4LKGCFGG.js.map → chunk-WWKOVDWC.js.map} +0 -0
  210. /package/dist/{chunk-NTTSUAVM.js.map → chunk-ZEWU5PZK.js.map} +0 -0
  211. /package/dist/{git-W3XUIFTR.js.map → claude-P3NQR6IJ.js.map} +0 -0
  212. /package/dist/{compile-EOWJORKO.js.map → compile-ZS4HYRX5.js.map} +0 -0
  213. /package/dist/{feedback-QPNDZQRV.js.map → feedback-TMBXSCM5.js.map} +0 -0
  214. /package/dist/{neon-helpers-VVFFTLXE.js.map → git-ET64COO3.js.map} +0 -0
  215. /package/dist/{lint-IHUH45OC.js.map → lint-6TQXDZ3T.js.map} +0 -0
  216. /package/dist/{projects-LH362JZQ.js.map → projects-2UOXFLNZ.js.map} +0 -0
  217. /package/dist/{rebase-AJOJOZUG.js.map → rebase-DWIB77KV.js.map} +0 -0
  218. /package/dist/{test-5GPWWO3P.js.map → test-F7JNJZYP.js.map} +0 -0
  219. /package/dist/{test-git-EJUKDB7F.js.map → test-git-BTAOIUE2.js.map} +0 -0
  220. /package/dist/{test-prefix-23TOBUXY.js.map → test-prefix-Q6TFSU6F.js.map} +0 -0
  221. /package/dist/{test-webserver-CKROHFBQ.js.map → test-webserver-EONCG7E7.js.map} +0 -0
  222. /package/dist/{vscode-6TOLFCI2.js.map → vscode-VA5X4P25.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/ClaudeService.ts"],"sourcesContent":["import { detectClaudeCli, launchClaude, launchClaudeInNewTerminalWindow, ClaudeCliOptions } from '../utils/claude.js'\nimport { PromptTemplateManager, TemplateVariables } from './PromptTemplateManager.js'\nimport { SettingsManager, IloomSettings } from './SettingsManager.js'\nimport { logger } from '../utils/logger.js'\n\nexport interface ClaudeWorkflowOptions {\n\ttype: 'issue' | 'pr' | 'regular'\n\tissueNumber?: string | number\n\tprNumber?: number\n\ttitle?: string\n\tworkspacePath: string\n\tport?: number\n\theadless?: boolean\n\tbranchName?: string\n\toneShot?: import('../types/index.js').OneShotMode\n\tsetArguments?: string[] // Raw --set arguments to forward\n\texecutablePath?: string // Executable path to use for spin command\n}\n\nexport class ClaudeService {\n\tprivate templateManager: PromptTemplateManager\n\tprivate settingsManager: SettingsManager\n\tprivate settings?: IloomSettings\n\n\tconstructor(templateManager?: PromptTemplateManager, settingsManager?: SettingsManager) {\n\t\tthis.templateManager = templateManager ?? new PromptTemplateManager()\n\t\tthis.settingsManager = settingsManager ?? new SettingsManager()\n\t}\n\n\t/**\n\t * Check if Claude CLI is available\n\t */\n\tasync isAvailable(): Promise<boolean> {\n\t\treturn detectClaudeCli()\n\t}\n\n\t/**\n\t * Get the appropriate permission mode for a workflow type\n\t */\n\tprivate getPermissionModeForWorkflow(\n\t\ttype: 'issue' | 'pr' | 'regular'\n\t): ClaudeCliOptions['permissionMode'] {\n\t\t// Check settings for configured permission mode\n\t\tif (this.settings?.workflows) {\n\t\t\tconst workflowConfig =\n\t\t\t\ttype === 'issue'\n\t\t\t\t\t? this.settings.workflows.issue\n\t\t\t\t\t: type === 'pr'\n\t\t\t\t\t\t? this.settings.workflows.pr\n\t\t\t\t\t\t: this.settings.workflows.regular\n\n\t\t\tif (workflowConfig?.permissionMode) {\n\t\t\t\treturn workflowConfig.permissionMode\n\t\t\t}\n\t\t}\n\n\t\t// Fall back to acceptEdits for all workflow types\n\t\treturn 'acceptEdits'\n\t}\n\n\t/**\n\t * Launch Claude for a specific workflow\n\t */\n\tasync launchForWorkflow(options: ClaudeWorkflowOptions): Promise<string | void> {\n\t\tconst { type, issueNumber, prNumber, title, workspacePath, port, headless = false, branchName, oneShot = 'default', setArguments, executablePath } = options\n\n\t\ttry {\n\t\t\t// Load settings if not already cached\n\t\t\t// Settings are pre-validated at CLI startup, so no error handling needed here\n\t\t\tthis.settings ??= await this.settingsManager.loadSettings()\n\n\t\t\t// Build template variables\n\t\t\tconst variables: TemplateVariables = {\n\t\t\t\tWORKSPACE_PATH: workspacePath,\n\t\t\t}\n\n\t\t\tif (issueNumber !== undefined) {\n\t\t\t\tvariables.ISSUE_NUMBER = issueNumber\n\t\t\t}\n\n\t\t\tif (prNumber !== undefined) {\n\t\t\t\tvariables.PR_NUMBER = prNumber\n\t\t\t}\n\n\t\t\tif (title !== undefined) {\n\t\t\t\tif (type === 'issue') {\n\t\t\t\t\tvariables.ISSUE_TITLE = title\n\t\t\t\t} else if (type === 'pr') {\n\t\t\t\t\tvariables.PR_TITLE = title\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (port !== undefined) {\n\t\t\t\tvariables.PORT = port\n\t\t\t}\n\n\t\t\t// Get the prompt from template manager\n\t\t\tconst prompt = await this.templateManager.getPrompt(type, variables)\n\n\t\t\t// Determine permission mode (model uses Claude's default for start command)\n\t\t\tconst permissionMode = this.getPermissionModeForWorkflow(type)\n\n\t\t\t// Display warning if bypassPermissions mode is used\n\t\t\tif (permissionMode === 'bypassPermissions') {\n\t\t\t\tlogger.warn(\n\t\t\t\t\t'⚠️ WARNING: Using bypassPermissions mode - Claude will execute all tool calls without confirmation. ' +\n\t\t\t\t\t\t'This can be dangerous. Use with caution.'\n\t\t\t\t)\n\t\t\t}\n\n\t\t\t// Build Claude CLI options\n\t\t\tconst claudeOptions: ClaudeCliOptions = {\n\t\t\t\taddDir: workspacePath,\n\t\t\t\theadless,\n\t\t\t}\n\n\t\t\t// Add permission mode if not default\n\t\t\tif (permissionMode !== undefined && permissionMode !== 'default') {\n\t\t\t\tclaudeOptions.permissionMode = permissionMode\n\t\t\t}\n\n\t\t\t// Add optional branch name for terminal coloring\n\t\t\tif (branchName !== undefined) {\n\t\t\t\tclaudeOptions.branchName = branchName\n\t\t\t}\n\n\t\t\t// Add optional port for terminal window export\n\t\t\tif (port !== undefined) {\n\t\t\t\tclaudeOptions.port = port\n\t\t\t}\n\n\t\t\t// Add optional setArguments for forwarding\n\t\t\tif (setArguments !== undefined) {\n\t\t\t\tclaudeOptions.setArguments = setArguments\n\t\t\t}\n\n\t\t\t// Add optional executablePath for spin command\n\t\t\tif (executablePath !== undefined) {\n\t\t\t\tclaudeOptions.executablePath = executablePath\n\t\t\t}\n\n\t\t\tlogger.debug('Launching Claude for workflow', {\n\t\t\t\ttype,\n\t\t\t\tpermissionMode,\n\t\t\t\theadless,\n\t\t\t\tworkspacePath,\n\t\t\t})\n\n\t\t\t// Launch Claude\n\t\t\tif (headless) {\n\t\t\t\t// Headless mode: use simple launchClaude\n\t\t\t\treturn await launchClaude(prompt, claudeOptions)\n\t\t\t} else {\n\t\t\t\t// Interactive workflow mode: use terminal window launcher\n\t\t\t\t// This is the \"end of il start\" behavior\n\t\t\t\tif (!claudeOptions.addDir) {\n\t\t\t\t\tthrow new Error('workspacePath required for interactive workflow launch')\n\t\t\t\t}\n\n\t\t\t\treturn await launchClaudeInNewTerminalWindow(prompt, {\n\t\t\t\t\t...claudeOptions,\n\t\t\t\t\tworkspacePath: claudeOptions.addDir,\n\t\t\t\t\toneShot,\n\t\t\t\t})\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tlogger.error('Failed to launch Claude for workflow', { error, options })\n\t\t\tthrow error\n\t\t}\n\t}\n\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAmBO,IAAM,gBAAN,MAAoB;AAAA,EAK1B,YAAY,iBAAyC,iBAAmC;AACvF,SAAK,kBAAkB,mBAAmB,IAAI,sBAAsB;AACpE,SAAK,kBAAkB,mBAAmB,IAAI,gBAAgB;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAgC;AACrC,WAAO,gBAAgB;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKQ,6BACP,MACqC;AAzCvC;AA2CE,SAAI,UAAK,aAAL,mBAAe,WAAW;AAC7B,YAAM,iBACL,SAAS,UACN,KAAK,SAAS,UAAU,QACxB,SAAS,OACR,KAAK,SAAS,UAAU,KACxB,KAAK,SAAS,UAAU;AAE7B,UAAI,iDAAgB,gBAAgB;AACnC,eAAO,eAAe;AAAA,MACvB;AAAA,IACD;AAGA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,kBAAkB,SAAwD;AAC/E,UAAM,EAAE,MAAM,aAAa,UAAU,OAAO,eAAe,MAAM,WAAW,OAAO,YAAY,UAAU,WAAW,cAAc,eAAe,IAAI;AAErJ,QAAI;AAGH,WAAK,aAAa,MAAM,KAAK,gBAAgB,aAAa;AAG1D,YAAM,YAA+B;AAAA,QACpC,gBAAgB;AAAA,MACjB;AAEA,UAAI,gBAAgB,QAAW;AAC9B,kBAAU,eAAe;AAAA,MAC1B;AAEA,UAAI,aAAa,QAAW;AAC3B,kBAAU,YAAY;AAAA,MACvB;AAEA,UAAI,UAAU,QAAW;AACxB,YAAI,SAAS,SAAS;AACrB,oBAAU,cAAc;AAAA,QACzB,WAAW,SAAS,MAAM;AACzB,oBAAU,WAAW;AAAA,QACtB;AAAA,MACD;AAEA,UAAI,SAAS,QAAW;AACvB,kBAAU,OAAO;AAAA,MAClB;AAGA,YAAM,SAAS,MAAM,KAAK,gBAAgB,UAAU,MAAM,SAAS;AAGnE,YAAM,iBAAiB,KAAK,6BAA6B,IAAI;AAG7D,UAAI,mBAAmB,qBAAqB;AAC3C,eAAO;AAAA,UACN;AAAA,QAED;AAAA,MACD;AAGA,YAAM,gBAAkC;AAAA,QACvC,QAAQ;AAAA,QACR;AAAA,MACD;AAGA,UAAI,mBAAmB,UAAa,mBAAmB,WAAW;AACjE,sBAAc,iBAAiB;AAAA,MAChC;AAGA,UAAI,eAAe,QAAW;AAC7B,sBAAc,aAAa;AAAA,MAC5B;AAGA,UAAI,SAAS,QAAW;AACvB,sBAAc,OAAO;AAAA,MACtB;AAGA,UAAI,iBAAiB,QAAW;AAC/B,sBAAc,eAAe;AAAA,MAC9B;AAGA,UAAI,mBAAmB,QAAW;AACjC,sBAAc,iBAAiB;AAAA,MAChC;AAEA,aAAO,MAAM,iCAAiC;AAAA,QAC7C;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD,CAAC;AAGD,UAAI,UAAU;AAEb,eAAO,MAAM,aAAa,QAAQ,aAAa;AAAA,MAChD,OAAO;AAGN,YAAI,CAAC,cAAc,QAAQ;AAC1B,gBAAM,IAAI,MAAM,wDAAwD;AAAA,QACzE;AAEA,eAAO,MAAM,gCAAgC,QAAQ;AAAA,UACpD,GAAG;AAAA,UACH,eAAe,cAAc;AAAA,UAC7B;AAAA,QACD,CAAC;AAAA,MACF;AAAA,IACD,SAAS,OAAO;AACf,aAAO,MAAM,wCAAwC,EAAE,OAAO,QAAQ,CAAC;AACvE,YAAM;AAAA,IACP;AAAA,EACD;AAED;","names":[]}
1
+ {"version":3,"sources":["../src/lib/ClaudeService.ts"],"sourcesContent":["import { detectClaudeCli, launchClaude, launchClaudeInNewTerminalWindow, ClaudeCliOptions } from '../utils/claude.js'\nimport { PromptTemplateManager, TemplateVariables } from './PromptTemplateManager.js'\nimport { SettingsManager, IloomSettings } from './SettingsManager.js'\nimport { logger } from '../utils/logger.js'\n\nexport interface ClaudeWorkflowOptions {\n\ttype: 'issue' | 'pr' | 'regular'\n\tissueNumber?: string | number\n\tprNumber?: number\n\ttitle?: string\n\tworkspacePath: string\n\tport?: number\n\theadless?: boolean\n\tbranchName?: string\n\toneShot?: import('../types/index.js').OneShotMode\n\tsetArguments?: string[] // Raw --set arguments to forward\n\texecutablePath?: string // Executable path to use for spin command\n}\n\nexport class ClaudeService {\n\tprivate templateManager: PromptTemplateManager\n\tprivate settingsManager: SettingsManager\n\tprivate settings?: IloomSettings\n\n\tconstructor(templateManager?: PromptTemplateManager, settingsManager?: SettingsManager) {\n\t\tthis.templateManager = templateManager ?? new PromptTemplateManager()\n\t\tthis.settingsManager = settingsManager ?? new SettingsManager()\n\t}\n\n\t/**\n\t * Check if Claude CLI is available\n\t */\n\tasync isAvailable(): Promise<boolean> {\n\t\treturn detectClaudeCli()\n\t}\n\n\t/**\n\t * Get the appropriate permission mode for a workflow type\n\t */\n\tprivate getPermissionModeForWorkflow(\n\t\ttype: 'issue' | 'pr' | 'regular'\n\t): ClaudeCliOptions['permissionMode'] {\n\t\t// Check settings for configured permission mode\n\t\tif (this.settings?.workflows) {\n\t\t\tconst workflowConfig =\n\t\t\t\ttype === 'issue'\n\t\t\t\t\t? this.settings.workflows.issue\n\t\t\t\t\t: type === 'pr'\n\t\t\t\t\t\t? this.settings.workflows.pr\n\t\t\t\t\t\t: this.settings.workflows.regular\n\n\t\t\tif (workflowConfig?.permissionMode) {\n\t\t\t\treturn workflowConfig.permissionMode\n\t\t\t}\n\t\t}\n\n\t\t// Fall back to acceptEdits for all workflow types\n\t\treturn 'acceptEdits'\n\t}\n\n\t/**\n\t * Launch Claude for a specific workflow\n\t */\n\tasync launchForWorkflow(options: ClaudeWorkflowOptions): Promise<string | void> {\n\t\tconst { type, issueNumber, prNumber, title, workspacePath, port, headless = false, branchName, oneShot = 'default', setArguments, executablePath } = options\n\n\t\ttry {\n\t\t\t// Load settings if not already cached\n\t\t\t// Settings are pre-validated at CLI startup, so no error handling needed here\n\t\t\tthis.settings ??= await this.settingsManager.loadSettings()\n\n\t\t\t// Build template variables\n\t\t\tconst variables: TemplateVariables = {\n\t\t\t\tWORKSPACE_PATH: workspacePath,\n\t\t\t}\n\n\t\t\tif (issueNumber !== undefined) {\n\t\t\t\tvariables.ISSUE_NUMBER = issueNumber\n\t\t\t}\n\n\t\t\tif (prNumber !== undefined) {\n\t\t\t\tvariables.PR_NUMBER = prNumber\n\t\t\t}\n\n\t\t\tif (title !== undefined) {\n\t\t\t\tif (type === 'issue') {\n\t\t\t\t\tvariables.ISSUE_TITLE = title\n\t\t\t\t} else if (type === 'pr') {\n\t\t\t\t\tvariables.PR_TITLE = title\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (port !== undefined) {\n\t\t\t\tvariables.PORT = port\n\t\t\t}\n\n\t\t\t// Detect VS Code mode\n\t\t\tconst isVscodeMode = process.env.ILOOM_VSCODE === '1'\n\t\t\tvariables.IS_VSCODE_MODE = isVscodeMode\n\n\t\t\t// Get the prompt from template manager\n\t\t\tconst prompt = await this.templateManager.getPrompt(type, variables)\n\n\t\t\t// Determine permission mode (model uses Claude's default for start command)\n\t\t\tconst permissionMode = this.getPermissionModeForWorkflow(type)\n\n\t\t\t// Display warning if bypassPermissions mode is used\n\t\t\tif (permissionMode === 'bypassPermissions') {\n\t\t\t\tlogger.warn(\n\t\t\t\t\t'⚠️ WARNING: Using bypassPermissions mode - Claude will execute all tool calls without confirmation. ' +\n\t\t\t\t\t\t'This can be dangerous. Use with caution.'\n\t\t\t\t)\n\t\t\t}\n\n\t\t\t// Build Claude CLI options\n\t\t\tconst claudeOptions: ClaudeCliOptions = {\n\t\t\t\taddDir: workspacePath,\n\t\t\t\theadless,\n\t\t\t}\n\n\t\t\t// Add permission mode if not default\n\t\t\tif (permissionMode !== undefined && permissionMode !== 'default') {\n\t\t\t\tclaudeOptions.permissionMode = permissionMode\n\t\t\t}\n\n\t\t\t// Add optional branch name for terminal coloring\n\t\t\tif (branchName !== undefined) {\n\t\t\t\tclaudeOptions.branchName = branchName\n\t\t\t}\n\n\t\t\t// Add optional port for terminal window export\n\t\t\tif (port !== undefined) {\n\t\t\t\tclaudeOptions.port = port\n\t\t\t}\n\n\t\t\t// Add optional setArguments for forwarding\n\t\t\tif (setArguments !== undefined) {\n\t\t\t\tclaudeOptions.setArguments = setArguments\n\t\t\t}\n\n\t\t\t// Add optional executablePath for spin command\n\t\t\tif (executablePath !== undefined) {\n\t\t\t\tclaudeOptions.executablePath = executablePath\n\t\t\t}\n\n\t\t\tlogger.debug('Launching Claude for workflow', {\n\t\t\t\ttype,\n\t\t\t\tpermissionMode,\n\t\t\t\theadless,\n\t\t\t\tworkspacePath,\n\t\t\t})\n\n\t\t\t// Launch Claude\n\t\t\tif (headless) {\n\t\t\t\t// Headless mode: use simple launchClaude\n\t\t\t\treturn await launchClaude(prompt, claudeOptions)\n\t\t\t} else {\n\t\t\t\t// Interactive workflow mode: use terminal window launcher\n\t\t\t\t// This is the \"end of il start\" behavior\n\t\t\t\tif (!claudeOptions.addDir) {\n\t\t\t\t\tthrow new Error('workspacePath required for interactive workflow launch')\n\t\t\t\t}\n\n\t\t\t\treturn await launchClaudeInNewTerminalWindow(prompt, {\n\t\t\t\t\t...claudeOptions,\n\t\t\t\t\tworkspacePath: claudeOptions.addDir,\n\t\t\t\t\toneShot,\n\t\t\t\t})\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tlogger.error('Failed to launch Claude for workflow', { error, options })\n\t\t\tthrow error\n\t\t}\n\t}\n\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAmBO,IAAM,gBAAN,MAAoB;AAAA,EAK1B,YAAY,iBAAyC,iBAAmC;AACvF,SAAK,kBAAkB,mBAAmB,IAAI,sBAAsB;AACpE,SAAK,kBAAkB,mBAAmB,IAAI,gBAAgB;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAgC;AACrC,WAAO,gBAAgB;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKQ,6BACP,MACqC;AAzCvC;AA2CE,SAAI,UAAK,aAAL,mBAAe,WAAW;AAC7B,YAAM,iBACL,SAAS,UACN,KAAK,SAAS,UAAU,QACxB,SAAS,OACR,KAAK,SAAS,UAAU,KACxB,KAAK,SAAS,UAAU;AAE7B,UAAI,iDAAgB,gBAAgB;AACnC,eAAO,eAAe;AAAA,MACvB;AAAA,IACD;AAGA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,kBAAkB,SAAwD;AAC/E,UAAM,EAAE,MAAM,aAAa,UAAU,OAAO,eAAe,MAAM,WAAW,OAAO,YAAY,UAAU,WAAW,cAAc,eAAe,IAAI;AAErJ,QAAI;AAGH,WAAK,aAAa,MAAM,KAAK,gBAAgB,aAAa;AAG1D,YAAM,YAA+B;AAAA,QACpC,gBAAgB;AAAA,MACjB;AAEA,UAAI,gBAAgB,QAAW;AAC9B,kBAAU,eAAe;AAAA,MAC1B;AAEA,UAAI,aAAa,QAAW;AAC3B,kBAAU,YAAY;AAAA,MACvB;AAEA,UAAI,UAAU,QAAW;AACxB,YAAI,SAAS,SAAS;AACrB,oBAAU,cAAc;AAAA,QACzB,WAAW,SAAS,MAAM;AACzB,oBAAU,WAAW;AAAA,QACtB;AAAA,MACD;AAEA,UAAI,SAAS,QAAW;AACvB,kBAAU,OAAO;AAAA,MAClB;AAGA,YAAM,eAAe,QAAQ,IAAI,iBAAiB;AAClD,gBAAU,iBAAiB;AAG3B,YAAM,SAAS,MAAM,KAAK,gBAAgB,UAAU,MAAM,SAAS;AAGnE,YAAM,iBAAiB,KAAK,6BAA6B,IAAI;AAG7D,UAAI,mBAAmB,qBAAqB;AAC3C,eAAO;AAAA,UACN;AAAA,QAED;AAAA,MACD;AAGA,YAAM,gBAAkC;AAAA,QACvC,QAAQ;AAAA,QACR;AAAA,MACD;AAGA,UAAI,mBAAmB,UAAa,mBAAmB,WAAW;AACjE,sBAAc,iBAAiB;AAAA,MAChC;AAGA,UAAI,eAAe,QAAW;AAC7B,sBAAc,aAAa;AAAA,MAC5B;AAGA,UAAI,SAAS,QAAW;AACvB,sBAAc,OAAO;AAAA,MACtB;AAGA,UAAI,iBAAiB,QAAW;AAC/B,sBAAc,eAAe;AAAA,MAC9B;AAGA,UAAI,mBAAmB,QAAW;AACjC,sBAAc,iBAAiB;AAAA,MAChC;AAEA,aAAO,MAAM,iCAAiC;AAAA,QAC7C;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACD,CAAC;AAGD,UAAI,UAAU;AAEb,eAAO,MAAM,aAAa,QAAQ,aAAa;AAAA,MAChD,OAAO;AAGN,YAAI,CAAC,cAAc,QAAQ;AAC1B,gBAAM,IAAI,MAAM,wDAAwD;AAAA,QACzE;AAEA,eAAO,MAAM,gCAAgC,QAAQ;AAAA,UACpD,GAAG;AAAA,UACH,eAAe,cAAc;AAAA,UAC7B;AAAA,QACD,CAAC;AAAA,MACF;AAAA,IACD,SAAS,OAAO;AACf,aAAO,MAAM,wCAAwC,EAAE,OAAO,QAAQ,CAAC;AACvE,YAAM;AAAA,IACP;AAAA,EACD;AAED;","names":[]}
@@ -1,19 +1,25 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  PRManager
4
- } from "./chunk-I3HMNWQQ.js";
4
+ } from "./chunk-ZW2LKWWE.js";
5
+ import {
6
+ archiveRecap
7
+ } from "./chunk-Y4YZTHZE.js";
5
8
  import {
6
9
  calculatePortForBranch,
7
10
  calculatePortFromIdentifier
8
- } from "./chunk-USSL2X4A.js";
11
+ } from "./chunk-3D7WQM7I.js";
9
12
  import {
10
13
  installDependencies,
11
14
  runScript
12
- } from "./chunk-4LKGCFGG.js";
15
+ } from "./chunk-WWKOVDWC.js";
13
16
  import {
14
17
  getPackageConfig,
15
18
  hasScript
16
- } from "./chunk-VOGGLPG5.js";
19
+ } from "./chunk-YQ57ORTV.js";
20
+ import {
21
+ generateRandomSessionId
22
+ } from "./chunk-ONQYPICO.js";
17
23
  import {
18
24
  GitCommandError,
19
25
  PLACEHOLDER_COMMIT_PREFIX,
@@ -31,16 +37,19 @@ import {
31
37
  isBranchMergedIntoMain,
32
38
  isFileTrackedByGit,
33
39
  pushBranchToRemote
34
- } from "./chunk-H6ST2TGP.js";
40
+ } from "./chunk-MNHZB4Z2.js";
35
41
  import {
36
42
  SettingsManager
37
- } from "./chunk-XFEK2X2D.js";
43
+ } from "./chunk-YYAKPQBT.js";
38
44
  import {
39
45
  MetadataManager
40
- } from "./chunk-KBEIQP4G.js";
46
+ } from "./chunk-KB64WNBZ.js";
41
47
  import {
42
48
  GitHubService
43
- } from "./chunk-Y5HSSIK2.js";
49
+ } from "./chunk-KXDRI47U.js";
50
+ import {
51
+ getLogger
52
+ } from "./chunk-6MLEBAYZ.js";
44
53
  import {
45
54
  calculateForegroundColor,
46
55
  generateColorFromBranchName,
@@ -49,12 +58,6 @@ import {
49
58
  rgbToHex,
50
59
  selectDistinctColor
51
60
  } from "./chunk-433MOLAU.js";
52
- import {
53
- generateRandomSessionId
54
- } from "./chunk-FO5GGFOV.js";
55
- import {
56
- getLogger
57
- } from "./chunk-6MLEBAYZ.js";
58
61
  import {
59
62
  detectDarkMode,
60
63
  findEnvFileForDatabaseUrl,
@@ -244,10 +247,10 @@ var LoomManager = class {
244
247
  * NEW: Checks for existing worktrees and reuses them if found
245
248
  */
246
249
  async createIloom(input) {
247
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
250
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
248
251
  getLogger().info("Fetching issue data...");
249
252
  const issueData = await this.fetchIssueData(input);
250
- if (input.type === "issue" || input.type === "pr" || input.type === "branch") {
253
+ if (input.type === "issue" || input.type === "epic" || input.type === "pr" || input.type === "branch") {
251
254
  getLogger().info("Checking for existing worktree...");
252
255
  const existing = await this.findExistingIloom(input, issueData);
253
256
  if (existing) {
@@ -259,7 +262,7 @@ var LoomManager = class {
259
262
  getLogger().info("Preparing branch name...");
260
263
  const branchName = await this.prepareBranchName(input, issueData);
261
264
  getLogger().info("Creating git worktree...");
262
- const worktreePath = await this.createWorktreeOnly(input, branchName);
265
+ const worktreePath = await this.createWorktreeOnly(input, branchName, issueData);
263
266
  this.loadMainEnvFile();
264
267
  const { capabilities, binEntries } = await this.capabilityDetector.detectCapabilities(worktreePath);
265
268
  await this.copyEnvironmentFiles(worktreePath);
@@ -332,7 +335,7 @@ var LoomManager = class {
332
335
  let draftPrNumber = void 0;
333
336
  let draftPrUrl = void 0;
334
337
  const mergeBehavior = settingsData.mergeBehavior ?? { mode: "local" };
335
- if (mergeBehavior.mode === "github-draft-pr" && (input.type === "issue" || input.type === "branch")) {
338
+ if (mergeBehavior.mode === "github-draft-pr" && (input.type === "issue" || input.type === "epic" || input.type === "branch")) {
336
339
  const prManager = new PRManager(settingsData);
337
340
  getLogger().info("Fetching from origin...");
338
341
  await executeGitCommand(["fetch", "origin"], { cwd: worktreePath });
@@ -367,6 +370,8 @@ var LoomManager = class {
367
370
  getLogger().debug("Placeholder commit created");
368
371
  getLogger().info("Pushing branch to remote for draft PR...");
369
372
  await pushBranchToRemote(branchName, worktreePath, { dryRun: false });
373
+ await executeGitCommand(["reset", "--soft", "HEAD~1"], { cwd: worktreePath });
374
+ getLogger().debug("Placeholder commit removed from local branch (still on remote)");
370
375
  }
371
376
  const existingPR = await prManager.checkForExistingPR(branchName, worktreePath);
372
377
  if (existingPR) {
@@ -376,7 +381,7 @@ var LoomManager = class {
376
381
  } else {
377
382
  const prTitle = (issueData == null ? void 0 : issueData.title) ?? `Work on ${branchName}`;
378
383
  let prBody;
379
- if (input.type === "issue") {
384
+ if (input.type === "issue" || input.type === "epic") {
380
385
  const issueBody = (issueData == null ? void 0 : issueData.body) ? `
381
386
 
382
387
  ## ${issueData.title}
@@ -419,7 +424,7 @@ ${issueData.body}` : "";
419
424
  error
420
425
  );
421
426
  }
422
- if (input.type === "issue") {
427
+ if (input.type === "issue" || input.type === "epic") {
423
428
  try {
424
429
  getLogger().info("Moving issue to In Progress...");
425
430
  if (this.issueTracker.moveIssueToInProgress) {
@@ -440,8 +445,8 @@ ${issueData.body}` : "";
440
445
  const setArguments = (_k = input.options) == null ? void 0 : _k.setArguments;
441
446
  const executablePath = (_l = input.options) == null ? void 0 : _l.executablePath;
442
447
  if (enableClaude || enableCode || enableDevServer || enableTerminal) {
443
- const { LoomLauncher } = await import("./LoomLauncher-3I47SUPV.js");
444
- const { ClaudeContextManager } = await import("./ClaudeContextManager-X2Y72GRL.js");
448
+ const { LoomLauncher } = await import("./LoomLauncher-L64HHS3T.js");
449
+ const { ClaudeContextManager } = await import("./ClaudeContextManager-QXX6ZFST.js");
445
450
  const claudeContext = new ClaudeContextManager(void 0, void 0, this.settings);
446
451
  const launcher = new LoomLauncher(claudeContext, this.settings);
447
452
  await launcher.launchLoom({
@@ -453,7 +458,7 @@ ${issueData.body}` : "";
453
458
  branchName,
454
459
  port,
455
460
  capabilities,
456
- workflowType: input.type === "branch" ? "regular" : input.type,
461
+ workflowType: input.type === "branch" ? "regular" : input.type === "epic" ? "issue" : input.type,
457
462
  identifier: input.identifier,
458
463
  ...(issueData == null ? void 0 : issueData.title) && { title: issueData.title },
459
464
  oneShot,
@@ -467,7 +472,7 @@ ${issueData.body}` : "";
467
472
  const description = (issueData == null ? void 0 : issueData.title) ?? branchName;
468
473
  let issue_numbers = [];
469
474
  let extractedIssueNum = null;
470
- if (input.type === "issue") {
475
+ if (input.type === "issue" || input.type === "epic") {
471
476
  issue_numbers = [String(input.identifier)];
472
477
  } else if (input.type === "pr") {
473
478
  extractedIssueNum = extractIssueNumber(branchName);
@@ -481,7 +486,7 @@ ${issueData.body}` : "";
481
486
  }
482
487
  const sessionId = generateRandomSessionId();
483
488
  let issueUrls = {};
484
- if (input.type === "issue" && (issueData == null ? void 0 : issueData.url)) {
489
+ if ((input.type === "issue" || input.type === "epic") && (issueData == null ? void 0 : issueData.url)) {
485
490
  issueUrls = { [String(input.identifier)]: issueData.url };
486
491
  } else if (input.type === "pr" && extractedIssueNum && (issueData == null ? void 0 : issueData.url)) {
487
492
  const issueUrl = issueData.url.replace(`/pull/${input.identifier}`, `/issues/${extractedIssueNum}`);
@@ -493,6 +498,7 @@ ${issueData.body}` : "";
493
498
  branchName,
494
499
  worktreePath,
495
500
  issueType: input.type,
501
+ ...(input.type === "issue" || input.type === "epic") && { issueKey: this.issueTracker.normalizeIdentifier(input.identifier) },
496
502
  issue_numbers,
497
503
  pr_numbers,
498
504
  issueTracker: this.issueTracker.providerName,
@@ -504,6 +510,9 @@ ${issueData.body}` : "";
504
510
  capabilities,
505
511
  ...draftPrNumber && { draftPrNumber },
506
512
  ...((_o = input.options) == null ? void 0 : _o.oneShot) && { oneShot: input.options.oneShot },
513
+ ...((_p = input.options) == null ? void 0 : _p.childIssueNumbers) && input.options.childIssueNumbers.length > 0 && { childIssueNumbers: input.options.childIssueNumbers },
514
+ ...((_q = input.options) == null ? void 0 : _q.childIssues) && input.options.childIssues.length > 0 && { childIssues: input.options.childIssues },
515
+ ...((_r = input.options) == null ? void 0 : _r.dependencyMap) && Object.keys(input.options.dependencyMap).length > 0 && { dependencyMap: input.options.dependencyMap },
507
516
  ...input.parentLoom && { parentLoom: input.parentLoom }
508
517
  };
509
518
  await this.metadataManager.writeMetadata(worktreePath, metadataInput);
@@ -592,7 +601,7 @@ ${issueData.body}` : "";
592
601
  async checkAndWarnChildLooms(branchName) {
593
602
  let targetBranch = branchName;
594
603
  if (!targetBranch) {
595
- const { getCurrentBranch } = await import("./git-W3XUIFTR.js");
604
+ const { getCurrentBranch } = await import("./git-ET64COO3.js");
596
605
  targetBranch = await getCurrentBranch();
597
606
  }
598
607
  if (!targetBranch) {
@@ -621,7 +630,7 @@ ${issueData.body}` : "";
621
630
  * Fetch issue/PR data based on input type
622
631
  */
623
632
  async fetchIssueData(input) {
624
- if (input.type === "issue") {
633
+ if (input.type === "issue" || input.type === "epic") {
625
634
  return await this.issueTracker.fetchIssue(input.identifier);
626
635
  } else if (input.type === "pr") {
627
636
  if (this.issueTracker.supportsPullRequests && this.issueTracker.fetchPR) {
@@ -645,7 +654,7 @@ ${issueData.body}` : "";
645
654
  if (input.type === "pr" && issueData && "branch" in issueData) {
646
655
  return issueData.branch;
647
656
  }
648
- if (input.type === "issue" && issueData) {
657
+ if ((input.type === "issue" || input.type === "epic") && issueData) {
649
658
  const branchName = await this.branchNaming.generateBranchName({
650
659
  issueNumber: input.identifier,
651
660
  title: issueData.title
@@ -660,7 +669,7 @@ ${issueData.body}` : "";
660
669
  /**
661
670
  * Create worktree for the loom (without dependency installation)
662
671
  */
663
- async createWorktreeOnly(input, branchName) {
672
+ async createWorktreeOnly(input, branchName, issueData) {
664
673
  var _a;
665
674
  getLogger().info("Ensuring repository has initial commit...");
666
675
  await ensureRepositoryHasCommits(this.gitWorktree.workingDirectory);
@@ -680,15 +689,31 @@ ${issueData.body}` : "";
680
689
  void 0,
681
690
  pathOptions
682
691
  );
692
+ const isForkPR = input.type === "pr" && issueData && "isFork" in issueData && issueData.isFork === true;
683
693
  if (input.type === "pr") {
684
- getLogger().info("Fetching all remote branches...");
685
- try {
686
- await executeGitCommand(["fetch", "origin"], { cwd: this.gitWorktree.workingDirectory });
687
- getLogger().success("Successfully fetched from remote");
688
- } catch (error) {
689
- throw new Error(
690
- `Failed to fetch from remote: ${error instanceof Error ? error.message : "Unknown error"}. Make sure you have access to the repository.`
691
- );
694
+ if (isForkPR) {
695
+ getLogger().info(`Fetching PR #${input.identifier} ref from origin...`);
696
+ try {
697
+ await executeGitCommand(
698
+ ["fetch", "origin", `refs/pull/${input.identifier}/head`],
699
+ { cwd: this.gitWorktree.workingDirectory }
700
+ );
701
+ getLogger().success("Successfully fetched PR ref from remote");
702
+ } catch (error) {
703
+ throw new Error(
704
+ `Failed to fetch PR ref: ${error instanceof Error ? error.message : "Unknown error"}. Make sure you have access to the repository.`
705
+ );
706
+ }
707
+ } else {
708
+ getLogger().info("Fetching all remote branches...");
709
+ try {
710
+ await executeGitCommand(["fetch", "origin"], { cwd: this.gitWorktree.workingDirectory });
711
+ getLogger().success("Successfully fetched from remote");
712
+ } catch (error) {
713
+ throw new Error(
714
+ `Failed to fetch from remote: ${error instanceof Error ? error.message : "Unknown error"}. Make sure you have access to the repository.`
715
+ );
716
+ }
692
717
  }
693
718
  }
694
719
  const branchExistedLocally = await branchExists(branchName, process.cwd(), false);
@@ -712,21 +737,33 @@ ${issueData.body}` : "";
712
737
  } else {
713
738
  baseBranch = input.baseBranch;
714
739
  }
715
- await this.gitWorktree.createWorktree({
716
- path: worktreePath,
717
- branch: branchName,
718
- createBranch: input.type !== "pr",
719
- // PRs use existing branches
720
- ...baseBranch && { baseBranch }
721
- });
722
- if (input.type === "pr" && !branchExistedLocally) {
723
- getLogger().info("Resetting new PR branch to match remote exactly...");
724
- try {
725
- await executeGitCommand(["reset", "--hard", `origin/${branchName}`], { cwd: worktreePath });
726
- await executeGitCommand(["branch", "--set-upstream-to", `origin/${branchName}`], { cwd: worktreePath });
727
- getLogger().success("Successfully reset to match remote");
728
- } catch (error) {
729
- getLogger().warn(`Failed to reset to match remote: ${error instanceof Error ? error.message : "Unknown error"}`);
740
+ if (isForkPR) {
741
+ if (branchExistedLocally) {
742
+ await executeGitCommand(["branch", "-D", branchName], { cwd: this.gitWorktree.workingDirectory });
743
+ }
744
+ await this.gitWorktree.createWorktree({
745
+ path: worktreePath,
746
+ branch: branchName,
747
+ createBranch: true,
748
+ baseBranch: "FETCH_HEAD"
749
+ });
750
+ } else {
751
+ await this.gitWorktree.createWorktree({
752
+ path: worktreePath,
753
+ branch: branchName,
754
+ createBranch: input.type !== "pr",
755
+ // PRs use existing branches
756
+ ...baseBranch && { baseBranch }
757
+ });
758
+ if (input.type === "pr" && !branchExistedLocally) {
759
+ getLogger().info("Resetting new PR branch to match remote exactly...");
760
+ try {
761
+ await executeGitCommand(["reset", "--hard", `origin/${branchName}`], { cwd: worktreePath });
762
+ await executeGitCommand(["branch", "--set-upstream-to", `origin/${branchName}`], { cwd: worktreePath });
763
+ getLogger().success("Successfully reset to match remote");
764
+ } catch (error) {
765
+ getLogger().warn(`Failed to reset to match remote: ${error instanceof Error ? error.message : "Unknown error"}`);
766
+ }
730
767
  }
731
768
  }
732
769
  return worktreePath;
@@ -890,7 +927,7 @@ ${issueData.body}` : "";
890
927
  async setupPortForWeb(worktreePath, input, basePort) {
891
928
  const envFilePath = path2.join(worktreePath, ".env.local");
892
929
  const options = { basePort };
893
- if (input.type === "issue") {
930
+ if (input.type === "issue" || input.type === "epic") {
894
931
  options.issueNumber = input.identifier;
895
932
  } else if (input.type === "pr") {
896
933
  options.prNumber = input.identifier;
@@ -935,7 +972,7 @@ ${issueData.body}` : "";
935
972
  var _a, _b;
936
973
  const settingsData = await this.settings.loadSettings();
937
974
  const basePort = ((_b = (_a = settingsData.capabilities) == null ? void 0 : _a.web) == null ? void 0 : _b.basePort) ?? 3e3;
938
- if (input.type === "issue") {
975
+ if (input.type === "issue" || input.type === "epic") {
939
976
  if (typeof input.identifier === "number") {
940
977
  return this.environment.calculatePort({ basePort, issueNumber: input.identifier });
941
978
  } else if (typeof input.identifier === "string") {
@@ -989,8 +1026,8 @@ ${issueData.body}` : "";
989
1026
  let identifier = wt.branch;
990
1027
  if (loomMetadata == null ? void 0 : loomMetadata.issueType) {
991
1028
  type = loomMetadata.issueType;
992
- if (type === "issue" && ((_a = loomMetadata.issue_numbers) == null ? void 0 : _a[0])) {
993
- const issueId = loomMetadata.issue_numbers[0];
1029
+ if (type === "issue" && (loomMetadata.issueKey || ((_a = loomMetadata.issue_numbers) == null ? void 0 : _a[0]))) {
1030
+ const issueId = loomMetadata.issueKey ?? loomMetadata.issue_numbers[0] ?? "";
994
1031
  const numericId = parseInt(issueId, 10);
995
1032
  identifier = isNaN(numericId) ? issueId : numericId;
996
1033
  } else if (type === "pr" && ((_b = loomMetadata.pr_numbers) == null ? void 0 : _b[0])) {
@@ -1052,7 +1089,7 @@ ${issueData.body}` : "";
1052
1089
  * Ports: handle_existing_worktree() from bash script lines 168-215
1053
1090
  */
1054
1091
  async reuseIloom(worktree, input, issueData) {
1055
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
1092
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
1056
1093
  const worktreePath = worktree.path;
1057
1094
  const branchName = worktree.branch;
1058
1095
  this.loadMainEnvFile();
@@ -1112,8 +1149,8 @@ ${issueData.body}` : "";
1112
1149
  const executablePath = (_i = input.options) == null ? void 0 : _i.executablePath;
1113
1150
  if (enableClaude || enableCode || enableDevServer || enableTerminal) {
1114
1151
  getLogger().info("Launching workspace components...");
1115
- const { LoomLauncher } = await import("./LoomLauncher-3I47SUPV.js");
1116
- const { ClaudeContextManager } = await import("./ClaudeContextManager-X2Y72GRL.js");
1152
+ const { LoomLauncher } = await import("./LoomLauncher-L64HHS3T.js");
1153
+ const { ClaudeContextManager } = await import("./ClaudeContextManager-QXX6ZFST.js");
1117
1154
  const claudeContext = new ClaudeContextManager(void 0, void 0, this.settings);
1118
1155
  const launcher = new LoomLauncher(claudeContext, this.settings);
1119
1156
  await launcher.launchLoom({
@@ -1125,7 +1162,7 @@ ${issueData.body}` : "";
1125
1162
  branchName,
1126
1163
  port,
1127
1164
  capabilities,
1128
- workflowType: input.type === "branch" ? "regular" : input.type,
1165
+ workflowType: input.type === "branch" ? "regular" : input.type === "epic" ? "issue" : input.type,
1129
1166
  identifier: input.identifier,
1130
1167
  ...(issueData == null ? void 0 : issueData.title) && { title: issueData.title },
1131
1168
  oneShot,
@@ -1163,6 +1200,7 @@ ${issueData.body}` : "";
1163
1200
  branchName,
1164
1201
  worktreePath,
1165
1202
  issueType: input.type,
1203
+ ...input.type === "issue" && { issueKey: this.issueTracker.normalizeIdentifier(input.identifier) },
1166
1204
  issue_numbers,
1167
1205
  pr_numbers,
1168
1206
  issueTracker: this.issueTracker.providerName,
@@ -1173,6 +1211,7 @@ ${issueData.body}` : "";
1173
1211
  prUrls,
1174
1212
  capabilities,
1175
1213
  ...((_l = input.options) == null ? void 0 : _l.oneShot) && { oneShot: input.options.oneShot },
1214
+ ...((_m = input.options) == null ? void 0 : _m.childIssueNumbers) && input.options.childIssueNumbers.length > 0 && { childIssueNumbers: input.options.childIssueNumbers },
1176
1215
  ...input.parentLoom && { parentLoom: input.parentLoom }
1177
1216
  };
1178
1217
  await this.metadataManager.writeMetadata(worktreePath, metadataInput);
@@ -1848,41 +1887,7 @@ var DatabaseManager = class {
1848
1887
  };
1849
1888
 
1850
1889
  // src/lib/ResourceCleanup.ts
1851
- import path5 from "path";
1852
-
1853
- // src/utils/recap-archiver.ts
1854
1890
  import path4 from "path";
1855
- import os2 from "os";
1856
- import fs6 from "fs-extra";
1857
- var RECAPS_DIR = path4.join(os2.homedir(), ".config", "iloom-ai", "recaps");
1858
- var ARCHIVED_DIR = path4.join(RECAPS_DIR, "archived");
1859
- function slugifyPath(loomPath) {
1860
- let slug = loomPath.replace(/[/\\]+$/, "");
1861
- slug = slug.replace(/[/\\]/g, "___");
1862
- slug = slug.replace(/[^a-zA-Z0-9_-]/g, "-");
1863
- return `${slug}.json`;
1864
- }
1865
- async function archiveRecap(worktreePath) {
1866
- const filename = slugifyPath(worktreePath);
1867
- const sourcePath = path4.join(RECAPS_DIR, filename);
1868
- if (!await fs6.pathExists(sourcePath)) {
1869
- getLogger().debug(`No recap file to archive for worktree: ${worktreePath}`);
1870
- return;
1871
- }
1872
- const content = await fs6.readFile(sourcePath, "utf8");
1873
- const data = JSON.parse(content);
1874
- const archivedData = {
1875
- ...data,
1876
- archivedAt: (/* @__PURE__ */ new Date()).toISOString()
1877
- };
1878
- await fs6.ensureDir(ARCHIVED_DIR, { mode: 493 });
1879
- const destPath = path4.join(ARCHIVED_DIR, filename);
1880
- await fs6.writeFile(destPath, JSON.stringify(archivedData, null, 2), { mode: 420 });
1881
- await fs6.unlink(sourcePath);
1882
- getLogger().debug(`Recap archived for worktree: ${worktreePath}`);
1883
- }
1884
-
1885
- // src/lib/ResourceCleanup.ts
1886
1891
  var ResourceCleanup = class {
1887
1892
  constructor(gitWorktree, processManager, database, cliIsolation, settingsManager) {
1888
1893
  this.gitWorktree = gitWorktree;
@@ -1938,16 +1943,28 @@ var ResourceCleanup = class {
1938
1943
  }
1939
1944
  let worktree = null;
1940
1945
  try {
1941
- if (parsed.type === "pr" && parsed.number !== void 0) {
1942
- const prNumber = typeof parsed.number === "number" ? parsed.number : Number(parsed.number);
1943
- if (isNaN(prNumber) || !isFinite(prNumber)) {
1944
- throw new Error(`Invalid PR number: ${parsed.number}. PR numbers must be numeric.`);
1946
+ if (options.worktree) {
1947
+ worktree = {
1948
+ path: options.worktree.path,
1949
+ branch: options.worktree.branch,
1950
+ commit: "",
1951
+ bare: false,
1952
+ detached: false,
1953
+ locked: false
1954
+ };
1955
+ getLogger().debug(`Using pre-resolved worktree: path="${worktree.path}", branch="${worktree.branch}"`);
1956
+ } else {
1957
+ if (parsed.type === "pr" && parsed.number !== void 0) {
1958
+ const prNumber = typeof parsed.number === "number" ? parsed.number : Number(parsed.number);
1959
+ if (isNaN(prNumber) || !isFinite(prNumber)) {
1960
+ throw new Error(`Invalid PR number: ${parsed.number}. PR numbers must be numeric.`);
1961
+ }
1962
+ worktree = await this.gitWorktree.findWorktreeForPR(prNumber, "");
1963
+ } else if (parsed.type === "issue" && parsed.number !== void 0) {
1964
+ worktree = await this.gitWorktree.findWorktreeForIssue(parsed.number);
1965
+ } else if (parsed.type === "branch" && parsed.branchName) {
1966
+ worktree = await this.gitWorktree.findWorktreeForBranch(parsed.branchName);
1945
1967
  }
1946
- worktree = await this.gitWorktree.findWorktreeForPR(prNumber, "");
1947
- } else if (parsed.type === "issue" && parsed.number !== void 0) {
1948
- worktree = await this.gitWorktree.findWorktreeForIssue(parsed.number);
1949
- } else if (parsed.type === "branch" && parsed.branchName) {
1950
- worktree = await this.gitWorktree.findWorktreeForBranch(parsed.branchName);
1951
1968
  }
1952
1969
  if (!worktree) {
1953
1970
  throw new Error(`No worktree found for identifier: ${displayIdentifier}`);
@@ -1984,7 +2001,7 @@ ${blockerMessage}`);
1984
2001
  }
1985
2002
  let databaseConfig = null;
1986
2003
  if (!options.keepDatabase && worktree) {
1987
- const envFilePath = path5.join(worktree.path, ".env");
2004
+ const envFilePath = path4.join(worktree.path, ".env");
1988
2005
  try {
1989
2006
  const shouldCleanup = this.database ? await this.database.shouldUseDatabaseBranching(envFilePath) : false;
1990
2007
  databaseConfig = { shouldCleanup, envFilePath };
@@ -2246,11 +2263,32 @@ ${blockerMessage}`);
2246
2263
  }
2247
2264
  if (worktree) {
2248
2265
  if (options.dryRun) {
2266
+ const action = options.archive ? "archive" : "delete";
2249
2267
  operations.push({
2250
2268
  type: "metadata",
2251
2269
  success: true,
2252
- message: `[DRY RUN] Would delete metadata for worktree: ${worktree.path}`
2270
+ message: `[DRY RUN] Would ${action} metadata for worktree: ${worktree.path}`
2253
2271
  });
2272
+ } else if (options.archive) {
2273
+ try {
2274
+ await this.metadataManager.archiveMetadata(worktree.path);
2275
+ getLogger().info(`Metadata archived for worktree: ${worktree.path}`);
2276
+ operations.push({
2277
+ type: "metadata",
2278
+ success: true,
2279
+ message: "Metadata archived"
2280
+ });
2281
+ } catch (error) {
2282
+ const err = error instanceof Error ? error : new Error(String(error));
2283
+ errors.push(err);
2284
+ getLogger().warn(`Metadata archival failed: ${err.message}`);
2285
+ operations.push({
2286
+ type: "metadata",
2287
+ success: false,
2288
+ message: "Metadata archival failed (non-fatal)",
2289
+ error: err.message
2290
+ });
2291
+ }
2254
2292
  } else {
2255
2293
  try {
2256
2294
  await this.metadataManager.deleteMetadata(worktree.path);
@@ -2421,7 +2459,7 @@ ${blockerMessage}`);
2421
2459
  return false;
2422
2460
  }
2423
2461
  try {
2424
- const envFilePath = path5.join(worktreePath, ".env");
2462
+ const envFilePath = path4.join(worktreePath, ".env");
2425
2463
  const shouldCleanup = await this.database.shouldUseDatabaseBranching(envFilePath);
2426
2464
  let cwd;
2427
2465
  try {
@@ -2605,4 +2643,4 @@ export {
2605
2643
  DatabaseManager,
2606
2644
  ResourceCleanup
2607
2645
  };
2608
- //# sourceMappingURL=chunk-4ZIHFUPN.js.map
2646
+ //# sourceMappingURL=chunk-UD3WJDIV.js.map