@iloom/cli 0.5.0 → 0.5.2

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 (172) hide show
  1. package/dist/{BranchNamingService-GCCWB3LK.js → BranchNamingService-B5PVRR7F.js} +4 -4
  2. package/dist/ClaudeContextManager-PQ46VILL.js +14 -0
  3. package/dist/ClaudeService-6OMO552H.js +13 -0
  4. package/dist/GitHubService-S2OGUTDR.js +12 -0
  5. package/dist/{LoomLauncher-4UG2E4CD.js → LoomLauncher-ZHDTPKED.js} +15 -79
  6. package/dist/LoomLauncher-ZHDTPKED.js.map +1 -0
  7. package/dist/MetadataManager-DFI73J3G.js +10 -0
  8. package/dist/PRManager-OCSB2HPT.js +14 -0
  9. package/dist/PromptTemplateManager-5GNF7FCP.js +9 -0
  10. package/dist/{SettingsManager-XPR4TEQL.js → SettingsManager-CNYBGXDT.js} +3 -3
  11. package/dist/SettingsMigrationManager-KZKDG66H.js +10 -0
  12. package/dist/{chunk-OEGECBFS.js → chunk-3PT7RKL5.js} +4 -4
  13. package/dist/{chunk-WUQQNE63.js → chunk-433MOLAU.js} +44 -7
  14. package/dist/chunk-433MOLAU.js.map +1 -0
  15. package/dist/{chunk-LN4H3A6A.js → chunk-53OMUNUN.js} +5 -5
  16. package/dist/{chunk-THF25ICZ.js → chunk-5F6IWWRS.js} +2 -2
  17. package/dist/{chunk-P2ZQ5LKB.js → chunk-5IWU3HXE.js} +5 -5
  18. package/dist/{chunk-QIUJPPJQ.js → chunk-5TXLVEXT.js} +3 -3
  19. package/dist/{chunk-RFUOIUQF.js → chunk-66BMJ25W.js} +13 -7
  20. package/dist/chunk-66BMJ25W.js.map +1 -0
  21. package/dist/{chunk-6UIGZD2N.js → chunk-6MLEBAYZ.js} +2 -2
  22. package/dist/{chunk-VTXCGKV5.js → chunk-7HIRPCKU.js} +14 -6
  23. package/dist/chunk-7HIRPCKU.js.map +1 -0
  24. package/dist/{chunk-UNXRACJ7.js → chunk-7LSSNB7Y.js} +3 -3
  25. package/dist/{chunk-QHA67Q7A.js → chunk-7Q66W4OH.js} +2 -2
  26. package/dist/{chunk-RUC7OULH.js → chunk-AEIMYF4P.js} +6 -8
  27. package/dist/{chunk-RUC7OULH.js.map → chunk-AEIMYF4P.js.map} +1 -1
  28. package/dist/{chunk-MD6HA5IK.js → chunk-B2UO6EYE.js} +2 -2
  29. package/dist/{chunk-YZTDGPFB.js → chunk-CFUWQHCJ.js} +2 -2
  30. package/dist/{chunk-UYWAESOT.js → chunk-F2PWIRV4.js} +3 -3
  31. package/dist/{chunk-PSFVTBM7.js → chunk-FXDYIV3K.js} +2 -2
  32. package/dist/{chunk-CDQEK2WD.js → chunk-FXJKNVZW.js} +5 -5
  33. package/dist/{chunk-3CMGCRB5.js → chunk-HMMO2LDS.js} +3 -3
  34. package/dist/{chunk-OOU3DKNT.js → chunk-IDUICCZY.js} +2 -2
  35. package/dist/{chunk-HABINPX2.js → chunk-J7GHNTYK.js} +67 -11
  36. package/dist/chunk-J7GHNTYK.js.map +1 -0
  37. package/dist/{chunk-DKQ4SUII.js → chunk-K5G5SFWY.js} +2 -2
  38. package/dist/chunk-K5G5SFWY.js.map +1 -0
  39. package/dist/{chunk-KO2FOMHL.js → chunk-LT3SGBR7.js} +2 -2
  40. package/dist/{chunk-VBFDVGAE.js → chunk-LVLRMP7V.js} +2 -2
  41. package/dist/{chunk-RNZMHJK7.js → chunk-N4ZJVATC.js} +3 -3
  42. package/dist/chunk-NXMDEL3F.js +54 -0
  43. package/dist/chunk-NXMDEL3F.js.map +1 -0
  44. package/dist/chunk-O7VL5N6S.js +72 -0
  45. package/dist/chunk-O7VL5N6S.js.map +1 -0
  46. package/dist/{chunk-S65T4O6I.js → chunk-QPS6TZUW.js} +3 -3
  47. package/dist/{chunk-RJKMF6BC.js → chunk-SHVB3EFE.js} +3 -3
  48. package/dist/chunk-VT4PDUYT.js +578 -0
  49. package/dist/chunk-VT4PDUYT.js.map +1 -0
  50. package/dist/{chunk-4YTILIIH.js → chunk-VV66DH6T.js} +8 -8
  51. package/dist/{chunk-GVRO4PWE.js → chunk-XNNXAAZT.js} +6 -6
  52. package/dist/{chunk-AS2IRKLU.js → chunk-YU5HVI6B.js} +2 -2
  53. package/dist/{chunk-T5IIUG4Z.js → chunk-Z5BM4JWB.js} +25 -24
  54. package/dist/chunk-Z5BM4JWB.js.map +1 -0
  55. package/dist/{chunk-SJ2GZ6RF.js → chunk-ZX3GTM7O.js} +2 -2
  56. package/dist/{claude-ACVXNB6N.js → claude-H33OQMXO.js} +4 -6
  57. package/dist/{cleanup-MIDJVSIU.js → cleanup-Y5W3CNUV.js} +20 -22
  58. package/dist/{cleanup-MIDJVSIU.js.map → cleanup-Y5W3CNUV.js.map} +1 -1
  59. package/dist/cli.js +125 -81
  60. package/dist/cli.js.map +1 -1
  61. package/dist/{color-ZPIIUADB.js → color-4TJ4P5EY.js} +5 -3
  62. package/dist/{contribute-RS3DO3WP.js → contribute-K7UXBOML.js} +8 -8
  63. package/dist/{dev-server-ASH7HJVI.js → dev-server-HNBRWGCD.js} +11 -13
  64. package/dist/{dev-server-ASH7HJVI.js.map → dev-server-HNBRWGCD.js.map} +1 -1
  65. package/dist/{feedback-RVIGHBJG.js → feedback-567ZH2O7.js} +16 -14
  66. package/dist/{feedback-RVIGHBJG.js.map → feedback-567ZH2O7.js.map} +1 -1
  67. package/dist/{git-OQAPUPLP.js → git-OV6ADVO7.js} +6 -6
  68. package/dist/{ignite-XJALWFAT.js → ignite-3HB3ZBEW.js} +15 -17
  69. package/dist/{ignite-XJALWFAT.js.map → ignite-3HB3ZBEW.js.map} +1 -1
  70. package/dist/index.d.ts +54 -35
  71. package/dist/index.js +377 -276
  72. package/dist/index.js.map +1 -1
  73. package/dist/init-CMIRHFSR.js +19 -0
  74. package/dist/{installation-detector-6R6YOFVZ.js → installation-detector-VXZOCL6P.js} +3 -3
  75. package/dist/mcp/issue-management-server.js +62 -7
  76. package/dist/mcp/issue-management-server.js.map +1 -1
  77. package/dist/neon-helpers-3KBC4A3Y.js +11 -0
  78. package/dist/{open-KW4NTLXH.js → open-AXE225Z5.js} +11 -13
  79. package/dist/{open-KW4NTLXH.js.map → open-AXE225Z5.js.map} +1 -1
  80. package/dist/{projects-QEAEBAT2.js → projects-GVEMCN5R.js} +4 -4
  81. package/dist/{prompt-A7GGRHSY.js → prompt-3SAZYRUN.js} +3 -3
  82. package/dist/prompts/session-summary-prompt.txt +58 -4
  83. package/dist/{rebase-WZHHE5LU.js → rebase-6UIHMUWS.js} +9 -11
  84. package/dist/{rebase-WZHHE5LU.js.map → rebase-6UIHMUWS.js.map} +1 -1
  85. package/dist/{recap-33NPZ3ZO.js → recap-XTBNMEMO.js} +12 -19
  86. package/dist/recap-XTBNMEMO.js.map +1 -0
  87. package/dist/{remote-73TZ2ADI.js → remote-IJAMOEAP.js} +3 -3
  88. package/dist/{run-HRYQ7TR7.js → run-H375EYRB.js} +11 -13
  89. package/dist/{run-HRYQ7TR7.js.map → run-H375EYRB.js.map} +1 -1
  90. package/dist/{shell-JMU5XTHW.js → shell-33FJCWJQ.js} +9 -11
  91. package/dist/{shell-JMU5XTHW.js.map → shell-33FJCWJQ.js.map} +1 -1
  92. package/dist/{summary-4SSGGH7N.js → summary-JUMOCNLR.js} +14 -15
  93. package/dist/{summary-4SSGGH7N.js.map → summary-JUMOCNLR.js.map} +1 -1
  94. package/dist/{test-git-6SAIRBUD.js → test-git-CO3BA4BV.js} +6 -6
  95. package/dist/{test-prefix-RLVRK5ZD.js → test-prefix-HZYSDQYT.js} +6 -6
  96. package/dist/{test-tabs-3SCJWRKT.js → test-tabs-D3POYOJ5.js} +3 -6
  97. package/dist/{test-tabs-3SCJWRKT.js.map → test-tabs-D3POYOJ5.js.map} +1 -1
  98. package/dist/{test-webserver-VPNLAFZ3.js → test-webserver-YVQD42W6.js} +2 -2
  99. package/dist/{update-LETF5ASC.js → update-5NOHT4SG.js} +4 -4
  100. package/dist/{update-notifier-H55ZK7NU.js → update-notifier-ARA5SPUW.js} +3 -3
  101. package/package.json +1 -1
  102. package/dist/ClaudeContextManager-DQFKIMEP.js +0 -16
  103. package/dist/ClaudeService-CJS32WG2.js +0 -15
  104. package/dist/GitHubService-RPM27GWD.js +0 -12
  105. package/dist/LoomLauncher-4UG2E4CD.js.map +0 -1
  106. package/dist/MetadataManager-WXUVXKUS.js +0 -10
  107. package/dist/PRManager-7DSIMCAD.js +0 -16
  108. package/dist/PromptTemplateManager-72FEOGT6.js +0 -9
  109. package/dist/SettingsMigrationManager-EH3J2TCN.js +0 -10
  110. package/dist/chunk-DKQ4SUII.js.map +0 -1
  111. package/dist/chunk-HABINPX2.js.map +0 -1
  112. package/dist/chunk-RFUOIUQF.js.map +0 -1
  113. package/dist/chunk-T5IIUG4Z.js.map +0 -1
  114. package/dist/chunk-UYVWLISQ.js +0 -113
  115. package/dist/chunk-UYVWLISQ.js.map +0 -1
  116. package/dist/chunk-VAYGNQTE.js +0 -234
  117. package/dist/chunk-VAYGNQTE.js.map +0 -1
  118. package/dist/chunk-VTXCGKV5.js.map +0 -1
  119. package/dist/chunk-WUQQNE63.js.map +0 -1
  120. package/dist/chunk-Z5NXYJIG.js +0 -207
  121. package/dist/chunk-Z5NXYJIG.js.map +0 -1
  122. package/dist/init-F6PFMSU5.js +0 -21
  123. package/dist/neon-helpers-L5CXQ5CT.js +0 -11
  124. package/dist/recap-33NPZ3ZO.js.map +0 -1
  125. /package/dist/{BranchNamingService-GCCWB3LK.js.map → BranchNamingService-B5PVRR7F.js.map} +0 -0
  126. /package/dist/{ClaudeContextManager-DQFKIMEP.js.map → ClaudeContextManager-PQ46VILL.js.map} +0 -0
  127. /package/dist/{ClaudeService-CJS32WG2.js.map → ClaudeService-6OMO552H.js.map} +0 -0
  128. /package/dist/{GitHubService-RPM27GWD.js.map → GitHubService-S2OGUTDR.js.map} +0 -0
  129. /package/dist/{MetadataManager-WXUVXKUS.js.map → MetadataManager-DFI73J3G.js.map} +0 -0
  130. /package/dist/{PRManager-7DSIMCAD.js.map → PRManager-OCSB2HPT.js.map} +0 -0
  131. /package/dist/{PromptTemplateManager-72FEOGT6.js.map → PromptTemplateManager-5GNF7FCP.js.map} +0 -0
  132. /package/dist/{SettingsManager-XPR4TEQL.js.map → SettingsManager-CNYBGXDT.js.map} +0 -0
  133. /package/dist/{SettingsMigrationManager-EH3J2TCN.js.map → SettingsMigrationManager-KZKDG66H.js.map} +0 -0
  134. /package/dist/{chunk-OEGECBFS.js.map → chunk-3PT7RKL5.js.map} +0 -0
  135. /package/dist/{chunk-LN4H3A6A.js.map → chunk-53OMUNUN.js.map} +0 -0
  136. /package/dist/{chunk-THF25ICZ.js.map → chunk-5F6IWWRS.js.map} +0 -0
  137. /package/dist/{chunk-P2ZQ5LKB.js.map → chunk-5IWU3HXE.js.map} +0 -0
  138. /package/dist/{chunk-QIUJPPJQ.js.map → chunk-5TXLVEXT.js.map} +0 -0
  139. /package/dist/{chunk-6UIGZD2N.js.map → chunk-6MLEBAYZ.js.map} +0 -0
  140. /package/dist/{chunk-UNXRACJ7.js.map → chunk-7LSSNB7Y.js.map} +0 -0
  141. /package/dist/{chunk-QHA67Q7A.js.map → chunk-7Q66W4OH.js.map} +0 -0
  142. /package/dist/{chunk-MD6HA5IK.js.map → chunk-B2UO6EYE.js.map} +0 -0
  143. /package/dist/{chunk-YZTDGPFB.js.map → chunk-CFUWQHCJ.js.map} +0 -0
  144. /package/dist/{chunk-UYWAESOT.js.map → chunk-F2PWIRV4.js.map} +0 -0
  145. /package/dist/{chunk-PSFVTBM7.js.map → chunk-FXDYIV3K.js.map} +0 -0
  146. /package/dist/{chunk-CDQEK2WD.js.map → chunk-FXJKNVZW.js.map} +0 -0
  147. /package/dist/{chunk-3CMGCRB5.js.map → chunk-HMMO2LDS.js.map} +0 -0
  148. /package/dist/{chunk-OOU3DKNT.js.map → chunk-IDUICCZY.js.map} +0 -0
  149. /package/dist/{chunk-KO2FOMHL.js.map → chunk-LT3SGBR7.js.map} +0 -0
  150. /package/dist/{chunk-VBFDVGAE.js.map → chunk-LVLRMP7V.js.map} +0 -0
  151. /package/dist/{chunk-RNZMHJK7.js.map → chunk-N4ZJVATC.js.map} +0 -0
  152. /package/dist/{chunk-S65T4O6I.js.map → chunk-QPS6TZUW.js.map} +0 -0
  153. /package/dist/{chunk-RJKMF6BC.js.map → chunk-SHVB3EFE.js.map} +0 -0
  154. /package/dist/{chunk-4YTILIIH.js.map → chunk-VV66DH6T.js.map} +0 -0
  155. /package/dist/{chunk-GVRO4PWE.js.map → chunk-XNNXAAZT.js.map} +0 -0
  156. /package/dist/{chunk-AS2IRKLU.js.map → chunk-YU5HVI6B.js.map} +0 -0
  157. /package/dist/{chunk-SJ2GZ6RF.js.map → chunk-ZX3GTM7O.js.map} +0 -0
  158. /package/dist/{claude-ACVXNB6N.js.map → claude-H33OQMXO.js.map} +0 -0
  159. /package/dist/{color-ZPIIUADB.js.map → color-4TJ4P5EY.js.map} +0 -0
  160. /package/dist/{contribute-RS3DO3WP.js.map → contribute-K7UXBOML.js.map} +0 -0
  161. /package/dist/{git-OQAPUPLP.js.map → git-OV6ADVO7.js.map} +0 -0
  162. /package/dist/{init-F6PFMSU5.js.map → init-CMIRHFSR.js.map} +0 -0
  163. /package/dist/{installation-detector-6R6YOFVZ.js.map → installation-detector-VXZOCL6P.js.map} +0 -0
  164. /package/dist/{neon-helpers-L5CXQ5CT.js.map → neon-helpers-3KBC4A3Y.js.map} +0 -0
  165. /package/dist/{projects-QEAEBAT2.js.map → projects-GVEMCN5R.js.map} +0 -0
  166. /package/dist/{prompt-A7GGRHSY.js.map → prompt-3SAZYRUN.js.map} +0 -0
  167. /package/dist/{remote-73TZ2ADI.js.map → remote-IJAMOEAP.js.map} +0 -0
  168. /package/dist/{test-git-6SAIRBUD.js.map → test-git-CO3BA4BV.js.map} +0 -0
  169. /package/dist/{test-prefix-RLVRK5ZD.js.map → test-prefix-HZYSDQYT.js.map} +0 -0
  170. /package/dist/{test-webserver-VPNLAFZ3.js.map → test-webserver-YVQD42W6.js.map} +0 -0
  171. /package/dist/{update-LETF5ASC.js.map → update-5NOHT4SG.js.map} +0 -0
  172. /package/dist/{update-notifier-H55ZK7NU.js.map → update-notifier-ARA5SPUW.js.map} +0 -0
@@ -1 +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 { 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'\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) {}\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// 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
+ {"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 { 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'\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) {}\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// 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,28 +1,27 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  SessionSummaryService
4
- } from "./chunk-HABINPX2.js";
5
- import "./chunk-QHA67Q7A.js";
4
+ } from "./chunk-J7GHNTYK.js";
5
+ import "./chunk-NXMDEL3F.js";
6
+ import "./chunk-7Q66W4OH.js";
6
7
  import {
7
8
  GitWorktreeManager
8
- } from "./chunk-3CMGCRB5.js";
9
- import "./chunk-PSFVTBM7.js";
10
- import "./chunk-DKQ4SUII.js";
9
+ } from "./chunk-HMMO2LDS.js";
10
+ import "./chunk-FXDYIV3K.js";
11
+ import "./chunk-K5G5SFWY.js";
11
12
  import {
12
13
  extractIssueNumber
13
- } from "./chunk-LN4H3A6A.js";
14
- import "./chunk-OOU3DKNT.js";
14
+ } from "./chunk-53OMUNUN.js";
15
+ import "./chunk-IDUICCZY.js";
15
16
  import {
16
17
  MetadataManager
17
- } from "./chunk-YZTDGPFB.js";
18
- import "./chunk-KO2FOMHL.js";
19
- import "./chunk-RUC7OULH.js";
20
- import "./chunk-VAYGNQTE.js";
21
- import "./chunk-Z5NXYJIG.js";
18
+ } from "./chunk-CFUWQHCJ.js";
19
+ import "./chunk-LT3SGBR7.js";
20
+ import "./chunk-AEIMYF4P.js";
22
21
  import {
23
22
  getLogger
24
- } from "./chunk-6UIGZD2N.js";
25
- import "./chunk-UYVWLISQ.js";
23
+ } from "./chunk-6MLEBAYZ.js";
24
+ import "./chunk-VT4PDUYT.js";
26
25
 
27
26
  // src/commands/summary.ts
28
27
  import path from "path";
@@ -249,4 +248,4 @@ Please provide an issue number, PR number, or branch name.`
249
248
  export {
250
249
  SummaryCommand
251
250
  };
252
- //# sourceMappingURL=summary-4SSGGH7N.js.map
251
+ //# sourceMappingURL=summary-JUMOCNLR.js.map
@@ -1 +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 { 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'\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) {}\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\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)\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?.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?.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?.issue_numbers?.[0]) {\n\t\t\t\tissueNumber = 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?.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?.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?.issue_numbers?.[0]) {\n\t\t\t\tresolvedIssueNumber = 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
+ {"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 { 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'\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) {}\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\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)\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?.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?.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?.issue_numbers?.[0]) {\n\t\t\t\tissueNumber = 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?.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?.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?.issue_numbers?.[0]) {\n\t\t\t\tresolvedIssueNumber = 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,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  findMainWorktreePath
4
- } from "./chunk-LN4H3A6A.js";
4
+ } from "./chunk-53OMUNUN.js";
5
5
  import {
6
6
  SettingsManager
7
- } from "./chunk-OOU3DKNT.js";
8
- import "./chunk-YZTDGPFB.js";
9
- import "./chunk-6UIGZD2N.js";
7
+ } from "./chunk-IDUICCZY.js";
8
+ import "./chunk-CFUWQHCJ.js";
9
+ import "./chunk-6MLEBAYZ.js";
10
10
  import {
11
11
  logger
12
- } from "./chunk-UYVWLISQ.js";
12
+ } from "./chunk-VT4PDUYT.js";
13
13
 
14
14
  // src/commands/test-git.ts
15
15
  var TestGitCommand = class {
@@ -51,4 +51,4 @@ var TestGitCommand = class {
51
51
  export {
52
52
  TestGitCommand
53
53
  };
54
- //# sourceMappingURL=test-git-6SAIRBUD.js.map
54
+ //# sourceMappingURL=test-git-CO3BA4BV.js.map
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  generateWorktreePath
4
- } from "./chunk-LN4H3A6A.js";
4
+ } from "./chunk-53OMUNUN.js";
5
5
  import {
6
6
  SettingsManager
7
- } from "./chunk-OOU3DKNT.js";
8
- import "./chunk-YZTDGPFB.js";
9
- import "./chunk-6UIGZD2N.js";
7
+ } from "./chunk-IDUICCZY.js";
8
+ import "./chunk-CFUWQHCJ.js";
9
+ import "./chunk-6MLEBAYZ.js";
10
10
  import {
11
11
  logger
12
- } from "./chunk-UYVWLISQ.js";
12
+ } from "./chunk-VT4PDUYT.js";
13
13
 
14
14
  // src/commands/test-prefix.ts
15
15
  var TestPrefixCommand = class {
@@ -67,4 +67,4 @@ var TestPrefixCommand = class {
67
67
  export {
68
68
  TestPrefixCommand
69
69
  };
70
- //# sourceMappingURL=test-prefix-RLVRK5ZD.js.map
70
+ //# sourceMappingURL=test-prefix-HZYSDQYT.js.map
@@ -1,12 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  detectITerm2,
4
+ logger,
4
5
  openMultipleTerminalWindows
5
- } from "./chunk-VAYGNQTE.js";
6
- import "./chunk-Z5NXYJIG.js";
7
- import {
8
- logger
9
- } from "./chunk-UYVWLISQ.js";
6
+ } from "./chunk-VT4PDUYT.js";
10
7
 
11
8
  // src/commands/test-tabs.ts
12
9
  var TestTabsCommand = class {
@@ -67,4 +64,4 @@ var TestTabsCommand = class {
67
64
  export {
68
65
  TestTabsCommand
69
66
  };
70
- //# sourceMappingURL=test-tabs-3SCJWRKT.js.map
67
+ //# sourceMappingURL=test-tabs-D3POYOJ5.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/test-tabs.ts"],"sourcesContent":["import { logger } from '../utils/logger.js'\nimport { openMultipleTerminalWindows, detectITerm2 } from '../utils/terminal.js'\n\n/**\n * Input structure for TestTabsCommand.execute()\n */\nexport interface TestTabsCommandInput {\n options: Record<string, never>\n}\n\n/**\n * Test command to verify the iTerm2 multiple tab functionality\n * Opens three tabs with the same background color and runs simple test commands\n */\nexport class TestTabsCommand {\n /**\n * Main entry point for the test-tabs command\n * Opens multiple terminal tabs with test commands\n */\n public async execute(): Promise<void> {\n try {\n logger.info('Testing iTerm2 Multiple Tab Integration\\n')\n\n // Check if iTerm2 is available\n const hasITerm2 = await detectITerm2()\n\n if (!hasITerm2) {\n logger.warn('iTerm2 not detected. This command works best with iTerm2 installed.')\n logger.info('Falling back to Terminal.app with separate windows...\\n')\n } else {\n logger.info('iTerm2 detected. Opening multiple tabs in single window...\\n')\n }\n\n // Define test background color (light blue)\n const backgroundColor = { r: 235, g: 235, b: 250 }\n\n // Open multiple terminal tabs with test commands\n logger.info('Opening tabs with test commands...')\n\n await openMultipleTerminalWindows([\n {\n workspacePath: process.cwd(),\n command: 'echo \"Tab 1 test\" && echo \"Current directory: $(pwd)\"',\n backgroundColor,\n title: 'Test Tab 1'\n },\n {\n workspacePath: process.cwd(),\n command: 'echo \"Tab 2 test\" && echo \"Current directory: $(pwd)\"',\n backgroundColor,\n title: 'Test Tab 2'\n },\n {\n workspacePath: process.cwd(),\n command: 'echo \"Tab 3 test\" && echo \"Current directory: $(pwd)\"',\n backgroundColor,\n title: 'Test Tab 3'\n }\n ])\n\n logger.success('\\nMultiple tabs opened successfully!')\n logger.info('Check the terminal windows/tabs to verify:')\n logger.info(' - Three tabs/windows are open')\n logger.info(' - All have the same light blue background color')\n logger.info(' - Tab 1 shows \"Tab 1 test\"')\n logger.info(' - Tab 2 shows \"Tab 2 test\"')\n logger.info(' - Tab 3 shows \"Tab 3 test\"')\n logger.info(' - All show the current directory')\n\n } catch (error) {\n if (error instanceof Error) {\n logger.error(`Test failed: ${error.message}`)\n } else {\n logger.error('Test failed with unknown error')\n }\n throw error\n }\n }\n}\n"],"mappings":";;;;;;;;;;;AAcO,IAAM,kBAAN,MAAsB;AAAA;AAAA;AAAA;AAAA;AAAA,EAK3B,MAAa,UAAyB;AACpC,QAAI;AACF,aAAO,KAAK,2CAA2C;AAGvD,YAAM,YAAY,MAAM,aAAa;AAErC,UAAI,CAAC,WAAW;AACd,eAAO,KAAK,qEAAqE;AACjF,eAAO,KAAK,yDAAyD;AAAA,MACvE,OAAO;AACL,eAAO,KAAK,8DAA8D;AAAA,MAC5E;AAGA,YAAM,kBAAkB,EAAE,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI;AAGjD,aAAO,KAAK,oCAAoC;AAEhD,YAAM,4BAA4B;AAAA,QAChC;AAAA,UACE,eAAe,QAAQ,IAAI;AAAA,UAC3B,SAAS;AAAA,UACT;AAAA,UACA,OAAO;AAAA,QACT;AAAA,QACA;AAAA,UACE,eAAe,QAAQ,IAAI;AAAA,UAC3B,SAAS;AAAA,UACT;AAAA,UACA,OAAO;AAAA,QACT;AAAA,QACA;AAAA,UACE,eAAe,QAAQ,IAAI;AAAA,UAC3B,SAAS;AAAA,UACT;AAAA,UACA,OAAO;AAAA,QACT;AAAA,MACF,CAAC;AAED,aAAO,QAAQ,sCAAsC;AACrD,aAAO,KAAK,4CAA4C;AACxD,aAAO,KAAK,iCAAiC;AAC7C,aAAO,KAAK,mDAAmD;AAC/D,aAAO,KAAK,8BAA8B;AAC1C,aAAO,KAAK,8BAA8B;AAC1C,aAAO,KAAK,8BAA8B;AAC1C,aAAO,KAAK,oCAAoC;AAAA,IAElD,SAAS,OAAO;AACd,UAAI,iBAAiB,OAAO;AAC1B,eAAO,MAAM,gBAAgB,MAAM,OAAO,EAAE;AAAA,MAC9C,OAAO;AACL,eAAO,MAAM,gCAAgC;AAAA,MAC/C;AACA,YAAM;AAAA,IACR;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/commands/test-tabs.ts"],"sourcesContent":["import { logger } from '../utils/logger.js'\nimport { openMultipleTerminalWindows, detectITerm2 } from '../utils/terminal.js'\n\n/**\n * Input structure for TestTabsCommand.execute()\n */\nexport interface TestTabsCommandInput {\n options: Record<string, never>\n}\n\n/**\n * Test command to verify the iTerm2 multiple tab functionality\n * Opens three tabs with the same background color and runs simple test commands\n */\nexport class TestTabsCommand {\n /**\n * Main entry point for the test-tabs command\n * Opens multiple terminal tabs with test commands\n */\n public async execute(): Promise<void> {\n try {\n logger.info('Testing iTerm2 Multiple Tab Integration\\n')\n\n // Check if iTerm2 is available\n const hasITerm2 = await detectITerm2()\n\n if (!hasITerm2) {\n logger.warn('iTerm2 not detected. This command works best with iTerm2 installed.')\n logger.info('Falling back to Terminal.app with separate windows...\\n')\n } else {\n logger.info('iTerm2 detected. Opening multiple tabs in single window...\\n')\n }\n\n // Define test background color (light blue)\n const backgroundColor = { r: 235, g: 235, b: 250 }\n\n // Open multiple terminal tabs with test commands\n logger.info('Opening tabs with test commands...')\n\n await openMultipleTerminalWindows([\n {\n workspacePath: process.cwd(),\n command: 'echo \"Tab 1 test\" && echo \"Current directory: $(pwd)\"',\n backgroundColor,\n title: 'Test Tab 1'\n },\n {\n workspacePath: process.cwd(),\n command: 'echo \"Tab 2 test\" && echo \"Current directory: $(pwd)\"',\n backgroundColor,\n title: 'Test Tab 2'\n },\n {\n workspacePath: process.cwd(),\n command: 'echo \"Tab 3 test\" && echo \"Current directory: $(pwd)\"',\n backgroundColor,\n title: 'Test Tab 3'\n }\n ])\n\n logger.success('\\nMultiple tabs opened successfully!')\n logger.info('Check the terminal windows/tabs to verify:')\n logger.info(' - Three tabs/windows are open')\n logger.info(' - All have the same light blue background color')\n logger.info(' - Tab 1 shows \"Tab 1 test\"')\n logger.info(' - Tab 2 shows \"Tab 2 test\"')\n logger.info(' - Tab 3 shows \"Tab 3 test\"')\n logger.info(' - All show the current directory')\n\n } catch (error) {\n if (error instanceof Error) {\n logger.error(`Test failed: ${error.message}`)\n } else {\n logger.error('Test failed with unknown error')\n }\n throw error\n }\n }\n}\n"],"mappings":";;;;;;;;AAcO,IAAM,kBAAN,MAAsB;AAAA;AAAA;AAAA;AAAA;AAAA,EAK3B,MAAa,UAAyB;AACpC,QAAI;AACF,aAAO,KAAK,2CAA2C;AAGvD,YAAM,YAAY,MAAM,aAAa;AAErC,UAAI,CAAC,WAAW;AACd,eAAO,KAAK,qEAAqE;AACjF,eAAO,KAAK,yDAAyD;AAAA,MACvE,OAAO;AACL,eAAO,KAAK,8DAA8D;AAAA,MAC5E;AAGA,YAAM,kBAAkB,EAAE,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI;AAGjD,aAAO,KAAK,oCAAoC;AAEhD,YAAM,4BAA4B;AAAA,QAChC;AAAA,UACE,eAAe,QAAQ,IAAI;AAAA,UAC3B,SAAS;AAAA,UACT;AAAA,UACA,OAAO;AAAA,QACT;AAAA,QACA;AAAA,UACE,eAAe,QAAQ,IAAI;AAAA,UAC3B,SAAS;AAAA,UACT;AAAA,UACA,OAAO;AAAA,QACT;AAAA,QACA;AAAA,UACE,eAAe,QAAQ,IAAI;AAAA,UAC3B,SAAS;AAAA,UACT;AAAA,UACA,OAAO;AAAA,QACT;AAAA,MACF,CAAC;AAED,aAAO,QAAQ,sCAAsC;AACrD,aAAO,KAAK,4CAA4C;AACxD,aAAO,KAAK,iCAAiC;AAC7C,aAAO,KAAK,mDAAmD;AAC/D,aAAO,KAAK,8BAA8B;AAC1C,aAAO,KAAK,8BAA8B;AAC1C,aAAO,KAAK,8BAA8B;AAC1C,aAAO,KAAK,oCAAoC;AAAA,IAElD,SAAS,OAAO;AACd,UAAI,iBAAiB,OAAO;AAC1B,eAAO,MAAM,gBAAgB,MAAM,OAAO,EAAE;AAAA,MAC9C,OAAO;AACL,eAAO,MAAM,gCAAgC;AAAA,MAC/C;AACA,YAAM;AAAA,IACR;AAAA,EACF;AACF;","names":[]}
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-VU3QMIP2.js";
5
5
  import {
6
6
  logger
7
- } from "./chunk-UYVWLISQ.js";
7
+ } from "./chunk-VT4PDUYT.js";
8
8
 
9
9
  // src/commands/test-webserver.ts
10
10
  var TestWebserverCommand = class {
@@ -59,4 +59,4 @@ var TestWebserverCommand = class {
59
59
  export {
60
60
  TestWebserverCommand
61
61
  };
62
- //# sourceMappingURL=test-webserver-VPNLAFZ3.js.map
62
+ //# sourceMappingURL=test-webserver-YVQD42W6.js.map
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  UpdateNotifier
4
- } from "./chunk-MD6HA5IK.js";
4
+ } from "./chunk-B2UO6EYE.js";
5
5
  import {
6
6
  detectInstallationMethod
7
- } from "./chunk-THF25ICZ.js";
7
+ } from "./chunk-5F6IWWRS.js";
8
8
  import {
9
9
  logger
10
- } from "./chunk-UYVWLISQ.js";
10
+ } from "./chunk-VT4PDUYT.js";
11
11
 
12
12
  // src/commands/update.ts
13
13
  import { spawn } from "child_process";
@@ -82,4 +82,4 @@ var UpdateCommand = class {
82
82
  export {
83
83
  UpdateCommand
84
84
  };
85
- //# sourceMappingURL=update-LETF5ASC.js.map
85
+ //# sourceMappingURL=update-5NOHT4SG.js.map
@@ -2,10 +2,10 @@
2
2
  import {
3
3
  UpdateNotifier,
4
4
  checkAndNotifyUpdate
5
- } from "./chunk-MD6HA5IK.js";
6
- import "./chunk-UYVWLISQ.js";
5
+ } from "./chunk-B2UO6EYE.js";
6
+ import "./chunk-VT4PDUYT.js";
7
7
  export {
8
8
  UpdateNotifier,
9
9
  checkAndNotifyUpdate
10
10
  };
11
- //# sourceMappingURL=update-notifier-H55ZK7NU.js.map
11
+ //# sourceMappingURL=update-notifier-ARA5SPUW.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iloom/cli",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
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,16 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- ClaudeContextManager
4
- } from "./chunk-S65T4O6I.js";
5
- import "./chunk-CDQEK2WD.js";
6
- import "./chunk-DKQ4SUII.js";
7
- import "./chunk-OOU3DKNT.js";
8
- import "./chunk-RUC7OULH.js";
9
- import "./chunk-VAYGNQTE.js";
10
- import "./chunk-Z5NXYJIG.js";
11
- import "./chunk-6UIGZD2N.js";
12
- import "./chunk-UYVWLISQ.js";
13
- export {
14
- ClaudeContextManager
15
- };
16
- //# sourceMappingURL=ClaudeContextManager-DQFKIMEP.js.map
@@ -1,15 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- ClaudeService
4
- } from "./chunk-CDQEK2WD.js";
5
- import "./chunk-DKQ4SUII.js";
6
- import "./chunk-OOU3DKNT.js";
7
- import "./chunk-RUC7OULH.js";
8
- import "./chunk-VAYGNQTE.js";
9
- import "./chunk-Z5NXYJIG.js";
10
- import "./chunk-6UIGZD2N.js";
11
- import "./chunk-UYVWLISQ.js";
12
- export {
13
- ClaudeService
14
- };
15
- //# sourceMappingURL=ClaudeService-CJS32WG2.js.map
@@ -1,12 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- GitHubService
4
- } from "./chunk-OEGECBFS.js";
5
- import "./chunk-KO2FOMHL.js";
6
- import "./chunk-SJ2GZ6RF.js";
7
- import "./chunk-6UIGZD2N.js";
8
- import "./chunk-UYVWLISQ.js";
9
- export {
10
- GitHubService
11
- };
12
- //# sourceMappingURL=GitHubService-RPM27GWD.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/lib/LoomLauncher.ts","../src/utils/ide.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}\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\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","import { execa } from 'execa'\nimport { logger } from './logger.js'\nimport type { IdeSettings } from '../lib/SettingsManager.js'\n\n// IDE preset configuration\nconst IDE_PRESETS = {\n\tvscode: { command: 'code', name: 'Visual Studio Code', args: [] },\n\tcursor: { command: 'cursor', name: 'Cursor', args: [] },\n\twebstorm: { command: 'webstorm', name: 'WebStorm', args: ['--nosplash'] },\n\tsublime: { command: 'subl', name: 'Sublime Text', args: [] },\n\tintellij: { command: 'idea', name: 'IntelliJ IDEA', args: ['--nosplash'] },\n\twindsurf: { command: 'surf', name: 'Windsurf', args: [] },\n\tantigravity: { command: 'agy', name: 'Antigravity', args: [] },\n} as const\n\ntype IdePreset = keyof typeof IDE_PRESETS\n\n// Resolve IDE configuration to command and args\nexport function getIdeConfig(ideSettings?: IdeSettings): {\n\tcommand: string\n\targs: string[]\n\tname: string\n} {\n\t// Default to vscode if not configured\n\tconst type = ideSettings?.type ?? 'vscode'\n\n\tconst preset = IDE_PRESETS[type as IdePreset]\n\treturn {\n\t\tcommand: preset.command,\n\t\targs: [...preset.args],\n\t\tname: preset.name,\n\t}\n}\n\n// Check if IDE is available\nexport async function isIdeAvailable(command: string): Promise<boolean> {\n\ttry {\n\t\tawait execa('command', ['-v', command], { shell: true, timeout: 5000 })\n\t\treturn true\n\t} catch {\n\t\treturn false\n\t}\n}\n\n// Get installation hint for IDE\nfunction getInstallHint(type: string): string {\n\tconst hints: Record<string, string> = {\n\t\tvscode:\n\t\t\t'Install command-line tools: Open VSCode > Command Palette > \"Shell Command: Install \\'code\\' command in PATH\"',\n\t\tcursor:\n\t\t\t'Install command-line tools: Open Cursor > Command Palette > \"Install \\'cursor\\' command in PATH\"',\n\t\twebstorm: 'Install via JetBrains Toolbox > Settings > Shell Scripts > Enable',\n\t\tsublime:\n\t\t\t'Create symlink: ln -s \"/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl\" /usr/local/bin/subl',\n\t\tintellij: 'Install via JetBrains Toolbox > Settings > Shell Scripts > Enable',\n\t\twindsurf:\n\t\t\t'Install command-line tools during Windsurf installation or create symlink manually',\n\t\tantigravity:\n\t\t\t'Install command-line tools during Antigravity installation or create symlink manually',\n\t}\n\treturn hints[type] ?? `Ensure the IDE command is available in your PATH`\n}\n\n// Open IDE window for workspace\nexport async function openIdeWindow(\n\tworkspacePath: string,\n\tideSettings?: IdeSettings\n): Promise<void> {\n\tconst config = getIdeConfig(ideSettings)\n\tconst available = await isIdeAvailable(config.command)\n\n\tif (!available) {\n\t\tconst type = ideSettings?.type ?? 'vscode'\n\t\tthrow new Error(\n\t\t\t`${config.name} is not available. The \"${config.command}\" command was not found in PATH.\\n` +\n\t\t\t\tgetInstallHint(type)\n\t\t)\n\t}\n\n\ttry {\n\t\tawait execa(config.command, [...config.args, workspacePath])\n\t\tlogger.debug(`Opened ${config.name} for workspace: ${workspacePath}`)\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`Failed to open ${config.name}: ${error instanceof Error ? error.message : 'Unknown error'}`\n\t\t)\n\t}\n}\n"],"mappings":"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","names":[]}
@@ -1,10 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- MetadataManager
4
- } from "./chunk-YZTDGPFB.js";
5
- import "./chunk-6UIGZD2N.js";
6
- import "./chunk-UYVWLISQ.js";
7
- export {
8
- MetadataManager
9
- };
10
- //# sourceMappingURL=MetadataManager-WXUVXKUS.js.map
@@ -1,16 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- PRManager
4
- } from "./chunk-P2ZQ5LKB.js";
5
- import "./chunk-YETJNRQM.js";
6
- import "./chunk-PSFVTBM7.js";
7
- import "./chunk-KO2FOMHL.js";
8
- import "./chunk-RUC7OULH.js";
9
- import "./chunk-VAYGNQTE.js";
10
- import "./chunk-Z5NXYJIG.js";
11
- import "./chunk-6UIGZD2N.js";
12
- import "./chunk-UYVWLISQ.js";
13
- export {
14
- PRManager
15
- };
16
- //# sourceMappingURL=PRManager-7DSIMCAD.js.map
@@ -1,9 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- PromptTemplateManager
4
- } from "./chunk-DKQ4SUII.js";
5
- import "./chunk-UYVWLISQ.js";
6
- export {
7
- PromptTemplateManager
8
- };
9
- //# sourceMappingURL=PromptTemplateManager-72FEOGT6.js.map
@@ -1,10 +0,0 @@
1
- #!/usr/bin/env node
2
- import {
3
- SettingsMigrationManager
4
- } from "./chunk-UYWAESOT.js";
5
- import "./chunk-SJ2GZ6RF.js";
6
- import "./chunk-UYVWLISQ.js";
7
- export {
8
- SettingsMigrationManager
9
- };
10
- //# sourceMappingURL=SettingsMigrationManager-EH3J2TCN.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/lib/PromptTemplateManager.ts"],"sourcesContent":["import { readFile } from 'fs/promises'\nimport { accessSync } from 'fs'\nimport path from 'path'\nimport { fileURLToPath } from 'url'\nimport { logger } from '../utils/logger.js'\n\nexport interface TemplateVariables {\n\tISSUE_NUMBER?: string | number\n\tPR_NUMBER?: number\n\tISSUE_TITLE?: string\n\tPR_TITLE?: string\n\tWORKSPACE_PATH?: string\n\tPORT?: number\n\tONE_SHOT_MODE?: boolean\n\tINTERACTIVE_MODE?: boolean\n\tSETTINGS_SCHEMA?: string\n\tSETTINGS_GLOBAL_JSON?: string\n\tSETTINGS_JSON?: string\n\tSETTINGS_LOCAL_JSON?: string\n\tSHELL_TYPE?: string\n\tSHELL_CONFIG_PATH?: string\n\tSHELL_CONFIG_CONTENT?: string\n\tREMOTES_INFO?: string\n\tMULTIPLE_REMOTES?: string\n\tSINGLE_REMOTE?: string\n\tSINGLE_REMOTE_NAME?: string\n\tSINGLE_REMOTE_URL?: string\n\tNO_REMOTES?: string\n\tREADME_CONTENT?: string\n\tSETTINGS_SCHEMA_CONTENT?: string\n\tFIRST_TIME_USER?: boolean\n\tVSCODE_SETTINGS_GITIGNORED?: string\n\t// Session summary template variables\n\tSESSION_CONTEXT?: string // Session ID for Claude to reference its conversation\n\tBRANCH_NAME?: string // Branch being finished\n\tLOOM_TYPE?: string // 'issue' or 'pr'\n\tCOMPACT_SUMMARIES?: string // Extracted compact summaries from session transcript\n\t// Draft PR mode variables - mutually exclusive with standard issue mode\n\tDRAFT_PR_NUMBER?: number // PR number for draft PR workflow\n\tDRAFT_PR_MODE?: boolean // True when using github-draft-pr merge mode\n\tSTANDARD_ISSUE_MODE?: boolean // True when using standard issue commenting (not draft PR)\n}\n\nexport class PromptTemplateManager {\n\tprivate templateDir: string\n\n\tconstructor(templateDir?: string) {\n\t\tif (templateDir) {\n\t\t\tthis.templateDir = templateDir\n\t\t} else {\n\t\t\t// Find templates relative to the package installation\n\t\t\t// When running from dist/, templates are copied to dist/prompts/\n\t\t\tconst currentFileUrl = import.meta.url\n\t\t\tconst currentFilePath = fileURLToPath(currentFileUrl)\n\t\t\tconst distDir = path.dirname(currentFilePath) // dist directory (may be chunked file location)\n\n\t\t\t// Walk up to find the dist directory (in case of chunked files)\n\t\t\tlet templateDir = path.join(distDir, 'prompts')\n\t\t\tlet currentDir = distDir\n\n\t\t\t// Try to find the prompts directory by walking up\n\t\t\twhile (currentDir !== path.dirname(currentDir)) {\n\t\t\t\tconst candidatePath = path.join(currentDir, 'prompts')\n\t\t\t\ttry {\n\t\t\t\t\t// Check if this directory exists (sync check for constructor)\n\t\t\t\t\taccessSync(candidatePath)\n\t\t\t\t\ttemplateDir = candidatePath\n\t\t\t\t\tbreak\n\t\t\t\t} catch {\n\t\t\t\t\tcurrentDir = path.dirname(currentDir)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.templateDir = templateDir\n\t\t\tlogger.debug('PromptTemplateManager initialized', {\n\t\t\t\tcurrentFilePath,\n\t\t\t\tdistDir,\n\t\t\t\ttemplateDir: this.templateDir\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Load a template file by name\n\t */\n\tasync loadTemplate(templateName: 'issue' | 'pr' | 'regular' | 'init' | 'session-summary'): Promise<string> {\n\t\tconst templatePath = path.join(this.templateDir, `${templateName}-prompt.txt`)\n\n\t\tlogger.debug('Loading template', {\n\t\t\ttemplateName,\n\t\t\ttemplateDir: this.templateDir,\n\t\t\ttemplatePath\n\t\t})\n\n\t\ttry {\n\t\t\treturn await readFile(templatePath, 'utf-8')\n\t\t} catch (error) {\n\t\t\tlogger.error('Failed to load template', { templateName, templatePath, error })\n\t\t\tthrow new Error(`Template not found: ${templatePath}`)\n\t\t}\n\t}\n\n\t/**\n\t * Substitute variables in a template string\n\t */\n\tsubstituteVariables(template: string, variables: TemplateVariables): string {\n\t\tlet result = template\n\n\t\t// Process conditional sections first\n\t\tresult = this.processConditionalSections(result, variables)\n\n\t\t// Replace each variable if it exists\n\t\tif (variables.ISSUE_NUMBER !== undefined) {\n\t\t\tresult = result.replace(/ISSUE_NUMBER/g, String(variables.ISSUE_NUMBER))\n\t\t}\n\n\t\tif (variables.PR_NUMBER !== undefined) {\n\t\t\tresult = result.replace(/PR_NUMBER/g, String(variables.PR_NUMBER))\n\t\t}\n\n\t\tif (variables.ISSUE_TITLE !== undefined) {\n\t\t\tresult = result.replace(/ISSUE_TITLE/g, variables.ISSUE_TITLE)\n\t\t}\n\n\t\tif (variables.PR_TITLE !== undefined) {\n\t\t\tresult = result.replace(/PR_TITLE/g, variables.PR_TITLE)\n\t\t}\n\n\t\tif (variables.WORKSPACE_PATH !== undefined) {\n\t\t\tresult = result.replace(/WORKSPACE_PATH/g, variables.WORKSPACE_PATH)\n\t\t}\n\n\t\tif (variables.PORT !== undefined) {\n\t\t\tresult = result.replace(/PORT/g, String(variables.PORT))\n\t\t}\n\n\t\tif (variables.SETTINGS_SCHEMA !== undefined) {\n\t\t\tresult = result.replace(/SETTINGS_SCHEMA/g, variables.SETTINGS_SCHEMA)\n\t\t}\n\n\t\tif (variables.SETTINGS_GLOBAL_JSON !== undefined) {\n\t\t\tresult = result.replace(/SETTINGS_GLOBAL_JSON/g, variables.SETTINGS_GLOBAL_JSON)\n\t\t}\n\n\t\tif (variables.SETTINGS_JSON !== undefined) {\n\t\t\tresult = result.replace(/SETTINGS_JSON/g, variables.SETTINGS_JSON)\n\t\t}\n\n\t\tif (variables.SETTINGS_LOCAL_JSON !== undefined) {\n\t\t\tresult = result.replace(/SETTINGS_LOCAL_JSON/g, variables.SETTINGS_LOCAL_JSON)\n\t\t}\n\n\t\tif (variables.SHELL_TYPE !== undefined) {\n\t\t\tresult = result.replace(/SHELL_TYPE/g, variables.SHELL_TYPE)\n\t\t}\n\n\t\tif (variables.SHELL_CONFIG_PATH !== undefined) {\n\t\t\tresult = result.replace(/SHELL_CONFIG_PATH/g, variables.SHELL_CONFIG_PATH)\n\t\t}\n\n\t\tif (variables.SHELL_CONFIG_CONTENT !== undefined) {\n\t\t\tresult = result.replace(/SHELL_CONFIG_CONTENT/g, variables.SHELL_CONFIG_CONTENT)\n\t\t}\n\n\t\tif (variables.REMOTES_INFO !== undefined) {\n\t\t\tresult = result.replace(/REMOTES_INFO/g, variables.REMOTES_INFO)\n\t\t}\n\n\t\tif (variables.MULTIPLE_REMOTES !== undefined) {\n\t\t\tresult = result.replace(/MULTIPLE_REMOTES/g, variables.MULTIPLE_REMOTES)\n\t\t}\n\n\t\tif (variables.SINGLE_REMOTE !== undefined) {\n\t\t\tresult = result.replace(/SINGLE_REMOTE/g, variables.SINGLE_REMOTE)\n\t\t}\n\n\t\tif (variables.SINGLE_REMOTE_NAME !== undefined) {\n\t\t\tresult = result.replace(/SINGLE_REMOTE_NAME/g, variables.SINGLE_REMOTE_NAME)\n\t\t}\n\n\t\tif (variables.SINGLE_REMOTE_URL !== undefined) {\n\t\t\tresult = result.replace(/SINGLE_REMOTE_URL/g, variables.SINGLE_REMOTE_URL)\n\t\t}\n\n\t\tif (variables.NO_REMOTES !== undefined) {\n\t\t\tresult = result.replace(/NO_REMOTES/g, variables.NO_REMOTES)\n\t\t}\n\n\t\tif (variables.README_CONTENT !== undefined) {\n\t\t\tresult = result.replace(/README_CONTENT/g, variables.README_CONTENT)\n\t\t}\n\n\t\tif (variables.SETTINGS_SCHEMA_CONTENT !== undefined) {\n\t\t\tresult = result.replace(/SETTINGS_SCHEMA_CONTENT/g, variables.SETTINGS_SCHEMA_CONTENT)\n\t\t}\n\n\t\tif (variables.VSCODE_SETTINGS_GITIGNORED !== undefined) {\n\t\t\tresult = result.replace(/VSCODE_SETTINGS_GITIGNORED/g, variables.VSCODE_SETTINGS_GITIGNORED)\n\t\t}\n\n\t\t// Session summary template variables\n\t\tif (variables.SESSION_CONTEXT !== undefined) {\n\t\t\tresult = result.replace(/SESSION_CONTEXT/g, variables.SESSION_CONTEXT)\n\t\t}\n\n\t\tif (variables.BRANCH_NAME !== undefined) {\n\t\t\tresult = result.replace(/BRANCH_NAME/g, variables.BRANCH_NAME)\n\t\t}\n\n\t\tif (variables.LOOM_TYPE !== undefined) {\n\t\t\tresult = result.replace(/LOOM_TYPE/g, variables.LOOM_TYPE)\n\t\t}\n\n\t\tif (variables.COMPACT_SUMMARIES !== undefined) {\n\t\t\tresult = result.replace(/COMPACT_SUMMARIES/g, variables.COMPACT_SUMMARIES)\n\t\t}\n\n\t\t// Draft PR mode variable substitution\n\t\tif (variables.DRAFT_PR_NUMBER !== undefined) {\n\t\t\tresult = result.replace(/DRAFT_PR_NUMBER/g, String(variables.DRAFT_PR_NUMBER))\n\t\t}\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Process conditional sections in template\n\t * Format: {{#IF ONE_SHOT_MODE}}content{{/IF ONE_SHOT_MODE}}\n\t *\n\t * Note: /s flag allows . to match newlines\n\t */\n\tprivate processConditionalSections(template: string, variables: TemplateVariables): string {\n\t\tlet result = template\n\n\t\t// Process ONE_SHOT_MODE conditionals\n\t\tconst oneShotRegex = /\\{\\{#IF ONE_SHOT_MODE\\}\\}(.*?)\\{\\{\\/IF ONE_SHOT_MODE\\}\\}/gs\n\n\t\tif (variables.ONE_SHOT_MODE === true) {\n\t\t\t// Include the content, remove the conditional markers\n\t\t\tresult = result.replace(oneShotRegex, '$1')\n\t\t} else {\n\t\t\t// Remove the entire conditional block\n\t\t\tresult = result.replace(oneShotRegex, '')\n\t\t}\n\n\t\t// Process SETTINGS_JSON conditionals\n\t\tconst settingsJsonRegex = /\\{\\{#IF SETTINGS_JSON\\}\\}(.*?)\\{\\{\\/IF SETTINGS_JSON\\}\\}/gs\n\n\t\tif (variables.SETTINGS_JSON !== undefined && variables.SETTINGS_JSON !== '') {\n\t\t\t// Include the content, remove the conditional markers\n\t\t\tresult = result.replace(settingsJsonRegex, '$1')\n\t\t} else {\n\t\t\t// Remove the entire conditional block\n\t\t\tresult = result.replace(settingsJsonRegex, '')\n\t\t}\n\n\t\t// Process SETTINGS_GLOBAL_JSON conditionals\n\t\tconst settingsGlobalJsonRegex = /\\{\\{#IF SETTINGS_GLOBAL_JSON\\}\\}(.*?)\\{\\{\\/IF SETTINGS_GLOBAL_JSON\\}\\}/gs\n\n\t\tif (variables.SETTINGS_GLOBAL_JSON !== undefined && variables.SETTINGS_GLOBAL_JSON !== '') {\n\t\t\t// Include the content, remove the conditional markers\n\t\t\tresult = result.replace(settingsGlobalJsonRegex, '$1')\n\t\t} else {\n\t\t\t// Remove the entire conditional block\n\t\t\tresult = result.replace(settingsGlobalJsonRegex, '')\n\t\t}\n\n\t\t// Process SETTINGS_LOCAL_JSON conditionals\n\t\tconst settingsLocalJsonRegex = /\\{\\{#IF SETTINGS_LOCAL_JSON\\}\\}(.*?)\\{\\{\\/IF SETTINGS_LOCAL_JSON\\}\\}/gs\n\n\t\tif (variables.SETTINGS_LOCAL_JSON !== undefined && variables.SETTINGS_LOCAL_JSON !== '') {\n\t\t\t// Include the content, remove the conditional markers\n\t\t\tresult = result.replace(settingsLocalJsonRegex, '$1')\n\t\t} else {\n\t\t\t// Remove the entire conditional block\n\t\t\tresult = result.replace(settingsLocalJsonRegex, '')\n\t\t}\n\n\t\t// Process MULTIPLE_REMOTES conditionals\n\t\tconst multipleRemotesRegex = /\\{\\{#IF MULTIPLE_REMOTES\\}\\}(.*?)\\{\\{\\/IF MULTIPLE_REMOTES\\}\\}/gs\n\n\t\tif (variables.MULTIPLE_REMOTES !== undefined && variables.MULTIPLE_REMOTES !== '') {\n\t\t\t// Include the content, remove the conditional markers\n\t\t\tresult = result.replace(multipleRemotesRegex, '$1')\n\t\t} else {\n\t\t\t// Remove the entire conditional block\n\t\t\tresult = result.replace(multipleRemotesRegex, '')\n\t\t}\n\n\t\t// Process SINGLE_REMOTE conditionals\n\t\tconst singleRemoteRegex = /\\{\\{#IF SINGLE_REMOTE\\}\\}(.*?)\\{\\{\\/IF SINGLE_REMOTE\\}\\}/gs\n\n\t\tif (variables.SINGLE_REMOTE !== undefined && variables.SINGLE_REMOTE !== '') {\n\t\t\t// Include the content, remove the conditional markers\n\t\t\tresult = result.replace(singleRemoteRegex, '$1')\n\t\t} else {\n\t\t\t// Remove the entire conditional block\n\t\t\tresult = result.replace(singleRemoteRegex, '')\n\t\t}\n\n\t\t// Process NO_REMOTES conditionals\n\t\tconst noRemotesRegex = /\\{\\{#IF NO_REMOTES\\}\\}(.*?)\\{\\{\\/IF NO_REMOTES\\}\\}/gs\n\n\t\tif (variables.NO_REMOTES !== undefined && variables.NO_REMOTES !== '') {\n\t\t\t// Include the content, remove the conditional markers\n\t\t\tresult = result.replace(noRemotesRegex, '$1')\n\t\t} else {\n\t\t\t// Remove the entire conditional block\n\t\t\tresult = result.replace(noRemotesRegex, '')\n\t\t}\n\n\t\t// Process FIRST_TIME_USER conditionals\n\t\tconst firstTimeUserRegex = /\\{\\{#IF FIRST_TIME_USER\\}\\}(.*?)\\{\\{\\/IF FIRST_TIME_USER\\}\\}/gs\n\n\t\tif (variables.FIRST_TIME_USER === true) {\n\t\t\t// Include the content, remove the conditional markers\n\t\t\tresult = result.replace(firstTimeUserRegex, '$1')\n\t\t} else {\n\t\t\t// Remove the entire conditional block\n\t\t\tresult = result.replace(firstTimeUserRegex, '')\n\t\t}\n\n\t\t// Process INTERACTIVE_MODE conditionals\n\t\tconst interactiveModeRegex = /\\{\\{#IF INTERACTIVE_MODE\\}\\}(.*?)\\{\\{\\/IF INTERACTIVE_MODE\\}\\}/gs\n\n\t\tif (variables.INTERACTIVE_MODE === true) {\n\t\t\t// Include the content, remove the conditional markers\n\t\t\tresult = result.replace(interactiveModeRegex, '$1')\n\t\t} else {\n\t\t\t// Remove the entire conditional block\n\t\t\tresult = result.replace(interactiveModeRegex, '')\n\t\t}\n\n\t\t// Process COMPACT_SUMMARIES conditionals\n\t\tconst compactSummariesRegex = /\\{\\{#IF COMPACT_SUMMARIES\\}\\}(.*?)\\{\\{\\/IF COMPACT_SUMMARIES\\}\\}/gs\n\n\t\tif (variables.COMPACT_SUMMARIES !== undefined && variables.COMPACT_SUMMARIES !== '') {\n\t\t\t// Include the content, remove the conditional markers\n\t\t\tresult = result.replace(compactSummariesRegex, '$1')\n\t\t} else {\n\t\t\t// Remove the entire conditional block\n\t\t\tresult = result.replace(compactSummariesRegex, '')\n\t\t}\n\n\t\t// Process DRAFT_PR_MODE conditionals\n\t\tconst draftPrModeRegex = /\\{\\{#IF DRAFT_PR_MODE\\}\\}(.*?)\\{\\{\\/IF DRAFT_PR_MODE\\}\\}/gs\n\n\t\tif (variables.DRAFT_PR_MODE === true) {\n\t\t\t// Include the content, remove the conditional markers\n\t\t\tresult = result.replace(draftPrModeRegex, '$1')\n\t\t} else {\n\t\t\t// Remove the entire conditional block\n\t\t\tresult = result.replace(draftPrModeRegex, '')\n\t\t}\n\n\t\t// Process STANDARD_ISSUE_MODE conditionals\n\t\tconst standardIssueModeRegex = /\\{\\{#IF STANDARD_ISSUE_MODE\\}\\}(.*?)\\{\\{\\/IF STANDARD_ISSUE_MODE\\}\\}/gs\n\n\t\tif (variables.STANDARD_ISSUE_MODE === true) {\n\t\t\t// Include the content, remove the conditional markers\n\t\t\tresult = result.replace(standardIssueModeRegex, '$1')\n\t\t} else {\n\t\t\t// Remove the entire conditional block\n\t\t\tresult = result.replace(standardIssueModeRegex, '')\n\t\t}\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Get a fully processed prompt for a workflow type\n\t */\n\tasync getPrompt(\n\t\ttype: 'issue' | 'pr' | 'regular' | 'init' | 'session-summary',\n\t\tvariables: TemplateVariables\n\t): Promise<string> {\n\t\tconst template = await this.loadTemplate(type)\n\t\treturn this.substituteVariables(template, variables)\n\t}\n}\n"],"mappings":"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","names":["templateDir"]}