@iloom/cli 0.8.3 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +50 -4
  3. package/dist/{BranchNamingService-AO7BPIUJ.js → BranchNamingService-K6XNWQ6C.js} +2 -2
  4. package/dist/ClaudeContextManager-X2Y72GRL.js +14 -0
  5. package/dist/ClaudeService-7P32TTES.js +13 -0
  6. package/dist/{GitHubService-ACZVNTJE.js → GitHubService-O7T6CFAJ.js} +3 -3
  7. package/dist/{LoomLauncher-NHZMEVTQ.js → LoomLauncher-3I47SUPV.js} +6 -6
  8. package/dist/{ProjectCapabilityDetector-IA56AUE6.js → ProjectCapabilityDetector-N5L7T4IY.js} +3 -3
  9. package/dist/PromptTemplateManager-36YLQRHP.js +11 -0
  10. package/dist/README.md +50 -4
  11. package/dist/{SettingsManager-VCVLL32H.js → SettingsManager-QR7V2IW2.js} +2 -2
  12. package/dist/agents/iloom-artifact-reviewer.md +280 -0
  13. package/dist/agents/iloom-code-reviewer.md +9 -7
  14. package/dist/agents/iloom-issue-analyze-and-plan.md +21 -6
  15. package/dist/agents/iloom-issue-analyzer.md +21 -6
  16. package/dist/agents/iloom-issue-complexity-evaluator.md +21 -6
  17. package/dist/agents/iloom-issue-enhancer.md +21 -6
  18. package/dist/agents/iloom-issue-implementer.md +21 -6
  19. package/dist/agents/iloom-issue-planner.md +21 -6
  20. package/dist/{build-Z3WCIKPD.js → build-IC4CJRMP.js} +8 -8
  21. package/dist/{chunk-TVH67KEO.js → chunk-2HZX6AMR.js} +2 -2
  22. package/dist/{chunk-VZYSM7N7.js → chunk-2JPXGGP4.js} +20 -15
  23. package/dist/chunk-2JPXGGP4.js.map +1 -0
  24. package/dist/{chunk-SC6X5EBG.js → chunk-3P6J4IZZ.js} +3 -3
  25. package/dist/{chunk-HSGZW3ID.js → chunk-4GAJJUYS.js} +3 -3
  26. package/dist/chunk-4GAJJUYS.js.map +1 -0
  27. package/dist/{chunk-RD7I2Q2F.js → chunk-4LKGCFGG.js} +2 -2
  28. package/dist/{chunk-GWONJE3X.js → chunk-4ZIHFUPN.js} +226 -62
  29. package/dist/chunk-4ZIHFUPN.js.map +1 -0
  30. package/dist/{chunk-SSASIBDJ.js → chunk-5LVVQGB3.js} +5 -5
  31. package/dist/{chunk-4BSXZ5YZ.js → chunk-B7U6OKUR.js} +5 -24
  32. package/dist/chunk-B7U6OKUR.js.map +1 -0
  33. package/dist/{chunk-RNBIISBZ.js → chunk-ENGCJIYQ.js} +48 -3
  34. package/dist/chunk-ENGCJIYQ.js.map +1 -0
  35. package/dist/{chunk-IGKPPACU.js → chunk-FO5GGFOV.js} +17 -8
  36. package/dist/chunk-FO5GGFOV.js.map +1 -0
  37. package/dist/{chunk-GDS2HXSW.js → chunk-H6ST2TGP.js} +20 -3
  38. package/dist/chunk-H6ST2TGP.js.map +1 -0
  39. package/dist/{chunk-A7XHHUEV.js → chunk-HZXBHMVM.js} +47 -22
  40. package/dist/chunk-HZXBHMVM.js.map +1 -0
  41. package/dist/{chunk-44Y5IF7P.js → chunk-I3HMNWQQ.js} +9 -8
  42. package/dist/chunk-I3HMNWQQ.js.map +1 -0
  43. package/dist/{chunk-XJHQVOT6.js → chunk-J7FJ6PUT.js} +2 -2
  44. package/dist/chunk-JT5LZRMI.js +302 -0
  45. package/dist/chunk-JT5LZRMI.js.map +1 -0
  46. package/dist/{chunk-Q457PKGH.js → chunk-KAYXR544.js} +2 -2
  47. package/dist/{chunk-XU5A6BWA.js → chunk-MZPRBNYC.js} +4 -4
  48. package/dist/{chunk-XHNACIHO.js → chunk-NTTSUAVM.js} +2 -2
  49. package/dist/{chunk-PLI3JQWT.js → chunk-OAVJR4PM.js} +2 -2
  50. package/dist/{chunk-UDZCTLD6.js → chunk-OK7LUTRW.js} +3 -3
  51. package/dist/{chunk-PBSHQVCT.js → chunk-POU2UMWN.js} +5 -5
  52. package/dist/chunk-QN47QVBX.js +131 -0
  53. package/dist/chunk-QN47QVBX.js.map +1 -0
  54. package/dist/{chunk-3FC3VNEX.js → chunk-RD7OPXZK.js} +34 -8
  55. package/dist/chunk-RD7OPXZK.js.map +1 -0
  56. package/dist/{chunk-O6LECMT6.js → chunk-TGRK3CHF.js} +8 -8
  57. package/dist/{chunk-7GLZVDPQ.js → chunk-TL72BGP6.js} +2 -2
  58. package/dist/{chunk-THS5L54H.js → chunk-TRUMP4DA.js} +26 -2
  59. package/dist/{chunk-THS5L54H.js.map → chunk-TRUMP4DA.js.map} +1 -1
  60. package/dist/{chunk-52MVUK5V.js → chunk-USSL2X4A.js} +2 -2
  61. package/dist/chunk-USSL2X4A.js.map +1 -0
  62. package/dist/{chunk-XPKN3QWY.js → chunk-VOGGLPG5.js} +1 -2
  63. package/dist/{chunk-IWIIOFEB.js → chunk-XFEK2X2D.js} +16 -6
  64. package/dist/chunk-XFEK2X2D.js.map +1 -0
  65. package/dist/{chunk-PVW6JE7E.js → chunk-Y5HSSIK2.js} +2 -2
  66. package/dist/{chunk-4KGRPHM6.js → chunk-Y5O2ALDZ.js} +3 -3
  67. package/dist/{claude-V4HRPR4Z.js → claude-TP2QO3BU.js} +2 -2
  68. package/dist/{cleanup-NWNKWPUY.js → cleanup-D3CSRBBZ.js} +23 -18
  69. package/dist/{cleanup-NWNKWPUY.js.map → cleanup-D3CSRBBZ.js.map} +1 -1
  70. package/dist/cli.js +143 -93
  71. package/dist/cli.js.map +1 -1
  72. package/dist/{commit-534QIRHY.js → commit-IWGT42XN.js} +13 -13
  73. package/dist/{compile-UANHMNTS.js → compile-EOWJORKO.js} +8 -8
  74. package/dist/{contribute-7USRBWRM.js → contribute-WSJTV2RX.js} +4 -4
  75. package/dist/{dev-server-TO7RLYJI.js → dev-server-Q6M62ATG.js} +13 -13
  76. package/dist/{feedback-7ZZI6RC5.js → feedback-QPNDZQRV.js} +14 -14
  77. package/dist/{git-GUNOPP4Q.js → git-W3XUIFTR.js} +5 -3
  78. package/dist/hooks/iloom-hook.js +5 -3
  79. package/dist/{ignite-JBX3BUDE.js → ignite-OPO6EDYT.js} +95 -52
  80. package/dist/ignite-OPO6EDYT.js.map +1 -0
  81. package/dist/index.d.ts +40 -2
  82. package/dist/index.js +52 -15
  83. package/dist/index.js.map +1 -1
  84. package/dist/{chunk-FPNSFP6K.js → init-ALYWKNWG.js} +42 -329
  85. package/dist/init-ALYWKNWG.js.map +1 -0
  86. package/dist/issues-L7TBUPXT.js +116 -0
  87. package/dist/issues-L7TBUPXT.js.map +1 -0
  88. package/dist/{lint-XPODLDVA.js → lint-IHUH45OC.js} +8 -8
  89. package/dist/mcp/issue-management-server.js +3 -2
  90. package/dist/mcp/issue-management-server.js.map +1 -1
  91. package/dist/{open-M2SUR74Y.js → open-KWOV2OFO.js} +15 -15
  92. package/dist/{plan-FB4AOJ2Q.js → plan-BRJBFJHF.js} +60 -28
  93. package/dist/plan-BRJBFJHF.js.map +1 -0
  94. package/dist/{projects-325GEEGJ.js → projects-LH362JZQ.js} +3 -3
  95. package/dist/prompts/init-prompt.txt +9 -1
  96. package/dist/prompts/issue-prompt.txt +310 -0
  97. package/dist/prompts/plan-prompt.txt +4 -6
  98. package/dist/prompts/pr-prompt.txt +79 -0
  99. package/dist/prompts/regular-prompt.txt +205 -0
  100. package/dist/{rebase-4FNRBW3H.js → rebase-AJOJOZUG.js} +9 -9
  101. package/dist/{recap-GSXFEOD6.js → recap-GKJXMDXW.js} +5 -5
  102. package/dist/{run-GZNHRJB2.js → run-QEUVZF7J.js} +15 -15
  103. package/dist/schema/settings.schema.json +9 -1
  104. package/dist/{shell-2SPM3Z5O.js → shell-DAAVG4YN.js} +5 -5
  105. package/dist/{summary-Z4F7YFXE.js → summary-ZKOA35PT.js} +13 -13
  106. package/dist/{test-LBSPYIJW.js → test-5GPWWO3P.js} +8 -8
  107. package/dist/{test-git-ZPSPA2TP.js → test-git-EJUKDB7F.js} +3 -3
  108. package/dist/{test-prefix-6DLB2BHE.js → test-prefix-23TOBUXY.js} +3 -3
  109. package/dist/{test-webserver-XLJ2TZFP.js → test-webserver-CKROHFBQ.js} +5 -5
  110. package/dist/{vscode-LH3VSQ2W.js → vscode-6TOLFCI2.js} +5 -5
  111. package/package.json +2 -2
  112. package/dist/ClaudeContextManager-RDP6CLK6.js +0 -14
  113. package/dist/ClaudeService-FKPOQRA4.js +0 -13
  114. package/dist/PRManager-A63LT3NF.js +0 -16
  115. package/dist/PromptTemplateManager-OUYDHOPI.js +0 -9
  116. package/dist/chunk-3FC3VNEX.js.map +0 -1
  117. package/dist/chunk-44Y5IF7P.js.map +0 -1
  118. package/dist/chunk-4BSXZ5YZ.js.map +0 -1
  119. package/dist/chunk-52MVUK5V.js.map +0 -1
  120. package/dist/chunk-66QOCD5N.js +0 -79
  121. package/dist/chunk-66QOCD5N.js.map +0 -1
  122. package/dist/chunk-A7XHHUEV.js.map +0 -1
  123. package/dist/chunk-FPNSFP6K.js.map +0 -1
  124. package/dist/chunk-GDS2HXSW.js.map +0 -1
  125. package/dist/chunk-GWONJE3X.js.map +0 -1
  126. package/dist/chunk-HSGZW3ID.js.map +0 -1
  127. package/dist/chunk-IGKPPACU.js.map +0 -1
  128. package/dist/chunk-IWIIOFEB.js.map +0 -1
  129. package/dist/chunk-RNBIISBZ.js.map +0 -1
  130. package/dist/chunk-VZYSM7N7.js.map +0 -1
  131. package/dist/git-GUNOPP4Q.js.map +0 -1
  132. package/dist/ignite-JBX3BUDE.js.map +0 -1
  133. package/dist/init-XXDIB2UJ.js +0 -21
  134. package/dist/init-XXDIB2UJ.js.map +0 -1
  135. package/dist/plan-FB4AOJ2Q.js.map +0 -1
  136. /package/dist/{BranchNamingService-AO7BPIUJ.js.map → BranchNamingService-K6XNWQ6C.js.map} +0 -0
  137. /package/dist/{ClaudeContextManager-RDP6CLK6.js.map → ClaudeContextManager-X2Y72GRL.js.map} +0 -0
  138. /package/dist/{ClaudeService-FKPOQRA4.js.map → ClaudeService-7P32TTES.js.map} +0 -0
  139. /package/dist/{GitHubService-ACZVNTJE.js.map → GitHubService-O7T6CFAJ.js.map} +0 -0
  140. /package/dist/{LoomLauncher-NHZMEVTQ.js.map → LoomLauncher-3I47SUPV.js.map} +0 -0
  141. /package/dist/{PRManager-A63LT3NF.js.map → ProjectCapabilityDetector-N5L7T4IY.js.map} +0 -0
  142. /package/dist/{ProjectCapabilityDetector-IA56AUE6.js.map → PromptTemplateManager-36YLQRHP.js.map} +0 -0
  143. /package/dist/{PromptTemplateManager-OUYDHOPI.js.map → SettingsManager-QR7V2IW2.js.map} +0 -0
  144. /package/dist/{build-Z3WCIKPD.js.map → build-IC4CJRMP.js.map} +0 -0
  145. /package/dist/{chunk-TVH67KEO.js.map → chunk-2HZX6AMR.js.map} +0 -0
  146. /package/dist/{chunk-SC6X5EBG.js.map → chunk-3P6J4IZZ.js.map} +0 -0
  147. /package/dist/{chunk-RD7I2Q2F.js.map → chunk-4LKGCFGG.js.map} +0 -0
  148. /package/dist/{chunk-SSASIBDJ.js.map → chunk-5LVVQGB3.js.map} +0 -0
  149. /package/dist/{chunk-XJHQVOT6.js.map → chunk-J7FJ6PUT.js.map} +0 -0
  150. /package/dist/{chunk-Q457PKGH.js.map → chunk-KAYXR544.js.map} +0 -0
  151. /package/dist/{chunk-XU5A6BWA.js.map → chunk-MZPRBNYC.js.map} +0 -0
  152. /package/dist/{chunk-XHNACIHO.js.map → chunk-NTTSUAVM.js.map} +0 -0
  153. /package/dist/{chunk-PLI3JQWT.js.map → chunk-OAVJR4PM.js.map} +0 -0
  154. /package/dist/{chunk-UDZCTLD6.js.map → chunk-OK7LUTRW.js.map} +0 -0
  155. /package/dist/{chunk-PBSHQVCT.js.map → chunk-POU2UMWN.js.map} +0 -0
  156. /package/dist/{chunk-O6LECMT6.js.map → chunk-TGRK3CHF.js.map} +0 -0
  157. /package/dist/{chunk-7GLZVDPQ.js.map → chunk-TL72BGP6.js.map} +0 -0
  158. /package/dist/{chunk-XPKN3QWY.js.map → chunk-VOGGLPG5.js.map} +0 -0
  159. /package/dist/{chunk-PVW6JE7E.js.map → chunk-Y5HSSIK2.js.map} +0 -0
  160. /package/dist/{chunk-4KGRPHM6.js.map → chunk-Y5O2ALDZ.js.map} +0 -0
  161. /package/dist/{SettingsManager-VCVLL32H.js.map → claude-TP2QO3BU.js.map} +0 -0
  162. /package/dist/{commit-534QIRHY.js.map → commit-IWGT42XN.js.map} +0 -0
  163. /package/dist/{compile-UANHMNTS.js.map → compile-EOWJORKO.js.map} +0 -0
  164. /package/dist/{contribute-7USRBWRM.js.map → contribute-WSJTV2RX.js.map} +0 -0
  165. /package/dist/{dev-server-TO7RLYJI.js.map → dev-server-Q6M62ATG.js.map} +0 -0
  166. /package/dist/{feedback-7ZZI6RC5.js.map → feedback-QPNDZQRV.js.map} +0 -0
  167. /package/dist/{claude-V4HRPR4Z.js.map → git-W3XUIFTR.js.map} +0 -0
  168. /package/dist/{lint-XPODLDVA.js.map → lint-IHUH45OC.js.map} +0 -0
  169. /package/dist/{open-M2SUR74Y.js.map → open-KWOV2OFO.js.map} +0 -0
  170. /package/dist/{projects-325GEEGJ.js.map → projects-LH362JZQ.js.map} +0 -0
  171. /package/dist/{rebase-4FNRBW3H.js.map → rebase-AJOJOZUG.js.map} +0 -0
  172. /package/dist/{recap-GSXFEOD6.js.map → recap-GKJXMDXW.js.map} +0 -0
  173. /package/dist/{run-GZNHRJB2.js.map → run-QEUVZF7J.js.map} +0 -0
  174. /package/dist/{shell-2SPM3Z5O.js.map → shell-DAAVG4YN.js.map} +0 -0
  175. /package/dist/{summary-Z4F7YFXE.js.map → summary-ZKOA35PT.js.map} +0 -0
  176. /package/dist/{test-LBSPYIJW.js.map → test-5GPWWO3P.js.map} +0 -0
  177. /package/dist/{test-git-ZPSPA2TP.js.map → test-git-EJUKDB7F.js.map} +0 -0
  178. /package/dist/{test-prefix-6DLB2BHE.js.map → test-prefix-23TOBUXY.js.map} +0 -0
  179. /package/dist/{test-webserver-XLJ2TZFP.js.map → test-webserver-CKROHFBQ.js.map} +0 -0
  180. /package/dist/{vscode-LH3VSQ2W.js.map → vscode-6TOLFCI2.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/ignite.ts","../src/lib/ClaudeHookManager.ts"],"sourcesContent":["import path from 'path'\nimport { logger, createStderrLogger } from '../utils/logger.js'\nimport { withLogger } from '../utils/logger-context.js'\nimport { ClaudeWorkflowOptions } from '../lib/ClaudeService.js'\nimport { GitWorktreeManager } from '../lib/GitWorktreeManager.js'\nimport { launchClaude, ClaudeCliOptions } from '../utils/claude.js'\nimport { PromptTemplateManager, TemplateVariables, buildReviewTemplateVariables } from '../lib/PromptTemplateManager.js'\nimport { generateIssueManagementMcpConfig, generateRecapMcpConfig } from '../utils/mcp.js'\nimport { AgentManager } from '../lib/AgentManager.js'\nimport { IssueTrackerFactory } from '../lib/IssueTrackerFactory.js'\nimport { SettingsManager, type IloomSettings } from '../lib/SettingsManager.js'\nimport { MetadataManager } from '../lib/MetadataManager.js'\nimport { extractSettingsOverrides } from '../utils/cli-overrides.js'\nimport { FirstRunManager } from '../utils/FirstRunManager.js'\nimport { extractIssueNumber, isValidGitRepo, getWorktreeRoot } from '../utils/git.js'\nimport { getWorkspacePort } from '../utils/port.js'\nimport { readFile } from 'fs/promises'\nimport { ClaudeHookManager } from '../lib/ClaudeHookManager.js'\nimport type { OneShotMode } from '../types/index.js'\n\n/**\n * Error thrown when the spin command is run from an invalid location\n */\nexport class WorktreeValidationError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly suggestion: string\n\t) {\n\t\tsuper(message)\n\t\tthis.name = 'WorktreeValidationError'\n\t}\n}\n\n/**\n * IgniteCommand: Auto-detect workspace context and launch Claude\n *\n * This command:\n * 1. Auto-detects context from current directory and git branch\n * 2. Loads appropriate prompt template with variable substitution\n * 3. Launches Claude with existing agent system (NO changes to agent loading)\n * 4. Executes in current terminal (not opening a new window)\n *\n * CRITICAL: This command works with agents exactly as they currently function.\n * NO modifications to agent loading mechanisms.\n */\nexport class IgniteCommand {\n\tprivate templateManager: PromptTemplateManager\n\tprivate gitWorktreeManager: GitWorktreeManager\n\tprivate agentManager: AgentManager\n\tprivate settingsManager: SettingsManager\n\tprivate firstRunManager: FirstRunManager\n\tprivate hookManager: ClaudeHookManager\n\tprivate settings?: IloomSettings\n\n\tconstructor(\n\t\ttemplateManager?: PromptTemplateManager,\n\t\tgitWorktreeManager?: GitWorktreeManager,\n\t\tagentManager?: AgentManager,\n\t\tsettingsManager?: SettingsManager,\n\t\tfirstRunManager?: FirstRunManager,\n\t\thookManager?: ClaudeHookManager\n\t) {\n\t\tthis.templateManager = templateManager ?? new PromptTemplateManager()\n\t\tthis.gitWorktreeManager = gitWorktreeManager ?? new GitWorktreeManager()\n\t\tthis.agentManager = agentManager ?? new AgentManager()\n\t\tthis.settingsManager = settingsManager ?? new SettingsManager()\n\t\tthis.firstRunManager = firstRunManager ?? new FirstRunManager('spin')\n\t\tthis.hookManager = hookManager ?? new ClaudeHookManager()\n\t}\n\n\t/**\n\t * Validate that we're not running from the main worktree\n\t * @throws WorktreeValidationError if running from main worktree\n\t */\n\tprivate async validateNotMainWorktree(): Promise<void> {\n\t\tconst currentDir = process.cwd()\n\n\t\t// Step 1: Check if we're in a git repository at all\n\t\tconst isGitRepo = await isValidGitRepo(currentDir)\n\t\tif (!isGitRepo) {\n\t\t\t// Not a git repo - let detectWorkspaceContext handle this gracefully\n\t\t\treturn\n\t\t}\n\n\t\t// Step 2: Get the worktree root (handles subdirectories)\n\t\tconst worktreeRoot = await getWorktreeRoot(currentDir)\n\t\tif (!worktreeRoot) {\n\t\t\t// Could not determine root - let detectWorkspaceContext handle this\n\t\t\treturn\n\t\t}\n\n\t\t// Step 3: Check if this path is a registered git worktree\n\t\tconst worktrees = await this.gitWorktreeManager.listWorktrees()\n\t\tconst currentWorktree = worktrees.find(wt => wt.path === worktreeRoot)\n\n\t\tif (!currentWorktree) {\n\t\t\t// Not a registered worktree - let detectWorkspaceContext handle this\n\t\t\treturn\n\t\t}\n\n\t\t// Step 4: Check if this is the main worktree\n\t\tconst isMain = await this.gitWorktreeManager.isMainWorktree(currentWorktree, this.settingsManager)\n\t\tif (isMain) {\n\t\t\tthrow new WorktreeValidationError(\n\t\t\t\t'You cannot run the command from the main worktree.',\n\t\t\t\t\"Navigate to a feature worktree created by 'il start <issue>' and run 'il spin' from there.\"\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * Print mode options for headless/CI execution\n\t */\n\tpublic printOptions: {\n\t\tprint?: boolean\n\t\toutputFormat?: 'json' | 'stream-json' | 'text'\n\t\tverbose?: boolean\n\t\tjson?: boolean // --json flag: output final JSON object\n\t\tjsonStream?: boolean // --json-stream flag: stream JSONL to stdout\n\t} | undefined\n\n\t/**\n\t * Main entry point for spin command\n\t * @param oneShot - One-shot automation mode\n\t * @param printOptions - Print mode options for headless/CI execution\n\t */\n\tasync execute(oneShot?: OneShotMode, printOptions?: {\n\t\tprint?: boolean\n\t\toutputFormat?: 'json' | 'stream-json' | 'text'\n\t\tverbose?: boolean\n\t\tjson?: boolean\n\t\tjsonStream?: boolean\n\t}): Promise<void> {\n\t\tthis.printOptions = printOptions\n\n\t\t// Wrap execution in stderr logger for JSON modes to keep stdout clean\n\t\tconst isJsonMode = (this.printOptions?.json ?? false) || (this.printOptions?.jsonStream ?? false)\n\t\tif (isJsonMode) {\n\t\t\tconst jsonLogger = createStderrLogger()\n\t\t\treturn withLogger(jsonLogger, () => this.executeInternal(oneShot))\n\t\t}\n\n\t\treturn this.executeInternal(oneShot)\n\t}\n\n\t/**\n\t * Internal execution method (separated for withLogger wrapping)\n\t */\n\tprivate async executeInternal(oneShot?: OneShotMode): Promise<void> {\n\t\t// Set ILOOM=1 so hooks know this is an iloom session\n\t\t// This is inherited by the Claude child process\n\t\tprocess.env.ILOOM = '1'\n\n\t\t// Validate we're not in the main worktree first\n\t\ttry {\n\t\t\tawait this.validateNotMainWorktree()\n\t\t} catch (error) {\n\t\t\tif (error instanceof WorktreeValidationError) {\n\t\t\t\tlogger.error(error.message)\n\t\t\t\tlogger.info(error.suggestion)\n\t\t\t\tthrow error\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\n\t\ttry {\n\t\t\tlogger.info('🚀 Your loom is spinning up, please wait...')\n\n\t\t\t// Step 0.5: Check if this is first-time user\n\t\t\tconst isFirstRun = await this.firstRunManager.isFirstRun()\n\t\t\tif (isFirstRun) {\n\t\t\t\tlogger.success('Welcome to iloom! Preparing first-time experience...')\n\t\t\t}\n\n\t\t\t// Step 0.6: Install Claude hooks for VSCode integration (idempotent, quick)\n\t\t\tawait this.hookManager.installHooks()\n\n\t\t\t// Step 1: Auto-detect workspace context\n\t\t\tconst context = await this.detectWorkspaceContext()\n\n\t\t\tlogger.debug('Auto-detected workspace context', { context })\n\n\t\t\t// Inform user what context was detected\n\t\t\tthis.logDetectedContext(context)\n\n\t\t\tlogger.info('📝 Loading prompt template and preparing Claude...')\n\n\t\t\t// Step 2: Read metadata early to get draftPrNumber and draftPrUrl for templates and MCP config\n\t\t\tconst metadataManager = new MetadataManager()\n\t\t\tconst metadata = await metadataManager.readMetadata(context.workspacePath)\n\t\t\tconst draftPrNumber = metadata?.draftPrNumber ?? undefined\n\t\t\t// Extract draft PR URL from prUrls map if available\n\t\t\tconst draftPrUrl = draftPrNumber && metadata?.prUrls?.[String(draftPrNumber)]\n\t\t\t\t? metadata.prUrls[String(draftPrNumber)]\n\t\t\t\t: undefined\n\n\t\t\t// Step 2.0.4: Determine effective oneShot mode\n\t\t\t// If print mode is enabled, force noReview to skip interactive reviews\n\t\t\t// If oneShot is provided (any value including 'default'), use it\n\t\t\t// If oneShot is undefined (not passed), use metadata or fallback to 'default'\n\t\t\t// Note: metadata?.oneShot can be null (for legacy looms), so we need double nullish coalescing\n\t\t\tconst storedOneShot = metadata?.oneShot ?? 'default'\n\t\t\tconst isHeadlessForOneShot = this.printOptions?.print ?? false\n\t\t\tconst effectiveOneShot: OneShotMode = isHeadlessForOneShot ? 'noReview' : (oneShot ?? storedOneShot)\n\n\t\t\t// Step 2.0.5: Load settings early if not cached (needed for port calculation)\n\t\t\tif (!this.settings) {\n\t\t\t\tconst cliOverrides = extractSettingsOverrides()\n\t\t\t\tthis.settings = await this.settingsManager.loadSettings(undefined, cliOverrides)\n\t\t\t}\n\n\t\t\t// Step 2.0.6: Calculate port for web-capable looms\n\t\t\tif (metadata?.capabilities?.includes('web') && context.branchName) {\n\t\t\t\tconst basePort = this.settings?.capabilities?.web?.basePort ?? 3000\n\t\t\t\tcontext.port = await getWorkspacePort({\n\t\t\t\t\tbasePort,\n\t\t\t\t\tworktreePath: context.workspacePath,\n\t\t\t\t\tworktreeBranch: context.branchName,\n\t\t\t\t})\n\t\t\t\tlogger.info(`🌐 Development server port: ${context.port}`)\n\t\t\t}\n\n\t\t\t// Step 2.1: Get prompt template with variable substitution\n\t\t\tconst variables = this.buildTemplateVariables(context, effectiveOneShot, draftPrNumber, draftPrUrl)\n\n\t\t\t// Step 2.5: Add first-time user context if needed\n\t\t\tif (isFirstRun) {\n\t\t\t\tvariables.FIRST_TIME_USER = true\n\t\t\t\tvariables.README_CONTENT = await this.loadReadmeContent()\n\t\t\t\tvariables.SETTINGS_SCHEMA_CONTENT = await this.loadSettingsSchemaContent()\n\t\t\t}\n\n\t\t\tconst systemInstructions = await this.templateManager.getPrompt(context.type, variables)\n\n\t\t\t// User prompt to trigger the workflow (includes one-shot bypass instructions if needed)\n\t\t\tconst userPrompt = this.buildUserPrompt(effectiveOneShot)\n\n\t\t\t// Step 3: Determine model and permission mode based on workflow type\n\t\t\tconst model = this.settingsManager.getSpinModel(this.settings)\n\t\t\tlet permissionMode = this.getPermissionModeForWorkflow(context.type)\n\n\t\t\t// Override permission mode if bypassPermissions oneShot mode\n\t\t\tif (effectiveOneShot === 'bypassPermissions') {\n\t\t\t\tpermissionMode = 'bypassPermissions'\n\t\t\t}\n\n\t\t\t// Display warning if bypassPermissions is used\n\t\t\tif (permissionMode === 'bypassPermissions') {\n\t\t\t\tlogger.warn(\n\t\t\t\t\t'⚠️ WARNING: Using bypassPermissions mode - Claude will execute all tool calls without confirmation. ' +\n\t\t\t\t\t\t'This can be dangerous. Use with caution.'\n\t\t\t\t)\n\t\t\t}\n\n\t\t\t// Step 4: Build Claude CLI options\n\t\t\t// Session ID must come from loom metadata - no fallback generation\n\t\t\tconst sessionId = metadata?.sessionId\n\t\t\tif (!sessionId) {\n\t\t\t\tthrow new Error('No session ID found in loom metadata. This loom may need to be recreated with `il start`.')\n\t\t\t}\n\t\t\tlogger.debug('Using session ID from metadata', { sessionId })\n\n\t\t\t// Determine if we're in print/headless mode\n\t\t\tconst isHeadless = this.printOptions?.print ?? false\n\n\t\t\tconst claudeOptions: ClaudeCliOptions = {\n\t\t\t\theadless: isHeadless,\n\t\t\t\taddDir: context.workspacePath,\n\t\t\t\tsessionId, // Enable Claude Code session resume\n\t\t\t}\n\n\t\t\t// Add optional model if present\n\t\t\tif (model !== undefined) {\n\t\t\t\tclaudeOptions.model = model\n\t\t\t}\n\n\t\t\t// Add permission mode if not default\n\t\t\t// When print mode is enabled, force bypassPermissions for autonomous execution\n\t\t\tif (isHeadless) {\n\t\t\t\tpermissionMode = 'bypassPermissions'\n\t\t\t}\n\t\t\tif (permissionMode !== undefined && permissionMode !== 'default') {\n\t\t\t\tclaudeOptions.permissionMode = permissionMode\n\t\t\t}\n\n\t\t\t// Add output format and verbose options if provided (print mode only)\n\t\t\tif (this.printOptions?.outputFormat !== undefined) {\n\t\t\t\tclaudeOptions.outputFormat = this.printOptions.outputFormat\n\t\t\t}\n\t\t\tif (this.printOptions?.verbose !== undefined) {\n\t\t\t\tclaudeOptions.verbose = this.printOptions.verbose\n\t\t\t}\n\n\t\t\t// Add JSON mode if specified (requires print mode)\n\t\t\tif (this.printOptions?.json) {\n\t\t\t\tclaudeOptions.jsonMode = 'json'\n\t\t\t\tclaudeOptions.outputFormat = 'stream-json' // Force stream-json for parsing\n\t\t\t} else if (this.printOptions?.jsonStream) {\n\t\t\t\tclaudeOptions.jsonMode = 'stream'\n\t\t\t\tclaudeOptions.outputFormat = 'stream-json' // Force stream-json for streaming\n\t\t\t}\n\n\t\t\t// Add optional branch name for context\n\t\t\tif (context.branchName !== undefined) {\n\t\t\t\tclaudeOptions.branchName = context.branchName\n\t\t\t}\n\n\t\t\t// Step 4.5: Generate MCP config and tool filtering for issue/PR workflows\n\t\t\tlet mcpConfig: Record<string, unknown>[] | undefined\n\t\t\tlet allowedTools: string[] | undefined\n\t\t\tlet disallowedTools: string[] | undefined\n\n\t\t\tif (context.type === 'issue' || context.type === 'pr') {\n\t\t\t\ttry {\n\t\t\t\t\tconst provider = this.settings ? IssueTrackerFactory.getProviderName(this.settings) : 'github'\n\t\t\t\t\t// Pass draftPrNumber to route comments to PR when in github-draft-pr mode\n\t\t\t\t\tmcpConfig = await generateIssueManagementMcpConfig(context.type, undefined, provider, this.settings, draftPrNumber)\n\t\t\t\t\tlogger.debug('Generated MCP configuration for issue management', { provider, draftPrNumber })\n\n\t\t\t\t\t// Configure tool filtering for issue/PR workflows\n\t\t\t\t\t// Note: set_goal is only allowed for PR workflow (user's purpose unclear)\n\t\t\t\t\t// For issue workflow, the issue title provides context so set_goal is not needed\n\t\t\t\t\tconst baseTools = [\n\t\t\t\t\t\t'mcp__issue_management__get_issue',\n\t\t\t\t\t\t'mcp__issue_management__get_comment',\n\t\t\t\t\t\t'mcp__issue_management__create_comment',\n\t\t\t\t\t\t'mcp__issue_management__update_comment',\n\t\t\t\t\t\t'mcp__issue_management__create_issue',\n\t\t\t\t\t\t'mcp__recap__add_entry',\n\t\t\t\t\t\t'mcp__recap__get_recap',\n\t\t\t\t\t\t'mcp__recap__add_artifact',\n\t\t\t\t\t\t'mcp__recap__set_complexity'\n\t\t\t\t\t]\n\t\t\t\t\tallowedTools = context.type === 'pr'\n\t\t\t\t\t\t? [...baseTools, 'mcp__issue_management__get_pr', 'mcp__recap__set_goal']\n\t\t\t\t\t\t: baseTools\n\t\t\t\t\tdisallowedTools = ['Bash(gh api:*), Bash(gh issue view:*), Bash(gh pr view:*), Bash(gh issue comment:*)']\n\n\t\t\t\t\tlogger.debug('Configured tool filtering for issue/PR workflow', { allowedTools, disallowedTools })\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// Log warning but continue without MCP\n\t\t\t\t\tlogger.warn(`Failed to generate MCP config: ${error instanceof Error ? error.message : 'Unknown error'}`)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Regular/branch workflow - allow recap tools (including set_goal since no issue/PR context)\n\t\t\t\tallowedTools = [\n\t\t\t\t\t'mcp__recap__set_goal',\n\t\t\t\t\t'mcp__recap__add_entry',\n\t\t\t\t\t'mcp__recap__get_recap',\n\t\t\t\t\t'mcp__recap__set_complexity',\n\t\t\t\t]\n\t\t\t\tlogger.debug('Configured tool filtering for regular workflow', { allowedTools })\n\t\t\t}\n\n\t\t\t// Step 4.5.1: Generate recap MCP config (always added for all workflow types)\n\t\t\t// Reuses metadata already read in Step 2\n\t\t\ttry {\n\t\t\t\tif (!metadata) {\n\t\t\t\t\tthrow new Error('No loom metadata found for this workspace')\n\t\t\t\t}\n\t\t\t\tconst recapMcpConfig = generateRecapMcpConfig(context.workspacePath, metadata)\n\t\t\t\tif (mcpConfig) {\n\t\t\t\t\tmcpConfig.push(...recapMcpConfig)\n\t\t\t\t} else {\n\t\t\t\t\tmcpConfig = recapMcpConfig\n\t\t\t\t}\n\t\t\t\tlogger.debug('Generated MCP configuration for recap server')\n\t\t\t} catch (error) {\n\t\t\t\t// Log warning but continue without recap MCP\n\t\t\t\tlogger.warn(`Failed to generate recap MCP config: ${error instanceof Error ? error.message : 'Unknown error'}`)\n\t\t\t}\n\n\t\t\t// Step 4.6: Load agent configurations using cached settings\n\t\t\tlet agents: Record<string, unknown> | undefined\n\t\t\ttry {\n\t\t\t\t// Use cached settings from Step 2.5\n\t\t\t\tif (this.settings?.agents && Object.keys(this.settings.agents).length > 0) {\n\t\t\t\t\tlogger.debug('Loaded project settings', {\n\t\t\t\t\t\tagentOverrides: Object.keys(this.settings.agents),\n\t\t\t\t\t})\n\t\t\t\t}\n\n\t\t\t\t// Load agents with settings overrides and template variables for substitution\n\t\t\t\t// Exclude init-only agents (e.g., framework-detector which is only for il init)\n\t\t\t\tconst loadedAgents = await this.agentManager.loadAgents(\n\t\t\t\t\tthis.settings,\n\t\t\t\t\tvariables,\n\t\t\t\t\t['*.md', '!iloom-framework-detector.md']\n\t\t\t\t)\n\t\t\t\tagents = this.agentManager.formatForCli(loadedAgents)\n\t\t\t\tlogger.debug('Loaded agent configurations', {\n\t\t\t\t\tagentCount: Object.keys(agents).length,\n\t\t\t\t\tagentNames: Object.keys(agents),\n\t\t\t\t})\n\t\t\t} catch (error) {\n\t\t\t\t// Log warning but continue without agents\n\t\t\t\tlogger.warn(`Failed to load agents: ${error instanceof Error ? error.message : 'Unknown error'}`)\n\t\t\t}\n\n\t\t\tlogger.debug('Launching Claude in current terminal', {\n\t\t\t\ttype: context.type,\n\t\t\t\tmodel,\n\t\t\t\tpermissionMode,\n\t\t\t\tworkspacePath: context.workspacePath,\n\t\t\t\thasMcpConfig: !!mcpConfig,\n\t\t\t})\n\n\t\t\tlogger.info(isHeadless ? '✨ Launching Claude in headless mode...' : '✨ Launching Claude in current terminal...')\n\n\t\t\t// Step 5: Launch Claude with system instructions appended and user prompt\n\t\t\tconst claudeResult = await launchClaude(userPrompt, {\n\t\t\t\t...claudeOptions,\n\t\t\t\tappendSystemPrompt: systemInstructions,\n\t\t\t\t...(mcpConfig && { mcpConfig }),\n\t\t\t\t...(allowedTools && { allowedTools }),\n\t\t\t\t...(disallowedTools && { disallowedTools }),\n\t\t\t\t...(agents && { agents }),\n\t\t\t})\n\n\t\t\t// Output final JSON for --json mode (--json-stream already streamed to stdout)\n\t\t\tif (this.printOptions?.json) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.log(JSON.stringify({\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\toutput: claudeResult ?? ''\n\t\t\t\t}))\n\t\t\t}\n\n\t\t\t// Step 6: Mark as run after successful launch\n\t\t\tif (isFirstRun) {\n\t\t\t\tawait this.firstRunManager.markAsRun()\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst errorMessage = error instanceof Error ? error.message : 'Unknown error'\n\t\t\t// Output error as JSON for --json mode\n\t\t\tif (this.printOptions?.json) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.log(JSON.stringify({\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\terror: errorMessage\n\t\t\t\t}))\n\t\t\t} else {\n\t\t\t\tlogger.error(`Failed to launch Claude: ${errorMessage}`)\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t/**\n\t * Log user-friendly information about detected context\n\t */\n\tprivate logDetectedContext(context: ClaudeWorkflowOptions): void {\n\t\tif (context.type === 'issue') {\n\t\t\tlogger.info(`🎯 Detected issue workflow: Issue #${context.issueNumber}`)\n\t\t} else if (context.type === 'pr') {\n\t\t\tlogger.info(`🔄 Detected PR workflow: PR #${context.prNumber}`)\n\t\t} else {\n\t\t\tlogger.info('🌟 Detected regular workflow')\n\t\t}\n\n\t\tif (context.branchName) {\n\t\t\tlogger.info(`🌿 Working on branch: ${context.branchName}`)\n\t\t}\n\n\t\tif (context.port) {\n\t\t\tlogger.info(`🌐 Development server port: ${context.port}`)\n\t\t}\n\t}\n\n\t/**\n\t * Build template variables from context\n\t */\n\tprivate buildTemplateVariables(\n\t\tcontext: ClaudeWorkflowOptions,\n\t\toneShot: OneShotMode,\n\t\tdraftPrNumber?: number,\n\t\tdraftPrUrl?: string\n\t): TemplateVariables {\n\t\tconst variables: TemplateVariables = {\n\t\t\tWORKSPACE_PATH: context.workspacePath,\n\t\t}\n\n\t\tif (context.issueNumber !== undefined) {\n\t\t\tvariables.ISSUE_NUMBER = context.issueNumber\n\t\t}\n\n\t\tif (context.prNumber !== undefined) {\n\t\t\tvariables.PR_NUMBER = context.prNumber\n\t\t}\n\n\t\tif (context.title !== undefined) {\n\t\t\tif (context.type === 'issue') {\n\t\t\t\tvariables.ISSUE_TITLE = context.title\n\t\t\t} else if (context.type === 'pr') {\n\t\t\t\tvariables.PR_TITLE = context.title\n\t\t\t}\n\t\t}\n\n\t\tif (context.port !== undefined) {\n\t\t\tvariables.PORT = context.port\n\t\t}\n\n\t\t// Set ONE_SHOT_MODE or INTERACTIVE_MODE flag for template conditional sections\n\t\tif (oneShot === 'noReview' || oneShot === 'bypassPermissions') {\n\t\t\tvariables.ONE_SHOT_MODE = true\n\t\t} else {\n\t\t\tvariables.INTERACTIVE_MODE = true\n\t\t}\n\n\t\t// Set review configuration variables (code reviewer + artifact reviewer + per-agent flags)\n\t\tObject.assign(variables, buildReviewTemplateVariables(this.settings?.agents))\n\n\t\t// Set draft PR mode flags (mutually exclusive)\n\t\t// When draftPrNumber is set, we're in github-draft-pr mode\n\t\tif (draftPrNumber !== undefined) {\n\t\t\tvariables.DRAFT_PR_MODE = true\n\t\t\tvariables.DRAFT_PR_NUMBER = draftPrNumber\n\t\t\tif (draftPrUrl) {\n\t\t\t\tvariables.DRAFT_PR_URL = draftPrUrl\n\t\t\t}\n\t\t\t// Set AUTO_COMMIT_PUSH when in draft PR mode and not explicitly disabled\n\t\t\t// Default is true (enabled) for draft PR mode\n\t\t\tconst autoCommitPushEnabled = this.settings?.mergeBehavior?.autoCommitPush !== false\n\t\t\tvariables.AUTO_COMMIT_PUSH = autoCommitPushEnabled\n\t\t\t// Set GIT_REMOTE from settings or default to 'origin'\n\t\t\tconst remote = this.settings?.mergeBehavior?.remote ?? 'origin'\n\t\t\tif (!/^[a-zA-Z0-9_-]+$/.test(remote)) {\n\t\t\t\tthrow new Error(`Invalid git remote name: \"${remote}\". Remote names can only contain alphanumeric characters, underscores, and hyphens.`)\n\t\t\t}\n\t\t\tvariables.GIT_REMOTE = remote\n\t\t} else if (context.type === 'regular') {\n\t\t\t// Branch mode without draft PR\n\t\t\tvariables.STANDARD_BRANCH_MODE = true\n\t\t} else {\n\t\t\t// Issue/PR mode without draft PR\n\t\t\tvariables.STANDARD_ISSUE_MODE = true\n\t\t}\n\n\t\treturn variables\n\t}\n\n\t/**\n\t * Get the appropriate permission mode for a workflow type\n\t * Same logic as ClaudeService.getPermissionModeForWorkflow()\n\t */\n\tprivate getPermissionModeForWorkflow(\n\t\ttype: 'issue' | 'pr' | 'regular'\n\t): ClaudeCliOptions['permissionMode'] {\n\t\t// Check settings for configured permission mode\n\t\tif (this.settings?.workflows) {\n\t\t\tconst workflowConfig =\n\t\t\t\ttype === 'issue'\n\t\t\t\t\t? this.settings.workflows.issue\n\t\t\t\t\t: type === 'pr'\n\t\t\t\t\t\t? this.settings.workflows.pr\n\t\t\t\t\t\t: this.settings.workflows.regular\n\n\t\t\tif (workflowConfig?.permissionMode) {\n\t\t\t\treturn workflowConfig.permissionMode\n\t\t\t}\n\t\t}\n\n\t\t// Fall back to current defaults\n\t\tif (type === 'issue') {\n\t\t\treturn 'acceptEdits'\n\t\t}\n\t\t// For PR and regular workflows, use default permissions\n\t\treturn 'default'\n\t}\n\n\t/**\n\t * Auto-detect workspace context from current directory and git branch\n\t *\n\t * Detection priority:\n\t * 1. Directory name patterns (_pr_N, issue-N)\n\t * 2. Git branch name patterns\n\t * 3. Fallback to 'regular' workflow\n\t *\n\t * This leverages the same logic as FinishCommand.autoDetectFromCurrentDirectory()\n\t */\n\tprivate async detectWorkspaceContext(): Promise<ClaudeWorkflowOptions> {\n\t\tconst workspacePath = process.cwd()\n\t\tconst currentDir = path.basename(workspacePath)\n\n\t\t// Check for PR worktree pattern: _pr_N suffix\n\t\t// Pattern: /.*_pr_(\\d+)$/\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\treturn this.buildContextForPR(prNumber, workspacePath)\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\treturn this.buildContextForIssue(issueNumber, workspacePath)\n\t\t}\n\n\t\t// Fallback: Try to extract from git branch name\n\t\ttry {\n\t\t\tconst repoInfo = await this.gitWorktreeManager.getRepoInfo()\n\t\t\tconst currentBranch = repoInfo.currentBranch\n\n\t\t\tif (currentBranch) {\n\t\t\t\t// Try to extract issue from branch name\n\t\t\t\tconst branchIssueNumber = extractIssueNumber(currentBranch)\n\t\t\t\tif (branchIssueNumber !== null) {\n\t\t\t\t\tlogger.debug(`Auto-detected issue #${branchIssueNumber} from branch: ${currentBranch}`)\n\n\t\t\t\t\treturn this.buildContextForIssue(branchIssueNumber, workspacePath, currentBranch)\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Git command failed - not a git repo or other git error\n\t\t\tlogger.debug('Could not detect from git branch', { error })\n\t\t}\n\n\t\t// Last resort: use regular workflow\n\t\tlogger.debug('No specific context detected, using regular workflow')\n\t\treturn this.buildContextForRegular(workspacePath)\n\t}\n\n\t/**\n\t * Build context for issue workflow\n\t */\n\tprivate async buildContextForIssue(\n\t\tissueNumber: string | number,\n\t\tworkspacePath: string,\n\t\tbranchName?: string\n\t): Promise<ClaudeWorkflowOptions> {\n\t\t// Get branch name if not provided\n\t\tif (!branchName) {\n\t\t\ttry {\n\t\t\t\tconst repoInfo = await this.gitWorktreeManager.getRepoInfo()\n\t\t\t\tbranchName = repoInfo.currentBranch ?? undefined\n\t\t\t} catch {\n\t\t\t\t// Ignore git errors\n\t\t\t}\n\t\t}\n\n\t\tconst context: ClaudeWorkflowOptions = {\n\t\t\ttype: 'issue',\n\t\t\tissueNumber,\n\t\t\tworkspacePath,\n\t\t\theadless: false, // Interactive mode\n\t\t}\n\n\t\tif (branchName !== undefined) {\n\t\t\tcontext.branchName = branchName\n\t\t}\n\n\t\treturn context\n\t}\n\n\t/**\n\t * Build context for PR workflow\n\t */\n\tprivate async buildContextForPR(\n\t\tprNumber: number,\n\t\tworkspacePath: string\n\t): Promise<ClaudeWorkflowOptions> {\n\t\t// Get branch name\n\t\tlet branchName: string | undefined\n\t\ttry {\n\t\t\tconst repoInfo = await this.gitWorktreeManager.getRepoInfo()\n\t\t\tbranchName = repoInfo.currentBranch ?? undefined\n\t\t} catch {\n\t\t\t// Ignore git errors\n\t\t}\n\n\t\tconst context: ClaudeWorkflowOptions = {\n\t\t\ttype: 'pr',\n\t\t\tprNumber,\n\t\t\tworkspacePath,\n\t\t\theadless: false, // Interactive mode\n\t\t}\n\n\t\tif (branchName !== undefined) {\n\t\t\tcontext.branchName = branchName\n\t\t}\n\n\t\treturn context\n\t}\n\n\t/**\n\t * Build context for regular workflow\n\t */\n\tprivate async buildContextForRegular(workspacePath: string): Promise<ClaudeWorkflowOptions> {\n\t\t// Get branch name\n\t\tlet branchName: string | undefined\n\t\ttry {\n\t\t\tconst repoInfo = await this.gitWorktreeManager.getRepoInfo()\n\t\t\tbranchName = repoInfo.currentBranch ?? undefined\n\t\t} catch {\n\t\t\t// Ignore git errors\n\t\t}\n\n\t\tconst context: ClaudeWorkflowOptions = {\n\t\t\ttype: 'regular',\n\t\t\tworkspacePath,\n\t\t\theadless: false, // Interactive mode\n\t\t}\n\n\t\tif (branchName !== undefined) {\n\t\t\tcontext.branchName = branchName\n\t\t}\n\n\t\treturn context\n\t}\n\n\n\t/**\n\t * Build user prompt based on one-shot mode\n\t */\n\tprivate buildUserPrompt(oneShot: OneShotMode = 'default'): string {\n\t\t// For one-shot modes, add bypass instructions to override template approval requirements\n\t\tif (oneShot === 'noReview' || oneShot === 'bypassPermissions') {\n\t\t\treturn 'Guide the user through the iloom workflow! The user has requested you move through the workflow without awaiting confirmation. This supersedes any other guidance.'\n\t\t}\n\n\t\t// Default mode: simple \"Go!\" prompt\n\t\treturn 'Guide the user through the iloom workflow!'\n\t}\n\n\t/**\n\t * Load README.md content for first-time users\n\t * Walks up from dist directory to find README.md in project root\n\t */\n\tprivate async loadReadmeContent(): Promise<string> {\n\t\ttry {\n\t\t\t// Walk up from current file location to find README.md\n\t\t\t// Use same pattern as PromptTemplateManager for finding files\n\t\t\tlet currentDir = path.dirname(new URL(import.meta.url).pathname)\n\n\t\t\t// Walk up to find README.md\n\t\t\twhile (currentDir !== path.dirname(currentDir)) {\n\t\t\t\tconst readmePath = path.join(currentDir, 'README.md')\n\t\t\t\ttry {\n\t\t\t\t\tconst content = await readFile(readmePath, 'utf-8')\n\t\t\t\t\tlogger.debug('Loaded README.md for first-time user', { readmePath })\n\t\t\t\t\treturn content\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\tlogger.debug('README.md not found, returning empty string')\n\t\t\treturn ''\n\t\t} catch (error) {\n\t\t\t// Graceful degradation - return empty string on error\n\t\t\tlogger.debug(`Failed to load README.md: ${error}`)\n\t\t\treturn ''\n\t\t}\n\t}\n\n\t/**\n\t * Load settings schema content for first-time users\n\t * Walks up from dist directory to find .iloom/README.md\n\t */\n\tprivate async loadSettingsSchemaContent(): Promise<string> {\n\t\ttry {\n\t\t\t// Walk up from current file location to find .iloom/README.md\n\t\t\tlet currentDir = path.dirname(new URL(import.meta.url).pathname)\n\n\t\t\t// Walk up to find .iloom/README.md\n\t\t\twhile (currentDir !== path.dirname(currentDir)) {\n\t\t\t\tconst schemaPath = path.join(currentDir, '.iloom', 'README.md')\n\t\t\t\ttry {\n\t\t\t\t\tconst content = await readFile(schemaPath, 'utf-8')\n\t\t\t\t\tlogger.debug('Loaded .iloom/README.md for first-time user', { schemaPath })\n\t\t\t\t\treturn content\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\tlogger.debug('.iloom/README.md not found, returning empty string')\n\t\t\treturn ''\n\t\t} catch (error) {\n\t\t\t// Graceful degradation - return empty string on error\n\t\t\tlogger.debug(`Failed to load .iloom/README.md: ${error}`)\n\t\t\treturn ''\n\t\t}\n\t}\n}\n","import os from 'os'\nimport path from 'path'\nimport fs from 'fs-extra'\nimport { parse, modify, applyEdits, ParseError } from 'jsonc-parser'\nimport { fileURLToPath } from 'url'\nimport { accessSync } from 'fs'\nimport { logger } from '../utils/logger.js'\n\n/**\n * Hook configuration for a single event\n */\ninterface HookEntry {\n\ttype: 'command'\n\tcommand: string\n\ttimeout?: number\n}\n\n/**\n * Hook event configuration\n */\ninterface HookEventConfig {\n\tmatcher?: string\n\thooks: HookEntry[]\n}\n\n/**\n * Claude settings.json structure (partial)\n */\ninterface ClaudeSettings {\n\thooks?: Record<string, HookEventConfig[]>\n\t[key: string]: unknown\n}\n\n/**\n * Manages installation of Claude Code hooks to ~/.claude/\n *\n * Hooks enable real-time monitoring of Claude session state\n * via Unix socket communication with the iloom-vscode extension.\n */\nexport class ClaudeHookManager {\n\tprivate claudeDir: string\n\tprivate hooksDir: string\n\tprivate settingsPath: string\n\tprivate templateDir: string\n\n\tconstructor() {\n\t\t// Initialize paths using os.homedir()\n\t\tthis.claudeDir = path.join(os.homedir(), '.claude')\n\t\tthis.hooksDir = path.join(this.claudeDir, 'hooks')\n\t\tthis.settingsPath = path.join(this.claudeDir, 'settings.json')\n\n\t\t// Find templates relative to the package installation\n\t\t// Same pattern as PromptTemplateManager\n\t\tconst currentFileUrl = import.meta.url\n\t\tconst currentFilePath = fileURLToPath(currentFileUrl)\n\t\tconst distDir = path.dirname(currentFilePath)\n\n\t\t// Walk up to find the hooks template directory\n\t\tlet templateDir = path.join(distDir, 'hooks')\n\t\tlet currentDir = distDir\n\n\t\twhile (currentDir !== path.dirname(currentDir)) {\n\t\t\tconst candidatePath = path.join(currentDir, 'hooks')\n\t\t\ttry {\n\t\t\t\taccessSync(candidatePath)\n\t\t\t\ttemplateDir = candidatePath\n\t\t\t\tbreak\n\t\t\t} catch {\n\t\t\t\tcurrentDir = path.dirname(currentDir)\n\t\t\t}\n\t\t}\n\n\t\tthis.templateDir = templateDir\n\t\tlogger.debug('ClaudeHookManager initialized', {\n\t\t\tclaudeDir: this.claudeDir,\n\t\t\thooksDir: this.hooksDir,\n\t\t\tsettingsPath: this.settingsPath,\n\t\t\ttemplateDir: this.templateDir\n\t\t})\n\t}\n\n\t/**\n\t * Install Claude hooks for VSCode integration\n\t *\n\t * This is idempotent - safe to call on every spin.\n\t * Installs hook script to ~/.claude/hooks/ and merges\n\t * hook configuration into ~/.claude/settings.json\n\t */\n\tasync installHooks(): Promise<void> {\n\t\ttry {\n\t\t\t// 1. Create ~/.claude/hooks if missing\n\t\t\tawait fs.ensureDir(this.hooksDir)\n\n\t\t\t// 2. Install hook script from bundled templates\n\t\t\tawait this.installHookScript()\n\n\t\t\t// 3. Merge hook config into settings.json\n\t\t\tawait this.mergeHookConfig()\n\n\t\t\tlogger.debug('Claude hooks installed successfully')\n\t\t} catch (error) {\n\t\t\t// Log warning but don't fail - hooks are optional enhancement\n\t\t\tlogger.warn(\n\t\t\t\t`Failed to install Claude hooks: ${error instanceof Error ? error.message : 'Unknown error'}`\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * Check if hooks are already installed\n\t */\n\tasync isHooksInstalled(): Promise<boolean> {\n\t\ttry {\n\t\t\t// Check if hook script exists\n\t\t\tconst hookScriptPath = path.join(this.hooksDir, 'iloom-hook.js')\n\t\t\tif (!(await fs.pathExists(hookScriptPath))) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\t// Check if settings.json has our hooks\n\t\t\tif (!(await fs.pathExists(this.settingsPath))) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\tconst content = await fs.readFile(this.settingsPath, 'utf8')\n\t\t\tconst errors: ParseError[] = []\n\t\t\tconst settings = parse(content, errors, { allowTrailingComma: true }) as ClaudeSettings\n\n\t\t\tif (errors.length > 0 || !settings?.hooks) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\t// Check if our hooks are registered (check for SessionStart as indicator)\n\t\t\treturn Array.isArray(settings.hooks.SessionStart)\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}\n\n\t/**\n\t * Install the hook script from bundled templates\n\t * Skips write if destination already has identical content\n\t */\n\tprivate async installHookScript(): Promise<void> {\n\t\tconst sourcePath = path.join(this.templateDir, 'iloom-hook.js')\n\t\tconst destPath = path.join(this.hooksDir, 'iloom-hook.js')\n\n\t\t// Check if source template exists\n\t\tif (!(await fs.pathExists(sourcePath))) {\n\t\t\tthrow new Error(`Hook template not found at ${sourcePath}`)\n\t\t}\n\n\t\t// Skip if destination exists and content matches\n\t\tif (await fs.pathExists(destPath)) {\n\t\t\tconst [sourceContent, destContent] = await Promise.all([\n\t\t\t\tfs.readFile(sourcePath, 'utf8'),\n\t\t\t\tfs.readFile(destPath, 'utf8')\n\t\t\t])\n\t\t\tif (sourceContent === destContent) {\n\t\t\t\tlogger.debug('Hook script already up to date, skipping')\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\t// Copy hook script (only when content differs or doesn't exist)\n\t\tawait fs.copyFile(sourcePath, destPath)\n\t\tlogger.debug('Hook script installed', { sourcePath, destPath })\n\t}\n\n\t/**\n\t * Merge hook configuration into settings.json\n\t * Preserves existing user hooks and comments\n\t */\n\tprivate async mergeHookConfig(): Promise<void> {\n\t\t// Ensure ~/.claude directory exists\n\t\tawait fs.ensureDir(this.claudeDir)\n\n\t\t// Read existing settings (or create empty)\n\t\tlet existingContent = '{}'\n\t\tlet existingSettings: ClaudeSettings = {}\n\n\t\tif (await fs.pathExists(this.settingsPath)) {\n\t\t\texistingContent = await fs.readFile(this.settingsPath, 'utf8')\n\t\t\tconst errors: ParseError[] = []\n\t\t\texistingSettings = parse(existingContent, errors, { allowTrailingComma: true }) as ClaudeSettings\n\n\t\t\tif (errors.length > 0) {\n\t\t\t\tlogger.warn('Existing settings.json has parse errors, will attempt to merge anyway')\n\t\t\t}\n\t\t}\n\n\t\t// Get our hook configuration\n\t\tconst ourHooks = this.getHookConfig()\n\n\t\t// Merge hooks - preserve user's existing hooks on same events\n\t\tconst mergedHooks: Record<string, HookEventConfig[]> = { ...(existingSettings.hooks ?? {}) }\n\t\tlet hooksAdded = false\n\n\t\tfor (const [eventName, eventConfigs] of Object.entries(ourHooks)) {\n\t\t\tconst existing = mergedHooks[eventName] ?? []\n\n\t\t\t// Check if our hook is already registered\n\t\t\tconst ourConfig = eventConfigs[0]\n\t\t\tconst ourCommand = ourConfig?.hooks?.[0]?.command\n\t\t\tconst existingConfigIndex = existing.findIndex(\n\t\t\t\t(config) => config.hooks?.some((h) => h.command === ourCommand)\n\t\t\t)\n\n\t\t\tif (existingConfigIndex === -1) {\n\t\t\t\t// Add our hook config to the event\n\t\t\t\tmergedHooks[eventName] = [...existing, ...eventConfigs]\n\t\t\t\thooksAdded = true\n\t\t\t} else {\n\t\t\t\t// Hook is already registered - check if we need to update the matcher\n\t\t\t\tconst existingConfig = existing[existingConfigIndex]\n\t\t\t\tconst ourMatcher = ourConfig?.matcher\n\n\t\t\t\t// Update matcher if our config has one and existing doesn't match\n\t\t\t\tif (existingConfig && ourMatcher !== undefined && existingConfig.matcher !== ourMatcher) {\n\t\t\t\t\texisting[existingConfigIndex] = {\n\t\t\t\t\t\t...existingConfig,\n\t\t\t\t\t\tmatcher: ourMatcher\n\t\t\t\t\t}\n\t\t\t\t\thooksAdded = true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Skip write if no new hooks were added\n\t\tif (!hooksAdded) {\n\t\t\tlogger.debug('All hooks already registered, skipping settings.json update')\n\t\t\treturn\n\t\t}\n\n\t\t// Write updated settings\n\t\tlet content: string\n\n\t\t// Check if existing content has comments\n\t\tif (existingContent.includes('//') || existingContent.includes('/*')) {\n\t\t\t// Use jsonc-parser to preserve comments\n\t\t\tlet modifiedContent = existingContent\n\t\t\tconst edits = modify(modifiedContent, ['hooks'], mergedHooks, {})\n\t\t\tcontent = applyEdits(modifiedContent, edits)\n\t\t} else {\n\t\t\t// No comments - use JSON.stringify\n\t\t\tconst updatedSettings: ClaudeSettings = {\n\t\t\t\t...existingSettings,\n\t\t\t\thooks: mergedHooks\n\t\t\t}\n\t\t\tcontent = JSON.stringify(updatedSettings, null, 2) + '\\n'\n\t\t}\n\n\t\t// Write atomically using temp file + rename\n\t\tconst tempPath = `${this.settingsPath}.tmp`\n\t\tawait fs.writeFile(tempPath, content, 'utf8')\n\t\tawait fs.rename(tempPath, this.settingsPath)\n\n\t\tlogger.debug('Hook configuration merged into settings.json')\n\t}\n\n\t/**\n\t * Get the hook configuration to register\n\t *\n\t * Each event maps to a hook that runs iloom-hook.js\n\t */\n\tprivate getHookConfig(): Record<string, HookEventConfig[]> {\n\t\tconst hookCommand = `node ${path.join(this.hooksDir, 'iloom-hook.js')}`\n\n\t\treturn {\n\t\t\tNotification: [\n\t\t\t\t{ hooks: [{ type: 'command', command: hookCommand }] }\n\t\t\t],\n\t\t\tStop: [\n\t\t\t\t{ hooks: [{ type: 'command', command: hookCommand }] }\n\t\t\t],\n\t\t\tSubagentStop: [\n\t\t\t\t{ hooks: [{ type: 'command', command: hookCommand }] }\n\t\t\t],\n\t\t\tPermissionRequest: [\n\t\t\t\t{ matcher: '*', hooks: [{ type: 'command', command: hookCommand, timeout: 86400 }] }\n\t\t\t],\n\t\t\tPreToolUse: [\n\t\t\t\t{ matcher: '*', hooks: [{ type: 'command', command: hookCommand }] }\n\t\t\t],\n\t\t\tPostToolUse: [\n\t\t\t\t{ matcher: '*', hooks: [{ type: 'command', command: hookCommand }] }\n\t\t\t],\n\t\t\tSessionStart: [\n\t\t\t\t{ matcher: '*', hooks: [{ type: 'command', command: hookCommand }] }\n\t\t\t],\n\t\t\tSessionEnd: [\n\t\t\t\t{ hooks: [{ type: 'command', command: hookCommand }] }\n\t\t\t],\n\t\t\tUserPromptSubmit: [\n\t\t\t\t{ hooks: [{ type: 'command', command: hookCommand }] }\n\t\t\t]\n\t\t}\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAOA,WAAU;AAgBjB,SAAS,gBAAgB;;;AChBzB,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,OAAO,QAAQ;AACf,SAAS,OAAO,QAAQ,kBAA8B;AACtD,SAAS,qBAAqB;AAC9B,SAAS,kBAAkB;AAkCpB,IAAM,oBAAN,MAAwB;AAAA,EAM9B,cAAc;AAEb,SAAK,YAAY,KAAK,KAAK,GAAG,QAAQ,GAAG,SAAS;AAClD,SAAK,WAAW,KAAK,KAAK,KAAK,WAAW,OAAO;AACjD,SAAK,eAAe,KAAK,KAAK,KAAK,WAAW,eAAe;AAI7D,UAAM,iBAAiB,YAAY;AACnC,UAAM,kBAAkB,cAAc,cAAc;AACpD,UAAM,UAAU,KAAK,QAAQ,eAAe;AAG5C,QAAI,cAAc,KAAK,KAAK,SAAS,OAAO;AAC5C,QAAI,aAAa;AAEjB,WAAO,eAAe,KAAK,QAAQ,UAAU,GAAG;AAC/C,YAAM,gBAAgB,KAAK,KAAK,YAAY,OAAO;AACnD,UAAI;AACH,mBAAW,aAAa;AACxB,sBAAc;AACd;AAAA,MACD,QAAQ;AACP,qBAAa,KAAK,QAAQ,UAAU;AAAA,MACrC;AAAA,IACD;AAEA,SAAK,cAAc;AACnB,WAAO,MAAM,iCAAiC;AAAA,MAC7C,WAAW,KAAK;AAAA,MAChB,UAAU,KAAK;AAAA,MACf,cAAc,KAAK;AAAA,MACnB,aAAa,KAAK;AAAA,IACnB,CAAC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,eAA8B;AACnC,QAAI;AAEH,YAAM,GAAG,UAAU,KAAK,QAAQ;AAGhC,YAAM,KAAK,kBAAkB;AAG7B,YAAM,KAAK,gBAAgB;AAE3B,aAAO,MAAM,qCAAqC;AAAA,IACnD,SAAS,OAAO;AAEf,aAAO;AAAA,QACN,mCAAmC,iBAAiB,QAAQ,MAAM,UAAU,eAAe;AAAA,MAC5F;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,mBAAqC;AAC1C,QAAI;AAEH,YAAM,iBAAiB,KAAK,KAAK,KAAK,UAAU,eAAe;AAC/D,UAAI,CAAE,MAAM,GAAG,WAAW,cAAc,GAAI;AAC3C,eAAO;AAAA,MACR;AAGA,UAAI,CAAE,MAAM,GAAG,WAAW,KAAK,YAAY,GAAI;AAC9C,eAAO;AAAA,MACR;AAEA,YAAM,UAAU,MAAM,GAAG,SAAS,KAAK,cAAc,MAAM;AAC3D,YAAM,SAAuB,CAAC;AAC9B,YAAM,WAAW,MAAM,SAAS,QAAQ,EAAE,oBAAoB,KAAK,CAAC;AAEpE,UAAI,OAAO,SAAS,KAAK,EAAC,qCAAU,QAAO;AAC1C,eAAO;AAAA,MACR;AAGA,aAAO,MAAM,QAAQ,SAAS,MAAM,YAAY;AAAA,IACjD,QAAQ;AACP,aAAO;AAAA,IACR;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,oBAAmC;AAChD,UAAM,aAAa,KAAK,KAAK,KAAK,aAAa,eAAe;AAC9D,UAAM,WAAW,KAAK,KAAK,KAAK,UAAU,eAAe;AAGzD,QAAI,CAAE,MAAM,GAAG,WAAW,UAAU,GAAI;AACvC,YAAM,IAAI,MAAM,8BAA8B,UAAU,EAAE;AAAA,IAC3D;AAGA,QAAI,MAAM,GAAG,WAAW,QAAQ,GAAG;AAClC,YAAM,CAAC,eAAe,WAAW,IAAI,MAAM,QAAQ,IAAI;AAAA,QACtD,GAAG,SAAS,YAAY,MAAM;AAAA,QAC9B,GAAG,SAAS,UAAU,MAAM;AAAA,MAC7B,CAAC;AACD,UAAI,kBAAkB,aAAa;AAClC,eAAO,MAAM,0CAA0C;AACvD;AAAA,MACD;AAAA,IACD;AAGA,UAAM,GAAG,SAAS,YAAY,QAAQ;AACtC,WAAO,MAAM,yBAAyB,EAAE,YAAY,SAAS,CAAC;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,kBAAiC;AA7KhD;AA+KE,UAAM,GAAG,UAAU,KAAK,SAAS;AAGjC,QAAI,kBAAkB;AACtB,QAAI,mBAAmC,CAAC;AAExC,QAAI,MAAM,GAAG,WAAW,KAAK,YAAY,GAAG;AAC3C,wBAAkB,MAAM,GAAG,SAAS,KAAK,cAAc,MAAM;AAC7D,YAAM,SAAuB,CAAC;AAC9B,yBAAmB,MAAM,iBAAiB,QAAQ,EAAE,oBAAoB,KAAK,CAAC;AAE9E,UAAI,OAAO,SAAS,GAAG;AACtB,eAAO,KAAK,uEAAuE;AAAA,MACpF;AAAA,IACD;AAGA,UAAM,WAAW,KAAK,cAAc;AAGpC,UAAM,cAAiD,EAAE,GAAI,iBAAiB,SAAS,CAAC,EAAG;AAC3F,QAAI,aAAa;AAEjB,eAAW,CAAC,WAAW,YAAY,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACjE,YAAM,WAAW,YAAY,SAAS,KAAK,CAAC;AAG5C,YAAM,YAAY,aAAa,CAAC;AAChC,YAAM,cAAa,kDAAW,UAAX,mBAAmB,OAAnB,mBAAuB;AAC1C,YAAM,sBAAsB,SAAS;AAAA,QACpC,CAAC,WAAQ;AA7Mb,cAAAC;AA6MgB,kBAAAA,MAAA,OAAO,UAAP,gBAAAA,IAAc,KAAK,CAAC,MAAM,EAAE,YAAY;AAAA;AAAA,MACrD;AAEA,UAAI,wBAAwB,IAAI;AAE/B,oBAAY,SAAS,IAAI,CAAC,GAAG,UAAU,GAAG,YAAY;AACtD,qBAAa;AAAA,MACd,OAAO;AAEN,cAAM,iBAAiB,SAAS,mBAAmB;AACnD,cAAM,aAAa,uCAAW;AAG9B,YAAI,kBAAkB,eAAe,UAAa,eAAe,YAAY,YAAY;AACxF,mBAAS,mBAAmB,IAAI;AAAA,YAC/B,GAAG;AAAA,YACH,SAAS;AAAA,UACV;AACA,uBAAa;AAAA,QACd;AAAA,MACD;AAAA,IACD;AAGA,QAAI,CAAC,YAAY;AAChB,aAAO,MAAM,6DAA6D;AAC1E;AAAA,IACD;AAGA,QAAI;AAGJ,QAAI,gBAAgB,SAAS,IAAI,KAAK,gBAAgB,SAAS,IAAI,GAAG;AAErE,UAAI,kBAAkB;AACtB,YAAM,QAAQ,OAAO,iBAAiB,CAAC,OAAO,GAAG,aAAa,CAAC,CAAC;AAChE,gBAAU,WAAW,iBAAiB,KAAK;AAAA,IAC5C,OAAO;AAEN,YAAM,kBAAkC;AAAA,QACvC,GAAG;AAAA,QACH,OAAO;AAAA,MACR;AACA,gBAAU,KAAK,UAAU,iBAAiB,MAAM,CAAC,IAAI;AAAA,IACtD;AAGA,UAAM,WAAW,GAAG,KAAK,YAAY;AACrC,UAAM,GAAG,UAAU,UAAU,SAAS,MAAM;AAC5C,UAAM,GAAG,OAAO,UAAU,KAAK,YAAY;AAE3C,WAAO,MAAM,8CAA8C;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,gBAAmD;AAC1D,UAAM,cAAc,QAAQ,KAAK,KAAK,KAAK,UAAU,eAAe,CAAC;AAErE,WAAO;AAAA,MACN,cAAc;AAAA,QACb,EAAE,OAAO,CAAC,EAAE,MAAM,WAAW,SAAS,YAAY,CAAC,EAAE;AAAA,MACtD;AAAA,MACA,MAAM;AAAA,QACL,EAAE,OAAO,CAAC,EAAE,MAAM,WAAW,SAAS,YAAY,CAAC,EAAE;AAAA,MACtD;AAAA,MACA,cAAc;AAAA,QACb,EAAE,OAAO,CAAC,EAAE,MAAM,WAAW,SAAS,YAAY,CAAC,EAAE;AAAA,MACtD;AAAA,MACA,mBAAmB;AAAA,QAClB,EAAE,SAAS,KAAK,OAAO,CAAC,EAAE,MAAM,WAAW,SAAS,aAAa,SAAS,MAAM,CAAC,EAAE;AAAA,MACpF;AAAA,MACA,YAAY;AAAA,QACX,EAAE,SAAS,KAAK,OAAO,CAAC,EAAE,MAAM,WAAW,SAAS,YAAY,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,aAAa;AAAA,QACZ,EAAE,SAAS,KAAK,OAAO,CAAC,EAAE,MAAM,WAAW,SAAS,YAAY,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,cAAc;AAAA,QACb,EAAE,SAAS,KAAK,OAAO,CAAC,EAAE,MAAM,WAAW,SAAS,YAAY,CAAC,EAAE;AAAA,MACpE;AAAA,MACA,YAAY;AAAA,QACX,EAAE,OAAO,CAAC,EAAE,MAAM,WAAW,SAAS,YAAY,CAAC,EAAE;AAAA,MACtD;AAAA,MACA,kBAAkB;AAAA,QACjB,EAAE,OAAO,CAAC,EAAE,MAAM,WAAW,SAAS,YAAY,CAAC,EAAE;AAAA,MACtD;AAAA,IACD;AAAA,EACD;AACD;;;ADnRO,IAAM,0BAAN,cAAsC,MAAM;AAAA,EAClD,YACC,SACgB,YACf;AACD,UAAM,OAAO;AAFG;AAGhB,SAAK,OAAO;AAAA,EACb;AACD;AAcO,IAAM,gBAAN,MAAoB;AAAA,EAS1B,YACC,iBACA,oBACA,cACA,iBACA,iBACA,aACC;AACD,SAAK,kBAAkB,mBAAmB,IAAI,sBAAsB;AACpE,SAAK,qBAAqB,sBAAsB,IAAI,mBAAmB;AACvE,SAAK,eAAe,gBAAgB,IAAI,aAAa;AACrD,SAAK,kBAAkB,mBAAmB,IAAI,gBAAgB;AAC9D,SAAK,kBAAkB,mBAAmB,IAAI,gBAAgB,MAAM;AACpE,SAAK,cAAc,eAAe,IAAI,kBAAkB;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,0BAAyC;AACtD,UAAM,aAAa,QAAQ,IAAI;AAG/B,UAAM,YAAY,MAAM,eAAe,UAAU;AACjD,QAAI,CAAC,WAAW;AAEf;AAAA,IACD;AAGA,UAAM,eAAe,MAAM,gBAAgB,UAAU;AACrD,QAAI,CAAC,cAAc;AAElB;AAAA,IACD;AAGA,UAAM,YAAY,MAAM,KAAK,mBAAmB,cAAc;AAC9D,UAAM,kBAAkB,UAAU,KAAK,QAAM,GAAG,SAAS,YAAY;AAErE,QAAI,CAAC,iBAAiB;AAErB;AAAA,IACD;AAGA,UAAM,SAAS,MAAM,KAAK,mBAAmB,eAAe,iBAAiB,KAAK,eAAe;AACjG,QAAI,QAAQ;AACX,YAAM,IAAI;AAAA,QACT;AAAA,QACA;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,MAAM,QAAQ,SAAuB,cAMnB;AApInB;AAqIE,SAAK,eAAe;AAGpB,UAAM,gBAAc,UAAK,iBAAL,mBAAmB,SAAQ,aAAW,UAAK,iBAAL,mBAAmB,eAAc;AAC3F,QAAI,YAAY;AACf,YAAM,aAAa,mBAAmB;AACtC,aAAO,WAAW,YAAY,MAAM,KAAK,gBAAgB,OAAO,CAAC;AAAA,IAClE;AAEA,WAAO,KAAK,gBAAgB,OAAO;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,gBAAgB,SAAsC;AApJrE;AAuJE,YAAQ,IAAI,QAAQ;AAGpB,QAAI;AACH,YAAM,KAAK,wBAAwB;AAAA,IACpC,SAAS,OAAO;AACf,UAAI,iBAAiB,yBAAyB;AAC7C,eAAO,MAAM,MAAM,OAAO;AAC1B,eAAO,KAAK,MAAM,UAAU;AAC5B,cAAM;AAAA,MACP;AACA,YAAM;AAAA,IACP;AAEA,QAAI;AACH,aAAO,KAAK,oDAA6C;AAGzD,YAAM,aAAa,MAAM,KAAK,gBAAgB,WAAW;AACzD,UAAI,YAAY;AACf,eAAO,QAAQ,sDAAsD;AAAA,MACtE;AAGA,YAAM,KAAK,YAAY,aAAa;AAGpC,YAAM,UAAU,MAAM,KAAK,uBAAuB;AAElD,aAAO,MAAM,mCAAmC,EAAE,QAAQ,CAAC;AAG3D,WAAK,mBAAmB,OAAO;AAE/B,aAAO,KAAK,2DAAoD;AAGhE,YAAM,kBAAkB,IAAI,gBAAgB;AAC5C,YAAM,WAAW,MAAM,gBAAgB,aAAa,QAAQ,aAAa;AACzE,YAAM,iBAAgB,qCAAU,kBAAiB;AAEjD,YAAM,aAAa,mBAAiB,0CAAU,WAAV,mBAAmB,OAAO,aAAa,MACxE,SAAS,OAAO,OAAO,aAAa,CAAC,IACrC;AAOH,YAAM,iBAAgB,qCAAU,YAAW;AAC3C,YAAM,yBAAuB,UAAK,iBAAL,mBAAmB,UAAS;AACzD,YAAM,mBAAgC,uBAAuB,aAAc,WAAW;AAGtF,UAAI,CAAC,KAAK,UAAU;AACnB,cAAM,eAAe,yBAAyB;AAC9C,aAAK,WAAW,MAAM,KAAK,gBAAgB,aAAa,QAAW,YAAY;AAAA,MAChF;AAGA,YAAI,0CAAU,iBAAV,mBAAwB,SAAS,WAAU,QAAQ,YAAY;AAClE,cAAM,aAAW,sBAAK,aAAL,mBAAe,iBAAf,mBAA6B,QAA7B,mBAAkC,aAAY;AAC/D,gBAAQ,OAAO,MAAM,iBAAiB;AAAA,UACrC;AAAA,UACA,cAAc,QAAQ;AAAA,UACtB,gBAAgB,QAAQ;AAAA,QACzB,CAAC;AACD,eAAO,KAAK,sCAA+B,QAAQ,IAAI,EAAE;AAAA,MAC1D;AAGA,YAAM,YAAY,KAAK,uBAAuB,SAAS,kBAAkB,eAAe,UAAU;AAGlG,UAAI,YAAY;AACf,kBAAU,kBAAkB;AAC5B,kBAAU,iBAAiB,MAAM,KAAK,kBAAkB;AACxD,kBAAU,0BAA0B,MAAM,KAAK,0BAA0B;AAAA,MAC1E;AAEA,YAAM,qBAAqB,MAAM,KAAK,gBAAgB,UAAU,QAAQ,MAAM,SAAS;AAGvF,YAAM,aAAa,KAAK,gBAAgB,gBAAgB;AAGxD,YAAM,QAAQ,KAAK,gBAAgB,aAAa,KAAK,QAAQ;AAC7D,UAAI,iBAAiB,KAAK,6BAA6B,QAAQ,IAAI;AAGnE,UAAI,qBAAqB,qBAAqB;AAC7C,yBAAiB;AAAA,MAClB;AAGA,UAAI,mBAAmB,qBAAqB;AAC3C,eAAO;AAAA,UACN;AAAA,QAED;AAAA,MACD;AAIA,YAAM,YAAY,qCAAU;AAC5B,UAAI,CAAC,WAAW;AACf,cAAM,IAAI,MAAM,2FAA2F;AAAA,MAC5G;AACA,aAAO,MAAM,kCAAkC,EAAE,UAAU,CAAC;AAG5D,YAAM,eAAa,UAAK,iBAAL,mBAAmB,UAAS;AAE/C,YAAM,gBAAkC;AAAA,QACvC,UAAU;AAAA,QACV,QAAQ,QAAQ;AAAA,QAChB;AAAA;AAAA,MACD;AAGA,UAAI,UAAU,QAAW;AACxB,sBAAc,QAAQ;AAAA,MACvB;AAIA,UAAI,YAAY;AACf,yBAAiB;AAAA,MAClB;AACA,UAAI,mBAAmB,UAAa,mBAAmB,WAAW;AACjE,sBAAc,iBAAiB;AAAA,MAChC;AAGA,YAAI,UAAK,iBAAL,mBAAmB,kBAAiB,QAAW;AAClD,sBAAc,eAAe,KAAK,aAAa;AAAA,MAChD;AACA,YAAI,UAAK,iBAAL,mBAAmB,aAAY,QAAW;AAC7C,sBAAc,UAAU,KAAK,aAAa;AAAA,MAC3C;AAGA,WAAI,UAAK,iBAAL,mBAAmB,MAAM;AAC5B,sBAAc,WAAW;AACzB,sBAAc,eAAe;AAAA,MAC9B,YAAW,UAAK,iBAAL,mBAAmB,YAAY;AACzC,sBAAc,WAAW;AACzB,sBAAc,eAAe;AAAA,MAC9B;AAGA,UAAI,QAAQ,eAAe,QAAW;AACrC,sBAAc,aAAa,QAAQ;AAAA,MACpC;AAGA,UAAI;AACJ,UAAI;AACJ,UAAI;AAEJ,UAAI,QAAQ,SAAS,WAAW,QAAQ,SAAS,MAAM;AACtD,YAAI;AACH,gBAAM,WAAW,KAAK,WAAW,oBAAoB,gBAAgB,KAAK,QAAQ,IAAI;AAEtF,sBAAY,MAAM,iCAAiC,QAAQ,MAAM,QAAW,UAAU,KAAK,UAAU,aAAa;AAClH,iBAAO,MAAM,oDAAoD,EAAE,UAAU,cAAc,CAAC;AAK5F,gBAAM,YAAY;AAAA,YACjB;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACD;AACA,yBAAe,QAAQ,SAAS,OAC7B,CAAC,GAAG,WAAW,iCAAiC,sBAAsB,IACtE;AACH,4BAAkB,CAAC,qFAAqF;AAExG,iBAAO,MAAM,mDAAmD,EAAE,cAAc,gBAAgB,CAAC;AAAA,QAClG,SAAS,OAAO;AAEf,iBAAO,KAAK,kCAAkC,iBAAiB,QAAQ,MAAM,UAAU,eAAe,EAAE;AAAA,QACzG;AAAA,MACD,OAAO;AAEN,uBAAe;AAAA,UACd;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACD;AACA,eAAO,MAAM,kDAAkD,EAAE,aAAa,CAAC;AAAA,MAChF;AAIA,UAAI;AACH,YAAI,CAAC,UAAU;AACd,gBAAM,IAAI,MAAM,2CAA2C;AAAA,QAC5D;AACA,cAAM,iBAAiB,uBAAuB,QAAQ,eAAe,QAAQ;AAC7E,YAAI,WAAW;AACd,oBAAU,KAAK,GAAG,cAAc;AAAA,QACjC,OAAO;AACN,sBAAY;AAAA,QACb;AACA,eAAO,MAAM,8CAA8C;AAAA,MAC5D,SAAS,OAAO;AAEf,eAAO,KAAK,wCAAwC,iBAAiB,QAAQ,MAAM,UAAU,eAAe,EAAE;AAAA,MAC/G;AAGA,UAAI;AACJ,UAAI;AAEH,cAAI,UAAK,aAAL,mBAAe,WAAU,OAAO,KAAK,KAAK,SAAS,MAAM,EAAE,SAAS,GAAG;AAC1E,iBAAO,MAAM,2BAA2B;AAAA,YACvC,gBAAgB,OAAO,KAAK,KAAK,SAAS,MAAM;AAAA,UACjD,CAAC;AAAA,QACF;AAIA,cAAM,eAAe,MAAM,KAAK,aAAa;AAAA,UAC5C,KAAK;AAAA,UACL;AAAA,UACA,CAAC,QAAQ,8BAA8B;AAAA,QACxC;AACA,iBAAS,KAAK,aAAa,aAAa,YAAY;AACpD,eAAO,MAAM,+BAA+B;AAAA,UAC3C,YAAY,OAAO,KAAK,MAAM,EAAE;AAAA,UAChC,YAAY,OAAO,KAAK,MAAM;AAAA,QAC/B,CAAC;AAAA,MACF,SAAS,OAAO;AAEf,eAAO,KAAK,0BAA0B,iBAAiB,QAAQ,MAAM,UAAU,eAAe,EAAE;AAAA,MACjG;AAEA,aAAO,MAAM,wCAAwC;AAAA,QACpD,MAAM,QAAQ;AAAA,QACd;AAAA,QACA;AAAA,QACA,eAAe,QAAQ;AAAA,QACvB,cAAc,CAAC,CAAC;AAAA,MACjB,CAAC;AAED,aAAO,KAAK,aAAa,gDAA2C,gDAA2C;AAG/G,YAAM,eAAe,MAAM,aAAa,YAAY;AAAA,QACnD,GAAG;AAAA,QACH,oBAAoB;AAAA,QACpB,GAAI,aAAa,EAAE,UAAU;AAAA,QAC7B,GAAI,gBAAgB,EAAE,aAAa;AAAA,QACnC,GAAI,mBAAmB,EAAE,gBAAgB;AAAA,QACzC,GAAI,UAAU,EAAE,OAAO;AAAA,MACxB,CAAC;AAGD,WAAI,UAAK,iBAAL,mBAAmB,MAAM;AAE5B,gBAAQ,IAAI,KAAK,UAAU;AAAA,UAC1B,SAAS;AAAA,UACT,QAAQ,gBAAgB;AAAA,QACzB,CAAC,CAAC;AAAA,MACH;AAGA,UAAI,YAAY;AACf,cAAM,KAAK,gBAAgB,UAAU;AAAA,MACtC;AAAA,IACD,SAAS,OAAO;AACf,YAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU;AAE9D,WAAI,UAAK,iBAAL,mBAAmB,MAAM;AAE5B,gBAAQ,IAAI,KAAK,UAAU;AAAA,UAC1B,SAAS;AAAA,UACT,OAAO;AAAA,QACR,CAAC,CAAC;AAAA,MACH,OAAO;AACN,eAAO,MAAM,4BAA4B,YAAY,EAAE;AAAA,MACxD;AACA,YAAM;AAAA,IACP;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAmB,SAAsC;AAChE,QAAI,QAAQ,SAAS,SAAS;AAC7B,aAAO,KAAK,6CAAsC,QAAQ,WAAW,EAAE;AAAA,IACxE,WAAW,QAAQ,SAAS,MAAM;AACjC,aAAO,KAAK,uCAAgC,QAAQ,QAAQ,EAAE;AAAA,IAC/D,OAAO;AACN,aAAO,KAAK,qCAA8B;AAAA,IAC3C;AAEA,QAAI,QAAQ,YAAY;AACvB,aAAO,KAAK,gCAAyB,QAAQ,UAAU,EAAE;AAAA,IAC1D;AAEA,QAAI,QAAQ,MAAM;AACjB,aAAO,KAAK,sCAA+B,QAAQ,IAAI,EAAE;AAAA,IAC1D;AAAA,EACD;AAAA;AAAA;AAAA;AAAA,EAKQ,uBACP,SACA,SACA,eACA,YACoB;AA7dtB;AA8dE,UAAM,YAA+B;AAAA,MACpC,gBAAgB,QAAQ;AAAA,IACzB;AAEA,QAAI,QAAQ,gBAAgB,QAAW;AACtC,gBAAU,eAAe,QAAQ;AAAA,IAClC;AAEA,QAAI,QAAQ,aAAa,QAAW;AACnC,gBAAU,YAAY,QAAQ;AAAA,IAC/B;AAEA,QAAI,QAAQ,UAAU,QAAW;AAChC,UAAI,QAAQ,SAAS,SAAS;AAC7B,kBAAU,cAAc,QAAQ;AAAA,MACjC,WAAW,QAAQ,SAAS,MAAM;AACjC,kBAAU,WAAW,QAAQ;AAAA,MAC9B;AAAA,IACD;AAEA,QAAI,QAAQ,SAAS,QAAW;AAC/B,gBAAU,OAAO,QAAQ;AAAA,IAC1B;AAGA,QAAI,YAAY,cAAc,YAAY,qBAAqB;AAC9D,gBAAU,gBAAgB;AAAA,IAC3B,OAAO;AACN,gBAAU,mBAAmB;AAAA,IAC9B;AAGA,WAAO,OAAO,WAAW,8BAA6B,UAAK,aAAL,mBAAe,MAAM,CAAC;AAI5E,QAAI,kBAAkB,QAAW;AAChC,gBAAU,gBAAgB;AAC1B,gBAAU,kBAAkB;AAC5B,UAAI,YAAY;AACf,kBAAU,eAAe;AAAA,MAC1B;AAGA,YAAM,0BAAwB,gBAAK,aAAL,mBAAe,kBAAf,mBAA8B,oBAAmB;AAC/E,gBAAU,mBAAmB;AAE7B,YAAM,WAAS,gBAAK,aAAL,mBAAe,kBAAf,mBAA8B,WAAU;AACvD,UAAI,CAAC,mBAAmB,KAAK,MAAM,GAAG;AACrC,cAAM,IAAI,MAAM,6BAA6B,MAAM,qFAAqF;AAAA,MACzI;AACA,gBAAU,aAAa;AAAA,IACxB,WAAW,QAAQ,SAAS,WAAW;AAEtC,gBAAU,uBAAuB;AAAA,IAClC,OAAO;AAEN,gBAAU,sBAAsB;AAAA,IACjC;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,6BACP,MACqC;AAniBvC;AAqiBE,SAAI,UAAK,aAAL,mBAAe,WAAW;AAC7B,YAAM,iBACL,SAAS,UACN,KAAK,SAAS,UAAU,QACxB,SAAS,OACR,KAAK,SAAS,UAAU,KACxB,KAAK,SAAS,UAAU;AAE7B,UAAI,iDAAgB,gBAAgB;AACnC,eAAO,eAAe;AAAA,MACvB;AAAA,IACD;AAGA,QAAI,SAAS,SAAS;AACrB,aAAO;AAAA,IACR;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAc,yBAAyD;AACtE,UAAM,gBAAgB,QAAQ,IAAI;AAClC,UAAM,aAAaC,MAAK,SAAS,aAAa;AAI9C,UAAM,YAAY;AAClB,UAAM,UAAU,WAAW,MAAM,SAAS;AAE1C,QAAI,mCAAU,IAAI;AACjB,YAAM,WAAW,SAAS,QAAQ,CAAC,GAAG,EAAE;AACxC,aAAO,MAAM,qBAAqB,QAAQ,oBAAoB,UAAU,EAAE;AAE1E,aAAO,KAAK,kBAAkB,UAAU,aAAa;AAAA,IACtD;AAGA,UAAM,cAAc,mBAAmB,UAAU;AAEjD,QAAI,gBAAgB,MAAM;AACzB,aAAO,MAAM,wBAAwB,WAAW,oBAAoB,UAAU,EAAE;AAEhF,aAAO,KAAK,qBAAqB,aAAa,aAAa;AAAA,IAC5D;AAGA,QAAI;AACH,YAAM,WAAW,MAAM,KAAK,mBAAmB,YAAY;AAC3D,YAAM,gBAAgB,SAAS;AAE/B,UAAI,eAAe;AAElB,cAAM,oBAAoB,mBAAmB,aAAa;AAC1D,YAAI,sBAAsB,MAAM;AAC/B,iBAAO,MAAM,wBAAwB,iBAAiB,iBAAiB,aAAa,EAAE;AAEtF,iBAAO,KAAK,qBAAqB,mBAAmB,eAAe,aAAa;AAAA,QACjF;AAAA,MACD;AAAA,IACD,SAAS,OAAO;AAEf,aAAO,MAAM,oCAAoC,EAAE,MAAM,CAAC;AAAA,IAC3D;AAGA,WAAO,MAAM,sDAAsD;AACnE,WAAO,KAAK,uBAAuB,aAAa;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,qBACb,aACA,eACA,YACiC;AAEjC,QAAI,CAAC,YAAY;AAChB,UAAI;AACH,cAAM,WAAW,MAAM,KAAK,mBAAmB,YAAY;AAC3D,qBAAa,SAAS,iBAAiB;AAAA,MACxC,QAAQ;AAAA,MAER;AAAA,IACD;AAEA,UAAM,UAAiC;AAAA,MACtC,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,UAAU;AAAA;AAAA,IACX;AAEA,QAAI,eAAe,QAAW;AAC7B,cAAQ,aAAa;AAAA,IACtB;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,kBACb,UACA,eACiC;AAEjC,QAAI;AACJ,QAAI;AACH,YAAM,WAAW,MAAM,KAAK,mBAAmB,YAAY;AAC3D,mBAAa,SAAS,iBAAiB;AAAA,IACxC,QAAQ;AAAA,IAER;AAEA,UAAM,UAAiC;AAAA,MACtC,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,UAAU;AAAA;AAAA,IACX;AAEA,QAAI,eAAe,QAAW;AAC7B,cAAQ,aAAa;AAAA,IACtB;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,uBAAuB,eAAuD;AAE3F,QAAI;AACJ,QAAI;AACH,YAAM,WAAW,MAAM,KAAK,mBAAmB,YAAY;AAC3D,mBAAa,SAAS,iBAAiB;AAAA,IACxC,QAAQ;AAAA,IAER;AAEA,UAAM,UAAiC;AAAA,MACtC,MAAM;AAAA,MACN;AAAA,MACA,UAAU;AAAA;AAAA,IACX;AAEA,QAAI,eAAe,QAAW;AAC7B,cAAQ,aAAa;AAAA,IACtB;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAMQ,gBAAgB,UAAuB,WAAmB;AAEjE,QAAI,YAAY,cAAc,YAAY,qBAAqB;AAC9D,aAAO;AAAA,IACR;AAGA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,oBAAqC;AAClD,QAAI;AAGH,UAAI,aAAaA,MAAK,QAAQ,IAAI,IAAI,YAAY,GAAG,EAAE,QAAQ;AAG/D,aAAO,eAAeA,MAAK,QAAQ,UAAU,GAAG;AAC/C,cAAM,aAAaA,MAAK,KAAK,YAAY,WAAW;AACpD,YAAI;AACH,gBAAM,UAAU,MAAM,SAAS,YAAY,OAAO;AAClD,iBAAO,MAAM,wCAAwC,EAAE,WAAW,CAAC;AACnE,iBAAO;AAAA,QACR,QAAQ;AACP,uBAAaA,MAAK,QAAQ,UAAU;AAAA,QACrC;AAAA,MACD;AAEA,aAAO,MAAM,6CAA6C;AAC1D,aAAO;AAAA,IACR,SAAS,OAAO;AAEf,aAAO,MAAM,6BAA6B,KAAK,EAAE;AACjD,aAAO;AAAA,IACR;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,4BAA6C;AAC1D,QAAI;AAEH,UAAI,aAAaA,MAAK,QAAQ,IAAI,IAAI,YAAY,GAAG,EAAE,QAAQ;AAG/D,aAAO,eAAeA,MAAK,QAAQ,UAAU,GAAG;AAC/C,cAAM,aAAaA,MAAK,KAAK,YAAY,UAAU,WAAW;AAC9D,YAAI;AACH,gBAAM,UAAU,MAAM,SAAS,YAAY,OAAO;AAClD,iBAAO,MAAM,+CAA+C,EAAE,WAAW,CAAC;AAC1E,iBAAO;AAAA,QACR,QAAQ;AACP,uBAAaA,MAAK,QAAQ,UAAU;AAAA,QACrC;AAAA,MACD;AAEA,aAAO,MAAM,oDAAoD;AACjE,aAAO;AAAA,IACR,SAAS,OAAO;AAEf,aAAO,MAAM,oCAAoC,KAAK,EAAE;AACxD,aAAO;AAAA,IACR;AAAA,EACD;AACD;","names":["path","_a","path"]}
package/dist/index.d.ts CHANGED
@@ -269,14 +269,17 @@ declare const IloomSettingsSchema: z.ZodObject<{
269
269
  model: z.ZodOptional<z.ZodEnum<["sonnet", "opus", "haiku"]>>;
270
270
  enabled: z.ZodOptional<z.ZodBoolean>;
271
271
  providers: z.ZodOptional<z.ZodRecord<z.ZodEnum<["claude", "gemini", "codex"]>, z.ZodString>>;
272
+ review: z.ZodOptional<z.ZodBoolean>;
272
273
  }, "strip", z.ZodTypeAny, {
273
274
  model?: "opus" | "sonnet" | "haiku" | undefined;
274
275
  enabled?: boolean | undefined;
275
276
  providers?: Partial<Record<"claude" | "gemini" | "codex", string>> | undefined;
277
+ review?: boolean | undefined;
276
278
  }, {
277
279
  model?: "opus" | "sonnet" | "haiku" | undefined;
278
280
  enabled?: boolean | undefined;
279
281
  providers?: Partial<Record<"claude" | "gemini" | "codex", string>> | undefined;
282
+ review?: boolean | undefined;
280
283
  }>>>>;
281
284
  spin: z.ZodOptional<z.ZodObject<{
282
285
  model: z.ZodDefault<z.ZodEnum<["sonnet", "opus", "haiku"]>>;
@@ -406,12 +409,15 @@ declare const IloomSettingsSchema: z.ZodObject<{
406
409
  mergeBehavior: z.ZodOptional<z.ZodObject<{
407
410
  mode: z.ZodDefault<z.ZodEnum<["local", "github-pr", "github-draft-pr"]>>;
408
411
  remote: z.ZodOptional<z.ZodString>;
412
+ autoCommitPush: z.ZodOptional<z.ZodBoolean>;
409
413
  }, "strip", z.ZodTypeAny, {
410
414
  mode: "local" | "github-pr" | "github-draft-pr";
411
415
  remote?: string | undefined;
416
+ autoCommitPush?: boolean | undefined;
412
417
  }, {
413
418
  remote?: string | undefined;
414
419
  mode?: "local" | "github-pr" | "github-draft-pr" | undefined;
420
+ autoCommitPush?: boolean | undefined;
415
421
  }>>;
416
422
  ide: z.ZodOptional<z.ZodObject<{
417
423
  type: z.ZodDefault<z.ZodEnum<["vscode", "cursor", "webstorm", "sublime", "intellij", "windsurf", "antigravity"]>>;
@@ -485,6 +491,7 @@ declare const IloomSettingsSchema: z.ZodObject<{
485
491
  model?: "opus" | "sonnet" | "haiku" | undefined;
486
492
  enabled?: boolean | undefined;
487
493
  providers?: Partial<Record<"claude" | "gemini" | "codex", string>> | undefined;
494
+ review?: boolean | undefined;
488
495
  }> | null | undefined;
489
496
  spin?: {
490
497
  model: "opus" | "sonnet" | "haiku";
@@ -512,6 +519,7 @@ declare const IloomSettingsSchema: z.ZodObject<{
512
519
  mergeBehavior?: {
513
520
  mode: "local" | "github-pr" | "github-draft-pr";
514
521
  remote?: string | undefined;
522
+ autoCommitPush?: boolean | undefined;
515
523
  } | undefined;
516
524
  ide?: {
517
525
  type: "vscode" | "cursor" | "webstorm" | "sublime" | "intellij" | "windsurf" | "antigravity";
@@ -573,6 +581,7 @@ declare const IloomSettingsSchema: z.ZodObject<{
573
581
  model?: "opus" | "sonnet" | "haiku" | undefined;
574
582
  enabled?: boolean | undefined;
575
583
  providers?: Partial<Record<"claude" | "gemini" | "codex", string>> | undefined;
584
+ review?: boolean | undefined;
576
585
  }> | null | undefined;
577
586
  spin?: {
578
587
  model?: "opus" | "sonnet" | "haiku" | undefined;
@@ -600,6 +609,7 @@ declare const IloomSettingsSchema: z.ZodObject<{
600
609
  mergeBehavior?: {
601
610
  remote?: string | undefined;
602
611
  mode?: "local" | "github-pr" | "github-draft-pr" | undefined;
612
+ autoCommitPush?: boolean | undefined;
603
613
  } | undefined;
604
614
  ide?: {
605
615
  type?: "vscode" | "cursor" | "webstorm" | "sublime" | "intellij" | "windsurf" | "antigravity" | undefined;
@@ -916,7 +926,7 @@ interface CleanupResult {
916
926
  */
917
927
  interface OperationResult {
918
928
  /** Type of operation performed */
919
- type: 'dev-server' | 'worktree' | 'branch' | 'database' | 'cli-symlinks';
929
+ type: 'dev-server' | 'worktree' | 'branch' | 'database' | 'cli-symlinks' | 'recap' | 'metadata';
920
930
  /** Whether operation succeeded */
921
931
  success: boolean;
922
932
  /** Human-readable message */
@@ -952,6 +962,9 @@ interface BranchDeleteOptions {
952
962
  /** Pre-fetched merge target branch (parent branch for child looms, main branch for others).
953
963
  * This must be fetched BEFORE worktree deletion since metadata won't be readable after deletion. */
954
964
  mergeTargetBranch?: string;
965
+ /** Safety check has verified no data loss risk. When true, allows force delete
966
+ * if git branch -d fails with "not fully merged" since safety is already confirmed. */
967
+ safetyVerified?: boolean;
955
968
  }
956
969
  /**
957
970
  * Target for batch cleanup - represents a branch that may or may not have a worktree
@@ -1616,8 +1629,11 @@ interface TemplateVariables {
1616
1629
  COMPACT_SUMMARIES?: string;
1617
1630
  RECAP_DATA?: string;
1618
1631
  DRAFT_PR_NUMBER?: number;
1632
+ DRAFT_PR_URL?: string;
1619
1633
  DRAFT_PR_MODE?: boolean;
1634
+ AUTO_COMMIT_PUSH?: boolean;
1620
1635
  STANDARD_ISSUE_MODE?: boolean;
1636
+ STANDARD_BRANCH_MODE?: boolean;
1621
1637
  IS_VSCODE_MODE?: boolean;
1622
1638
  HAS_PACKAGE_JSON?: boolean;
1623
1639
  NO_PACKAGE_JSON?: boolean;
@@ -1628,6 +1644,19 @@ interface TemplateVariables {
1628
1644
  HAS_REVIEW_CLAUDE?: boolean;
1629
1645
  HAS_REVIEW_GEMINI?: boolean;
1630
1646
  HAS_REVIEW_CODEX?: boolean;
1647
+ ARTIFACT_REVIEW_ENABLED?: boolean;
1648
+ ARTIFACT_REVIEW_CLAUDE_MODEL?: string;
1649
+ ARTIFACT_REVIEW_GEMINI_MODEL?: string;
1650
+ ARTIFACT_REVIEW_CODEX_MODEL?: string;
1651
+ HAS_ARTIFACT_REVIEW_CLAUDE?: boolean;
1652
+ HAS_ARTIFACT_REVIEW_GEMINI?: boolean;
1653
+ HAS_ARTIFACT_REVIEW_CODEX?: boolean;
1654
+ ENHANCER_REVIEW_ENABLED?: boolean;
1655
+ ANALYZER_REVIEW_ENABLED?: boolean;
1656
+ PLANNER_REVIEW_ENABLED?: boolean;
1657
+ ANALYZE_AND_PLAN_REVIEW_ENABLED?: boolean;
1658
+ IMPLEMENTER_REVIEW_ENABLED?: boolean;
1659
+ COMPLEXITY_REVIEW_ENABLED?: boolean;
1631
1660
  EXISTING_ISSUE_MODE?: boolean;
1632
1661
  FRESH_PLANNING_MODE?: boolean;
1633
1662
  PARENT_ISSUE_NUMBER?: string | undefined;
@@ -1644,6 +1673,7 @@ interface TemplateVariables {
1644
1673
  USE_GEMINI_REVIEWER?: boolean;
1645
1674
  USE_CODEX_REVIEWER?: boolean;
1646
1675
  HAS_REVIEWER?: boolean;
1676
+ GIT_REMOTE?: string;
1647
1677
  }
1648
1678
  declare class PromptTemplateManager {
1649
1679
  private templateDir;
@@ -2030,6 +2060,14 @@ declare function ensureRepositoryHasCommits(path?: string): Promise<void>;
2030
2060
  declare function pushBranchToRemote(branchName: string, worktreePath: string, options?: {
2031
2061
  dryRun?: boolean;
2032
2062
  }): Promise<void>;
2063
+ /**
2064
+ * Fetch from origin to ensure we have latest refs
2065
+ * Used before branching and rebasing operations to stay current with remote
2066
+ *
2067
+ * @param cwd - Working directory to run git command in
2068
+ * @throws Error if fetch fails (network issues, access denied, etc.)
2069
+ */
2070
+ declare function fetchOrigin(cwd: string): Promise<void>;
2033
2071
  /**
2034
2072
  * Check if a file is tracked by git
2035
2073
  * Uses git ls-files to check if file is in the index
@@ -2350,4 +2388,4 @@ declare class TableFormatter {
2350
2388
  static previewFormatting(headers: string[], options?: TableFormatterOptions): string;
2351
2389
  }
2352
2390
 
2353
- export { type AddIssueOptions, type AddIssueResult, type BatchCleanupResult, type BranchCleanupTarget, type BranchDeleteOptions, type BranchGenerationOptions, type BranchNameStrategy, type Capability, type ClaudeContext, ClaudeContextManager, type CleanupOptions, type CleanupResult, type ColorData, type CommitOptions, type Config, type CreateLoomInput, type DatabaseDeletionResult, DatabaseManager, type DatabaseProvider, type EnhanceOptions, type EnhanceResult, type EnvFileOptions, type EnvOperationResult, type EnvVariable, EnvironmentManager, type FeedbackOptions, type FinishOptions, type FinishResult, GitCommandError, GitHubService, type GitStatus, type GitWorktree, GitWorktreeManager, type InstallationMethod, type Issue, type IssueTracker, IssueTrackerFactory, type IssueTrackerInputDetection, type IssueTrackerProviderType, type LaunchMode, LinearMarkupConverter, type ListOptions, type Logger, type LoggerOptions, type Loom, type LoomSummary, type MergeOptions, type MergeResult, type MockOptions, type OneShotMode, type OperationResult, PLACEHOLDER_COMMIT_PREFIX, type PRWorktreePattern, type Platform, type PortAssignmentOptions, type ProcessInfo, type ProjectCapability, type PullRequest, type RemoteBranchStatus, type ResourceCleanupOptions, type RgbColor, type SafetyCheck, type StartOptions, type StartResult, type SummaryResult, TableFormatter, type TableFormatterOptions, type TableGenerationOptions, type UpdateCheckCache, type UpdateCheckResult, UserAbortedCommitError, type ValidationOptions, type ValidationResult, type ValidationStepResult, type Workspace, type WorkspaceInput, WorkspaceManager, type WorkspaceSummary, type Worktree, type WorktreeCleanupOptions, type WorktreeCreateOptions, type WorktreeListOptions, type WorktreeOperationResult, type WorktreeStatus, type WorktreeValidation, branchExists, checkRemoteBranchStatus, createLogger, createStderrLogger, ensureRepositoryHasCommits, executeGitCommand, extractIssueNumber, extractPRNumber, findAllBranchesForIssue, findMainWorktreePath, findMainWorktreePathWithSettings, findPlaceholderCommitSha, findWorktreeForBranch, generateWorktreePath, getCurrentBranch, getDefaultBranch, getMergeTargetBranch, getRepoRoot, getThemeMode, getWorktreeRoot, hasUncommittedChanges, isBranchMergedIntoMain, isEmptyRepository, isFileGitignored, isFileTrackedByGit, isPRBranch, isPlaceholderCommit, isRemoteBranchUpToDate, isValidGitRepo, isWorktreePath, logger, parseWorktreeList, pushBranchToRemote, removePlaceholderCommitFromHead, removePlaceholderCommitFromHistory, setThemeMode };
2391
+ export { type AddIssueOptions, type AddIssueResult, type BatchCleanupResult, type BranchCleanupTarget, type BranchDeleteOptions, type BranchGenerationOptions, type BranchNameStrategy, type Capability, type ClaudeContext, ClaudeContextManager, type CleanupOptions, type CleanupResult, type ColorData, type CommitOptions, type Config, type CreateLoomInput, type DatabaseDeletionResult, DatabaseManager, type DatabaseProvider, type EnhanceOptions, type EnhanceResult, type EnvFileOptions, type EnvOperationResult, type EnvVariable, EnvironmentManager, type FeedbackOptions, type FinishOptions, type FinishResult, GitCommandError, GitHubService, type GitStatus, type GitWorktree, GitWorktreeManager, type InstallationMethod, type Issue, type IssueTracker, IssueTrackerFactory, type IssueTrackerInputDetection, type IssueTrackerProviderType, type LaunchMode, LinearMarkupConverter, type ListOptions, type Logger, type LoggerOptions, type Loom, type LoomSummary, type MergeOptions, type MergeResult, type MockOptions, type OneShotMode, type OperationResult, PLACEHOLDER_COMMIT_PREFIX, type PRWorktreePattern, type Platform, type PortAssignmentOptions, type ProcessInfo, type ProjectCapability, type PullRequest, type RemoteBranchStatus, type ResourceCleanupOptions, type RgbColor, type SafetyCheck, type StartOptions, type StartResult, type SummaryResult, TableFormatter, type TableFormatterOptions, type TableGenerationOptions, type UpdateCheckCache, type UpdateCheckResult, UserAbortedCommitError, type ValidationOptions, type ValidationResult, type ValidationStepResult, type Workspace, type WorkspaceInput, WorkspaceManager, type WorkspaceSummary, type Worktree, type WorktreeCleanupOptions, type WorktreeCreateOptions, type WorktreeListOptions, type WorktreeOperationResult, type WorktreeStatus, type WorktreeValidation, branchExists, checkRemoteBranchStatus, createLogger, createStderrLogger, ensureRepositoryHasCommits, executeGitCommand, extractIssueNumber, extractPRNumber, fetchOrigin, findAllBranchesForIssue, findMainWorktreePath, findMainWorktreePathWithSettings, findPlaceholderCommitSha, findWorktreeForBranch, generateWorktreePath, getCurrentBranch, getDefaultBranch, getMergeTargetBranch, getRepoRoot, getThemeMode, getWorktreeRoot, hasUncommittedChanges, isBranchMergedIntoMain, isEmptyRepository, isFileGitignored, isFileTrackedByGit, isPRBranch, isPlaceholderCommit, isRemoteBranchUpToDate, isValidGitRepo, isWorktreePath, logger, parseWorktreeList, pushBranchToRemote, removePlaceholderCommitFromHead, removePlaceholderCommitFromHistory, setThemeMode };
package/dist/index.js CHANGED
@@ -507,7 +507,8 @@ var init_SettingsManager = __esm({
507
507
  providers: z.record(
508
508
  z.enum(["claude", "gemini", "codex"]),
509
509
  z.string()
510
- ).optional().describe('Map of review providers to model names. Keys: claude, gemini, codex. Values: model name strings (e.g., "sonnet", "gemini-3-pro-preview", "gpt-5.2-codex")')
510
+ ).optional().describe('Map of review providers to model names. Keys: claude, gemini, codex. Values: model name strings (e.g., "sonnet", "gemini-3-pro-preview", "gpt-5.2-codex")'),
511
+ review: z.boolean().optional().describe("Whether artifacts from this agent should be reviewed before posting (defaults to false)")
511
512
  });
512
513
  SpinAgentSettingsSchema = z.object({
513
514
  model: z.enum(["sonnet", "opus", "haiku"]).default("opus").describe("Claude model shorthand for spin orchestrator")
@@ -605,7 +606,7 @@ var init_SettingsManager = __esm({
605
606
  copyGitIgnoredPatterns: z.array(z.string().min(1, "Pattern cannot be empty")).optional().describe(`Glob patterns for gitignored files to copy to looms (e.g., ["*.db", "data/*.sqlite"]). Great for local dbs and large test data files that are too big to commit to git. Note: .env (dotenv-flow) files, iloom's and claude's local settings are automatically copied and do not need to be specified here.`),
606
607
  workflows: WorkflowsSettingsSchema.describe("Per-workflow-type permission configurations"),
607
608
  agents: z.record(z.string(), AgentSettingsSchema).optional().nullable().describe(
608
- "Per-agent configuration overrides. Available agents: iloom-issue-analyzer (analyzes issues), iloom-issue-planner (creates implementation plans), iloom-issue-analyze-and-plan (combined analysis and planning), iloom-issue-complexity-evaluator (evaluates complexity), iloom-issue-enhancer (enhances issue descriptions), iloom-issue-implementer (implements code changes), iloom-code-reviewer (reviews code changes against requirements)"
609
+ "Per-agent configuration overrides. Available agents: iloom-issue-analyzer (analyzes issues), iloom-issue-planner (creates implementation plans), iloom-issue-analyze-and-plan (combined analysis and planning), iloom-issue-complexity-evaluator (evaluates complexity), iloom-issue-enhancer (enhances issue descriptions), iloom-issue-implementer (implements code changes), iloom-code-reviewer (reviews code changes against requirements), iloom-artifact-reviewer (reviews artifacts before posting)"
609
610
  ),
610
611
  spin: SpinAgentSettingsSchema.optional().describe(
611
612
  "Spin orchestrator configuration. Model defaults to opus when not configured."
@@ -619,6 +620,7 @@ var init_SettingsManager = __esm({
619
620
  capabilities: CapabilitiesSettingsSchema.describe("Project capability configurations"),
620
621
  databaseProviders: DatabaseProvidersSettingsSchema.describe("Database provider configurations"),
621
622
  issueManagement: z.object({
623
+ // SYNC: If this default changes, update displayDefaultsBox() in src/utils/first-run-setup.ts
622
624
  provider: z.enum(["github", "linear"]).optional().default("github").describe("Issue tracker provider (github, linear)"),
623
625
  github: z.object({
624
626
  remote: z.string().min(1, "Remote name cannot be empty").describe("Git remote name to use for GitHub operations")
@@ -630,10 +632,15 @@ var init_SettingsManager = __esm({
630
632
  }).optional()
631
633
  }).optional().describe("Issue management configuration"),
632
634
  mergeBehavior: z.object({
635
+ // SYNC: If this default changes, update displayDefaultsBox() in src/utils/first-run-setup.ts
633
636
  mode: z.enum(["local", "github-pr", "github-draft-pr"]).default("local"),
634
- remote: z.string().optional()
637
+ remote: z.string().optional(),
638
+ autoCommitPush: z.boolean().optional().describe(
639
+ "Auto-commit and push after code review in draft PR mode. Defaults to true when mode is github-draft-pr."
640
+ )
635
641
  }).optional().describe("Merge behavior configuration: local (merge locally), github-pr (create PR), or github-draft-pr (create draft PR at start, mark ready on finish)"),
636
642
  ide: z.object({
643
+ // SYNC: If this default changes, update displayDefaultsBox() in src/utils/first-run-setup.ts
637
644
  type: z.enum(["vscode", "cursor", "webstorm", "sublime", "intellij", "windsurf", "antigravity"]).default("vscode").describe(
638
645
  "IDE to launch when starting a loom. Options: vscode (Visual Studio Code), cursor (Cursor AI editor), webstorm (JetBrains WebStorm), sublime (Sublime Text), intellij (JetBrains IntelliJ IDEA), windsurf (Windsurf editor), antigravity (Antigravity IDE)."
639
646
  )
@@ -680,7 +687,7 @@ var init_SettingsManager = __esm({
680
687
  copyGitIgnoredPatterns: z.array(z.string().min(1, "Pattern cannot be empty")).optional().describe(`Glob patterns for gitignored files to copy to looms (e.g., ["*.db", "data/*.sqlite"]). Great for local dbs and large test data files that are too big to commit to git. Note: .env (dotenv-flow) files, iloom's and claude's local settings are automatically copied and do not need to be specified here.`),
681
688
  workflows: WorkflowsSettingsSchemaNoDefaults.describe("Per-workflow-type permission configurations"),
682
689
  agents: z.record(z.string(), AgentSettingsSchema).optional().nullable().describe(
683
- "Per-agent configuration overrides. Available agents: iloom-issue-analyzer (analyzes issues), iloom-issue-planner (creates implementation plans), iloom-issue-analyze-and-plan (combined analysis and planning), iloom-issue-complexity-evaluator (evaluates complexity), iloom-issue-enhancer (enhances issue descriptions), iloom-issue-implementer (implements code changes), iloom-code-reviewer (reviews code changes against requirements)"
690
+ "Per-agent configuration overrides. Available agents: iloom-issue-analyzer (analyzes issues), iloom-issue-planner (creates implementation plans), iloom-issue-analyze-and-plan (combined analysis and planning), iloom-issue-complexity-evaluator (evaluates complexity), iloom-issue-enhancer (enhances issue descriptions), iloom-issue-implementer (implements code changes), iloom-code-reviewer (reviews code changes against requirements), iloom-artifact-reviewer (reviews artifacts before posting)"
684
691
  ),
685
692
  spin: z.object({
686
693
  model: z.enum(["sonnet", "opus", "haiku"]).optional()
@@ -708,7 +715,10 @@ var init_SettingsManager = __esm({
708
715
  }).optional().describe("Issue management configuration"),
709
716
  mergeBehavior: z.object({
710
717
  mode: z.enum(["local", "github-pr", "github-draft-pr"]).optional(),
711
- remote: z.string().optional()
718
+ remote: z.string().optional(),
719
+ autoCommitPush: z.boolean().optional().describe(
720
+ "Auto-commit and push after code review in draft PR mode. Defaults to true when mode is github-draft-pr."
721
+ )
712
722
  }).optional().describe("Merge behavior configuration: local (merge locally), github-pr (create PR), or github-draft-pr (create draft PR at start, mark ready on finish)"),
713
723
  ide: z.object({
714
724
  type: z.enum(["vscode", "cursor", "webstorm", "sublime", "intellij", "windsurf", "antigravity"]).optional().describe(
@@ -1987,6 +1997,22 @@ async function pushBranchToRemote(branchName, worktreePath, options) {
1987
1997
  throw new Error(`Failed to push to remote: ${errorMessage}`);
1988
1998
  }
1989
1999
  }
2000
+ async function fetchOrigin(cwd) {
2001
+ try {
2002
+ await executeGitCommand(["fetch", "origin"], {
2003
+ cwd,
2004
+ timeout: 6e4
2005
+ // 60 second timeout for fetch operations
2006
+ });
2007
+ } catch (error) {
2008
+ const errorMessage = error instanceof Error ? error.message : String(error);
2009
+ throw new Error(
2010
+ `Failed to fetch from origin: ${errorMessage}
2011
+
2012
+ Check your network connection and repository access.`
2013
+ );
2014
+ }
2015
+ }
1990
2016
  async function isFileTrackedByGit(filePath, cwd = process.cwd()) {
1991
2017
  try {
1992
2018
  const result = await executeGitCommand(
@@ -2261,7 +2287,7 @@ var GitWorktreeManager = class {
2261
2287
  } else if (options.baseBranch) {
2262
2288
  args.push(options.baseBranch);
2263
2289
  }
2264
- await executeGitCommand(args, { cwd: this._workingDirectory });
2290
+ await executeGitCommand(args, { cwd: this._workingDirectory, timeout: 3e5 });
2265
2291
  return absolutePath;
2266
2292
  }
2267
2293
  /**
@@ -3096,8 +3122,9 @@ function getLinearApiToken() {
3096
3122
  }
3097
3123
  return token;
3098
3124
  }
3099
- function createLinearClient() {
3100
- return new LinearClient({ apiKey: getLinearApiToken() });
3125
+ function createLinearClient(apiToken) {
3126
+ const token = apiToken ?? getLinearApiToken();
3127
+ return new LinearClient({ apiKey: token });
3101
3128
  }
3102
3129
  function handleLinearError(error, context) {
3103
3130
  logger.debug(`${context}: Handling error`, { error });
@@ -3911,13 +3938,16 @@ function parseJsonStreamOutput(output) {
3911
3938
  }
3912
3939
  }
3913
3940
  async function launchClaude(prompt, options = {}) {
3914
- const { model, permissionMode, addDir, headless = false, appendSystemPrompt, mcpConfig, allowedTools, disallowedTools, agents, sessionId, noSessionPersistence } = options;
3941
+ const { model, permissionMode, addDir, headless = false, appendSystemPrompt, mcpConfig, allowedTools, disallowedTools, agents, sessionId, noSessionPersistence, outputFormat, verbose, jsonMode } = options;
3915
3942
  const log = getLogger();
3916
3943
  const args = [];
3917
3944
  if (headless) {
3918
3945
  args.push("-p");
3919
- args.push("--output-format", "stream-json");
3920
- args.push("--verbose");
3946
+ const effectiveOutputFormat = outputFormat ?? "stream-json";
3947
+ args.push("--output-format", effectiveOutputFormat);
3948
+ if (verbose !== false) {
3949
+ args.push("--verbose");
3950
+ }
3921
3951
  }
3922
3952
  if (model) {
3923
3953
  args.push("--model", model);
@@ -3975,7 +4005,10 @@ async function launchClaude(prompt, options = {}) {
3975
4005
  subprocess.stdout.on("data", (chunk) => {
3976
4006
  const text = chunk.toString();
3977
4007
  outputBuffer += text;
3978
- if (isDebugMode) {
4008
+ if (jsonMode === "stream") {
4009
+ process.stdout.write(text);
4010
+ } else if (jsonMode === "json") {
4011
+ } else if (isDebugMode) {
3979
4012
  log.stdout.write(text);
3980
4013
  } else {
3981
4014
  if (isFirstProgress) {
@@ -3990,7 +4023,7 @@ async function launchClaude(prompt, options = {}) {
3990
4023
  const result = await subprocess;
3991
4024
  if (isStreaming) {
3992
4025
  const rawOutput = outputBuffer.trim();
3993
- if (!isDebugMode) {
4026
+ if (!isDebugMode && !jsonMode) {
3994
4027
  log.stdout.write("\n");
3995
4028
  }
3996
4029
  return isJsonStreamFormat ? parseJsonStreamOutput(rawOutput) : rawOutput;
@@ -4075,7 +4108,10 @@ async function launchClaude(prompt, options = {}) {
4075
4108
  subprocess.stdout.on("data", (chunk) => {
4076
4109
  const text = chunk.toString();
4077
4110
  outputBuffer += text;
4078
- if (isDebugMode) {
4111
+ if (jsonMode === "stream") {
4112
+ process.stdout.write(text);
4113
+ } else if (jsonMode === "json") {
4114
+ } else if (isDebugMode) {
4079
4115
  log.stdout.write(text);
4080
4116
  } else {
4081
4117
  if (isFirstProgress) {
@@ -4090,7 +4126,7 @@ async function launchClaude(prompt, options = {}) {
4090
4126
  const result = await subprocess;
4091
4127
  if (isStreaming) {
4092
4128
  const rawOutput = outputBuffer.trim();
4093
- if (!isDebugMode) {
4129
+ if (!isDebugMode && !jsonMode) {
4094
4130
  log.stdout.write("\n");
4095
4131
  }
4096
4132
  return isJsonStreamFormat ? parseJsonStreamOutput(rawOutput) : rawOutput;
@@ -4725,6 +4761,7 @@ export {
4725
4761
  executeGitCommand,
4726
4762
  extractIssueNumber,
4727
4763
  extractPRNumber,
4764
+ fetchOrigin,
4728
4765
  findAllBranchesForIssue,
4729
4766
  findMainWorktreePath,
4730
4767
  findMainWorktreePathWithSettings,