@iloom/cli 0.9.2 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +159 -40
  3. package/dist/{BranchNamingService-K6XNWQ6C.js → BranchNamingService-ECJHBB67.js} +2 -2
  4. package/dist/ClaudeContextManager-QXX6ZFST.js +14 -0
  5. package/dist/ClaudeService-NJNK2SUH.js +13 -0
  6. package/dist/{GitHubService-TGWJN4V4.js → GitHubService-MEHKHUQP.js} +4 -4
  7. package/dist/IssueTrackerFactory-NG53YX5S.js +14 -0
  8. package/dist/{LoomLauncher-73NXL2CL.js → LoomLauncher-L64HHS3T.js} +9 -9
  9. package/dist/{MetadataManager-W3C54UYT.js → MetadataManager-5QZSTKNN.js} +2 -2
  10. package/dist/{ProjectCapabilityDetector-N5L7T4IY.js → ProjectCapabilityDetector-5KSYUTBJ.js} +3 -3
  11. package/dist/{PromptTemplateManager-36YLQRHP.js → PromptTemplateManager-DULSVRRE.js} +2 -2
  12. package/dist/README.md +159 -40
  13. package/dist/{SettingsManager-AW3JTJHD.js → SettingsManager-BQDQA3FK.js} +4 -2
  14. package/dist/agents/iloom-artifact-reviewer.md +11 -0
  15. package/dist/agents/iloom-code-reviewer.md +14 -0
  16. package/dist/agents/iloom-issue-analyze-and-plan.md +55 -12
  17. package/dist/agents/iloom-issue-analyzer.md +49 -6
  18. package/dist/agents/iloom-issue-complexity-evaluator.md +47 -6
  19. package/dist/agents/iloom-issue-enhancer.md +86 -7
  20. package/dist/agents/iloom-issue-implementer.md +48 -7
  21. package/dist/agents/iloom-issue-planner.md +115 -62
  22. package/dist/{build-THZI572G.js → build-5GO3XW26.js} +9 -9
  23. package/dist/{chunk-NUACL52E.js → chunk-3D7WQM7I.js} +2 -2
  24. package/dist/chunk-4232AHNQ.js +35 -0
  25. package/dist/chunk-4232AHNQ.js.map +1 -0
  26. package/dist/{chunk-QN47QVBX.js → chunk-4WJNIR5O.js} +1 -1
  27. package/dist/chunk-4WJNIR5O.js.map +1 -0
  28. package/dist/{chunk-A7NJF73J.js → chunk-5MWV33NN.js} +4 -4
  29. package/dist/{chunk-3I4ONZRT.js → chunk-6EU6TCF6.js} +10 -10
  30. package/dist/chunk-6EU6TCF6.js.map +1 -0
  31. package/dist/{chunk-CWRI4JC3.js → chunk-FB47TIJG.js} +29 -11
  32. package/dist/chunk-FB47TIJG.js.map +1 -0
  33. package/dist/chunk-HEXKPKCK.js +1396 -0
  34. package/dist/chunk-HEXKPKCK.js.map +1 -0
  35. package/dist/{chunk-KAYXR544.js → chunk-J5S7DFYC.js} +2 -2
  36. package/dist/{chunk-ULSWCPQG.js → chunk-JO2LZ6EQ.js} +476 -5
  37. package/dist/chunk-JO2LZ6EQ.js.map +1 -0
  38. package/dist/{chunk-KBEIQP4G.js → chunk-KB64WNBZ.js} +43 -3
  39. package/dist/chunk-KB64WNBZ.js.map +1 -0
  40. package/dist/{chunk-OFDN5NKS.js → chunk-KXDRI47U.js} +69 -12
  41. package/dist/chunk-KXDRI47U.js.map +1 -0
  42. package/dist/{chunk-R4YWBGY6.js → chunk-LXLMMXXY.js} +54 -14
  43. package/dist/chunk-LXLMMXXY.js.map +1 -0
  44. package/dist/{chunk-AR5QKYNE.js → chunk-MNHZB4Z2.js} +4 -4
  45. package/dist/{chunk-TL72BGP6.js → chunk-MORRVYPT.js} +2 -2
  46. package/dist/{chunk-KJTVU3HZ.js → chunk-NRSWLOAZ.js} +8 -8
  47. package/dist/chunk-NRSWLOAZ.js.map +1 -0
  48. package/dist/{chunk-FO5GGFOV.js → chunk-ONQYPICO.js} +13 -5
  49. package/dist/chunk-ONQYPICO.js.map +1 -0
  50. package/dist/{chunk-7ZEHSSUP.js → chunk-P4O6EH46.js} +4 -4
  51. package/dist/chunk-QZWEJVWV.js +207 -0
  52. package/dist/chunk-QZWEJVWV.js.map +1 -0
  53. package/dist/chunk-RSYT7MVI.js +202 -0
  54. package/dist/chunk-RSYT7MVI.js.map +1 -0
  55. package/dist/{chunk-Z2TWEXR7.js → chunk-RYWFS37M.js} +6 -6
  56. package/dist/chunk-RYWFS37M.js.map +1 -0
  57. package/dist/{chunk-B7U6OKUR.js → chunk-SF2P22EE.js} +11 -3
  58. package/dist/chunk-SF2P22EE.js.map +1 -0
  59. package/dist/{chunk-6IIL5M2L.js → chunk-SN3SQCFK.js} +10 -8
  60. package/dist/{chunk-6IIL5M2L.js.map → chunk-SN3SQCFK.js.map} +1 -1
  61. package/dist/{chunk-SOSQILHO.js → chunk-UD3WJDIV.js} +92 -82
  62. package/dist/chunk-UD3WJDIV.js.map +1 -0
  63. package/dist/{chunk-KXGQYLFZ.js → chunk-UKBAJ2QQ.js} +61 -7
  64. package/dist/chunk-UKBAJ2QQ.js.map +1 -0
  65. package/dist/{chunk-W6DP5RVR.js → chunk-UVD4CZKS.js} +3 -3
  66. package/dist/chunk-UWGVCXRF.js +207 -0
  67. package/dist/chunk-UWGVCXRF.js.map +1 -0
  68. package/dist/{chunk-NWMORW3U.js → chunk-VECNX6VX.js} +2 -2
  69. package/dist/{chunk-4CO6KG5S.js → chunk-VG45TUYK.js} +53 -7
  70. package/dist/{chunk-4CO6KG5S.js.map → chunk-VG45TUYK.js.map} +1 -1
  71. package/dist/{chunk-TC7APDKU.js → chunk-VGGST52X.js} +2 -2
  72. package/dist/{chunk-4LKGCFGG.js → chunk-WWKOVDWC.js} +2 -2
  73. package/dist/{chunk-YKFCCV6S.js → chunk-WY4QBK43.js} +7 -7
  74. package/dist/chunk-WY4QBK43.js.map +1 -0
  75. package/dist/chunk-Y4YZTHZE.js +73 -0
  76. package/dist/chunk-Y4YZTHZE.js.map +1 -0
  77. package/dist/{chunk-VOGGLPG5.js → chunk-YQ57ORTV.js} +14 -1
  78. package/dist/chunk-YQ57ORTV.js.map +1 -0
  79. package/dist/{chunk-RI2YL6TK.js → chunk-YYAKPQBT.js} +65 -18
  80. package/dist/chunk-YYAKPQBT.js.map +1 -0
  81. package/dist/{chunk-IZIYLYPK.js → chunk-ZEWU5PZK.js} +2 -2
  82. package/dist/{chunk-VPTAX5TR.js → chunk-ZHPNZC75.js} +12 -12
  83. package/dist/chunk-ZHPNZC75.js.map +1 -0
  84. package/dist/{chunk-DGG2VY7B.js → chunk-ZW2LKWWE.js} +9 -9
  85. package/dist/chunk-ZW2LKWWE.js.map +1 -0
  86. package/dist/{claude-TP2QO3BU.js → claude-P3NQR6IJ.js} +2 -2
  87. package/dist/{cleanup-PJRIFFU4.js → cleanup-6UCPVMFG.js} +81 -32
  88. package/dist/cleanup-6UCPVMFG.js.map +1 -0
  89. package/dist/cli.js +638 -349
  90. package/dist/cli.js.map +1 -1
  91. package/dist/{commit-IVP3M4HG.js → commit-L3EPY5QG.js} +21 -20
  92. package/dist/commit-L3EPY5QG.js.map +1 -0
  93. package/dist/{compile-R2J65HBQ.js → compile-ZS4HYRX5.js} +9 -9
  94. package/dist/{contribute-VDZXHK5Y.js → contribute-ORDDQGSL.js} +14 -6
  95. package/dist/contribute-ORDDQGSL.js.map +1 -0
  96. package/dist/{dev-server-7F622OEO.js → dev-server-FYZ2AQIH.js} +29 -15
  97. package/dist/dev-server-FYZ2AQIH.js.map +1 -0
  98. package/dist/{feedback-E7VET7CL.js → feedback-TMBXSCM5.js} +15 -15
  99. package/dist/{git-2QDQ2X2S.js → git-ET64COO3.js} +4 -4
  100. package/dist/hooks/iloom-hook.js +15 -0
  101. package/dist/ignite-CGOV3TD4.js +1393 -0
  102. package/dist/ignite-CGOV3TD4.js.map +1 -0
  103. package/dist/index.d.ts +382 -53
  104. package/dist/index.js +1167 -36
  105. package/dist/index.js.map +1 -1
  106. package/dist/{init-676DHF6R.js → init-GFQ5W7GK.js} +57 -21
  107. package/dist/init-GFQ5W7GK.js.map +1 -0
  108. package/dist/{issues-PJSOLOBJ.js → issues-T4ZZSPEG.js} +61 -20
  109. package/dist/issues-T4ZZSPEG.js.map +1 -0
  110. package/dist/{lint-CJM7BAIM.js → lint-6TQXDZ3T.js} +9 -9
  111. package/dist/mcp/issue-management-server.js +2471 -256
  112. package/dist/mcp/issue-management-server.js.map +1 -1
  113. package/dist/mcp/recap-server.js +144 -21
  114. package/dist/mcp/recap-server.js.map +1 -1
  115. package/dist/{neon-helpers-VVFFTLXE.js → neon-helpers-CQN2PB4S.js} +3 -3
  116. package/dist/neon-helpers-CQN2PB4S.js.map +1 -0
  117. package/dist/{open-544H7JF5.js → open-5QZGXQRF.js} +15 -15
  118. package/dist/open-5QZGXQRF.js.map +1 -0
  119. package/dist/{plan-Q7ELXDLC.js → plan-U7ZQWLFY.js} +41 -25
  120. package/dist/plan-U7ZQWLFY.js.map +1 -0
  121. package/dist/{projects-LH362JZQ.js → projects-2UOXFLNZ.js} +4 -4
  122. package/dist/prompts/CLAUDE.md +62 -0
  123. package/dist/prompts/init-prompt.txt +347 -26
  124. package/dist/prompts/issue-prompt.txt +427 -54
  125. package/dist/prompts/plan-prompt.txt +97 -16
  126. package/dist/prompts/pr-prompt.txt +44 -1
  127. package/dist/prompts/regular-prompt.txt +42 -1
  128. package/dist/prompts/session-summary-prompt.txt +14 -0
  129. package/dist/prompts/swarm-orchestrator-prompt.txt +437 -0
  130. package/dist/{rebase-YND35CIE.js → rebase-DWIB77KV.js} +10 -10
  131. package/dist/{recap-3W7COH7D.js → recap-MX63HAKV.js} +47 -19
  132. package/dist/recap-MX63HAKV.js.map +1 -0
  133. package/dist/{run-QUXJKDQQ.js → run-O3TFNQFC.js} +15 -15
  134. package/dist/run-O3TFNQFC.js.map +1 -0
  135. package/dist/schema/package-iloom.schema.json +58 -0
  136. package/dist/schema/settings.schema.json +115 -15
  137. package/dist/{shell-QGECBLST.js → shell-G6VC2CYR.js} +14 -7
  138. package/dist/shell-G6VC2CYR.js.map +1 -0
  139. package/dist/{summary-G2T4452H.js → summary-FWHAX55O.js} +27 -25
  140. package/dist/summary-FWHAX55O.js.map +1 -0
  141. package/dist/{test-EA5NQFDC.js → test-F7JNJZYP.js} +9 -9
  142. package/dist/{test-git-M7LSLEFL.js → test-git-BTAOIUE2.js} +4 -4
  143. package/dist/test-jira-CHYNV33F.js +96 -0
  144. package/dist/test-jira-CHYNV33F.js.map +1 -0
  145. package/dist/{test-prefix-64NAAUON.js → test-prefix-Q6TFSU6F.js} +4 -4
  146. package/dist/{test-webserver-OK6Z5FJM.js → test-webserver-EONCG7E7.js} +6 -6
  147. package/dist/{vscode-AR5NNXXI.js → vscode-VA5X4P25.js} +7 -7
  148. package/package.json +5 -1
  149. package/dist/ClaudeContextManager-HR5JQKAI.js +0 -14
  150. package/dist/ClaudeService-TK7FMC2X.js +0 -13
  151. package/dist/chunk-3I4ONZRT.js.map +0 -1
  152. package/dist/chunk-B7U6OKUR.js.map +0 -1
  153. package/dist/chunk-CWRI4JC3.js.map +0 -1
  154. package/dist/chunk-DGG2VY7B.js.map +0 -1
  155. package/dist/chunk-FJDRTVJX.js +0 -520
  156. package/dist/chunk-FJDRTVJX.js.map +0 -1
  157. package/dist/chunk-FO5GGFOV.js.map +0 -1
  158. package/dist/chunk-KBEIQP4G.js.map +0 -1
  159. package/dist/chunk-KJTVU3HZ.js.map +0 -1
  160. package/dist/chunk-KXGQYLFZ.js.map +0 -1
  161. package/dist/chunk-OFDN5NKS.js.map +0 -1
  162. package/dist/chunk-QN47QVBX.js.map +0 -1
  163. package/dist/chunk-R4YWBGY6.js.map +0 -1
  164. package/dist/chunk-RI2YL6TK.js.map +0 -1
  165. package/dist/chunk-SOSQILHO.js.map +0 -1
  166. package/dist/chunk-ULSWCPQG.js.map +0 -1
  167. package/dist/chunk-VOGGLPG5.js.map +0 -1
  168. package/dist/chunk-VPTAX5TR.js.map +0 -1
  169. package/dist/chunk-WHI5KEOX.js +0 -121
  170. package/dist/chunk-WHI5KEOX.js.map +0 -1
  171. package/dist/chunk-YKFCCV6S.js.map +0 -1
  172. package/dist/chunk-Z2TWEXR7.js.map +0 -1
  173. package/dist/cleanup-PJRIFFU4.js.map +0 -1
  174. package/dist/commit-IVP3M4HG.js.map +0 -1
  175. package/dist/contribute-VDZXHK5Y.js.map +0 -1
  176. package/dist/dev-server-7F622OEO.js.map +0 -1
  177. package/dist/ignite-IW35CDBD.js +0 -784
  178. package/dist/ignite-IW35CDBD.js.map +0 -1
  179. package/dist/init-676DHF6R.js.map +0 -1
  180. package/dist/issues-PJSOLOBJ.js.map +0 -1
  181. package/dist/open-544H7JF5.js.map +0 -1
  182. package/dist/plan-Q7ELXDLC.js.map +0 -1
  183. package/dist/recap-3W7COH7D.js.map +0 -1
  184. package/dist/run-QUXJKDQQ.js.map +0 -1
  185. package/dist/shell-QGECBLST.js.map +0 -1
  186. package/dist/summary-G2T4452H.js.map +0 -1
  187. /package/dist/{BranchNamingService-K6XNWQ6C.js.map → BranchNamingService-ECJHBB67.js.map} +0 -0
  188. /package/dist/{ClaudeContextManager-HR5JQKAI.js.map → ClaudeContextManager-QXX6ZFST.js.map} +0 -0
  189. /package/dist/{ClaudeService-TK7FMC2X.js.map → ClaudeService-NJNK2SUH.js.map} +0 -0
  190. /package/dist/{GitHubService-TGWJN4V4.js.map → GitHubService-MEHKHUQP.js.map} +0 -0
  191. /package/dist/{MetadataManager-W3C54UYT.js.map → IssueTrackerFactory-NG53YX5S.js.map} +0 -0
  192. /package/dist/{LoomLauncher-73NXL2CL.js.map → LoomLauncher-L64HHS3T.js.map} +0 -0
  193. /package/dist/{ProjectCapabilityDetector-N5L7T4IY.js.map → MetadataManager-5QZSTKNN.js.map} +0 -0
  194. /package/dist/{PromptTemplateManager-36YLQRHP.js.map → ProjectCapabilityDetector-5KSYUTBJ.js.map} +0 -0
  195. /package/dist/{SettingsManager-AW3JTJHD.js.map → PromptTemplateManager-DULSVRRE.js.map} +0 -0
  196. /package/dist/{claude-TP2QO3BU.js.map → SettingsManager-BQDQA3FK.js.map} +0 -0
  197. /package/dist/{build-THZI572G.js.map → build-5GO3XW26.js.map} +0 -0
  198. /package/dist/{chunk-NUACL52E.js.map → chunk-3D7WQM7I.js.map} +0 -0
  199. /package/dist/{chunk-A7NJF73J.js.map → chunk-5MWV33NN.js.map} +0 -0
  200. /package/dist/{chunk-KAYXR544.js.map → chunk-J5S7DFYC.js.map} +0 -0
  201. /package/dist/{chunk-AR5QKYNE.js.map → chunk-MNHZB4Z2.js.map} +0 -0
  202. /package/dist/{chunk-TL72BGP6.js.map → chunk-MORRVYPT.js.map} +0 -0
  203. /package/dist/{chunk-7ZEHSSUP.js.map → chunk-P4O6EH46.js.map} +0 -0
  204. /package/dist/{chunk-W6DP5RVR.js.map → chunk-UVD4CZKS.js.map} +0 -0
  205. /package/dist/{chunk-NWMORW3U.js.map → chunk-VECNX6VX.js.map} +0 -0
  206. /package/dist/{chunk-TC7APDKU.js.map → chunk-VGGST52X.js.map} +0 -0
  207. /package/dist/{chunk-4LKGCFGG.js.map → chunk-WWKOVDWC.js.map} +0 -0
  208. /package/dist/{chunk-IZIYLYPK.js.map → chunk-ZEWU5PZK.js.map} +0 -0
  209. /package/dist/{git-2QDQ2X2S.js.map → claude-P3NQR6IJ.js.map} +0 -0
  210. /package/dist/{compile-R2J65HBQ.js.map → compile-ZS4HYRX5.js.map} +0 -0
  211. /package/dist/{feedback-E7VET7CL.js.map → feedback-TMBXSCM5.js.map} +0 -0
  212. /package/dist/{neon-helpers-VVFFTLXE.js.map → git-ET64COO3.js.map} +0 -0
  213. /package/dist/{lint-CJM7BAIM.js.map → lint-6TQXDZ3T.js.map} +0 -0
  214. /package/dist/{projects-LH362JZQ.js.map → projects-2UOXFLNZ.js.map} +0 -0
  215. /package/dist/{rebase-YND35CIE.js.map → rebase-DWIB77KV.js.map} +0 -0
  216. /package/dist/{test-EA5NQFDC.js.map → test-F7JNJZYP.js.map} +0 -0
  217. /package/dist/{test-git-M7LSLEFL.js.map → test-git-BTAOIUE2.js.map} +0 -0
  218. /package/dist/{test-prefix-64NAAUON.js.map → test-prefix-Q6TFSU6F.js.map} +0 -0
  219. /package/dist/{test-webserver-OK6Z5FJM.js.map → test-webserver-EONCG7E7.js.map} +0 -0
  220. /package/dist/{vscode-AR5NNXXI.js.map → vscode-VA5X4P25.js.map} +0 -0
@@ -1,35 +1,35 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  DevServerManager
4
- } from "./chunk-A7NJF73J.js";
5
- import "./chunk-IZIYLYPK.js";
4
+ } from "./chunk-5MWV33NN.js";
5
+ import "./chunk-ZEWU5PZK.js";
6
6
  import {
7
7
  getWorkspacePort
8
- } from "./chunk-NUACL52E.js";
8
+ } from "./chunk-3D7WQM7I.js";
9
+ import "./chunk-WWKOVDWC.js";
9
10
  import {
10
11
  IdentifierParser
11
- } from "./chunk-YKFCCV6S.js";
12
+ } from "./chunk-WY4QBK43.js";
13
+ import {
14
+ GitWorktreeManager
15
+ } from "./chunk-VGGST52X.js";
12
16
  import {
13
17
  openBrowser
14
18
  } from "./chunk-YETJNRQM.js";
15
- import "./chunk-4LKGCFGG.js";
16
19
  import {
17
- GitWorktreeManager
18
- } from "./chunk-TC7APDKU.js";
20
+ ProjectCapabilityDetector
21
+ } from "./chunk-MORRVYPT.js";
22
+ import "./chunk-YQ57ORTV.js";
19
23
  import {
20
24
  extractSettingsOverrides
21
25
  } from "./chunk-GYCR2LOU.js";
22
- import {
23
- ProjectCapabilityDetector
24
- } from "./chunk-TL72BGP6.js";
25
- import "./chunk-VOGGLPG5.js";
26
26
  import {
27
27
  extractIssueNumber
28
- } from "./chunk-AR5QKYNE.js";
28
+ } from "./chunk-MNHZB4Z2.js";
29
29
  import {
30
30
  SettingsManager
31
- } from "./chunk-RI2YL6TK.js";
32
- import "./chunk-KBEIQP4G.js";
31
+ } from "./chunk-YYAKPQBT.js";
32
+ import "./chunk-KB64WNBZ.js";
33
33
  import "./chunk-6MLEBAYZ.js";
34
34
  import {
35
35
  logger
@@ -238,4 +238,4 @@ Make sure the project is built (run 'il start' first)`
238
238
  export {
239
239
  RunCommand
240
240
  };
241
- //# sourceMappingURL=run-QUXJKDQQ.js.map
241
+ //# sourceMappingURL=run-O3TFNQFC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/run.ts"],"sourcesContent":["import path from 'path'\nimport fs from 'fs-extra'\nimport { execa } from 'execa'\nimport { GitWorktreeManager } from '../lib/GitWorktreeManager.js'\nimport { ProjectCapabilityDetector } from '../lib/ProjectCapabilityDetector.js'\nimport { DevServerManager } from '../lib/DevServerManager.js'\nimport { SettingsManager } from '../lib/SettingsManager.js'\nimport { IdentifierParser } from '../utils/IdentifierParser.js'\nimport { openBrowser } from '../utils/browser.js'\nimport { getWorkspacePort } from '../utils/port.js'\nimport { extractIssueNumber } from '../utils/git.js'\nimport { logger } from '../utils/logger.js'\nimport { extractSettingsOverrides } from '../utils/cli-overrides.js'\nimport type { GitWorktree } from '../types/worktree.js'\n\nexport interface RunCommandInput {\n\tidentifier?: string\n\targs?: string[]\n}\n\ninterface ParsedRunInput {\n\ttype: 'issue' | 'pr' | 'branch' | 'epic'\n\tnumber?: string | number // For issues and PRs\n\tbranchName?: string // For branches\n\toriginalInput: string\n\tautoDetected: boolean\n}\n\n/**\n * RunCommand - Runs CLI tool or opens workspace in browser\n * Priority: CLI first, Web fallback\n */\nexport class RunCommand {\n\tconstructor(\n\t\tprivate gitWorktreeManager = new GitWorktreeManager(),\n\t\tprivate capabilityDetector = new ProjectCapabilityDetector(),\n\t\tprivate identifierParser = new IdentifierParser(new GitWorktreeManager()),\n\t\tprivate devServerManager = new DevServerManager(),\n\t\tprivate settingsManager = new SettingsManager()\n\t) {}\n\n\tasync execute(input: RunCommandInput): Promise<void> {\n\t\t// 1. Parse or auto-detect identifier\n\t\tconst parsed = input.identifier\n\t\t\t? await this.parseExplicitInput(input.identifier)\n\t\t\t: await this.autoDetectFromCurrentDirectory()\n\n\t\tlogger.debug(`Parsed input: ${JSON.stringify(parsed)}`)\n\n\t\t// 2. Find worktree path based on identifier\n\t\tconst worktree = await this.findWorktreeForIdentifier(parsed)\n\n\t\tlogger.info(`Found worktree at: ${worktree.path}`)\n\n\t\t// 3. Detect project capabilities\n\t\tconst { capabilities, binEntries } =\n\t\t\tawait this.capabilityDetector.detectCapabilities(worktree.path)\n\n\t\tlogger.debug(`Detected capabilities: ${capabilities.join(', ')}`)\n\n\t\t// 4. Execute based on capabilities (CLI first, web fallback)\n\t\tif (capabilities.includes('cli')) {\n\t\t\tawait this.runCLITool(worktree.path, binEntries, input.args ?? [])\n\t\t} else if (capabilities.includes('web')) {\n\t\t\tawait this.openWebBrowser(worktree)\n\t\t} else {\n\t\t\tthrow new Error(\n\t\t\t\t`No CLI or web capabilities detected for workspace at ${worktree.path}`\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * Parse explicit identifier input\n\t */\n\tprivate async parseExplicitInput(identifier: string): Promise<ParsedRunInput> {\n\t\tconst parsed = await this.identifierParser.parseForPatternDetection(identifier)\n\n\t\t// Description type should never reach run command (converted in start)\n\t\tif (parsed.type === 'description') {\n\t\t\tthrow new Error('Description input type is not supported in run command')\n\t\t}\n\n\t\tconst result: ParsedRunInput = {\n\t\t\ttype: parsed.type,\n\t\t\toriginalInput: parsed.originalInput,\n\t\t\tautoDetected: false,\n\t\t}\n\n\t\tif (parsed.number !== undefined) {\n\t\t\tresult.number = parsed.number\n\t\t}\n\t\tif (parsed.branchName !== undefined) {\n\t\t\tresult.branchName = parsed.branchName\n\t\t}\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Auto-detect identifier from current directory\n\t * Same logic as FinishCommand.autoDetectFromCurrentDirectory()\n\t */\n\tprivate async autoDetectFromCurrentDirectory(): Promise<ParsedRunInput> {\n\t\tconst currentDir = path.basename(process.cwd())\n\n\t\t// Check for PR worktree pattern: _pr_N suffix\n\t\tconst prPattern = /_pr_(\\d+)$/\n\t\tconst prMatch = currentDir.match(prPattern)\n\n\t\tif (prMatch?.[1]) {\n\t\t\tconst prNumber = parseInt(prMatch[1], 10)\n\t\t\tlogger.debug(`Auto-detected PR #${prNumber} from directory: ${currentDir}`)\n\t\t\treturn {\n\t\t\t\ttype: 'pr',\n\t\t\t\tnumber: prNumber,\n\t\t\t\toriginalInput: currentDir,\n\t\t\t\tautoDetected: true,\n\t\t\t}\n\t\t}\n\n\t\t// Check for issue pattern in directory\n\t\tconst issueNumber = extractIssueNumber(currentDir)\n\n\t\tif (issueNumber !== null) {\n\t\t\tlogger.debug(`Auto-detected issue #${issueNumber} from directory: ${currentDir}`)\n\t\t\treturn {\n\t\t\t\ttype: 'issue',\n\t\t\t\tnumber: issueNumber,\n\t\t\t\toriginalInput: currentDir,\n\t\t\t\tautoDetected: true,\n\t\t\t}\n\t\t}\n\n\t\t// Fallback: get current branch name\n\t\tconst repoInfo = await this.gitWorktreeManager.getRepoInfo()\n\t\tconst currentBranch = repoInfo.currentBranch\n\n\t\tif (!currentBranch) {\n\t\t\tthrow new Error(\n\t\t\t\t'Could not auto-detect identifier. Please provide an issue number, PR number, or branch name.\\n' +\n\t\t\t\t\t'Expected directory pattern: feat/issue-XX-description OR worktree with _pr_N suffix'\n\t\t\t)\n\t\t}\n\n\t\t// Try to extract issue from branch name\n\t\tconst branchIssueNumber = extractIssueNumber(currentBranch)\n\t\tif (branchIssueNumber !== null) {\n\t\t\tlogger.debug(`Auto-detected issue #${branchIssueNumber} from branch: ${currentBranch}`)\n\t\t\treturn {\n\t\t\t\ttype: 'issue',\n\t\t\t\tnumber: branchIssueNumber,\n\t\t\t\toriginalInput: currentBranch,\n\t\t\t\tautoDetected: true,\n\t\t\t}\n\t\t}\n\n\t\t// Last resort: use branch name\n\t\treturn {\n\t\t\ttype: 'branch',\n\t\t\tbranchName: currentBranch,\n\t\t\toriginalInput: currentBranch,\n\t\t\tautoDetected: true,\n\t\t}\n\t}\n\n\t/**\n\t * Find worktree for the given identifier\n\t */\n\tprivate async findWorktreeForIdentifier(parsed: ParsedRunInput): Promise<GitWorktree> {\n\t\tlet worktree: GitWorktree | null = null\n\n\t\tif (parsed.type === 'issue' && parsed.number !== undefined) {\n\t\t\tworktree = await this.gitWorktreeManager.findWorktreeForIssue(parsed.number)\n\t\t} else if (parsed.type === 'pr' && parsed.number !== undefined) {\n\t\t\t// For PRs, ensure the number is numeric (PRs are always numeric per GitHub)\n\t\t\tconst prNumber = typeof parsed.number === 'number' ? parsed.number : Number(parsed.number)\n\t\t\tif (isNaN(prNumber) || !isFinite(prNumber)) {\n\t\t\t\tthrow new Error(`Invalid PR number: ${parsed.number}. PR numbers must be numeric.`)\n\t\t\t}\n\t\t\t// Pass empty string for branch name since we don't know it yet\n\t\t\tworktree = await this.gitWorktreeManager.findWorktreeForPR(prNumber, '')\n\t\t} else if (parsed.type === 'branch' && parsed.branchName) {\n\t\t\tworktree = await this.gitWorktreeManager.findWorktreeForBranch(\n\t\t\t\tparsed.branchName\n\t\t\t)\n\t\t}\n\n\t\tif (!worktree) {\n\t\t\tthrow new Error(\n\t\t\t\t`No worktree found for ${this.formatParsedInput(parsed)}. ` +\n\t\t\t\t\t`Run 'il start ${parsed.originalInput}' to create one.`\n\t\t\t)\n\t\t}\n\n\t\treturn worktree\n\t}\n\n\t/**\n\t * Format parsed input for display\n\t */\n\tprivate formatParsedInput(parsed: ParsedRunInput): string {\n\t\tconst autoLabel = parsed.autoDetected ? ' (auto-detected)' : ''\n\n\t\tif (parsed.type === 'issue') {\n\t\t\treturn `issue #${parsed.number}${autoLabel}`\n\t\t}\n\t\tif (parsed.type === 'pr') {\n\t\t\treturn `PR #${parsed.number}${autoLabel}`\n\t\t}\n\t\treturn `branch \"${parsed.branchName}\"${autoLabel}`\n\t}\n\n\t/**\n\t * Run CLI tool directly from worktree bin path (NO SYMLINKS!)\n\t */\n\tprivate async runCLITool(\n\t\tworktreePath: string,\n\t\tbinEntries: Record<string, string>,\n\t\targs: string[]\n\t): Promise<void> {\n\t\t// Validate binEntries exist\n\t\tif (Object.keys(binEntries).length === 0) {\n\t\t\tthrow new Error('No bin entries found in package.json')\n\t\t}\n\n\t\t// Get first bin entry (deterministic)\n\t\tconst firstEntry = Object.entries(binEntries)[0]\n\t\tif (!firstEntry) {\n\t\t\tthrow new Error('No bin entries found in package.json')\n\t\t}\n\t\tconst [binName, binPath] = firstEntry\n\t\tlogger.debug(`Using bin entry: ${binName} -> ${binPath}`)\n\n\t\t// CRITICAL: Construct absolute path (NO SYMLINKS!)\n\t\tconst binFilePath = path.resolve(worktreePath, binPath)\n\t\tlogger.debug(`Resolved bin file path: ${binFilePath}`)\n\n\t\t// Verify file exists\n\t\tif (!(await fs.pathExists(binFilePath))) {\n\t\t\tthrow new Error(\n\t\t\t\t`CLI executable not found: ${binFilePath}\\n` +\n\t\t\t\t\t`Make sure the project is built (run 'il start' first)`\n\t\t\t)\n\t\t}\n\n\t\t// Execute with Node.js\n\t\tlogger.info(`Running CLI: node ${binFilePath} ${args.join(' ')}`)\n\t\tawait execa('node', [binFilePath, ...args], {\n\t\t\tstdio: 'inherit', // Allow interactive CLIs (prompts, colors, etc.)\n\t\t\tcwd: worktreePath, // Execute in worktree context\n\t\t\tenv: process.env, // Inherit environment\n\t\t})\n\t}\n\n\t/**\n\t * Open web browser with workspace URL\n\t * Auto-starts dev server if not already running\n\t */\n\tprivate async openWebBrowser(worktree: GitWorktree): Promise<void> {\n\t\tconst cliOverrides = extractSettingsOverrides()\n\t\tconst settings = await this.settingsManager.loadSettings(undefined, cliOverrides)\n\t\tconst port = await getWorkspacePort({\n\t\t\tworktreePath: worktree.path,\n\t\t\tworktreeBranch: worktree.branch,\n\t\t\tbasePort: settings.capabilities?.web?.basePort,\n\t\t\tcheckEnvFile: true,\n\t\t})\n\n\t\t// Ensure dev server is running on the port\n\t\tconst serverReady = await this.devServerManager.ensureServerRunning(\n\t\t\tworktree.path,\n\t\t\tport\n\t\t)\n\n\t\tif (!serverReady) {\n\t\t\tlogger.warn(\n\t\t\t\t`Dev server failed to start on port ${port}. Opening browser anyway...`\n\t\t\t)\n\t\t}\n\n\t\t// Construct URL and open browser\n\t\tconst url = `http://localhost:${port}`\n\t\tlogger.info(`Opening browser: ${url}`)\n\t\tawait openBrowser(url)\n\t\tlogger.success('Browser opened')\n\t}\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,58 @@
1
+ {
2
+ "$ref": "#/definitions/PackageIloom",
3
+ "definitions": {
4
+ "PackageIloom": {
5
+ "type": "object",
6
+ "properties": {
7
+ "capabilities": {
8
+ "type": "array",
9
+ "items": {
10
+ "type": "string",
11
+ "enum": [
12
+ "cli",
13
+ "web"
14
+ ]
15
+ },
16
+ "description": "Project capabilities - \"cli\" for command-line tools (enables CLI isolation), \"web\" for web applications (enables port assignment and dev server)"
17
+ },
18
+ "scripts": {
19
+ "type": "object",
20
+ "properties": {
21
+ "install": {
22
+ "type": "string",
23
+ "description": "Install command (e.g., \"bundle install\", \"poetry install\")"
24
+ },
25
+ "build": {
26
+ "type": "string",
27
+ "description": "Build/compile command"
28
+ },
29
+ "test": {
30
+ "type": "string",
31
+ "description": "Test suite command"
32
+ },
33
+ "dev": {
34
+ "type": "string",
35
+ "description": "Dev server command"
36
+ },
37
+ "lint": {
38
+ "type": "string",
39
+ "description": "Linting command"
40
+ },
41
+ "typecheck": {
42
+ "type": "string",
43
+ "description": "Type checking command"
44
+ },
45
+ "compile": {
46
+ "type": "string",
47
+ "description": "Compilation command (preferred over typecheck if both exist)"
48
+ }
49
+ },
50
+ "additionalProperties": false,
51
+ "description": "Custom shell commands for project operations. These are raw shell commands, not npm script names."
52
+ }
53
+ },
54
+ "additionalProperties": false
55
+ }
56
+ },
57
+ "$schema": "http://json-schema.org/draft-07/schema#"
58
+ }
@@ -218,6 +218,47 @@
218
218
  "review": {
219
219
  "type": "boolean",
220
220
  "description": "Whether artifacts from this agent should be reviewed before posting (defaults to false)"
221
+ },
222
+ "agents": {
223
+ "type": "object",
224
+ "additionalProperties": {
225
+ "type": "object",
226
+ "properties": {
227
+ "model": {
228
+ "type": "string",
229
+ "enum": [
230
+ "sonnet",
231
+ "opus",
232
+ "haiku"
233
+ ],
234
+ "description": "Claude model shorthand: sonnet, opus, or haiku"
235
+ },
236
+ "enabled": {
237
+ "type": "boolean",
238
+ "description": "Whether this agent is enabled. Defaults to true."
239
+ },
240
+ "providers": {
241
+ "type": "object",
242
+ "additionalProperties": {
243
+ "type": "string"
244
+ },
245
+ "propertyNames": {
246
+ "enum": [
247
+ "claude",
248
+ "gemini",
249
+ "codex"
250
+ ]
251
+ },
252
+ "description": "Map of review providers to model names. Keys: claude, gemini, codex. Values: model name strings (e.g., \"sonnet\", \"gemini-3-pro-preview\", \"gpt-5.2-codex\")"
253
+ },
254
+ "review": {
255
+ "type": "boolean",
256
+ "description": "Whether artifacts from this agent should be reviewed before posting (defaults to false)"
257
+ }
258
+ },
259
+ "additionalProperties": false
260
+ },
261
+ "description": "Nested per-agent model overrides for swarm mode. Configure under agents.iloom-swarm-worker.agents.<agent-name>.model to set a different model for phase agents when running inside swarm workers. Fallback chain: swarm-specific agent model > explicit swarm worker model > base agent model. Only meaningful under the iloom-swarm-worker agent entry."
221
262
  }
222
263
  },
223
264
  "additionalProperties": false
@@ -229,7 +270,7 @@
229
270
  "type": "null"
230
271
  }
231
272
  ],
232
- "description": "Per-agent configuration overrides. Available agents: iloom-issue-analyzer (analyzes issues), iloom-issue-planner (creates implementation plans), iloom-issue-analyze-and-plan (combined analysis and planning), iloom-issue-complexity-evaluator (evaluates complexity), iloom-issue-enhancer (enhances issue descriptions), iloom-issue-implementer (implements code changes), iloom-code-reviewer (reviews code changes against requirements), iloom-artifact-reviewer (reviews artifacts before posting)"
273
+ "description": "Per-agent configuration overrides. Available agents: iloom-issue-analyzer (analyzes issues), iloom-issue-planner (creates implementation plans), iloom-issue-analyze-and-plan (combined analysis and planning), iloom-issue-complexity-evaluator (evaluates complexity), iloom-issue-enhancer (enhances issue descriptions), iloom-issue-implementer (implements code changes), iloom-code-reviewer (reviews code changes against requirements), iloom-artifact-reviewer (reviews artifacts before posting), iloom-swarm-worker (swarm worker agent, dynamically generated). The iloom-swarm-worker agent supports a nested \"agents\" sub-record for configuring phase agent models specifically in swarm mode."
233
274
  },
234
275
  "spin": {
235
276
  "type": "object",
@@ -306,17 +347,6 @@
306
347
  "capabilities": {
307
348
  "type": "object",
308
349
  "properties": {
309
- "capabilities": {
310
- "type": "array",
311
- "items": {
312
- "type": "string",
313
- "enum": [
314
- "cli",
315
- "web"
316
- ]
317
- },
318
- "description": "Explicitly declared project capabilities (auto-detected if not specified)"
319
- },
320
350
  "web": {
321
351
  "type": "object",
322
352
  "properties": {
@@ -327,7 +357,8 @@
327
357
  "description": "Base port for web workspace port calculations (default: 3000)"
328
358
  }
329
359
  },
330
- "additionalProperties": false
360
+ "additionalProperties": false,
361
+ "description": "Web dev server settings. To declare a project as a web project, add \"web\" to the capabilities array in .iloom/package.iloom.json or .iloom/package.iloom.local.json."
331
362
  },
332
363
  "database": {
333
364
  "type": "object",
@@ -382,10 +413,11 @@
382
413
  "type": "string",
383
414
  "enum": [
384
415
  "github",
385
- "linear"
416
+ "linear",
417
+ "jira"
386
418
  ],
387
419
  "default": "github",
388
- "description": "Issue tracker provider (github, linear)"
420
+ "description": "Issue tracker provider (github, linear, jira)"
389
421
  },
390
422
  "github": {
391
423
  "type": "object",
@@ -422,6 +454,69 @@
422
454
  "teamId"
423
455
  ],
424
456
  "additionalProperties": false
457
+ },
458
+ "jira": {
459
+ "type": "object",
460
+ "properties": {
461
+ "host": {
462
+ "type": "string",
463
+ "minLength": 1,
464
+ "description": "Jira instance URL (e.g., \"https://yourcompany.atlassian.net\")"
465
+ },
466
+ "username": {
467
+ "type": "string",
468
+ "minLength": 1,
469
+ "description": "Jira username or email address"
470
+ },
471
+ "apiToken": {
472
+ "type": "string",
473
+ "description": "Jira API token. SECURITY: Store in settings.local.json only, never commit to source control. Generate at: https://id.atlassian.com/manage-profile/security/api-tokens"
474
+ },
475
+ "projectKey": {
476
+ "type": "string",
477
+ "minLength": 1,
478
+ "description": "Jira project key (e.g., \"PROJ\", \"ENG\")"
479
+ },
480
+ "boardId": {
481
+ "type": "string",
482
+ "description": "Jira board ID for sprint/workflow operations (optional)"
483
+ },
484
+ "transitionMappings": {
485
+ "type": "object",
486
+ "additionalProperties": {
487
+ "type": "string"
488
+ },
489
+ "description": "Map iloom states to Jira transition names (e.g., {\"In Review\": \"Start Review\"})"
490
+ },
491
+ "defaultIssueType": {
492
+ "type": "string",
493
+ "minLength": 1,
494
+ "default": "Task",
495
+ "description": "Default Jira issue type name for creating issues (e.g., \"Task\", \"Story\", \"Bug\")"
496
+ },
497
+ "defaultSubtaskType": {
498
+ "type": "string",
499
+ "minLength": 1,
500
+ "default": "Subtask",
501
+ "description": "Default Jira issue type name for creating subtasks/child issues (e.g., \"Subtask\", \"Sub-task\")"
502
+ },
503
+ "doneStatuses": {
504
+ "type": "array",
505
+ "items": {
506
+ "type": "string"
507
+ },
508
+ "default": [
509
+ "Done"
510
+ ],
511
+ "description": "Status names to exclude from issue lists (e.g., [\"Done\", \"Closed\", \"Verify\"])"
512
+ }
513
+ },
514
+ "required": [
515
+ "host",
516
+ "username",
517
+ "projectKey"
518
+ ],
519
+ "additionalProperties": false
425
520
  }
426
521
  },
427
522
  "additionalProperties": false,
@@ -445,6 +540,11 @@
445
540
  "autoCommitPush": {
446
541
  "type": "boolean",
447
542
  "description": "Auto-commit and push after code review in draft PR mode. Defaults to true when mode is github-draft-pr."
543
+ },
544
+ "openBrowserOnFinish": {
545
+ "type": "boolean",
546
+ "default": true,
547
+ "description": "Open the PR in the default browser after finishing in github-pr or github-draft-pr mode. Use --no-browser flag to override."
448
548
  }
449
549
  },
450
550
  "additionalProperties": false,
@@ -1,17 +1,19 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  IdentifierParser
4
- } from "./chunk-YKFCCV6S.js";
4
+ } from "./chunk-WY4QBK43.js";
5
5
  import {
6
6
  GitWorktreeManager
7
- } from "./chunk-TC7APDKU.js";
7
+ } from "./chunk-VGGST52X.js";
8
8
  import {
9
9
  extractIssueNumber
10
- } from "./chunk-AR5QKYNE.js";
10
+ } from "./chunk-MNHZB4Z2.js";
11
11
  import {
12
12
  SettingsManager
13
- } from "./chunk-RI2YL6TK.js";
14
- import "./chunk-KBEIQP4G.js";
13
+ } from "./chunk-YYAKPQBT.js";
14
+ import {
15
+ MetadataManager
16
+ } from "./chunk-KB64WNBZ.js";
15
17
  import "./chunk-6MLEBAYZ.js";
16
18
  import {
17
19
  getDotenvFlowFiles,
@@ -24,10 +26,11 @@ import path from "path";
24
26
  import { execa } from "execa";
25
27
  import fs from "fs-extra";
26
28
  var ShellCommand = class {
27
- constructor(gitWorktreeManager = new GitWorktreeManager(), identifierParser = new IdentifierParser(new GitWorktreeManager()), settingsManager = new SettingsManager()) {
29
+ constructor(gitWorktreeManager = new GitWorktreeManager(), identifierParser = new IdentifierParser(new GitWorktreeManager()), settingsManager = new SettingsManager(), metadataManager = new MetadataManager()) {
28
30
  this.gitWorktreeManager = gitWorktreeManager;
29
31
  this.identifierParser = identifierParser;
30
32
  this.settingsManager = settingsManager;
33
+ this.metadataManager = metadataManager;
31
34
  }
32
35
  async execute(input) {
33
36
  const parsed = input.identifier ? await this.parseExplicitInput(input.identifier) : await this.autoDetectFromCurrentDirectory();
@@ -47,6 +50,10 @@ var ShellCommand = class {
47
50
  }
48
51
  const loomIdentifier = this.formatLoomIdentifier(parsed);
49
52
  envVars.ILOOM_LOOM = loomIdentifier;
53
+ const metadata = await this.metadataManager.readMetadata(worktree.path);
54
+ if (metadata == null ? void 0 : metadata.colorHex) {
55
+ envVars.ILOOM_COLOR_HEX = metadata.colorHex;
56
+ }
50
57
  const shell = this.detectShell();
51
58
  this.printSummary(worktree.path, shell, loadedEnvFiles, envVars, shouldLoadEnv);
52
59
  await execa(shell, [], {
@@ -235,4 +242,4 @@ var ShellCommand = class {
235
242
  export {
236
243
  ShellCommand
237
244
  };
238
- //# sourceMappingURL=shell-QGECBLST.js.map
245
+ //# sourceMappingURL=shell-G6VC2CYR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/shell.ts"],"sourcesContent":["import path from 'path'\nimport { execa } from 'execa'\nimport fs from 'fs-extra'\nimport { GitWorktreeManager } from '../lib/GitWorktreeManager.js'\nimport { MetadataManager } from '../lib/MetadataManager.js'\nimport { SettingsManager } from '../lib/SettingsManager.js'\nimport { IdentifierParser } from '../utils/IdentifierParser.js'\nimport { loadWorkspaceEnv, getDotenvFlowFiles } from '../utils/env.js'\nimport { extractIssueNumber } from '../utils/git.js'\nimport { logger } from '../utils/logger.js'\nimport type { GitWorktree } from '../types/worktree.js'\n\nexport interface ShellCommandInput {\n\tidentifier?: string | undefined\n}\n\ninterface ParsedShellInput {\n\ttype: 'issue' | 'pr' | 'branch' | 'epic'\n\tnumber?: string | number\n\tbranchName?: string\n\toriginalInput: string\n\tautoDetected: boolean\n}\n\n/**\n * ShellCommand - Open interactive shell with workspace environment\n * Loads dotenv-flow files when sourceEnvOnStart is configured\n */\nexport class ShellCommand {\n\tconstructor(\n\t\tprivate gitWorktreeManager = new GitWorktreeManager(),\n\t\tprivate identifierParser = new IdentifierParser(new GitWorktreeManager()),\n\t\tprivate settingsManager = new SettingsManager(),\n\t\tprivate metadataManager = new MetadataManager()\n\t) {}\n\n\tasync execute(input: ShellCommandInput): Promise<void> {\n\t\t// 1. Parse or auto-detect identifier\n\t\tconst parsed = input.identifier\n\t\t\t? await this.parseExplicitInput(input.identifier)\n\t\t\t: await this.autoDetectFromCurrentDirectory()\n\n\t\tlogger.debug(`Parsed input: ${JSON.stringify(parsed)}`)\n\n\t\t// 2. Find worktree path based on identifier\n\t\tconst worktree = await this.findWorktreeForIdentifier(parsed)\n\n\t\tlogger.debug(`Found worktree at: ${worktree.path}`)\n\n\t\t// 3. Load settings to check sourceEnvOnStart\n\t\tconst settings = await this.settingsManager.loadSettings()\n\t\tconst shouldLoadEnv = settings.sourceEnvOnStart ?? false\n\n\t\t// 4. Build environment variables\n\t\tlet envVars: Record<string, string> = { ...process.env as Record<string, string> }\n\t\tlet loadedEnvFiles: string[] = []\n\n\t\tif (shouldLoadEnv) {\n\t\t\tconst envResult = loadWorkspaceEnv(worktree.path)\n\t\t\tif (envResult.parsed) {\n\t\t\t\tenvVars = { ...envVars, ...envResult.parsed }\n\t\t\t}\n\t\t\t// Determine which files were actually loaded\n\t\t\tloadedEnvFiles = await this.getExistingEnvFiles(worktree.path)\n\t\t}\n\n\t\t// 5. Set ILOOM_LOOM for PS1 customization\n\t\tconst loomIdentifier = this.formatLoomIdentifier(parsed)\n\t\tenvVars.ILOOM_LOOM = loomIdentifier\n\n\t\t// 5b. Set ILOOM_COLOR_HEX from loom metadata if available\n\t\tconst metadata = await this.metadataManager.readMetadata(worktree.path)\n\t\tif (metadata?.colorHex) {\n\t\t\tenvVars.ILOOM_COLOR_HEX = metadata.colorHex\n\t\t}\n\n\t\t// 6. Detect shell\n\t\tconst shell = this.detectShell()\n\n\t\t// 7. Print summary\n\t\tthis.printSummary(worktree.path, shell, loadedEnvFiles, envVars, shouldLoadEnv)\n\n\t\t// 8. Launch interactive shell\n\t\tawait execa(shell, [], {\n\t\t\tcwd: worktree.path,\n\t\t\tenv: envVars,\n\t\t\tstdio: 'inherit',\n\t\t})\n\t}\n\n\t/**\n\t * Parse explicit identifier input\n\t */\n\tprivate async parseExplicitInput(identifier: string): Promise<ParsedShellInput> {\n\t\tconst parsed = await this.identifierParser.parseForPatternDetection(identifier)\n\n\t\t// Description type should never reach terminal command\n\t\tif (parsed.type === 'description') {\n\t\t\tthrow new Error('Description input type is not supported in terminal command')\n\t\t}\n\n\t\tconst result: ParsedShellInput = {\n\t\t\ttype: parsed.type,\n\t\t\toriginalInput: parsed.originalInput,\n\t\t\tautoDetected: false,\n\t\t}\n\n\t\tif (parsed.number !== undefined) {\n\t\t\tresult.number = parsed.number\n\t\t}\n\t\tif (parsed.branchName !== undefined) {\n\t\t\tresult.branchName = parsed.branchName\n\t\t}\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Auto-detect identifier from current directory\n\t */\n\tprivate async autoDetectFromCurrentDirectory(): Promise<ParsedShellInput> {\n\t\tconst currentDir = path.basename(process.cwd())\n\n\t\t// Check for PR worktree pattern: _pr_N suffix\n\t\tconst prPattern = /_pr_(\\d+)$/\n\t\tconst prMatch = currentDir.match(prPattern)\n\n\t\tif (prMatch?.[1]) {\n\t\t\tconst prNumber = parseInt(prMatch[1], 10)\n\t\t\tlogger.debug(`Auto-detected PR #${prNumber} from directory: ${currentDir}`)\n\t\t\treturn {\n\t\t\t\ttype: 'pr',\n\t\t\t\tnumber: prNumber,\n\t\t\t\toriginalInput: currentDir,\n\t\t\t\tautoDetected: true,\n\t\t\t}\n\t\t}\n\n\t\t// Check for issue pattern in directory\n\t\tconst issueNumber = extractIssueNumber(currentDir)\n\n\t\tif (issueNumber !== null) {\n\t\t\tlogger.debug(`Auto-detected issue #${issueNumber} from directory: ${currentDir}`)\n\t\t\treturn {\n\t\t\t\ttype: 'issue',\n\t\t\t\tnumber: issueNumber,\n\t\t\t\toriginalInput: currentDir,\n\t\t\t\tautoDetected: true,\n\t\t\t}\n\t\t}\n\n\t\t// Fallback: get current branch name\n\t\tconst repoInfo = await this.gitWorktreeManager.getRepoInfo()\n\t\tconst currentBranch = repoInfo.currentBranch\n\n\t\tif (!currentBranch) {\n\t\t\tthrow new Error(\n\t\t\t\t'Could not auto-detect identifier. Please provide an issue number, PR number, or branch name.\\n' +\n\t\t\t\t\t'Expected directory pattern: feat/issue-XX-description OR worktree with _pr_N suffix'\n\t\t\t)\n\t\t}\n\n\t\t// Try to extract issue from branch name\n\t\tconst branchIssueNumber = extractIssueNumber(currentBranch)\n\t\tif (branchIssueNumber !== null) {\n\t\t\tlogger.debug(`Auto-detected issue #${branchIssueNumber} from branch: ${currentBranch}`)\n\t\t\treturn {\n\t\t\t\ttype: 'issue',\n\t\t\t\tnumber: branchIssueNumber,\n\t\t\t\toriginalInput: currentBranch,\n\t\t\t\tautoDetected: true,\n\t\t\t}\n\t\t}\n\n\t\t// Last resort: use branch name\n\t\treturn {\n\t\t\ttype: 'branch',\n\t\t\tbranchName: currentBranch,\n\t\t\toriginalInput: currentBranch,\n\t\t\tautoDetected: true,\n\t\t}\n\t}\n\n\t/**\n\t * Find worktree for the given identifier\n\t */\n\tprivate async findWorktreeForIdentifier(parsed: ParsedShellInput): Promise<GitWorktree> {\n\t\tlet worktree: GitWorktree | null = null\n\n\t\tif (parsed.type === 'issue' && parsed.number !== undefined) {\n\t\t\tworktree = await this.gitWorktreeManager.findWorktreeForIssue(parsed.number)\n\t\t} else if (parsed.type === 'pr' && parsed.number !== undefined) {\n\t\t\tconst prNumber = typeof parsed.number === 'number' ? parsed.number : Number(parsed.number)\n\t\t\tif (isNaN(prNumber) || !isFinite(prNumber)) {\n\t\t\t\tthrow new Error(`Invalid PR number: ${parsed.number}. PR numbers must be numeric.`)\n\t\t\t}\n\t\t\tworktree = await this.gitWorktreeManager.findWorktreeForPR(prNumber, '')\n\t\t} else if (parsed.type === 'branch' && parsed.branchName) {\n\t\t\tworktree = await this.gitWorktreeManager.findWorktreeForBranch(\n\t\t\t\tparsed.branchName\n\t\t\t)\n\t\t}\n\n\t\tif (!worktree) {\n\t\t\tthrow new Error(\n\t\t\t\t`No worktree found for ${this.formatParsedInput(parsed)}. ` +\n\t\t\t\t\t`Run 'il start ${parsed.originalInput}' to create one.`\n\t\t\t)\n\t\t}\n\n\t\treturn worktree\n\t}\n\n\t/**\n\t * Format parsed input for display\n\t */\n\tprivate formatParsedInput(parsed: ParsedShellInput): string {\n\t\tconst autoLabel = parsed.autoDetected ? ' (auto-detected)' : ''\n\n\t\tif (parsed.type === 'issue') {\n\t\t\treturn `issue #${parsed.number}${autoLabel}`\n\t\t}\n\t\tif (parsed.type === 'pr') {\n\t\t\treturn `PR #${parsed.number}${autoLabel}`\n\t\t}\n\t\treturn `branch \"${parsed.branchName}\"${autoLabel}`\n\t}\n\n\t/**\n\t * Format loom identifier for ILOOM_LOOM env var\n\t */\n\tprivate formatLoomIdentifier(parsed: ParsedShellInput): string {\n\t\tif (parsed.type === 'issue') {\n\t\t\treturn `issue-${parsed.number}`\n\t\t}\n\t\tif (parsed.type === 'pr') {\n\t\t\treturn `pr-${parsed.number}`\n\t\t}\n\t\treturn parsed.branchName ?? parsed.originalInput\n\t}\n\n\t/**\n\t * Detect shell based on platform and environment variables\n\t */\n\tprivate detectShell(): string {\n\t\t// ILOOM_SHELL takes highest priority\n\t\tif (process.env.ILOOM_SHELL) {\n\t\t\treturn process.env.ILOOM_SHELL\n\t\t}\n\n\t\t// Platform-specific detection\n\t\tif (process.platform === 'win32') {\n\t\t\t// Windows: prefer PowerShell, fall back to COMSPEC (cmd.exe)\n\t\t\treturn process.env.COMSPEC ?? 'cmd.exe'\n\t\t}\n\n\t\t// Unix/macOS: use SHELL or fall back to /bin/bash\n\t\treturn process.env.SHELL ?? '/bin/bash'\n\t}\n\n\t/**\n\t * Get list of existing dotenv-flow files in workspace\n\t */\n\tprivate async getExistingEnvFiles(workspacePath: string): Promise<string[]> {\n\t\tconst files = getDotenvFlowFiles()\n\t\tconst existing: string[] = []\n\n\t\tfor (const file of files) {\n\t\t\tconst fullPath = path.join(workspacePath, file)\n\t\t\tif (await fs.pathExists(fullPath)) {\n\t\t\t\texisting.push(file)\n\t\t\t}\n\t\t}\n\n\t\treturn existing\n\t}\n\n\t/**\n\t * Print summary of shell session\n\t */\n\tprivate printSummary(\n\t\tworkspacePath: string,\n\t\tshell: string,\n\t\tloadedEnvFiles: string[],\n\t\tenvVars: Record<string, string>,\n\t\tenvEnabled: boolean\n\t): void {\n\t\tlogger.info('Opening interactive shell')\n\t\tlogger.info(` Workspace: ${workspacePath}`)\n\t\tlogger.info(` Shell: ${shell}`)\n\n\t\tif (envEnabled) {\n\t\t\tif (loadedEnvFiles.length > 0) {\n\t\t\t\tlogger.info(` Env files: ${loadedEnvFiles.join(', ')}`)\n\t\t\t} else {\n\t\t\t\tlogger.info(' Env files: (none found)')\n\t\t\t}\n\n\t\t\t// Print key environment variables if present\n\t\t\tconst keyVars = ['PORT', 'DATABASE_URL', 'NODE_ENV']\n\t\t\tconst presentVars = keyVars.filter(v => envVars[v])\n\t\t\tif (presentVars.length > 0) {\n\t\t\t\tconst varSummary = presentVars.map(v => {\n\t\t\t\t\tconst value = envVars[v]\n\t\t\t\t\t// Truncate long values like DATABASE_URL\n\t\t\t\t\tconst displayValue = value && value.length > 40\n\t\t\t\t\t\t? value.substring(0, 37) + '...'\n\t\t\t\t\t\t: value\n\t\t\t\t\treturn `${v}=${displayValue}`\n\t\t\t\t}).join(', ')\n\t\t\t\tlogger.info(` Key vars: ${varSummary}`)\n\t\t\t}\n\t\t} else {\n\t\t\tlogger.info(' Env loading: disabled (set sourceEnvOnStart in settings to enable)')\n\t\t}\n\n\t\tlogger.info('')\n\t}\n}\n"],"mappings":"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","names":[]}
@@ -1,33 +1,35 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  SessionSummaryService
4
- } from "./chunk-3I4ONZRT.js";
4
+ } from "./chunk-6EU6TCF6.js";
5
5
  import "./chunk-NXMDEL3F.js";
6
6
  import {
7
7
  PRManager
8
- } from "./chunk-DGG2VY7B.js";
9
- import "./chunk-YETJNRQM.js";
10
- import "./chunk-ULSWCPQG.js";
11
- import "./chunk-FJDRTVJX.js";
8
+ } from "./chunk-ZW2LKWWE.js";
9
+ import "./chunk-JO2LZ6EQ.js";
10
+ import "./chunk-4232AHNQ.js";
12
11
  import {
13
12
  GitWorktreeManager
14
- } from "./chunk-TC7APDKU.js";
13
+ } from "./chunk-VGGST52X.js";
14
+ import "./chunk-YETJNRQM.js";
15
15
  import "./chunk-FXDYIV3K.js";
16
- import "./chunk-QN47QVBX.js";
16
+ import "./chunk-ONQYPICO.js";
17
+ import "./chunk-4WJNIR5O.js";
17
18
  import {
18
19
  extractIssueNumber
19
- } from "./chunk-AR5QKYNE.js";
20
+ } from "./chunk-MNHZB4Z2.js";
20
21
  import {
21
22
  SettingsManager
22
- } from "./chunk-RI2YL6TK.js";
23
+ } from "./chunk-YYAKPQBT.js";
23
24
  import {
24
25
  MetadataManager
25
- } from "./chunk-KBEIQP4G.js";
26
- import "./chunk-4CO6KG5S.js";
27
- import "./chunk-FO5GGFOV.js";
26
+ } from "./chunk-KB64WNBZ.js";
27
+ import "./chunk-HEXKPKCK.js";
28
+ import "./chunk-VG45TUYK.js";
28
29
  import {
29
30
  getLogger
30
31
  } from "./chunk-6MLEBAYZ.js";
32
+ import "./chunk-7JDMYTFZ.js";
31
33
  import "./chunk-VT4PDUYT.js";
32
34
 
33
35
  // src/commands/summary.ts
@@ -120,7 +122,7 @@ var SummaryCommand = class {
120
122
  * - Branch names: "my-feature-branch"
121
123
  */
122
124
  async findLoom(identifier) {
123
- var _a, _b, _c, _d, _e, _f;
125
+ var _a, _b, _c, _d, _e, _f, _g;
124
126
  const cleanId = identifier.replace(/^#/, "").trim();
125
127
  const prMatch = cleanId.match(/^pr\/(\d+)$/i);
126
128
  if (prMatch == null ? void 0 : prMatch[1]) {
@@ -145,7 +147,7 @@ var SummaryCommand = class {
145
147
  return {
146
148
  worktree: issueWorktree,
147
149
  loomType: (metadata == null ? void 0 : metadata.issueType) ?? "issue",
148
- issueNumber: ((_b = metadata == null ? void 0 : metadata.issue_numbers) == null ? void 0 : _b[0]) ?? String(issueNumber)
150
+ issueNumber: (metadata == null ? void 0 : metadata.issueKey) ?? ((_b = metadata == null ? void 0 : metadata.issue_numbers) == null ? void 0 : _b[0]) ?? String(issueNumber)
149
151
  };
150
152
  }
151
153
  const prWorktree = await this.gitWorktreeManager.findWorktreeForPR(issueNumber, "");
@@ -168,7 +170,7 @@ var SummaryCommand = class {
168
170
  return {
169
171
  worktree: issueWorktree,
170
172
  loomType: (metadata == null ? void 0 : metadata.issueType) ?? "issue",
171
- issueNumber: ((_d = metadata == null ? void 0 : metadata.issue_numbers) == null ? void 0 : _d[0]) ?? alphanumericId
173
+ issueNumber: (metadata == null ? void 0 : metadata.issueKey) ?? ((_d = metadata == null ? void 0 : metadata.issue_numbers) == null ? void 0 : _d[0]) ?? alphanumericId
172
174
  };
173
175
  }
174
176
  throw new Error(`No loom found for identifier: ${identifier}`);
@@ -178,9 +180,9 @@ var SummaryCommand = class {
178
180
  const metadata = await this.metadataManager.readMetadata(branchWorktree.path);
179
181
  const loomType = (metadata == null ? void 0 : metadata.issueType) ?? "branch";
180
182
  let issueNumber;
181
- if (loomType === "issue" && ((_e = metadata == null ? void 0 : metadata.issue_numbers) == null ? void 0 : _e[0])) {
182
- issueNumber = metadata.issue_numbers[0];
183
- } else if (loomType === "pr" && ((_f = metadata == null ? void 0 : metadata.pr_numbers) == null ? void 0 : _f[0])) {
183
+ if (loomType === "issue" && ((metadata == null ? void 0 : metadata.issueKey) || ((_e = metadata == null ? void 0 : metadata.issue_numbers) == null ? void 0 : _e[0]))) {
184
+ issueNumber = (metadata == null ? void 0 : metadata.issueKey) ?? ((_f = metadata == null ? void 0 : metadata.issue_numbers) == null ? void 0 : _f[0]);
185
+ } else if (loomType === "pr" && ((_g = metadata == null ? void 0 : metadata.pr_numbers) == null ? void 0 : _g[0])) {
184
186
  issueNumber = metadata.pr_numbers[0];
185
187
  }
186
188
  return {
@@ -202,7 +204,7 @@ var SummaryCommand = class {
202
204
  * 4. Fall back to using current branch as branch loom
203
205
  */
204
206
  async autoDetectFromCurrentDirectory() {
205
- var _a, _b, _c, _d, _e;
207
+ var _a, _b, _c, _d, _e, _f;
206
208
  const logger = getLogger();
207
209
  const currentDir = path.basename(process.cwd());
208
210
  const prPattern = /_pr_(\d+)$/;
@@ -230,7 +232,7 @@ var SummaryCommand = class {
230
232
  return {
231
233
  worktree,
232
234
  loomType: (metadata == null ? void 0 : metadata.issueType) ?? "issue",
233
- issueNumber: ((_b = metadata == null ? void 0 : metadata.issue_numbers) == null ? void 0 : _b[0]) ?? String(issueNumber)
235
+ issueNumber: (metadata == null ? void 0 : metadata.issueKey) ?? ((_b = metadata == null ? void 0 : metadata.issue_numbers) == null ? void 0 : _b[0]) ?? String(issueNumber)
234
236
  };
235
237
  }
236
238
  throw new Error(`No loom found for auto-detected issue #${issueNumber}`);
@@ -251,7 +253,7 @@ var SummaryCommand = class {
251
253
  return {
252
254
  worktree,
253
255
  loomType: (metadata == null ? void 0 : metadata.issueType) ?? "issue",
254
- issueNumber: ((_c = metadata == null ? void 0 : metadata.issue_numbers) == null ? void 0 : _c[0]) ?? String(branchIssueNumber)
256
+ issueNumber: (metadata == null ? void 0 : metadata.issueKey) ?? ((_c = metadata == null ? void 0 : metadata.issue_numbers) == null ? void 0 : _c[0]) ?? String(branchIssueNumber)
255
257
  };
256
258
  }
257
259
  }
@@ -260,9 +262,9 @@ var SummaryCommand = class {
260
262
  const metadata = await this.metadataManager.readMetadata(branchWorktree.path);
261
263
  const loomType = (metadata == null ? void 0 : metadata.issueType) ?? "branch";
262
264
  let resolvedIssueNumber;
263
- if (loomType === "issue" && ((_d = metadata == null ? void 0 : metadata.issue_numbers) == null ? void 0 : _d[0])) {
264
- resolvedIssueNumber = metadata.issue_numbers[0];
265
- } else if (loomType === "pr" && ((_e = metadata == null ? void 0 : metadata.pr_numbers) == null ? void 0 : _e[0])) {
265
+ if (loomType === "issue" && ((metadata == null ? void 0 : metadata.issueKey) || ((_d = metadata == null ? void 0 : metadata.issue_numbers) == null ? void 0 : _d[0]))) {
266
+ resolvedIssueNumber = (metadata == null ? void 0 : metadata.issueKey) ?? ((_e = metadata == null ? void 0 : metadata.issue_numbers) == null ? void 0 : _e[0]);
267
+ } else if (loomType === "pr" && ((_f = metadata == null ? void 0 : metadata.pr_numbers) == null ? void 0 : _f[0])) {
266
268
  resolvedIssueNumber = metadata.pr_numbers[0];
267
269
  }
268
270
  return {
@@ -280,4 +282,4 @@ Please provide an issue number, PR number, or branch name.`
280
282
  export {
281
283
  SummaryCommand
282
284
  };
283
- //# sourceMappingURL=summary-G2T4452H.js.map
285
+ //# sourceMappingURL=summary-FWHAX55O.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/summary.ts"],"sourcesContent":["import path from 'path'\nimport { GitWorktreeManager } from '../lib/GitWorktreeManager.js'\nimport { MetadataManager } from '../lib/MetadataManager.js'\nimport { SessionSummaryService } from '../lib/SessionSummaryService.js'\nimport { SettingsManager } from '../lib/SettingsManager.js'\nimport { PRManager } from '../lib/PRManager.js'\nimport { getLogger } from '../utils/logger-context.js'\nimport { extractIssueNumber } from '../utils/git.js'\nimport type { GitWorktree } from '../types/worktree.js'\nimport type { SummaryResult } from '../types/index.js'\n\n/**\n * Options for the summary command\n */\nexport interface SummaryOptions {\n\twithComment?: boolean\n\tjson?: boolean\n}\n\n/**\n * Input for the summary command\n */\nexport interface SummaryCommandInput {\n\tidentifier?: string | undefined\n\toptions: SummaryOptions\n}\n\n/**\n * Parsed input with loom information\n */\ninterface ParsedSummaryInput {\n\tworktree: GitWorktree\n\tloomType: 'issue' | 'pr' | 'branch' | 'epic'\n\tissueNumber?: string | number | undefined\n}\n\n/**\n * SummaryCommand - Generate and optionally post Claude session summaries\n *\n * This command allows generating the session summary without going through\n * the full `il finish` workflow. It can:\n * 1. Generate a summary and print it to stdout\n * 2. Optionally post the summary as a comment (--with-comment flag)\n */\nexport class SummaryCommand {\n\tconstructor(\n\t\tprivate gitWorktreeManager = new GitWorktreeManager(),\n\t\tprivate metadataManager = new MetadataManager(),\n\t\tprivate sessionSummaryService = new SessionSummaryService(),\n\t\tprivate settingsManager = new SettingsManager()\n\t) {}\n\n\t/**\n\t * Determine PR number based on merge mode and metadata\n\t * Returns undefined if should post to issue instead\n\t */\n\tprivate async getPRNumberForPosting(\n\t\tworktreePath: string,\n\t\tbranchName: string\n\t): Promise<number | undefined> {\n\t\tconst settings = await this.settingsManager.loadSettings(worktreePath)\n\t\tconst mergeMode = settings.mergeBehavior?.mode ?? 'local'\n\n\t\tif (mergeMode === 'github-draft-pr') {\n\t\t\tconst metadata = await this.metadataManager.readMetadata(worktreePath)\n\t\t\treturn metadata?.draftPrNumber ?? undefined\n\t\t}\n\n\t\tif (mergeMode === 'github-pr') {\n\t\t\tconst prManager = new PRManager(settings)\n\t\t\tconst existingPR = await prManager.checkForExistingPR(branchName, worktreePath)\n\t\t\treturn existingPR?.number\n\t\t}\n\n\t\treturn undefined // local mode - post to issue\n\t}\n\n\t/**\n\t * Execute the summary command\n\t *\n\t * @param input - Command input containing identifier and options\n\t * @returns SummaryResult when in JSON mode, void otherwise\n\t */\n\tasync execute(input: SummaryCommandInput): Promise<SummaryResult | void> {\n\t\tconst logger = getLogger()\n\n\t\t// 1. Find the loom by identifier (or auto-detect from current directory)\n\t\tconst parsed = input.identifier?.trim()\n\t\t\t? await this.findLoom(input.identifier.trim())\n\t\t\t: await this.autoDetectFromCurrentDirectory()\n\n\t\t// 2. Generate the summary (service handles session ID internally, including deterministic fallback)\n\t\tconst result = await this.sessionSummaryService.generateSummary(\n\t\t\tparsed.worktree.path,\n\t\t\tparsed.worktree.branch,\n\t\t\tparsed.loomType,\n\t\t\tparsed.issueNumber\n\t\t)\n\n\t\t// 4. Apply attribution if --with-comment is used (so output matches what will be posted)\n\t\tlet displaySummary = result.summary\n\t\tif (input.options.withComment && parsed.loomType !== 'branch') {\n\t\t\tdisplaySummary = await this.sessionSummaryService.applyAttribution(\n\t\t\t\tresult.summary,\n\t\t\t\tparsed.worktree.path\n\t\t\t)\n\t\t}\n\n\t\t// 5. In JSON mode, return the structured result\n\t\tif (input.options.json) {\n\t\t\tconst jsonResult: SummaryResult = {\n\t\t\t\tsummary: displaySummary,\n\t\t\t\tsessionId: result.sessionId,\n\t\t\t\tbranchName: parsed.worktree.branch,\n\t\t\t\tloomType: parsed.loomType,\n\t\t\t}\n\t\t\t// Only include issueNumber if defined\n\t\t\tif (parsed.issueNumber !== undefined) {\n\t\t\t\tjsonResult.issueNumber = parsed.issueNumber\n\t\t\t}\n\t\t\treturn jsonResult\n\t\t}\n\n\t\t// 6. Print the summary to stdout (intentionally using console.log for piping/redirection)\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.log(displaySummary)\n\n\t\t// 7. Optionally post the summary as a comment\n\t\tif (input.options.withComment) {\n\t\t\t// Skip posting for branch type looms (no issue to comment on)\n\t\t\tif (parsed.loomType === 'branch') {\n\t\t\t\tlogger.debug('Skipping comment posting: branch type looms have no associated issue')\n\t\t\t} else if (parsed.issueNumber !== undefined) {\n\t\t\t\t// Determine if we should post to PR instead of issue\n\t\t\t\tconst prNumber = await this.getPRNumberForPosting(\n\t\t\t\t\tparsed.worktree.path,\n\t\t\t\t\tparsed.worktree.branch\n\t\t\t\t)\n\t\t\t\tawait this.sessionSummaryService.postSummary(\n\t\t\t\t\tparsed.issueNumber,\n\t\t\t\t\tresult.summary,\n\t\t\t\t\tparsed.worktree.path,\n\t\t\t\t\tprNumber\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Find a loom by identifier\n\t *\n\t * Supports:\n\t * - Numeric identifiers (issue numbers): \"123\", \"#123\"\n\t * - PR identifiers: \"pr/123\"\n\t * - Branch names: \"my-feature-branch\"\n\t */\n\tprivate async findLoom(identifier: string): Promise<ParsedSummaryInput> {\n\t\t// Remove # prefix if present and trim whitespace\n\t\tconst cleanId = identifier.replace(/^#/, '').trim()\n\n\t\t// Check for PR pattern: pr/123 or PR/123\n\t\tconst prMatch = cleanId.match(/^pr\\/(\\d+)$/i)\n\t\tif (prMatch?.[1]) {\n\t\t\tconst prNumber = parseInt(prMatch[1], 10)\n\t\t\tconst worktree = await this.gitWorktreeManager.findWorktreeForPR(prNumber, '')\n\t\t\tif (worktree) {\n\t\t\t\tconst metadata = await this.metadataManager.readMetadata(worktree.path)\n\t\t\t\treturn {\n\t\t\t\t\tworktree,\n\t\t\t\t\tloomType: 'pr',\n\t\t\t\t\tissueNumber: metadata?.pr_numbers?.[0] ?? String(prNumber),\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow new Error(`No loom found for identifier: ${identifier}`)\n\t\t}\n\n\t\t// Check if input is numeric (issue number)\n\t\tconst numericMatch = cleanId.match(/^(\\d+)$/)\n\t\tif (numericMatch?.[1]) {\n\t\t\tconst issueNumber = parseInt(numericMatch[1], 10)\n\n\t\t\t// Try issue first\n\t\t\tconst issueWorktree = await this.gitWorktreeManager.findWorktreeForIssue(issueNumber)\n\t\t\tif (issueWorktree) {\n\t\t\t\tconst metadata = await this.metadataManager.readMetadata(issueWorktree.path)\n\t\t\t\treturn {\n\t\t\t\t\tworktree: issueWorktree,\n\t\t\t\t\tloomType: metadata?.issueType ?? 'issue',\n\t\t\t\t\tissueNumber: metadata?.issueKey ?? metadata?.issue_numbers?.[0] ?? String(issueNumber),\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Then try PR\n\t\t\tconst prWorktree = await this.gitWorktreeManager.findWorktreeForPR(issueNumber, '')\n\t\t\tif (prWorktree) {\n\t\t\t\tconst metadata = await this.metadataManager.readMetadata(prWorktree.path)\n\t\t\t\treturn {\n\t\t\t\t\tworktree: prWorktree,\n\t\t\t\t\tloomType: 'pr',\n\t\t\t\t\tissueNumber: metadata?.pr_numbers?.[0] ?? String(issueNumber),\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthrow new Error(`No loom found for identifier: ${identifier}`)\n\t\t}\n\n\t\t// Check for alphanumeric issue identifier (Linear/Jira style: ABC-123)\n\t\tconst alphanumericMatch = cleanId.match(/^([A-Za-z]+-\\d+)$/)\n\t\tif (alphanumericMatch?.[1]) {\n\t\t\tconst alphanumericId = alphanumericMatch[1]\n\t\t\tconst issueWorktree = await this.gitWorktreeManager.findWorktreeForIssue(alphanumericId)\n\t\t\tif (issueWorktree) {\n\t\t\t\tconst metadata = await this.metadataManager.readMetadata(issueWorktree.path)\n\t\t\t\treturn {\n\t\t\t\t\tworktree: issueWorktree,\n\t\t\t\t\tloomType: metadata?.issueType ?? 'issue',\n\t\t\t\t\tissueNumber: metadata?.issueKey ?? metadata?.issue_numbers?.[0] ?? alphanumericId,\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow new Error(`No loom found for identifier: ${identifier}`)\n\t\t}\n\n\t\t// Treat as branch name\n\t\tconst branchWorktree = await this.gitWorktreeManager.findWorktreeForBranch(cleanId)\n\t\tif (branchWorktree) {\n\t\t\tconst metadata = await this.metadataManager.readMetadata(branchWorktree.path)\n\t\t\tconst loomType = metadata?.issueType ?? 'branch'\n\n\t\t\t// For branch looms, try to get issue number from metadata\n\t\t\tlet issueNumber: string | number | undefined\n\t\t\tif (loomType === 'issue' && (metadata?.issueKey || metadata?.issue_numbers?.[0])) {\n\t\t\t\tissueNumber = metadata?.issueKey ?? metadata?.issue_numbers?.[0]\n\t\t\t} else if (loomType === 'pr' && metadata?.pr_numbers?.[0]) {\n\t\t\t\tissueNumber = metadata.pr_numbers[0]\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tworktree: branchWorktree,\n\t\t\t\tloomType,\n\t\t\t\tissueNumber,\n\t\t\t}\n\t\t}\n\n\t\tthrow new Error(`No loom found for identifier: ${identifier}`)\n\t}\n\n\t/**\n\t * Auto-detect loom from current working directory\n\t * Ports logic from FinishCommand.autoDetectFromCurrentDirectory()\n\t *\n\t * Detection strategy:\n\t * 1. Check current directory name for PR pattern (_pr_N suffix)\n\t * 2. Check current directory name for issue pattern (issue-N or -N-)\n\t * 3. Get current branch and check for issue pattern\n\t * 4. Fall back to using current branch as branch loom\n\t */\n\tprivate async autoDetectFromCurrentDirectory(): Promise<ParsedSummaryInput> {\n\t\tconst logger = getLogger()\n\t\tconst currentDir = path.basename(process.cwd())\n\n\t\t// Check for PR worktree pattern: _pr_N suffix\n\t\tconst prPattern = /_pr_(\\d+)$/\n\t\tconst prMatch = currentDir.match(prPattern)\n\n\t\tif (prMatch?.[1]) {\n\t\t\tconst prNumber = parseInt(prMatch[1], 10)\n\t\t\tlogger.debug(`Auto-detected PR #${prNumber} from directory: ${currentDir}`)\n\n\t\t\tconst worktree = await this.gitWorktreeManager.findWorktreeForPR(prNumber, '')\n\t\t\tif (worktree) {\n\t\t\t\tconst metadata = await this.metadataManager.readMetadata(worktree.path)\n\t\t\t\treturn {\n\t\t\t\t\tworktree,\n\t\t\t\t\tloomType: 'pr',\n\t\t\t\t\tissueNumber: metadata?.pr_numbers?.[0] ?? String(prNumber),\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow new Error(`No loom found for auto-detected PR #${prNumber}`)\n\t\t}\n\n\t\t// Check for issue pattern in directory name\n\t\tconst issueNumber = extractIssueNumber(currentDir)\n\n\t\tif (issueNumber !== null) {\n\t\t\tlogger.debug(`Auto-detected issue #${issueNumber} from directory: ${currentDir}`)\n\n\t\t\tconst worktree = await this.gitWorktreeManager.findWorktreeForIssue(issueNumber)\n\t\t\tif (worktree) {\n\t\t\t\tconst metadata = await this.metadataManager.readMetadata(worktree.path)\n\t\t\t\treturn {\n\t\t\t\t\tworktree,\n\t\t\t\t\tloomType: metadata?.issueType ?? 'issue',\n\t\t\t\t\tissueNumber: metadata?.issueKey ?? metadata?.issue_numbers?.[0] ?? String(issueNumber),\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow new Error(`No loom found for auto-detected issue #${issueNumber}`)\n\t\t}\n\n\t\t// Fallback: get current branch name\n\t\tconst repoInfo = await this.gitWorktreeManager.getRepoInfo()\n\t\tconst currentBranch = repoInfo.currentBranch\n\n\t\tif (!currentBranch) {\n\t\t\tthrow new Error(\n\t\t\t\t'Could not auto-detect loom. Please provide an issue number, PR number, or branch name.\\n' +\n\t\t\t\t'Expected directory pattern: feat/issue-XX-description OR worktree with _pr_N suffix'\n\t\t\t)\n\t\t}\n\n\t\t// Try to extract issue from branch name\n\t\tconst branchIssueNumber = extractIssueNumber(currentBranch)\n\t\tif (branchIssueNumber !== null) {\n\t\t\tlogger.debug(`Auto-detected issue #${branchIssueNumber} from branch: ${currentBranch}`)\n\n\t\t\tconst worktree = await this.gitWorktreeManager.findWorktreeForIssue(branchIssueNumber)\n\t\t\tif (worktree) {\n\t\t\t\tconst metadata = await this.metadataManager.readMetadata(worktree.path)\n\t\t\t\treturn {\n\t\t\t\t\tworktree,\n\t\t\t\t\tloomType: metadata?.issueType ?? 'issue',\n\t\t\t\t\tissueNumber: metadata?.issueKey ?? metadata?.issue_numbers?.[0] ?? String(branchIssueNumber),\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Last resort: use current branch as branch loom\n\t\tconst branchWorktree = await this.gitWorktreeManager.findWorktreeForBranch(currentBranch)\n\t\tif (branchWorktree) {\n\t\t\tconst metadata = await this.metadataManager.readMetadata(branchWorktree.path)\n\t\t\tconst loomType = metadata?.issueType ?? 'branch'\n\n\t\t\t// For branch looms, try to get issue number from metadata\n\t\t\tlet resolvedIssueNumber: string | number | undefined\n\t\t\tif (loomType === 'issue' && (metadata?.issueKey || metadata?.issue_numbers?.[0])) {\n\t\t\t\tresolvedIssueNumber = metadata?.issueKey ?? metadata?.issue_numbers?.[0]\n\t\t\t} else if (loomType === 'pr' && metadata?.pr_numbers?.[0]) {\n\t\t\t\tresolvedIssueNumber = metadata.pr_numbers[0]\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tworktree: branchWorktree,\n\t\t\t\tloomType,\n\t\t\t\tissueNumber: resolvedIssueNumber,\n\t\t\t}\n\t\t}\n\n\t\tthrow new Error(\n\t\t\t`Could not auto-detect loom from current directory or branch: ${currentBranch}\\n` +\n\t\t\t'Please provide an issue number, PR number, or branch name.'\n\t\t)\n\t}\n}\n"],"mappings":"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","names":[]}
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ScriptCommandBase
4
- } from "./chunk-KJTVU3HZ.js";
5
- import "./chunk-YKFCCV6S.js";
6
- import "./chunk-4LKGCFGG.js";
7
- import "./chunk-TC7APDKU.js";
8
- import "./chunk-VOGGLPG5.js";
9
- import "./chunk-AR5QKYNE.js";
10
- import "./chunk-RI2YL6TK.js";
11
- import "./chunk-KBEIQP4G.js";
4
+ } from "./chunk-NRSWLOAZ.js";
5
+ import "./chunk-WWKOVDWC.js";
6
+ import "./chunk-WY4QBK43.js";
7
+ import "./chunk-VGGST52X.js";
8
+ import "./chunk-YQ57ORTV.js";
9
+ import "./chunk-MNHZB4Z2.js";
10
+ import "./chunk-YYAKPQBT.js";
11
+ import "./chunk-KB64WNBZ.js";
12
12
  import "./chunk-6MLEBAYZ.js";
13
13
  import "./chunk-VT4PDUYT.js";
14
14
 
@@ -24,4 +24,4 @@ var TestCommand = class extends ScriptCommandBase {
24
24
  export {
25
25
  TestCommand
26
26
  };
27
- //# sourceMappingURL=test-EA5NQFDC.js.map
27
+ //# sourceMappingURL=test-F7JNJZYP.js.map