@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
package/dist/cli.js CHANGED
@@ -1,72 +1,83 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  SessionSummaryService
4
- } from "./chunk-3I4ONZRT.js";
4
+ } from "./chunk-EVPZFV3K.js";
5
5
  import "./chunk-NXMDEL3F.js";
6
+ import {
7
+ ResourceCleanup
8
+ } from "./chunk-RJ3VBUFK.js";
9
+ import "./chunk-LUKXJSRI.js";
10
+ import {
11
+ StartCommand,
12
+ launchFirstRunSetup,
13
+ needsFirstRunSetup
14
+ } from "./chunk-GRISNU6G.js";
6
15
  import {
7
16
  CLIIsolationManager,
8
17
  DatabaseManager,
9
18
  EnvironmentManager,
10
- LoomManager,
11
- ResourceCleanup
12
- } from "./chunk-SOSQILHO.js";
19
+ LoomManager
20
+ } from "./chunk-ZNMPGMHY.js";
13
21
  import {
14
22
  PRManager
15
- } from "./chunk-DGG2VY7B.js";
23
+ } from "./chunk-KVHIAWVT.js";
16
24
  import {
17
- launchFirstRunSetup,
18
- needsFirstRunSetup
19
- } from "./chunk-W6DP5RVR.js";
25
+ CommitManager,
26
+ UserAbortedCommitError,
27
+ ValidationRunner
28
+ } from "./chunk-5RPBYK5Q.js";
20
29
  import {
21
30
  BuildRunner,
22
31
  MergeManager
23
- } from "./chunk-R4YWBGY6.js";
32
+ } from "./chunk-5FJWO4IT.js";
24
33
  import {
25
- IssueTrackerFactory
26
- } from "./chunk-KXGQYLFZ.js";
34
+ assembleChildrenData
35
+ } from "./chunk-QZWEJVWV.js";
36
+ import {
37
+ IssueManagementProviderFactory
38
+ } from "./chunk-SWSJWA2S.js";
39
+ import "./chunk-4232AHNQ.js";
27
40
  import {
28
41
  ProcessManager
29
- } from "./chunk-IZIYLYPK.js";
30
- import "./chunk-NUACL52E.js";
42
+ } from "./chunk-G5V75JD5.js";
43
+ import "./chunk-LLHXQS3C.js";
31
44
  import {
32
- IdentifierParser,
33
- matchIssueIdentifier
34
- } from "./chunk-YKFCCV6S.js";
45
+ installDependencies
46
+ } from "./chunk-WWKOVDWC.js";
47
+ import {
48
+ IdentifierParser
49
+ } from "./chunk-63QWFWH3.js";
35
50
  import {
36
51
  createNeonProviderFromSettings
37
- } from "./chunk-7ZEHSSUP.js";
52
+ } from "./chunk-P4O6EH46.js";
38
53
  import {
39
54
  ShellCompletion
40
- } from "./chunk-NWMORW3U.js";
55
+ } from "./chunk-KIK2ZFAL.js";
56
+ import {
57
+ TelemetryManager,
58
+ TelemetryService
59
+ } from "./chunk-RSYT7MVI.js";
60
+ import {
61
+ GitWorktreeManager
62
+ } from "./chunk-I5T677EA.js";
41
63
  import "./chunk-Q7POFB5Q.js";
42
64
  import {
43
- IssueEnhancementService,
65
+ IssueEnhancementService
66
+ } from "./chunk-KKV5WH5M.js";
67
+ import {
44
68
  capitalizeFirstLetter
45
- } from "./chunk-CWRI4JC3.js";
46
- import "./chunk-WHI5KEOX.js";
69
+ } from "./chunk-4E7LCFUG.js";
70
+ import "./chunk-SKSYYBCU.js";
47
71
  import {
48
72
  openBrowser
49
73
  } from "./chunk-YETJNRQM.js";
50
74
  import {
51
- AgentManager
52
- } from "./chunk-B7U6OKUR.js";
53
- import {
54
- CommitManager,
55
- UserAbortedCommitError,
56
- ValidationRunner
57
- } from "./chunk-VPTAX5TR.js";
58
- import {
59
- IssueManagementProviderFactory
60
- } from "./chunk-ULSWCPQG.js";
61
- import {
62
- getLinearChildIssues
63
- } from "./chunk-FJDRTVJX.js";
64
- import {
65
- installDependencies
66
- } from "./chunk-4LKGCFGG.js";
75
+ ProjectCapabilityDetector
76
+ } from "./chunk-MORRVYPT.js";
77
+ import "./chunk-YQ57ORTV.js";
67
78
  import {
68
- GitWorktreeManager
69
- } from "./chunk-TC7APDKU.js";
79
+ AgentManager
80
+ } from "./chunk-C6HNNJIV.js";
70
81
  import {
71
82
  getConfiguredRepoFromSettings,
72
83
  hasMultipleRemotes
@@ -78,19 +89,12 @@ import {
78
89
  } from "./chunk-O7VL5N6S.js";
79
90
  import {
80
91
  ClaudeContextManager
81
- } from "./chunk-Z2TWEXR7.js";
82
- import "./chunk-6IIL5M2L.js";
83
- import "./chunk-QN47QVBX.js";
84
- import {
85
- extractSettingsOverrides
86
- } from "./chunk-GYCR2LOU.js";
87
- import {
88
- DefaultBranchNamingService
89
- } from "./chunk-KAYXR544.js";
90
- import {
91
- ProjectCapabilityDetector
92
- } from "./chunk-TL72BGP6.js";
93
- import "./chunk-VOGGLPG5.js";
92
+ } from "./chunk-E6KOWMKA.js";
93
+ import "./chunk-S7PZA6IV.js";
94
+ import "./chunk-UR5DGNUO.js";
95
+ import "./chunk-UUEW5KWB.js";
96
+ import "./chunk-GYCR2LOU.js";
97
+ import "./chunk-QVLPWNE3.js";
94
98
  import {
95
99
  GitCommandError,
96
100
  executeGitCommand,
@@ -103,29 +107,30 @@ import {
103
107
  pushBranchToRemote,
104
108
  removePlaceholderCommitFromHead,
105
109
  removePlaceholderCommitFromHistory
106
- } from "./chunk-AR5QKYNE.js";
110
+ } from "./chunk-4FGEGQW4.js";
107
111
  import {
108
112
  SettingsManager
109
- } from "./chunk-RI2YL6TK.js";
113
+ } from "./chunk-7VHJNVLF.js";
110
114
  import {
111
115
  MetadataManager
112
- } from "./chunk-KBEIQP4G.js";
116
+ } from "./chunk-KB64WNBZ.js";
117
+ import {
118
+ IssueTrackerFactory
119
+ } from "./chunk-UKBAJ2QQ.js";
120
+ import "./chunk-HEXKPKCK.js";
113
121
  import {
114
122
  GitHubService
115
- } from "./chunk-OFDN5NKS.js";
123
+ } from "./chunk-KXDRI47U.js";
124
+ import "./chunk-VG45TUYK.js";
116
125
  import {
117
- getSubIssues
118
- } from "./chunk-4CO6KG5S.js";
126
+ getLogger,
127
+ withLogger
128
+ } from "./chunk-6MLEBAYZ.js";
119
129
  import {
120
130
  promptConfirmation,
121
131
  waitForKeypress
122
132
  } from "./chunk-7JDMYTFZ.js";
123
133
  import "./chunk-433MOLAU.js";
124
- import "./chunk-FO5GGFOV.js";
125
- import {
126
- getLogger,
127
- withLogger
128
- } from "./chunk-6MLEBAYZ.js";
129
134
  import {
130
135
  createStderrLogger,
131
136
  loadEnvIntoProcess,
@@ -135,423 +140,6 @@ import {
135
140
  // src/cli.ts
136
141
  import { program, Option } from "commander";
137
142
 
138
- // src/commands/start.ts
139
- import path from "path";
140
- var StartCommand = class {
141
- constructor(issueTracker, loomManager, _agentManager, settingsManager) {
142
- this.loomManager = null;
143
- this.githubService = null;
144
- this.issueTracker = issueTracker;
145
- this.settingsManager = settingsManager ?? new SettingsManager();
146
- this.providedLoomManager = loomManager;
147
- const envResult = loadEnvIntoProcess();
148
- if (envResult.error) {
149
- getLogger().debug(`Environment loading warning: ${envResult.error.message}`);
150
- }
151
- if (envResult.parsed) {
152
- getLogger().debug(`Loaded ${Object.keys(envResult.parsed).length} environment variables`);
153
- }
154
- }
155
- /**
156
- * Get or create a GitHubService instance for PR operations
157
- * Used when the configured issue tracker doesn't support PRs (e.g., Linear)
158
- */
159
- getGitHubService() {
160
- this.githubService ??= new GitHubService();
161
- return this.githubService;
162
- }
163
- /**
164
- * Initialize LoomManager with the main worktree path
165
- * Uses lazy initialization to ensure we have the correct path
166
- */
167
- async initializeLoomManager() {
168
- var _a, _b;
169
- if (this.loomManager) {
170
- return this.loomManager;
171
- }
172
- if (this.providedLoomManager) {
173
- this.loomManager = this.providedLoomManager;
174
- return this.loomManager;
175
- }
176
- const mainWorktreePath = await findMainWorktreePathWithSettings();
177
- const settings = await this.settingsManager.loadSettings();
178
- const environmentManager = new EnvironmentManager();
179
- const neonProvider = createNeonProviderFromSettings(settings);
180
- const databaseUrlEnvVarName = ((_b = (_a = settings.capabilities) == null ? void 0 : _a.database) == null ? void 0 : _b.databaseUrlEnvVarName) ?? "DATABASE_URL";
181
- const databaseManager = new DatabaseManager(neonProvider, environmentManager, databaseUrlEnvVarName);
182
- const branchNaming = new DefaultBranchNamingService({ useClaude: true });
183
- this.loomManager = new LoomManager(
184
- new GitWorktreeManager(mainWorktreePath),
185
- this.issueTracker,
186
- branchNaming,
187
- // Add branch naming service
188
- environmentManager,
189
- // Reuse same instance
190
- new ClaudeContextManager(),
191
- new ProjectCapabilityDetector(),
192
- new CLIIsolationManager(),
193
- this.settingsManager,
194
- // Use same instance with CLI overrides
195
- databaseManager
196
- // Add database manager
197
- );
198
- return this.loomManager;
199
- }
200
- /**
201
- * Main entry point for the start command
202
- */
203
- async execute(input) {
204
- var _a, _b, _c, _d, _e;
205
- const isJsonMode = input.options.json === true;
206
- try {
207
- const initialSettings = await this.settingsManager.loadSettings();
208
- if (!isJsonMode && (process.env.FORCE_FIRST_TIME_SETUP === "true" || await needsFirstRunSetup())) {
209
- await launchFirstRunSetup();
210
- const newSettings = await this.settingsManager.loadSettings();
211
- const newProvider = ((_a = newSettings.issueManagement) == null ? void 0 : _a.provider) ?? "github";
212
- if (newProvider !== this.issueTracker.providerName) {
213
- getLogger().debug(`Reinitializing issue tracker: provider changed to "${newProvider}"`);
214
- this.issueTracker = IssueTrackerFactory.create(newSettings);
215
- }
216
- }
217
- let repo;
218
- if (this.issueTracker.providerName === "github" && await hasMultipleRemotes()) {
219
- repo = await getConfiguredRepoFromSettings(initialSettings);
220
- getLogger().info(`Using GitHub repository: ${repo}`);
221
- }
222
- const loomManager = await this.initializeLoomManager();
223
- let parentLoom = await this.detectParentLoom(loomManager);
224
- const parsed = await this.parseInput(input.identifier, repo);
225
- await this.validateInput(parsed, repo);
226
- if (parentLoom) {
227
- const { isInteractiveEnvironment, promptConfirmation: promptConfirmation2 } = await import("./prompt-ONNPSNKM.js");
228
- const parentDisplay = parentLoom.type === "issue" ? `issue #${parentLoom.identifier}` : parentLoom.type === "pr" ? `PR #${parentLoom.identifier}` : `branch ${parentLoom.identifier}`;
229
- if (input.options.childLoom === true) {
230
- getLogger().info(`Creating as child loom of ${parentDisplay} (--child-loom flag)`);
231
- } else if (input.options.childLoom === false) {
232
- parentLoom = null;
233
- getLogger().info("Creating as independent loom (--no-child-loom flag)");
234
- } else {
235
- if (isJsonMode) {
236
- throw new Error("JSON mode requires explicit --child-loom or --no-child-loom flag when running from inside a loom");
237
- }
238
- let createAsChild = true;
239
- if (isInteractiveEnvironment()) {
240
- createAsChild = await promptConfirmation2(
241
- `You are not in your main worktree. Create as a child loom of ${parentDisplay}?`,
242
- true
243
- // Default yes
244
- );
245
- } else {
246
- getLogger().error(`Non-interactive environment detected, use either --child-loom or --no-child-loom to specify behavior`);
247
- process.exit(1);
248
- }
249
- if (!createAsChild) {
250
- parentLoom = null;
251
- getLogger().info("Creating as independent loom");
252
- }
253
- }
254
- } else if (input.options.childLoom === true) {
255
- getLogger().debug("--child-loom flag provided but not running from inside an existing loom (ignored)");
256
- }
257
- if (parsed.type === "description") {
258
- getLogger().info("Creating GitHub issue from description...");
259
- const title = capitalizeFirstLetter(parsed.originalInput);
260
- const body = input.options.body ? capitalizeFirstLetter(input.options.body) : "";
261
- const result = await this.issueTracker.createIssue(
262
- title,
263
- // Use capitalized description as title
264
- body
265
- // Use capitalized body or empty
266
- );
267
- getLogger().success(`Created issue #${result.number}: ${result.url}`);
268
- parsed.type = "issue";
269
- parsed.number = result.number;
270
- }
271
- if (input.options.oneShot === "bypassPermissions" && input.options.claude !== false && !isJsonMode) {
272
- const { promptConfirmation: promptConfirmation2 } = await import("./prompt-ONNPSNKM.js");
273
- const confirmed = await promptConfirmation2(
274
- "WARNING: bypassPermissions mode will allow Claude to execute all tool calls without confirmation. This can be dangerous. Do you want to proceed?"
275
- );
276
- if (!confirmed) {
277
- getLogger().info("Operation cancelled by user");
278
- process.exit(0);
279
- }
280
- }
281
- const cliOverrides = extractSettingsOverrides();
282
- const settings = await this.settingsManager.loadSettings(void 0, cliOverrides);
283
- const workflowType = parsed.type === "branch" ? "regular" : parsed.type;
284
- const workflowConfig = (_b = settings.workflows) == null ? void 0 : _b[workflowType];
285
- const { extractRawSetArguments, getExecutablePath } = await import("./cli-overrides-XFZWY7CM.js");
286
- const setArguments = extractRawSetArguments();
287
- const executablePath = getExecutablePath();
288
- getLogger().info(`Validated input: ${this.formatParsedInput(parsed)}`);
289
- const identifier = parsed.type === "branch" ? parsed.branchName ?? "" : parsed.number ?? 0;
290
- const enableClaude = input.options.claude ?? (workflowConfig == null ? void 0 : workflowConfig.startAiAgent) ?? true;
291
- const enableCode = input.options.code ?? (workflowConfig == null ? void 0 : workflowConfig.startIde) ?? true;
292
- const enableDevServer = input.options.devServer ?? (workflowConfig == null ? void 0 : workflowConfig.startDevServer) ?? true;
293
- const enableTerminal = input.options.terminal ?? (workflowConfig == null ? void 0 : workflowConfig.startTerminal) ?? false;
294
- getLogger().debug("Final workflow config values:", {
295
- enableClaude,
296
- enableCode,
297
- enableDevServer,
298
- enableTerminal
299
- });
300
- const loom = await loomManager.createIloom({
301
- type: parsed.type,
302
- identifier,
303
- originalInput: parsed.originalInput,
304
- ...parentLoom && { parentLoom },
305
- options: {
306
- enableClaude,
307
- enableCode,
308
- enableDevServer,
309
- enableTerminal,
310
- ...input.options.oneShot && { oneShot: input.options.oneShot },
311
- ...setArguments.length > 0 && { setArguments },
312
- ...executablePath && { executablePath }
313
- }
314
- });
315
- getLogger().success(`Created loom: ${loom.id} at ${loom.path}`);
316
- getLogger().info(` Branch: ${loom.branch}`);
317
- if ((_c = loom.capabilities) == null ? void 0 : _c.includes("web")) {
318
- getLogger().info(` Port: ${loom.port}`);
319
- }
320
- if ((_d = loom.issueData) == null ? void 0 : _d.title) {
321
- getLogger().info(` Title: ${loom.issueData.title}`);
322
- }
323
- if (isJsonMode) {
324
- return {
325
- id: loom.id,
326
- path: loom.path,
327
- branch: loom.branch,
328
- type: parsed.type,
329
- identifier: loom.identifier,
330
- ...loom.port !== void 0 && { port: loom.port },
331
- ...((_e = loom.issueData) == null ? void 0 : _e.title) && { title: loom.issueData.title },
332
- ...loom.capabilities && { capabilities: loom.capabilities }
333
- };
334
- }
335
- } catch (error) {
336
- if (error instanceof Error) {
337
- getLogger().error(`${error.message}`);
338
- } else {
339
- getLogger().error("An unknown error occurred");
340
- }
341
- throw error;
342
- }
343
- }
344
- /**
345
- * Parse input to determine type and extract relevant data
346
- */
347
- async parseInput(identifier, repo) {
348
- const hasLeadingSpace = identifier.startsWith(" ");
349
- const trimmedIdentifier = identifier.trim();
350
- if (!trimmedIdentifier) {
351
- throw new Error("Missing required argument: identifier");
352
- }
353
- const spaceCount = (trimmedIdentifier.match(/ /g) ?? []).length;
354
- if (trimmedIdentifier.length > 15 && spaceCount >= 1) {
355
- return {
356
- type: "description",
357
- originalInput: hasLeadingSpace ? " " + trimmedIdentifier : trimmedIdentifier
358
- };
359
- }
360
- const prPattern = /^pr[/-](\d+)$/i;
361
- const prMatch = trimmedIdentifier.match(prPattern);
362
- if (prMatch == null ? void 0 : prMatch[1]) {
363
- return {
364
- type: "pr",
365
- number: parseInt(prMatch[1], 10),
366
- originalInput: trimmedIdentifier
367
- };
368
- }
369
- const identifierMatch = matchIssueIdentifier(trimmedIdentifier);
370
- if (identifierMatch.type === "linear" && identifierMatch.identifier) {
371
- const detection = await this.issueTracker.detectInputType(
372
- trimmedIdentifier,
373
- repo
374
- );
375
- if (detection.type === "issue" && detection.identifier) {
376
- return {
377
- type: "issue",
378
- number: detection.identifier,
379
- // Keep as string for Linear
380
- originalInput: trimmedIdentifier
381
- };
382
- }
383
- throw new Error(
384
- `Could not find Linear issue ${identifierMatch.identifier}`
385
- );
386
- }
387
- if (identifierMatch.type === "numeric" && identifierMatch.identifier) {
388
- const number = parseInt(identifierMatch.identifier, 10);
389
- if (this.issueTracker.supportsPullRequests) {
390
- const detection = await this.issueTracker.detectInputType(
391
- trimmedIdentifier,
392
- repo
393
- );
394
- if (detection.type === "pr") {
395
- return {
396
- type: "pr",
397
- number: detection.identifier ? parseInt(detection.identifier, 10) : number,
398
- originalInput: trimmedIdentifier
399
- };
400
- } else if (detection.type === "issue") {
401
- return {
402
- type: "issue",
403
- number: detection.identifier ? parseInt(detection.identifier, 10) : number,
404
- originalInput: trimmedIdentifier
405
- };
406
- } else {
407
- throw new Error(`Could not find issue or PR #${number}`);
408
- }
409
- } else {
410
- const githubService = this.getGitHubService();
411
- const detection = await githubService.detectInputType(trimmedIdentifier, repo);
412
- if (detection.type === "pr") {
413
- return {
414
- type: "pr",
415
- number: detection.identifier ? parseInt(detection.identifier, 10) : number,
416
- originalInput: trimmedIdentifier
417
- };
418
- } else {
419
- return {
420
- type: "issue",
421
- number,
422
- originalInput: trimmedIdentifier
423
- };
424
- }
425
- }
426
- }
427
- return {
428
- type: "branch",
429
- branchName: trimmedIdentifier,
430
- originalInput: trimmedIdentifier
431
- };
432
- }
433
- /**
434
- * Validate the parsed input based on its type
435
- */
436
- async validateInput(parsed, repo) {
437
- switch (parsed.type) {
438
- case "pr": {
439
- if (!parsed.number) {
440
- throw new Error("Invalid PR number");
441
- }
442
- if (this.issueTracker.supportsPullRequests && this.issueTracker.fetchPR && this.issueTracker.validatePRState) {
443
- const pr = await this.issueTracker.fetchPR(parsed.number, repo);
444
- await this.issueTracker.validatePRState(pr);
445
- } else {
446
- const githubService = this.getGitHubService();
447
- const pr = await githubService.fetchPR(parsed.number, repo);
448
- await githubService.validatePRState(pr);
449
- }
450
- getLogger().debug(`Validated PR #${parsed.number}`);
451
- break;
452
- }
453
- case "issue": {
454
- if (!parsed.number) {
455
- throw new Error("Invalid issue number");
456
- }
457
- const issue = await this.issueTracker.fetchIssue(parsed.number, repo);
458
- await this.issueTracker.validateIssueState(issue);
459
- getLogger().debug(`Validated issue #${parsed.number}`);
460
- break;
461
- }
462
- case "branch": {
463
- if (!parsed.branchName) {
464
- throw new Error("Invalid branch name");
465
- }
466
- if (!this.isValidBranchName(parsed.branchName)) {
467
- throw new Error(
468
- "Invalid branch name. Use only letters, numbers, hyphens, underscores, and slashes"
469
- );
470
- }
471
- getLogger().debug(`Validated branch name: ${parsed.branchName}`);
472
- break;
473
- }
474
- case "description": {
475
- getLogger().debug("Detected description input", {
476
- length: parsed.originalInput.length
477
- });
478
- break;
479
- }
480
- default: {
481
- const unknownType = parsed;
482
- throw new Error(`Unknown input type: ${unknownType.type}`);
483
- }
484
- }
485
- }
486
- /**
487
- * Validate branch name format
488
- */
489
- isValidBranchName(branch) {
490
- return /^[a-zA-Z0-9/_-]+$/.test(branch);
491
- }
492
- /**
493
- * Format parsed input for display
494
- */
495
- formatParsedInput(parsed) {
496
- switch (parsed.type) {
497
- case "pr":
498
- return `PR #${parsed.number}`;
499
- case "issue":
500
- return `Issue #${parsed.number}`;
501
- case "branch":
502
- return `Branch '${parsed.branchName}'`;
503
- case "description":
504
- return `Description: ${parsed.originalInput.slice(0, 50)}...`;
505
- default:
506
- return "Unknown input";
507
- }
508
- }
509
- /**
510
- * Detect if running from inside an existing loom worktree
511
- * Returns parent loom info if detected, null otherwise
512
- */
513
- async detectParentLoom(loomManager) {
514
- try {
515
- const cwd = process.cwd();
516
- const looms = await loomManager.listLooms();
517
- if (!looms) {
518
- return null;
519
- }
520
- const mainWorktreePath = await findMainWorktreePathWithSettings();
521
- const parentLoom = looms.find((loom) => {
522
- if (loom.path === mainWorktreePath) {
523
- return false;
524
- }
525
- return cwd === loom.path || cwd.startsWith(loom.path + path.sep);
526
- });
527
- if (!parentLoom) {
528
- return null;
529
- }
530
- getLogger().debug(`Detected parent loom: ${parentLoom.type} ${parentLoom.identifier} at ${parentLoom.path}`);
531
- const result = {
532
- type: parentLoom.type,
533
- identifier: parentLoom.identifier,
534
- branchName: parentLoom.branch,
535
- worktreePath: parentLoom.path
536
- };
537
- if (parentLoom.databaseBranch) {
538
- result.databaseBranch = parentLoom.databaseBranch;
539
- }
540
- if (!result.databaseBranch) {
541
- const databaseBranch = await loomManager.getDatabaseBranchForLoom(parentLoom.path);
542
- if (databaseBranch) {
543
- result.databaseBranch = databaseBranch;
544
- getLogger().debug(`Detected parent database branch: ${databaseBranch}`);
545
- }
546
- }
547
- return result;
548
- } catch (error) {
549
- getLogger().debug(`Failed to detect parent loom: ${error instanceof Error ? error.message : "Unknown error"}`);
550
- return null;
551
- }
552
- }
553
- };
554
-
555
143
  // src/commands/add-issue.ts
556
144
  var AddIssueCommand = class {
557
145
  constructor(enhancementService, settingsManager) {
@@ -588,7 +176,10 @@ var AddIssueCommand = class {
588
176
  }
589
177
  throw new Error("Description is required and must be more than 30 characters with at least 3 words");
590
178
  }
591
- const issueBody = body ?? await this.enhancementService.enhanceDescription(description);
179
+ const enhancementInput = body ? `${description}
180
+
181
+ ${body}` : description;
182
+ const issueBody = await this.enhancementService.enhanceDescription(enhancementInput);
592
183
  const result = await this.enhancementService.createEnhancedIssue(
593
184
  description,
594
185
  issueBody,
@@ -718,7 +309,7 @@ var EnhanceCommand = class {
718
309
  };
719
310
 
720
311
  // src/commands/finish.ts
721
- import path2 from "path";
312
+ import path from "path";
722
313
  var FinishCommand = class {
723
314
  constructor(issueTracker, gitWorktreeManager, validationRunner, commitManager, mergeManager, identifierParser, resourceCleanup, buildRunner, settingsManager, loomManager) {
724
315
  const envResult = loadEnvIntoProcess();
@@ -747,21 +338,21 @@ var FinishCommand = class {
747
338
  * Lazy initialization of ResourceCleanup with properly configured DatabaseManager
748
339
  */
749
340
  async ensureResourceCleanup() {
750
- var _a, _b;
341
+ var _a2, _b;
751
342
  if (this.resourceCleanup && this.loomManager) {
752
343
  return;
753
344
  }
754
345
  const settings = await this.settingsManager.loadSettings();
755
- const databaseUrlEnvVarName = ((_b = (_a = settings.capabilities) == null ? void 0 : _a.database) == null ? void 0 : _b.databaseUrlEnvVarName) ?? "DATABASE_URL";
346
+ const databaseUrlEnvVarName = ((_b = (_a2 = settings.capabilities) == null ? void 0 : _a2.database) == null ? void 0 : _b.databaseUrlEnvVarName) ?? "DATABASE_URL";
756
347
  const environmentManager = new EnvironmentManager();
757
348
  const neonProvider = createNeonProviderFromSettings(settings);
758
349
  const databaseManager = new DatabaseManager(neonProvider, environmentManager, databaseUrlEnvVarName);
759
350
  const cliIsolationManager = new CLIIsolationManager();
760
- const { DefaultBranchNamingService: DefaultBranchNamingService2 } = await import("./BranchNamingService-K6XNWQ6C.js");
351
+ const { DefaultBranchNamingService } = await import("./BranchNamingService-25KSZAEM.js");
761
352
  this.loomManager ??= new LoomManager(
762
353
  this.gitWorktreeManager,
763
354
  this.issueTracker,
764
- new DefaultBranchNamingService2({ useClaude: true }),
355
+ new DefaultBranchNamingService({ useClaude: true }),
765
356
  environmentManager,
766
357
  new ClaudeContextManager(),
767
358
  new ProjectCapabilityDetector(),
@@ -815,9 +406,9 @@ var FinishCommand = class {
815
406
  * Main entry point for finish command
816
407
  */
817
408
  async execute(input) {
818
- var _a, _b, _c, _d;
409
+ var _a2, _b, _c, _d, _e;
819
410
  process.env.ILOOM = "1";
820
- const isJsonMode = input.options.json === true;
411
+ const isJsonMode = input.options.json === true || input.options.jsonStream === true;
821
412
  const result = {
822
413
  success: false,
823
414
  type: "issue",
@@ -827,7 +418,7 @@ var FinishCommand = class {
827
418
  };
828
419
  if (isJsonMode) {
829
420
  const settings2 = await this.settingsManager.loadSettings();
830
- if ((((_a = settings2.mergeBehavior) == null ? void 0 : _a.mode) === "github-pr" || ((_b = settings2.mergeBehavior) == null ? void 0 : _b.mode) === "github-draft-pr") && input.options.cleanup === void 0) {
421
+ if ((((_a2 = settings2.mergeBehavior) == null ? void 0 : _a2.mode) === "github-pr" || ((_b = settings2.mergeBehavior) == null ? void 0 : _b.mode) === "github-draft-pr") && input.options.cleanup === void 0) {
831
422
  throw new Error('JSON mode with "github-pr"/"github-draft-pr" workflow requires --cleanup or --no-cleanup flag. Use: il finish --json --cleanup <identifier>');
832
423
  }
833
424
  }
@@ -848,6 +439,14 @@ var FinishCommand = class {
848
439
  if (!worktree) {
849
440
  throw new Error("No worktree found");
850
441
  }
442
+ let preFinishCreatedAt;
443
+ try {
444
+ const metadataManager = new MetadataManager();
445
+ const metadata = await metadataManager.readMetadata(worktree.path);
446
+ preFinishCreatedAt = (metadata == null ? void 0 : metadata.created_at) ?? void 0;
447
+ } catch (error) {
448
+ getLogger().debug(`Failed to read metadata for telemetry: ${error instanceof Error ? error.message : String(error)}`);
449
+ }
851
450
  if (parsed.type === "pr") {
852
451
  if (!parsed.number) {
853
452
  throw new Error("Invalid PR number");
@@ -861,6 +460,15 @@ var FinishCommand = class {
861
460
  await this.executeIssueWorkflow(parsed, input.options, worktree, result);
862
461
  }
863
462
  result.success = true;
463
+ try {
464
+ const durationMinutes = preFinishCreatedAt ? Math.round((Date.now() - new Date(preFinishCreatedAt).getTime()) / 6e4) : 0;
465
+ TelemetryService.getInstance().track("loom.finished", {
466
+ merge_behavior: ((_e = settings.mergeBehavior) == null ? void 0 : _e.mode) ?? "local",
467
+ duration_minutes: isNaN(durationMinutes) ? 0 : durationMinutes
468
+ });
469
+ } catch (error) {
470
+ getLogger().debug(`Failed to track loom.finished telemetry: ${error instanceof Error ? error.message : String(error)}`);
471
+ }
864
472
  if (isJsonMode) {
865
473
  return result;
866
474
  }
@@ -888,6 +496,7 @@ var FinishCommand = class {
888
496
  * (No GitHub API calls - uses IdentifierParser)
889
497
  */
890
498
  async parseExplicitInput(identifier) {
499
+ var _a2;
891
500
  const prPattern = /^(?:pr|PR)[/-](\d+)$/;
892
501
  const prMatch = identifier.match(prPattern);
893
502
  if (prMatch == null ? void 0 : prMatch[1]) {
@@ -913,6 +522,18 @@ var FinishCommand = class {
913
522
  if (parsed.branchName !== void 0) {
914
523
  result.branchName = parsed.branchName;
915
524
  }
525
+ if (result.type === "issue" && result.number !== void 0) {
526
+ const worktree = await this.gitWorktreeManager.findWorktreeForIssue(result.number);
527
+ if (worktree) {
528
+ const { MetadataManager: MetadataManager2 } = await import("./MetadataManager-5QZSTKNN.js");
529
+ const metadataManager = new MetadataManager2();
530
+ const metadata = await metadataManager.readMetadata(worktree.path);
531
+ const canonicalKey = (metadata == null ? void 0 : metadata.issueKey) ?? ((_a2 = metadata == null ? void 0 : metadata.issue_numbers) == null ? void 0 : _a2[0]);
532
+ if (canonicalKey) {
533
+ result.number = canonicalKey;
534
+ }
535
+ }
536
+ }
916
537
  return result;
917
538
  }
918
539
  /**
@@ -920,7 +541,8 @@ var FinishCommand = class {
920
541
  * Ports logic from merge-current-issue.sh lines 30-52
921
542
  */
922
543
  async autoDetectFromCurrentDirectory() {
923
- const currentDir = path2.basename(process.cwd());
544
+ var _a2, _b;
545
+ const currentDir = path.basename(process.cwd());
924
546
  const prPattern = /_pr_(\d+)$/;
925
547
  const prMatch = currentDir.match(prPattern);
926
548
  if (prMatch == null ? void 0 : prMatch[1]) {
@@ -933,14 +555,18 @@ var FinishCommand = class {
933
555
  autoDetected: true
934
556
  };
935
557
  }
558
+ const { MetadataManager: MetadataManager2 } = await import("./MetadataManager-5QZSTKNN.js");
559
+ const metadataManager = new MetadataManager2();
560
+ const metadata = await metadataManager.readMetadata(process.cwd());
936
561
  const issueNumber = extractIssueNumber(currentDir);
937
562
  if (issueNumber !== null) {
563
+ const originalIssueKey = (metadata == null ? void 0 : metadata.issueKey) ?? ((_a2 = metadata == null ? void 0 : metadata.issue_numbers) == null ? void 0 : _a2[0]) ?? issueNumber;
938
564
  getLogger().debug(
939
- `Auto-detected issue #${issueNumber} from directory: ${currentDir}`
565
+ `Auto-detected issue #${originalIssueKey} from directory: ${currentDir}`
940
566
  );
941
567
  return {
942
568
  type: "issue",
943
- number: issueNumber,
569
+ number: originalIssueKey,
944
570
  originalInput: currentDir,
945
571
  autoDetected: true
946
572
  };
@@ -954,12 +580,13 @@ var FinishCommand = class {
954
580
  }
955
581
  const branchIssueNumber = extractIssueNumber(currentBranch);
956
582
  if (branchIssueNumber !== null) {
583
+ const originalIssueKey = (metadata == null ? void 0 : metadata.issueKey) ?? ((_b = metadata == null ? void 0 : metadata.issue_numbers) == null ? void 0 : _b[0]) ?? branchIssueNumber;
957
584
  getLogger().debug(
958
- `Auto-detected issue #${branchIssueNumber} from branch: ${currentBranch}`
585
+ `Auto-detected issue #${originalIssueKey} from branch: ${currentBranch}`
959
586
  );
960
587
  return {
961
588
  type: "issue",
962
- number: branchIssueNumber,
589
+ number: originalIssueKey,
963
590
  originalInput: currentBranch,
964
591
  autoDetected: true
965
592
  };
@@ -1098,85 +725,104 @@ var FinishCommand = class {
1098
725
  * This is the workflow: rebase → validate → commit → merge → cleanup
1099
726
  */
1100
727
  async executeIssueWorkflow(parsed, options, worktree, result) {
1101
- var _a, _b, _c, _d, _e;
1102
- getLogger().info("Rebasing branch on main...");
728
+ var _a2, _b, _c, _d, _e, _f;
1103
729
  const mergeOptions = {
1104
730
  dryRun: options.dryRun ?? false,
1105
- force: options.force ?? false
731
+ force: options.force ?? false,
732
+ jsonStream: options.jsonStream ?? false
1106
733
  };
1107
- await this.mergeManager.rebaseOnMain(worktree.path, mergeOptions);
1108
- getLogger().success("Branch rebased successfully");
1109
- result.operations.push({
1110
- type: "rebase",
1111
- message: "Branch rebased on main",
1112
- success: true
1113
- });
1114
- if (!options.dryRun) {
1115
- getLogger().info("Running pre-merge validations...");
1116
- await this.validationRunner.runValidations(worktree.path, {
1117
- dryRun: options.dryRun ?? false
1118
- });
1119
- getLogger().success("All validations passed");
1120
- result.operations.push({
1121
- type: "validation",
1122
- message: "Pre-merge validations passed",
1123
- success: true
1124
- });
734
+ if (options.skipToPr) {
735
+ getLogger().info("Skipping rebase/validation/commit (--skip-to-pr flag)");
1125
736
  } else {
1126
- getLogger().info("[DRY RUN] Would run pre-merge validations");
737
+ getLogger().info("Rebasing branch on main...");
738
+ await this.mergeManager.rebaseOnMain(worktree.path, mergeOptions);
739
+ getLogger().success("Branch rebased successfully");
1127
740
  result.operations.push({
1128
- type: "validation",
1129
- message: "Would run pre-merge validations (dry-run)",
741
+ type: "rebase",
742
+ message: "Branch rebased on main",
1130
743
  success: true
1131
744
  });
1132
- }
1133
- const gitStatus = await this.commitManager.detectUncommittedChanges(worktree.path);
1134
- if (gitStatus.hasUncommittedChanges) {
1135
- if (options.dryRun) {
1136
- getLogger().info("[DRY RUN] Would auto-commit uncommitted changes (validation passed)");
745
+ if (!options.dryRun) {
746
+ getLogger().info("Installing dependencies...");
747
+ try {
748
+ await installDependencies(worktree.path, true, true);
749
+ } catch (error) {
750
+ const message = error instanceof Error ? error.message : "Unknown error";
751
+ getLogger().warn(`Dependency installation failed: ${message}`);
752
+ getLogger().warn("Please run your package manager install command manually");
753
+ }
754
+ } else {
755
+ getLogger().info("[DRY RUN] Would install dependencies");
756
+ }
757
+ if (!options.dryRun) {
758
+ getLogger().info("Running pre-merge validations...");
759
+ await this.validationRunner.runValidations(worktree.path, {
760
+ dryRun: options.dryRun ?? false,
761
+ jsonStream: options.jsonStream ?? false
762
+ });
763
+ getLogger().success("All validations passed");
1137
764
  result.operations.push({
1138
- type: "commit",
1139
- message: "Would auto-commit uncommitted changes (dry-run)",
765
+ type: "validation",
766
+ message: "Pre-merge validations passed",
1140
767
  success: true
1141
768
  });
1142
769
  } else {
1143
- getLogger().info("Validation passed, auto-committing uncommitted changes...");
1144
- const settings2 = await this.settingsManager.loadSettings(worktree.path);
1145
- const skipVerify = ((_b = (_a = settings2.workflows) == null ? void 0 : _a.issue) == null ? void 0 : _b.noVerify) ?? false;
1146
- const providerType = ((_c = settings2.issueManagement) == null ? void 0 : _c.provider) ?? "github";
1147
- const issuePrefix = IssueManagementProviderFactory.create(providerType).issuePrefix;
1148
- const commitOptions = {
1149
- dryRun: options.dryRun ?? false,
1150
- skipVerify,
1151
- issuePrefix,
1152
- timeout: (_d = settings2.git) == null ? void 0 : _d.commitTimeout
1153
- };
1154
- if (parsed.type === "issue" && parsed.number) {
1155
- commitOptions.issueNumber = parsed.number;
1156
- }
1157
- try {
1158
- await this.commitManager.commitChanges(worktree.path, commitOptions);
1159
- getLogger().success("Changes committed successfully");
770
+ getLogger().info("[DRY RUN] Would run pre-merge validations");
771
+ result.operations.push({
772
+ type: "validation",
773
+ message: "Would run pre-merge validations (dry-run)",
774
+ success: true
775
+ });
776
+ }
777
+ const gitStatus = await this.commitManager.detectUncommittedChanges(worktree.path);
778
+ if (gitStatus.hasUncommittedChanges) {
779
+ if (options.dryRun) {
780
+ getLogger().info("[DRY RUN] Would auto-commit uncommitted changes (validation passed)");
1160
781
  result.operations.push({
1161
782
  type: "commit",
1162
- message: "Changes committed successfully",
783
+ message: "Would auto-commit uncommitted changes (dry-run)",
1163
784
  success: true
1164
785
  });
1165
- } catch (error) {
1166
- if (error instanceof UserAbortedCommitError) {
1167
- getLogger().info("Commit aborted by user");
786
+ } else {
787
+ getLogger().info("Validation passed, auto-committing uncommitted changes...");
788
+ const settings2 = await this.settingsManager.loadSettings(worktree.path);
789
+ const skipVerify = ((_b = (_a2 = settings2.workflows) == null ? void 0 : _a2.issue) == null ? void 0 : _b.noVerify) ?? false;
790
+ const providerType = ((_c = settings2.issueManagement) == null ? void 0 : _c.provider) ?? "github";
791
+ const issuePrefix = IssueManagementProviderFactory.create(providerType, settings2).issuePrefix;
792
+ const commitOptions = {
793
+ dryRun: options.dryRun ?? false,
794
+ skipVerify,
795
+ issuePrefix,
796
+ timeout: (_d = settings2.git) == null ? void 0 : _d.commitTimeout,
797
+ noReview: options.review !== true || options.json === true
798
+ };
799
+ if (parsed.type === "issue" && parsed.number) {
800
+ commitOptions.issueNumber = parsed.number;
801
+ }
802
+ try {
803
+ await this.commitManager.commitChanges(worktree.path, commitOptions);
804
+ getLogger().success("Changes committed successfully");
1168
805
  result.operations.push({
1169
806
  type: "commit",
1170
- message: "Commit aborted by user",
1171
- success: false
807
+ message: "Changes committed successfully",
808
+ success: true
1172
809
  });
810
+ } catch (error) {
811
+ if (error instanceof UserAbortedCommitError) {
812
+ getLogger().info("Commit aborted by user");
813
+ result.operations.push({
814
+ type: "commit",
815
+ message: "Commit aborted by user",
816
+ success: false
817
+ });
818
+ throw error;
819
+ }
1173
820
  throw error;
1174
821
  }
1175
- throw error;
1176
822
  }
823
+ } else {
824
+ getLogger().debug("No uncommitted changes found");
1177
825
  }
1178
- } else {
1179
- getLogger().debug("No uncommitted changes found");
1180
826
  }
1181
827
  const settings = await this.settingsManager.loadSettings(worktree.path);
1182
828
  const mergeBehavior = settings.mergeBehavior ?? { mode: "local" };
@@ -1185,7 +831,7 @@ var FinishCommand = class {
1185
831
  return;
1186
832
  }
1187
833
  if (mergeBehavior.mode === "github-draft-pr") {
1188
- const { MetadataManager: MetadataManager3 } = await import("./MetadataManager-W3C54UYT.js");
834
+ const { MetadataManager: MetadataManager3 } = await import("./MetadataManager-5QZSTKNN.js");
1189
835
  const metadataManager2 = new MetadataManager3();
1190
836
  const metadata = await metadataManager2.readMetadata(worktree.path);
1191
837
  getLogger().debug(`Draft PR mode: worktree=${worktree.path}, draftPrNumber=${(metadata == null ? void 0 : metadata.draftPrNumber) ?? "none"}`);
@@ -1247,6 +893,10 @@ var FinishCommand = class {
1247
893
  if (prUrl) {
1248
894
  result.prUrl = prUrl;
1249
895
  }
896
+ const shouldOpenBrowser = !options.dryRun && !options.noBrowser && !options.json && ((_f = settings.mergeBehavior) == null ? void 0 : _f.openBrowserOnFinish) !== false;
897
+ if (shouldOpenBrowser && prUrl) {
898
+ await prManager.openPRInBrowser(prUrl);
899
+ }
1250
900
  result.operations.push({
1251
901
  type: "pr-ready",
1252
902
  message: `PR #${metadata.draftPrNumber} marked as ready for review`,
@@ -1277,7 +927,7 @@ var FinishCommand = class {
1277
927
  getLogger().debug("Skipping build verification (--skip-build flag provided)");
1278
928
  }
1279
929
  await this.generateSessionSummaryIfConfigured(parsed, worktree, options);
1280
- const { MetadataManager: MetadataManager2 } = await import("./MetadataManager-W3C54UYT.js");
930
+ const { MetadataManager: MetadataManager2 } = await import("./MetadataManager-5QZSTKNN.js");
1281
931
  const metadataManager = new MetadataManager2();
1282
932
  if (!options.dryRun) {
1283
933
  await metadataManager.archiveMetadata(worktree.path);
@@ -1296,7 +946,7 @@ var FinishCommand = class {
1296
946
  * - CLOSED/MERGED: Skip to cleanup
1297
947
  */
1298
948
  async executePRWorkflow(parsed, options, worktree, pr, result) {
1299
- var _a, _b, _c, _d;
949
+ var _a2, _b, _c, _d;
1300
950
  if (pr.state === "closed" || pr.state === "merged") {
1301
951
  getLogger().info(`PR #${parsed.number} is ${pr.state.toUpperCase()} - skipping to cleanup`);
1302
952
  const gitStatus = await this.commitManager.detectUncommittedChanges(worktree.path);
@@ -1306,7 +956,7 @@ var FinishCommand = class {
1306
956
  "Cannot cleanup PR with uncommitted changes. Commit or stash changes, then run again with --force to cleanup anyway."
1307
957
  );
1308
958
  }
1309
- const { MetadataManager: MetadataManager2 } = await import("./MetadataManager-W3C54UYT.js");
959
+ const { MetadataManager: MetadataManager2 } = await import("./MetadataManager-5QZSTKNN.js");
1310
960
  const metadataManager = new MetadataManager2();
1311
961
  if (!options.dryRun) {
1312
962
  await metadataManager.archiveMetadata(worktree.path);
@@ -1332,15 +982,16 @@ var FinishCommand = class {
1332
982
  } else {
1333
983
  getLogger().info("Committing uncommitted changes...");
1334
984
  const settings = await this.settingsManager.loadSettings(worktree.path);
1335
- const skipVerify = ((_b = (_a = settings.workflows) == null ? void 0 : _a.pr) == null ? void 0 : _b.noVerify) ?? false;
985
+ const skipVerify = ((_b = (_a2 = settings.workflows) == null ? void 0 : _a2.pr) == null ? void 0 : _b.noVerify) ?? false;
1336
986
  const providerType = ((_c = settings.issueManagement) == null ? void 0 : _c.provider) ?? "github";
1337
- const issuePrefix = IssueManagementProviderFactory.create(providerType).issuePrefix;
987
+ const issuePrefix = IssueManagementProviderFactory.create(providerType, settings).issuePrefix;
1338
988
  try {
1339
989
  await this.commitManager.commitChanges(worktree.path, {
1340
990
  dryRun: false,
1341
991
  skipVerify,
1342
992
  issuePrefix,
1343
- timeout: (_d = settings.git) == null ? void 0 : _d.commitTimeout
993
+ timeout: (_d = settings.git) == null ? void 0 : _d.commitTimeout,
994
+ noReview: options.review !== true || options.json === true
1344
995
  // Do NOT pass issueNumber for PRs - no "Fixes #" trailer needed
1345
996
  });
1346
997
  getLogger().success("Changes committed");
@@ -1385,6 +1036,7 @@ var FinishCommand = class {
1385
1036
  * Validates → Commits → Pushes → Creates PR → Prompts for cleanup
1386
1037
  */
1387
1038
  async executeGitHubPRWorkflow(parsed, options, worktree, settings, finishResult) {
1039
+ var _a2;
1388
1040
  if (options.dryRun) {
1389
1041
  getLogger().info("[DRY RUN] Would push branch to origin");
1390
1042
  } else {
@@ -1413,7 +1065,7 @@ var FinishCommand = class {
1413
1065
  success: true
1414
1066
  });
1415
1067
  } else {
1416
- const openInBrowser = options.noBrowser !== true;
1068
+ const openInBrowser = !options.noBrowser && !options.json && ((_a2 = settings.mergeBehavior) == null ? void 0 : _a2.openBrowserOnFinish) !== false;
1417
1069
  const prResult = await prManager.createOrOpenPR(
1418
1070
  worktree.branch,
1419
1071
  prTitle,
@@ -1436,10 +1088,23 @@ var FinishCommand = class {
1436
1088
  message: `Pull request created`,
1437
1089
  success: true
1438
1090
  });
1091
+ if (parsed.type === "issue" && parsed.number) {
1092
+ try {
1093
+ if (this.issueTracker.moveIssueToReadyForReview) {
1094
+ await this.issueTracker.moveIssueToReadyForReview(parsed.number);
1095
+ getLogger().info("Issue moved to Ready for Review");
1096
+ }
1097
+ } catch (error) {
1098
+ getLogger().warn(
1099
+ `Failed to move issue to Ready for Review: ${error instanceof Error ? error.message : "Unknown error"}`,
1100
+ error
1101
+ );
1102
+ }
1103
+ }
1439
1104
  }
1440
1105
  finishResult.prUrl = prResult.url;
1441
1106
  await this.generateSessionSummaryIfConfigured(parsed, worktree, options, prResult.number);
1442
- const { MetadataManager: MetadataManager2 } = await import("./MetadataManager-W3C54UYT.js");
1107
+ const { MetadataManager: MetadataManager2 } = await import("./MetadataManager-5QZSTKNN.js");
1443
1108
  const metadataManager = new MetadataManager2();
1444
1109
  if (!options.dryRun) {
1445
1110
  await metadataManager.archiveMetadata(worktree.path);
@@ -1493,7 +1158,8 @@ var FinishCommand = class {
1493
1158
  // Don't delete branch - PR still needs it
1494
1159
  keepDatabase: false,
1495
1160
  // Clean up database
1496
- force: options.force ?? false
1161
+ force: options.force ?? false,
1162
+ worktree: { path: worktree.path, branch: worktree.branch }
1497
1163
  };
1498
1164
  try {
1499
1165
  getLogger().info("Starting worktree cleanup...");
@@ -1576,7 +1242,8 @@ var FinishCommand = class {
1576
1242
  // For CLOSED PRs, we rely on checkMergeSafety to verify no unpushed commits
1577
1243
  // rather than checkRemoteBranch, since the remote branch may still exist
1578
1244
  // but local may have additional commits
1579
- checkRemoteBranch: false
1245
+ checkRemoteBranch: false,
1246
+ worktree: { path: worktree.path, branch: worktree.branch }
1580
1247
  };
1581
1248
  try {
1582
1249
  await this.ensureResourceCleanup();
@@ -1707,7 +1374,8 @@ var FinishCommand = class {
1707
1374
  // Delete branch after successful merge
1708
1375
  keepDatabase: false,
1709
1376
  // Clean up database after merge
1710
- force: options.force ?? false
1377
+ force: options.force ?? false,
1378
+ worktree: { path: worktree.path, branch: worktree.branch }
1711
1379
  };
1712
1380
  try {
1713
1381
  getLogger().info("Starting post-merge cleanup...");
@@ -1780,8 +1448,8 @@ var FinishCommand = class {
1780
1448
  * Check if current working directory is within the target worktree
1781
1449
  */
1782
1450
  isRunningFromWithinWorktree(worktreePath) {
1783
- const normalizedCwd = path2.normalize(process.cwd());
1784
- const normalizedWorktree = path2.normalize(worktreePath);
1451
+ const normalizedCwd = path.normalize(process.cwd());
1452
+ const normalizedWorktree = path.normalize(worktreePath);
1785
1453
  return normalizedCwd.startsWith(normalizedWorktree);
1786
1454
  }
1787
1455
  /**
@@ -1822,9 +1490,17 @@ function getPackageInfo(scriptPath) {
1822
1490
 
1823
1491
  // src/cli.ts
1824
1492
  import { fileURLToPath as fileURLToPath2 } from "url";
1825
- import { realpathSync } from "fs";
1493
+ import { realpathSync as realpathSync2 } from "fs";
1826
1494
 
1827
1495
  // src/utils/loom-formatter.ts
1496
+ import { realpathSync } from "fs";
1497
+ function resolvePathSafe(p) {
1498
+ try {
1499
+ return realpathSync(p);
1500
+ } catch {
1501
+ return p;
1502
+ }
1503
+ }
1828
1504
  function determineLoomType(worktree) {
1829
1505
  const prPathPattern = /_pr_\d+$/;
1830
1506
  if (prPathPattern.test(worktree.path)) {
@@ -1836,12 +1512,12 @@ function determineLoomType(worktree) {
1836
1512
  }
1837
1513
  return "branch";
1838
1514
  }
1839
- function extractPRNumbers(path5) {
1840
- if (!path5) {
1515
+ function extractPRNumbers(path4) {
1516
+ if (!path4) {
1841
1517
  return [];
1842
1518
  }
1843
1519
  const prPathPattern = /_pr_(\d+)$/;
1844
- const match = path5.match(prPathPattern);
1520
+ const match = path4.match(prPathPattern);
1845
1521
  if (match == null ? void 0 : match[1]) {
1846
1522
  return [match[1]];
1847
1523
  }
@@ -1857,7 +1533,37 @@ function extractIssueNumbers(branch) {
1857
1533
  }
1858
1534
  return [issueNumber];
1859
1535
  }
1860
- function formatLoomForJson(worktree, mainWorktreePath, metadata) {
1536
+ function enrichSwarmIssues(childIssues, allMetadata, finishedMetadata, projectPath) {
1537
+ const resolvedProjectPath = projectPath ? resolvePathSafe(projectPath) : null;
1538
+ const scopedActive = resolvedProjectPath ? allMetadata.filter((m) => m.projectPath && resolvePathSafe(m.projectPath) === resolvedProjectPath) : allMetadata;
1539
+ const scopedFinished = resolvedProjectPath && finishedMetadata ? finishedMetadata.filter((m) => m.projectPath && resolvePathSafe(m.projectPath) === resolvedProjectPath) : finishedMetadata;
1540
+ const issueNumberToMetadata = /* @__PURE__ */ new Map();
1541
+ for (const meta of scopedActive) {
1542
+ for (const issueNum of meta.issue_numbers) {
1543
+ issueNumberToMetadata.set(issueNum, meta);
1544
+ }
1545
+ }
1546
+ const finishedIssueNumberToMetadata = /* @__PURE__ */ new Map();
1547
+ if (scopedFinished) {
1548
+ for (const meta of scopedFinished) {
1549
+ for (const issueNum of meta.issue_numbers) {
1550
+ finishedIssueNumberToMetadata.set(issueNum, meta);
1551
+ }
1552
+ }
1553
+ }
1554
+ return childIssues.map((child) => {
1555
+ const lookupNumber = child.number.startsWith("#") ? child.number.slice(1) : child.number;
1556
+ const childMeta = issueNumberToMetadata.get(lookupNumber) ?? finishedIssueNumberToMetadata.get(lookupNumber);
1557
+ return {
1558
+ number: child.number,
1559
+ title: child.title,
1560
+ url: child.url,
1561
+ state: (childMeta == null ? void 0 : childMeta.state) ?? null,
1562
+ worktreePath: (childMeta == null ? void 0 : childMeta.worktreePath) ?? null
1563
+ };
1564
+ });
1565
+ }
1566
+ function formatLoomForJson(worktree, mainWorktreePath, metadata, allMetadata, finishedMetadata) {
1861
1567
  const loomType = (metadata == null ? void 0 : metadata.issueType) ?? determineLoomType(worktree);
1862
1568
  let issueNumbers;
1863
1569
  let prNumbers;
@@ -1874,6 +1580,9 @@ function formatLoomForJson(worktree, mainWorktreePath, metadata) {
1874
1580
  }
1875
1581
  }
1876
1582
  const isMainWorktree = mainWorktreePath ? worktree.path === mainWorktreePath : false;
1583
+ const isEpic = loomType === "epic";
1584
+ const swarmIssues = isEpic && (metadata == null ? void 0 : metadata.childIssues) && metadata.childIssues.length > 0 ? enrichSwarmIssues(metadata.childIssues, allMetadata ?? [], finishedMetadata, metadata == null ? void 0 : metadata.projectPath) : isEpic ? [] : void 0;
1585
+ const dependencyMap = isEpic ? (metadata == null ? void 0 : metadata.dependencyMap) && Object.keys(metadata.dependencyMap).length > 0 ? metadata.dependencyMap : {} : void 0;
1877
1586
  return {
1878
1587
  name: worktree.branch || worktree.path,
1879
1588
  worktreePath: worktree.bare ? null : worktree.path,
@@ -1890,15 +1599,22 @@ function formatLoomForJson(worktree, mainWorktreePath, metadata) {
1890
1599
  issueUrls: (metadata == null ? void 0 : metadata.issueUrls) ?? {},
1891
1600
  prUrls: (metadata == null ? void 0 : metadata.prUrls) ?? {},
1892
1601
  capabilities: (metadata == null ? void 0 : metadata.capabilities) ?? [],
1602
+ state: (metadata == null ? void 0 : metadata.state) ?? null,
1893
1603
  isChildLoom: (metadata == null ? void 0 : metadata.parentLoom) != null,
1894
- parentLoom: (metadata == null ? void 0 : metadata.parentLoom) ?? null
1604
+ parentLoom: (metadata == null ? void 0 : metadata.parentLoom) ?? null,
1605
+ ...swarmIssues !== void 0 && { swarmIssues },
1606
+ ...dependencyMap !== void 0 && { dependencyMap }
1895
1607
  };
1896
1608
  }
1897
- function formatLoomsForJson(worktrees, mainWorktreePath, metadata) {
1898
- return worktrees.map((wt) => formatLoomForJson(wt, mainWorktreePath, metadata == null ? void 0 : metadata.get(wt.path)));
1609
+ function formatLoomsForJson(worktrees, mainWorktreePath, metadata, allMetadata, finishedMetadata) {
1610
+ const resolvedAllMetadata = allMetadata ?? (metadata ? Array.from(metadata.values()).filter((m) => m != null) : []);
1611
+ return worktrees.map((wt) => formatLoomForJson(wt, mainWorktreePath, metadata == null ? void 0 : metadata.get(wt.path), resolvedAllMetadata, finishedMetadata));
1899
1612
  }
1900
- function formatFinishedLoomForJson(metadata) {
1613
+ function formatFinishedLoomForJson(metadata, allMetadata, finishedMetadata) {
1901
1614
  const loomType = metadata.issueType ?? "branch";
1615
+ const isEpic = loomType === "epic";
1616
+ const swarmIssues = isEpic && metadata.childIssues && metadata.childIssues.length > 0 ? enrichSwarmIssues(metadata.childIssues, allMetadata ?? [], finishedMetadata, metadata.projectPath) : isEpic ? [] : void 0;
1617
+ const dependencyMap = isEpic ? metadata.dependencyMap && Object.keys(metadata.dependencyMap).length > 0 ? metadata.dependencyMap : {} : void 0;
1902
1618
  return {
1903
1619
  name: metadata.branchName ?? metadata.worktreePath ?? "unknown",
1904
1620
  worktreePath: null,
@@ -1919,126 +1635,26 @@ function formatFinishedLoomForJson(metadata) {
1919
1635
  capabilities: metadata.capabilities ?? [],
1920
1636
  status: metadata.status ?? "finished",
1921
1637
  finishedAt: metadata.finishedAt ?? null,
1638
+ state: metadata.state ?? null,
1922
1639
  isChildLoom: metadata.parentLoom != null,
1923
- parentLoom: metadata.parentLoom ?? null
1640
+ parentLoom: metadata.parentLoom ?? null,
1641
+ ...swarmIssues !== void 0 && { swarmIssues },
1642
+ ...dependencyMap !== void 0 && { dependencyMap }
1924
1643
  };
1925
1644
  }
1926
1645
 
1927
- // src/utils/list-children.ts
1928
- async function fetchChildIssues(parentIssueNumber, settings, repo) {
1929
- const providerName = IssueTrackerFactory.getProviderName(settings);
1930
- logger.debug("Fetching child issues", { parentIssueNumber, provider: providerName, repo });
1931
- const results = await Promise.allSettled([
1932
- (async () => {
1933
- var _a, _b;
1934
- if (providerName === "github") {
1935
- const issueNum = parseInt(parentIssueNumber, 10);
1936
- if (isNaN(issueNum)) {
1937
- logger.warn(`Invalid GitHub issue number: ${parentIssueNumber}`);
1938
- return [];
1939
- }
1940
- return getSubIssues(issueNum, repo);
1941
- } else if (providerName === "linear") {
1942
- const apiToken = (_b = (_a = settings.issueManagement) == null ? void 0 : _a.linear) == null ? void 0 : _b.apiToken;
1943
- return getLinearChildIssues(parentIssueNumber, apiToken ? { apiToken } : void 0);
1944
- } else {
1945
- logger.warn(`Unsupported issue tracker provider: ${providerName}`);
1946
- return [];
1947
- }
1948
- })()
1949
- ]);
1950
- const result = results[0];
1951
- if (result.status === "fulfilled") {
1952
- return result.value;
1953
- } else {
1954
- logger.warn(`Failed to fetch child issues for ${parentIssueNumber}`, { error: result.reason });
1955
- return [];
1956
- }
1957
- }
1958
- async function findChildLooms(parentBranchName, metadataManager) {
1959
- logger.debug("Finding child looms", { parentBranchName });
1960
- const allMetadata = await metadataManager.listAllMetadata();
1961
- const childLooms = allMetadata.filter((metadata) => {
1962
- if (!metadata.parentLoom) {
1963
- return false;
1964
- }
1965
- return metadata.parentLoom.branchName === parentBranchName;
1966
- });
1967
- logger.debug(`Found ${childLooms.length} child looms for parent: ${parentBranchName}`);
1968
- return childLooms;
1969
- }
1970
- function matchChildrenData(childIssues, childLooms) {
1971
- const issueToLoomMap = /* @__PURE__ */ new Map();
1972
- for (const loom of childLooms) {
1973
- for (const issueNum of loom.issue_numbers) {
1974
- issueToLoomMap.set(issueNum, loom);
1975
- }
1976
- }
1977
- const childIssueIds = new Set(childIssues.map((issue) => issue.id));
1978
- const matchedIssues = childIssues.map((issue) => {
1979
- const matchingLoom = issueToLoomMap.get(issue.id);
1980
- return {
1981
- id: issue.id,
1982
- title: issue.title,
1983
- url: issue.url,
1984
- state: issue.state,
1985
- hasActiveLoom: matchingLoom != null,
1986
- loomBranch: (matchingLoom == null ? void 0 : matchingLoom.branchName) ?? null
1987
- };
1988
- });
1989
- const matchedLooms = childLooms.map((loom) => {
1990
- const hasMatchingIssue = loom.issue_numbers.some((issueNum) => childIssueIds.has(issueNum));
1991
- return {
1992
- branch: loom.branchName ?? "",
1993
- issueNumbers: loom.issue_numbers,
1994
- hasMatchingIssue
1995
- };
1996
- });
1997
- const summary = {
1998
- totalIssues: matchedIssues.length,
1999
- issuesWithLooms: matchedIssues.filter((issue) => issue.hasActiveLoom).length,
2000
- totalLooms: matchedLooms.length,
2001
- orphanLooms: matchedLooms.filter((loom) => !loom.hasMatchingIssue).length
2002
- };
2003
- return {
2004
- issues: matchedIssues,
2005
- looms: matchedLooms,
2006
- summary
2007
- };
2008
- }
2009
- async function assembleChildrenData(parentLoom, metadataManager, settings, repo) {
2010
- if (!parentLoom.issue_numbers || parentLoom.issue_numbers.length === 0) {
2011
- logger.debug("No issue_numbers on loom, skipping children fetch", {
2012
- branch: parentLoom.branchName
2013
- });
2014
- return null;
2015
- }
2016
- if (!parentLoom.branchName) {
2017
- logger.debug("No branchName on loom, skipping children fetch");
2018
- return null;
2019
- }
2020
- const parentIssueNumber = parentLoom.issue_numbers[0];
2021
- if (parentIssueNumber === void 0) {
2022
- return null;
2023
- }
2024
- const [childIssues, childLooms] = await Promise.all([
2025
- fetchChildIssues(parentIssueNumber, settings, repo),
2026
- findChildLooms(parentLoom.branchName, metadataManager)
2027
- ]);
2028
- return matchChildrenData(childIssues, childLooms);
2029
- }
2030
-
2031
1646
  // src/cli.ts
1647
+ import chalk from "chalk";
2032
1648
  import fs3 from "fs-extra";
2033
1649
 
2034
1650
  // src/lib/VersionMigrationManager.ts
2035
1651
  import fs2 from "fs-extra";
2036
- import path4 from "path";
1652
+ import path3 from "path";
2037
1653
  import os2 from "os";
2038
1654
 
2039
1655
  // src/migrations/index.ts
2040
1656
  import fs from "fs-extra";
2041
- import path3 from "path";
1657
+ import path2 from "path";
2042
1658
  import os from "os";
2043
1659
  var migrations = [
2044
1660
  // v0.6.0 is the baseline - no migrations needed
@@ -2046,9 +1662,9 @@ var migrations = [
2046
1662
  version: "0.6.1",
2047
1663
  description: "Add global gitignore for .iloom/settings.local.json",
2048
1664
  migrate: async () => {
2049
- const globalIgnorePath = path3.join(os.homedir(), ".config", "git", "ignore");
1665
+ const globalIgnorePath = path2.join(os.homedir(), ".config", "git", "ignore");
2050
1666
  const pattern = "**/.iloom/settings.local.json";
2051
- await fs.ensureDir(path3.dirname(globalIgnorePath));
1667
+ await fs.ensureDir(path2.dirname(globalIgnorePath));
2052
1668
  let content = "";
2053
1669
  try {
2054
1670
  content = await fs.readFile(globalIgnorePath, "utf-8");
@@ -2066,9 +1682,9 @@ var migrations = [
2066
1682
  version: "0.7.1",
2067
1683
  description: "Add global gitignore for .iloom/package.iloom.local.json",
2068
1684
  migrate: async () => {
2069
- const globalIgnorePath = path3.join(os.homedir(), ".config", "git", "ignore");
1685
+ const globalIgnorePath = path2.join(os.homedir(), ".config", "git", "ignore");
2070
1686
  const pattern = "**/.iloom/package.iloom.local.json";
2071
- await fs.ensureDir(path3.dirname(globalIgnorePath));
1687
+ await fs.ensureDir(path2.dirname(globalIgnorePath));
2072
1688
  let content = "";
2073
1689
  try {
2074
1690
  content = await fs.readFile(globalIgnorePath, "utf-8");
@@ -2081,6 +1697,28 @@ var migrations = [
2081
1697
  const newContent = content + separator + "\n# Added by iloom CLI\n" + pattern + "\n";
2082
1698
  await fs.writeFile(globalIgnorePath, newContent, "utf-8");
2083
1699
  }
1700
+ },
1701
+ {
1702
+ version: "0.9.3",
1703
+ description: "Add global gitignore for swarm mode agent and skill files",
1704
+ migrate: async () => {
1705
+ const globalIgnorePath = path2.join(os.homedir(), ".config", "git", "ignore");
1706
+ const agentPattern = "**/.claude/agents/iloom-*";
1707
+ const skillPattern = "**/.claude/skills/iloom-*";
1708
+ const mcpConfigPathPattern = "**/.claude/iloom-swarm-mcp-config-path";
1709
+ await fs.ensureDir(path2.dirname(globalIgnorePath));
1710
+ let content = "";
1711
+ try {
1712
+ content = await fs.readFile(globalIgnorePath, "utf-8");
1713
+ } catch {
1714
+ }
1715
+ if (content.includes(agentPattern)) {
1716
+ return;
1717
+ }
1718
+ const separator = content.endsWith("\n") || content === "" ? "" : "\n";
1719
+ const newContent = content + separator + "\n# Added by iloom CLI\n" + agentPattern + "\n" + skillPattern + "\n" + mcpConfigPathPattern + "\n";
1720
+ await fs.writeFile(globalIgnorePath, newContent, "utf-8");
1721
+ }
2084
1722
  }
2085
1723
  ];
2086
1724
 
@@ -2092,7 +1730,7 @@ var VersionMigrationManager = class {
2092
1730
  }
2093
1731
  // Return path to migration state file
2094
1732
  getMigrationStatePath() {
2095
- return path4.join(os2.homedir(), ".config", "iloom-ai", "migration-state.json");
1733
+ return path3.join(os2.homedir(), ".config", "iloom-ai", "migration-state.json");
2096
1734
  }
2097
1735
  // Get effective version, respecting ILOOM_VERSION_OVERRIDE env var
2098
1736
  // packageVersion is the version from package.json passed by caller
@@ -2132,7 +1770,7 @@ var VersionMigrationManager = class {
2132
1770
  async saveMigrationState(version, newFailures = []) {
2133
1771
  const statePath = this.getMigrationStatePath();
2134
1772
  try {
2135
- await fs2.ensureDir(path4.dirname(statePath));
1773
+ await fs2.ensureDir(path3.dirname(statePath));
2136
1774
  const existingState = await this.loadFullMigrationState();
2137
1775
  const existingFailures = existingState.failedMigrations ?? [];
2138
1776
  const allFailures = [...existingFailures];
@@ -2213,6 +1851,35 @@ var VersionMigrationManager = class {
2213
1851
  // src/cli.ts
2214
1852
  var __filename = fileURLToPath2(import.meta.url);
2215
1853
  var packageJson = getPackageInfo(__filename);
1854
+ function handleTelemetryLifecycle(currentVersion, jsonMode) {
1855
+ const service = TelemetryService.getInstance();
1856
+ const telemetryManager = service.getManager();
1857
+ if (!telemetryManager.hasBeenDisclosed()) {
1858
+ if (!jsonMode) {
1859
+ logger.info("");
1860
+ logger.info("iloom collects anonymous usage data to improve the product.");
1861
+ logger.info("No personal information, repo names, or code is collected.");
1862
+ logger.info('Run "il telemetry off" to disable CLI telemetry at any time.');
1863
+ logger.info("If you also use the iloom VS Code extension, its telemetry is managed separately in VS Code settings.");
1864
+ logger.info("");
1865
+ }
1866
+ telemetryManager.markDisclosed();
1867
+ service.track("cli.installed", {
1868
+ version: currentVersion,
1869
+ os: process.platform,
1870
+ node_version: process.version
1871
+ });
1872
+ }
1873
+ const lastVersion = telemetryManager.getLastVersion();
1874
+ if (lastVersion && lastVersion !== currentVersion) {
1875
+ service.track("cli.upgraded", {
1876
+ version: currentVersion,
1877
+ previous_version: lastVersion,
1878
+ os: process.platform
1879
+ });
1880
+ }
1881
+ telemetryManager.setLastVersion(currentVersion);
1882
+ }
2216
1883
  function parseIssueIdentifier(value) {
2217
1884
  const parsed = parseInt(value, 10);
2218
1885
  return !isNaN(parsed) && String(parsed) === value ? parsed : value;
@@ -2248,6 +1915,12 @@ program.name("iloom").description(packageJson.description).version(packageJson.v
2248
1915
  } catch (error) {
2249
1916
  logger.warn(`Version migration failed: ${error instanceof Error ? error.message : "Unknown"}`);
2250
1917
  }
1918
+ try {
1919
+ const jsonMode = actionCommand.opts().json === true;
1920
+ handleTelemetryLifecycle(packageJson.version, jsonMode);
1921
+ } catch (error) {
1922
+ logger.debug(`Telemetry: ${error instanceof Error ? error.message : String(error)}`);
1923
+ }
2251
1924
  await validateSettingsForCommand(actionCommand);
2252
1925
  await validateGhCliForCommand(actionCommand);
2253
1926
  await validateIdeForStartCommand(actionCommand);
@@ -2262,9 +1935,9 @@ program.name("iloom").description(packageJson.description).version(packageJson.v
2262
1935
  }
2263
1936
  });
2264
1937
  async function validateSettingsForCommand(command) {
2265
- var _a, _b;
1938
+ var _a2, _b;
2266
1939
  const commandName = command.name();
2267
- const bypassCommands = ["help", "init", "update", "contribute"];
1940
+ const bypassCommands = ["help", "init", "update", "contribute", "telemetry"];
2268
1941
  if (bypassCommands.includes(commandName)) {
2269
1942
  return;
2270
1943
  }
@@ -2273,7 +1946,7 @@ async function validateSettingsForCommand(command) {
2273
1946
  const settingsManager = new SettingsManager();
2274
1947
  const settings = await settingsManager.loadSettings();
2275
1948
  const multipleRemotes = await hasMultipleRemotes();
2276
- if (multipleRemotes && !((_b = (_a = settings.issueManagement) == null ? void 0 : _a.github) == null ? void 0 : _b.remote)) {
1949
+ if (multipleRemotes && !((_b = (_a2 = settings.issueManagement) == null ? void 0 : _a2.github) == null ? void 0 : _b.remote)) {
2277
1950
  await autoLaunchInitForMultipleRemotes();
2278
1951
  return;
2279
1952
  }
@@ -2288,7 +1961,7 @@ async function validateSettingsForCommand(command) {
2288
1961
  }
2289
1962
  }
2290
1963
  async function validateGhCliForCommand(command) {
2291
- var _a, _b;
1964
+ var _a2, _b;
2292
1965
  const commandName = command.name();
2293
1966
  const alwaysRequireGh = ["feedback", "contribute"];
2294
1967
  const conditionallyRequireGh = ["start", "finish", "enhance", "add-issue", "ignite", "spin"];
@@ -2303,7 +1976,7 @@ async function validateGhCliForCommand(command) {
2303
1976
  const settingsManager = new SettingsManager();
2304
1977
  const settings = await settingsManager.loadSettings();
2305
1978
  const provider = IssueTrackerFactory.getProviderName(settings);
2306
- const mergeBehaviorMode = (_a = settings.mergeBehavior) == null ? void 0 : _a.mode;
1979
+ const mergeBehaviorMode = (_a2 = settings.mergeBehavior) == null ? void 0 : _a2.mode;
2307
1980
  needsGhCli = provider === "github" || mergeBehaviorMode === "github-pr" || mergeBehaviorMode === "github-draft-pr";
2308
1981
  } catch {
2309
1982
  needsGhCli = true;
@@ -2341,7 +2014,7 @@ async function validateGhCliForCommand(command) {
2341
2014
  }
2342
2015
  }
2343
2016
  async function validateIdeForStartCommand(command) {
2344
- var _a, _b;
2017
+ var _a2, _b;
2345
2018
  const commandName = command.name();
2346
2019
  if (commandName !== "start") {
2347
2020
  return;
@@ -2357,7 +2030,7 @@ async function validateIdeForStartCommand(command) {
2357
2030
  } catch {
2358
2031
  return;
2359
2032
  }
2360
- const workflowConfig = (_a = settings.workflows) == null ? void 0 : _a.issue;
2033
+ const workflowConfig = (_a2 = settings.workflows) == null ? void 0 : _a2.issue;
2361
2034
  if ((workflowConfig == null ? void 0 : workflowConfig.startIde) === false && codeOption !== true) {
2362
2035
  return;
2363
2036
  }
@@ -2376,7 +2049,7 @@ async function validateIdeForStartCommand(command) {
2376
2049
  }
2377
2050
  }
2378
2051
  async function autoLaunchInitForMultipleRemotes() {
2379
- var _a, _b;
2052
+ var _a2, _b;
2380
2053
  logger.info("Multiple git remotes detected, but no GitHub remote is configured.");
2381
2054
  logger.info("");
2382
2055
  logger.info("iloom will now launch an interactive configuration session with Claude");
@@ -2386,19 +2059,19 @@ async function autoLaunchInitForMultipleRemotes() {
2386
2059
  await waitForKeypress2("Press any key to start configuration...");
2387
2060
  logger.info("");
2388
2061
  try {
2389
- const { InitCommand } = await import("./init-676DHF6R.js");
2062
+ const { InitCommand } = await import("./init-32YOKXRL.js");
2390
2063
  const initCommand = new InitCommand();
2391
2064
  const customInitialMessage = "Help me configure which git remote iloom should use for GitHub operations. I have multiple remotes and need to select the correct one.";
2392
2065
  await initCommand.execute(customInitialMessage);
2393
2066
  logger.info("");
2394
2067
  logger.info("Configuration complete! Continuing with your original command...");
2395
2068
  logger.info("");
2396
- const { SettingsManager: SettingsManager2 } = await import("./SettingsManager-AW3JTJHD.js");
2069
+ const { SettingsManager: SettingsManager2 } = await import("./SettingsManager-FNKCOZMQ.js");
2397
2070
  const settingsManager = new SettingsManager2();
2398
2071
  const settings = await settingsManager.loadSettings();
2399
2072
  const { hasMultipleRemotes: hasMultipleRemotes2 } = await import("./remote-IJAMOEAP.js");
2400
2073
  const multipleRemotes = await hasMultipleRemotes2();
2401
- if (multipleRemotes && !((_b = (_a = settings.issueManagement) == null ? void 0 : _a.github) == null ? void 0 : _b.remote)) {
2074
+ if (multipleRemotes && !((_b = (_a2 = settings.issueManagement) == null ? void 0 : _a2.github) == null ? void 0 : _b.remote)) {
2402
2075
  logger.error("Configuration incomplete: GitHub remote is still not configured.");
2403
2076
  logger.info('Please run "iloom init" again and configure the GitHub remote setting.');
2404
2077
  process.exit(1);
@@ -2412,7 +2085,7 @@ async function autoLaunchInitForMultipleRemotes() {
2412
2085
  }
2413
2086
  var shellCompletion = new ShellCompletion();
2414
2087
  shellCompletion.init();
2415
- program.command("start").alias("new").alias("create").alias("up").description("Create isolated workspace for an issue/PR").argument("[identifier]", "Issue number, PR number, or branch name (optional - will prompt if not provided)").option("--claude", "Enable Claude integration (default: true)").option("--no-claude", "Disable Claude integration").option("--code", "Enable VSCode (default: true)").option("--no-code", "Disable VSCode").option("--dev-server", "Enable dev server in terminal (default: true)").option("--no-dev-server", "Disable dev server").option("--terminal", "Enable terminal without dev server (default: false)").option("--no-terminal", "Disable terminal").option("--child-loom", "Force create as child loom (skip prompt)").option("--no-child-loom", "Force create as independent loom (skip prompt)").option("--body <text>", "Body text for issue (skips AI enhancement)").option("--json", "Output result as JSON").addOption(
2088
+ program.command("start").alias("new").alias("create").alias("up").description("Create isolated workspace for an issue/PR").argument("[identifier]", "Issue number, PR number, or branch name (optional - will prompt if not provided)").option("--claude", "Enable Claude integration (default: true)").option("--no-claude", "Disable Claude integration").option("--code", "Enable VSCode (default: true)").option("--no-code", "Disable VSCode").option("--dev-server", "Enable dev server in terminal (default: true)").option("--no-dev-server", "Disable dev server").option("--terminal", "Enable terminal without dev server (default: false)").option("--no-terminal", "Disable terminal").option("--child-loom", "Force create as child loom (skip prompt)").option("--no-child-loom", "Force create as independent loom (skip prompt)").option("--epic", "Create as epic loom with child issues (skip prompt; ignored if no children)").option("--no-epic", "Skip epic loom creation even if issue has children (ignored if no children)").option("--body <text>", "Body text for issue (skips AI enhancement)").option("--json", "Output result as JSON").addOption(
2416
2089
  new Option("--one-shot <mode>", "One-shot automation mode").choices(["default", "noReview", "bypassPermissions"]).default("default")
2417
2090
  ).option("--yolo", "Enable autonomous mode (shorthand for --one-shot=bypassPermissions)").action(async (identifier, options) => {
2418
2091
  if (options.yolo) {
@@ -2490,7 +2163,7 @@ program.command("add-issue").alias("a").description("Create and enhance GitHub i
2490
2163
  });
2491
2164
  program.command("feedback").alias("f").description("Submit feedback/bug report to iloom-cli repository").argument("<description>", "Feedback title (>30 chars, >2 spaces; or any non-empty text when --body provided)").option("--body <text>", "Body text for feedback (added after diagnostics)").action(async (description, options) => {
2492
2165
  try {
2493
- const { FeedbackCommand } = await import("./feedback-E7VET7CL.js");
2166
+ const { FeedbackCommand } = await import("./feedback-G2GJFN2F.js");
2494
2167
  const command = new FeedbackCommand();
2495
2168
  const feedbackOptions = {};
2496
2169
  if (options.body !== void 0) {
@@ -2541,7 +2214,15 @@ program.command("enhance").description("Apply enhancement agent to existing GitH
2541
2214
  await executeAction();
2542
2215
  }
2543
2216
  });
2544
- program.command("finish").alias("dn").description("Merge work and cleanup workspace").argument("[identifier]", "Issue number, PR number, or branch name (auto-detected if omitted)").option("-f, --force", "Skip confirmation prompts").option("-n, --dry-run", "Preview actions without executing").option("--pr <number>", "Treat input as PR number", parseFloat).option("--skip-build", "Skip post-merge build verification").option("--no-browser", "Skip opening PR in browser (github-pr mode only)").option("--cleanup", "Clean up worktree after finishing (default in local mode)").option("--no-cleanup", "Keep worktree after finishing").option("--json", "Output result as JSON").action(async (identifier, options) => {
2217
+ program.command("finish").alias("dn").description("Merge work and cleanup workspace").argument("[identifier]", "Issue number, PR number, or branch name (auto-detected if omitted)").option("-f, --force", "Skip confirmation prompts").option("-n, --dry-run", "Preview actions without executing").option("--pr <number>", "Treat input as PR number", parseFloat).option("--skip-build", "Skip post-merge build verification").option("--no-browser", "Skip opening PR in browser (github-pr and github-draft-pr modes)").option("--cleanup", "Clean up worktree after finishing (default in local mode)").option("--no-cleanup", "Keep worktree after finishing").option("--review", "Review commit message before committing (default: auto-commit without review)").option("--json", "Output result as JSON").option("--json-stream", "Stream JSONL output; runs Claude headless for conflict resolution").action(async (identifier, options) => {
2218
+ if (options.browser === false) {
2219
+ options.noBrowser = true;
2220
+ }
2221
+ if (options.json && options.jsonStream) {
2222
+ logger.error("--json and --json-stream are mutually exclusive");
2223
+ process.exit(1);
2224
+ }
2225
+ const isAnyJsonMode = options.json ?? options.jsonStream;
2545
2226
  const executeAction = async () => {
2546
2227
  try {
2547
2228
  const settingsManager = new SettingsManager();
@@ -2549,13 +2230,14 @@ program.command("finish").alias("dn").description("Merge work and cleanup worksp
2549
2230
  const issueTracker = IssueTrackerFactory.create(settings);
2550
2231
  const command = new FinishCommand(issueTracker);
2551
2232
  const result = await command.execute({ identifier, options });
2552
- if (options.json && result) {
2553
- console.log(JSON.stringify(result, null, 2));
2233
+ if (isAnyJsonMode && result) {
2234
+ console.log(options.jsonStream ? JSON.stringify(result) : JSON.stringify(result, null, 2));
2554
2235
  }
2555
2236
  process.exit(0);
2556
2237
  } catch (error) {
2557
- if (options.json) {
2558
- console.log(JSON.stringify({ success: false, error: error instanceof Error ? error.message : "Unknown error" }, null, 2));
2238
+ if (isAnyJsonMode) {
2239
+ const errorJson = { success: false, error: error instanceof Error ? error.message : "Unknown error" };
2240
+ console.log(options.jsonStream ? JSON.stringify(errorJson) : JSON.stringify(errorJson, null, 2));
2559
2241
  } else {
2560
2242
  logger.error(`Failed to finish workspace: ${error instanceof Error ? error.message : "Unknown error"}`);
2561
2243
  }
@@ -2565,69 +2247,97 @@ program.command("finish").alias("dn").description("Merge work and cleanup worksp
2565
2247
  process.exit(1);
2566
2248
  }
2567
2249
  };
2568
- if (options.json) {
2250
+ if (isAnyJsonMode) {
2569
2251
  const jsonLogger = createStderrLogger();
2570
2252
  await withLogger(jsonLogger, executeAction);
2571
2253
  } else {
2572
2254
  await executeAction();
2573
2255
  }
2574
2256
  });
2575
- program.command("commit").alias("c").description("Commit all uncommitted files with issue reference").option("-m, --message <text>", "Custom commit message (skip Claude generation)").option("--fixes", 'Use "Fixes #N" trailer instead of "Refs #N" (closes issue)').option("--no-review", "Skip commit message review prompt").option("--json", "Output result as JSON (implies --no-review)").option("--wip-commit", "Quick WIP commit: skip validations and pre-commit hooks").action(async (options) => {
2257
+ program.command("commit").alias("c").description("Commit all uncommitted files with issue reference").option("-m, --message <text>", "Custom commit message (skip Claude generation)").option("--fixes", 'Use "Fixes #N" trailer instead of "Refs #N" (closes issue)').option("--no-review", "Skip commit message review prompt").option("--json", "Output result as JSON (implies --no-review)").option("--json-stream", "Stream JSONL output; runs Claude headless for validation fixes").option("--wip-commit", "Quick WIP commit: skip validations and pre-commit hooks").action(async (options) => {
2258
+ if (options.json && options.jsonStream) {
2259
+ logger.error("--json and --json-stream are mutually exclusive");
2260
+ process.exit(1);
2261
+ }
2262
+ const isAnyJsonMode = options.json ?? options.jsonStream;
2576
2263
  const executeAction = async () => {
2577
2264
  try {
2578
- const { CommitCommand } = await import("./commit-IVP3M4HG.js");
2265
+ const { CommitCommand } = await import("./commit-FZR5XDQG.js");
2579
2266
  const command = new CommitCommand();
2580
- const noReview = options.review === false || options.json === true;
2267
+ const noReview = options.review === false || options.json === true || options.jsonStream === true;
2581
2268
  const result = await command.execute({
2582
2269
  message: options.message,
2583
2270
  fixes: options.fixes ?? false,
2584
2271
  noReview,
2585
2272
  json: options.json ?? false,
2273
+ jsonStream: options.jsonStream ?? false,
2586
2274
  wipCommit: options.wipCommit ?? false
2587
2275
  });
2588
- if (options.json && result) {
2589
- console.log(JSON.stringify(result, null, 2));
2276
+ if (isAnyJsonMode && result) {
2277
+ console.log(options.jsonStream ? JSON.stringify(result) : JSON.stringify(result, null, 2));
2590
2278
  }
2591
2279
  process.exit(0);
2592
2280
  } catch (error) {
2593
2281
  if (error instanceof UserAbortedCommitError) {
2594
2282
  process.exit(130);
2595
2283
  }
2596
- if (options.json) {
2597
- console.log(JSON.stringify({ success: false, error: error instanceof Error ? error.message : "Unknown error" }, null, 2));
2284
+ if (isAnyJsonMode) {
2285
+ const errorJson = { success: false, error: error instanceof Error ? error.message : "Unknown error" };
2286
+ console.log(options.jsonStream ? JSON.stringify(errorJson) : JSON.stringify(errorJson, null, 2));
2598
2287
  } else {
2599
2288
  logger.error(`Commit failed: ${error instanceof Error ? error.message : "Unknown error"}`);
2600
2289
  }
2601
2290
  process.exit(1);
2602
2291
  }
2603
2292
  };
2604
- if (options.json) {
2293
+ if (isAnyJsonMode) {
2605
2294
  const jsonLogger = createStderrLogger();
2606
2295
  await withLogger(jsonLogger, executeAction);
2607
2296
  } else {
2608
2297
  await executeAction();
2609
2298
  }
2610
2299
  });
2611
- program.command("rebase").description("Rebase current branch on main with Claude-assisted conflict resolution").option("-f, --force", "Skip confirmation prompts").option("-n, --dry-run", "Preview actions without executing").action(async (options) => {
2612
- try {
2613
- const { RebaseCommand } = await import("./rebase-YND35CIE.js");
2614
- const command = new RebaseCommand();
2615
- await command.execute(options);
2616
- } catch (error) {
2617
- logger.error(`Failed to rebase: ${error instanceof Error ? error.message : "Unknown error"}`);
2618
- process.exit(1);
2300
+ program.command("rebase").description("Rebase current branch on main with Claude-assisted conflict resolution").option("-f, --force", "Skip confirmation prompts").option("-n, --dry-run", "Preview actions without executing").option("--json-stream", "Stream JSONL output; runs Claude headless for conflict resolution").action(async (options) => {
2301
+ const executeAction = async () => {
2302
+ try {
2303
+ const { RebaseCommand } = await import("./rebase-6NVLX5V7.js");
2304
+ const command = new RebaseCommand();
2305
+ const result = await command.execute(options);
2306
+ if (options.jsonStream && result) {
2307
+ console.log(JSON.stringify(result));
2308
+ }
2309
+ process.exit(0);
2310
+ } catch (error) {
2311
+ if (options.jsonStream) {
2312
+ console.log(JSON.stringify({
2313
+ success: false,
2314
+ conflictsDetected: false,
2315
+ claudeLaunched: false,
2316
+ error: error instanceof Error ? error.message : "Unknown error"
2317
+ }));
2318
+ } else {
2319
+ logger.error(`Failed to rebase: ${error instanceof Error ? error.message : "Unknown error"}`);
2320
+ }
2321
+ process.exit(1);
2322
+ }
2323
+ };
2324
+ if (options.jsonStream) {
2325
+ const jsonLogger = createStderrLogger();
2326
+ await withLogger(jsonLogger, executeAction);
2327
+ } else {
2328
+ await executeAction();
2619
2329
  }
2620
2330
  });
2621
2331
  program.command("spin").alias("ignite").description("Launch Claude with auto-detected workspace context").addOption(
2622
2332
  new Option("--one-shot <mode>", "One-shot automation mode").choices(["default", "noReview", "bypassPermissions"])
2623
2333
  ).option("--yolo", "Enable autonomous mode (shorthand for --one-shot=bypassPermissions)").option("-p, --print", "Enable print/headless mode for CI/CD (uses bypassPermissions)").addOption(
2624
2334
  new Option("--output-format <format>", "Output format for Claude CLI (requires --print)").choices(["json", "stream-json", "text"])
2625
- ).option("--verbose", "Enable verbose output (requires --print)").option("--json", "Output final result as JSON object (requires --print)").option("--json-stream", "Stream JSONL output to stdout in real-time (requires --print)").action(async (options) => {
2335
+ ).option("--verbose", "Enable verbose output (requires --print)").option("--json", "Output final result as JSON object (requires --print)").option("--json-stream", "Stream JSONL output to stdout in real-time (requires --print)").option("--set <key=value>", "Override settings (repeatable, e.g., --set workflows.issue.permissionMode=bypassPermissions)").option("--skip-cleanup", "Skip automatic cleanup of child worktrees after they complete in swarm mode").action(async (options) => {
2626
2336
  if (options.yolo) {
2627
2337
  options.oneShot = "bypassPermissions";
2628
2338
  }
2629
2339
  try {
2630
- const { IgniteCommand } = await import("./ignite-IW35CDBD.js");
2340
+ const { IgniteCommand } = await import("./ignite-H2O5Y5A2.js");
2631
2341
  const command = new IgniteCommand();
2632
2342
  if (options.json && options.jsonStream) {
2633
2343
  logger.error("--json and --json-stream are mutually exclusive");
@@ -2646,7 +2356,7 @@ program.command("spin").alias("ignite").description("Launch Claude with auto-det
2646
2356
  ...options.json && { json: true },
2647
2357
  ...options.jsonStream && { jsonStream: true }
2648
2358
  } : void 0;
2649
- await command.execute(options.oneShot, printOptions);
2359
+ await command.execute(options.oneShot, printOptions, options.skipCleanup);
2650
2360
  } catch (error) {
2651
2361
  logger.error(`Failed to spin up loom: ${error instanceof Error ? error.message : "Unknown error"}`);
2652
2362
  process.exit(1);
@@ -2655,7 +2365,7 @@ program.command("spin").alias("ignite").description("Launch Claude with auto-det
2655
2365
  program.command("open").description("Open workspace in browser or run CLI tool").argument("[identifier]", "Issue number, PR number, or branch name (auto-detected if omitted)").allowUnknownOption().action(async (identifier, _options, command) => {
2656
2366
  try {
2657
2367
  const args = (command == null ? void 0 : command.args) ? command.args.slice(identifier ? 1 : 0) : [];
2658
- const { OpenCommand } = await import("./open-544H7JF5.js");
2368
+ const { OpenCommand } = await import("./open-FXWW3VI4.js");
2659
2369
  const cmd = new OpenCommand();
2660
2370
  const input = identifier ? { identifier, args } : { args };
2661
2371
  await cmd.execute(input);
@@ -2667,7 +2377,7 @@ program.command("open").description("Open workspace in browser or run CLI tool")
2667
2377
  program.command("run").description("Run CLI tool or open workspace in browser").argument("[identifier]", "Issue number, PR number, or branch name (auto-detected if omitted)").allowUnknownOption().action(async (identifier, _options, command) => {
2668
2378
  try {
2669
2379
  const args = (command == null ? void 0 : command.args) ? command.args.slice(identifier ? 1 : 0) : [];
2670
- const { RunCommand } = await import("./run-QUXJKDQQ.js");
2380
+ const { RunCommand } = await import("./run-BBXLRIZB.js");
2671
2381
  const cmd = new RunCommand();
2672
2382
  const input = identifier ? { identifier, args } : { args };
2673
2383
  await cmd.execute(input);
@@ -2678,7 +2388,7 @@ program.command("run").description("Run CLI tool or open workspace in browser").
2678
2388
  });
2679
2389
  program.command("vscode").description("Install iloom VS Code extension and open workspace in VS Code").argument("[identifier]", "Issue number, PR number, or branch name (auto-detected if omitted)").option("--no-wait", "Skip keypress prompt and open immediately").action(async (identifier, options) => {
2680
2390
  try {
2681
- const { VSCodeCommand } = await import("./vscode-AR5NNXXI.js");
2391
+ const { VSCodeCommand } = await import("./vscode-6XUGHJKL.js");
2682
2392
  const cmd = new VSCodeCommand();
2683
2393
  await cmd.execute({ identifier, wait: options == null ? void 0 : options.wait });
2684
2394
  } catch (error) {
@@ -2687,7 +2397,7 @@ program.command("vscode").description("Install iloom VS Code extension and open
2687
2397
  });
2688
2398
  program.command("dev-server").alias("dev").description("Start dev server for workspace (foreground)").argument("[identifier]", "Issue number, PR number, or branch name (auto-detected if omitted)").option("--json", "Output as JSON").action(async (identifier, options) => {
2689
2399
  try {
2690
- const { DevServerCommand } = await import("./dev-server-7F622OEO.js");
2400
+ const { DevServerCommand } = await import("./dev-server-7SMIB7OF.js");
2691
2401
  const cmd = new DevServerCommand();
2692
2402
  await cmd.execute({ identifier, json: options == null ? void 0 : options.json });
2693
2403
  } catch (error) {
@@ -2697,7 +2407,7 @@ program.command("dev-server").alias("dev").description("Start dev server for wor
2697
2407
  });
2698
2408
  program.command("shell").alias("terminal").description("Open interactive shell with workspace environment").argument("[identifier]", "Issue number, PR number, or branch name (auto-detected if omitted)").action(async (identifier) => {
2699
2409
  try {
2700
- const { ShellCommand } = await import("./shell-QGECBLST.js");
2410
+ const { ShellCommand } = await import("./shell-RF7LTND5.js");
2701
2411
  const cmd = new ShellCommand();
2702
2412
  await cmd.execute({ identifier });
2703
2413
  } catch (error) {
@@ -2707,7 +2417,7 @@ program.command("shell").alias("terminal").description("Open interactive shell w
2707
2417
  });
2708
2418
  program.command("build").description("Run the build script").argument("[identifier]", "Issue number, PR number, or branch name (auto-detected if omitted)").action(async (identifier) => {
2709
2419
  try {
2710
- const { BuildCommand } = await import("./build-THZI572G.js");
2420
+ const { BuildCommand } = await import("./build-VHGEMXBA.js");
2711
2421
  const cmd = new BuildCommand();
2712
2422
  await cmd.execute(identifier ? { identifier } : {});
2713
2423
  } catch (error) {
@@ -2717,7 +2427,7 @@ program.command("build").description("Run the build script").argument("[identifi
2717
2427
  });
2718
2428
  program.command("lint").description("Run the lint script").argument("[identifier]", "Issue number, PR number, or branch name (auto-detected if omitted)").action(async (identifier) => {
2719
2429
  try {
2720
- const { LintCommand } = await import("./lint-CJM7BAIM.js");
2430
+ const { LintCommand } = await import("./lint-AAN2NZWG.js");
2721
2431
  const cmd = new LintCommand();
2722
2432
  await cmd.execute(identifier ? { identifier } : {});
2723
2433
  } catch (error) {
@@ -2727,7 +2437,7 @@ program.command("lint").description("Run the lint script").argument("[identifier
2727
2437
  });
2728
2438
  program.command("test").description("Run the test script").argument("[identifier]", "Issue number, PR number, or branch name (auto-detected if omitted)").action(async (identifier) => {
2729
2439
  try {
2730
- const { TestCommand } = await import("./test-EA5NQFDC.js");
2440
+ const { TestCommand } = await import("./test-SGO6I5Z7.js");
2731
2441
  const cmd = new TestCommand();
2732
2442
  await cmd.execute(identifier ? { identifier } : {});
2733
2443
  } catch (error) {
@@ -2737,7 +2447,7 @@ program.command("test").description("Run the test script").argument("[identifier
2737
2447
  });
2738
2448
  program.command("compile").alias("typecheck").description("Run the compile or typecheck script (prefers compile if both exist)").argument("[identifier]", "Issue number, PR number, or branch name (auto-detected if omitted)").action(async (identifier) => {
2739
2449
  try {
2740
- const { CompileCommand } = await import("./compile-R2J65HBQ.js");
2450
+ const { CompileCommand } = await import("./compile-7ALJHZ4N.js");
2741
2451
  const cmd = new CompileCommand();
2742
2452
  await cmd.execute(identifier ? { identifier } : {});
2743
2453
  } catch (error) {
@@ -2745,10 +2455,10 @@ program.command("compile").alias("typecheck").description("Run the compile or ty
2745
2455
  process.exit(1);
2746
2456
  }
2747
2457
  });
2748
- program.command("cleanup").alias("remove").alias("clean").description("Remove workspaces").argument("[identifier]", "Branch name or issue number to cleanup (auto-detected)").option("-l, --list", "List all worktrees").option("-a, --all", "Remove all worktrees (interactive confirmation)").option("-i, --issue <number>", "Cleanup by issue number", parseInt).option("-f, --force", "Skip confirmations and force removal").option("--dry-run", "Show what would be done without doing it").option("--json", "Output result as JSON").option("--defer <ms>", "Wait specified milliseconds before cleanup", parseInt).action(async (identifier, options) => {
2458
+ program.command("cleanup").alias("remove").alias("clean").description("Remove workspaces").argument("[identifier]", "Branch name or issue number to cleanup (auto-detected)").option("-l, --list", "List all worktrees").option("-a, --all", "Remove all worktrees (interactive confirmation)").option("-i, --issue <number>", "Cleanup by issue number", parseInt).option("-f, --force", "Skip confirmations and force removal").option("--dry-run", "Show what would be done without doing it").option("--json", "Output result as JSON").option("--archive", "Archive metadata instead of deleting (preserves loom in il list --finished)").option("--defer <ms>", "Wait specified milliseconds before cleanup", parseInt).action(async (identifier, options) => {
2749
2459
  const executeAction = async () => {
2750
2460
  try {
2751
- const { CleanupCommand } = await import("./cleanup-PJRIFFU4.js");
2461
+ const { CleanupCommand } = await import("./cleanup-6PVAC4NI.js");
2752
2462
  const command = new CleanupCommand();
2753
2463
  const input = {
2754
2464
  options: options ?? {}
@@ -2777,6 +2487,22 @@ program.command("cleanup").alias("remove").alias("clean").description("Remove wo
2777
2487
  await executeAction();
2778
2488
  }
2779
2489
  });
2490
+ function colorizeState(state) {
2491
+ switch (state) {
2492
+ case "pending":
2493
+ return chalk.gray(state);
2494
+ case "in_progress":
2495
+ return chalk.yellow(state);
2496
+ case "code_review":
2497
+ return chalk.blue(state);
2498
+ case "done":
2499
+ return chalk.green(state);
2500
+ case "failed":
2501
+ return chalk.red(state);
2502
+ default:
2503
+ return chalk.gray(state);
2504
+ }
2505
+ }
2780
2506
  program.command("list").description("Show active workspaces").option("--json", "Output as JSON").option("--finished", "Show only finished looms (sorted by finish time, latest first)").option("--all", "Show both active and finished looms").option("--global", "Show looms from all projects (default: current project only)").option("--children", "Fetch and display child issues and child looms for each parent loom").action(async (options) => {
2781
2507
  try {
2782
2508
  const manager = new GitWorktreeManager();
@@ -2834,10 +2560,7 @@ program.command("list").description("Show active workspaces").option("--json", "
2834
2560
  }
2835
2561
  }
2836
2562
  }
2837
- let finishedLooms = [];
2838
- if (showFinished) {
2839
- finishedLooms = await metadataManager.listFinishedMetadata();
2840
- }
2563
+ const finishedLooms = await metadataManager.listFinishedMetadata();
2841
2564
  let filteredWorktrees = worktrees;
2842
2565
  let filteredGlobalActiveLooms = globalActiveLooms;
2843
2566
  let filteredFinishedLooms = finishedLooms;
@@ -2856,32 +2579,41 @@ program.command("list").description("Show active workspaces").option("--json", "
2856
2579
  mainWorktreePath = await findMainWorktreePathWithSettings();
2857
2580
  } catch {
2858
2581
  }
2582
+ const allActiveMetadata = options.global ? globalActiveLooms : Array.from(metadata.values()).filter((m) => m != null);
2859
2583
  let activeJson = [];
2860
2584
  if (showActive) {
2861
2585
  if (options.global) {
2862
- activeJson = globalActiveLooms.map((loom) => ({
2863
- name: loom.branchName ?? loom.worktreePath ?? "unknown",
2864
- worktreePath: loom.worktreePath,
2865
- branch: loom.branchName,
2866
- type: loom.issueType ?? "branch",
2867
- issue_numbers: loom.issue_numbers,
2868
- pr_numbers: loom.pr_numbers,
2869
- isMainWorktree: false,
2870
- // Global looms from other projects are never the main worktree
2871
- description: loom.description ?? null,
2872
- created_at: loom.created_at ?? null,
2873
- issueTracker: loom.issueTracker ?? null,
2874
- colorHex: loom.colorHex ?? null,
2875
- projectPath: loom.projectPath ?? null,
2876
- issueUrls: loom.issueUrls ?? {},
2877
- prUrls: loom.prUrls ?? {},
2878
- status: "active",
2879
- finishedAt: null,
2880
- isChildLoom: loom.parentLoom != null,
2881
- parentLoom: loom.parentLoom ?? null
2882
- }));
2586
+ activeJson = globalActiveLooms.map((loom) => {
2587
+ const isEpic = (loom.issueType ?? "branch") === "epic";
2588
+ const swarmIssues = isEpic && loom.childIssues && loom.childIssues.length > 0 ? enrichSwarmIssues(loom.childIssues, globalActiveLooms, finishedLooms, loom.projectPath) : isEpic ? [] : void 0;
2589
+ const depMap = isEpic ? loom.dependencyMap && Object.keys(loom.dependencyMap).length > 0 ? loom.dependencyMap : {} : void 0;
2590
+ return {
2591
+ name: loom.branchName ?? loom.worktreePath ?? "unknown",
2592
+ worktreePath: loom.worktreePath,
2593
+ branch: loom.branchName,
2594
+ type: loom.issueType ?? "branch",
2595
+ issue_numbers: loom.issue_numbers,
2596
+ pr_numbers: loom.pr_numbers,
2597
+ isMainWorktree: false,
2598
+ // Global looms from other projects are never the main worktree
2599
+ description: loom.description ?? null,
2600
+ created_at: loom.created_at ?? null,
2601
+ issueTracker: loom.issueTracker ?? null,
2602
+ colorHex: loom.colorHex ?? null,
2603
+ projectPath: loom.projectPath ?? null,
2604
+ issueUrls: loom.issueUrls ?? {},
2605
+ prUrls: loom.prUrls ?? {},
2606
+ status: "active",
2607
+ finishedAt: null,
2608
+ state: loom.state ?? null,
2609
+ isChildLoom: loom.parentLoom != null,
2610
+ parentLoom: loom.parentLoom ?? null,
2611
+ ...swarmIssues !== void 0 && { swarmIssues },
2612
+ ...depMap !== void 0 && { dependencyMap: depMap }
2613
+ };
2614
+ });
2883
2615
  } else {
2884
- activeJson = formatLoomsForJson(worktrees, mainWorktreePath, metadata).map((loom) => ({
2616
+ activeJson = formatLoomsForJson(worktrees, mainWorktreePath, metadata, allActiveMetadata, finishedLooms).map((loom) => ({
2885
2617
  ...loom,
2886
2618
  status: "active",
2887
2619
  finishedAt: null
@@ -2893,7 +2625,7 @@ program.command("list").description("Show active workspaces").option("--json", "
2893
2625
  (loom) => loom.projectPath == null || loom.projectPath === currentProjectPath
2894
2626
  );
2895
2627
  }
2896
- let finishedJson = finishedLooms.map(formatFinishedLoomForJson);
2628
+ let finishedJson = showFinished ? finishedLooms.map((loom) => formatFinishedLoomForJson(loom, allActiveMetadata, finishedLooms)) : [];
2897
2629
  if (currentProjectPath) {
2898
2630
  finishedJson = finishedJson.filter(
2899
2631
  (loom) => loom.projectPath == null || loom.projectPath === currentProjectPath
@@ -2902,6 +2634,7 @@ program.command("list").description("Show active workspaces").option("--json", "
2902
2634
  if (options.children) {
2903
2635
  const settingsManager = new SettingsManager();
2904
2636
  const settings = await settingsManager.loadSettings();
2637
+ const issueTracker = IssueTrackerFactory.create(settings);
2905
2638
  const activeChildrenResults = await Promise.allSettled(
2906
2639
  activeJson.map(async (loom) => {
2907
2640
  const index = activeJson.indexOf(loom);
@@ -2909,7 +2642,7 @@ program.command("list").description("Show active workspaces").option("--json", "
2909
2642
  if (!loomMetadata) {
2910
2643
  return { index, children: null };
2911
2644
  }
2912
- const children = await assembleChildrenData(loomMetadata, metadataManager, settings);
2645
+ const children = await assembleChildrenData(loomMetadata, metadataManager, issueTracker);
2913
2646
  return { index, children };
2914
2647
  })
2915
2648
  );
@@ -2927,7 +2660,7 @@ program.command("list").description("Show active workspaces").option("--json", "
2927
2660
  if (!loomMetadata) {
2928
2661
  return { index, children: null };
2929
2662
  }
2930
- const children = await assembleChildrenData(loomMetadata, metadataManager, settings);
2663
+ const children = await assembleChildrenData(loomMetadata, metadataManager, issueTracker);
2931
2664
  return { index, children };
2932
2665
  })
2933
2666
  );
@@ -2956,10 +2689,11 @@ program.command("list").description("Show active workspaces").option("--json", "
2956
2689
  }
2957
2690
  return;
2958
2691
  }
2959
- let textSettings = null;
2692
+ let textIssueTracker = null;
2960
2693
  if (options.children) {
2961
2694
  const settingsManager = new SettingsManager();
2962
- textSettings = await settingsManager.loadSettings();
2695
+ const textSettings = await settingsManager.loadSettings();
2696
+ textIssueTracker = IssueTrackerFactory.create(textSettings);
2963
2697
  }
2964
2698
  if (showActive && hasActive) {
2965
2699
  logger.info("Active workspaces:");
@@ -2973,14 +2707,17 @@ program.command("list").description("Show active workspaces").option("--json", "
2973
2707
  if (loom.description) {
2974
2708
  logger.info(` Description: ${loom.description}`);
2975
2709
  }
2710
+ if (loom.state) {
2711
+ logger.info(` State: ${colorizeState(loom.state)}`);
2712
+ }
2976
2713
  if (loom.worktreePath) {
2977
2714
  logger.info(` Path: ${loom.worktreePath}`);
2978
2715
  }
2979
2716
  if (loom.projectPath) {
2980
2717
  logger.info(` Project: ${loom.projectPath}`);
2981
2718
  }
2982
- if (options.children && textSettings) {
2983
- const childrenData = await assembleChildrenData(loom, metadataManager, textSettings);
2719
+ if (options.children && textIssueTracker) {
2720
+ const childrenData = await assembleChildrenData(loom, metadataManager, textIssueTracker);
2984
2721
  if (childrenData && (childrenData.summary.totalIssues > 0 || childrenData.summary.totalLooms > 0)) {
2985
2722
  logger.info(` Child Issues: ${childrenData.summary.totalIssues} (${childrenData.summary.issuesWithLooms} with active looms)`);
2986
2723
  for (const issue of childrenData.issues) {
@@ -3003,10 +2740,13 @@ program.command("list").description("Show active workspaces").option("--json", "
3003
2740
  if (loomMetadata == null ? void 0 : loomMetadata.description) {
3004
2741
  logger.info(` Description: ${loomMetadata.description}`);
3005
2742
  }
2743
+ if (loomMetadata == null ? void 0 : loomMetadata.state) {
2744
+ logger.info(` State: ${colorizeState(loomMetadata.state)}`);
2745
+ }
3006
2746
  logger.info(` Path: ${formatted.path}`);
3007
2747
  logger.info(` Commit: ${formatted.commit}`);
3008
- if (options.children && textSettings && loomMetadata) {
3009
- const childrenData = await assembleChildrenData(loomMetadata, metadataManager, textSettings);
2748
+ if (options.children && textIssueTracker && loomMetadata) {
2749
+ const childrenData = await assembleChildrenData(loomMetadata, metadataManager, textIssueTracker);
3010
2750
  if (childrenData && (childrenData.summary.totalIssues > 0 || childrenData.summary.totalLooms > 0)) {
3011
2751
  logger.info(` Child Issues: ${childrenData.summary.totalIssues} (${childrenData.summary.issuesWithLooms} with active looms)`);
3012
2752
  for (const issue of childrenData.issues) {
@@ -3033,11 +2773,14 @@ program.command("list").description("Show active workspaces").option("--json", "
3033
2773
  if (loom.description) {
3034
2774
  logger.info(` Description: ${loom.description}`);
3035
2775
  }
2776
+ if (loom.state) {
2777
+ logger.info(` State: ${colorizeState(loom.state)}`);
2778
+ }
3036
2779
  if (loom.finishedAt) {
3037
2780
  logger.info(` Finished: ${new Date(loom.finishedAt).toLocaleString()}`);
3038
2781
  }
3039
- if (options.children && textSettings) {
3040
- const childrenData = await assembleChildrenData(loom, metadataManager, textSettings);
2782
+ if (options.children && textIssueTracker) {
2783
+ const childrenData = await assembleChildrenData(loom, metadataManager, textIssueTracker);
3041
2784
  if (childrenData && (childrenData.summary.totalIssues > 0 || childrenData.summary.totalLooms > 0)) {
3042
2785
  logger.info(` Child Issues: ${childrenData.summary.totalIssues} (${childrenData.summary.issuesWithLooms} with active looms)`);
3043
2786
  for (const issue of childrenData.issues) {
@@ -3064,7 +2807,7 @@ program.command("list").description("Show active workspaces").option("--json", "
3064
2807
  });
3065
2808
  program.command("projects").description("List configured iloom projects").option("--json", "Output as JSON (default behavior)").action(async (options) => {
3066
2809
  try {
3067
- const { ProjectsCommand } = await import("./projects-LH362JZQ.js");
2810
+ const { ProjectsCommand } = await import("./projects-2UOXFLNZ.js");
3068
2811
  const command = new ProjectsCommand();
3069
2812
  const result = await command.execute(options);
3070
2813
  console.log(JSON.stringify(result, null, 2));
@@ -3073,15 +2816,17 @@ program.command("projects").description("List configured iloom projects").option
3073
2816
  process.exit(1);
3074
2817
  }
3075
2818
  });
3076
- program.command("issues").description("List project issues from configured issue tracker").argument("[project-path]", "Path to project root (auto-detected if omitted)").option("--json", "Output as JSON (default behavior)").option("--limit <n>", "Max issues to return", "100").action(async (projectPath, options) => {
2819
+ program.command("issues").description("List project issues from configured issue tracker").argument("[project-path]", "Path to project root (auto-detected if omitted)").option("--json", "Output as JSON (default behavior)").option("--limit <n>", "Max issues to return", "100").option("--sprint <name>", 'Jira only: filter by sprint name (e.g., "Sprint 17") or "current" for active sprint').option("--mine", "Show only issues and PRs assigned to me").action(async (projectPath, options) => {
3077
2820
  try {
3078
- const { IssuesCommand } = await import("./issues-PJSOLOBJ.js");
2821
+ const { IssuesCommand } = await import("./issues-4UUAQ5K6.js");
3079
2822
  const command = new IssuesCommand();
3080
2823
  const parsedLimit = parseInt((options == null ? void 0 : options.limit) ?? "100", 10);
3081
2824
  const limit = Number.isNaN(parsedLimit) || parsedLimit <= 0 ? 100 : parsedLimit;
3082
2825
  const result = await command.execute({
3083
2826
  ...projectPath ? { projectPath } : {},
3084
- limit
2827
+ limit,
2828
+ sprint: options == null ? void 0 : options.sprint,
2829
+ mine: options == null ? void 0 : options.mine
3085
2830
  });
3086
2831
  console.log(JSON.stringify(result, null, 2));
3087
2832
  } catch (error) {
@@ -3089,13 +2834,13 @@ program.command("issues").description("List project issues from configured issue
3089
2834
  process.exit(1);
3090
2835
  }
3091
2836
  });
3092
- program.command("init").alias("config").description("Initialize iloom configuration").argument("[prompt]", 'Custom initial message to send to Claude (defaults to "Help me configure iloom settings.")').action(async (prompt) => {
2837
+ program.command("init").alias("config").description("Initialize iloom configuration").argument("[prompt]", 'Custom initial message to send to Claude (defaults to "Help me configure iloom settings.")').addOption(new Option("--accept-defaults").hideHelp()).action(async (prompt, options) => {
3093
2838
  try {
3094
- const { InitCommand } = await import("./init-676DHF6R.js");
2839
+ const { InitCommand } = await import("./init-32YOKXRL.js");
3095
2840
  const command = new InitCommand();
3096
2841
  const trimmedPrompt = prompt == null ? void 0 : prompt.trim();
3097
2842
  const customPrompt = trimmedPrompt && trimmedPrompt.length > 0 ? trimmedPrompt : void 0;
3098
- await command.execute(customPrompt);
2843
+ await command.execute(customPrompt, options == null ? void 0 : options.acceptDefaults);
3099
2844
  } catch (error) {
3100
2845
  logger.error(`Failed to initialize: ${error instanceof Error ? error.message : "Unknown error"}`);
3101
2846
  process.exit(1);
@@ -3103,9 +2848,9 @@ program.command("init").alias("config").description("Initialize iloom configurat
3103
2848
  });
3104
2849
  program.command("plan").description("Launch interactive planning session with Architect persona").argument("[prompt]", "Initial planning prompt or topic").option("--model <model>", "Model to use (default: opus)").option("--yolo", "Enable autonomous mode - Claude proceeds without user interaction").option("--planner <provider>", "AI provider for planning: claude, gemini, codex (default: claude)").option("--reviewer <provider>", "AI provider for review: claude, gemini, codex, none (default: none)").option("-p, --print", "Enable print/headless mode for CI/CD (uses bypassPermissions)").addOption(
3105
2850
  new Option("--output-format <format>", "Output format for Claude CLI (requires --print)").choices(["json", "stream-json", "text"])
3106
- ).option("--verbose", "Enable verbose output (requires --print)").option("--json", "Output final result as JSON object (requires --print)").option("--json-stream", "Stream JSONL output to stdout in real-time (requires --print)").action(async (prompt, options) => {
2851
+ ).option("--verbose", "Enable verbose output (requires --print)").option("--json", "Output final result as JSON object (requires --print)").option("--json-stream", "Stream JSONL output to stdout in real-time (requires --print)").option("--auto-swarm", "Enable auto-swarm: plan, start epic, and spin automatically").action(async (prompt, options) => {
3107
2852
  try {
3108
- const { PlanCommand } = await import("./plan-Q7ELXDLC.js");
2853
+ const { PlanCommand } = await import("./plan-RQ5FPIGF.js");
3109
2854
  const command = new PlanCommand();
3110
2855
  if ((options == null ? void 0 : options.json) && (options == null ? void 0 : options.jsonStream)) {
3111
2856
  logger.error("--json and --json-stream are mutually exclusive");
@@ -3124,7 +2869,7 @@ program.command("plan").description("Launch interactive planning session with Ar
3124
2869
  ...(options == null ? void 0 : options.json) && { json: true },
3125
2870
  ...(options == null ? void 0 : options.jsonStream) && { jsonStream: true }
3126
2871
  } : void 0;
3127
- await command.execute(prompt, options == null ? void 0 : options.model, options == null ? void 0 : options.yolo, options == null ? void 0 : options.planner, options == null ? void 0 : options.reviewer, printOptions);
2872
+ await command.execute(prompt, options == null ? void 0 : options.model, options == null ? void 0 : options.yolo, options == null ? void 0 : options.planner, options == null ? void 0 : options.reviewer, printOptions, options == null ? void 0 : options.autoSwarm);
3128
2873
  } catch (error) {
3129
2874
  logger.error(`Planning session failed: ${error instanceof Error ? error.message : "Unknown error"}`);
3130
2875
  process.exit(1);
@@ -3132,7 +2877,7 @@ program.command("plan").description("Launch interactive planning session with Ar
3132
2877
  });
3133
2878
  program.command("contribute").description("Set up local development environment for contributing to a GitHub project").argument("[repository]", "GitHub repository (owner/repo, github.com/owner/repo, or full URL). Defaults to iloom-ai/iloom-cli").action(async (repository) => {
3134
2879
  try {
3135
- const { ContributeCommand } = await import("./contribute-VDZXHK5Y.js");
2880
+ const { ContributeCommand } = await import("./contribute-5GKLK3BQ.js");
3136
2881
  const command = new ContributeCommand();
3137
2882
  await command.execute(repository);
3138
2883
  } catch (error) {
@@ -3152,11 +2897,11 @@ program.command("update").description("Update iloom-cli to the latest version").
3152
2897
  });
3153
2898
  program.command("test-github").description("Test GitHub integration (Issue #3)").argument("<identifier>", "Issue number or PR number").option("--no-claude", "Skip Claude for branch name generation").action(async (identifier, options) => {
3154
2899
  try {
3155
- const { GitHubService: GitHubService2 } = await import("./GitHubService-TGWJN4V4.js");
3156
- const { DefaultBranchNamingService: DefaultBranchNamingService2 } = await import("./BranchNamingService-K6XNWQ6C.js");
2900
+ const { GitHubService: GitHubService2 } = await import("./GitHubService-MEHKHUQP.js");
2901
+ const { DefaultBranchNamingService } = await import("./BranchNamingService-25KSZAEM.js");
3157
2902
  logger.info("Testing GitHub Integration\n");
3158
2903
  const service = new GitHubService2();
3159
- const branchNaming = new DefaultBranchNamingService2({ useClaude: options.claude !== false });
2904
+ const branchNaming = new DefaultBranchNamingService({ useClaude: options.claude !== false });
3160
2905
  logger.info("Detecting input type...");
3161
2906
  const detection = await service.detectInputType(identifier);
3162
2907
  logger.info(` Type: ${detection.type}`);
@@ -3211,10 +2956,10 @@ program.command("test-github").description("Test GitHub integration (Issue #3)")
3211
2956
  });
3212
2957
  program.command("test-claude").description("Test Claude integration (Issue #10)").option("--detect", "Test Claude CLI detection").option("--version", "Get Claude CLI version").option("--branch <title>", "Test branch name generation with given title").option("--issue <number>", "Issue number for branch generation", "123").option("--launch <prompt>", "Launch Claude with a prompt (headless)").option("--interactive", "Launch Claude interactively (requires --launch)").option("--template <name>", "Test template loading").action(async (options) => {
3213
2958
  try {
3214
- const { detectClaudeCli, getClaudeVersion, generateBranchName, launchClaude } = await import("./claude-TP2QO3BU.js");
3215
- const { PromptTemplateManager } = await import("./PromptTemplateManager-36YLQRHP.js");
3216
- const { ClaudeService } = await import("./ClaudeService-TK7FMC2X.js");
3217
- const { ClaudeContextManager: ClaudeContextManager2 } = await import("./ClaudeContextManager-HR5JQKAI.js");
2959
+ const { detectClaudeCli, getClaudeVersion, generateBranchName, launchClaude } = await import("./claude-7GGEWVEM.js");
2960
+ const { PromptTemplateManager } = await import("./PromptTemplateManager-YOE2SIPG.js");
2961
+ const { ClaudeService } = await import("./ClaudeService-7KM5NA5Z.js");
2962
+ const { ClaudeContextManager: ClaudeContextManager2 } = await import("./ClaudeContextManager-66GR4BGM.js");
3218
2963
  logger.info("Testing Claude Integration\n");
3219
2964
  if (options.detect) {
3220
2965
  logger.info("Detecting Claude CLI...");
@@ -3349,7 +3094,7 @@ program.command("test-claude").description("Test Claude integration (Issue #10)"
3349
3094
  });
3350
3095
  program.command("test-webserver").description("Test if a web server is running on a workspace port").argument("<issue-number>", "Issue number (port will be calculated as 3000 + issue number)", parseInt).option("--kill", "Kill the web server if detected").action(async (issueNumber, options) => {
3351
3096
  try {
3352
- const { TestWebserverCommand } = await import("./test-webserver-OK6Z5FJM.js");
3097
+ const { TestWebserverCommand } = await import("./test-webserver-NZ3JTVLL.js");
3353
3098
  const command = new TestWebserverCommand();
3354
3099
  await command.execute({ issueNumber, options });
3355
3100
  } catch (error) {
@@ -3362,7 +3107,7 @@ program.command("test-webserver").description("Test if a web server is running o
3362
3107
  });
3363
3108
  program.command("test-git").description("Test Git integration - findMainWorktreePath() function (reads .iloom/settings.json)").action(async () => {
3364
3109
  try {
3365
- const { TestGitCommand } = await import("./test-git-M7LSLEFL.js");
3110
+ const { TestGitCommand } = await import("./test-git-XM4TM65W.js");
3366
3111
  const command = new TestGitCommand();
3367
3112
  await command.execute();
3368
3113
  } catch (error) {
@@ -3388,7 +3133,7 @@ program.command("test-tabs").description("Test iTerm2 dual tab functionality - o
3388
3133
  });
3389
3134
  program.command("test-prefix").description("Test worktree prefix configuration - preview worktree paths (reads .iloom/settings.json)").action(async () => {
3390
3135
  try {
3391
- const { TestPrefixCommand } = await import("./test-prefix-64NAAUON.js");
3136
+ const { TestPrefixCommand } = await import("./test-prefix-GBO37XCN.js");
3392
3137
  const command = new TestPrefixCommand();
3393
3138
  await command.execute();
3394
3139
  } catch (error) {
@@ -3402,7 +3147,7 @@ program.command("test-prefix").description("Test worktree prefix configuration -
3402
3147
  program.command("summary").description("Generate Claude session summary for a loom").argument("[identifier]", "Issue number, PR number (pr/123), or branch name (auto-detected if omitted)").option("--with-comment", "Post summary as a comment to the issue/PR").option("--json", "Output result as JSON").action(async (identifier, options) => {
3403
3148
  const executeAction = async () => {
3404
3149
  try {
3405
- const { SummaryCommand } = await import("./summary-G2T4452H.js");
3150
+ const { SummaryCommand } = await import("./summary-WTQZ7XG2.js");
3406
3151
  const command = new SummaryCommand();
3407
3152
  const result = await command.execute({ identifier, options });
3408
3153
  if (options.json && result) {
@@ -3431,7 +3176,7 @@ program.command("summary").description("Generate Claude session summary for a lo
3431
3176
  program.command("recap").description("Get recap for a loom (defaults to current directory)").argument("[identifier]", "Issue number, PR number (pr/123), or branch name (auto-detected if omitted)").option("--json", "Output as JSON with filePath for file watching").action(async (identifier, options) => {
3432
3177
  const executeAction = async () => {
3433
3178
  try {
3434
- const { RecapCommand } = await import("./recap-3W7COH7D.js");
3179
+ const { RecapCommand } = await import("./recap-OMBOKJST.js");
3435
3180
  const command = new RecapCommand();
3436
3181
  const result = await command.execute({ identifier, json: options.json });
3437
3182
  if (options.json && result) {
@@ -3457,16 +3202,62 @@ program.command("recap").description("Get recap for a loom (defaults to current
3457
3202
  await executeAction();
3458
3203
  }
3459
3204
  });
3205
+ var testJiraCommand = program.command("test-jira").description("Test Jira integration methods against a real Jira instance");
3206
+ testJiraCommand.command("child-issue").description("Create a test child issue under a parent").argument("<parentKey>", "Parent issue key (e.g., PROJ-123)").action(async (parentKey) => {
3207
+ try {
3208
+ const { TestJiraCommand } = await import("./test-jira-LDTOYFSD.js");
3209
+ await new TestJiraCommand().createChildIssue(parentKey);
3210
+ } catch (error) {
3211
+ logger.error(`Failed: ${error instanceof Error ? error.message : "Unknown error"}`);
3212
+ process.exit(1);
3213
+ }
3214
+ });
3215
+ testJiraCommand.command("create-dep").description('Create a "Blocks" dependency between two issues').argument("<blockingKey>", "Issue key that blocks (e.g., PROJ-100)").argument("<blockedKey>", "Issue key being blocked (e.g., PROJ-200)").action(async (blockingKey, blockedKey) => {
3216
+ try {
3217
+ const { TestJiraCommand } = await import("./test-jira-LDTOYFSD.js");
3218
+ await new TestJiraCommand().createDependency(blockingKey, blockedKey);
3219
+ } catch (error) {
3220
+ logger.error(`Failed: ${error instanceof Error ? error.message : "Unknown error"}`);
3221
+ process.exit(1);
3222
+ }
3223
+ });
3224
+ testJiraCommand.command("get-deps").description("Fetch and print dependencies for an issue").argument("<issueKey>", "Issue key (e.g., PROJ-123)").action(async (issueKey) => {
3225
+ try {
3226
+ const { TestJiraCommand } = await import("./test-jira-LDTOYFSD.js");
3227
+ await new TestJiraCommand().getDependencies(issueKey);
3228
+ } catch (error) {
3229
+ logger.error(`Failed: ${error instanceof Error ? error.message : "Unknown error"}`);
3230
+ process.exit(1);
3231
+ }
3232
+ });
3233
+ testJiraCommand.command("remove-dep").description('Remove a "Blocks" dependency between two issues').argument("<blockingKey>", "Issue key that blocks (e.g., PROJ-100)").argument("<blockedKey>", "Issue key being blocked (e.g., PROJ-200)").action(async (blockingKey, blockedKey) => {
3234
+ try {
3235
+ const { TestJiraCommand } = await import("./test-jira-LDTOYFSD.js");
3236
+ await new TestJiraCommand().removeDependency(blockingKey, blockedKey);
3237
+ } catch (error) {
3238
+ logger.error(`Failed: ${error instanceof Error ? error.message : "Unknown error"}`);
3239
+ process.exit(1);
3240
+ }
3241
+ });
3242
+ testJiraCommand.command("get-children").description("List child issues of a parent").argument("<issueKey>", "Parent issue key (e.g., PROJ-123)").action(async (issueKey) => {
3243
+ try {
3244
+ const { TestJiraCommand } = await import("./test-jira-LDTOYFSD.js");
3245
+ await new TestJiraCommand().getChildIssues(issueKey);
3246
+ } catch (error) {
3247
+ logger.error(`Failed: ${error instanceof Error ? error.message : "Unknown error"}`);
3248
+ process.exit(1);
3249
+ }
3250
+ });
3460
3251
  program.command("test-neon").description("Test Neon integration and debug configuration").action(async () => {
3461
- var _a;
3252
+ var _a2;
3462
3253
  try {
3463
- const { SettingsManager: SettingsManager2 } = await import("./SettingsManager-AW3JTJHD.js");
3464
- const { createNeonProviderFromSettings: createNeonProviderFromSettings2 } = await import("./neon-helpers-VVFFTLXE.js");
3254
+ const { SettingsManager: SettingsManager2 } = await import("./SettingsManager-FNKCOZMQ.js");
3255
+ const { createNeonProviderFromSettings: createNeonProviderFromSettings2 } = await import("./neon-helpers-CQN2PB4S.js");
3465
3256
  logger.info("Testing Neon Integration\n");
3466
3257
  logger.info("1. Settings Configuration:");
3467
3258
  const settingsManager = new SettingsManager2();
3468
3259
  const settings = await settingsManager.loadSettings();
3469
- const neonConfig = (_a = settings.databaseProviders) == null ? void 0 : _a.neon;
3260
+ const neonConfig = (_a2 = settings.databaseProviders) == null ? void 0 : _a2.neon;
3470
3261
  logger.info(` projectId: ${(neonConfig == null ? void 0 : neonConfig.projectId) ?? "(not configured)"}`);
3471
3262
  logger.info(` parentBranch: ${(neonConfig == null ? void 0 : neonConfig.parentBranch) ?? "(not configured)"}`);
3472
3263
  logger.info("\n2. Creating NeonProvider...");
@@ -3525,6 +3316,23 @@ program.command("test-neon").description("Test Neon integration and debug config
3525
3316
  process.exit(1);
3526
3317
  }
3527
3318
  });
3319
+ var telemetryCmd = program.command("telemetry").description("Manage anonymous usage telemetry");
3320
+ telemetryCmd.command("off").description("Disable anonymous usage telemetry").action(async () => {
3321
+ const manager = new TelemetryManager();
3322
+ manager.disable();
3323
+ logger.info("Telemetry disabled. No usage data will be collected.");
3324
+ });
3325
+ telemetryCmd.command("on").description("Enable anonymous usage telemetry").action(async () => {
3326
+ const manager = new TelemetryManager();
3327
+ manager.enable();
3328
+ logger.info("Telemetry enabled. Anonymous usage data will be collected to improve iloom.");
3329
+ });
3330
+ telemetryCmd.command("status").description("Show current telemetry status").action(async () => {
3331
+ const manager = new TelemetryManager();
3332
+ const status = manager.getStatus();
3333
+ logger.info(`Telemetry: ${status.enabled ? "enabled" : "disabled"}`);
3334
+ logger.info(`Anonymous ID: ${status.distinctId}`);
3335
+ });
3528
3336
  program.command("help").description("Display help information").argument("[command]", "Show help for specific command").action(async (command) => {
3529
3337
  if (command) {
3530
3338
  const subCommand = program.commands.find((cmd) => cmd.name() === command);
@@ -3541,24 +3349,45 @@ program.command("help").description("Display help information").argument("[comma
3541
3349
  });
3542
3350
  var isRunDirectly = process.argv[1] && (() => {
3543
3351
  try {
3544
- const scriptPath = realpathSync(process.argv[1]);
3352
+ const scriptPath = realpathSync2(process.argv[1]);
3545
3353
  const modulePath = fileURLToPath2(import.meta.url);
3546
3354
  return scriptPath === modulePath;
3547
3355
  } catch {
3548
3356
  return true;
3549
3357
  }
3550
3358
  })();
3359
+ var _a;
3551
3360
  if (isRunDirectly) {
3552
3361
  try {
3553
3362
  await program.parseAsync();
3363
+ try {
3364
+ await TelemetryService.getInstance().shutdown();
3365
+ } catch (shutdownError) {
3366
+ logger.debug(`Telemetry shutdown: ${shutdownError instanceof Error ? shutdownError.message : String(shutdownError)}`);
3367
+ }
3554
3368
  } catch (error) {
3369
+ try {
3370
+ const commandName = ((_a = program.args) == null ? void 0 : _a[0]) ?? "unknown";
3371
+ TelemetryService.getInstance().track("error.occurred", {
3372
+ error_type: error instanceof Error ? error.constructor.name : "Unknown",
3373
+ command: commandName,
3374
+ phase: "execution"
3375
+ });
3376
+ await TelemetryService.getInstance().shutdown();
3377
+ } catch (telemetryError) {
3378
+ logger.debug(`Telemetry error tracking: ${telemetryError instanceof Error ? telemetryError.message : String(telemetryError)}`);
3379
+ }
3555
3380
  if (error instanceof Error) {
3556
3381
  logger.error(`Error: ${error.message}`);
3557
3382
  process.exit(1);
3383
+ } else {
3384
+ logger.error(`Error: ${String(error)}`);
3385
+ process.exit(1);
3558
3386
  }
3559
3387
  }
3560
3388
  }
3561
3389
  export {
3390
+ handleTelemetryLifecycle,
3562
3391
  validateGhCliForCommand,
3563
3392
  validateIdeForStartCommand
3564
3393
  };