@iloom/cli 0.10.1 → 0.11.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 (262) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +4 -2
  3. package/dist/{BranchNamingService-25KSZAEM.js → BranchNamingService-XBCO747L.js} +4 -4
  4. package/dist/ClaudeContextManager-SXDCWDJA.js +14 -0
  5. package/dist/ClaudeService-6E6MCGJE.js +13 -0
  6. package/dist/GitHubService-2R5GQG4K.js +12 -0
  7. package/dist/IssueTrackerFactory-XN6MQ4UN.js +14 -0
  8. package/dist/{LoomLauncher-TDLZSYG2.js → LoomLauncher-5AZU2F5I.js} +15 -12
  9. package/dist/LoomLauncher-5AZU2F5I.js.map +1 -0
  10. package/dist/MetadataManager-CMQQTFLQ.js +10 -0
  11. package/dist/ProjectCapabilityDetector-IC6NAFGY.js +11 -0
  12. package/dist/{PromptTemplateManager-YOE2SIPG.js → PromptTemplateManager-T5VTLJP3.js} +3 -3
  13. package/dist/README.md +4 -2
  14. package/dist/{SettingsManager-FNKCOZMQ.js → SettingsManager-WQ5NSGAH.js} +3 -3
  15. package/dist/SettingsMigrationManager-S6J7OHUH.js +10 -0
  16. package/dist/agents/iloom-code-reviewer.md +50 -8
  17. package/dist/agents/iloom-issue-analyze-and-plan.md +10 -0
  18. package/dist/agents/iloom-issue-analyzer.md +13 -0
  19. package/dist/agents/iloom-issue-complexity-evaluator.md +8 -1
  20. package/dist/agents/iloom-issue-enhancer.md +8 -1
  21. package/dist/agents/iloom-issue-planner.md +5 -0
  22. package/dist/build-OLS6J5KZ.js +27 -0
  23. package/dist/{chunk-WWKOVDWC.js → chunk-3GTUXW26.js} +3 -3
  24. package/dist/{chunk-4FGEGQW4.js → chunk-3RXYOBME.js} +5 -5
  25. package/dist/{chunk-HEXKPKCK.js → chunk-5LTID2AF.js} +6 -6
  26. package/dist/{chunk-G5V75JD5.js → chunk-5PNZBH6V.js} +2 -2
  27. package/dist/{chunk-SKSYYBCU.js → chunk-5UFGO4ZT.js} +24 -3
  28. package/dist/{chunk-SKSYYBCU.js.map → chunk-5UFGO4ZT.js.map} +1 -1
  29. package/dist/{chunk-E6KOWMKA.js → chunk-6YVJVUR4.js} +3 -3
  30. package/dist/{chunk-RJ3VBUFK.js → chunk-7FIXNAUO.js} +36 -7
  31. package/dist/chunk-7FIXNAUO.js.map +1 -0
  32. package/dist/{chunk-QVLPWNE3.js → chunk-7NFCGKZT.js} +3 -3
  33. package/dist/{chunk-433MOLAU.js → chunk-7OCGBJLR.js} +2 -2
  34. package/dist/{chunk-KVHIAWVT.js → chunk-ABVMUNCD.js} +8 -8
  35. package/dist/{chunk-7JDMYTFZ.js → chunk-CV47VCMQ.js} +2 -2
  36. package/dist/{chunk-7VHJNVLF.js → chunk-ET6A2JR4.js} +8 -6
  37. package/dist/chunk-ET6A2JR4.js.map +1 -0
  38. package/dist/{chunk-MORRVYPT.js → chunk-G2MNSPA4.js} +2 -2
  39. package/dist/{chunk-RSYT7MVI.js → chunk-GMDSYLI6.js} +36 -3
  40. package/dist/chunk-GMDSYLI6.js.map +1 -0
  41. package/dist/{chunk-VT4PDUYT.js → chunk-H2SSF24U.js} +284 -209
  42. package/dist/chunk-H2SSF24U.js.map +1 -0
  43. package/dist/{chunk-LLHXQS3C.js → chunk-HLDY5S4C.js} +3 -3
  44. package/dist/{chunk-BYUMEDDD.js → chunk-IDCE26KD.js} +3 -3
  45. package/dist/{chunk-OTGH2HRS.js → chunk-IR74O2F6.js} +221 -88
  46. package/dist/chunk-IR74O2F6.js.map +1 -0
  47. package/dist/{chunk-O7VL5N6S.js → chunk-K7R5QY6C.js} +2 -2
  48. package/dist/{chunk-S7PZA6IV.js → chunk-KQFIGI37.js} +5 -5
  49. package/dist/{chunk-I5T677EA.js → chunk-LE2NOUTN.js} +3 -3
  50. package/dist/{chunk-KXDRI47U.js → chunk-LHDD4JHC.js} +6 -6
  51. package/dist/{chunk-5FJWO4IT.js → chunk-LL6TOX3G.js} +9 -9
  52. package/dist/{chunk-YQ57ORTV.js → chunk-NCPZYQ4B.js} +2 -2
  53. package/dist/{chunk-EWJFUFPT.js → chunk-NDSGJZI2.js} +2 -2
  54. package/dist/{chunk-VG45TUYK.js → chunk-NH3QZYE5.js} +2 -2
  55. package/dist/{chunk-KKV5WH5M.js → chunk-NN5RYWXA.js} +7 -7
  56. package/dist/chunk-NOMQ5RFG.js +118 -0
  57. package/dist/chunk-NOMQ5RFG.js.map +1 -0
  58. package/dist/{chunk-KIK2ZFAL.js → chunk-QNHZM5ZV.js} +3 -3
  59. package/dist/{chunk-EVPZFV3K.js → chunk-QR4FU53I.js} +8 -8
  60. package/dist/{chunk-FXDYIV3K.js → chunk-QVAA5KHK.js} +2 -2
  61. package/dist/{chunk-NGJZ4TOU.js → chunk-RBYTXYGD.js} +2 -2
  62. package/dist/{chunk-SWSJWA2S.js → chunk-RMLADZRY.js} +12 -9
  63. package/dist/chunk-RMLADZRY.js.map +1 -0
  64. package/dist/{chunk-CVCTIDDK.js → chunk-RVI6C2H5.js} +5 -5
  65. package/dist/{chunk-Q7POFB5Q.js → chunk-SQYHPBFP.js} +2 -2
  66. package/dist/{chunk-GRISNU6G.js → chunk-TEJAGQX2.js} +64 -40
  67. package/dist/chunk-TEJAGQX2.js.map +1 -0
  68. package/dist/{chunk-QZWEJVWV.js → chunk-TZNNJLGT.js} +6 -6
  69. package/dist/{chunk-63QWFWH3.js → chunk-UDCI3QTS.js} +2 -2
  70. package/dist/{chunk-UKBAJ2QQ.js → chunk-UHIBKD73.js} +7 -7
  71. package/dist/{chunk-WXIM2WS7.js → chunk-V4STTBQD.js} +10 -10
  72. package/dist/{chunk-P4O6EH46.js → chunk-VMZG66UV.js} +5 -5
  73. package/dist/{chunk-C6HNNJIV.js → chunk-VNYWBHKR.js} +34 -4
  74. package/dist/chunk-VNYWBHKR.js.map +1 -0
  75. package/dist/{chunk-5RPBYK5Q.js → chunk-VUUN3KE4.js} +10 -10
  76. package/dist/chunk-VUUN3KE4.js.map +1 -0
  77. package/dist/{chunk-UUEW5KWB.js → chunk-WG4MLJ6J.js} +15 -10
  78. package/dist/chunk-WG4MLJ6J.js.map +1 -0
  79. package/dist/{chunk-ZNMPGMHY.js → chunk-XFQGI2E3.js} +66 -43
  80. package/dist/chunk-XFQGI2E3.js.map +1 -0
  81. package/dist/{chunk-LUKXJSRI.js → chunk-XXFSOVL3.js} +4 -4
  82. package/dist/{chunk-UR5DGNUO.js → chunk-Y3RX7LZT.js} +11 -8
  83. package/dist/chunk-Y3RX7LZT.js.map +1 -0
  84. package/dist/{chunk-KB64WNBZ.js → chunk-YRCEOQPX.js} +4 -2
  85. package/dist/chunk-YRCEOQPX.js.map +1 -0
  86. package/dist/{chunk-6MLEBAYZ.js → chunk-ZAXRQLK3.js} +2 -2
  87. package/dist/{claude-7GGEWVEM.js → claude-ONQTDWV3.js} +4 -4
  88. package/dist/{cleanup-6PVAC4NI.js → cleanup-YOM6PQCN.js} +35 -34
  89. package/dist/{cleanup-6PVAC4NI.js.map → cleanup-YOM6PQCN.js.map} +1 -1
  90. package/dist/cli.js +235 -147
  91. package/dist/cli.js.map +1 -1
  92. package/dist/{color-4TJ4P5EY.js → color-VQD52LOI.js} +3 -3
  93. package/dist/{commit-FZR5XDQG.js → commit-DC2Q5CDY.js} +15 -15
  94. package/dist/{compile-7ALJHZ4N.js → compile-4NCQECKE.js} +11 -11
  95. package/dist/{contribute-5GKLK3BQ.js → contribute-M5UWXCAV.js} +12 -12
  96. package/dist/darwin-5BHWRJ7D.js +10 -0
  97. package/dist/{dev-server-7SMIB7OF.js → dev-server-CYRP6M73.js} +19 -19
  98. package/dist/{feedback-G2GJFN2F.js → feedback-BMAZGKRW.js} +16 -16
  99. package/dist/{git-GTLKAZRJ.js → git-BXUD6CL5.js} +6 -6
  100. package/dist/ignite-IO4LXVXJ.js +35 -0
  101. package/dist/index.d.ts +39 -65
  102. package/dist/index.js +637 -110
  103. package/dist/index.js.map +1 -1
  104. package/dist/{init-32YOKXRL.js → init-CI43GJHV.js} +17 -17
  105. package/dist/{init-32YOKXRL.js.map → init-CI43GJHV.js.map} +1 -1
  106. package/dist/install-deps-SRTM5U7D.js +43 -0
  107. package/dist/install-deps-SRTM5U7D.js.map +1 -0
  108. package/dist/{installation-detector-MMFWLJYN.js → installation-detector-HF6QN7KP.js} +3 -3
  109. package/dist/{issues-4UUAQ5K6.js → issues-DMRQJH7E.js} +15 -15
  110. package/dist/lint-BSWRMGPZ.js +27 -0
  111. package/dist/linux-RYLOP2LY.js +103 -0
  112. package/dist/linux-RYLOP2LY.js.map +1 -0
  113. package/dist/mcp/chunk-PIIRD4LO.js +373 -0
  114. package/dist/mcp/chunk-PIIRD4LO.js.map +1 -0
  115. package/dist/mcp/darwin-3JFFE3W2.js +10 -0
  116. package/dist/mcp/issue-management-server.js +23 -127
  117. package/dist/mcp/issue-management-server.js.map +1 -1
  118. package/dist/mcp/linux-JBVS4R3A.js +103 -0
  119. package/dist/mcp/linux-JBVS4R3A.js.map +1 -0
  120. package/dist/mcp/tmux-RYBLEHUZ.js +156 -0
  121. package/dist/mcp/tmux-RYBLEHUZ.js.map +1 -0
  122. package/dist/mcp/wsl-4QZIQLLE.js +78 -0
  123. package/dist/mcp/wsl-4QZIQLLE.js.map +1 -0
  124. package/dist/neon-helpers-HWIYRKOW.js +11 -0
  125. package/dist/{open-FXWW3VI4.js → open-2Y7GSUTJ.js} +19 -19
  126. package/dist/{plan-RQ5FPIGF.js → plan-SWFPLNJE.js} +47 -46
  127. package/dist/{plan-RQ5FPIGF.js.map → plan-SWFPLNJE.js.map} +1 -1
  128. package/dist/{projects-2UOXFLNZ.js → projects-IUSUXD5D.js} +6 -6
  129. package/dist/{prompt-ONNPSNKM.js → prompt-7LZB4PAT.js} +3 -3
  130. package/dist/prompts/init-prompt.txt +56 -107
  131. package/dist/prompts/issue-prompt.txt +57 -11
  132. package/dist/prompts/pr-prompt.txt +154 -4
  133. package/dist/prompts/regular-prompt.txt +20 -3
  134. package/dist/prompts/swarm-orchestrator-prompt.txt +134 -14
  135. package/dist/{rebase-6NVLX5V7.js → rebase-S6OHAOOF.js} +12 -12
  136. package/dist/{recap-OMBOKJST.js → recap-GGVCG5VH.js} +9 -9
  137. package/dist/{remote-IJAMOEAP.js → remote-MZTFHHTU.js} +3 -3
  138. package/dist/remote-MZTFHHTU.js.map +1 -0
  139. package/dist/{run-BBXLRIZB.js → run-ST3FR75O.js} +19 -19
  140. package/dist/schema/settings.schema.json +8 -49
  141. package/dist/{shell-RF7LTND5.js → shell-W4SBQPTE.js} +8 -8
  142. package/dist/{summary-WTQZ7XG2.js → summary-P2JCIIJO.js} +17 -17
  143. package/dist/test-6JH4FE2X.js +27 -0
  144. package/dist/{test-git-XM4TM65W.js → test-git-2KFFAQ6B.js} +6 -6
  145. package/dist/{test-jira-LDTOYFSD.js → test-jira-FKDKG6CD.js} +8 -8
  146. package/dist/{test-prefix-GBO37XCN.js → test-prefix-GP2DAX37.js} +11 -11
  147. package/dist/test-prefix-GP2DAX37.js.map +1 -0
  148. package/dist/{test-tabs-D3POYOJ5.js → test-tabs-YDWMWTVA.js} +3 -3
  149. package/dist/{test-webserver-NZ3JTVLL.js → test-webserver-QI3QQFZ3.js} +8 -8
  150. package/dist/tmux-7ZTA3BDI.js +156 -0
  151. package/dist/tmux-7ZTA3BDI.js.map +1 -0
  152. package/dist/{update-HJKDYA3F.js → update-XLW7R7FL.js} +4 -4
  153. package/dist/{update-notifier-LBAUOOLM.js → update-notifier-EYLAXZAA.js} +3 -3
  154. package/dist/update-notifier-EYLAXZAA.js.map +1 -0
  155. package/dist/{vscode-6XUGHJKL.js → vscode-TOGE5N67.js} +13 -13
  156. package/dist/{vscode-announcement-EQ2SKK3T.js → vscode-announcement-NIX7O2MG.js} +3 -3
  157. package/dist/wsl-Y4GUTOQ7.js +78 -0
  158. package/dist/wsl-Y4GUTOQ7.js.map +1 -0
  159. package/package.json +4 -2
  160. package/dist/ClaudeContextManager-66GR4BGM.js +0 -14
  161. package/dist/ClaudeService-7KM5NA5Z.js +0 -13
  162. package/dist/GitHubService-MEHKHUQP.js +0 -12
  163. package/dist/IssueTrackerFactory-NG53YX5S.js +0 -14
  164. package/dist/LoomLauncher-TDLZSYG2.js.map +0 -1
  165. package/dist/MetadataManager-5QZSTKNN.js +0 -10
  166. package/dist/ProjectCapabilityDetector-5KSYUTBJ.js +0 -11
  167. package/dist/SettingsMigrationManager-LEBMJP3B.js +0 -10
  168. package/dist/build-VHGEMXBA.js +0 -27
  169. package/dist/chunk-5RPBYK5Q.js.map +0 -1
  170. package/dist/chunk-7VHJNVLF.js.map +0 -1
  171. package/dist/chunk-C6HNNJIV.js.map +0 -1
  172. package/dist/chunk-GRISNU6G.js.map +0 -1
  173. package/dist/chunk-KB64WNBZ.js.map +0 -1
  174. package/dist/chunk-OTGH2HRS.js.map +0 -1
  175. package/dist/chunk-RJ3VBUFK.js.map +0 -1
  176. package/dist/chunk-RSYT7MVI.js.map +0 -1
  177. package/dist/chunk-SWSJWA2S.js.map +0 -1
  178. package/dist/chunk-UR5DGNUO.js.map +0 -1
  179. package/dist/chunk-UUEW5KWB.js.map +0 -1
  180. package/dist/chunk-VT4PDUYT.js.map +0 -1
  181. package/dist/chunk-ZNMPGMHY.js.map +0 -1
  182. package/dist/ignite-H2O5Y5A2.js +0 -34
  183. package/dist/lint-AAN2NZWG.js +0 -27
  184. package/dist/neon-helpers-CQN2PB4S.js +0 -11
  185. package/dist/test-SGO6I5Z7.js +0 -27
  186. package/dist/test-prefix-GBO37XCN.js.map +0 -1
  187. /package/dist/{BranchNamingService-25KSZAEM.js.map → BranchNamingService-XBCO747L.js.map} +0 -0
  188. /package/dist/{ClaudeContextManager-66GR4BGM.js.map → ClaudeContextManager-SXDCWDJA.js.map} +0 -0
  189. /package/dist/{ClaudeService-7KM5NA5Z.js.map → ClaudeService-6E6MCGJE.js.map} +0 -0
  190. /package/dist/{GitHubService-MEHKHUQP.js.map → GitHubService-2R5GQG4K.js.map} +0 -0
  191. /package/dist/{IssueTrackerFactory-NG53YX5S.js.map → IssueTrackerFactory-XN6MQ4UN.js.map} +0 -0
  192. /package/dist/{MetadataManager-5QZSTKNN.js.map → MetadataManager-CMQQTFLQ.js.map} +0 -0
  193. /package/dist/{ProjectCapabilityDetector-5KSYUTBJ.js.map → ProjectCapabilityDetector-IC6NAFGY.js.map} +0 -0
  194. /package/dist/{PromptTemplateManager-YOE2SIPG.js.map → PromptTemplateManager-T5VTLJP3.js.map} +0 -0
  195. /package/dist/{SettingsManager-FNKCOZMQ.js.map → SettingsManager-WQ5NSGAH.js.map} +0 -0
  196. /package/dist/{SettingsMigrationManager-LEBMJP3B.js.map → SettingsMigrationManager-S6J7OHUH.js.map} +0 -0
  197. /package/dist/{build-VHGEMXBA.js.map → build-OLS6J5KZ.js.map} +0 -0
  198. /package/dist/{chunk-WWKOVDWC.js.map → chunk-3GTUXW26.js.map} +0 -0
  199. /package/dist/{chunk-4FGEGQW4.js.map → chunk-3RXYOBME.js.map} +0 -0
  200. /package/dist/{chunk-HEXKPKCK.js.map → chunk-5LTID2AF.js.map} +0 -0
  201. /package/dist/{chunk-G5V75JD5.js.map → chunk-5PNZBH6V.js.map} +0 -0
  202. /package/dist/{chunk-E6KOWMKA.js.map → chunk-6YVJVUR4.js.map} +0 -0
  203. /package/dist/{chunk-QVLPWNE3.js.map → chunk-7NFCGKZT.js.map} +0 -0
  204. /package/dist/{chunk-433MOLAU.js.map → chunk-7OCGBJLR.js.map} +0 -0
  205. /package/dist/{chunk-KVHIAWVT.js.map → chunk-ABVMUNCD.js.map} +0 -0
  206. /package/dist/{chunk-7JDMYTFZ.js.map → chunk-CV47VCMQ.js.map} +0 -0
  207. /package/dist/{chunk-MORRVYPT.js.map → chunk-G2MNSPA4.js.map} +0 -0
  208. /package/dist/{chunk-LLHXQS3C.js.map → chunk-HLDY5S4C.js.map} +0 -0
  209. /package/dist/{chunk-BYUMEDDD.js.map → chunk-IDCE26KD.js.map} +0 -0
  210. /package/dist/{chunk-O7VL5N6S.js.map → chunk-K7R5QY6C.js.map} +0 -0
  211. /package/dist/{chunk-S7PZA6IV.js.map → chunk-KQFIGI37.js.map} +0 -0
  212. /package/dist/{chunk-I5T677EA.js.map → chunk-LE2NOUTN.js.map} +0 -0
  213. /package/dist/{chunk-KXDRI47U.js.map → chunk-LHDD4JHC.js.map} +0 -0
  214. /package/dist/{chunk-5FJWO4IT.js.map → chunk-LL6TOX3G.js.map} +0 -0
  215. /package/dist/{chunk-YQ57ORTV.js.map → chunk-NCPZYQ4B.js.map} +0 -0
  216. /package/dist/{chunk-EWJFUFPT.js.map → chunk-NDSGJZI2.js.map} +0 -0
  217. /package/dist/{chunk-VG45TUYK.js.map → chunk-NH3QZYE5.js.map} +0 -0
  218. /package/dist/{chunk-KKV5WH5M.js.map → chunk-NN5RYWXA.js.map} +0 -0
  219. /package/dist/{chunk-KIK2ZFAL.js.map → chunk-QNHZM5ZV.js.map} +0 -0
  220. /package/dist/{chunk-EVPZFV3K.js.map → chunk-QR4FU53I.js.map} +0 -0
  221. /package/dist/{chunk-FXDYIV3K.js.map → chunk-QVAA5KHK.js.map} +0 -0
  222. /package/dist/{chunk-NGJZ4TOU.js.map → chunk-RBYTXYGD.js.map} +0 -0
  223. /package/dist/{chunk-CVCTIDDK.js.map → chunk-RVI6C2H5.js.map} +0 -0
  224. /package/dist/{chunk-Q7POFB5Q.js.map → chunk-SQYHPBFP.js.map} +0 -0
  225. /package/dist/{chunk-QZWEJVWV.js.map → chunk-TZNNJLGT.js.map} +0 -0
  226. /package/dist/{chunk-63QWFWH3.js.map → chunk-UDCI3QTS.js.map} +0 -0
  227. /package/dist/{chunk-UKBAJ2QQ.js.map → chunk-UHIBKD73.js.map} +0 -0
  228. /package/dist/{chunk-WXIM2WS7.js.map → chunk-V4STTBQD.js.map} +0 -0
  229. /package/dist/{chunk-P4O6EH46.js.map → chunk-VMZG66UV.js.map} +0 -0
  230. /package/dist/{chunk-LUKXJSRI.js.map → chunk-XXFSOVL3.js.map} +0 -0
  231. /package/dist/{chunk-6MLEBAYZ.js.map → chunk-ZAXRQLK3.js.map} +0 -0
  232. /package/dist/{claude-7GGEWVEM.js.map → claude-ONQTDWV3.js.map} +0 -0
  233. /package/dist/{color-4TJ4P5EY.js.map → color-VQD52LOI.js.map} +0 -0
  234. /package/dist/{commit-FZR5XDQG.js.map → commit-DC2Q5CDY.js.map} +0 -0
  235. /package/dist/{compile-7ALJHZ4N.js.map → compile-4NCQECKE.js.map} +0 -0
  236. /package/dist/{contribute-5GKLK3BQ.js.map → contribute-M5UWXCAV.js.map} +0 -0
  237. /package/dist/{git-GTLKAZRJ.js.map → darwin-5BHWRJ7D.js.map} +0 -0
  238. /package/dist/{dev-server-7SMIB7OF.js.map → dev-server-CYRP6M73.js.map} +0 -0
  239. /package/dist/{feedback-G2GJFN2F.js.map → feedback-BMAZGKRW.js.map} +0 -0
  240. /package/dist/{ignite-H2O5Y5A2.js.map → git-BXUD6CL5.js.map} +0 -0
  241. /package/dist/{installation-detector-MMFWLJYN.js.map → ignite-IO4LXVXJ.js.map} +0 -0
  242. /package/dist/{neon-helpers-CQN2PB4S.js.map → installation-detector-HF6QN7KP.js.map} +0 -0
  243. /package/dist/{issues-4UUAQ5K6.js.map → issues-DMRQJH7E.js.map} +0 -0
  244. /package/dist/{lint-AAN2NZWG.js.map → lint-BSWRMGPZ.js.map} +0 -0
  245. /package/dist/{prompt-ONNPSNKM.js.map → mcp/darwin-3JFFE3W2.js.map} +0 -0
  246. /package/dist/{remote-IJAMOEAP.js.map → neon-helpers-HWIYRKOW.js.map} +0 -0
  247. /package/dist/{open-FXWW3VI4.js.map → open-2Y7GSUTJ.js.map} +0 -0
  248. /package/dist/{projects-2UOXFLNZ.js.map → projects-IUSUXD5D.js.map} +0 -0
  249. /package/dist/{update-notifier-LBAUOOLM.js.map → prompt-7LZB4PAT.js.map} +0 -0
  250. /package/dist/{rebase-6NVLX5V7.js.map → rebase-S6OHAOOF.js.map} +0 -0
  251. /package/dist/{recap-OMBOKJST.js.map → recap-GGVCG5VH.js.map} +0 -0
  252. /package/dist/{run-BBXLRIZB.js.map → run-ST3FR75O.js.map} +0 -0
  253. /package/dist/{shell-RF7LTND5.js.map → shell-W4SBQPTE.js.map} +0 -0
  254. /package/dist/{summary-WTQZ7XG2.js.map → summary-P2JCIIJO.js.map} +0 -0
  255. /package/dist/{test-SGO6I5Z7.js.map → test-6JH4FE2X.js.map} +0 -0
  256. /package/dist/{test-git-XM4TM65W.js.map → test-git-2KFFAQ6B.js.map} +0 -0
  257. /package/dist/{test-jira-LDTOYFSD.js.map → test-jira-FKDKG6CD.js.map} +0 -0
  258. /package/dist/{test-tabs-D3POYOJ5.js.map → test-tabs-YDWMWTVA.js.map} +0 -0
  259. /package/dist/{test-webserver-NZ3JTVLL.js.map → test-webserver-QI3QQFZ3.js.map} +0 -0
  260. /package/dist/{update-HJKDYA3F.js.map → update-XLW7R7FL.js.map} +0 -0
  261. /package/dist/{vscode-6XUGHJKL.js.map → vscode-TOGE5N67.js.map} +0 -0
  262. /package/dist/{vscode-announcement-EQ2SKK3T.js.map → vscode-announcement-NIX7O2MG.js.map} +0 -0
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
- import {
3
- getLogger
4
- } from "./chunk-6MLEBAYZ.js";
5
2
  import {
6
3
  promptConfirmation
7
- } from "./chunk-7JDMYTFZ.js";
4
+ } from "./chunk-CV47VCMQ.js";
5
+ import {
6
+ getLogger
7
+ } from "./chunk-ZAXRQLK3.js";
8
8
  import {
9
9
  logger
10
- } from "./chunk-VT4PDUYT.js";
10
+ } from "./chunk-H2SSF24U.js";
11
11
 
12
12
  // src/utils/linear.ts
13
13
  import { LinearClient, IssueRelationType } from "@linear/sdk";
@@ -1393,4 +1393,4 @@ export {
1393
1393
  JiraApiClient,
1394
1394
  JiraIssueTracker
1395
1395
  };
1396
- //# sourceMappingURL=chunk-HEXKPKCK.js.map
1396
+ //# sourceMappingURL=chunk-5LTID2AF.js.map
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  calculatePortFromIdentifier
4
- } from "./chunk-LLHXQS3C.js";
4
+ } from "./chunk-HLDY5S4C.js";
5
5
 
6
6
  // src/lib/process/ProcessManager.ts
7
7
  import { execa } from "execa";
@@ -179,4 +179,4 @@ var ProcessManager = class {
179
179
  export {
180
180
  ProcessManager
181
181
  };
182
- //# sourceMappingURL=chunk-G5V75JD5.js.map
182
+ //# sourceMappingURL=chunk-5PNZBH6V.js.map
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  getRepoInfo
4
- } from "./chunk-VG45TUYK.js";
4
+ } from "./chunk-NH3QZYE5.js";
5
5
  import {
6
6
  logger
7
- } from "./chunk-VT4PDUYT.js";
7
+ } from "./chunk-H2SSF24U.js";
8
8
 
9
9
  // src/utils/mcp.ts
10
10
  import path from "path";
@@ -115,6 +115,24 @@ function slugifyPath(loomPath) {
115
115
  slug = slug.replace(/[^a-zA-Z0-9_-]/g, "-");
116
116
  return `${slug}.json`;
117
117
  }
118
+ function resolveRecapFilePath(worktreePath) {
119
+ const recapsDir = path.join(os.homedir(), ".config", "iloom-ai", "recaps");
120
+ return path.join(recapsDir, slugifyPath(worktreePath));
121
+ }
122
+ async function readRecapFile(filePath) {
123
+ try {
124
+ if (await fs.pathExists(filePath)) {
125
+ const content = await fs.readFile(filePath, "utf8");
126
+ return JSON.parse(content);
127
+ }
128
+ } catch {
129
+ }
130
+ return {};
131
+ }
132
+ async function writeRecapFile(filePath, recap) {
133
+ await fs.ensureDir(path.dirname(filePath), { mode: 493 });
134
+ await fs.writeFile(filePath, JSON.stringify(recap, null, 2), { mode: 420 });
135
+ }
118
136
  function generateRecapMcpConfig(loomPath, loomMetadata) {
119
137
  const recapsDir = path.join(os.homedir(), ".config", "iloom-ai", "recaps");
120
138
  const recapFilePath = path.join(recapsDir, slugifyPath(loomPath));
@@ -222,8 +240,11 @@ async function generateAndWriteMcpConfigFile(loomPath, loomMetadata, provider =
222
240
 
223
241
  export {
224
242
  generateIssueManagementMcpConfig,
243
+ resolveRecapFilePath,
244
+ readRecapFile,
245
+ writeRecapFile,
225
246
  generateRecapMcpConfig,
226
247
  generateHarnessMcpConfig,
227
248
  generateAndWriteMcpConfigFile
228
249
  };
229
- //# sourceMappingURL=chunk-SKSYYBCU.js.map
250
+ //# sourceMappingURL=chunk-5UFGO4ZT.js.map
@@ -1 +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":[]}
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 * Resolve recap file path for a given worktree path\n */\nexport function resolveRecapFilePath(worktreePath: string): string {\n\tconst recapsDir = path.join(os.homedir(), '.config', 'iloom-ai', 'recaps')\n\treturn path.join(recapsDir, slugifyPath(worktreePath))\n}\n\n/**\n * Read recap file (returns empty object if not found or invalid)\n */\nexport async function readRecapFile(filePath: string): Promise<Record<string, unknown>> {\n\ttry {\n\t\tif (await fs.pathExists(filePath)) {\n\t\t\tconst content = await fs.readFile(filePath, 'utf8')\n\t\t\treturn JSON.parse(content) as Record<string, unknown>\n\t\t}\n\t} catch {\n\t\t// Ignore read errors - return empty recap\n\t}\n\treturn {}\n}\n\n/**\n * Write recap file (ensures parent directory exists)\n */\nexport async function writeRecapFile(filePath: string, recap: Record<string, unknown>): Promise<void> {\n\tawait fs.ensureDir(path.dirname(filePath), { mode: 0o755 })\n\tawait fs.writeFile(filePath, JSON.stringify(recap, null, 2), { mode: 0o644 })\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":[]}
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ClaudeService
4
- } from "./chunk-S7PZA6IV.js";
4
+ } from "./chunk-KQFIGI37.js";
5
5
  import {
6
6
  logger
7
- } from "./chunk-VT4PDUYT.js";
7
+ } from "./chunk-H2SSF24U.js";
8
8
 
9
9
  // src/lib/ClaudeContextManager.ts
10
10
  var ClaudeContextManager = class {
@@ -63,4 +63,4 @@ var ClaudeContextManager = class {
63
63
  export {
64
64
  ClaudeContextManager
65
65
  };
66
- //# sourceMappingURL=chunk-E6KOWMKA.js.map
66
+ //# sourceMappingURL=chunk-6YVJVUR4.js.map
@@ -1,10 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  archiveRecap
4
- } from "./chunk-LUKXJSRI.js";
4
+ } from "./chunk-XXFSOVL3.js";
5
+ import {
6
+ removeClaudeTrust
7
+ } from "./chunk-NOMQ5RFG.js";
5
8
  import {
6
9
  calculatePortFromIdentifier
7
- } from "./chunk-LLHXQS3C.js";
10
+ } from "./chunk-HLDY5S4C.js";
8
11
  import {
9
12
  checkRemoteBranchStatus,
10
13
  executeGitCommand,
@@ -14,16 +17,16 @@ import {
14
17
  getMergeTargetBranch,
15
18
  hasUncommittedChanges,
16
19
  isBranchMergedIntoMain
17
- } from "./chunk-4FGEGQW4.js";
20
+ } from "./chunk-3RXYOBME.js";
18
21
  import {
19
22
  SettingsManager
20
- } from "./chunk-7VHJNVLF.js";
23
+ } from "./chunk-ET6A2JR4.js";
21
24
  import {
22
25
  MetadataManager
23
- } from "./chunk-KB64WNBZ.js";
26
+ } from "./chunk-YRCEOQPX.js";
24
27
  import {
25
28
  getLogger
26
- } from "./chunk-6MLEBAYZ.js";
29
+ } from "./chunk-ZAXRQLK3.js";
27
30
 
28
31
  // src/lib/ResourceCleanup.ts
29
32
  import path from "path";
@@ -450,6 +453,32 @@ ${blockerMessage}`);
450
453
  }
451
454
  }
452
455
  }
456
+ if (worktree && !options.dryRun) {
457
+ try {
458
+ await removeClaudeTrust(worktree.path);
459
+ getLogger().debug(`Claude trust entry removed for worktree: ${worktree.path}`);
460
+ operations.push({
461
+ type: "trust",
462
+ success: true,
463
+ message: "Claude trust entry removed"
464
+ });
465
+ } catch (error) {
466
+ const err = error instanceof Error ? error : new Error(String(error));
467
+ getLogger().warn(`Claude trust removal failed (non-fatal): ${err.message}`);
468
+ operations.push({
469
+ type: "trust",
470
+ success: false,
471
+ message: "Claude trust removal failed (non-fatal)",
472
+ error: err.message
473
+ });
474
+ }
475
+ } else if (worktree && options.dryRun) {
476
+ operations.push({
477
+ type: "trust",
478
+ success: true,
479
+ message: `[DRY RUN] Would remove Claude trust entry for: ${worktree.path}`
480
+ });
481
+ }
453
482
  const success = errors.length === 0;
454
483
  return {
455
484
  identifier: displayIdentifier,
@@ -778,4 +807,4 @@ Please resolve before cleanup - you have some options:
778
807
  export {
779
808
  ResourceCleanup
780
809
  };
781
- //# sourceMappingURL=chunk-RJ3VBUFK.js.map
810
+ //# sourceMappingURL=chunk-7FIXNAUO.js.map
@@ -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 { removeClaudeTrust } from '../utils/claude-trust.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// Step 7.5: Remove Claude trust entry for the worktree\n\t\tif (worktree && !options.dryRun) {\n\t\t\ttry {\n\t\t\t\tawait removeClaudeTrust(worktree.path)\n\t\t\t\tgetLogger().debug(`Claude trust entry removed for worktree: ${worktree.path}`)\n\t\t\t\toperations.push({\n\t\t\t\t\ttype: 'trust',\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tmessage: 'Claude trust entry removed',\n\t\t\t\t})\n\t\t\t} catch (error) {\n\t\t\t\t// Non-fatal: trust removal failure should not block cleanup\n\t\t\t\tconst err = error instanceof Error ? error : new Error(String(error))\n\t\t\t\tgetLogger().warn(`Claude trust removal failed (non-fatal): ${err.message}`)\n\t\t\t\toperations.push({\n\t\t\t\t\ttype: 'trust',\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\tmessage: 'Claude trust removal failed (non-fatal)',\n\t\t\t\t\terror: err.message,\n\t\t\t\t})\n\t\t\t}\n\t\t} else if (worktree && options.dryRun) {\n\t\t\toperations.push({\n\t\t\t\ttype: 'trust',\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage: `[DRY RUN] Would remove Claude trust entry for: ${worktree.path}`,\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":[]}
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  getLogger
4
- } from "./chunk-6MLEBAYZ.js";
4
+ } from "./chunk-ZAXRQLK3.js";
5
5
 
6
6
  // src/lib/BranchNamingService.ts
7
7
  var SimpleBranchNameStrategy = class {
@@ -15,7 +15,7 @@ var ClaudeBranchNameStrategy = class {
15
15
  this.claudeModel = claudeModel;
16
16
  }
17
17
  async generate(issueNumber, title) {
18
- const { generateBranchName } = await import("./claude-7GGEWVEM.js");
18
+ const { generateBranchName } = await import("./claude-ONQTDWV3.js");
19
19
  return generateBranchName(title, issueNumber, this.claudeModel);
20
20
  }
21
21
  };
@@ -52,4 +52,4 @@ export {
52
52
  ClaudeBranchNameStrategy,
53
53
  DefaultBranchNamingService
54
54
  };
55
- //# sourceMappingURL=chunk-QVLPWNE3.js.map
55
+ //# sourceMappingURL=chunk-7NFCGKZT.js.map
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  logger_default
4
- } from "./chunk-VT4PDUYT.js";
4
+ } from "./chunk-H2SSF24U.js";
5
5
 
6
6
  // src/utils/color.ts
7
7
  import { createHash } from "crypto";
@@ -202,4 +202,4 @@ export {
202
202
  saturateColor,
203
203
  calculateForegroundColor
204
204
  };
205
- //# sourceMappingURL=chunk-433MOLAU.js.map
205
+ //# sourceMappingURL=chunk-7OCGBJLR.js.map
@@ -1,25 +1,25 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  IssueManagementProviderFactory
4
- } from "./chunk-SWSJWA2S.js";
4
+ } from "./chunk-RMLADZRY.js";
5
5
  import {
6
6
  openBrowser
7
7
  } from "./chunk-YETJNRQM.js";
8
+ import {
9
+ executeGhCommand
10
+ } from "./chunk-NH3QZYE5.js";
8
11
  import {
9
12
  getConfiguredRepoFromSettings,
10
13
  getEffectivePRTargetRemote,
11
14
  parseGitRemotes
12
- } from "./chunk-FXDYIV3K.js";
15
+ } from "./chunk-QVAA5KHK.js";
13
16
  import {
14
17
  detectClaudeCli,
15
18
  launchClaude
16
- } from "./chunk-UR5DGNUO.js";
17
- import {
18
- executeGhCommand
19
- } from "./chunk-VG45TUYK.js";
19
+ } from "./chunk-Y3RX7LZT.js";
20
20
  import {
21
21
  getLogger
22
- } from "./chunk-6MLEBAYZ.js";
22
+ } from "./chunk-ZAXRQLK3.js";
23
23
 
24
24
  // src/lib/PRManager.ts
25
25
  var PRManager = class {
@@ -359,4 +359,4 @@ Then retry: il start`
359
359
  export {
360
360
  PRManager
361
361
  };
362
- //# sourceMappingURL=chunk-KVHIAWVT.js.map
362
+ //# sourceMappingURL=chunk-ABVMUNCD.js.map
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  logger
4
- } from "./chunk-VT4PDUYT.js";
4
+ } from "./chunk-H2SSF24U.js";
5
5
 
6
6
  // src/utils/prompt.ts
7
7
  import * as readline from "readline";
@@ -248,4 +248,4 @@ export {
248
248
  isInteractiveEnvironment,
249
249
  promptCommitAction
250
250
  };
251
- //# sourceMappingURL=chunk-7JDMYTFZ.js.map
251
+ //# sourceMappingURL=chunk-CV47VCMQ.js.map
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  logger
4
- } from "./chunk-VT4PDUYT.js";
4
+ } from "./chunk-H2SSF24U.js";
5
5
 
6
6
  // src/lib/SettingsManager.ts
7
7
  import { readFile } from "fs/promises";
@@ -17,15 +17,16 @@ var BaseAgentSettingsSchema = z.object({
17
17
  z.enum(["claude", "gemini", "codex"]),
18
18
  z.string()
19
19
  ).optional().describe('Map of review providers to model names. Keys: claude, gemini, codex. Values: model name strings (e.g., "sonnet", "gemini-3-pro-preview", "gpt-5.2-codex")'),
20
- review: z.boolean().optional().describe("Whether artifacts from this agent should be reviewed before posting (defaults to false)")
20
+ review: z.boolean().optional().describe("Whether artifacts from this agent should be reviewed before posting (defaults to false)"),
21
+ swarmReview: z.boolean().optional().describe("Whether artifacts from this agent should be reviewed in swarm mode. Defaults to false if not set (review is off in swarm mode for speed and cost unless explicitly enabled).")
21
22
  });
22
23
  var AgentSettingsSchema = BaseAgentSettingsSchema.extend({
23
- agents: z.record(z.string(), BaseAgentSettingsSchema).optional().describe("Nested per-agent settings. Only meaningful under the iloom-swarm-worker agent entry for sub-agent timeout configuration."),
24
24
  subAgentTimeout: z.number().min(1, "Sub-agent timeout must be at least 1 minute").max(120, "Sub-agent timeout cannot exceed 120 minutes").default(10).describe("Timeout in minutes for sub-agent claude -p invocations in swarm mode. Applies to each phase agent (evaluator, analyzer, planner, implementer) when invoked via the Bash tool. Default: 10 minutes. Only meaningful under the iloom-swarm-worker agent entry.")
25
25
  });
26
26
  var SpinAgentSettingsSchema = z.object({
27
27
  model: z.enum(["sonnet", "opus", "haiku"]).default("opus").describe("Claude model shorthand for spin orchestrator"),
28
- swarmModel: z.enum(["sonnet", "opus", "haiku"]).optional().describe("Model for the spin orchestrator when running in swarm mode. Overrides spin.model for swarm workflows.")
28
+ swarmModel: z.enum(["sonnet", "opus", "haiku"]).optional().describe("Model for the spin orchestrator when running in swarm mode. Overrides spin.model for swarm workflows."),
29
+ postSwarmReview: z.boolean().default(true).describe("Run a full code review after swarm completion, auto-fixing issues with confidence 80+. Defaults to true.")
29
30
  });
30
31
  var PlanCommandSettingsSchema = z.object({
31
32
  model: z.enum(["sonnet", "opus", "haiku"]).default("opus").describe("Claude model shorthand for plan command"),
@@ -220,7 +221,8 @@ var IloomSettingsSchemaNoDefaults = z.object({
220
221
  ),
221
222
  spin: z.object({
222
223
  model: z.enum(["sonnet", "opus", "haiku"]).optional(),
223
- swarmModel: z.enum(["sonnet", "opus", "haiku"]).optional()
224
+ swarmModel: z.enum(["sonnet", "opus", "haiku"]).optional(),
225
+ postSwarmReview: z.boolean().optional()
224
226
  }).optional().describe("Spin orchestrator configuration"),
225
227
  plan: z.object({
226
228
  model: z.enum(["sonnet", "opus", "haiku"]).optional(),
@@ -584,4 +586,4 @@ export {
584
586
  IloomSettingsSchemaNoDefaults,
585
587
  SettingsManager
586
588
  };
587
- //# sourceMappingURL=chunk-7VHJNVLF.js.map
589
+ //# sourceMappingURL=chunk-ET6A2JR4.js.map