@iloom/cli 0.13.2 → 0.13.4

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 (169) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +1 -1
  3. package/dist/{BranchNamingService-MEK2WZUD.js → BranchNamingService-PBP6DY3H.js} +2 -2
  4. package/dist/{ClaudeContextManager-KJ4VEA2F.js → ClaudeContextManager-3HT4LEIU.js} +5 -5
  5. package/dist/{ClaudeService-WTJO4UW6.js → ClaudeService-7BHL2GWC.js} +4 -4
  6. package/dist/{IssueTrackerFactory-UEJALI4X.js → IssueTrackerFactory-JH34S4GX.js} +3 -3
  7. package/dist/{LoomLauncher-KG2VBNQA.js → LoomLauncher-RGXJOCMC.js} +8 -5
  8. package/dist/LoomLauncher-RGXJOCMC.js.map +1 -0
  9. package/dist/{MetadataManager-HHE6LQF2.js → MetadataManager-WKM7JJIO.js} +2 -2
  10. package/dist/README.md +1 -1
  11. package/dist/{SettingsManager-PVHBSCMI.js → SettingsManager-Y5OU5HCX.js} +4 -2
  12. package/dist/agents/CLAUDE.md +12 -7
  13. package/dist/agents/iloom-code-reviewer.md +2 -1
  14. package/dist/agents/iloom-framework-detector.md +56 -9
  15. package/dist/agents/iloom-issue-analyze-and-plan.md +1 -0
  16. package/dist/agents/iloom-issue-analyzer.md +1 -0
  17. package/dist/agents/iloom-issue-complexity-evaluator.md +1 -0
  18. package/dist/agents/iloom-issue-enhancer.md +2 -1
  19. package/dist/agents/iloom-issue-implementer.md +4 -1
  20. package/dist/agents/iloom-issue-planner.md +2 -1
  21. package/dist/agents/iloom-wave-verifier.md +1 -0
  22. package/dist/{build-2FXDYEZQ.js → build-NJJT6UHO.js} +7 -7
  23. package/dist/{chunk-VUIPDX3T.js → chunk-27CQSBUG.js} +2 -2
  24. package/dist/{chunk-YVNG35OW.js → chunk-2Z4VKQND.js} +2 -2
  25. package/dist/{chunk-UQWMPQ2Q.js → chunk-4QROZMPZ.js} +3 -3
  26. package/dist/{chunk-U2OPXZ6E.js → chunk-5NVJ6N3C.js} +7 -7
  27. package/dist/{chunk-2WRD6Y5E.js → chunk-5VP2HAWF.js} +2 -2
  28. package/dist/{chunk-CQHHEW2M.js → chunk-5WJN63T4.js} +1 -1
  29. package/dist/chunk-5WJN63T4.js.map +1 -0
  30. package/dist/{chunk-H4TSDALC.js → chunk-64K5SZXC.js} +6 -6
  31. package/dist/{chunk-5W44AI63.js → chunk-6FHFHMNF.js} +4 -4
  32. package/dist/{chunk-XC5JKRSH.js → chunk-6RKZDUTQ.js} +2 -2
  33. package/dist/{chunk-RP6MHV24.js → chunk-7VSOM25S.js} +20 -15
  34. package/dist/chunk-7VSOM25S.js.map +1 -0
  35. package/dist/{chunk-UMAOVKQX.js → chunk-CSJ7JNJV.js} +3 -3
  36. package/dist/{chunk-AQUSMNBF.js → chunk-CWRQ4NU4.js} +2 -2
  37. package/dist/{chunk-R2EFSRKR.js → chunk-EBPFEM5X.js} +16 -15
  38. package/dist/chunk-EBPFEM5X.js.map +1 -0
  39. package/dist/{chunk-OMV47LLA.js → chunk-FPM6XDEO.js} +2 -2
  40. package/dist/{chunk-DYLOITSO.js → chunk-HMMDNIKG.js} +38 -31
  41. package/dist/chunk-HMMDNIKG.js.map +1 -0
  42. package/dist/{chunk-XIVLGWUX.js → chunk-JDXJIPXR.js} +3 -1
  43. package/dist/chunk-JDXJIPXR.js.map +1 -0
  44. package/dist/{chunk-ZWXJ7G2C.js → chunk-JIMFSNZI.js} +2 -2
  45. package/dist/{chunk-D6FU4DLN.js → chunk-LULQYBRA.js} +2 -2
  46. package/dist/{chunk-DDHWZNGL.js → chunk-MB4CB7Q4.js} +6 -5
  47. package/dist/chunk-MB4CB7Q4.js.map +1 -0
  48. package/dist/{chunk-OHX3PSAY.js → chunk-MZPVETJH.js} +7 -15
  49. package/dist/chunk-MZPVETJH.js.map +1 -0
  50. package/dist/{chunk-OIJNBFMP.js → chunk-OSWL7YDO.js} +2 -2
  51. package/dist/{chunk-32D4CWWH.js → chunk-R2RGFNR4.js} +2 -2
  52. package/dist/{chunk-MPHSR6GA.js → chunk-R4Y2ZBOL.js} +5 -5
  53. package/dist/{chunk-L3P3YJCE.js → chunk-RLFS5KHU.js} +3 -3
  54. package/dist/{chunk-DMNI225H.js → chunk-SM2YM3YR.js} +4 -4
  55. package/dist/{chunk-MNPKEWBQ.js → chunk-UVZBZ5IF.js} +52 -1
  56. package/dist/chunk-UVZBZ5IF.js.map +1 -0
  57. package/dist/{chunk-Y2JHYPMX.js → chunk-VG7UFVF2.js} +47 -35
  58. package/dist/chunk-VG7UFVF2.js.map +1 -0
  59. package/dist/{chunk-OVW26FHW.js → chunk-VQ3Y3PVT.js} +2 -2
  60. package/dist/{chunk-PH65MFQM.js → chunk-Y2TPRF5H.js} +3 -3
  61. package/dist/{claude-ACL7G4CF.js → claude-IYLIOOP7.js} +2 -2
  62. package/dist/{cleanup-I62RA5TZ.js → cleanup-Q6PEKMVF.js} +18 -18
  63. package/dist/cli.js +93 -77
  64. package/dist/cli.js.map +1 -1
  65. package/dist/{commit-7RI2JFFW.js → commit-JKZQYNEB.js} +8 -8
  66. package/dist/{compile-NWTMKAGL.js → compile-QEMZDLKO.js} +7 -7
  67. package/dist/{contribute-QWPOT4QR.js → contribute-TCEOVFDN.js} +4 -4
  68. package/dist/{dev-server-OZ6KKKTR.js → dev-server-25BIZKTB.js} +12 -12
  69. package/dist/{feedback-G63MODT2.js → feedback-CQ42GFZE.js} +7 -7
  70. package/dist/{git-ZTMT6OAI.js → git-HWDX2KWU.js} +4 -4
  71. package/dist/{ignite-GUYKYC5G.js → ignite-25QLX2FS.js} +13 -13
  72. package/dist/index.d.ts +1764 -1709
  73. package/dist/index.js +105 -8
  74. package/dist/index.js.map +1 -1
  75. package/dist/{init-AMLCFVXG.js → init-LRNRRFFU.js} +8 -8
  76. package/dist/{install-deps-XS2UUCUS.js → install-deps-DHFHT3KI.js} +7 -7
  77. package/dist/{issues-2IT7PSNZ.js → issues-W722ILMI.js} +5 -5
  78. package/dist/{lint-DKWJHET3.js → lint-TZDEPVKN.js} +7 -7
  79. package/dist/mcp/issue-management-server.js +39 -0
  80. package/dist/mcp/issue-management-server.js.map +1 -1
  81. package/dist/mcp/recap-server.js +2 -2
  82. package/dist/mcp/recap-server.js.map +1 -1
  83. package/dist/{open-6PXNIPXS.js → open-BCQSZYAD.js} +12 -12
  84. package/dist/{plan-NJVQBBT3.js → plan-2LUGSOYG.js} +30 -28
  85. package/dist/plan-2LUGSOYG.js.map +1 -0
  86. package/dist/{projects-3F6T3KZL.js → projects-INTNTWRM.js} +2 -2
  87. package/dist/prompts/init-prompt.txt +72 -4
  88. package/dist/prompts/issue-prompt.txt +6 -3
  89. package/dist/prompts/pr-prompt.txt +3 -2
  90. package/dist/prompts/regular-prompt.txt +3 -2
  91. package/dist/prompts/session-summary-prompt.txt +2 -1
  92. package/dist/prompts/swarm-orchestrator-prompt.txt +2 -2
  93. package/dist/{rebase-6AXN45AE.js → rebase-ZKZKKQKB.js} +7 -7
  94. package/dist/{recap-XDKI3MTA.js → recap-XXLLMETY.js} +7 -7
  95. package/dist/{run-RHE5NPDT.js → run-5P5ULYZY.js} +12 -12
  96. package/dist/schema/settings.schema.json +50 -0
  97. package/dist/{shell-XOILFEZW.js → shell-GNDHII2J.js} +6 -6
  98. package/dist/{summary-BVYOM63C.js → summary-TVLBZNKY.js} +10 -10
  99. package/dist/{test-6T2UMQ7T.js → test-T5K7FOKQ.js} +7 -7
  100. package/dist/{test-git-CQ65OL45.js → test-git-AQ3ZQ4RA.js} +4 -4
  101. package/dist/{test-jira-CQQHGZ3S.js → test-jira-7XQ63U2C.js} +3 -3
  102. package/dist/{test-prefix-HMTZSS67.js → test-prefix-OTY2HBSB.js} +4 -4
  103. package/dist/{test-webserver-ZN73CM2T.js → test-webserver-CPQMUCDD.js} +6 -6
  104. package/dist/{vscode-ABQ5ZSH7.js → vscode-M4KRTKZK.js} +6 -6
  105. package/package.json +1 -1
  106. package/dist/LoomLauncher-KG2VBNQA.js.map +0 -1
  107. package/dist/chunk-CQHHEW2M.js.map +0 -1
  108. package/dist/chunk-DDHWZNGL.js.map +0 -1
  109. package/dist/chunk-DYLOITSO.js.map +0 -1
  110. package/dist/chunk-MNPKEWBQ.js.map +0 -1
  111. package/dist/chunk-OHX3PSAY.js.map +0 -1
  112. package/dist/chunk-R2EFSRKR.js.map +0 -1
  113. package/dist/chunk-RP6MHV24.js.map +0 -1
  114. package/dist/chunk-XIVLGWUX.js.map +0 -1
  115. package/dist/chunk-Y2JHYPMX.js.map +0 -1
  116. package/dist/plan-NJVQBBT3.js.map +0 -1
  117. /package/dist/{BranchNamingService-MEK2WZUD.js.map → BranchNamingService-PBP6DY3H.js.map} +0 -0
  118. /package/dist/{ClaudeContextManager-KJ4VEA2F.js.map → ClaudeContextManager-3HT4LEIU.js.map} +0 -0
  119. /package/dist/{ClaudeService-WTJO4UW6.js.map → ClaudeService-7BHL2GWC.js.map} +0 -0
  120. /package/dist/{IssueTrackerFactory-UEJALI4X.js.map → IssueTrackerFactory-JH34S4GX.js.map} +0 -0
  121. /package/dist/{MetadataManager-HHE6LQF2.js.map → MetadataManager-WKM7JJIO.js.map} +0 -0
  122. /package/dist/{SettingsManager-PVHBSCMI.js.map → SettingsManager-Y5OU5HCX.js.map} +0 -0
  123. /package/dist/{build-2FXDYEZQ.js.map → build-NJJT6UHO.js.map} +0 -0
  124. /package/dist/{chunk-VUIPDX3T.js.map → chunk-27CQSBUG.js.map} +0 -0
  125. /package/dist/{chunk-YVNG35OW.js.map → chunk-2Z4VKQND.js.map} +0 -0
  126. /package/dist/{chunk-UQWMPQ2Q.js.map → chunk-4QROZMPZ.js.map} +0 -0
  127. /package/dist/{chunk-U2OPXZ6E.js.map → chunk-5NVJ6N3C.js.map} +0 -0
  128. /package/dist/{chunk-2WRD6Y5E.js.map → chunk-5VP2HAWF.js.map} +0 -0
  129. /package/dist/{chunk-H4TSDALC.js.map → chunk-64K5SZXC.js.map} +0 -0
  130. /package/dist/{chunk-5W44AI63.js.map → chunk-6FHFHMNF.js.map} +0 -0
  131. /package/dist/{chunk-XC5JKRSH.js.map → chunk-6RKZDUTQ.js.map} +0 -0
  132. /package/dist/{chunk-UMAOVKQX.js.map → chunk-CSJ7JNJV.js.map} +0 -0
  133. /package/dist/{chunk-AQUSMNBF.js.map → chunk-CWRQ4NU4.js.map} +0 -0
  134. /package/dist/{chunk-OMV47LLA.js.map → chunk-FPM6XDEO.js.map} +0 -0
  135. /package/dist/{chunk-ZWXJ7G2C.js.map → chunk-JIMFSNZI.js.map} +0 -0
  136. /package/dist/{chunk-D6FU4DLN.js.map → chunk-LULQYBRA.js.map} +0 -0
  137. /package/dist/{chunk-OIJNBFMP.js.map → chunk-OSWL7YDO.js.map} +0 -0
  138. /package/dist/{chunk-32D4CWWH.js.map → chunk-R2RGFNR4.js.map} +0 -0
  139. /package/dist/{chunk-MPHSR6GA.js.map → chunk-R4Y2ZBOL.js.map} +0 -0
  140. /package/dist/{chunk-L3P3YJCE.js.map → chunk-RLFS5KHU.js.map} +0 -0
  141. /package/dist/{chunk-DMNI225H.js.map → chunk-SM2YM3YR.js.map} +0 -0
  142. /package/dist/{chunk-OVW26FHW.js.map → chunk-VQ3Y3PVT.js.map} +0 -0
  143. /package/dist/{chunk-PH65MFQM.js.map → chunk-Y2TPRF5H.js.map} +0 -0
  144. /package/dist/{claude-ACL7G4CF.js.map → claude-IYLIOOP7.js.map} +0 -0
  145. /package/dist/{cleanup-I62RA5TZ.js.map → cleanup-Q6PEKMVF.js.map} +0 -0
  146. /package/dist/{commit-7RI2JFFW.js.map → commit-JKZQYNEB.js.map} +0 -0
  147. /package/dist/{compile-NWTMKAGL.js.map → compile-QEMZDLKO.js.map} +0 -0
  148. /package/dist/{contribute-QWPOT4QR.js.map → contribute-TCEOVFDN.js.map} +0 -0
  149. /package/dist/{dev-server-OZ6KKKTR.js.map → dev-server-25BIZKTB.js.map} +0 -0
  150. /package/dist/{feedback-G63MODT2.js.map → feedback-CQ42GFZE.js.map} +0 -0
  151. /package/dist/{git-ZTMT6OAI.js.map → git-HWDX2KWU.js.map} +0 -0
  152. /package/dist/{ignite-GUYKYC5G.js.map → ignite-25QLX2FS.js.map} +0 -0
  153. /package/dist/{init-AMLCFVXG.js.map → init-LRNRRFFU.js.map} +0 -0
  154. /package/dist/{install-deps-XS2UUCUS.js.map → install-deps-DHFHT3KI.js.map} +0 -0
  155. /package/dist/{issues-2IT7PSNZ.js.map → issues-W722ILMI.js.map} +0 -0
  156. /package/dist/{lint-DKWJHET3.js.map → lint-TZDEPVKN.js.map} +0 -0
  157. /package/dist/{open-6PXNIPXS.js.map → open-BCQSZYAD.js.map} +0 -0
  158. /package/dist/{projects-3F6T3KZL.js.map → projects-INTNTWRM.js.map} +0 -0
  159. /package/dist/{rebase-6AXN45AE.js.map → rebase-ZKZKKQKB.js.map} +0 -0
  160. /package/dist/{recap-XDKI3MTA.js.map → recap-XXLLMETY.js.map} +0 -0
  161. /package/dist/{run-RHE5NPDT.js.map → run-5P5ULYZY.js.map} +0 -0
  162. /package/dist/{shell-XOILFEZW.js.map → shell-GNDHII2J.js.map} +0 -0
  163. /package/dist/{summary-BVYOM63C.js.map → summary-TVLBZNKY.js.map} +0 -0
  164. /package/dist/{test-6T2UMQ7T.js.map → test-T5K7FOKQ.js.map} +0 -0
  165. /package/dist/{test-git-CQ65OL45.js.map → test-git-AQ3ZQ4RA.js.map} +0 -0
  166. /package/dist/{test-jira-CQQHGZ3S.js.map → test-jira-7XQ63U2C.js.map} +0 -0
  167. /package/dist/{test-prefix-HMTZSS67.js.map → test-prefix-OTY2HBSB.js.map} +0 -0
  168. /package/dist/{test-webserver-ZN73CM2T.js.map → test-webserver-CPQMUCDD.js.map} +0 -0
  169. /package/dist/{vscode-ABQ5ZSH7.js.map → vscode-M4KRTKZK.js.map} +0 -0
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ProcessManager
4
- } from "./chunk-2WRD6Y5E.js";
5
- import "./chunk-YVNG35OW.js";
6
- import "./chunk-5W44AI63.js";
4
+ } from "./chunk-5VP2HAWF.js";
5
+ import "./chunk-2Z4VKQND.js";
6
+ import "./chunk-6FHFHMNF.js";
7
7
  import {
8
8
  SettingsManager
9
- } from "./chunk-MNPKEWBQ.js";
10
- import "./chunk-XIVLGWUX.js";
9
+ } from "./chunk-UVZBZ5IF.js";
10
+ import "./chunk-JDXJIPXR.js";
11
11
  import "./chunk-FTYWGQFM.js";
12
12
  import {
13
13
  logger
@@ -81,4 +81,4 @@ var TestWebserverCommand = class {
81
81
  export {
82
82
  TestWebserverCommand
83
83
  };
84
- //# sourceMappingURL=test-webserver-ZN73CM2T.js.map
84
+ //# sourceMappingURL=test-webserver-CPQMUCDD.js.map
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  IdentifierParser
4
- } from "./chunk-XC5JKRSH.js";
4
+ } from "./chunk-6RKZDUTQ.js";
5
5
  import {
6
6
  GitWorktreeManager
7
- } from "./chunk-D6FU4DLN.js";
7
+ } from "./chunk-LULQYBRA.js";
8
8
  import {
9
9
  getInstallHint,
10
10
  isIdeAvailable
@@ -14,9 +14,9 @@ import {
14
14
  } from "./chunk-NPVA65KS.js";
15
15
  import {
16
16
  extractIssueNumber
17
- } from "./chunk-5W44AI63.js";
18
- import "./chunk-MNPKEWBQ.js";
19
- import "./chunk-XIVLGWUX.js";
17
+ } from "./chunk-6FHFHMNF.js";
18
+ import "./chunk-UVZBZ5IF.js";
19
+ import "./chunk-JDXJIPXR.js";
20
20
  import "./chunk-FTYWGQFM.js";
21
21
  import {
22
22
  logger
@@ -161,4 +161,4 @@ var VSCodeCommand = class {
161
161
  export {
162
162
  VSCodeCommand
163
163
  };
164
- //# sourceMappingURL=vscode-ABQ5ZSH7.js.map
164
+ //# sourceMappingURL=vscode-M4KRTKZK.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iloom/cli",
3
- "version": "0.13.2",
3
+ "version": "0.13.4",
4
4
  "description": "Control plane for maintaining alignment between you and Claude Code as you work across multiple issues using isolated environments, visible context, and multi-agent workflows to scale understanding, not just output",
5
5
  "keywords": [
6
6
  "ai",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/lib/LoomLauncher.ts"],"sourcesContent":["import { existsSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { openTerminalWindow, openMultipleTerminalWindows } from '../utils/terminal.js'\nimport type { TerminalWindowOptions } from '../utils/terminal.js'\nimport { openIdeWindow } from '../utils/ide.js'\nimport { generateColorFromBranchName, hexToRgb } from '../utils/color.js'\nimport { getLogger } from '../utils/logger-context.js'\nimport { ClaudeContextManager } from './ClaudeContextManager.js'\nimport type { SettingsManager } from './SettingsManager.js'\nimport type { Capability } from '../types/loom.js'\nimport { getDotenvFlowFiles } from '../utils/env.js'\nimport { getExecutablePath } from '../utils/cli-overrides.js'\n\nexport interface LaunchLoomOptions {\n\tenableClaude: boolean\n\tenableCode: boolean\n\tenableDevServer: boolean\n\tenableTerminal: boolean\n\tworktreePath: string\n\tbranchName: string\n\tport?: number\n\tcapabilities: Capability[]\n\tworkflowType: 'issue' | 'pr' | 'regular'\n\tidentifier: string | number\n\ttitle?: string\n\toneShot?: import('../types/index.js').OneShotMode\n\tsetArguments?: string[] // Raw --set arguments to forward\n\texecutablePath?: string // Executable path to use for spin command\n\tsourceEnvOnStart?: boolean // defaults to false if undefined\n\tcolorTerminal?: boolean // defaults to true if undefined\n\tcolorHex?: string // Pre-calculated hex color from metadata, avoids recalculation\n\tcomplexity?: import('../types/index.js').ComplexityOverride\n}\n\n/**\n * LoomLauncher orchestrates opening loom components\n */\nexport class LoomLauncher {\n\tprivate claudeContext: ClaudeContextManager\n\tprivate settings?: SettingsManager\n\n\tconstructor(claudeContext?: ClaudeContextManager, settings?: SettingsManager) {\n\t\tthis.claudeContext = claudeContext ?? new ClaudeContextManager()\n\t\tif (settings !== undefined) {\n\t\t\tthis.settings = settings\n\t\t}\n\t}\n\n\t/**\n\t * Launch loom components based on individual flags\n\t */\n\tasync launchLoom(options: LaunchLoomOptions): Promise<void> {\n\t\tconst { enableClaude, enableCode, enableDevServer, enableTerminal } = options\n\n\t\tgetLogger().debug(`Launching loom components: Claude=${enableClaude}, Code=${enableCode}, DevServer=${enableDevServer}, Terminal=${enableTerminal}`)\n\n\t\tconst launchPromises: Promise<void>[] = []\n\n\t\t// Launch VSCode if enabled\n\t\tif (enableCode) {\n\t\t\tgetLogger().debug('Launching VSCode')\n\t\t\tlaunchPromises.push(this.launchVSCode(options))\n\t\t}\n\n\t\t// Build array of terminals to launch\n\t\tconst terminalsToLaunch: Array<{\n\t\t\ttype: 'claude' | 'devServer' | 'terminal'\n\t\t\toptions: TerminalWindowOptions\n\t\t}> = []\n\n\t\tif (enableDevServer) {\n\t\t\tterminalsToLaunch.push({\n\t\t\t\ttype: 'devServer',\n\t\t\t\toptions: this.buildDevServerTerminalOptions(options),\n\t\t\t})\n\t\t}\n\n\t\tif (enableTerminal) {\n\t\t\tterminalsToLaunch.push({\n\t\t\t\ttype: 'terminal',\n\t\t\t\toptions: this.buildStandaloneTerminalOptions(options),\n\t\t\t})\n\t\t}\n\n\t\tif (enableClaude) {\n\t\t\tterminalsToLaunch.push({\n\t\t\t\ttype: 'claude',\n\t\t\t\toptions: await this.buildClaudeTerminalOptions(options),\n\t\t\t})\n\t\t}\n\n\t\t// Launch terminals based on count\n\t\tif (terminalsToLaunch.length > 1) {\n\t\t\t// Multiple terminals - launch as tabs in single window\n\t\t\tgetLogger().debug(`Launching ${terminalsToLaunch.length} terminals in single window`)\n\t\t\tlaunchPromises.push(this.launchMultipleTerminals(terminalsToLaunch, options))\n\t\t} else if (terminalsToLaunch.length === 1) {\n\t\t\t// Single terminal - launch standalone\n\t\t\tconst terminal = terminalsToLaunch[0]\n\t\t\tif (!terminal) {\n\t\t\t\tthrow new Error('Terminal configuration is undefined')\n\t\t\t}\n\t\t\tconst terminalType = terminal.type\n\t\t\tgetLogger().debug(`Launching single ${terminalType} terminal`)\n\n\t\t\tif (terminalType === 'claude') {\n\t\t\t\tlaunchPromises.push(this.launchClaudeTerminal(options))\n\t\t\t} else if (terminalType === 'devServer') {\n\t\t\t\tlaunchPromises.push(this.launchDevServerTerminal(options))\n\t\t\t} else {\n\t\t\t\tlaunchPromises.push(this.launchStandaloneTerminal(options))\n\t\t\t}\n\t\t}\n\n\t\t// Wait for all components to launch\n\t\tawait Promise.all(launchPromises)\n\n\t\tgetLogger().success('loom launched successfully')\n\t}\n\n\t/**\n\t * Launch IDE (VSCode or configured alternative)\n\t */\n\tprivate async launchVSCode(options: LaunchLoomOptions): Promise<void> {\n\t\tconst ideConfig = await this.settings?.loadSettings().then((s) => s.ide)\n\t\tawait openIdeWindow(options.worktreePath, ideConfig)\n\t\tgetLogger().info('IDE opened')\n\t}\n\n\t/**\n\t * Launch Claude terminal\n\t */\n\tprivate async launchClaudeTerminal(options: LaunchLoomOptions): Promise<void> {\n\t\tawait this.claudeContext.launchWithContext({\n\t\t\tworkspacePath: options.worktreePath,\n\t\t\ttype: options.workflowType,\n\t\t\tidentifier: options.identifier,\n\t\t\tbranchName: options.branchName,\n\t\t\t...(options.title && { title: options.title }),\n\t\t\t...(options.port !== undefined && { port: options.port }),\n\t\t\toneShot: options.oneShot ?? 'default',\n\t\t\t...(options.setArguments && { setArguments: options.setArguments }),\n\t\t\t...(options.executablePath && { executablePath: options.executablePath }),\n\t\t})\n\t\tgetLogger().info('Claude terminal opened')\n\t}\n\n\t/**\n\t * Launch dev server terminal\n\t * Runs `il dev-server [identifier]` which handles env loading internally\n\t */\n\tprivate async launchDevServerTerminal(options: LaunchLoomOptions): Promise<void> {\n\t\t// Build dev-server command with identifier\n\t\tconst executable = options.executablePath ?? getExecutablePath()\n\t\tconst devServerIdentifier = String(options.identifier)\n\t\tconst devServerCommand = `${executable} dev-server ${devServerIdentifier}`\n\n\t\t// Only generate color if terminal coloring is enabled (default: true)\n\t\tconst backgroundColor = (options.colorTerminal ?? true)\n\t\t\t? options.colorHex\n\t\t\t\t? hexToRgb(options.colorHex)\n\t\t\t\t: generateColorFromBranchName(options.branchName).rgb\n\t\t\t: undefined\n\n\t\tawait openTerminalWindow({\n\t\t\tworkspacePath: options.worktreePath,\n\t\t\tcommand: devServerCommand,\n\t\t\t...(backgroundColor && { backgroundColor }),\n\t\t\t// il dev-server handles env loading internally, so no includeEnvSetup\n\t\t\tincludeEnvSetup: false,\n\t\t\tincludePortExport: options.capabilities.includes('web'),\n\t\t\t...(options.port !== undefined && { port: options.port }),\n\t\t})\n\t\tgetLogger().info('Dev server terminal opened')\n\t}\n\n\t/**\n\t * Launch standalone terminal running `il shell <identifier>`\n\t */\n\tprivate async launchStandaloneTerminal(options: LaunchLoomOptions): Promise<void> {\n\t\t// Build shell command with identifier\n\t\tconst executable = options.executablePath ?? getExecutablePath()\n\t\tconst shellIdentifier = String(options.identifier)\n\t\tconst shellCommand = `${executable} shell ${shellIdentifier}`\n\n\t\t// Only generate color if terminal coloring is enabled (default: true)\n\t\tconst backgroundColor = (options.colorTerminal ?? true)\n\t\t\t? options.colorHex\n\t\t\t\t? hexToRgb(options.colorHex)\n\t\t\t\t: generateColorFromBranchName(options.branchName).rgb\n\t\t\t: undefined\n\n\t\tawait openTerminalWindow({\n\t\t\tworkspacePath: options.worktreePath,\n\t\t\tcommand: shellCommand,\n\t\t\t...(backgroundColor && { backgroundColor }),\n\t\t\t// il shell handles env loading internally, so we don't need includeEnvSetup\n\t\t\tincludeEnvSetup: false,\n\t\t\tincludePortExport: options.capabilities.includes('web'),\n\t\t\t...(options.port !== undefined && { port: options.port }),\n\t\t})\n\t\tgetLogger().info('Standalone terminal opened')\n\t}\n\n\t/**\n\t * Build terminal options for Claude\n\t */\n\tprivate async buildClaudeTerminalOptions(\n\t\toptions: LaunchLoomOptions\n\t): Promise<TerminalWindowOptions> {\n\t\tconst hasEnvFile = this.hasAnyEnvFiles(options.worktreePath)\n\t\tconst claudeTitle = `Claude - ${this.formatIdentifier(options.workflowType, options.identifier)}`\n\n\t\tconst executable = options.executablePath ?? 'iloom'\n\t\tlet claudeCommand = `${executable} spin`\n\t\tif (options.oneShot !== undefined && options.oneShot !== 'default') {\n\t\t\tclaudeCommand += ` --one-shot=${options.oneShot}`\n\t\t}\n\t\tif (options.setArguments && options.setArguments.length > 0) {\n\t\t\tfor (const setArg of options.setArguments) {\n\t\t\t\tclaudeCommand += ` --set ${setArg}`\n\t\t\t}\n\t\t}\n\t\tif (options.complexity) {\n\t\t\tclaudeCommand += ` --complexity=${options.complexity}`\n\t\t}\n\n\t\t// Only generate color if terminal coloring is enabled (default: true)\n\t\tconst backgroundColor = (options.colorTerminal ?? true)\n\t\t\t? options.colorHex\n\t\t\t\t? hexToRgb(options.colorHex)\n\t\t\t\t: generateColorFromBranchName(options.branchName).rgb\n\t\t\t: undefined\n\n\t\treturn {\n\t\t\tworkspacePath: options.worktreePath,\n\t\t\tcommand: claudeCommand,\n\t\t\t...(backgroundColor && { backgroundColor }),\n\t\t\ttitle: claudeTitle,\n\t\t\tincludeEnvSetup: (options.sourceEnvOnStart ?? false) && hasEnvFile,\n\t\t\t...(options.port !== undefined && { port: options.port, includePortExport: true }),\n\t\t}\n\t}\n\n\t/**\n\t * Build terminal options for dev server\n\t * Uses `il dev-server [identifier]` which handles env loading internally\n\t */\n\tprivate buildDevServerTerminalOptions(\n\t\toptions: LaunchLoomOptions\n\t): TerminalWindowOptions {\n\t\t// Build dev-server command with identifier\n\t\tconst executable = options.executablePath ?? getExecutablePath()\n\t\tconst devServerIdentifier = String(options.identifier)\n\t\tconst devServerCommand = `${executable} dev-server ${devServerIdentifier}`\n\n\t\tconst devServerTitle = `Dev Server - ${this.formatIdentifier(options.workflowType, options.identifier)}`\n\n\t\t// Only generate color if terminal coloring is enabled (default: true)\n\t\tconst backgroundColor = (options.colorTerminal ?? true)\n\t\t\t? options.colorHex\n\t\t\t\t? hexToRgb(options.colorHex)\n\t\t\t\t: generateColorFromBranchName(options.branchName).rgb\n\t\t\t: undefined\n\n\t\treturn {\n\t\t\tworkspacePath: options.worktreePath,\n\t\t\tcommand: devServerCommand,\n\t\t\t...(backgroundColor && { backgroundColor }),\n\t\t\ttitle: devServerTitle,\n\t\t\t// il dev-server handles env loading internally\n\t\t\tincludeEnvSetup: false,\n\t\t\tincludePortExport: options.capabilities.includes('web'),\n\t\t\t...(options.port !== undefined && { port: options.port }),\n\t\t}\n\t}\n\n\t/**\n\t * Build terminal options for standalone terminal\n\t * Runs `il shell <identifier>` which handles env loading internally\n\t */\n\tprivate buildStandaloneTerminalOptions(\n\t\toptions: LaunchLoomOptions\n\t): TerminalWindowOptions {\n\t\tconst terminalTitle = `Terminal - ${this.formatIdentifier(options.workflowType, options.identifier)}`\n\n\t\t// Build shell command with identifier\n\t\t// Use the same executable path pattern as buildClaudeTerminalOptions\n\t\tconst executable = options.executablePath ?? getExecutablePath()\n\t\tconst shellIdentifier = String(options.identifier)\n\t\tconst shellCommand = `${executable} shell ${shellIdentifier}`\n\n\t\t// Only generate color if terminal coloring is enabled (default: true)\n\t\tconst backgroundColor = (options.colorTerminal ?? true)\n\t\t\t? options.colorHex\n\t\t\t\t? hexToRgb(options.colorHex)\n\t\t\t\t: generateColorFromBranchName(options.branchName).rgb\n\t\t\t: undefined\n\n\t\treturn {\n\t\t\tworkspacePath: options.worktreePath,\n\t\t\tcommand: shellCommand,\n\t\t\t...(backgroundColor && { backgroundColor }),\n\t\t\ttitle: terminalTitle,\n\t\t\t// il shell handles env loading internally, so we don't need includeEnvSetup\n\t\t\tincludeEnvSetup: false,\n\t\t\tincludePortExport: options.capabilities.includes('web'),\n\t\t\t...(options.port !== undefined && { port: options.port }),\n\t\t}\n\t}\n\n\t/**\n\t * Launch multiple terminals (2+) as tabs in single window\n\t */\n\tprivate async launchMultipleTerminals(\n\t\tterminals: Array<{ type: string; options: TerminalWindowOptions }>,\n\t\t_options: LaunchLoomOptions\n\t): Promise<void> {\n\t\tconst terminalOptions = terminals.map((t) => t.options)\n\n\t\tawait openMultipleTerminalWindows(terminalOptions)\n\n\t\tconst terminalTypes = terminals.map((t) => t.type).join(' + ')\n\t\tgetLogger().info(`Multiple terminals opened: ${terminalTypes}`)\n\t}\n\n\t/**\n\t * Check if any dotenv-flow files exist in the workspace\n\t * Checks all files: .env, .env.local, .env.{NODE_ENV}, .env.{NODE_ENV}.local\n\t */\n\tprivate hasAnyEnvFiles(workspacePath: string): boolean {\n\t\tconst envFiles = getDotenvFlowFiles()\n\t\treturn envFiles.some(file => existsSync(join(workspacePath, file)))\n\t}\n\n\t/**\n\t * Format identifier for terminal tab titles\n\t */\n\tprivate formatIdentifier(workflowType: 'issue' | 'pr' | 'regular', identifier: string | number): string {\n\t\tif (workflowType === 'issue') {\n\t\t\treturn `Issue #${identifier}`\n\t\t} else if (workflowType === 'pr') {\n\t\t\treturn `PR #${identifier}`\n\t\t} else {\n\t\t\treturn `Branch: ${identifier}`\n\t\t}\n\t}\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/utils/mcp.ts"],"sourcesContent":["import path from 'path'\nimport os from 'os'\nimport fs from 'fs-extra'\nimport { getRepoInfo } from './github.js'\nimport { logger } from './logger.js'\nimport type { IloomSettings } from '../lib/SettingsManager.js'\nimport type { LoomMetadata } from '../lib/MetadataManager.js'\n\n/**\n * Generate MCP configuration for issue management\n * Uses a single server that can handle both issues and pull requests\n * Returns array of MCP server config objects\n * @param contextType - Optional context type (issue or pr)\n * @param repo - Optional repo in \"owner/repo\" format. If not provided, will auto-detect from git.\n * @param provider - Issue management provider (default: 'github')\n * @param settings - Optional settings to extract Linear API token from\n * @param draftPrNumber - Optional draft PR number for draft-pr mode (routes comments to PR)\n */\nexport async function generateIssueManagementMcpConfig(\n\tcontextType?: 'issue' | 'pr',\n\trepo?: string,\n\tprovider: 'github' | 'linear' | 'jira' = 'github',\n\tsettings?: IloomSettings,\n\tdraftPrNumber?: number\n): Promise<Record<string, unknown>[]> {\n\t// When draftPrNumber is provided (draft-pr mode), force contextType to 'pr'\n\t// This ensures agents route comments to the draft PR instead of the issue\n\tconst effectiveContextType = draftPrNumber ? 'pr' : contextType\n\n\t// Build provider-specific environment variables\n\tlet envVars: Record<string, string> = {\n\t\tISSUE_PROVIDER: provider,\n\t}\n\n\t// Add draft PR number to env vars if provided\n\tif (draftPrNumber) {\n\t\tenvVars.DRAFT_PR_NUMBER = String(draftPrNumber)\n\t}\n\n\tif (provider === 'github') {\n\t\t// Get repository information for GitHub - either from provided repo string or auto-detect\n\t\tlet owner: string\n\t\tlet name: string\n\n\t\tif (repo) {\n\t\t\tconst parts = repo.split('/')\n\t\t\tif (parts.length !== 2 || !parts[0] || !parts[1]) {\n\t\t\t\tthrow new Error(`Invalid repo format: ${repo}. Expected \"owner/repo\"`)\n\t\t\t}\n\t\t\towner = parts[0]\n\t\t\tname = parts[1]\n\t\t} else {\n\t\t\tconst repoInfo = await getRepoInfo()\n\t\t\towner = repoInfo.owner\n\t\t\tname = repoInfo.name\n\t\t}\n\n\t\t// Map logical types to GitHub's webhook event names (handle GitHub's naming quirk here)\n\t\t// Use effectiveContextType which may be overridden by draftPrNumber\n\t\tconst githubEventName = effectiveContextType === 'issue' ? 'issues' : effectiveContextType === 'pr' ? 'pull_request' : undefined\n\n\t\tenvVars = {\n\t\t\t...envVars,\n\t\t\tREPO_OWNER: owner,\n\t\t\tREPO_NAME: name,\n\t\t\tGITHUB_API_URL: 'https://api.github.com/',\n\t\t\t...(githubEventName && { GITHUB_EVENT_NAME: githubEventName }),\n\t\t}\n\n\t\tlogger.debug('Generated MCP config for GitHub issue management', {\n\t\t\tprovider,\n\t\t\trepoOwner: owner,\n\t\t\trepoName: name,\n\t\t\tcontextType: effectiveContextType ?? 'auto-detect',\n\t\t\tgithubEventName: githubEventName ?? 'auto-detect',\n\t\t\tdraftPrNumber: draftPrNumber ?? undefined,\n\t\t})\n\t} else if (provider === 'linear') {\n\t\t// Linear needs API token passed through\n\t\tconst apiToken = settings?.issueManagement?.linear?.apiToken ?? process.env.LINEAR_API_TOKEN\n\n\t\tif (apiToken) {\n\t\t\tenvVars.LINEAR_API_TOKEN = apiToken\n\t\t}\n\n\t\t// Pass through LINEAR_TEAM_KEY from settings (primary) or env var (fallback)\n\t\t// Settings teamId is the preferred source as it's configured via `il init`\n\t\tconst teamKey = settings?.issueManagement?.linear?.teamId ?? process.env.LINEAR_TEAM_KEY\n\t\tif (teamKey) {\n\t\t\tenvVars.LINEAR_TEAM_KEY = teamKey\n\t\t}\n\n\t\tlogger.debug('Generated MCP config for Linear issue management', {\n\t\t\tprovider,\n\t\t\thasApiToken: !!apiToken,\n\t\t\thasTeamKey: !!teamKey,\n\t\t\tcontextType: contextType ?? 'auto-detect',\n\t\t})\n\t} else if (provider === 'jira') {\n\t\t// Jira configuration - pass credentials via environment variables\n\t\tconst jiraSettings = settings?.issueManagement?.jira\n\n\t\tif (jiraSettings?.host) {\n\t\t\tenvVars.JIRA_HOST = jiraSettings.host\n\t\t}\n\t\tif (jiraSettings?.username) {\n\t\t\tenvVars.JIRA_USERNAME = jiraSettings.username\n\t\t}\n\t\tif (jiraSettings?.apiToken) {\n\t\t\tenvVars.JIRA_API_TOKEN = jiraSettings.apiToken\n\t\t}\n\t\tif (jiraSettings?.projectKey) {\n\t\t\tenvVars.JIRA_PROJECT_KEY = jiraSettings.projectKey\n\t\t}\n\t\tif (jiraSettings?.transitionMappings) {\n\t\t\tenvVars.JIRA_TRANSITION_MAPPINGS = JSON.stringify(jiraSettings.transitionMappings)\n\t\t}\n\t\tif (jiraSettings?.defaultIssueType) {\n\t\t\tenvVars.JIRA_DEFAULT_ISSUE_TYPE = jiraSettings.defaultIssueType\n\t\t}\n\t\tif (jiraSettings?.defaultSubtaskType) {\n\t\t\tenvVars.JIRA_DEFAULT_SUBTASK_TYPE = jiraSettings.defaultSubtaskType\n\t\t}\n\n\t\tlogger.debug('Generated MCP config for Jira issue management', {\n\t\t\tprovider,\n\t\t\thasApiToken: !!jiraSettings?.apiToken,\n\t\t\tprojectKey: jiraSettings?.projectKey,\n\t\t\tcontextType: contextType ?? 'auto-detect',\n\t\t})\n\t}\n\n\t// Compute absolute path to the MCP server JS file\n\tconst serverJsPath = path.join(path.dirname(new globalThis.URL(import.meta.url).pathname), '../dist/mcp/issue-management-server.js')\n\tconst resolvedServerJsPath = path.resolve(serverJsPath)\n\n\t// Generate single MCP server config\n\tconst mcpServerConfig = {\n\t\tmcpServers: {\n\t\t\tissue_management: {\n\t\t\t\ttransport: 'stdio',\n\t\t\t\tcommand: 'node',\n\t\t\t\targs: [resolvedServerJsPath],\n\t\t\t\tenv: envVars,\n\t\t\t},\n\t\t},\n\t}\n\n\treturn [mcpServerConfig]\n}\n\n/**\n * Reuse MetadataManager.slugifyPath() algorithm for recap file naming\n *\n * Algorithm:\n * 1. Trim trailing slashes\n * 2. Replace all path separators (/ or \\) with ___ (triple underscore)\n * 3. Replace any other non-alphanumeric characters (except _ and -) with -\n * 4. Append .json\n */\nexport function slugifyPath(loomPath: string): string {\n\tlet slug = loomPath.replace(/[/\\\\]+$/, '')\n\tslug = slug.replace(/[/\\\\]/g, '___')\n\tslug = slug.replace(/[^a-zA-Z0-9_-]/g, '-')\n\treturn `${slug}.json`\n}\n\n/**\n * Resolve recap file path for a given worktree path\n */\nexport function resolveRecapFilePath(worktreePath: string): string {\n\tconst recapsDir = path.join(os.homedir(), '.config', 'iloom-ai', 'recaps')\n\treturn path.join(recapsDir, slugifyPath(worktreePath))\n}\n\n/**\n * Read recap file (returns empty object if not found or invalid)\n */\nexport async function readRecapFile(filePath: string): Promise<Record<string, unknown>> {\n\ttry {\n\t\tif (await fs.pathExists(filePath)) {\n\t\t\tconst content = await fs.readFile(filePath, 'utf8')\n\t\t\treturn JSON.parse(content) as Record<string, unknown>\n\t\t}\n\t} catch {\n\t\t// Ignore read errors - return empty recap\n\t}\n\treturn {}\n}\n\n/**\n * Write recap file (ensures parent directory exists)\n */\nexport async function writeRecapFile(filePath: string, recap: Record<string, unknown>): Promise<void> {\n\tawait fs.ensureDir(path.dirname(filePath), { mode: 0o755 })\n\tawait fs.writeFile(filePath, JSON.stringify(recap, null, 2), { mode: 0o644 })\n}\n\n/**\n * Generate MCP configuration for recap server\n *\n * The recap server captures session context (goal, decisions, insights, risks, assumptions)\n * for the VS Code Loom Context Panel.\n *\n * @param loomPath - Absolute path to the loom workspace\n * @param loomMetadata - The loom metadata object (will be stringified as JSON)\n */\nexport function generateRecapMcpConfig(\n\tloomPath: string,\n\tloomMetadata: LoomMetadata\n): Record<string, unknown>[] {\n\t// Compute recap file path using slugifyPath algorithm (same as MetadataManager)\n\tconst recapsDir = path.join(os.homedir(), '.config', 'iloom-ai', 'recaps')\n\tconst recapFilePath = path.join(recapsDir, slugifyPath(loomPath))\n\n\t// Compute metadata file path (same directory/naming as MetadataManager)\n\tconst loomsDir = path.join(os.homedir(), '.config', 'iloom-ai', 'looms')\n\tconst metadataFilePath = path.join(loomsDir, slugifyPath(loomPath))\n\n\t// Pass env vars:\n\t// - RECAP_FILE_PATH: where to read/write recap data\n\t// - LOOM_METADATA_JSON: stringified loom metadata (parsed by MCP using LoomMetadata type)\n\t// - METADATA_FILE_PATH: path to loom metadata file (for state transition tools)\n\tconst envVars: Record<string, string> = {\n\t\tRECAP_FILE_PATH: recapFilePath,\n\t\tLOOM_METADATA_JSON: JSON.stringify(loomMetadata),\n\t\tMETADATA_FILE_PATH: metadataFilePath,\n\t}\n\n\t// Disable set_goal for issue and epic workflows\n\t// (set_goal should only be available in PR and regular/branch workflows)\n\tif (loomMetadata.issueType === 'issue' || loomMetadata.issueType === 'epic') {\n\t\tenvVars.RECAP_DISABLE_SET_GOAL = 'true'\n\t}\n\n\tlogger.debug('Generated MCP config for recap server', {\n\t\tloomPath,\n\t\trecapFilePath,\n\t\tloomMetadataDescription: loomMetadata.description,\n\t})\n\n\t// Compute absolute path to the recap MCP server JS file\n\tconst recapServerJsPath = path.resolve(\n\t\tpath.join(\n\t\t\tpath.dirname(new globalThis.URL(import.meta.url).pathname),\n\t\t\t'../dist/mcp/recap-server.js'\n\t\t)\n\t)\n\n\treturn [\n\t\t{\n\t\t\tmcpServers: {\n\t\t\t\trecap: {\n\t\t\t\t\ttransport: 'stdio',\n\t\t\t\t\tcommand: 'node',\n\t\t\t\t\targs: [recapServerJsPath],\n\t\t\t\t\tenv: envVars,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t]\n}\n\n/**\n * Generate MCP configuration for the harness server\n *\n * The harness server provides Claude with a `signal` tool to send structured\n * messages to the iloom harness process via Unix domain socket.\n *\n * @param socketPath - Absolute path to the harness Unix domain socket\n */\nexport function generateHarnessMcpConfig(socketPath: string): Record<string, unknown>[] {\n\tconst harnessServerJsPath = path.resolve(\n\t\tpath.join(\n\t\t\tpath.dirname(new globalThis.URL(import.meta.url).pathname),\n\t\t\t'../dist/mcp/harness-server.js'\n\t\t)\n\t)\n\n\tlogger.debug('Generated MCP config for harness server', { socketPath })\n\n\treturn [\n\t\t{\n\t\t\tmcpServers: {\n\t\t\t\tharness: {\n\t\t\t\t\ttransport: 'stdio',\n\t\t\t\t\tcommand: 'node',\n\t\t\t\t\targs: [harnessServerJsPath],\n\t\t\t\t\tenv: { ILOOM_HARNESS_SOCKET: socketPath },\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t]\n}\n\n/**\n * Get the MCP configs directory path\n */\nexport function getMcpConfigsDir(): string {\n\treturn path.join(os.homedir(), '.config', 'iloom-ai', 'mcp-configs')\n}\n\n/**\n * Get the MCP config file path for a given loom path\n */\nexport function getMcpConfigFilePath(loomPath: string): string {\n\treturn path.join(getMcpConfigsDir(), slugifyPath(loomPath))\n}\n\n/**\n * Generate and write a per-loom MCP config file to ~/.config/iloom-ai/mcp-configs/<loom-slug>.json\n *\n * Merges issue management and recap MCP server configs into a single file.\n * Used by swarm workers to pass --mcp-config <path> to claude -p commands.\n *\n * @param loomPath - Absolute path to the loom workspace\n * @param loomMetadata - The loom metadata object\n * @param provider - Issue tracker provider name\n * @param settings - Optional settings for provider configuration\n * @returns The absolute path to the written MCP config file\n */\nexport async function generateAndWriteMcpConfigFile(\n\tloomPath: string,\n\tloomMetadata: LoomMetadata,\n\tprovider: 'github' | 'linear' | 'jira' = 'github',\n\tsettings?: IloomSettings,\n): Promise<string> {\n\tconst mcpConfigs: Record<string, unknown>[] = []\n\n\t// Generate issue management MCP config\n\ttry {\n\t\tconst issueMcpConfigs = await generateIssueManagementMcpConfig(\n\t\t\t'issue',\n\t\t\tundefined,\n\t\t\tprovider,\n\t\t\tsettings,\n\t\t)\n\t\tmcpConfigs.push(...issueMcpConfigs)\n\t} catch (error) {\n\t\tlogger.warn(`Failed to generate issue management MCP config for loom: ${error instanceof Error ? error.message : 'Unknown error'}`)\n\t}\n\n\t// Generate recap MCP config\n\ttry {\n\t\tconst recapMcpConfigs = generateRecapMcpConfig(loomPath, loomMetadata)\n\t\tmcpConfigs.push(...recapMcpConfigs)\n\t} catch (error) {\n\t\tlogger.warn(`Failed to generate recap MCP config for loom: ${error instanceof Error ? error.message : 'Unknown error'}`)\n\t}\n\n\t// Merge all mcpServers into a single config object\n\tconst mergedServers: Record<string, unknown> = {}\n\tfor (const config of mcpConfigs) {\n\t\tif ('mcpServers' in config && typeof config.mcpServers === 'object') {\n\t\t\tObject.assign(mergedServers, config.mcpServers)\n\t\t}\n\t}\n\n\tconst mergedConfig = { mcpServers: mergedServers }\n\n\t// Verify MCP server JS files exist before writing config\n\tfor (const [serverName, serverConfig] of Object.entries(mergedServers)) {\n\t\tconst config = serverConfig as { args?: string[] }\n\t\tconst jsPath = config.args?.[0]\n\t\tif (jsPath) {\n\t\t\tconst exists = await fs.pathExists(jsPath)\n\t\t\tif (!exists) {\n\t\t\t\tlogger.warn(`MCP server JS file not found: ${serverName} -> ${jsPath}`)\n\t\t\t}\n\t\t}\n\t}\n\n\t// Write to file\n\tconst configDir = getMcpConfigsDir()\n\tawait fs.ensureDir(configDir, { mode: 0o755 })\n\n\tconst configFilePath = getMcpConfigFilePath(loomPath)\n\tawait fs.writeFile(configFilePath, JSON.stringify(mergedConfig, null, 2), { mode: 0o644 })\n\n\treturn configFilePath\n}"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/utils/claude.ts"],"sourcesContent":["/* global AbortSignal */\nimport { execa, type ExecaChildProcess } from 'execa'\nimport { existsSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { createHash, randomUUID } from 'node:crypto'\nimport { logger } from './logger.js'\nimport { getLogger } from './logger-context.js'\nimport { openTerminalWindow } from './terminal.js'\n\n/**\n * Generate a deterministic UUID v5 from a worktree path\n * Uses SHA1 hash with URL namespace to create a consistent session ID\n * that can be used to resume Claude Code sessions\n */\nexport function generateDeterministicSessionId(worktreePath: string): string {\n\t// UUID v5 namespace for URLs (RFC 4122)\n\tconst URL_NAMESPACE = '6ba7b811-9dad-11d1-80b4-00c04fd430c8'\n\n\t// Create SHA1 hash of namespace + path\n\tconst hash = createHash('sha1')\n\n\t// Convert namespace UUID to bytes\n\tconst namespaceBytes = Buffer.from(URL_NAMESPACE.replace(/-/g, ''), 'hex')\n\thash.update(namespaceBytes)\n\thash.update(worktreePath)\n\n\tconst digest = hash.digest()\n\n\t// Format as UUID v5:\n\t// - Set version (bits 12-15 of time_hi_and_version) to 5\n\t// - Set variant (bits 6-7 of clock_seq_hi_and_reserved) to binary 10\n\tconst bytes = Array.from(digest.subarray(0, 16))\n\n\t// Set version to 5 (byte 6, high nibble)\n\tconst byte6 = bytes[6] ?? 0\n\tbytes[6] = (byte6 & 0x0f) | 0x50\n\n\t// Set variant to RFC 4122 (byte 8, high 2 bits = 10)\n\tconst byte8 = bytes[8] ?? 0\n\tbytes[8] = (byte8 & 0x3f) | 0x80\n\n\t// Format as UUID string\n\tconst hex = Buffer.from(bytes).toString('hex')\n\treturn `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`\n}\n\n/**\n * Generate a random UUID v4 for session ID\n * Uses crypto.randomUUID() for cryptographically secure random UUID generation\n * Used to create unique session IDs for each loom, enabling fresh Claude sessions\n */\nexport function generateRandomSessionId(): string {\n\treturn randomUUID()\n}\n\nexport interface ClaudeCliOptions {\n\tmodel?: string\n\tpermissionMode?: 'plan' | 'acceptEdits' | 'bypassPermissions' | 'default'\n\taddDir?: string\n\theadless?: boolean\n\tbranchName?: string // Optional branch name for terminal coloring\n\tport?: number // Optional port for terminal window export\n\ttimeout?: number // Timeout in milliseconds\n\tappendSystemPrompt?: string // System instructions to append to system prompt\n\tappendSystemPromptFile?: string // Path to file containing system instructions\n\tmcpConfig?: Record<string, unknown>[] // Array of MCP server configurations\n\tallowedTools?: string[] // Tools to allow via --allowed-tools flag\n\tdisallowedTools?: string[] // Tools to disallow via --disallowed-tools flag\n\tagents?: Record<string, unknown> // Agent configurations for --agents flag\n\tpluginDir?: string // Path to plugin directory for --plugin-dir flag\n\toneShot?: import('../types/index.js').OneShotMode // One-shot automation mode\n\tsetArguments?: string[] // Raw --set arguments to forward (e.g., ['workflows.issue.startIde=false'])\n\texecutablePath?: string // Executable path to use for spin command (e.g., 'il', 'il-125', or '/path/to/dist/cli.js')\n\tsessionId?: string // Session ID for Claude Code resume support (must be valid UUID)\n\tnoSessionPersistence?: boolean // Prevent session data from being saved to disk (for utility operations)\n\toutputFormat?: 'json' | 'stream-json' | 'text' // Output format for Claude CLI (headless mode)\n\tverbose?: boolean // Enable verbose output (headless mode) - defaults to true when headless\n\tjsonMode?: 'json' | 'stream' // JSON output mode: 'json' for final object, 'stream' for real-time JSONL\n\tpassthroughStdout?: boolean // In headless mode, pipe stdout to process.stdout instead of capturing\n\tenv?: Record<string, string> // Additional environment variables to pass to the Claude process\n\tsignal?: AbortSignal // Optional AbortSignal for graceful termination of the Claude process\n}\n\n/**\n * Detect if Claude CLI is available on the system\n */\nexport async function detectClaudeCli(): Promise<boolean> {\n\ttry {\n\t\t// Use 'command -v' for cross-platform compatibility (works on macOS/Linux)\n\t\tawait execa('command', ['-v', 'claude'], {\n\t\t\tshell: true,\n\t\t\ttimeout: 5000,\n\t\t})\n\t\treturn true\n\t} catch (error) {\n\t\t// Claude CLI not found\n\t\tlogger.debug('Claude CLI not available', { error })\n\t\treturn false\n\t}\n}\n\n/**\n * Get Claude CLI version\n */\nexport async function getClaudeVersion(): Promise<string | null> {\n\ttry {\n\t\tconst result = await execa('claude', ['--version'], {\n\t\t\ttimeout: 5000,\n\t\t})\n\t\treturn result.stdout.trim()\n\t} catch (error) {\n\t\tlogger.warn('Failed to get Claude version', { error })\n\t\treturn null\n\t}\n}\n\n/**\n * Parse JSON stream output and extract result from last JSON object with type:\"result\"\n */\nfunction parseJsonStreamOutput(output: string): string {\n\ttry {\n\t\t// Split by newlines and filter out empty lines\n\t\tconst lines = output.split('\\n').filter(line => line.trim())\n\n\t\t// Find the last valid JSON object with type:\"result\"\n\t\tlet lastResult = ''\n\t\tfor (const line of lines) {\n\t\t\ttry {\n\t\t\t\tconst jsonObj = JSON.parse(line)\n\t\t\t\tif (jsonObj && typeof jsonObj === 'object' && jsonObj.type === 'result' && 'result' in jsonObj) {\n\t\t\t\t\tlastResult = jsonObj.result\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Skip invalid JSON lines\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\n\t\treturn lastResult || output // Fallback to original output if no valid result found\n\t} catch {\n\t\t// If parsing fails completely, return original output\n\t\treturn output\n\t}\n}\n\n/**\n * Launch Claude CLI with specified options\n * In headless mode, returns stdout. In interactive mode, returns void.\n */\nexport async function launchClaude(\n\tprompt: string,\n\toptions: ClaudeCliOptions = {}\n): Promise<string | void> {\n\tconst { model, permissionMode, addDir, headless = false, appendSystemPrompt, appendSystemPromptFile, mcpConfig, allowedTools, disallowedTools, agents, pluginDir, sessionId, noSessionPersistence, outputFormat, verbose, jsonMode, passthroughStdout, env: extraEnv, signal } = options\n\tconst log = getLogger()\n\n\t// Build command arguments\n\tconst args: string[] = []\n\n\tif (headless) {\n\t\targs.push('-p')\n\n\t\t// Use user-provided outputFormat or default to stream-json for progress tracking\n\t\tconst effectiveOutputFormat = outputFormat ?? 'stream-json'\n\t\targs.push('--output-format', effectiveOutputFormat)\n\n\t\t// Use user-provided verbose setting or default to true\n\t\tif (verbose !== false) {\n\t\t\targs.push('--verbose')\n\t\t}\n\t}\n\n\tif (model) {\n\t\targs.push('--model', model)\n\t}\n\n\tif (permissionMode && permissionMode !== 'default') {\n\t\targs.push('--permission-mode', permissionMode)\n\t}\n\n\tif (addDir) {\n\t\targs.push('--add-dir', addDir)\n\t}\n\n\targs.push('--add-dir', '/tmp') //TODO: Won't work on Windows\n\n\t// Add system prompt flag\n\tif (appendSystemPrompt) {\n\t\targs.push('--append-system-prompt', appendSystemPrompt)\n\t}\n\n\t// Add system prompt file flag\n\tif (appendSystemPromptFile) {\n\t\targs.push('--append-system-prompt-file', appendSystemPromptFile)\n\t}\n\n\t// Add --mcp-config flags for each MCP server configuration\n\tif (mcpConfig && mcpConfig.length > 0) {\n\t\tfor (const config of mcpConfig) {\n\t\t\targs.push('--mcp-config', JSON.stringify(config))\n\t\t}\n\t}\n\n\t// Add --allowed-tools flags if provided\n\tif (allowedTools && allowedTools.length > 0) {\n\t\targs.push('--allowed-tools', ...allowedTools)\n\t}\n\n\t// Add --disallowed-tools flags if provided\n\tif (disallowedTools && disallowedTools.length > 0) {\n\t\targs.push('--disallowed-tools', ...disallowedTools)\n\t}\n\n\t// Add --agents flag if provided\n\tif (agents) {\n\t\targs.push('--agents', JSON.stringify(agents))\n\t}\n\n\t// Add --plugin-dir flag if provided\n\tif (pluginDir) {\n\t\targs.push('--plugin-dir', pluginDir)\n\t}\n\n\t// Add --session-id flag if provided (enables Claude Code session resume)\n\tif (sessionId) {\n\t\targs.push('--session-id', sessionId)\n\t}\n\tconst isDebugMode = logger.isDebugEnabled()\n\n\tif (isDebugMode) {\n\t\targs.push('--debug') // Enable debug mode for more detailed logs\n\t}\n\n\t// Add --no-session-persistence flag if requested (for utility operations that don't need session persistence)\n\t// Note: --no-session-persistence can only be used with --print mode (-p), which is only added in headless mode\n\tif (noSessionPersistence && headless) {\n\t\targs.push('--no-session-persistence')\n\t}\n\n\t// Set CLAUDECODE=0 to prevent Claude from detecting it's running inside Claude Code\n\tconst claudeEnv = { ...process.env, CLAUDECODE: '0' }\n\n\t// Helper to attach AbortSignal to a subprocess for graceful termination\n\tfunction attachAbortSignal(subprocess: ExecaChildProcess): void {\n\t\tif (!signal) return\n\t\tconst onAbort = (): void => {\n\t\t\tsubprocess.kill('SIGTERM')\n\t\t}\n\t\tsignal.addEventListener('abort', onAbort, { once: true })\n\t\tsubprocess.on('exit', (): void => {\n\t\t\tsignal.removeEventListener('abort', onAbort)\n\t\t})\n\t}\n\n\ttry {\n\t\tif (headless && passthroughStdout) {\n\t\t\t// Headless + passthrough: Claude's stdout goes directly to process.stdout\n\t\t\t// Used for --json-stream where JSONL must reach the caller's stdout\n\t\t\tconst subprocess = execa('claude', args, {\n\t\t\t\tinput: prompt,\n\t\t\t\ttimeout: 0,\n\t\t\t\t...(addDir && { cwd: addDir }),\n\t\t\t\tenv: { ...claudeEnv, ...extraEnv }, // CLAUDECODE=0 + any extra env vars\n\t\t\t\tstdio: ['pipe', 'inherit', 'pipe'], // stdin: pipe (for prompt), stdout: inherit (passthrough), stderr: pipe (capture errors)\n\t\t\t})\n\n\t\t\tattachAbortSignal(subprocess)\n\t\t\ttry {\n\t\t\t\tawait subprocess\n\t\t\t} catch (err) {\n\t\t\t\tif (signal?.aborted) return\n\t\t\t\tthrow err\n\t\t\t}\n\t\t\treturn // No output to return - it went directly to stdout\n\t\t}\n\n\t\tif (headless) {\n\t\t\t// Headless mode: capture and return output\n\n\t\t\t// Set up execa options based on debug mode\n\t\t\tconst execaOptions = {\n\t\t\t\tinput: prompt,\n\t\t\t\ttimeout: 0, // Disable timeout for long responses\n\t\t\t\t...(addDir && { cwd: addDir }), // Run Claude in the worktree directory\n\t\t\t\tverbose: isDebugMode,\n\t\t\t\tenv: { ...claudeEnv, ...extraEnv }, // CLAUDECODE=0 + any extra env vars\n\t\t\t\t...(isDebugMode && { stdio: ['pipe', 'pipe', 'pipe'] as const }), // Enable streaming in debug mode\n\t\t\t}\n\n\t\t\tconst subprocess = execa('claude', args, execaOptions)\n\t\t\tattachAbortSignal(subprocess)\n\n\t\t\t// Check if JSON streaming format is enabled (always true in headless mode)\n\t\t\tconst isJsonStreamFormat = args.includes('--output-format') && args.includes('stream-json')\n\n\t\t\t// Handle real-time streaming (enabled for progress tracking)\n\t\t\tlet outputBuffer = ''\n\t\t\tlet isStreaming = false\n\t\t\tlet isFirstProgress = true\n\t\t\tif (subprocess.stdout && typeof subprocess.stdout.on === 'function') {\n\t\t\t\tisStreaming = true\n\t\t\t\tsubprocess.stdout.on('data', (chunk: Buffer) => {\n\t\t\t\t\tconst text = chunk.toString()\n\t\t\t\t\toutputBuffer += text\n\n\t\t\t\t\tif (jsonMode === 'stream') {\n\t\t\t\t\t\t// --json-stream: Output raw JSONL to stdout immediately\n\t\t\t\t\t\tprocess.stdout.write(text)\n\t\t\t\t\t} else if (jsonMode === 'json') {\n\t\t\t\t\t\t// --json: Suppress all progress output (will return final JSON)\n\t\t\t\t\t\t// Do nothing - just accumulate in buffer\n\t\t\t\t\t} else if (isDebugMode) {\n\t\t\t\t\t\tlog.stdout.write(text) // Full JSON streaming in debug mode\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Progress dots in non-debug mode with robot emoji prefix\n\t\t\t\t\t\tif (isFirstProgress) {\n\t\t\t\t\t\t\tlog.stdout.write('🤖 .')\n\t\t\t\t\t\t\tisFirstProgress = false\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlog.stdout.write('.')\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t}\n\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t\tlet result: any\n\t\t\ttry {\n\t\t\t\tresult = await subprocess\n\t\t\t} catch (subprocessError) {\n\t\t\t\t// If aborted intentionally, do not treat as an error\n\t\t\t\tif (signal?.aborted) return\n\t\t\t\tthrow subprocessError\n\t\t\t}\n\n\t\t\t// Return streamed output if we were streaming, otherwise use result.stdout\n\t\t\tif (isStreaming) {\n\t\t\t\tconst rawOutput = outputBuffer.trim()\n\n\t\t\t\t// Clean up progress dots with newline in non-debug mode (skip for json modes)\n\t\t\t\tif (!isDebugMode && !jsonMode) {\n\t\t\t\t\tlog.stdout.write('\\n')\n\t\t\t\t}\n\n\t\t\t\treturn isJsonStreamFormat ? parseJsonStreamOutput(rawOutput) : rawOutput\n\t\t\t} else {\n\t\t\t\t// Fallback for mocked tests or when streaming not available\n\t\t\t\tif (isDebugMode) {\n\t\t\t\t\t// In debug mode, write to stdout even if not streaming (old behavior for tests)\n\t\t\t\t\tlog.stdout.write(result.stdout)\n\t\t\t\t\tif (result.stdout && !result.stdout.endsWith('\\n')) {\n\t\t\t\t\t\tlog.stdout.write('\\n')\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// In non-debug mode, show a single progress dot even without streaming (for tests)\n\t\t\t\t\tlog.stdout.write('🤖 .')\n\t\t\t\t\tlog.stdout.write('\\n')\n\t\t\t\t}\n\t\t\t\tconst rawOutput = result.stdout.trim()\n\t\t\t\treturn isJsonStreamFormat ? parseJsonStreamOutput(rawOutput) : rawOutput\n\t\t\t}\n\t\t} else {\n\t\t\t// Simple interactive mode: run Claude in current terminal with stdio inherit\n\t\t\t// Used for conflict resolution, error fixing, etc.\n\t\t\t// This is the simple approach: claude -- \"prompt\"\n\n\t\t\t// First attempt: capture stderr to detect session ID conflicts\n\t\t\t// stdin/stdout inherit for interactivity, stderr captured for error detection\n\t\t\ttry {\n\t\t\t\tconst interactiveSubprocess = execa('claude', [...args, '--', prompt], {\n\t\t\t\t\t...(addDir && { cwd: addDir }),\n\t\t\t\t\tstdio: ['inherit', 'inherit', 'pipe'], // Capture stderr to detect session conflicts\n\t\t\t\t\ttimeout: 0, // Disable timeout\n\t\t\t\t\tverbose: logger.isDebugEnabled(),\n\t\t\t\t\tenv: { ...claudeEnv, ...extraEnv }, // CLAUDECODE=0 + any extra env vars\n\t\t\t\t})\n\t\t\t\tattachAbortSignal(interactiveSubprocess)\n\t\t\t\ttry {\n\t\t\t\t\tawait interactiveSubprocess\n\t\t\t\t} catch (err) {\n\t\t\t\t\tif (signal?.aborted) return\n\t\t\t\t\tthrow err\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t} catch (interactiveError) {\n\t\t\t\tif (signal?.aborted) return\n\t\t\t\tconst interactiveExecaError = interactiveError as { stderr?: string; message?: string }\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- intentional: empty string stderr should fall through to message\n\t\t\t\tconst interactiveErrorMessage = interactiveExecaError.stderr || interactiveExecaError.message || ''\n\n\t\t\t\t// Check for session ID conflict\n\t\t\t\tconst sessionMatch = interactiveErrorMessage.match(/Session ID ([0-9a-f-]+) is already in use/i)\n\t\t\t\tconst conflictSessionId = sessionMatch?.[1]\n\t\t\t\tif (sessionMatch && sessionId && conflictSessionId) {\n\t\t\t\t\tlog.debug(`Session ID ${conflictSessionId} already in use, retrying with --resume`)\n\n\t\t\t\t\t// Rebuild args with --resume instead of --session-id\n\t\t\t\t\tconst resumeArgs = args.filter((arg, idx) => {\n\t\t\t\t\t\tif (arg === '--session-id') return false\n\t\t\t\t\t\tif (idx > 0 && args[idx - 1] === '--session-id') return false\n\t\t\t\t\t\treturn true\n\t\t\t\t\t})\n\t\t\t\t\tresumeArgs.push('--resume', conflictSessionId)\n\n\t\t\t\t\t// Retry with full stdio inherit for proper interactive experience\n\t\t\t\t\t// Note: When using --resume, we omit the prompt since the session already has context\n\t\t\t\t\tconst resumeSubprocess = execa('claude', resumeArgs, {\n\t\t\t\t\t\t...(addDir && { cwd: addDir }),\n\t\t\t\t\t\tstdio: 'inherit',\n\t\t\t\t\t\ttimeout: 0,\n\t\t\t\t\t\tverbose: logger.isDebugEnabled(),\n\t\t\t\t\t\tenv: claudeEnv,\n\t\t\t\t\t})\n\t\t\t\t\tattachAbortSignal(resumeSubprocess)\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait resumeSubprocess\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tif (signal?.aborted) return\n\t\t\t\t\t\tthrow err\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// Not a session conflict, re-throw\n\t\t\t\tthrow interactiveError\n\t\t\t}\n\t\t}\n\t} catch (error) {\n\t\t// If aborted intentionally, do not treat as an error\n\t\tif (signal?.aborted) return\n\n\t\t// Check for specific Claude CLI errors\n\t\tconst execaError = error as {\n\t\t\tstderr?: string\n\t\t\tmessage?: string\n\t\t\texitCode?: number\n\t\t}\n\n\t\t// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- intentional: empty string stderr should fall through to message\n\t\tconst errorMessage = execaError.stderr || execaError.message || 'Unknown Claude CLI error'\n\n\t\t// Check for \"Session ID ... is already in use\" error and retry with --resume\n\t\tconst sessionInUseMatch = errorMessage.match(/Session ID ([0-9a-f-]+) is already in use/i)\n\t\tconst extractedSessionId = sessionInUseMatch?.[1]\n\t\tif (sessionInUseMatch && sessionId && extractedSessionId) {\n\t\t\tlog.debug(`Session ID ${extractedSessionId} already in use, retrying with --resume`)\n\n\t\t\t// Rebuild args with --resume instead of --session-id\n\t\t\tconst resumeArgs = args.filter((arg, idx) => {\n\t\t\t\t// Filter out --session-id and its value\n\t\t\t\tif (arg === '--session-id') return false\n\t\t\t\tif (idx > 0 && args[idx - 1] === '--session-id') return false\n\t\t\t\treturn true\n\t\t\t})\n\t\t\tresumeArgs.push('--resume', extractedSessionId)\n\n\t\t\ttry {\n\t\t\t\tif (headless) {\n\t\t\t\t\tconst isDebugMode = logger.isDebugEnabled()\n\t\t\t\t\t// Note: In headless mode, we still need to pass the prompt even with --resume\n\t\t\t\t\t// because there's no interactive input mechanism\n\t\t\t\t\tconst execaOptions = {\n\t\t\t\t\t\tinput: prompt,\n\t\t\t\t\t\ttimeout: 0,\n\t\t\t\t\t\t...(addDir && { cwd: addDir }),\n\t\t\t\t\t\tverbose: isDebugMode,\n\t\t\t\t\t\tenv: claudeEnv,\n\t\t\t\t\t\t...(isDebugMode && { stdio: ['pipe', 'pipe', 'pipe'] as const }),\n\t\t\t\t\t}\n\n\t\t\t\t\tconst subprocess = execa('claude', resumeArgs, execaOptions)\n\t\t\t\t\tconst isJsonStreamFormat = resumeArgs.includes('--output-format') && resumeArgs.includes('stream-json')\n\n\t\t\t\t\tlet outputBuffer = ''\n\t\t\t\t\tlet isStreaming = false\n\t\t\t\t\tlet isFirstProgress = true\n\t\t\t\t\tif (subprocess.stdout && typeof subprocess.stdout.on === 'function') {\n\t\t\t\t\t\tisStreaming = true\n\t\t\t\t\t\tsubprocess.stdout.on('data', (chunk: Buffer) => {\n\t\t\t\t\t\t\tconst text = chunk.toString()\n\t\t\t\t\t\t\toutputBuffer += text\n\t\t\t\t\t\t\tif (jsonMode === 'stream') {\n\t\t\t\t\t\t\t\tprocess.stdout.write(text)\n\t\t\t\t\t\t\t} else if (jsonMode === 'json') {\n\t\t\t\t\t\t\t\t// Suppress progress output for json mode\n\t\t\t\t\t\t\t} else if (isDebugMode) {\n\t\t\t\t\t\t\t\tlog.stdout.write(text)\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tif (isFirstProgress) {\n\t\t\t\t\t\t\t\t\tlog.stdout.write('🤖 .')\n\t\t\t\t\t\t\t\t\tisFirstProgress = false\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tlog.stdout.write('.')\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\n\t\t\t\t\tconst result = await subprocess\n\n\t\t\t\t\tif (isStreaming) {\n\t\t\t\t\t\tconst rawOutput = outputBuffer.trim()\n\t\t\t\t\t\tif (!isDebugMode && !jsonMode) {\n\t\t\t\t\t\t\tlog.stdout.write('\\n')\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn isJsonStreamFormat ? parseJsonStreamOutput(rawOutput) : rawOutput\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (isDebugMode) {\n\t\t\t\t\t\t\tlog.stdout.write(result.stdout)\n\t\t\t\t\t\t\tif (result.stdout && !result.stdout.endsWith('\\n')) {\n\t\t\t\t\t\t\t\tlog.stdout.write('\\n')\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tlog.stdout.write('🤖 .')\n\t\t\t\t\t\t\tlog.stdout.write('\\n')\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst rawOutput = result.stdout.trim()\n\t\t\t\t\t\treturn isJsonStreamFormat ? parseJsonStreamOutput(rawOutput) : rawOutput\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Note: When using --resume, we omit the prompt since the session already has context\n\t\t\t\t\tawait execa('claude', resumeArgs, {\n\t\t\t\t\t\t...(addDir && { cwd: addDir }),\n\t\t\t\t\t\tstdio: 'inherit',\n\t\t\t\t\t\ttimeout: 0,\n\t\t\t\t\t\tverbose: logger.isDebugEnabled(),\n\t\t\t\t\t\tenv: claudeEnv,\n\t\t\t\t\t})\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t} catch (retryError) {\n\t\t\t\tconst retryExecaError = retryError as { stderr?: string; message?: string }\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- intentional: empty string stderr should fall through to message\n\t\t\t\tconst retryErrorMessage = retryExecaError.stderr || retryExecaError.message || 'Unknown Claude CLI error'\n\t\t\t\tthrow new Error(`Claude CLI error: ${retryErrorMessage}`)\n\t\t\t}\n\t\t}\n\n\t\t// Re-throw with more context\n\t\tthrow new Error(`Claude CLI error: ${errorMessage}`)\n\t}\n}\n\n/**\n * Launch Claude in a new terminal window with rich context\n * This is specifically for \"end of il start\" workflow\n * Ports the terminal window opening, coloring, and .env sourcing behavior\n */\nexport async function launchClaudeInNewTerminalWindow(\n\t_prompt: string,\n\toptions: ClaudeCliOptions & {\n\t\tworkspacePath: string // Required for terminal window launch\n\t}\n): Promise<void> {\n\tconst { workspacePath, branchName, oneShot = 'default', port, setArguments, executablePath } = options\n\n\t// Verify required parameter\n\tif (!workspacePath) {\n\t\tthrow new Error('workspacePath is required for terminal window launch')\n\t}\n\n\t// Build launch command with optional --one-shot flag\n\t// Use provided executable path or fallback to 'il'\n\tconst executable = executablePath ?? 'iloom'\n\tlet launchCommand = `${executable} spin`\n\tif (oneShot !== 'default') {\n\t\tlaunchCommand += ` --one-shot=${oneShot}`\n\t}\n\n\t// Append --set arguments if provided\n\tif (setArguments && setArguments.length > 0) {\n\t\tfor (const setArg of setArguments) {\n\t\t\tlaunchCommand += ` --set ${setArg}`\n\t\t}\n\t}\n\n\t// Apply terminal background color if branch name available\n\tlet backgroundColor: { r: number; g: number; b: number } | undefined\n\tif (branchName) {\n\t\ttry {\n\t\t\tconst { generateColorFromBranchName } = await import('./color.js')\n\t\t\tconst colorData = generateColorFromBranchName(branchName)\n\t\t\tbackgroundColor = colorData.rgb\n\t\t} catch (error) {\n\t\t\tlogger.warn(\n\t\t\t\t`Failed to generate terminal color: ${error instanceof Error ? error.message : 'Unknown error'}`\n\t\t\t)\n\t\t}\n\t}\n\n\t// Check if .env file exists in workspace\n\tconst hasEnvFile = existsSync(join(workspacePath, '.env'))\n\n\t// Open new terminal window with Claude\n\tawait openTerminalWindow({\n\t\tworkspacePath,\n\t\tcommand: launchCommand,\n\t\t...(backgroundColor && { backgroundColor }),\n\t\tincludeEnvSetup: hasEnvFile, // source .env only if it exists\n\t\t...(port !== undefined && { port, includePortExport: true }),\n\t})\n}\n\n/**\n * Generate a branch name using Claude with fallback\n * This matches the implementation that was working in ClaudeBranchNameStrategy\n */\nexport async function generateBranchName(\n\tissueTitle: string,\n\tissueNumber: string | number,\n\tmodel: string = 'haiku'\n): Promise<string> {\n\ttry {\n\t\t// Check if Claude CLI is available\n\t\tconst isAvailable = await detectClaudeCli()\n\t\tif (!isAvailable) {\n\t\t\tlogger.warn('Claude CLI not available, using fallback branch name')\n\t\t\treturn `feat/issue-${issueNumber}`\n\t\t}\n\n\t\tlogger.debug('Generating branch name with Claude', { issueNumber, issueTitle })\n\n\t\t// Use the proven prompt format from ClaudeBranchNameStrategy\n\t\tconst prompt = `<Task>\nGenerate a git branch name for the following issue:\n<Issue>\n<IssueNumber>${issueNumber}</IssueNumber>\n<IssueTitle>${issueTitle}</IssueTitle>\n</Issue>\n\n<Requirements>\n<IssueNumber>Must use this exact issue number: ${issueNumber}</IssueNumber>\n<Format>Format must be: {prefix}/issue-${issueNumber}__{description}</Format>\n<Prefix>Prefix must be one of: feat, fix, docs, refactor, test, chore</Prefix>\n<MaxLength>Maximum 50 characters total</MaxLength>\n<Characters>Only lowercase letters, numbers, and hyphens allowed</Characters>\n<Output>Reply with ONLY the branch name, nothing else</Output>\n</Requirements>\n</Task>`\n\n\t\tlogger.debug('Sending prompt to Claude', { prompt })\n\n\t\tconst result = (await launchClaude(prompt, {\n\t\t\tmodel,\n\t\t\theadless: true,\n\t\t\tnoSessionPersistence: true, // Utility operation - don't persist session\n\t\t\tenv: { CLAUDE_CODE_SIMPLE: '1' }, // Minimal mode - no MCP, hooks, or CLAUDE.md loading\n\t\t})) as string\n\n\t\t// Normalize to lowercase for consistency (Linear IDs are uppercase but branches should be lowercase)\n\t\tconst branchName = result.trim().toLowerCase()\n\t\tlogger.debug('Claude returned branch name', { branchName, issueNumber })\n\n\t\t// Validate generated name using same validation as ClaudeBranchNameStrategy\n\t\tif (!branchName || !isValidBranchName(branchName, issueNumber)) {\n\t\t\tlogger.warn('Invalid branch name from Claude, using fallback', { branchName })\n\t\t\treturn `feat/issue-${issueNumber}`.toLowerCase()\n\t\t}\n\n\t\treturn branchName\n\t} catch (error) {\n\t\tlogger.warn('Failed to generate branch name with Claude', { error })\n\t\treturn `feat/issue-${issueNumber}`.toLowerCase()\n\t}\n}\n\n/**\n * Validate branch name format\n * Check format: {prefix}/issue-{number}__{description}\n * Uses case-insensitive matching for issue number (Linear uses uppercase like MARK-1)\n */\nfunction isValidBranchName(name: string, issueNumber: string | number): boolean {\n\tconst pattern = new RegExp(`^(feat|fix|docs|refactor|test|chore)/issue-${issueNumber}__[a-z0-9-]+$`, 'i')\n\treturn pattern.test(name) && name.length <= 50\n}\n"],"mappings":"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","names":["isDebugMode"]}