@iloom/cli 0.1.14

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 (161) hide show
  1. package/LICENSE +33 -0
  2. package/README.md +711 -0
  3. package/dist/ClaudeContextManager-XOSXQ67R.js +13 -0
  4. package/dist/ClaudeContextManager-XOSXQ67R.js.map +1 -0
  5. package/dist/ClaudeService-YSZ6EXWP.js +12 -0
  6. package/dist/ClaudeService-YSZ6EXWP.js.map +1 -0
  7. package/dist/GitHubService-F7Z3XJOS.js +11 -0
  8. package/dist/GitHubService-F7Z3XJOS.js.map +1 -0
  9. package/dist/LoomLauncher-MODG2SEM.js +263 -0
  10. package/dist/LoomLauncher-MODG2SEM.js.map +1 -0
  11. package/dist/NeonProvider-PAGPUH7F.js +12 -0
  12. package/dist/NeonProvider-PAGPUH7F.js.map +1 -0
  13. package/dist/PromptTemplateManager-7FINLRDE.js +9 -0
  14. package/dist/PromptTemplateManager-7FINLRDE.js.map +1 -0
  15. package/dist/SettingsManager-VAZF26S2.js +19 -0
  16. package/dist/SettingsManager-VAZF26S2.js.map +1 -0
  17. package/dist/SettingsMigrationManager-MTQIMI54.js +146 -0
  18. package/dist/SettingsMigrationManager-MTQIMI54.js.map +1 -0
  19. package/dist/add-issue-22JBNOML.js +54 -0
  20. package/dist/add-issue-22JBNOML.js.map +1 -0
  21. package/dist/agents/iloom-issue-analyze-and-plan.md +580 -0
  22. package/dist/agents/iloom-issue-analyzer.md +290 -0
  23. package/dist/agents/iloom-issue-complexity-evaluator.md +224 -0
  24. package/dist/agents/iloom-issue-enhancer.md +266 -0
  25. package/dist/agents/iloom-issue-implementer.md +262 -0
  26. package/dist/agents/iloom-issue-planner.md +358 -0
  27. package/dist/agents/iloom-issue-reviewer.md +63 -0
  28. package/dist/chunk-2ZPFJQ3B.js +63 -0
  29. package/dist/chunk-2ZPFJQ3B.js.map +1 -0
  30. package/dist/chunk-37DYYFVK.js +29 -0
  31. package/dist/chunk-37DYYFVK.js.map +1 -0
  32. package/dist/chunk-BLCTGFZN.js +121 -0
  33. package/dist/chunk-BLCTGFZN.js.map +1 -0
  34. package/dist/chunk-CP2NU2JC.js +545 -0
  35. package/dist/chunk-CP2NU2JC.js.map +1 -0
  36. package/dist/chunk-CWR2SANQ.js +39 -0
  37. package/dist/chunk-CWR2SANQ.js.map +1 -0
  38. package/dist/chunk-F3XBU2R7.js +110 -0
  39. package/dist/chunk-F3XBU2R7.js.map +1 -0
  40. package/dist/chunk-GEHQXLEI.js +130 -0
  41. package/dist/chunk-GEHQXLEI.js.map +1 -0
  42. package/dist/chunk-GYCR2LOU.js +143 -0
  43. package/dist/chunk-GYCR2LOU.js.map +1 -0
  44. package/dist/chunk-GZP4UGGM.js +48 -0
  45. package/dist/chunk-GZP4UGGM.js.map +1 -0
  46. package/dist/chunk-H4E4THUZ.js +55 -0
  47. package/dist/chunk-H4E4THUZ.js.map +1 -0
  48. package/dist/chunk-HPJJSYNS.js +644 -0
  49. package/dist/chunk-HPJJSYNS.js.map +1 -0
  50. package/dist/chunk-JBH2ZYYZ.js +220 -0
  51. package/dist/chunk-JBH2ZYYZ.js.map +1 -0
  52. package/dist/chunk-JNKJ7NJV.js +78 -0
  53. package/dist/chunk-JNKJ7NJV.js.map +1 -0
  54. package/dist/chunk-JQ7VOSTC.js +437 -0
  55. package/dist/chunk-JQ7VOSTC.js.map +1 -0
  56. package/dist/chunk-KQDEK2ZW.js +199 -0
  57. package/dist/chunk-KQDEK2ZW.js.map +1 -0
  58. package/dist/chunk-O2QWO64Z.js +179 -0
  59. package/dist/chunk-O2QWO64Z.js.map +1 -0
  60. package/dist/chunk-OC4H6HJD.js +248 -0
  61. package/dist/chunk-OC4H6HJD.js.map +1 -0
  62. package/dist/chunk-PR7FKQBG.js +120 -0
  63. package/dist/chunk-PR7FKQBG.js.map +1 -0
  64. package/dist/chunk-PXZBAC2M.js +250 -0
  65. package/dist/chunk-PXZBAC2M.js.map +1 -0
  66. package/dist/chunk-QEPVTTHD.js +383 -0
  67. package/dist/chunk-QEPVTTHD.js.map +1 -0
  68. package/dist/chunk-RSRO7564.js +203 -0
  69. package/dist/chunk-RSRO7564.js.map +1 -0
  70. package/dist/chunk-SJUQ2NDR.js +146 -0
  71. package/dist/chunk-SJUQ2NDR.js.map +1 -0
  72. package/dist/chunk-SPYPLHMK.js +177 -0
  73. package/dist/chunk-SPYPLHMK.js.map +1 -0
  74. package/dist/chunk-SSCQCCJ7.js +75 -0
  75. package/dist/chunk-SSCQCCJ7.js.map +1 -0
  76. package/dist/chunk-SSR5AVRJ.js +41 -0
  77. package/dist/chunk-SSR5AVRJ.js.map +1 -0
  78. package/dist/chunk-T7QPXANZ.js +315 -0
  79. package/dist/chunk-T7QPXANZ.js.map +1 -0
  80. package/dist/chunk-U3WU5OWO.js +203 -0
  81. package/dist/chunk-U3WU5OWO.js.map +1 -0
  82. package/dist/chunk-W3DQTW63.js +124 -0
  83. package/dist/chunk-W3DQTW63.js.map +1 -0
  84. package/dist/chunk-WKEWRSDB.js +151 -0
  85. package/dist/chunk-WKEWRSDB.js.map +1 -0
  86. package/dist/chunk-Y7SAGNUT.js +66 -0
  87. package/dist/chunk-Y7SAGNUT.js.map +1 -0
  88. package/dist/chunk-YETJNRQM.js +39 -0
  89. package/dist/chunk-YETJNRQM.js.map +1 -0
  90. package/dist/chunk-YYSKGAZT.js +384 -0
  91. package/dist/chunk-YYSKGAZT.js.map +1 -0
  92. package/dist/chunk-ZZZWQGTS.js +169 -0
  93. package/dist/chunk-ZZZWQGTS.js.map +1 -0
  94. package/dist/claude-7LUVDZZ4.js +17 -0
  95. package/dist/claude-7LUVDZZ4.js.map +1 -0
  96. package/dist/cleanup-3LUWPSM7.js +412 -0
  97. package/dist/cleanup-3LUWPSM7.js.map +1 -0
  98. package/dist/cli-overrides-XFZWY7CM.js +16 -0
  99. package/dist/cli-overrides-XFZWY7CM.js.map +1 -0
  100. package/dist/cli.js +603 -0
  101. package/dist/cli.js.map +1 -0
  102. package/dist/color-ZVALX37U.js +21 -0
  103. package/dist/color-ZVALX37U.js.map +1 -0
  104. package/dist/enhance-XJIQHVPD.js +166 -0
  105. package/dist/enhance-XJIQHVPD.js.map +1 -0
  106. package/dist/env-MDFL4ZXL.js +23 -0
  107. package/dist/env-MDFL4ZXL.js.map +1 -0
  108. package/dist/feedback-23CLXKFT.js +158 -0
  109. package/dist/feedback-23CLXKFT.js.map +1 -0
  110. package/dist/finish-CY4CIH6O.js +1608 -0
  111. package/dist/finish-CY4CIH6O.js.map +1 -0
  112. package/dist/git-LVRZ57GJ.js +43 -0
  113. package/dist/git-LVRZ57GJ.js.map +1 -0
  114. package/dist/ignite-WXEF2ID5.js +359 -0
  115. package/dist/ignite-WXEF2ID5.js.map +1 -0
  116. package/dist/index.d.ts +1341 -0
  117. package/dist/index.js +3058 -0
  118. package/dist/index.js.map +1 -0
  119. package/dist/init-RHACUR4E.js +123 -0
  120. package/dist/init-RHACUR4E.js.map +1 -0
  121. package/dist/installation-detector-VARGFFRZ.js +11 -0
  122. package/dist/installation-detector-VARGFFRZ.js.map +1 -0
  123. package/dist/logger-MKYH4UDV.js +12 -0
  124. package/dist/logger-MKYH4UDV.js.map +1 -0
  125. package/dist/mcp/chunk-6SDFJ42P.js +62 -0
  126. package/dist/mcp/chunk-6SDFJ42P.js.map +1 -0
  127. package/dist/mcp/claude-YHHHLSXH.js +249 -0
  128. package/dist/mcp/claude-YHHHLSXH.js.map +1 -0
  129. package/dist/mcp/color-QS5BFCNN.js +168 -0
  130. package/dist/mcp/color-QS5BFCNN.js.map +1 -0
  131. package/dist/mcp/github-comment-server.js +165 -0
  132. package/dist/mcp/github-comment-server.js.map +1 -0
  133. package/dist/mcp/terminal-SDCMDVD7.js +202 -0
  134. package/dist/mcp/terminal-SDCMDVD7.js.map +1 -0
  135. package/dist/open-X6BTENPV.js +278 -0
  136. package/dist/open-X6BTENPV.js.map +1 -0
  137. package/dist/prompt-ANTQWHUF.js +13 -0
  138. package/dist/prompt-ANTQWHUF.js.map +1 -0
  139. package/dist/prompts/issue-prompt.txt +230 -0
  140. package/dist/prompts/pr-prompt.txt +35 -0
  141. package/dist/prompts/regular-prompt.txt +14 -0
  142. package/dist/run-2JCPQAX3.js +278 -0
  143. package/dist/run-2JCPQAX3.js.map +1 -0
  144. package/dist/schema/settings.schema.json +221 -0
  145. package/dist/start-LWVRBJ6S.js +982 -0
  146. package/dist/start-LWVRBJ6S.js.map +1 -0
  147. package/dist/terminal-3D6TUAKJ.js +16 -0
  148. package/dist/terminal-3D6TUAKJ.js.map +1 -0
  149. package/dist/test-git-XPF4SZXJ.js +52 -0
  150. package/dist/test-git-XPF4SZXJ.js.map +1 -0
  151. package/dist/test-prefix-XGFXFAYN.js +68 -0
  152. package/dist/test-prefix-XGFXFAYN.js.map +1 -0
  153. package/dist/test-tabs-JRKY3QMM.js +69 -0
  154. package/dist/test-tabs-JRKY3QMM.js.map +1 -0
  155. package/dist/test-webserver-M2I3EV4J.js +62 -0
  156. package/dist/test-webserver-M2I3EV4J.js.map +1 -0
  157. package/dist/update-3ZT2XX2G.js +79 -0
  158. package/dist/update-3ZT2XX2G.js.map +1 -0
  159. package/dist/update-notifier-QSSEB5KC.js +11 -0
  160. package/dist/update-notifier-QSSEB5KC.js.map +1 -0
  161. package/package.json +113 -0
@@ -0,0 +1,982 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ extractSettingsOverrides
4
+ } from "./chunk-GYCR2LOU.js";
5
+ import {
6
+ IssueEnhancementService
7
+ } from "./chunk-PR7FKQBG.js";
8
+ import {
9
+ AgentManager
10
+ } from "./chunk-OC4H6HJD.js";
11
+ import "./chunk-YETJNRQM.js";
12
+ import {
13
+ CLIIsolationManager,
14
+ DatabaseManager,
15
+ EnvironmentManager
16
+ } from "./chunk-HPJJSYNS.js";
17
+ import "./chunk-37DYYFVK.js";
18
+ import {
19
+ installDependencies
20
+ } from "./chunk-BLCTGFZN.js";
21
+ import {
22
+ NeonProvider
23
+ } from "./chunk-YYSKGAZT.js";
24
+ import {
25
+ ProjectCapabilityDetector
26
+ } from "./chunk-CWR2SANQ.js";
27
+ import "./chunk-2ZPFJQ3B.js";
28
+ import {
29
+ calculateForegroundColor,
30
+ generateColorFromBranchName,
31
+ hexToRgb,
32
+ lightenColor,
33
+ rgbToHex
34
+ } from "./chunk-ZZZWQGTS.js";
35
+ import {
36
+ GitHubService
37
+ } from "./chunk-T7QPXANZ.js";
38
+ import "./chunk-KQDEK2ZW.js";
39
+ import {
40
+ loadEnvIntoProcess
41
+ } from "./chunk-SJUQ2NDR.js";
42
+ import {
43
+ ClaudeContextManager
44
+ } from "./chunk-Y7SAGNUT.js";
45
+ import "./chunk-WKEWRSDB.js";
46
+ import "./chunk-PXZBAC2M.js";
47
+ import "./chunk-F3XBU2R7.js";
48
+ import {
49
+ GitWorktreeManager
50
+ } from "./chunk-QEPVTTHD.js";
51
+ import {
52
+ SettingsManager
53
+ } from "./chunk-JBH2ZYYZ.js";
54
+ import {
55
+ branchExists,
56
+ ensureRepositoryHasCommits,
57
+ executeGitCommand,
58
+ findMainWorktreePathWithSettings
59
+ } from "./chunk-JQ7VOSTC.js";
60
+ import "./chunk-JNKJ7NJV.js";
61
+ import {
62
+ logger
63
+ } from "./chunk-GEHQXLEI.js";
64
+
65
+ // src/lib/LoomManager.ts
66
+ import path2 from "path";
67
+ import fs2 from "fs-extra";
68
+
69
+ // src/lib/VSCodeIntegration.ts
70
+ import fs from "fs-extra";
71
+ import path from "path";
72
+ import { parse, modify, applyEdits } from "jsonc-parser";
73
+ var VSCodeIntegration = class {
74
+ /**
75
+ * Set VSCode title bar color for a workspace
76
+ *
77
+ * @param workspacePath - Path to workspace directory
78
+ * @param hexColor - Hex color string (e.g., "#dcebf8")
79
+ */
80
+ async setTitleBarColor(workspacePath, hexColor) {
81
+ const vscodeDir = path.join(workspacePath, ".vscode");
82
+ const settingsPath = path.join(vscodeDir, "settings.json");
83
+ try {
84
+ await fs.ensureDir(vscodeDir);
85
+ const settings = await this.readSettings(settingsPath);
86
+ const updatedSettings = this.mergeColorSettings(settings, hexColor);
87
+ await this.writeSettings(settingsPath, updatedSettings);
88
+ logger.debug(`Set VSCode title bar color to ${hexColor} for ${workspacePath}`);
89
+ } catch (error) {
90
+ throw new Error(
91
+ `Failed to set VSCode title bar color: ${error instanceof Error ? error.message : "Unknown error"}`
92
+ );
93
+ }
94
+ }
95
+ /**
96
+ * Read VSCode settings from file
97
+ * Supports JSONC (JSON with Comments)
98
+ *
99
+ * @param settingsPath - Path to settings.json file
100
+ * @returns Parsed settings object
101
+ */
102
+ async readSettings(settingsPath) {
103
+ try {
104
+ if (!await fs.pathExists(settingsPath)) {
105
+ return {};
106
+ }
107
+ const content = await fs.readFile(settingsPath, "utf8");
108
+ const errors = [];
109
+ const settings = parse(content, errors, { allowTrailingComma: true });
110
+ if (errors.length > 0) {
111
+ const firstError = errors[0];
112
+ throw new Error(`Invalid JSON: ${firstError ? firstError.error : "Unknown parse error"}`);
113
+ }
114
+ return settings ?? {};
115
+ } catch (error) {
116
+ throw new Error(
117
+ `Failed to parse settings.json: ${error instanceof Error ? error.message : "Unknown error"}`
118
+ );
119
+ }
120
+ }
121
+ /**
122
+ * Write VSCode settings to file atomically
123
+ * Preserves comments if present (using JSONC parser)
124
+ *
125
+ * @param settingsPath - Path to settings.json file
126
+ * @param settings - Settings object to write
127
+ */
128
+ async writeSettings(settingsPath, settings) {
129
+ try {
130
+ let content;
131
+ if (await fs.pathExists(settingsPath)) {
132
+ const existingContent = await fs.readFile(settingsPath, "utf8");
133
+ if (existingContent.includes("//") || existingContent.includes("/*")) {
134
+ content = await this.modifyWithCommentsPreserved(existingContent, settings);
135
+ } else {
136
+ content = JSON.stringify(settings, null, 2) + "\n";
137
+ }
138
+ } else {
139
+ content = JSON.stringify(settings, null, 2) + "\n";
140
+ }
141
+ const tempPath = `${settingsPath}.tmp`;
142
+ await fs.writeFile(tempPath, content, "utf8");
143
+ await fs.rename(tempPath, settingsPath);
144
+ } catch (error) {
145
+ throw new Error(
146
+ `Failed to write settings.json: ${error instanceof Error ? error.message : "Unknown error"}`
147
+ );
148
+ }
149
+ }
150
+ /**
151
+ * Modify JSONC content while preserving comments
152
+ *
153
+ * @param existingContent - Original JSONC content
154
+ * @param newSettings - New settings to apply
155
+ * @returns Modified JSONC content with comments preserved
156
+ */
157
+ async modifyWithCommentsPreserved(existingContent, newSettings) {
158
+ let modifiedContent = existingContent;
159
+ for (const [key, value] of Object.entries(newSettings)) {
160
+ const edits = modify(modifiedContent, [key], value, {});
161
+ modifiedContent = applyEdits(modifiedContent, edits);
162
+ }
163
+ return modifiedContent;
164
+ }
165
+ /**
166
+ * Merge color settings into existing settings object
167
+ *
168
+ * @param existing - Existing settings object
169
+ * @param hexColor - Hex color to apply (subtle palette color)
170
+ * @returns Updated settings object with color merged
171
+ */
172
+ mergeColorSettings(existing, hexColor) {
173
+ const updated = { ...existing };
174
+ updated["workbench.colorCustomizations"] ??= {};
175
+ const colors = updated["workbench.colorCustomizations"];
176
+ const baseRgb = hexToRgb(hexColor);
177
+ const foreground = calculateForegroundColor(baseRgb);
178
+ const foregroundTransparent = foreground.replace("#", "#") + "99";
179
+ const lighterRgb = lightenColor(baseRgb, 0.05);
180
+ const lighterHex = rgbToHex(lighterRgb.r, lighterRgb.g, lighterRgb.b);
181
+ colors["titleBar.activeBackground"] = hexColor;
182
+ colors["titleBar.inactiveBackground"] = hexColor + "99";
183
+ colors["titleBar.activeForeground"] = foreground;
184
+ colors["titleBar.inactiveForeground"] = foregroundTransparent;
185
+ colors["statusBar.background"] = hexColor;
186
+ colors["statusBar.foreground"] = foreground;
187
+ colors["statusBarItem.hoverBackground"] = lighterHex;
188
+ colors["statusBarItem.remoteBackground"] = hexColor;
189
+ colors["statusBarItem.remoteForeground"] = foreground;
190
+ colors["sash.hoverBorder"] = hexColor;
191
+ colors["commandCenter.border"] = foregroundTransparent;
192
+ return updated;
193
+ }
194
+ };
195
+
196
+ // src/lib/LoomManager.ts
197
+ var LoomManager = class {
198
+ constructor(gitWorktree, github, environment, _claude, capabilityDetector, cliIsolation, settings, database) {
199
+ this.gitWorktree = gitWorktree;
200
+ this.github = github;
201
+ this.environment = environment;
202
+ this.capabilityDetector = capabilityDetector;
203
+ this.cliIsolation = cliIsolation;
204
+ this.settings = settings;
205
+ this.database = database;
206
+ }
207
+ /**
208
+ * Create a new loom (isolated workspace)
209
+ * Orchestrates worktree creation, environment setup, and Claude context generation
210
+ * NEW: Checks for existing worktrees and reuses them if found
211
+ */
212
+ async createIloom(input) {
213
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
214
+ logger.info("Fetching GitHub data...");
215
+ const githubData = await this.fetchGitHubData(input);
216
+ if (input.type === "issue" || input.type === "pr") {
217
+ logger.info("Checking for existing worktree...");
218
+ const existing = await this.findExistingIloom(input, githubData);
219
+ if (existing) {
220
+ logger.success(`Found existing worktree, reusing: ${existing.path}`);
221
+ return await this.reuseIloom(existing, input, githubData);
222
+ }
223
+ logger.info("No existing worktree found, creating new one...");
224
+ }
225
+ logger.info("Preparing branch name...");
226
+ const branchName = await this.prepareBranchName(input, githubData);
227
+ logger.info("Creating git worktree...");
228
+ const worktreePath = await this.createWorktreeOnly(input, branchName);
229
+ this.loadMainEnvFile();
230
+ const { capabilities, binEntries } = await this.capabilityDetector.detectCapabilities(worktreePath);
231
+ await this.copyEnvironmentFiles(worktreePath);
232
+ await this.copyIloomSettings(worktreePath);
233
+ const settingsData = await this.settings.loadSettings();
234
+ const basePort = ((_b = (_a = settingsData.capabilities) == null ? void 0 : _a.web) == null ? void 0 : _b.basePort) ?? 3e3;
235
+ let port = basePort;
236
+ if (capabilities.includes("web")) {
237
+ port = await this.setupPortForWeb(worktreePath, input, basePort);
238
+ }
239
+ try {
240
+ await installDependencies(worktreePath, true);
241
+ } catch (error) {
242
+ logger.warn(`Failed to install dependencies: ${error instanceof Error ? error.message : "Unknown error"}`, error);
243
+ }
244
+ let databaseBranch = void 0;
245
+ if (this.database && !((_c = input.options) == null ? void 0 : _c.skipDatabase)) {
246
+ try {
247
+ const connectionString = await this.database.createBranchIfConfigured(
248
+ branchName,
249
+ path2.join(worktreePath, ".env")
250
+ );
251
+ if (connectionString) {
252
+ await this.environment.setEnvVar(
253
+ path2.join(worktreePath, ".env"),
254
+ this.database.getConfiguredVariableName(),
255
+ connectionString
256
+ );
257
+ logger.success("Database branch configured");
258
+ databaseBranch = branchName;
259
+ }
260
+ } catch (error) {
261
+ logger.error(
262
+ `Failed to setup database branch: ${error instanceof Error ? error.message : "Unknown error"}`
263
+ );
264
+ throw error;
265
+ }
266
+ }
267
+ let cliSymlinks = void 0;
268
+ if (capabilities.includes("cli")) {
269
+ try {
270
+ cliSymlinks = await this.cliIsolation.setupCLIIsolation(
271
+ worktreePath,
272
+ input.identifier,
273
+ binEntries
274
+ );
275
+ } catch (error) {
276
+ logger.warn(
277
+ `Failed to setup CLI isolation: ${error instanceof Error ? error.message : "Unknown error"}`,
278
+ error
279
+ );
280
+ }
281
+ }
282
+ if (!((_d = input.options) == null ? void 0 : _d.skipColorSync)) {
283
+ try {
284
+ await this.applyColorSynchronization(worktreePath, branchName);
285
+ } catch (error) {
286
+ logger.warn(
287
+ `Failed to apply color synchronization: ${error instanceof Error ? error.message : "Unknown error"}`,
288
+ error
289
+ );
290
+ }
291
+ }
292
+ if (input.type === "issue") {
293
+ try {
294
+ logger.info("Moving issue to In Progress...");
295
+ await this.github.moveIssueToInProgress(input.identifier);
296
+ } catch (error) {
297
+ logger.warn(
298
+ `Failed to move issue to In Progress: ${error instanceof Error ? error.message : "Unknown error"}`,
299
+ error
300
+ );
301
+ }
302
+ }
303
+ const enableClaude = ((_e = input.options) == null ? void 0 : _e.enableClaude) !== false;
304
+ const enableCode = ((_f = input.options) == null ? void 0 : _f.enableCode) !== false;
305
+ const enableDevServer = ((_g = input.options) == null ? void 0 : _g.enableDevServer) !== false;
306
+ const enableTerminal = ((_h = input.options) == null ? void 0 : _h.enableTerminal) ?? false;
307
+ const oneShot = ((_i = input.options) == null ? void 0 : _i.oneShot) ?? "default";
308
+ const setArguments = (_j = input.options) == null ? void 0 : _j.setArguments;
309
+ const executablePath = (_k = input.options) == null ? void 0 : _k.executablePath;
310
+ if (enableClaude || enableCode || enableDevServer || enableTerminal) {
311
+ const { LoomLauncher } = await import("./LoomLauncher-MODG2SEM.js");
312
+ const { ClaudeContextManager: ClaudeContextManager2 } = await import("./ClaudeContextManager-XOSXQ67R.js");
313
+ const claudeContext = new ClaudeContextManager2(void 0, void 0, this.settings);
314
+ const launcher = new LoomLauncher(claudeContext);
315
+ await launcher.launchLoom({
316
+ enableClaude,
317
+ enableCode,
318
+ enableDevServer,
319
+ enableTerminal,
320
+ worktreePath,
321
+ branchName,
322
+ port,
323
+ capabilities,
324
+ workflowType: input.type === "branch" ? "regular" : input.type,
325
+ identifier: input.identifier,
326
+ ...(githubData == null ? void 0 : githubData.title) && { title: githubData.title },
327
+ oneShot,
328
+ ...setArguments && { setArguments },
329
+ ...executablePath && { executablePath }
330
+ });
331
+ }
332
+ const loom = {
333
+ id: this.generateLoomId(input),
334
+ path: worktreePath,
335
+ branch: branchName,
336
+ type: input.type,
337
+ identifier: input.identifier,
338
+ port,
339
+ createdAt: /* @__PURE__ */ new Date(),
340
+ lastAccessed: /* @__PURE__ */ new Date(),
341
+ ...databaseBranch !== void 0 && { databaseBranch },
342
+ ...capabilities.length > 0 && { capabilities },
343
+ ...Object.keys(binEntries).length > 0 && { binEntries },
344
+ ...cliSymlinks && cliSymlinks.length > 0 && { cliSymlinks },
345
+ ...githubData !== null && {
346
+ githubData: {
347
+ title: githubData.title,
348
+ body: githubData.body,
349
+ url: githubData.url,
350
+ state: githubData.state
351
+ }
352
+ }
353
+ };
354
+ logger.success(`Created loom: ${loom.id} at ${loom.path}`);
355
+ return loom;
356
+ }
357
+ /**
358
+ * Finish a loom (merge work and cleanup)
359
+ * Not yet implemented - see Issue #7
360
+ */
361
+ async finishIloom(_identifier) {
362
+ throw new Error("Not implemented - see Issue #7");
363
+ }
364
+ /**
365
+ * List all active looms
366
+ */
367
+ async listLooms() {
368
+ const worktrees = await this.gitWorktree.listWorktrees();
369
+ return await this.mapWorktreesToLooms(worktrees);
370
+ }
371
+ /**
372
+ * Find a specific loom by identifier
373
+ */
374
+ async findIloom(identifier) {
375
+ const looms = await this.listLooms();
376
+ return looms.find(
377
+ (h) => h.id === identifier || h.identifier.toString() === identifier || h.branch === identifier
378
+ ) ?? null;
379
+ }
380
+ /**
381
+ * Fetch GitHub data based on input type
382
+ */
383
+ async fetchGitHubData(input) {
384
+ if (input.type === "issue") {
385
+ return await this.github.fetchIssue(input.identifier);
386
+ } else if (input.type === "pr") {
387
+ return await this.github.fetchPR(input.identifier);
388
+ }
389
+ return null;
390
+ }
391
+ /**
392
+ * Prepare branch name based on input type and GitHub data
393
+ */
394
+ async prepareBranchName(input, githubData) {
395
+ if (input.type === "branch") {
396
+ return input.identifier;
397
+ }
398
+ if (input.type === "pr" && githubData && "branch" in githubData) {
399
+ return githubData.branch;
400
+ }
401
+ if (input.type === "issue" && githubData) {
402
+ const branchName = await this.github.generateBranchName({
403
+ issueNumber: input.identifier,
404
+ title: githubData.title
405
+ });
406
+ return branchName;
407
+ }
408
+ if (input.type === "pr") {
409
+ return `pr-${input.identifier}`;
410
+ }
411
+ throw new Error(`Unable to determine branch name for input type: ${input.type}`);
412
+ }
413
+ /**
414
+ * Create worktree for the loom (without dependency installation)
415
+ */
416
+ async createWorktreeOnly(input, branchName) {
417
+ logger.info("Ensuring repository has initial commit...");
418
+ await ensureRepositoryHasCommits(this.gitWorktree.workingDirectory);
419
+ const settingsData = await this.settings.loadSettings();
420
+ const worktreePrefix = settingsData.worktreePrefix;
421
+ const pathOptions = input.type === "pr" ? { isPR: true, prNumber: input.identifier } : {};
422
+ if (worktreePrefix !== void 0) {
423
+ pathOptions.prefix = worktreePrefix;
424
+ }
425
+ const worktreePath = this.gitWorktree.generateWorktreePath(
426
+ branchName,
427
+ void 0,
428
+ pathOptions
429
+ );
430
+ if (input.type === "pr") {
431
+ logger.info("Fetching all remote branches...");
432
+ try {
433
+ await executeGitCommand(["fetch", "origin"], { cwd: this.gitWorktree.workingDirectory });
434
+ logger.success("Successfully fetched from remote");
435
+ } catch (error) {
436
+ throw new Error(
437
+ `Failed to fetch from remote: ${error instanceof Error ? error.message : "Unknown error"}. Make sure you have access to the repository.`
438
+ );
439
+ }
440
+ }
441
+ const branchExistedLocally = await branchExists(branchName);
442
+ if (input.type !== "pr" && branchExistedLocally) {
443
+ throw new Error(
444
+ `Cannot create worktree: branch '${branchName}' already exists. Use 'git branch -D ${branchName}' to delete it first if needed.`
445
+ );
446
+ }
447
+ await this.gitWorktree.createWorktree({
448
+ path: worktreePath,
449
+ branch: branchName,
450
+ createBranch: input.type !== "pr",
451
+ // PRs use existing branches
452
+ ...input.baseBranch && { baseBranch: input.baseBranch }
453
+ });
454
+ if (input.type === "pr" && !branchExistedLocally) {
455
+ logger.info("Resetting new PR branch to match remote exactly...");
456
+ try {
457
+ await executeGitCommand(["reset", "--hard", `origin/${branchName}`], { cwd: worktreePath });
458
+ await executeGitCommand(["branch", "--set-upstream-to", `origin/${branchName}`], { cwd: worktreePath });
459
+ logger.success("Successfully reset to match remote");
460
+ } catch (error) {
461
+ logger.warn(`Failed to reset to match remote: ${error instanceof Error ? error.message : "Unknown error"}`);
462
+ }
463
+ }
464
+ return worktreePath;
465
+ }
466
+ /**
467
+ * Copy user application environment files (.env) from main repo to worktree
468
+ * Always called regardless of project capabilities
469
+ */
470
+ async copyEnvironmentFiles(worktreePath) {
471
+ const envFilePath = path2.join(worktreePath, ".env");
472
+ try {
473
+ const mainEnvPath = path2.join(process.cwd(), ".env");
474
+ if (await fs2.pathExists(envFilePath)) {
475
+ logger.warn(".env file already exists in worktree, skipping copy");
476
+ } else {
477
+ await this.environment.copyIfExists(mainEnvPath, envFilePath);
478
+ }
479
+ } catch (error) {
480
+ logger.warn(`Warning: Failed to copy main .env file: ${error instanceof Error ? error.message : "Unknown error"}`);
481
+ }
482
+ }
483
+ /**
484
+ * Copy iloom configuration (settings.local.json) from main repo to worktree
485
+ * Always called regardless of project capabilities
486
+ */
487
+ async copyIloomSettings(worktreePath) {
488
+ const mainSettingsLocalPath = path2.join(process.cwd(), ".iloom", "settings.local.json");
489
+ try {
490
+ const worktreeIloomDir = path2.join(worktreePath, ".iloom");
491
+ await fs2.ensureDir(worktreeIloomDir);
492
+ const worktreeSettingsLocalPath = path2.join(worktreeIloomDir, "settings.local.json");
493
+ if (await fs2.pathExists(worktreeSettingsLocalPath)) {
494
+ logger.warn("settings.local.json already exists in worktree, skipping copy");
495
+ } else {
496
+ await this.environment.copyIfExists(mainSettingsLocalPath, worktreeSettingsLocalPath);
497
+ }
498
+ } catch (error) {
499
+ logger.warn(`Warning: Failed to copy settings.local.json: ${error instanceof Error ? error.message : "Unknown error"}`);
500
+ }
501
+ }
502
+ /**
503
+ * Setup PORT environment variable for web projects
504
+ * Only called when project has web capabilities
505
+ */
506
+ async setupPortForWeb(worktreePath, input, basePort) {
507
+ const envFilePath = path2.join(worktreePath, ".env");
508
+ const options = { basePort };
509
+ if (input.type === "issue") {
510
+ options.issueNumber = input.identifier;
511
+ } else if (input.type === "pr") {
512
+ options.prNumber = input.identifier;
513
+ } else if (input.type === "branch") {
514
+ options.branchName = input.identifier;
515
+ }
516
+ const port = this.environment.calculatePort(options);
517
+ await this.environment.setEnvVar(envFilePath, "PORT", String(port));
518
+ return port;
519
+ }
520
+ /**
521
+ * Load environment variables from main .env file into process.env
522
+ * Uses dotenv-flow to handle various .env file patterns
523
+ */
524
+ loadMainEnvFile() {
525
+ const result = loadEnvIntoProcess({ path: process.cwd() });
526
+ if (result.error) {
527
+ logger.warn(`Warning: Could not load .env files: ${result.error.message}`);
528
+ } else {
529
+ logger.info("Loaded environment variables using dotenv-flow");
530
+ if (result.parsed && Object.keys(result.parsed).length > 0) {
531
+ logger.debug(`Loaded ${Object.keys(result.parsed).length} environment variables`);
532
+ }
533
+ }
534
+ }
535
+ /**
536
+ * Generate a unique loom ID
537
+ */
538
+ generateLoomId(input) {
539
+ const prefix = input.type;
540
+ return `${prefix}-${input.identifier}`;
541
+ }
542
+ /**
543
+ * Calculate port for the loom
544
+ * Base port: configurable via settings.capabilities.web.basePort (default 3000) + issue/PR number (or deterministic hash for branches)
545
+ */
546
+ async calculatePort(input) {
547
+ var _a, _b;
548
+ const settingsData = await this.settings.loadSettings();
549
+ const basePort = ((_b = (_a = settingsData.capabilities) == null ? void 0 : _a.web) == null ? void 0 : _b.basePort) ?? 3e3;
550
+ if (input.type === "issue" && typeof input.identifier === "number") {
551
+ return this.environment.calculatePort({ basePort, issueNumber: input.identifier });
552
+ }
553
+ if (input.type === "pr" && typeof input.identifier === "number") {
554
+ return this.environment.calculatePort({ basePort, prNumber: input.identifier });
555
+ }
556
+ if (input.type === "branch" && typeof input.identifier === "string") {
557
+ return this.environment.calculatePort({ basePort, branchName: input.identifier });
558
+ }
559
+ throw new Error(`Unknown input type: ${input.type}`);
560
+ }
561
+ /**
562
+ * Apply color synchronization to both VSCode and terminal
563
+ * Colors are cosmetic - errors are logged but don't block workflow
564
+ */
565
+ async applyColorSynchronization(worktreePath, branchName) {
566
+ const colorData = generateColorFromBranchName(branchName);
567
+ const vscode = new VSCodeIntegration();
568
+ await vscode.setTitleBarColor(worktreePath, colorData.hex);
569
+ logger.info(`Applied VSCode title bar color: ${colorData.hex} for branch: ${branchName}`);
570
+ }
571
+ /**
572
+ * Map worktrees to loom objects
573
+ * This is a simplified conversion - in production we'd store loom metadata
574
+ */
575
+ async mapWorktreesToLooms(worktrees) {
576
+ return await Promise.all(worktrees.map(async (wt) => {
577
+ let type = "branch";
578
+ let identifier = wt.branch;
579
+ if (wt.branch.startsWith("issue-")) {
580
+ type = "issue";
581
+ identifier = parseInt(wt.branch.replace("issue-", ""), 10);
582
+ } else if (wt.branch.startsWith("pr-")) {
583
+ type = "pr";
584
+ identifier = parseInt(wt.branch.replace("pr-", ""), 10);
585
+ }
586
+ return {
587
+ id: `${type}-${identifier}`,
588
+ path: wt.path,
589
+ branch: wt.branch,
590
+ type,
591
+ identifier,
592
+ port: await this.calculatePort({ type, identifier, originalInput: "" }),
593
+ createdAt: /* @__PURE__ */ new Date(),
594
+ lastAccessed: /* @__PURE__ */ new Date()
595
+ };
596
+ }));
597
+ }
598
+ /**
599
+ * NEW: Find existing loom for the given input
600
+ * Checks for worktrees matching the issue/PR identifier
601
+ */
602
+ async findExistingIloom(input, githubData) {
603
+ if (input.type === "issue") {
604
+ return await this.gitWorktree.findWorktreeForIssue(input.identifier);
605
+ } else if (input.type === "pr" && githubData && "branch" in githubData) {
606
+ return await this.gitWorktree.findWorktreeForPR(
607
+ input.identifier,
608
+ githubData.branch
609
+ );
610
+ }
611
+ return null;
612
+ }
613
+ /**
614
+ * NEW: Reuse an existing loom
615
+ * Includes environment setup and database branching for existing worktrees
616
+ * Ports: handle_existing_worktree() from bash script lines 168-215
617
+ */
618
+ async reuseIloom(worktree, input, githubData) {
619
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
620
+ const worktreePath = worktree.path;
621
+ const branchName = worktree.branch;
622
+ this.loadMainEnvFile();
623
+ const { capabilities, binEntries } = await this.capabilityDetector.detectCapabilities(worktreePath);
624
+ await this.copyEnvironmentFiles(worktreePath);
625
+ await this.copyIloomSettings(worktreePath);
626
+ const settingsData = await this.settings.loadSettings();
627
+ const basePort = ((_b = (_a = settingsData.capabilities) == null ? void 0 : _a.web) == null ? void 0 : _b.basePort) ?? 3e3;
628
+ let port = basePort;
629
+ if (capabilities.includes("web")) {
630
+ port = await this.setupPortForWeb(worktreePath, input, basePort);
631
+ }
632
+ logger.info("Database branch assumed to be already configured for existing worktree");
633
+ const databaseBranch = void 0;
634
+ if (input.type === "issue") {
635
+ try {
636
+ logger.info("Moving issue to In Progress...");
637
+ await this.github.moveIssueToInProgress(input.identifier);
638
+ } catch (error) {
639
+ logger.warn(
640
+ `Failed to move issue to In Progress: ${error instanceof Error ? error.message : "Unknown error"}`,
641
+ error
642
+ );
643
+ }
644
+ }
645
+ const enableClaude = ((_c = input.options) == null ? void 0 : _c.enableClaude) !== false;
646
+ const enableCode = ((_d = input.options) == null ? void 0 : _d.enableCode) !== false;
647
+ const enableDevServer = ((_e = input.options) == null ? void 0 : _e.enableDevServer) !== false;
648
+ const enableTerminal = ((_f = input.options) == null ? void 0 : _f.enableTerminal) ?? false;
649
+ const oneShot = ((_g = input.options) == null ? void 0 : _g.oneShot) ?? "default";
650
+ const setArguments = (_h = input.options) == null ? void 0 : _h.setArguments;
651
+ const executablePath = (_i = input.options) == null ? void 0 : _i.executablePath;
652
+ if (enableClaude || enableCode || enableDevServer || enableTerminal) {
653
+ logger.info("Launching workspace components...");
654
+ const { LoomLauncher } = await import("./LoomLauncher-MODG2SEM.js");
655
+ const { ClaudeContextManager: ClaudeContextManager2 } = await import("./ClaudeContextManager-XOSXQ67R.js");
656
+ const claudeContext = new ClaudeContextManager2(void 0, void 0, this.settings);
657
+ const launcher = new LoomLauncher(claudeContext);
658
+ await launcher.launchLoom({
659
+ enableClaude,
660
+ enableCode,
661
+ enableDevServer,
662
+ enableTerminal,
663
+ worktreePath,
664
+ branchName,
665
+ port,
666
+ capabilities,
667
+ workflowType: input.type === "branch" ? "regular" : input.type,
668
+ identifier: input.identifier,
669
+ ...(githubData == null ? void 0 : githubData.title) && { title: githubData.title },
670
+ oneShot,
671
+ ...setArguments && { setArguments },
672
+ ...executablePath && { executablePath }
673
+ });
674
+ }
675
+ const loom = {
676
+ id: this.generateLoomId(input),
677
+ path: worktreePath,
678
+ branch: branchName,
679
+ type: input.type,
680
+ identifier: input.identifier,
681
+ port,
682
+ createdAt: /* @__PURE__ */ new Date(),
683
+ // We don't have actual creation date, use now
684
+ lastAccessed: /* @__PURE__ */ new Date(),
685
+ ...databaseBranch !== void 0 && { databaseBranch },
686
+ ...capabilities.length > 0 && { capabilities },
687
+ ...Object.keys(binEntries).length > 0 && { binEntries },
688
+ ...githubData !== null && {
689
+ githubData: {
690
+ title: githubData.title,
691
+ body: githubData.body,
692
+ url: githubData.url,
693
+ state: githubData.state
694
+ }
695
+ }
696
+ };
697
+ logger.success(`Reused existing loom: ${loom.id} at ${loom.path}`);
698
+ return loom;
699
+ }
700
+ };
701
+
702
+ // src/commands/start.ts
703
+ var StartCommand = class {
704
+ constructor(gitHubService, loomManager, agentManager, settingsManager) {
705
+ this.loomManager = null;
706
+ this.gitHubService = gitHubService ?? new GitHubService();
707
+ this.agentManager = agentManager ?? new AgentManager();
708
+ this.settingsManager = settingsManager ?? new SettingsManager();
709
+ this.enhancementService = new IssueEnhancementService(
710
+ this.gitHubService,
711
+ this.agentManager,
712
+ this.settingsManager
713
+ );
714
+ this.providedLoomManager = loomManager;
715
+ const envResult = loadEnvIntoProcess();
716
+ if (envResult.error) {
717
+ logger.debug(`Environment loading warning: ${envResult.error.message}`);
718
+ }
719
+ if (envResult.parsed) {
720
+ logger.debug(`Loaded ${Object.keys(envResult.parsed).length} environment variables`);
721
+ }
722
+ }
723
+ /**
724
+ * Initialize LoomManager with the main worktree path
725
+ * Uses lazy initialization to ensure we have the correct path
726
+ */
727
+ async initializeLoomManager() {
728
+ var _a, _b, _c;
729
+ if (this.loomManager) {
730
+ return this.loomManager;
731
+ }
732
+ if (this.providedLoomManager) {
733
+ this.loomManager = this.providedLoomManager;
734
+ return this.loomManager;
735
+ }
736
+ const mainWorktreePath = await findMainWorktreePathWithSettings();
737
+ const environmentManager = new EnvironmentManager();
738
+ logger.debug("Environment variables for Neon:", {
739
+ NEON_PROJECT_ID: process.env.NEON_PROJECT_ID,
740
+ NEON_PARENT_BRANCH: process.env.NEON_PARENT_BRANCH,
741
+ hasNeonProjectId: !!process.env.NEON_PROJECT_ID,
742
+ hasNeonParentBranch: !!process.env.NEON_PARENT_BRANCH,
743
+ neonProjectIdLength: ((_a = process.env.NEON_PROJECT_ID) == null ? void 0 : _a.length) ?? 0
744
+ });
745
+ const neonProvider = new NeonProvider({
746
+ projectId: process.env.NEON_PROJECT_ID ?? "",
747
+ parentBranch: process.env.NEON_PARENT_BRANCH ?? ""
748
+ });
749
+ const settings = await this.settingsManager.loadSettings();
750
+ const databaseUrlEnvVarName = ((_c = (_b = settings.capabilities) == null ? void 0 : _b.database) == null ? void 0 : _c.databaseUrlEnvVarName) ?? "DATABASE_URL";
751
+ const databaseManager = new DatabaseManager(neonProvider, environmentManager, databaseUrlEnvVarName);
752
+ this.loomManager = new LoomManager(
753
+ new GitWorktreeManager(mainWorktreePath),
754
+ this.gitHubService,
755
+ environmentManager,
756
+ // Reuse same instance
757
+ new ClaudeContextManager(),
758
+ new ProjectCapabilityDetector(),
759
+ new CLIIsolationManager(),
760
+ this.settingsManager,
761
+ // Use same instance with CLI overrides
762
+ databaseManager
763
+ // Add database manager
764
+ );
765
+ return this.loomManager;
766
+ }
767
+ /**
768
+ * Main entry point for the start command
769
+ */
770
+ async execute(input) {
771
+ var _a, _b, _c;
772
+ try {
773
+ const loomManager = await this.initializeLoomManager();
774
+ const parsed = await this.parseInput(input.identifier);
775
+ await this.validateInput(parsed);
776
+ if (parsed.type === "description") {
777
+ const issueNumber = await this.enhanceAndCreateIssue(parsed.originalInput);
778
+ parsed.type = "issue";
779
+ parsed.number = issueNumber;
780
+ }
781
+ if (input.options.oneShot === "bypassPermissions") {
782
+ const { promptConfirmation } = await import("./prompt-ANTQWHUF.js");
783
+ const confirmed = await promptConfirmation(
784
+ "\u26A0\uFE0F WARNING: bypassPermissions mode will allow Claude to execute all tool calls without confirmation. This can be dangerous. Do you want to proceed?"
785
+ );
786
+ if (!confirmed) {
787
+ logger.info("Operation cancelled by user");
788
+ process.exit(0);
789
+ }
790
+ }
791
+ const cliOverrides = extractSettingsOverrides();
792
+ const settings = await this.settingsManager.loadSettings(void 0, cliOverrides);
793
+ const workflowType = parsed.type === "branch" ? "regular" : parsed.type;
794
+ const workflowConfig = (_a = settings.workflows) == null ? void 0 : _a[workflowType];
795
+ const { extractRawSetArguments, getExecutablePath } = await import("./cli-overrides-XFZWY7CM.js");
796
+ const setArguments = extractRawSetArguments();
797
+ const executablePath = getExecutablePath();
798
+ logger.info(`\u2705 Validated input: ${this.formatParsedInput(parsed)}`);
799
+ const identifier = parsed.type === "branch" ? parsed.branchName ?? "" : parsed.number ?? 0;
800
+ const enableClaude = input.options.claude ?? (workflowConfig == null ? void 0 : workflowConfig.startAiAgent) ?? true;
801
+ const enableCode = input.options.code ?? (workflowConfig == null ? void 0 : workflowConfig.startIde) ?? true;
802
+ const enableDevServer = input.options.devServer ?? (workflowConfig == null ? void 0 : workflowConfig.startDevServer) ?? true;
803
+ const enableTerminal = input.options.terminal ?? (workflowConfig == null ? void 0 : workflowConfig.startTerminal) ?? false;
804
+ logger.debug("Final workflow config values:", {
805
+ enableClaude,
806
+ enableCode,
807
+ enableDevServer,
808
+ enableTerminal
809
+ });
810
+ const loom = await loomManager.createIloom({
811
+ type: parsed.type,
812
+ identifier,
813
+ originalInput: parsed.originalInput,
814
+ options: {
815
+ enableClaude,
816
+ enableCode,
817
+ enableDevServer,
818
+ enableTerminal,
819
+ ...input.options.oneShot && { oneShot: input.options.oneShot },
820
+ ...setArguments.length > 0 && { setArguments },
821
+ ...executablePath && { executablePath }
822
+ }
823
+ });
824
+ logger.success(`\u2705 Created loom: ${loom.id} at ${loom.path}`);
825
+ logger.info(` Branch: ${loom.branch}`);
826
+ if ((_b = loom.capabilities) == null ? void 0 : _b.includes("web")) {
827
+ logger.info(` Port: ${loom.port}`);
828
+ }
829
+ if ((_c = loom.githubData) == null ? void 0 : _c.title) {
830
+ logger.info(` Title: ${loom.githubData.title}`);
831
+ }
832
+ } catch (error) {
833
+ if (error instanceof Error) {
834
+ logger.error(`\u274C ${error.message}`);
835
+ } else {
836
+ logger.error("\u274C An unknown error occurred");
837
+ }
838
+ throw error;
839
+ }
840
+ }
841
+ /**
842
+ * Parse input to determine type and extract relevant data
843
+ */
844
+ async parseInput(identifier) {
845
+ const trimmedIdentifier = identifier.trim();
846
+ if (!trimmedIdentifier) {
847
+ throw new Error("Missing required argument: identifier");
848
+ }
849
+ const spaceCount = (trimmedIdentifier.match(/ /g) ?? []).length;
850
+ if (trimmedIdentifier.length > 25 && spaceCount > 2) {
851
+ return {
852
+ type: "description",
853
+ originalInput: trimmedIdentifier
854
+ };
855
+ }
856
+ const prPattern = /^(?:pr|PR)[/-](\d+)$/;
857
+ const prMatch = trimmedIdentifier.match(prPattern);
858
+ if (prMatch == null ? void 0 : prMatch[1]) {
859
+ return {
860
+ type: "pr",
861
+ number: parseInt(prMatch[1], 10),
862
+ originalInput: trimmedIdentifier
863
+ };
864
+ }
865
+ const numericPattern = /^#?(\d+)$/;
866
+ const numericMatch = trimmedIdentifier.match(numericPattern);
867
+ if (numericMatch == null ? void 0 : numericMatch[1]) {
868
+ const number = parseInt(numericMatch[1], 10);
869
+ const detection = await this.gitHubService.detectInputType(
870
+ trimmedIdentifier
871
+ );
872
+ if (detection.type === "pr") {
873
+ return {
874
+ type: "pr",
875
+ number: detection.number ?? number,
876
+ originalInput: trimmedIdentifier
877
+ };
878
+ } else if (detection.type === "issue") {
879
+ return {
880
+ type: "issue",
881
+ number: detection.number ?? number,
882
+ originalInput: trimmedIdentifier
883
+ };
884
+ } else {
885
+ throw new Error(`Could not find issue or PR #${number}`);
886
+ }
887
+ }
888
+ return {
889
+ type: "branch",
890
+ branchName: trimmedIdentifier,
891
+ originalInput: trimmedIdentifier
892
+ };
893
+ }
894
+ /**
895
+ * Validate the parsed input based on its type
896
+ */
897
+ async validateInput(parsed) {
898
+ switch (parsed.type) {
899
+ case "pr": {
900
+ if (!parsed.number) {
901
+ throw new Error("Invalid PR number");
902
+ }
903
+ const pr = await this.gitHubService.fetchPR(parsed.number);
904
+ await this.gitHubService.validatePRState(pr);
905
+ logger.debug(`Validated PR #${parsed.number}`);
906
+ break;
907
+ }
908
+ case "issue": {
909
+ if (!parsed.number) {
910
+ throw new Error("Invalid issue number");
911
+ }
912
+ const issue = await this.gitHubService.fetchIssue(parsed.number);
913
+ await this.gitHubService.validateIssueState(issue);
914
+ logger.debug(`Validated issue #${parsed.number}`);
915
+ break;
916
+ }
917
+ case "branch": {
918
+ if (!parsed.branchName) {
919
+ throw new Error("Invalid branch name");
920
+ }
921
+ if (!this.isValidBranchName(parsed.branchName)) {
922
+ throw new Error(
923
+ "Invalid branch name. Use only letters, numbers, hyphens, underscores, and slashes"
924
+ );
925
+ }
926
+ const exists = await branchExists(parsed.branchName);
927
+ if (exists) {
928
+ throw new Error(`Branch '${parsed.branchName}' already exists`);
929
+ }
930
+ logger.debug(`Validated branch name: ${parsed.branchName}`);
931
+ break;
932
+ }
933
+ case "description": {
934
+ logger.debug("Detected description input", {
935
+ length: parsed.originalInput.length
936
+ });
937
+ break;
938
+ }
939
+ default: {
940
+ const unknownType = parsed;
941
+ throw new Error(`Unknown input type: ${unknownType.type}`);
942
+ }
943
+ }
944
+ }
945
+ /**
946
+ * Validate branch name format
947
+ */
948
+ isValidBranchName(branch) {
949
+ return /^[a-zA-Z0-9/_-]+$/.test(branch);
950
+ }
951
+ /**
952
+ * Format parsed input for display
953
+ */
954
+ formatParsedInput(parsed) {
955
+ switch (parsed.type) {
956
+ case "pr":
957
+ return `PR #${parsed.number}`;
958
+ case "issue":
959
+ return `Issue #${parsed.number}`;
960
+ case "branch":
961
+ return `Branch '${parsed.branchName}'`;
962
+ case "description":
963
+ return `Description: ${parsed.originalInput.slice(0, 50)}...`;
964
+ default:
965
+ return "Unknown input";
966
+ }
967
+ }
968
+ /**
969
+ * Enhance description using Claude AI and create GitHub issue
970
+ * Returns the new issue number
971
+ */
972
+ async enhanceAndCreateIssue(description) {
973
+ const enhancedDescription = await this.enhancementService.enhanceDescription(description);
974
+ const result = await this.enhancementService.createEnhancedIssue(description, enhancedDescription);
975
+ await this.enhancementService.waitForReviewAndOpen(result.number, true);
976
+ return result.number;
977
+ }
978
+ };
979
+ export {
980
+ StartCommand
981
+ };
982
+ //# sourceMappingURL=start-LWVRBJ6S.js.map