@iloom/cli 0.9.2 → 0.10.1

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 (231) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +160 -41
  3. package/dist/{BranchNamingService-K6XNWQ6C.js → BranchNamingService-25KSZAEM.js} +2 -2
  4. package/dist/ClaudeContextManager-66GR4BGM.js +14 -0
  5. package/dist/ClaudeService-7KM5NA5Z.js +13 -0
  6. package/dist/{GitHubService-TGWJN4V4.js → GitHubService-MEHKHUQP.js} +4 -4
  7. package/dist/IssueTrackerFactory-NG53YX5S.js +14 -0
  8. package/dist/{LoomLauncher-73NXL2CL.js → LoomLauncher-TDLZSYG2.js} +9 -9
  9. package/dist/{MetadataManager-W3C54UYT.js → MetadataManager-5QZSTKNN.js} +2 -2
  10. package/dist/{ProjectCapabilityDetector-N5L7T4IY.js → ProjectCapabilityDetector-5KSYUTBJ.js} +3 -3
  11. package/dist/{PromptTemplateManager-36YLQRHP.js → PromptTemplateManager-YOE2SIPG.js} +2 -2
  12. package/dist/README.md +160 -41
  13. package/dist/{SettingsManager-AW3JTJHD.js → SettingsManager-FNKCOZMQ.js} +4 -2
  14. package/dist/agents/iloom-artifact-reviewer.md +11 -0
  15. package/dist/agents/iloom-code-reviewer.md +14 -0
  16. package/dist/agents/iloom-issue-analyze-and-plan.md +55 -12
  17. package/dist/agents/iloom-issue-analyzer.md +49 -6
  18. package/dist/agents/iloom-issue-complexity-evaluator.md +47 -6
  19. package/dist/agents/iloom-issue-enhancer.md +86 -7
  20. package/dist/agents/iloom-issue-implementer.md +48 -7
  21. package/dist/agents/iloom-issue-planner.md +115 -62
  22. package/dist/{build-THZI572G.js → build-VHGEMXBA.js} +9 -9
  23. package/dist/chunk-4232AHNQ.js +35 -0
  24. package/dist/chunk-4232AHNQ.js.map +1 -0
  25. package/dist/chunk-4E7LCFUG.js +24 -0
  26. package/dist/chunk-4E7LCFUG.js.map +1 -0
  27. package/dist/{chunk-AR5QKYNE.js → chunk-4FGEGQW4.js} +4 -4
  28. package/dist/{chunk-R4YWBGY6.js → chunk-5FJWO4IT.js} +67 -22
  29. package/dist/chunk-5FJWO4IT.js.map +1 -0
  30. package/dist/{chunk-VPTAX5TR.js → chunk-5RPBYK5Q.js} +35 -30
  31. package/dist/chunk-5RPBYK5Q.js.map +1 -0
  32. package/dist/{chunk-YKFCCV6S.js → chunk-63QWFWH3.js} +7 -7
  33. package/dist/chunk-63QWFWH3.js.map +1 -0
  34. package/dist/{chunk-RI2YL6TK.js → chunk-7VHJNVLF.js} +80 -23
  35. package/dist/chunk-7VHJNVLF.js.map +1 -0
  36. package/dist/{chunk-B7U6OKUR.js → chunk-C6HNNJIV.js} +11 -3
  37. package/dist/chunk-C6HNNJIV.js.map +1 -0
  38. package/dist/{chunk-A7NJF73J.js → chunk-CVCTIDDK.js} +4 -4
  39. package/dist/{chunk-Z2TWEXR7.js → chunk-E6KOWMKA.js} +6 -6
  40. package/dist/chunk-E6KOWMKA.js.map +1 -0
  41. package/dist/{chunk-3I4ONZRT.js → chunk-EVPZFV3K.js} +10 -10
  42. package/dist/chunk-EVPZFV3K.js.map +1 -0
  43. package/dist/{chunk-IZIYLYPK.js → chunk-G5V75JD5.js} +2 -2
  44. package/dist/chunk-GRISNU6G.js +651 -0
  45. package/dist/chunk-GRISNU6G.js.map +1 -0
  46. package/dist/chunk-HEXKPKCK.js +1396 -0
  47. package/dist/chunk-HEXKPKCK.js.map +1 -0
  48. package/dist/{chunk-TC7APDKU.js → chunk-I5T677EA.js} +2 -2
  49. package/dist/{chunk-KBEIQP4G.js → chunk-KB64WNBZ.js} +43 -3
  50. package/dist/chunk-KB64WNBZ.js.map +1 -0
  51. package/dist/{chunk-NWMORW3U.js → chunk-KIK2ZFAL.js} +2 -2
  52. package/dist/{chunk-CWRI4JC3.js → chunk-KKV5WH5M.js} +30 -31
  53. package/dist/chunk-KKV5WH5M.js.map +1 -0
  54. package/dist/{chunk-DGG2VY7B.js → chunk-KVHIAWVT.js} +9 -9
  55. package/dist/chunk-KVHIAWVT.js.map +1 -0
  56. package/dist/{chunk-OFDN5NKS.js → chunk-KXDRI47U.js} +69 -12
  57. package/dist/chunk-KXDRI47U.js.map +1 -0
  58. package/dist/{chunk-NUACL52E.js → chunk-LLHXQS3C.js} +2 -2
  59. package/dist/chunk-LUKXJSRI.js +73 -0
  60. package/dist/chunk-LUKXJSRI.js.map +1 -0
  61. package/dist/{chunk-TL72BGP6.js → chunk-MORRVYPT.js} +2 -2
  62. package/dist/chunk-OTGH2HRS.js +1427 -0
  63. package/dist/chunk-OTGH2HRS.js.map +1 -0
  64. package/dist/{chunk-7ZEHSSUP.js → chunk-P4O6EH46.js} +4 -4
  65. package/dist/{chunk-KAYXR544.js → chunk-QVLPWNE3.js} +2 -2
  66. package/dist/chunk-QZWEJVWV.js +207 -0
  67. package/dist/chunk-QZWEJVWV.js.map +1 -0
  68. package/dist/chunk-RJ3VBUFK.js +781 -0
  69. package/dist/chunk-RJ3VBUFK.js.map +1 -0
  70. package/dist/chunk-RSYT7MVI.js +202 -0
  71. package/dist/chunk-RSYT7MVI.js.map +1 -0
  72. package/dist/{chunk-6IIL5M2L.js → chunk-S7PZA6IV.js} +10 -8
  73. package/dist/{chunk-6IIL5M2L.js.map → chunk-S7PZA6IV.js.map} +1 -1
  74. package/dist/chunk-SKSYYBCU.js +229 -0
  75. package/dist/chunk-SKSYYBCU.js.map +1 -0
  76. package/dist/{chunk-ULSWCPQG.js → chunk-SWSJWA2S.js} +476 -5
  77. package/dist/chunk-SWSJWA2S.js.map +1 -0
  78. package/dist/{chunk-KXGQYLFZ.js → chunk-UKBAJ2QQ.js} +61 -7
  79. package/dist/chunk-UKBAJ2QQ.js.map +1 -0
  80. package/dist/{chunk-FO5GGFOV.js → chunk-UR5DGNUO.js} +71 -9
  81. package/dist/chunk-UR5DGNUO.js.map +1 -0
  82. package/dist/{chunk-QN47QVBX.js → chunk-UUEW5KWB.js} +1 -1
  83. package/dist/chunk-UUEW5KWB.js.map +1 -0
  84. package/dist/{chunk-4CO6KG5S.js → chunk-VG45TUYK.js} +53 -7
  85. package/dist/{chunk-4CO6KG5S.js.map → chunk-VG45TUYK.js.map} +1 -1
  86. package/dist/{chunk-4LKGCFGG.js → chunk-WWKOVDWC.js} +2 -2
  87. package/dist/{chunk-KJTVU3HZ.js → chunk-WXIM2WS7.js} +8 -8
  88. package/dist/chunk-WXIM2WS7.js.map +1 -0
  89. package/dist/{chunk-VOGGLPG5.js → chunk-YQ57ORTV.js} +14 -1
  90. package/dist/chunk-YQ57ORTV.js.map +1 -0
  91. package/dist/{chunk-SOSQILHO.js → chunk-ZNMPGMHY.js} +44 -797
  92. package/dist/chunk-ZNMPGMHY.js.map +1 -0
  93. package/dist/{claude-TP2QO3BU.js → claude-7GGEWVEM.js} +2 -2
  94. package/dist/{cleanup-PJRIFFU4.js → cleanup-6PVAC4NI.js} +85 -34
  95. package/dist/cleanup-6PVAC4NI.js.map +1 -0
  96. package/dist/cli.js +630 -801
  97. package/dist/cli.js.map +1 -1
  98. package/dist/{commit-IVP3M4HG.js → commit-FZR5XDQG.js} +26 -23
  99. package/dist/commit-FZR5XDQG.js.map +1 -0
  100. package/dist/{compile-R2J65HBQ.js → compile-7ALJHZ4N.js} +9 -9
  101. package/dist/{contribute-VDZXHK5Y.js → contribute-5GKLK3BQ.js} +14 -6
  102. package/dist/contribute-5GKLK3BQ.js.map +1 -0
  103. package/dist/{dev-server-7F622OEO.js → dev-server-7SMIB7OF.js} +29 -15
  104. package/dist/dev-server-7SMIB7OF.js.map +1 -0
  105. package/dist/{feedback-E7VET7CL.js → feedback-G2GJFN2F.js} +18 -16
  106. package/dist/{feedback-E7VET7CL.js.map → feedback-G2GJFN2F.js.map} +1 -1
  107. package/dist/{git-2QDQ2X2S.js → git-GTLKAZRJ.js} +4 -4
  108. package/dist/hooks/iloom-hook.js +15 -0
  109. package/dist/ignite-H2O5Y5A2.js +34 -0
  110. package/dist/ignite-H2O5Y5A2.js.map +1 -0
  111. package/dist/index.d.ts +482 -58
  112. package/dist/index.js +1340 -44
  113. package/dist/index.js.map +1 -1
  114. package/dist/{init-676DHF6R.js → init-32YOKXRL.js} +57 -21
  115. package/dist/init-32YOKXRL.js.map +1 -0
  116. package/dist/{issues-PJSOLOBJ.js → issues-4UUAQ5K6.js} +61 -20
  117. package/dist/issues-4UUAQ5K6.js.map +1 -0
  118. package/dist/{lint-CJM7BAIM.js → lint-AAN2NZWG.js} +9 -9
  119. package/dist/mcp/harness-server.js +140 -0
  120. package/dist/mcp/harness-server.js.map +1 -0
  121. package/dist/mcp/issue-management-server.js +2599 -262
  122. package/dist/mcp/issue-management-server.js.map +1 -1
  123. package/dist/mcp/recap-server.js +144 -21
  124. package/dist/mcp/recap-server.js.map +1 -1
  125. package/dist/{neon-helpers-VVFFTLXE.js → neon-helpers-CQN2PB4S.js} +3 -3
  126. package/dist/neon-helpers-CQN2PB4S.js.map +1 -0
  127. package/dist/{open-544H7JF5.js → open-FXWW3VI4.js} +15 -15
  128. package/dist/open-FXWW3VI4.js.map +1 -0
  129. package/dist/{plan-Q7ELXDLC.js → plan-RQ5FPIGF.js} +358 -40
  130. package/dist/plan-RQ5FPIGF.js.map +1 -0
  131. package/dist/{projects-LH362JZQ.js → projects-2UOXFLNZ.js} +4 -4
  132. package/dist/prompts/CLAUDE.md +62 -0
  133. package/dist/prompts/init-prompt.txt +430 -34
  134. package/dist/prompts/issue-prompt.txt +473 -54
  135. package/dist/prompts/plan-prompt.txt +140 -19
  136. package/dist/prompts/pr-prompt.txt +44 -1
  137. package/dist/prompts/regular-prompt.txt +42 -1
  138. package/dist/prompts/session-summary-prompt.txt +14 -0
  139. package/dist/prompts/swarm-orchestrator-prompt.txt +464 -0
  140. package/dist/{rebase-YND35CIE.js → rebase-6NVLX5V7.js} +21 -12
  141. package/dist/rebase-6NVLX5V7.js.map +1 -0
  142. package/dist/{recap-3W7COH7D.js → recap-OMBOKJST.js} +47 -19
  143. package/dist/recap-OMBOKJST.js.map +1 -0
  144. package/dist/{run-QUXJKDQQ.js → run-BBXLRIZB.js} +15 -15
  145. package/dist/run-BBXLRIZB.js.map +1 -0
  146. package/dist/schema/package-iloom.schema.json +58 -0
  147. package/dist/schema/settings.schema.json +149 -15
  148. package/dist/{shell-QGECBLST.js → shell-RF7LTND5.js} +14 -7
  149. package/dist/shell-RF7LTND5.js.map +1 -0
  150. package/dist/{summary-G2T4452H.js → summary-WTQZ7XG2.js} +27 -25
  151. package/dist/summary-WTQZ7XG2.js.map +1 -0
  152. package/dist/{test-EA5NQFDC.js → test-SGO6I5Z7.js} +9 -9
  153. package/dist/{test-git-M7LSLEFL.js → test-git-XM4TM65W.js} +4 -4
  154. package/dist/test-jira-LDTOYFSD.js +96 -0
  155. package/dist/test-jira-LDTOYFSD.js.map +1 -0
  156. package/dist/{test-prefix-64NAAUON.js → test-prefix-GBO37XCN.js} +4 -4
  157. package/dist/{test-webserver-OK6Z5FJM.js → test-webserver-NZ3JTVLL.js} +6 -6
  158. package/dist/{vscode-AR5NNXXI.js → vscode-6XUGHJKL.js} +7 -7
  159. package/package.json +5 -1
  160. package/dist/ClaudeContextManager-HR5JQKAI.js +0 -14
  161. package/dist/ClaudeService-TK7FMC2X.js +0 -13
  162. package/dist/chunk-3I4ONZRT.js.map +0 -1
  163. package/dist/chunk-B7U6OKUR.js.map +0 -1
  164. package/dist/chunk-CWRI4JC3.js.map +0 -1
  165. package/dist/chunk-DGG2VY7B.js.map +0 -1
  166. package/dist/chunk-FJDRTVJX.js +0 -520
  167. package/dist/chunk-FJDRTVJX.js.map +0 -1
  168. package/dist/chunk-FO5GGFOV.js.map +0 -1
  169. package/dist/chunk-KBEIQP4G.js.map +0 -1
  170. package/dist/chunk-KJTVU3HZ.js.map +0 -1
  171. package/dist/chunk-KXGQYLFZ.js.map +0 -1
  172. package/dist/chunk-OFDN5NKS.js.map +0 -1
  173. package/dist/chunk-QN47QVBX.js.map +0 -1
  174. package/dist/chunk-R4YWBGY6.js.map +0 -1
  175. package/dist/chunk-RI2YL6TK.js.map +0 -1
  176. package/dist/chunk-SOSQILHO.js.map +0 -1
  177. package/dist/chunk-ULSWCPQG.js.map +0 -1
  178. package/dist/chunk-VOGGLPG5.js.map +0 -1
  179. package/dist/chunk-VPTAX5TR.js.map +0 -1
  180. package/dist/chunk-W6DP5RVR.js +0 -101
  181. package/dist/chunk-W6DP5RVR.js.map +0 -1
  182. package/dist/chunk-WHI5KEOX.js +0 -121
  183. package/dist/chunk-WHI5KEOX.js.map +0 -1
  184. package/dist/chunk-YKFCCV6S.js.map +0 -1
  185. package/dist/chunk-Z2TWEXR7.js.map +0 -1
  186. package/dist/cleanup-PJRIFFU4.js.map +0 -1
  187. package/dist/commit-IVP3M4HG.js.map +0 -1
  188. package/dist/contribute-VDZXHK5Y.js.map +0 -1
  189. package/dist/dev-server-7F622OEO.js.map +0 -1
  190. package/dist/ignite-IW35CDBD.js +0 -784
  191. package/dist/ignite-IW35CDBD.js.map +0 -1
  192. package/dist/init-676DHF6R.js.map +0 -1
  193. package/dist/issues-PJSOLOBJ.js.map +0 -1
  194. package/dist/open-544H7JF5.js.map +0 -1
  195. package/dist/plan-Q7ELXDLC.js.map +0 -1
  196. package/dist/rebase-YND35CIE.js.map +0 -1
  197. package/dist/recap-3W7COH7D.js.map +0 -1
  198. package/dist/run-QUXJKDQQ.js.map +0 -1
  199. package/dist/shell-QGECBLST.js.map +0 -1
  200. package/dist/summary-G2T4452H.js.map +0 -1
  201. /package/dist/{BranchNamingService-K6XNWQ6C.js.map → BranchNamingService-25KSZAEM.js.map} +0 -0
  202. /package/dist/{ClaudeContextManager-HR5JQKAI.js.map → ClaudeContextManager-66GR4BGM.js.map} +0 -0
  203. /package/dist/{ClaudeService-TK7FMC2X.js.map → ClaudeService-7KM5NA5Z.js.map} +0 -0
  204. /package/dist/{GitHubService-TGWJN4V4.js.map → GitHubService-MEHKHUQP.js.map} +0 -0
  205. /package/dist/{MetadataManager-W3C54UYT.js.map → IssueTrackerFactory-NG53YX5S.js.map} +0 -0
  206. /package/dist/{LoomLauncher-73NXL2CL.js.map → LoomLauncher-TDLZSYG2.js.map} +0 -0
  207. /package/dist/{ProjectCapabilityDetector-N5L7T4IY.js.map → MetadataManager-5QZSTKNN.js.map} +0 -0
  208. /package/dist/{PromptTemplateManager-36YLQRHP.js.map → ProjectCapabilityDetector-5KSYUTBJ.js.map} +0 -0
  209. /package/dist/{SettingsManager-AW3JTJHD.js.map → PromptTemplateManager-YOE2SIPG.js.map} +0 -0
  210. /package/dist/{claude-TP2QO3BU.js.map → SettingsManager-FNKCOZMQ.js.map} +0 -0
  211. /package/dist/{build-THZI572G.js.map → build-VHGEMXBA.js.map} +0 -0
  212. /package/dist/{chunk-AR5QKYNE.js.map → chunk-4FGEGQW4.js.map} +0 -0
  213. /package/dist/{chunk-A7NJF73J.js.map → chunk-CVCTIDDK.js.map} +0 -0
  214. /package/dist/{chunk-IZIYLYPK.js.map → chunk-G5V75JD5.js.map} +0 -0
  215. /package/dist/{chunk-TC7APDKU.js.map → chunk-I5T677EA.js.map} +0 -0
  216. /package/dist/{chunk-NWMORW3U.js.map → chunk-KIK2ZFAL.js.map} +0 -0
  217. /package/dist/{chunk-NUACL52E.js.map → chunk-LLHXQS3C.js.map} +0 -0
  218. /package/dist/{chunk-TL72BGP6.js.map → chunk-MORRVYPT.js.map} +0 -0
  219. /package/dist/{chunk-7ZEHSSUP.js.map → chunk-P4O6EH46.js.map} +0 -0
  220. /package/dist/{chunk-KAYXR544.js.map → chunk-QVLPWNE3.js.map} +0 -0
  221. /package/dist/{chunk-4LKGCFGG.js.map → chunk-WWKOVDWC.js.map} +0 -0
  222. /package/dist/{git-2QDQ2X2S.js.map → claude-7GGEWVEM.js.map} +0 -0
  223. /package/dist/{compile-R2J65HBQ.js.map → compile-7ALJHZ4N.js.map} +0 -0
  224. /package/dist/{neon-helpers-VVFFTLXE.js.map → git-GTLKAZRJ.js.map} +0 -0
  225. /package/dist/{lint-CJM7BAIM.js.map → lint-AAN2NZWG.js.map} +0 -0
  226. /package/dist/{projects-LH362JZQ.js.map → projects-2UOXFLNZ.js.map} +0 -0
  227. /package/dist/{test-EA5NQFDC.js.map → test-SGO6I5Z7.js.map} +0 -0
  228. /package/dist/{test-git-M7LSLEFL.js.map → test-git-XM4TM65W.js.map} +0 -0
  229. /package/dist/{test-prefix-64NAAUON.js.map → test-prefix-GBO37XCN.js.map} +0 -0
  230. /package/dist/{test-webserver-OK6Z5FJM.js.map → test-webserver-NZ3JTVLL.js.map} +0 -0
  231. /package/dist/{vscode-AR5NNXXI.js.map → vscode-6XUGHJKL.js.map} +0 -0
@@ -1,44 +1,71 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ IgniteCommand
4
+ } from "./chunk-OTGH2HRS.js";
5
+ import {
6
+ StartCommand,
3
7
  launchFirstRunSetup,
4
8
  needsFirstRunSetup
5
- } from "./chunk-W6DP5RVR.js";
9
+ } from "./chunk-GRISNU6G.js";
10
+ import "./chunk-ZNMPGMHY.js";
11
+ import "./chunk-KVHIAWVT.js";
12
+ import "./chunk-QZWEJVWV.js";
6
13
  import {
7
- IssueTrackerFactory
8
- } from "./chunk-KXGQYLFZ.js";
14
+ IssueManagementProviderFactory
15
+ } from "./chunk-SWSJWA2S.js";
16
+ import "./chunk-4232AHNQ.js";
17
+ import "./chunk-LLHXQS3C.js";
18
+ import "./chunk-WWKOVDWC.js";
9
19
  import {
10
20
  matchIssueIdentifier
11
- } from "./chunk-YKFCCV6S.js";
21
+ } from "./chunk-63QWFWH3.js";
22
+ import "./chunk-P4O6EH46.js";
23
+ import {
24
+ TelemetryService
25
+ } from "./chunk-RSYT7MVI.js";
26
+ import "./chunk-I5T677EA.js";
12
27
  import "./chunk-Q7POFB5Q.js";
28
+ import "./chunk-4E7LCFUG.js";
13
29
  import {
30
+ generateHarnessMcpConfig,
14
31
  generateIssueManagementMcpConfig
15
- } from "./chunk-WHI5KEOX.js";
32
+ } from "./chunk-SKSYYBCU.js";
33
+ import "./chunk-YETJNRQM.js";
34
+ import "./chunk-MORRVYPT.js";
35
+ import "./chunk-YQ57ORTV.js";
36
+ import "./chunk-C6HNNJIV.js";
37
+ import "./chunk-FXDYIV3K.js";
38
+ import "./chunk-E6KOWMKA.js";
39
+ import "./chunk-S7PZA6IV.js";
16
40
  import {
17
- IssueManagementProviderFactory
18
- } from "./chunk-ULSWCPQG.js";
19
- import "./chunk-FJDRTVJX.js";
41
+ detectClaudeCli,
42
+ launchClaude
43
+ } from "./chunk-UR5DGNUO.js";
20
44
  import {
21
45
  PromptTemplateManager
22
- } from "./chunk-QN47QVBX.js";
23
- import "./chunk-AR5QKYNE.js";
46
+ } from "./chunk-UUEW5KWB.js";
47
+ import "./chunk-GYCR2LOU.js";
48
+ import "./chunk-QVLPWNE3.js";
49
+ import "./chunk-4FGEGQW4.js";
24
50
  import {
25
51
  PlanCommandSettingsSchema,
26
52
  SettingsManager
27
- } from "./chunk-RI2YL6TK.js";
28
- import "./chunk-KBEIQP4G.js";
29
- import "./chunk-OFDN5NKS.js";
30
- import "./chunk-4CO6KG5S.js";
31
- import {
32
- isInteractiveEnvironment,
33
- promptConfirmation
34
- } from "./chunk-7JDMYTFZ.js";
53
+ } from "./chunk-7VHJNVLF.js";
54
+ import "./chunk-KB64WNBZ.js";
35
55
  import {
36
- detectClaudeCli,
37
- launchClaude
38
- } from "./chunk-FO5GGFOV.js";
56
+ IssueTrackerFactory
57
+ } from "./chunk-UKBAJ2QQ.js";
58
+ import "./chunk-HEXKPKCK.js";
59
+ import "./chunk-KXDRI47U.js";
60
+ import "./chunk-VG45TUYK.js";
39
61
  import {
40
62
  withLogger
41
63
  } from "./chunk-6MLEBAYZ.js";
64
+ import {
65
+ isInteractiveEnvironment,
66
+ promptConfirmation
67
+ } from "./chunk-7JDMYTFZ.js";
68
+ import "./chunk-433MOLAU.js";
42
69
  import {
43
70
  createStderrLogger,
44
71
  logger
@@ -46,6 +73,157 @@ import {
46
73
 
47
74
  // src/commands/plan.ts
48
75
  import chalk from "chalk";
76
+
77
+ // src/lib/HarnessServer.ts
78
+ import net from "net";
79
+ import fs from "fs";
80
+ import os from "os";
81
+ import path from "path";
82
+ import { randomUUID } from "crypto";
83
+ var HarnessServer = class {
84
+ constructor(options = {}) {
85
+ this.server = null;
86
+ this.handlers = /* @__PURE__ */ new Map();
87
+ this.idempotentTypes = /* @__PURE__ */ new Set();
88
+ this.handledTypes = /* @__PURE__ */ new Set();
89
+ this.connections = /* @__PURE__ */ new Set();
90
+ this.waiters = /* @__PURE__ */ new Map();
91
+ this.socketPath = options.socketPath ?? path.join(os.tmpdir(), `iloom-harness-${randomUUID()}.sock`);
92
+ this.boundSignalHandler = (signal) => {
93
+ void this.stop().finally(() => {
94
+ process.kill(process.pid, signal);
95
+ });
96
+ };
97
+ }
98
+ get path() {
99
+ return this.socketPath;
100
+ }
101
+ registerHandler(type, handler, options) {
102
+ this.handlers.set(type, handler);
103
+ if (options == null ? void 0 : options.idempotent) {
104
+ this.idempotentTypes.add(type);
105
+ }
106
+ }
107
+ async start() {
108
+ if (this.server !== null) {
109
+ throw new Error("HarnessServer is already started");
110
+ }
111
+ fs.rmSync(this.socketPath, { force: true });
112
+ const server = net.createServer((socket) => {
113
+ this.handleConnection(socket);
114
+ });
115
+ this.server = server;
116
+ await new Promise((resolve, reject) => {
117
+ server.listen(this.socketPath, () => resolve());
118
+ server.once("error", reject);
119
+ });
120
+ fs.chmodSync(this.socketPath, 384);
121
+ process.on("SIGINT", this.boundSignalHandler);
122
+ process.on("SIGTERM", this.boundSignalHandler);
123
+ logger.debug(`HarnessServer listening on ${this.socketPath}`);
124
+ }
125
+ async stop() {
126
+ if (this.server === null) {
127
+ return;
128
+ }
129
+ for (const socket of this.connections) {
130
+ socket.destroy();
131
+ }
132
+ this.connections.clear();
133
+ const serverToClose = this.server;
134
+ this.server = null;
135
+ try {
136
+ await new Promise((resolve, reject) => {
137
+ serverToClose.close((err) => {
138
+ if (err) reject(err);
139
+ else resolve();
140
+ });
141
+ });
142
+ } finally {
143
+ fs.rmSync(this.socketPath, { force: true });
144
+ this.waiters.clear();
145
+ process.off("SIGINT", this.boundSignalHandler);
146
+ process.off("SIGTERM", this.boundSignalHandler);
147
+ logger.debug("HarnessServer stopped");
148
+ }
149
+ }
150
+ waitFor(type) {
151
+ return new Promise((resolve) => {
152
+ const resolvers = this.waiters.get(type) ?? [];
153
+ resolvers.push(resolve);
154
+ this.waiters.set(type, resolvers);
155
+ });
156
+ }
157
+ handleConnection(socket) {
158
+ this.connections.add(socket);
159
+ let buffer = "";
160
+ const MAX_BUFFER_SIZE = 1024 * 1024;
161
+ socket.on("data", (chunk) => {
162
+ buffer += chunk.toString();
163
+ if (buffer.length > MAX_BUFFER_SIZE) {
164
+ socket.destroy(new Error("Payload too large"));
165
+ return;
166
+ }
167
+ const lines = buffer.split("\n");
168
+ buffer = lines.pop() ?? "";
169
+ for (const line of lines) {
170
+ const trimmed = line.trim();
171
+ if (trimmed) {
172
+ void this.processMessage(trimmed, socket);
173
+ }
174
+ }
175
+ });
176
+ socket.on("close", () => {
177
+ this.connections.delete(socket);
178
+ });
179
+ socket.on("error", (err) => {
180
+ logger.debug(`HarnessServer socket error: ${err.message}`);
181
+ });
182
+ }
183
+ async processMessage(raw, socket) {
184
+ let message;
185
+ try {
186
+ const parsed = JSON.parse(raw);
187
+ if (!parsed || typeof parsed !== "object" || typeof parsed.type !== "string") {
188
+ this.sendResponse(socket, { type: "error", content: "Invalid message format" });
189
+ return;
190
+ }
191
+ message = parsed;
192
+ } catch {
193
+ this.sendResponse(socket, { type: "error", content: "Malformed JSON" });
194
+ return;
195
+ }
196
+ const resolvers = this.waiters.get(message.type);
197
+ if (resolvers && resolvers.length > 0) {
198
+ this.waiters.delete(message.type);
199
+ for (const resolve of resolvers) {
200
+ resolve(message.data);
201
+ }
202
+ }
203
+ if (this.idempotentTypes.has(message.type) && this.handledTypes.has(message.type)) {
204
+ this.sendResponse(socket, { type: "acknowledged" });
205
+ return;
206
+ }
207
+ const handler = this.handlers.get(message.type);
208
+ if (!handler) {
209
+ this.sendResponse(socket, {
210
+ type: "error",
211
+ content: `No handler registered for type: ${message.type}`
212
+ });
213
+ return;
214
+ }
215
+ if (this.idempotentTypes.has(message.type)) {
216
+ this.handledTypes.add(message.type);
217
+ }
218
+ const response = await handler(message.data);
219
+ this.sendResponse(socket, response);
220
+ }
221
+ sendResponse(socket, response) {
222
+ socket.write(JSON.stringify(response) + "\n");
223
+ }
224
+ };
225
+
226
+ // src/commands/plan.ts
49
227
  var PLANNER_PROVIDERS = ["claude", "gemini", "codex"];
50
228
  var REVIEWER_PROVIDERS = ["claude", "gemini", "codex", "none"];
51
229
  function formatChildIssues(children, issuePrefix) {
@@ -82,18 +260,18 @@ var PlanCommand = class {
82
260
  * @param reviewer - Optional reviewer provider (defaults to 'none')
83
261
  * @param printOptions - Print mode options for headless/CI execution
84
262
  */
85
- async execute(prompt, model, yolo, planner, reviewer, printOptions) {
263
+ async execute(prompt, model, yolo, planner, reviewer, printOptions, autoSwarm) {
86
264
  const isJsonMode = ((printOptions == null ? void 0 : printOptions.json) ?? false) || ((printOptions == null ? void 0 : printOptions.jsonStream) ?? false);
87
265
  if (isJsonMode) {
88
266
  const jsonLogger = createStderrLogger();
89
- return withLogger(jsonLogger, () => this.executeInternal(prompt, model, yolo, planner, reviewer, printOptions));
267
+ return withLogger(jsonLogger, () => this.executeInternal(prompt, model, yolo, planner, reviewer, printOptions, autoSwarm));
90
268
  }
91
- return this.executeInternal(prompt, model, yolo, planner, reviewer, printOptions);
269
+ return this.executeInternal(prompt, model, yolo, planner, reviewer, printOptions, autoSwarm);
92
270
  }
93
271
  /**
94
272
  * Internal execution method (separated for withLogger wrapping)
95
273
  */
96
- async executeInternal(prompt, model, yolo, planner, reviewer, printOptions) {
274
+ async executeInternal(prompt, model, yolo, planner, reviewer, printOptions, autoSwarm) {
97
275
  let normalizedPlanner;
98
276
  if (planner) {
99
277
  const normalized = planner.toLowerCase();
@@ -152,7 +330,7 @@ var PlanCommand = class {
152
330
  };
153
331
  logger.info(chalk.dim(`Preparing to create a detailed plan for issue #${decompositionContext.identifier}: ${decompositionContext.title}`));
154
332
  try {
155
- const mcpProvider = IssueManagementProviderFactory.create(provider);
333
+ const mcpProvider = IssueManagementProviderFactory.create(provider, settings ?? void 0);
156
334
  logger.debug("Fetching child issues for decomposition context", { identifier: decompositionContext.identifier });
157
335
  const children = await mcpProvider.getChildIssues({ number: decompositionContext.identifier });
158
336
  if (children.length > 0) {
@@ -205,7 +383,7 @@ var PlanCommand = class {
205
383
  );
206
384
  if (shouldRunInit) {
207
385
  logger.info(chalk.bold("Launching iloom init..."));
208
- const { InitCommand } = await import("./init-676DHF6R.js");
386
+ const { InitCommand } = await import("./init-32YOKXRL.js");
209
387
  const initCommand = new InitCommand();
210
388
  await initCommand.execute(
211
389
  "Help the user set up a GitHub repository or Linear project for this project so they can use issue management features. When complete tell the user they can exit to continue the planning session."
@@ -272,6 +450,50 @@ var PlanCommand = class {
272
450
  logger.debug("MCP config generated", {
273
451
  serverCount: mcpConfig.length
274
452
  });
453
+ let harness = null;
454
+ let externalHarness = false;
455
+ let epicData = null;
456
+ const controller = autoSwarm ? new AbortController() : null;
457
+ const autoSwarmStartTime = autoSwarm ? Date.now() : null;
458
+ let autoSwarmSuccess = false;
459
+ let autoSwarmPhaseReached = "plan";
460
+ let autoSwarmFallbackToNormal = false;
461
+ if (autoSwarm) {
462
+ const autoSwarmSource = decompositionContext ? "decomposition" : "fresh";
463
+ try {
464
+ TelemetryService.getInstance().track("auto_swarm.started", {
465
+ source: autoSwarmSource,
466
+ planner: effectivePlanner
467
+ });
468
+ } catch (error) {
469
+ logger.debug(`Telemetry auto_swarm.started tracking failed: ${error instanceof Error ? error.message : error}`);
470
+ }
471
+ yolo = true;
472
+ const externalSocket = process.env.ILOOM_HARNESS_SOCKET;
473
+ externalHarness = !!externalSocket;
474
+ if (!externalSocket) {
475
+ harness = new HarnessServer();
476
+ await harness.start();
477
+ }
478
+ const socketPath = externalSocket ?? (harness == null ? void 0 : harness.path);
479
+ if (!socketPath) {
480
+ throw new Error("Unexpected: no harness socket path available");
481
+ }
482
+ if (harness) {
483
+ harness.registerHandler("done", (data) => {
484
+ epicData = data;
485
+ setImmediate(() => {
486
+ controller == null ? void 0 : controller.abort();
487
+ });
488
+ return {
489
+ type: "instruction",
490
+ content: "Planning complete. The auto-swarm pipeline will now create the epic workspace and launch swarm mode automatically."
491
+ };
492
+ }, { idempotent: true });
493
+ }
494
+ const harnessMcpConfig = generateHarnessMcpConfig(socketPath);
495
+ mcpConfig = [...mcpConfig, ...harnessMcpConfig];
496
+ }
275
497
  const isVscodeMode = process.env.ILOOM_VSCODE === "1";
276
498
  logger.debug("VS Code mode detection", { isVscodeMode });
277
499
  const providerFlags = PLANNER_PROVIDERS.reduce((acc, p) => ({
@@ -294,6 +516,7 @@ var PlanCommand = class {
294
516
  PLANNER: effectivePlanner,
295
517
  REVIEWER: effectiveReviewer,
296
518
  HAS_REVIEWER: effectiveReviewer !== "none",
519
+ AUTO_SWARM_MODE: autoSwarm ?? false,
297
520
  ...providerFlags
298
521
  };
299
522
  const architectPrompt = await this.templateManager.getPrompt("plan", templateVariables);
@@ -329,6 +552,9 @@ var PlanCommand = class {
329
552
  "Bash(git diff:*)",
330
553
  "Bash(git show:*)"
331
554
  ];
555
+ if (autoSwarm) {
556
+ allowedTools.push("mcp__harness__signal");
557
+ }
332
558
  const isHeadless = (printOptions == null ? void 0 : printOptions.print) ?? false;
333
559
  const claudeOptions = {
334
560
  model: effectiveModel,
@@ -357,7 +583,7 @@ var PlanCommand = class {
357
583
  throw new Error('--yolo requires a prompt or issue identifier (e.g., il plan --yolo "add gitlab support" or il plan --yolo 42)');
358
584
  }
359
585
  logger.warn(
360
- "\u26A0\uFE0F YOLO mode enabled - Claude will skip permission prompts and proceed autonomously. This could destroy important data or make irreversible changes. Proceeding means you accept this risk."
586
+ "YOLO mode enabled - Claude will skip permission prompts and proceed autonomously. This could destroy important data or make irreversible changes. Proceeding means you accept this risk."
361
587
  );
362
588
  }
363
589
  logger.debug("Launching Claude with options", {
@@ -383,21 +609,113 @@ Proceed through the flow without requiring user interaction. Make and document y
383
609
  [TOPIC]
384
610
  ${initialMessage}`;
385
611
  }
386
- const claudeResult = await launchClaude(initialMessage, {
387
- ...claudeOptions,
388
- ...effectiveYolo && { permissionMode: "bypassPermissions" }
389
- });
390
- if (printOptions == null ? void 0 : printOptions.json) {
391
- console.log(JSON.stringify({
392
- success: true,
393
- output: claudeResult ?? ""
394
- }));
612
+ try {
613
+ const claudeResult = await launchClaude(initialMessage, {
614
+ ...claudeOptions,
615
+ ...effectiveYolo && { permissionMode: "bypassPermissions" },
616
+ ...controller && { signal: controller.signal }
617
+ });
618
+ if (autoSwarm) {
619
+ if (externalHarness) {
620
+ logger.info(chalk.green("Planning session ended. External harness will manage the pipeline."));
621
+ autoSwarmSuccess = true;
622
+ autoSwarmPhaseReached = "plan";
623
+ } else if (!epicData) {
624
+ throw new Error("Plan phase exited without completing. The Architect did not signal done.");
625
+ } else {
626
+ const resolvedEpicData = epicData;
627
+ const epicIssueNumber = resolvedEpicData.epicIssueNumber;
628
+ const childIssues = resolvedEpicData.childIssues ?? [];
629
+ logger.info(chalk.green(`Planning complete. Epic issue: #${epicIssueNumber}`));
630
+ autoSwarmFallbackToNormal = childIssues.length === 0;
631
+ const startCommand = new StartCommand(IssueTrackerFactory.create(settings ?? {}));
632
+ if (childIssues.length === 0) {
633
+ logger.info("No child issues created. Starting as a normal autonomous loom.");
634
+ let startResult;
635
+ try {
636
+ startResult = await startCommand.execute({
637
+ identifier: String(epicIssueNumber),
638
+ options: { oneShot: "bypassPermissions", json: true, claude: false, code: false, devServer: false, terminal: false }
639
+ });
640
+ } catch (startError) {
641
+ throw new Error(
642
+ `Auto-swarm: failed to create epic workspace. ${startError instanceof Error ? startError.message : String(startError)}`
643
+ );
644
+ }
645
+ const epicWorktreePath = startResult == null ? void 0 : startResult.path;
646
+ if (!epicWorktreePath) {
647
+ throw new Error("Auto-swarm: StartCommand did not return a workspace path.");
648
+ }
649
+ const igniteCommand = new IgniteCommand();
650
+ await igniteCommand.execute("bypassPermissions", void 0, void 0, epicWorktreePath);
651
+ } else {
652
+ let startResult;
653
+ try {
654
+ startResult = await startCommand.execute({
655
+ identifier: String(epicIssueNumber),
656
+ options: { epic: true, json: true, oneShot: "bypassPermissions", claude: false, code: false, devServer: false, terminal: false }
657
+ });
658
+ } catch (startError) {
659
+ throw new Error(
660
+ `Auto-swarm: failed to create epic workspace. ${startError instanceof Error ? startError.message : String(startError)}`
661
+ );
662
+ }
663
+ const epicWorktreePath = startResult == null ? void 0 : startResult.path;
664
+ if (!epicWorktreePath) {
665
+ throw new Error("Auto-swarm: StartCommand did not return a workspace path.");
666
+ }
667
+ const igniteCommand = new IgniteCommand();
668
+ await igniteCommand.execute("bypassPermissions", void 0, void 0, epicWorktreePath);
669
+ }
670
+ autoSwarmSuccess = true;
671
+ autoSwarmPhaseReached = "spin";
672
+ }
673
+ }
674
+ if (decompositionContext) {
675
+ try {
676
+ const mcpProv = IssueManagementProviderFactory.create(provider, settings ?? void 0);
677
+ const children = await mcpProv.getChildIssues({ number: decompositionContext.identifier });
678
+ TelemetryService.getInstance().track("epic.planned", {
679
+ child_count: children.length,
680
+ tracker: provider
681
+ });
682
+ } catch (error) {
683
+ logger.debug(`Telemetry epic.planned tracking failed: ${error instanceof Error ? error.message : error}`);
684
+ }
685
+ }
686
+ if (printOptions == null ? void 0 : printOptions.json) {
687
+ console.log(JSON.stringify({
688
+ success: true,
689
+ output: claudeResult ?? ""
690
+ }));
691
+ }
692
+ logger.debug("Claude session completed");
693
+ logger.info(chalk.green("Planning session ended."));
694
+ } finally {
695
+ if (harness) {
696
+ await harness.stop();
697
+ }
698
+ if (autoSwarm && autoSwarmStartTime !== null) {
699
+ const durationMinutes = (Date.now() - autoSwarmStartTime) / 6e4;
700
+ const autoSwarmSource = decompositionContext ? "decomposition" : "fresh";
701
+ const resolvedEpicData = epicData;
702
+ try {
703
+ TelemetryService.getInstance().track("auto_swarm.completed", {
704
+ source: autoSwarmSource,
705
+ success: autoSwarmSuccess,
706
+ child_count: (resolvedEpicData == null ? void 0 : resolvedEpicData.childIssues.length) ?? 0,
707
+ duration_minutes: Math.round(durationMinutes * 10) / 10,
708
+ phase_reached: autoSwarmPhaseReached,
709
+ fallback_to_normal: autoSwarmFallbackToNormal
710
+ });
711
+ } catch (error) {
712
+ logger.debug(`Telemetry auto_swarm.completed tracking failed: ${error instanceof Error ? error.message : error}`);
713
+ }
714
+ }
395
715
  }
396
- logger.debug("Claude session completed");
397
- logger.info(chalk.green("Planning session ended."));
398
716
  }
399
717
  };
400
718
  export {
401
719
  PlanCommand
402
720
  };
403
- //# sourceMappingURL=plan-Q7ELXDLC.js.map
721
+ //# sourceMappingURL=plan-RQ5FPIGF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/plan.ts","../src/lib/HarnessServer.ts"],"sourcesContent":["/* global AbortController, setImmediate */\nimport { logger, createStderrLogger } from '../utils/logger.js'\nimport { withLogger } from '../utils/logger-context.js'\nimport chalk from 'chalk'\nimport { detectClaudeCli, launchClaude } from '../utils/claude.js'\nimport { PromptTemplateManager, type TemplateVariables } from '../lib/PromptTemplateManager.js'\nimport { generateIssueManagementMcpConfig, generateHarnessMcpConfig } from '../utils/mcp.js'\nimport { HarnessServer } from '../lib/HarnessServer.js'\nimport { SettingsManager, PlanCommandSettingsSchema } from '../lib/SettingsManager.js'\nimport { IssueTrackerFactory } from '../lib/IssueTrackerFactory.js'\nimport { matchIssueIdentifier } from '../utils/IdentifierParser.js'\nimport { IssueManagementProviderFactory } from '../mcp/IssueManagementProviderFactory.js'\nimport { needsFirstRunSetup, launchFirstRunSetup } from '../utils/first-run-setup.js'\nimport type { IssueProvider, ChildIssueResult, DependenciesResult } from '../mcp/types.js'\nimport { promptConfirmation, isInteractiveEnvironment } from '../utils/prompt.js'\nimport { TelemetryService } from '../lib/TelemetryService.js'\nimport { StartCommand } from './start.js'\nimport { IgniteCommand } from './ignite.js'\n\n// Define provider arrays for validation and dynamic flag generation\nconst PLANNER_PROVIDERS = ['claude', 'gemini', 'codex'] as const\nconst REVIEWER_PROVIDERS = ['claude', 'gemini', 'codex', 'none'] as const\n\ntype PlannerProvider = (typeof PLANNER_PROVIDERS)[number]\ntype ReviewerProvider = (typeof REVIEWER_PROVIDERS)[number]\n\n/**\n * Format child issues as a markdown list for inclusion in the prompt\n */\nfunction formatChildIssues(children: ChildIssueResult[], issuePrefix: string): string {\n\tif (children.length === 0) return 'None'\n\treturn children\n\t\t.map(child => `- ${issuePrefix}${child.id}: ${child.title} (${child.state})`)\n\t\t.join('\\n')\n}\n\n/**\n * Format dependencies as a markdown list for inclusion in the prompt\n */\nfunction formatDependencies(dependencies: DependenciesResult, issuePrefix: string): string {\n\tconst lines: string[] = []\n\n\tif (dependencies.blockedBy.length > 0) {\n\t\tlines.push('**Blocked by:**')\n\t\tfor (const dep of dependencies.blockedBy) {\n\t\t\tlines.push(`- ${issuePrefix}${dep.id}: ${dep.title} (${dep.state})`)\n\t\t}\n\t}\n\n\tif (dependencies.blocking.length > 0) {\n\t\tif (lines.length > 0) lines.push('')\n\t\tlines.push('**Blocking:**')\n\t\tfor (const dep of dependencies.blocking) {\n\t\t\tlines.push(`- ${issuePrefix}${dep.id}: ${dep.title} (${dep.state})`)\n\t\t}\n\t}\n\n\treturn lines.length > 0 ? lines.join('\\n') : 'None'\n}\n\n/**\n * Launch interactive planning session with Architect persona\n * Implements the `il plan` command requested in issue #471\n *\n * The Architect persona helps users:\n * - Break epics down into child issues following \"1 issue = 1 loom = 1 PR\" pattern\n * - Think through implementation approaches\n * - Create issues at the end of the planning session using MCP tools\n */\nexport class PlanCommand {\n\tprivate readonly templateManager: PromptTemplateManager\n\n\tconstructor(templateManager?: PromptTemplateManager) {\n\t\tthis.templateManager = templateManager ?? new PromptTemplateManager()\n\t}\n\n\t/**\n\t * Main entry point for the plan command\n\t * @param prompt - Optional initial planning prompt or topic\n\t * @param model - Optional model to use (defaults to 'opus')\n\t * @param yolo - Optional flag to enable autonomous mode (skip permission prompts)\n\t * @param planner - Optional planner provider (defaults to 'claude')\n\t * @param reviewer - Optional reviewer provider (defaults to 'none')\n\t * @param printOptions - Print mode options for headless/CI execution\n\t */\n\tpublic async execute(\n\t\tprompt?: string,\n\t\tmodel?: string,\n\t\tyolo?: boolean,\n\t\tplanner?: string,\n\t\treviewer?: string,\n\t\tprintOptions?: {\n\t\t\tprint?: boolean\n\t\t\toutputFormat?: 'json' | 'stream-json' | 'text'\n\t\t\tverbose?: boolean\n\t\t\tjson?: boolean\n\t\t\tjsonStream?: boolean\n\t\t},\n\t\tautoSwarm?: boolean\n\t): Promise<void> {\n\t\t// Wrap execution in stderr logger for JSON modes to keep stdout clean\n\t\tconst isJsonMode = (printOptions?.json ?? false) || (printOptions?.jsonStream ?? false)\n\t\tif (isJsonMode) {\n\t\t\tconst jsonLogger = createStderrLogger()\n\t\t\treturn withLogger(jsonLogger, () => this.executeInternal(prompt, model, yolo, planner, reviewer, printOptions, autoSwarm))\n\t\t}\n\n\t\treturn this.executeInternal(prompt, model, yolo, planner, reviewer, printOptions, autoSwarm)\n\t}\n\n\t/**\n\t * Internal execution method (separated for withLogger wrapping)\n\t */\n\tprivate async executeInternal(\n\t\tprompt?: string,\n\t\tmodel?: string,\n\t\tyolo?: boolean,\n\t\tplanner?: string,\n\t\treviewer?: string,\n\t\tprintOptions?: {\n\t\t\tprint?: boolean\n\t\t\toutputFormat?: 'json' | 'stream-json' | 'text'\n\t\t\tverbose?: boolean\n\t\t\tjson?: boolean\n\t\t\tjsonStream?: boolean\n\t\t},\n\t\tautoSwarm?: boolean\n\t): Promise<void> {\n\t\t// Validate and normalize planner CLI argument\n\t\tlet normalizedPlanner: PlannerProvider | undefined\n\t\tif (planner) {\n\t\t\tconst normalized = planner.toLowerCase()\n\t\t\tconst result = PlanCommandSettingsSchema.shape.planner.safeParse(normalized)\n\t\t\tif (!result.success) {\n\t\t\t\tthrow new Error(`Invalid planner: \"${planner}\". Allowed values: ${PLANNER_PROVIDERS.join(', ')}`)\n\t\t\t}\n\t\t\tnormalizedPlanner = normalized as PlannerProvider\n\t\t}\n\n\t\t// Validate and normalize reviewer CLI argument\n\t\tlet normalizedReviewer: ReviewerProvider | undefined\n\t\tif (reviewer) {\n\t\t\tconst normalized = reviewer.toLowerCase()\n\t\t\tconst result = PlanCommandSettingsSchema.shape.reviewer.safeParse(normalized)\n\t\t\tif (!result.success) {\n\t\t\t\tthrow new Error(`Invalid reviewer: \"${reviewer}\". Allowed values: ${REVIEWER_PROVIDERS.join(', ')}`)\n\t\t\t}\n\t\t\tnormalizedReviewer = normalized as ReviewerProvider\n\t\t}\n\n\t\tlogger.debug('PlanCommand.execute() starting', {\n\t\t\tcwd: process.cwd(),\n\t\t\thasPrompt: !!prompt,\n\t\t\tyolo,\n\t\t\tplanner: normalizedPlanner ?? planner,\n\t\t\treviewer: normalizedReviewer ?? reviewer,\n\t\t})\n\n\t\t// Check for first-run setup (same check as StartCommand)\n\t\tif (process.env.FORCE_FIRST_TIME_SETUP === \"true\" || await needsFirstRunSetup()) {\n\t\t\tawait launchFirstRunSetup()\n\t\t}\n\n\t\tlogger.info(chalk.bold('Starting interactive planning session...'))\n\n\t\t// Check if Claude CLI is available\n\t\tlogger.debug('Checking Claude CLI availability')\n\t\tconst claudeAvailable = await detectClaudeCli()\n\t\tlogger.debug('Claude CLI availability check result', { claudeAvailable })\n\n\t\tif (!claudeAvailable) {\n\t\t\tlogger.error(\n\t\t\t\t\"Claude Code not detected. Please install it: npm install -g @anthropic-ai/claude-code\"\n\t\t\t)\n\t\t\tthrow new Error('Claude Code CLI is required for planning sessions')\n\t\t}\n\n\t\t// Load settings to detect configured issue provider and model\n\t\tconst settingsManager = new SettingsManager()\n\t\tconst settings = await settingsManager.loadSettings()\n\n\t\t// Detect if prompt is an issue number for decomposition mode\n\t\t// Uses shared matchIssueIdentifier() utility to identify issue identifiers:\n\t\t// - Numeric pattern: #123 or 123 (GitHub format)\n\t\t// - Project key pattern: ENG-123, PROJ-456 (requires at least 2 letters before dash)\n\t\tconst identifierMatch = prompt ? matchIssueIdentifier(prompt) : { isIssueIdentifier: false }\n\t\tconst looksLikeIssueIdentifier = identifierMatch.isIssueIdentifier\n\t\tlet decompositionContext: {\n\t\t\tidentifier: string\n\t\t\ttitle: string\n\t\t\tbody: string\n\t\t\tchildren?: ChildIssueResult[]\n\t\t\tdependencies?: DependenciesResult\n\t\t} | null = null\n\n\t\tconst provider = settings ? IssueTrackerFactory.getProviderName(settings) : 'github'\n\t\tconst issuePrefix = provider === 'github' ? '#' : ''\n\n\t\tif (prompt && looksLikeIssueIdentifier) {\n\t\t\t// Validate and fetch issue using issueTracker.detectInputType() pattern from StartCommand\n\t\t\tconst issueTracker = IssueTrackerFactory.create(settings)\n\n\t\t\tlogger.debug('Detected potential issue identifier, validating via issueTracker', { identifier: prompt })\n\n\t\t\t// Use detectInputType to validate the identifier exists (same pattern as StartCommand)\n\t\t\tconst detection = await issueTracker.detectInputType(prompt)\n\n\t\t\tif (detection.type === 'issue' && detection.identifier) {\n\t\t\t\t// Valid issue found - fetch full details for decomposition context\n\t\t\t\tconst issue = await issueTracker.fetchIssue(detection.identifier)\n\t\t\t\tdecompositionContext = {\n\t\t\t\t\tidentifier: String(issue.number),\n\t\t\t\t\ttitle: issue.title,\n\t\t\t\t\tbody: issue.body\n\t\t\t\t}\n\t\t\t\tlogger.info(chalk.dim(`Preparing to create a detailed plan for issue #${decompositionContext.identifier}: ${decompositionContext.title}`))\n\n\t\t\t\t// Fetch existing children and dependencies using MCP provider\n\t\t\t\t// This allows users to resume planning where they left off\n\t\t\t\ttry {\n\t\t\t\t\tconst mcpProvider = IssueManagementProviderFactory.create(provider as IssueProvider, settings ?? undefined)\n\n\t\t\t\t\t// Fetch child issues\n\t\t\t\t\tlogger.debug('Fetching child issues for decomposition context', { identifier: decompositionContext.identifier })\n\t\t\t\t\tconst children = await mcpProvider.getChildIssues({ number: decompositionContext.identifier })\n\t\t\t\t\tif (children.length > 0) {\n\t\t\t\t\t\tdecompositionContext.children = children\n\t\t\t\t\t\tlogger.debug('Found existing child issues', { count: children.length })\n\t\t\t\t\t}\n\n\t\t\t\t\t// Fetch dependencies (both directions)\n\t\t\t\t\tlogger.debug('Fetching dependencies for decomposition context', { identifier: decompositionContext.identifier })\n\t\t\t\t\tconst dependencies = await mcpProvider.getDependencies({\n\t\t\t\t\t\tnumber: decompositionContext.identifier,\n\t\t\t\t\t\tdirection: 'both'\n\t\t\t\t\t})\n\t\t\t\t\tif (dependencies.blocking.length > 0 || dependencies.blockedBy.length > 0) {\n\t\t\t\t\t\tdecompositionContext.dependencies = dependencies\n\t\t\t\t\t\tlogger.debug('Found existing dependencies', {\n\t\t\t\t\t\t\tblocking: dependencies.blocking.length,\n\t\t\t\t\t\t\tblockedBy: dependencies.blockedBy.length\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// Log but don't fail - children/dependencies are optional context\n\t\t\t\t\tlogger.debug('Failed to fetch children/dependencies, continuing without them', {\n\t\t\t\t\t\terror: error instanceof Error ? error.message : 'Unknown error'\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Input matched issue pattern but issue not found - treat as regular prompt\n\t\t\t\tlogger.debug('Input matched issue pattern but issue not found, treating as planning topic', {\n\t\t\t\t\tidentifier: prompt,\n\t\t\t\t\tdetectionType: detection.type\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\t// Use CLI model if provided, otherwise use settings (plan.model), defaults to opus\n\t\tconst effectiveModel = model ?? settingsManager.getPlanModel(settings ?? undefined)\n\n\t\t// Get effective planner/reviewer (CLI > settings > default)\n\t\tconst effectivePlanner = normalizedPlanner ?? settingsManager.getPlanPlanner(settings ?? undefined)\n\t\tconst effectiveReviewer = normalizedReviewer ?? settingsManager.getPlanReviewer(settings ?? undefined)\n\n\t\tlogger.debug('Detected issue provider, model, planner, and reviewer', {\n\t\t\tprovider,\n\t\t\teffectiveModel,\n\t\t\teffectivePlanner,\n\t\t\teffectiveReviewer,\n\t\t})\n\n\t\t// Generate MCP config for issue management tools\n\t\t// This will throw if no git remote is configured - offer to run 'il init' as fallback\n\t\tlogger.debug('Generating MCP config for issue management')\n\t\tlet mcpConfig: Record<string, unknown>[]\n\t\ttry {\n\t\t\tmcpConfig = await generateIssueManagementMcpConfig(undefined, undefined, provider, settings ?? undefined)\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : 'Unknown error'\n\n\t\t\t// Check if running in interactive mode - offer to run init\n\t\t\tif (isInteractiveEnvironment()) {\n\t\t\t\tconst shouldRunInit = await promptConfirmation(\n\t\t\t\t\t\"No git repository or remote found. Would you like to run 'il init' to set up?\",\n\t\t\t\t\ttrue\n\t\t\t\t)\n\t\t\t\tif (shouldRunInit) {\n\t\t\t\t\t// Dynamically import and run InitCommand\n\t\t\t\t\tlogger.info(chalk.bold('Launching iloom init...'))\n\t\t\t\t\tconst { InitCommand } = await import('./init.js')\n\t\t\t\t\tconst initCommand = new InitCommand()\n\t\t\t\t\tawait initCommand.execute(\n\t\t\t\t\t\t'Help the user set up a GitHub repository or Linear project for this project so they can use issue management features. When complete tell the user they can exit to continue the planning session.'\n\t\t\t\t\t)\n\n\t\t\t\t\t// Retry MCP config generation after init\n\t\t\t\t\tlogger.info(chalk.bold('Retrying planning session setup...'))\n\t\t\t\t\ttry {\n\t\t\t\t\t\tmcpConfig = await generateIssueManagementMcpConfig(undefined, undefined, provider, settings ?? undefined)\n\t\t\t\t\t} catch (retryError) {\n\t\t\t\t\t\tconst retryMessage = retryError instanceof Error ? retryError.message : 'Unknown error'\n\t\t\t\t\t\tlogger.error(`Failed to generate MCP config: ${retryMessage}`)\n\t\t\t\t\t\tif (provider === 'github') {\n\t\t\t\t\t\t\tlogger.error(\n\t\t\t\t\t\t\t\t'GitHub issue management requires a git repository with a GitHub remote configured.'\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t`Cannot start planning session after init: ${retryMessage}. Ensure you are in a git repository with a GitHub remote configured.`\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlogger.error(\n\t\t\t\t\t\t\t\t'Linear issue management requires LINEAR_API_TOKEN to be configured.'\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t`Cannot start planning session after init: ${retryMessage}. Ensure LINEAR_API_TOKEN is configured in settings or environment.`\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// User declined init prompt - show provider-specific error messages\n\t\t\t\t\tlogger.error(`Failed to generate MCP config: ${message}`)\n\t\t\t\t\tif (provider === 'github') {\n\t\t\t\t\t\tlogger.error(\n\t\t\t\t\t\t\t'GitHub issue management requires a git repository with a GitHub remote configured.'\n\t\t\t\t\t\t)\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`Cannot start planning session: ${message}. Ensure you are in a git repository with a GitHub remote configured.`\n\t\t\t\t\t\t)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlogger.error(\n\t\t\t\t\t\t\t'Linear issue management requires LINEAR_API_TOKEN to be configured.'\n\t\t\t\t\t\t)\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t`Cannot start planning session: ${message}. Ensure LINEAR_API_TOKEN is configured in settings or environment.`\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Non-interactive mode - show provider-specific error messages\n\t\t\t\tlogger.error(`Failed to generate MCP config: ${message}`)\n\t\t\t\tif (provider === 'github') {\n\t\t\t\t\tlogger.error(\n\t\t\t\t\t\t'GitHub issue management requires a git repository with a GitHub remote configured.'\n\t\t\t\t\t)\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Cannot start planning session: ${message}. Ensure you are in a git repository with a GitHub remote configured.`\n\t\t\t\t\t)\n\t\t\t\t} else {\n\t\t\t\t\tlogger.error(\n\t\t\t\t\t\t'Linear issue management requires LINEAR_API_TOKEN to be configured.'\n\t\t\t\t\t)\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Cannot start planning session: ${message}. Ensure LINEAR_API_TOKEN is configured in settings or environment.`\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tlogger.debug('MCP config generated', {\n\t\t\tserverCount: mcpConfig.length,\n\t\t})\n\n\t\t// --- Auto-swarm harness lifecycle ---\n\t\tlet harness: HarnessServer | null = null\n\t\tlet externalHarness = false\n\t\tlet epicData: { epicIssueNumber: string; childIssues: number[] } | null = null\n\t\tconst controller = autoSwarm ? new AbortController() : null\n\t\tconst autoSwarmStartTime = autoSwarm ? Date.now() : null\n\t\tlet autoSwarmSuccess = false\n\t\tlet autoSwarmPhaseReached: 'plan' | 'start' | 'spin' = 'plan'\n\t\tlet autoSwarmFallbackToNormal = false\n\n\t\tif (autoSwarm) {\n\t\t\tconst autoSwarmSource = decompositionContext ? 'decomposition' : 'fresh'\n\t\t\ttry {\n\t\t\t\tTelemetryService.getInstance().track('auto_swarm.started', {\n\t\t\t\t\tsource: autoSwarmSource,\n\t\t\t\t\tplanner: effectivePlanner,\n\t\t\t\t})\n\t\t\t} catch (error) {\n\t\t\t\tlogger.debug(`Telemetry auto_swarm.started tracking failed: ${error instanceof Error ? error.message : error}`)\n\t\t\t}\n\n\t\t\t// 1. Force yolo mode\n\t\t\tyolo = true\n\n\t\t\t// 2. Check for external harness (e.g., VS Code extension provides its own socket)\n\t\t\tconst externalSocket = process.env.ILOOM_HARNESS_SOCKET\n\t\t\texternalHarness = !!externalSocket\n\n\t\t\tif (!externalSocket) {\n\t\t\t\t// 3. Create and start harness server\n\t\t\t\tharness = new HarnessServer()\n\t\t\t\tawait harness.start()\n\t\t\t}\n\n\t\t\tconst socketPath = externalSocket ?? harness?.path\n\t\t\tif (!socketPath) {\n\t\t\t\tthrow new Error('Unexpected: no harness socket path available')\n\t\t\t}\n\n\t\t\t// 4. Register \"done\" handler (only when we own the harness server)\n\t\t\tif (harness) {\n\t\t\t\tharness.registerHandler('done', (data) => {\n\t\t\t\t\tepicData = data as typeof epicData\n\t\t\t\t\tsetImmediate(() => { controller?.abort() })\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: 'instruction' as const,\n\t\t\t\t\t\tcontent: 'Planning complete. The auto-swarm pipeline will now create the epic workspace and launch swarm mode automatically.',\n\t\t\t\t\t}\n\t\t\t\t}, { idempotent: true })\n\t\t\t}\n\n\t\t\t// 5. Merge harness MCP config\n\t\t\tconst harnessMcpConfig = generateHarnessMcpConfig(socketPath)\n\t\t\tmcpConfig = [...mcpConfig, ...harnessMcpConfig]\n\t\t}\n\n\t\t// Detect VS Code mode\n\t\tconst isVscodeMode = process.env.ILOOM_VSCODE === '1'\n\t\tlogger.debug('VS Code mode detection', { isVscodeMode })\n\n\t\t// Compute template variables for multi-AI provider support\n\t\t// Generate USE_*_PLANNER and USE_*_REVIEWER flags dynamically\n\t\tconst providerFlags = PLANNER_PROVIDERS.reduce((acc, p) => ({\n\t\t\t...acc,\n\t\t\t[`USE_${p.toUpperCase()}_PLANNER`]: effectivePlanner === p,\n\t\t}), {} as Record<string, boolean>)\n\n\t\t// Add reviewer flags (excluding 'none')\n\t\t;(['claude', 'gemini', 'codex'] as const).forEach(p => {\n\t\t\tproviderFlags[`USE_${p.toUpperCase()}_REVIEWER`] = effectiveReviewer === p\n\t\t})\n\n\t\t// Load plan prompt template with mode-specific variables\n\t\tlogger.debug('Loading plan prompt template')\n\t\tconst templateVariables: TemplateVariables = {\n\t\t\tIS_VSCODE_MODE: isVscodeMode,\n\t\t\tEXISTING_ISSUE_MODE: !!decompositionContext,\n\t\t\tFRESH_PLANNING_MODE: !decompositionContext,\n\t\t\tPARENT_ISSUE_NUMBER: decompositionContext?.identifier,\n\t\t\tPARENT_ISSUE_TITLE: decompositionContext?.title,\n\t\t\tPARENT_ISSUE_BODY: decompositionContext?.body,\n\t\t\tPARENT_ISSUE_CHILDREN: decompositionContext?.children\n\t\t\t\t? formatChildIssues(decompositionContext.children, issuePrefix)\n\t\t\t\t: undefined,\n\t\t\tPARENT_ISSUE_DEPENDENCIES: decompositionContext?.dependencies\n\t\t\t\t? formatDependencies(decompositionContext.dependencies, issuePrefix)\n\t\t\t\t: undefined,\n\t\t\tPLANNER: effectivePlanner,\n\t\t\tREVIEWER: effectiveReviewer,\n\t\t\tHAS_REVIEWER: effectiveReviewer !== 'none',\n\t\t\tAUTO_SWARM_MODE: autoSwarm ?? false,\n\t\t\t...providerFlags,\n\t\t}\n\t\tconst architectPrompt = await this.templateManager.getPrompt('plan', templateVariables)\n\t\tlogger.debug('Plan prompt loaded', {\n\t\t\tpromptLength: architectPrompt.length,\n\t\t\tmode: decompositionContext ? 'decomposition' : 'fresh',\n\t\t})\n\n\t\t// Define allowed tools for the Architect persona\n\t\tconst allowedTools = [\n\t\t\t// Issue management tools\n\t\t\t'mcp__issue_management__create_issue',\n\t\t\t'mcp__issue_management__create_child_issue',\n\t\t\t'mcp__issue_management__get_issue',\n\t\t\t'mcp__issue_management__get_child_issues',\n\t\t\t'mcp__issue_management__get_comment',\n\t\t\t'mcp__issue_management__create_comment',\n\t\t\t// Dependency management tools\n\t\t\t'mcp__issue_management__create_dependency',\n\t\t\t'mcp__issue_management__get_dependencies',\n\t\t\t'mcp__issue_management__remove_dependency',\n\t\t\t// Codebase exploration tools (read-only)\n\t\t\t'Read',\n\t\t\t'Glob',\n\t\t\t'Grep',\n\t\t\t'Task',\n\t\t\t// Web research tools\n\t\t\t'WebFetch',\n\t\t\t'WebSearch',\n\t\t\t// Git commands for understanding repo state\n\t\t\t'Bash(git status:*)',\n\t\t\t'Bash(git log:*)',\n\t\t\t'Bash(git branch:*)',\n\t\t\t'Bash(git remote:*)',\n\t\t\t'Bash(git diff:*)',\n\t\t\t'Bash(git show:*)',\n\t\t]\n\n\t\tif (autoSwarm) {\n\t\t\tallowedTools.push('mcp__harness__signal')\n\t\t}\n\n\t\t// Determine if we're in print/headless mode\n\t\tconst isHeadless = printOptions?.print ?? false\n\n\t\t// Build Claude options\n\t\tconst claudeOptions: Parameters<typeof launchClaude>[1] = {\n\t\t\tmodel: effectiveModel,\n\t\t\theadless: isHeadless,\n\t\t\tappendSystemPrompt: architectPrompt,\n\t\t\tmcpConfig,\n\t\t\taddDir: process.cwd(),\n\t\t\tallowedTools,\n\t\t}\n\n\t\t// Add output format and verbose options if provided (print mode only)\n\t\tif (printOptions?.outputFormat !== undefined) {\n\t\t\tclaudeOptions.outputFormat = printOptions.outputFormat\n\t\t}\n\t\tif (printOptions?.verbose !== undefined) {\n\t\t\tclaudeOptions.verbose = printOptions.verbose\n\t\t}\n\n\t\t// Add JSON mode if specified (requires print mode)\n\t\tif (printOptions?.json) {\n\t\t\tclaudeOptions.jsonMode = 'json'\n\t\t\tclaudeOptions.outputFormat = 'stream-json' // Force stream-json for parsing\n\t\t} else if (printOptions?.jsonStream) {\n\t\t\tclaudeOptions.jsonMode = 'stream'\n\t\t\tclaudeOptions.outputFormat = 'stream-json' // Force stream-json for streaming\n\t\t}\n\n\t\t// Force yolo mode when print mode is enabled (headless execution requires autonomous mode)\n\t\tconst effectiveYolo = (yolo ?? false) || isHeadless\n\n\t\t// Handle --yolo mode\n\t\tif (effectiveYolo) {\n\t\t\t// Only require prompt for explicit --yolo flag, not for print mode auto-yolo\n\t\t\tif (yolo && !prompt) {\n\t\t\t\tthrow new Error('--yolo requires a prompt or issue identifier (e.g., il plan --yolo \"add gitlab support\" or il plan --yolo 42)')\n\t\t\t}\n\t\t\tlogger.warn(\n\t\t\t\t'YOLO mode enabled - Claude will skip permission prompts and proceed autonomously. This could destroy important data or make irreversible changes. Proceeding means you accept this risk.'\n\t\t\t)\n\t\t}\n\n\t\tlogger.debug('Launching Claude with options', {\n\t\t\toptionKeys: Object.keys(claudeOptions),\n\t\t\theadless: claudeOptions.headless,\n\t\t\thasSystemPrompt: !!claudeOptions.appendSystemPrompt,\n\t\t\taddDir: claudeOptions.addDir,\n\t\t\tyolo,\n\t\t\tprint: isHeadless,\n\t\t})\n\n\t\t// Launch Claude in interactive mode\n\t\t// Construct initial message based on mode\n\t\tlet initialMessage: string\n\t\tif (decompositionContext) {\n\t\t\t// Issue decomposition mode - provide context about what to decompose\n\t\t\tinitialMessage = `Break down issue #${decompositionContext.identifier} into child issues.`\n\t\t} else if (prompt) {\n\t\t\t// Fresh planning with user-provided topic\n\t\t\tinitialMessage = prompt\n\t\t} else {\n\t\t\t// Interactive mode - no topic provided\n\t\t\tinitialMessage = 'Help me plan a feature or decompose work into issues.'\n\t\t}\n\n\t\t// Apply yolo mode wrapper if enabled (includes print mode)\n\t\tif (effectiveYolo) {\n\t\t\tinitialMessage = `[AUTONOMOUS MODE]\nProceed through the flow without requiring user interaction. Make and document your assumptions and proceed to create the epic and child issues and dependencies if necessary. This guidance supersedes all previous guidance.\n\n[TOPIC]\n${initialMessage}`\n\t\t}\n\n\t\ttry {\n\t\t\tconst claudeResult = await launchClaude(initialMessage, {\n\t\t\t\t...claudeOptions,\n\t\t\t\t...(effectiveYolo && { permissionMode: 'bypassPermissions' as const }),\n\t\t\t\t...(controller && { signal: controller.signal }),\n\t\t\t})\n\n\t\t\t// Check auto-swarm outcome\n\t\t\tif (autoSwarm) {\n\t\t\t\t// When an external harness (e.g., VS Code) owns the socket, it handles\n\t\t\t\t// the \"done\" signal and manages the start/spin pipeline itself.\n\t\t\t\t// The CLI just exits cleanly after the plan phase.\n\t\t\t\tif (externalHarness) {\n\t\t\t\t\tlogger.info(chalk.green('Planning session ended. External harness will manage the pipeline.'))\n\t\t\t\t\tautoSwarmSuccess = true\n\t\t\t\t\tautoSwarmPhaseReached = 'plan'\n\t\t\t\t} else if (!epicData) {\n\t\t\t\t\tthrow new Error('Plan phase exited without completing. The Architect did not signal done.')\n\t\t\t\t} else {\n\t\t\t\t\t// Cast required because TypeScript cannot narrow let variables mutated in closures.\n\t\t\t\t\t// Defensively default childIssues — the data comes from AI-generated signal payloads.\n\t\t\t\t\tconst resolvedEpicData = epicData as { epicIssueNumber: string; childIssues?: number[] }\n\t\t\t\t\tconst epicIssueNumber = resolvedEpicData.epicIssueNumber\n\t\t\t\t\tconst childIssues = resolvedEpicData.childIssues ?? []\n\t\t\t\t\tlogger.info(chalk.green(`Planning complete. Epic issue: #${epicIssueNumber}`))\n\t\t\t\t\tautoSwarmFallbackToNormal = childIssues.length === 0\n\n\t\t\t\t\tconst startCommand = new StartCommand(IssueTrackerFactory.create(settings ?? {}))\n\n\t\t\t\t\tif (childIssues.length === 0) {\n\t\t\t\t\t\t// Zero-children fallback: normal (non-epic) autonomous loom\n\t\t\t\t\t\tlogger.info('No child issues created. Starting as a normal autonomous loom.')\n\t\t\t\t\t\tlet startResult\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tstartResult = await startCommand.execute({\n\t\t\t\t\t\t\t\tidentifier: String(epicIssueNumber),\n\t\t\t\t\t\t\t\toptions: { oneShot: 'bypassPermissions', json: true, claude: false, code: false, devServer: false, terminal: false },\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t} catch (startError) {\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t`Auto-swarm: failed to create epic workspace. ${startError instanceof Error ? startError.message : String(startError)}`\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst epicWorktreePath = startResult?.path\n\t\t\t\t\t\tif (!epicWorktreePath) {\n\t\t\t\t\t\t\tthrow new Error('Auto-swarm: StartCommand did not return a workspace path.')\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst igniteCommand = new IgniteCommand()\n\t\t\t\t\t\tawait igniteCommand.execute('bypassPermissions', undefined, undefined, epicWorktreePath)\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Epic mode: start + spin with swarm\n\t\t\t\t\t\tlet startResult\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tstartResult = await startCommand.execute({\n\t\t\t\t\t\t\t\tidentifier: String(epicIssueNumber),\n\t\t\t\t\t\t\t\toptions: { epic: true, json: true, oneShot: 'bypassPermissions', claude: false, code: false, devServer: false, terminal: false },\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t} catch (startError) {\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t`Auto-swarm: failed to create epic workspace. ${startError instanceof Error ? startError.message : String(startError)}`\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst epicWorktreePath = startResult?.path\n\t\t\t\t\t\tif (!epicWorktreePath) {\n\t\t\t\t\t\t\tthrow new Error('Auto-swarm: StartCommand did not return a workspace path.')\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst igniteCommand = new IgniteCommand()\n\t\t\t\t\t\tawait igniteCommand.execute('bypassPermissions', undefined, undefined, epicWorktreePath)\n\t\t\t\t\t}\n\n\t\t\t\t\tautoSwarmSuccess = true\n\t\t\t\t\tautoSwarmPhaseReached = 'spin'\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Track epic.planned telemetry for decomposition sessions\n\t\t\tif (decompositionContext) {\n\t\t\t\ttry {\n\t\t\t\t\tconst mcpProv = IssueManagementProviderFactory.create(provider as IssueProvider, settings ?? undefined)\n\t\t\t\t\tconst children = await mcpProv.getChildIssues({ number: decompositionContext.identifier })\n\t\t\t\t\tTelemetryService.getInstance().track('epic.planned', {\n\t\t\t\t\t\tchild_count: children.length,\n\t\t\t\t\t\ttracker: provider,\n\t\t\t\t\t})\n\t\t\t\t} catch (error) {\n\t\t\t\t\tlogger.debug(`Telemetry epic.planned tracking failed: ${error instanceof Error ? error.message : error}`)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Output final JSON for --json mode (--json-stream already streamed to stdout)\n\t\t\tif (printOptions?.json) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.log(JSON.stringify({\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\toutput: claudeResult ?? ''\n\t\t\t\t}))\n\t\t\t}\n\n\t\t\tlogger.debug('Claude session completed')\n\t\t\tlogger.info(chalk.green('Planning session ended.'))\n\t\t} finally {\n\t\t\tif (harness) {\n\t\t\t\tawait harness.stop()\n\t\t\t}\n\n\t\t\tif (autoSwarm && autoSwarmStartTime !== null) {\n\t\t\t\tconst durationMinutes = (Date.now() - autoSwarmStartTime) / 60000\n\t\t\t\tconst autoSwarmSource = decompositionContext ? 'decomposition' : 'fresh'\n\t\t\t\tconst resolvedEpicData = epicData as { epicIssueNumber: string; childIssues: number[] } | null\n\t\t\t\ttry {\n\t\t\t\t\tTelemetryService.getInstance().track('auto_swarm.completed', {\n\t\t\t\t\t\tsource: autoSwarmSource,\n\t\t\t\t\t\tsuccess: autoSwarmSuccess,\n\t\t\t\t\t\tchild_count: resolvedEpicData?.childIssues.length ?? 0,\n\t\t\t\t\t\tduration_minutes: Math.round(durationMinutes * 10) / 10,\n\t\t\t\t\t\tphase_reached: autoSwarmPhaseReached,\n\t\t\t\t\t\tfallback_to_normal: autoSwarmFallbackToNormal,\n\t\t\t\t\t})\n\t\t\t\t} catch (error) {\n\t\t\t\t\tlogger.debug(`Telemetry auto_swarm.completed tracking failed: ${error instanceof Error ? error.message : error}`)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n","import net from 'net'\nimport fs from 'fs'\nimport os from 'os'\nimport path from 'path'\nimport { randomUUID } from 'crypto'\nimport { logger } from '../utils/logger.js'\n\nexport interface HarnessMessage {\n\ttype: string\n\tdata?: unknown\n}\n\nexport interface HarnessResponse {\n\ttype: 'instruction' | 'acknowledged' | 'error'\n\tcontent?: string\n}\n\nexport type HarnessHandler = (data: unknown) => HarnessResponse | Promise<HarnessResponse>\n\nexport interface HarnessServerOptions {\n\tsocketPath?: string\n}\n\nexport class HarnessServer {\n\tprivate server: net.Server | null = null\n\tprivate readonly socketPath: string\n\tprivate readonly handlers: Map<string, HarnessHandler> = new Map()\n\tprivate readonly idempotentTypes: Set<string> = new Set()\n\tprivate readonly handledTypes: Set<string> = new Set()\n\tprivate readonly connections: Set<net.Socket> = new Set()\n\tprivate readonly waiters: Map<string, Array<(data: unknown) => void>> = new Map()\n\tprivate readonly boundSignalHandler: (signal: NodeJS.Signals) => void\n\n\tconstructor(options: HarnessServerOptions = {}) {\n\t\tthis.socketPath =\n\t\t\toptions.socketPath ??\n\t\t\tpath.join(os.tmpdir(), `iloom-harness-${randomUUID()}.sock`)\n\t\tthis.boundSignalHandler = (signal: NodeJS.Signals): void => {\n\t\t\tvoid this.stop().finally(() => {\n\t\t\t\t// Re-raise so the default handler terminates the process\n\t\t\t\tprocess.kill(process.pid, signal)\n\t\t\t})\n\t\t}\n\t}\n\n\tget path(): string {\n\t\treturn this.socketPath\n\t}\n\n\tregisterHandler(type: string, handler: HarnessHandler, options?: { idempotent?: boolean }): void {\n\t\tthis.handlers.set(type, handler)\n\t\tif (options?.idempotent) {\n\t\t\tthis.idempotentTypes.add(type)\n\t\t}\n\t}\n\n\tasync start(): Promise<void> {\n\t\tif (this.server !== null) {\n\t\t\tthrow new Error('HarnessServer is already started')\n\t\t}\n\n\t\t// Remove stale socket file from crashed previous runs\n\t\tfs.rmSync(this.socketPath, { force: true })\n\n\t\tconst server = net.createServer((socket) => {\n\t\t\tthis.handleConnection(socket)\n\t\t})\n\t\tthis.server = server\n\n\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\tserver.listen(this.socketPath, () => resolve())\n\t\t\tserver.once('error', reject)\n\t\t})\n\n\t\t// Set socket to owner read/write only\n\t\tfs.chmodSync(this.socketPath, 0o600)\n\n\t\t// Register signal handlers for cleanup on process exit\n\t\tprocess.on('SIGINT', this.boundSignalHandler)\n\t\tprocess.on('SIGTERM', this.boundSignalHandler)\n\n\t\tlogger.debug(`HarnessServer listening on ${this.socketPath}`)\n\t}\n\n\tasync stop(): Promise<void> {\n\t\tif (this.server === null) {\n\t\t\treturn\n\t\t}\n\n\t\t// Destroy all active connections so the server can close\n\t\tfor (const socket of this.connections) {\n\t\t\tsocket.destroy()\n\t\t}\n\t\tthis.connections.clear()\n\n\t\t// Close the server (set to null first for idempotency guard)\n\t\tconst serverToClose = this.server\n\t\tthis.server = null\n\n\t\ttry {\n\t\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\t\tserverToClose.close((err) => {\n\t\t\t\t\tif (err) reject(err)\n\t\t\t\t\telse resolve()\n\t\t\t\t})\n\t\t\t})\n\t\t} finally {\n\t\t\t// Cleanup must run even if server.close() rejects\n\t\t\tfs.rmSync(this.socketPath, { force: true })\n\t\t\tthis.waiters.clear()\n\t\t\tprocess.off('SIGINT', this.boundSignalHandler)\n\t\t\tprocess.off('SIGTERM', this.boundSignalHandler)\n\t\t\tlogger.debug('HarnessServer stopped')\n\t\t}\n\t}\n\n\twaitFor(type: string): Promise<unknown> {\n\t\treturn new Promise<unknown>((resolve) => {\n\t\t\tconst resolvers = this.waiters.get(type) ?? []\n\t\t\tresolvers.push(resolve)\n\t\t\tthis.waiters.set(type, resolvers)\n\t\t})\n\t}\n\n\tprivate handleConnection(socket: net.Socket): void {\n\t\tthis.connections.add(socket)\n\t\tlet buffer = ''\n\t\tconst MAX_BUFFER_SIZE = 1024 * 1024 // 1MB\n\n\t\tsocket.on('data', (chunk: Buffer) => {\n\t\t\tbuffer += chunk.toString()\n\t\t\tif (buffer.length > MAX_BUFFER_SIZE) {\n\t\t\t\tsocket.destroy(new Error('Payload too large'))\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst lines = buffer.split('\\n')\n\t\t\t// Keep the last potentially incomplete segment in the buffer\n\t\t\tbuffer = lines.pop() ?? ''\n\t\t\tfor (const line of lines) {\n\t\t\t\tconst trimmed = line.trim()\n\t\t\t\tif (trimmed) {\n\t\t\t\t\tvoid this.processMessage(trimmed, socket)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\n\t\tsocket.on('close', () => {\n\t\t\tthis.connections.delete(socket)\n\t\t})\n\n\t\tsocket.on('error', (err: Error) => {\n\t\t\tlogger.debug(`HarnessServer socket error: ${err.message}`)\n\t\t})\n\t}\n\n\tprivate async processMessage(raw: string, socket: net.Socket): Promise<void> {\n\t\tlet message: HarnessMessage\n\t\ttry {\n\t\t\tconst parsed: unknown = JSON.parse(raw)\n\t\t\tif (!parsed || typeof parsed !== 'object' || typeof (parsed as Record<string, unknown>).type !== 'string') {\n\t\t\t\tthis.sendResponse(socket, { type: 'error', content: 'Invalid message format' })\n\t\t\t\treturn\n\t\t\t}\n\t\t\tmessage = parsed as HarnessMessage\n\t\t} catch {\n\t\t\tthis.sendResponse(socket, { type: 'error', content: 'Malformed JSON' })\n\t\t\treturn\n\t\t}\n\n\t\t// Resolve any waiters registered for this message type\n\t\tconst resolvers = this.waiters.get(message.type)\n\t\tif (resolvers && resolvers.length > 0) {\n\t\t\tthis.waiters.delete(message.type)\n\t\t\tfor (const resolve of resolvers) {\n\t\t\t\tresolve(message.data)\n\t\t\t}\n\t\t}\n\n\t\t// Idempotent handling: only applies to handlers registered with { idempotent: true }\n\t\tif (this.idempotentTypes.has(message.type) && this.handledTypes.has(message.type)) {\n\t\t\tthis.sendResponse(socket, { type: 'acknowledged' })\n\t\t\treturn\n\t\t}\n\n\t\t// No handler registered for this type\n\t\tconst handler = this.handlers.get(message.type)\n\t\tif (!handler) {\n\t\t\tthis.sendResponse(socket, {\n\t\t\t\ttype: 'error',\n\t\t\t\tcontent: `No handler registered for type: ${message.type}`,\n\t\t\t})\n\t\t\treturn\n\t\t}\n\n\t\t// Mark as handled before calling handler (only for idempotent types)\n\t\tif (this.idempotentTypes.has(message.type)) {\n\t\t\tthis.handledTypes.add(message.type)\n\t\t}\n\t\tconst response = await handler(message.data)\n\t\tthis.sendResponse(socket, response)\n\t}\n\n\tprivate sendResponse(socket: net.Socket, response: HarnessResponse): void {\n\t\tsocket.write(JSON.stringify(response) + '\\n')\n\t}\n}\n"],"mappings":"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","names":[]}
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ProjectCapabilityDetector
4
- } from "./chunk-TL72BGP6.js";
5
- import "./chunk-VOGGLPG5.js";
4
+ } from "./chunk-MORRVYPT.js";
5
+ import "./chunk-YQ57ORTV.js";
6
6
  import {
7
7
  MetadataManager
8
- } from "./chunk-KBEIQP4G.js";
8
+ } from "./chunk-KB64WNBZ.js";
9
9
  import {
10
10
  getLogger
11
11
  } from "./chunk-6MLEBAYZ.js";
@@ -100,4 +100,4 @@ var ProjectsCommand = class {
100
100
  export {
101
101
  ProjectsCommand
102
102
  };
103
- //# sourceMappingURL=projects-LH362JZQ.js.map
103
+ //# sourceMappingURL=projects-2UOXFLNZ.js.map