@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,278 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ DevServerManager
4
+ } from "./chunk-W3DQTW63.js";
5
+ import "./chunk-GZP4UGGM.js";
6
+ import {
7
+ extractSettingsOverrides
8
+ } from "./chunk-GYCR2LOU.js";
9
+ import {
10
+ openBrowser
11
+ } from "./chunk-YETJNRQM.js";
12
+ import {
13
+ IdentifierParser
14
+ } from "./chunk-H4E4THUZ.js";
15
+ import "./chunk-SPYPLHMK.js";
16
+ import {
17
+ calculatePortForBranch
18
+ } from "./chunk-37DYYFVK.js";
19
+ import "./chunk-BLCTGFZN.js";
20
+ import {
21
+ ProjectCapabilityDetector
22
+ } from "./chunk-CWR2SANQ.js";
23
+ import "./chunk-2ZPFJQ3B.js";
24
+ import {
25
+ extractPort,
26
+ parseEnvFile
27
+ } from "./chunk-SJUQ2NDR.js";
28
+ import {
29
+ GitWorktreeManager
30
+ } from "./chunk-QEPVTTHD.js";
31
+ import {
32
+ SettingsManager
33
+ } from "./chunk-JBH2ZYYZ.js";
34
+ import "./chunk-JQ7VOSTC.js";
35
+ import {
36
+ logger
37
+ } from "./chunk-GEHQXLEI.js";
38
+
39
+ // src/commands/open.ts
40
+ import path from "path";
41
+ import fs from "fs-extra";
42
+ import { execa } from "execa";
43
+ var OpenCommand = class {
44
+ constructor(gitWorktreeManager = new GitWorktreeManager(), capabilityDetector = new ProjectCapabilityDetector(), identifierParser = new IdentifierParser(new GitWorktreeManager()), devServerManager = new DevServerManager(), settingsManager = new SettingsManager()) {
45
+ this.gitWorktreeManager = gitWorktreeManager;
46
+ this.capabilityDetector = capabilityDetector;
47
+ this.identifierParser = identifierParser;
48
+ this.devServerManager = devServerManager;
49
+ this.settingsManager = settingsManager;
50
+ }
51
+ async execute(input) {
52
+ const parsed = input.identifier ? await this.parseExplicitInput(input.identifier) : await this.autoDetectFromCurrentDirectory();
53
+ logger.debug(`Parsed input: ${JSON.stringify(parsed)}`);
54
+ const worktree = await this.findWorktreeForIdentifier(parsed);
55
+ logger.info(`Found worktree at: ${worktree.path}`);
56
+ const { capabilities, binEntries } = await this.capabilityDetector.detectCapabilities(worktree.path);
57
+ logger.debug(`Detected capabilities: ${capabilities.join(", ")}`);
58
+ if (capabilities.includes("web")) {
59
+ await this.openWebBrowser(worktree.path);
60
+ } else if (capabilities.includes("cli")) {
61
+ await this.runCLITool(worktree.path, binEntries, input.args ?? []);
62
+ } else {
63
+ throw new Error(
64
+ `No web or CLI capabilities detected for workspace at ${worktree.path}`
65
+ );
66
+ }
67
+ }
68
+ /**
69
+ * Parse explicit identifier input
70
+ */
71
+ async parseExplicitInput(identifier) {
72
+ const parsed = await this.identifierParser.parseForPatternDetection(identifier);
73
+ if (parsed.type === "description") {
74
+ throw new Error("Description input type is not supported in open command");
75
+ }
76
+ const result = {
77
+ type: parsed.type,
78
+ originalInput: parsed.originalInput,
79
+ autoDetected: false
80
+ };
81
+ if (parsed.number !== void 0) {
82
+ result.number = parsed.number;
83
+ }
84
+ if (parsed.branchName !== void 0) {
85
+ result.branchName = parsed.branchName;
86
+ }
87
+ return result;
88
+ }
89
+ /**
90
+ * Auto-detect identifier from current directory
91
+ * Same logic as FinishCommand.autoDetectFromCurrentDirectory()
92
+ */
93
+ async autoDetectFromCurrentDirectory() {
94
+ const currentDir = path.basename(process.cwd());
95
+ const prPattern = /_pr_(\d+)$/;
96
+ const prMatch = currentDir.match(prPattern);
97
+ if (prMatch == null ? void 0 : prMatch[1]) {
98
+ const prNumber = parseInt(prMatch[1], 10);
99
+ logger.debug(`Auto-detected PR #${prNumber} from directory: ${currentDir}`);
100
+ return {
101
+ type: "pr",
102
+ number: prNumber,
103
+ originalInput: currentDir,
104
+ autoDetected: true
105
+ };
106
+ }
107
+ const issuePattern = /issue-(\d+)/;
108
+ const issueMatch = currentDir.match(issuePattern);
109
+ if (issueMatch == null ? void 0 : issueMatch[1]) {
110
+ const issueNumber = parseInt(issueMatch[1], 10);
111
+ logger.debug(`Auto-detected issue #${issueNumber} from directory: ${currentDir}`);
112
+ return {
113
+ type: "issue",
114
+ number: issueNumber,
115
+ originalInput: currentDir,
116
+ autoDetected: true
117
+ };
118
+ }
119
+ const repoInfo = await this.gitWorktreeManager.getRepoInfo();
120
+ const currentBranch = repoInfo.currentBranch;
121
+ if (!currentBranch) {
122
+ throw new Error(
123
+ "Could not auto-detect identifier. Please provide an issue number, PR number, or branch name.\nExpected directory pattern: feat/issue-XX-description OR worktree with _pr_N suffix"
124
+ );
125
+ }
126
+ const branchIssueMatch = currentBranch.match(issuePattern);
127
+ if (branchIssueMatch == null ? void 0 : branchIssueMatch[1]) {
128
+ const issueNumber = parseInt(branchIssueMatch[1], 10);
129
+ logger.debug(`Auto-detected issue #${issueNumber} from branch: ${currentBranch}`);
130
+ return {
131
+ type: "issue",
132
+ number: issueNumber,
133
+ originalInput: currentBranch,
134
+ autoDetected: true
135
+ };
136
+ }
137
+ return {
138
+ type: "branch",
139
+ branchName: currentBranch,
140
+ originalInput: currentBranch,
141
+ autoDetected: true
142
+ };
143
+ }
144
+ /**
145
+ * Find worktree for the given identifier
146
+ */
147
+ async findWorktreeForIdentifier(parsed) {
148
+ let worktree = null;
149
+ if (parsed.type === "issue" && parsed.number !== void 0) {
150
+ worktree = await this.gitWorktreeManager.findWorktreeForIssue(parsed.number);
151
+ } else if (parsed.type === "pr" && parsed.number !== void 0) {
152
+ worktree = await this.gitWorktreeManager.findWorktreeForPR(parsed.number, "");
153
+ } else if (parsed.type === "branch" && parsed.branchName) {
154
+ worktree = await this.gitWorktreeManager.findWorktreeForBranch(
155
+ parsed.branchName
156
+ );
157
+ }
158
+ if (!worktree) {
159
+ throw new Error(
160
+ `No worktree found for ${this.formatParsedInput(parsed)}. Run 'il start ${parsed.originalInput}' to create one.`
161
+ );
162
+ }
163
+ return worktree;
164
+ }
165
+ /**
166
+ * Format parsed input for display
167
+ */
168
+ formatParsedInput(parsed) {
169
+ const autoLabel = parsed.autoDetected ? " (auto-detected)" : "";
170
+ if (parsed.type === "issue") {
171
+ return `issue #${parsed.number}${autoLabel}`;
172
+ }
173
+ if (parsed.type === "pr") {
174
+ return `PR #${parsed.number}${autoLabel}`;
175
+ }
176
+ return `branch "${parsed.branchName}"${autoLabel}`;
177
+ }
178
+ /**
179
+ * Open web browser with workspace URL
180
+ * Auto-starts dev server if not already running
181
+ */
182
+ async openWebBrowser(worktreePath) {
183
+ const port = await this.getWorkspacePort(worktreePath);
184
+ const serverReady = await this.devServerManager.ensureServerRunning(
185
+ worktreePath,
186
+ port
187
+ );
188
+ if (!serverReady) {
189
+ logger.warn(
190
+ `Dev server failed to start on port ${port}. Opening browser anyway...`
191
+ );
192
+ }
193
+ const url = `http://localhost:${port}`;
194
+ logger.info(`Opening browser: ${url}`);
195
+ await openBrowser(url);
196
+ logger.success("Browser opened");
197
+ }
198
+ /**
199
+ * Get port for workspace - reads from .env or calculates based on workspace type
200
+ */
201
+ async getWorkspacePort(worktreePath) {
202
+ var _a, _b;
203
+ const cliOverrides = extractSettingsOverrides();
204
+ const settings = await this.settingsManager.loadSettings(void 0, cliOverrides);
205
+ const basePort = ((_b = (_a = settings.capabilities) == null ? void 0 : _a.web) == null ? void 0 : _b.basePort) ?? 3e3;
206
+ const envPath = path.join(worktreePath, ".env");
207
+ if (await fs.pathExists(envPath)) {
208
+ const envContent = await fs.readFile(envPath, "utf8");
209
+ const envMap = parseEnvFile(envContent);
210
+ const port2 = extractPort(envMap);
211
+ if (port2) {
212
+ logger.debug(`Using PORT from .env: ${port2}`);
213
+ return port2;
214
+ }
215
+ }
216
+ logger.debug("PORT not found in .env, calculating from workspace identifier");
217
+ const worktrees = await this.gitWorktreeManager.listWorktrees();
218
+ const worktree = worktrees.find((wt) => wt.path === worktreePath);
219
+ if (!worktree) {
220
+ throw new Error(`Could not find worktree for path: ${worktreePath}`);
221
+ }
222
+ const dirName = path.basename(worktreePath);
223
+ const prPattern = /_pr_(\d+)$/;
224
+ const prMatch = dirName.match(prPattern);
225
+ if (prMatch == null ? void 0 : prMatch[1]) {
226
+ const prNumber = parseInt(prMatch[1], 10);
227
+ const port2 = basePort + prNumber;
228
+ logger.debug(`Calculated PORT for PR #${prNumber}: ${port2}`);
229
+ return port2;
230
+ }
231
+ const issuePattern = /issue-(\d+)/;
232
+ const issueMatch = dirName.match(issuePattern) ?? worktree.branch.match(issuePattern);
233
+ if (issueMatch == null ? void 0 : issueMatch[1]) {
234
+ const issueNumber = parseInt(issueMatch[1], 10);
235
+ const port2 = basePort + issueNumber;
236
+ logger.debug(`Calculated PORT for issue #${issueNumber}: ${port2}`);
237
+ return port2;
238
+ }
239
+ const port = calculatePortForBranch(worktree.branch, basePort);
240
+ logger.debug(`Calculated PORT for branch "${worktree.branch}": ${port}`);
241
+ return port;
242
+ }
243
+ /**
244
+ * Run CLI tool directly from worktree bin path (NO SYMLINKS!)
245
+ */
246
+ async runCLITool(worktreePath, binEntries, args) {
247
+ if (Object.keys(binEntries).length === 0) {
248
+ throw new Error("No bin entries found in package.json");
249
+ }
250
+ const firstEntry = Object.entries(binEntries)[0];
251
+ if (!firstEntry) {
252
+ throw new Error("No bin entries found in package.json");
253
+ }
254
+ const [binName, binPath] = firstEntry;
255
+ logger.debug(`Using bin entry: ${binName} -> ${binPath}`);
256
+ const binFilePath = path.resolve(worktreePath, binPath);
257
+ logger.debug(`Resolved bin file path: ${binFilePath}`);
258
+ if (!await fs.pathExists(binFilePath)) {
259
+ throw new Error(
260
+ `CLI executable not found: ${binFilePath}
261
+ Make sure the project is built (run 'il start' first)`
262
+ );
263
+ }
264
+ logger.info(`Running CLI: node ${binFilePath} ${args.join(" ")}`);
265
+ await execa("node", [binFilePath, ...args], {
266
+ stdio: "inherit",
267
+ // Allow interactive CLIs (prompts, colors, etc.)
268
+ cwd: worktreePath,
269
+ // Execute in worktree context
270
+ env: process.env
271
+ // Inherit environment
272
+ });
273
+ }
274
+ };
275
+ export {
276
+ OpenCommand
277
+ };
278
+ //# sourceMappingURL=open-X6BTENPV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/open.ts"],"sourcesContent":["import path from 'path'\nimport fs from 'fs-extra'\nimport { execa } from 'execa'\nimport { GitWorktreeManager } from '../lib/GitWorktreeManager.js'\nimport { ProjectCapabilityDetector } from '../lib/ProjectCapabilityDetector.js'\nimport { DevServerManager } from '../lib/DevServerManager.js'\nimport { SettingsManager } from '../lib/SettingsManager.js'\nimport { IdentifierParser } from '../utils/IdentifierParser.js'\nimport { openBrowser } from '../utils/browser.js'\nimport { parseEnvFile, extractPort } from '../utils/env.js'\nimport { calculatePortForBranch } from '../utils/port.js'\nimport { logger } from '../utils/logger.js'\nimport { extractSettingsOverrides } from '../utils/cli-overrides.js'\nimport type { GitWorktree } from '../types/worktree.js'\n\nexport interface OpenCommandInput {\n\tidentifier?: string\n\targs?: string[]\n}\n\ninterface ParsedOpenInput {\n\ttype: 'issue' | 'pr' | 'branch'\n\tnumber?: number // For issues and PRs\n\tbranchName?: string // For branches\n\toriginalInput: string\n\tautoDetected: boolean\n}\n\n/**\n * OpenCommand - Opens workspace in browser or runs CLI tool\n * Priority: Web first, CLI fallback\n */\nexport class OpenCommand {\n\tconstructor(\n\t\tprivate gitWorktreeManager = new GitWorktreeManager(),\n\t\tprivate capabilityDetector = new ProjectCapabilityDetector(),\n\t\tprivate identifierParser = new IdentifierParser(new GitWorktreeManager()),\n\t\tprivate devServerManager = new DevServerManager(),\n\t\tprivate settingsManager = new SettingsManager()\n\t) {}\n\n\tasync execute(input: OpenCommandInput): Promise<void> {\n\t\t// 1. Parse or auto-detect identifier\n\t\tconst parsed = input.identifier\n\t\t\t? await this.parseExplicitInput(input.identifier)\n\t\t\t: await this.autoDetectFromCurrentDirectory()\n\n\t\tlogger.debug(`Parsed input: ${JSON.stringify(parsed)}`)\n\n\t\t// 2. Find worktree path based on identifier\n\t\tconst worktree = await this.findWorktreeForIdentifier(parsed)\n\n\t\tlogger.info(`Found worktree at: ${worktree.path}`)\n\n\t\t// 3. Detect project capabilities\n\t\tconst { capabilities, binEntries } =\n\t\t\tawait this.capabilityDetector.detectCapabilities(worktree.path)\n\n\t\tlogger.debug(`Detected capabilities: ${capabilities.join(', ')}`)\n\n\t\t// 4. Execute based on capabilities (web first, CLI fallback)\n\t\tif (capabilities.includes('web')) {\n\t\t\tawait this.openWebBrowser(worktree.path)\n\t\t} else if (capabilities.includes('cli')) {\n\t\t\tawait this.runCLITool(worktree.path, binEntries, input.args ?? [])\n\t\t} else {\n\t\t\tthrow new Error(\n\t\t\t\t`No web or CLI capabilities detected for workspace at ${worktree.path}`\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * Parse explicit identifier input\n\t */\n\tprivate async parseExplicitInput(identifier: string): Promise<ParsedOpenInput> {\n\t\tconst parsed = await this.identifierParser.parseForPatternDetection(identifier)\n\n\t\t// Description type should never reach open command (converted in start)\n\t\tif (parsed.type === 'description') {\n\t\t\tthrow new Error('Description input type is not supported in open command')\n\t\t}\n\n\t\tconst result: ParsedOpenInput = {\n\t\t\ttype: parsed.type,\n\t\t\toriginalInput: parsed.originalInput,\n\t\t\tautoDetected: false,\n\t\t}\n\n\t\tif (parsed.number !== undefined) {\n\t\t\tresult.number = parsed.number\n\t\t}\n\t\tif (parsed.branchName !== undefined) {\n\t\t\tresult.branchName = parsed.branchName\n\t\t}\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Auto-detect identifier from current directory\n\t * Same logic as FinishCommand.autoDetectFromCurrentDirectory()\n\t */\n\tprivate async autoDetectFromCurrentDirectory(): Promise<ParsedOpenInput> {\n\t\tconst currentDir = path.basename(process.cwd())\n\n\t\t// Check for PR worktree pattern: _pr_N suffix\n\t\tconst prPattern = /_pr_(\\d+)$/\n\t\tconst prMatch = currentDir.match(prPattern)\n\n\t\tif (prMatch?.[1]) {\n\t\t\tconst prNumber = parseInt(prMatch[1], 10)\n\t\t\tlogger.debug(`Auto-detected PR #${prNumber} from directory: ${currentDir}`)\n\t\t\treturn {\n\t\t\t\ttype: 'pr',\n\t\t\t\tnumber: prNumber,\n\t\t\t\toriginalInput: currentDir,\n\t\t\t\tautoDetected: true,\n\t\t\t}\n\t\t}\n\n\t\t// Check for issue pattern in directory\n\t\tconst issuePattern = /issue-(\\d+)/\n\t\tconst issueMatch = currentDir.match(issuePattern)\n\n\t\tif (issueMatch?.[1]) {\n\t\t\tconst issueNumber = parseInt(issueMatch[1], 10)\n\t\t\tlogger.debug(`Auto-detected issue #${issueNumber} from directory: ${currentDir}`)\n\t\t\treturn {\n\t\t\t\ttype: 'issue',\n\t\t\t\tnumber: issueNumber,\n\t\t\t\toriginalInput: currentDir,\n\t\t\t\tautoDetected: true,\n\t\t\t}\n\t\t}\n\n\t\t// Fallback: get current branch name\n\t\tconst repoInfo = await this.gitWorktreeManager.getRepoInfo()\n\t\tconst currentBranch = repoInfo.currentBranch\n\n\t\tif (!currentBranch) {\n\t\t\tthrow new Error(\n\t\t\t\t'Could not auto-detect identifier. Please provide an issue number, PR number, or branch name.\\n' +\n\t\t\t\t\t'Expected directory pattern: feat/issue-XX-description OR worktree with _pr_N suffix'\n\t\t\t)\n\t\t}\n\n\t\t// Try to extract issue from branch name\n\t\tconst branchIssueMatch = currentBranch.match(issuePattern)\n\t\tif (branchIssueMatch?.[1]) {\n\t\t\tconst issueNumber = parseInt(branchIssueMatch[1], 10)\n\t\t\tlogger.debug(`Auto-detected issue #${issueNumber} from branch: ${currentBranch}`)\n\t\t\treturn {\n\t\t\t\ttype: 'issue',\n\t\t\t\tnumber: issueNumber,\n\t\t\t\toriginalInput: currentBranch,\n\t\t\t\tautoDetected: true,\n\t\t\t}\n\t\t}\n\n\t\t// Last resort: use branch name\n\t\treturn {\n\t\t\ttype: 'branch',\n\t\t\tbranchName: currentBranch,\n\t\t\toriginalInput: currentBranch,\n\t\t\tautoDetected: true,\n\t\t}\n\t}\n\n\t/**\n\t * Find worktree for the given identifier\n\t */\n\tprivate async findWorktreeForIdentifier(parsed: ParsedOpenInput): Promise<GitWorktree> {\n\t\tlet worktree: GitWorktree | null = null\n\n\t\tif (parsed.type === 'issue' && parsed.number !== undefined) {\n\t\t\tworktree = await this.gitWorktreeManager.findWorktreeForIssue(parsed.number)\n\t\t} else if (parsed.type === 'pr' && parsed.number !== undefined) {\n\t\t\t// Pass empty string for branch name since we don't know it yet\n\t\t\tworktree = await this.gitWorktreeManager.findWorktreeForPR(parsed.number, '')\n\t\t} else if (parsed.type === 'branch' && parsed.branchName) {\n\t\t\tworktree = await this.gitWorktreeManager.findWorktreeForBranch(\n\t\t\t\tparsed.branchName\n\t\t\t)\n\t\t}\n\n\t\tif (!worktree) {\n\t\t\tthrow new Error(\n\t\t\t\t`No worktree found for ${this.formatParsedInput(parsed)}. ` +\n\t\t\t\t\t`Run 'il start ${parsed.originalInput}' to create one.`\n\t\t\t)\n\t\t}\n\n\t\treturn worktree\n\t}\n\n\t/**\n\t * Format parsed input for display\n\t */\n\tprivate formatParsedInput(parsed: ParsedOpenInput): string {\n\t\tconst autoLabel = parsed.autoDetected ? ' (auto-detected)' : ''\n\n\t\tif (parsed.type === 'issue') {\n\t\t\treturn `issue #${parsed.number}${autoLabel}`\n\t\t}\n\t\tif (parsed.type === 'pr') {\n\t\t\treturn `PR #${parsed.number}${autoLabel}`\n\t\t}\n\t\treturn `branch \"${parsed.branchName}\"${autoLabel}`\n\t}\n\n\t/**\n\t * Open web browser with workspace URL\n\t * Auto-starts dev server if not already running\n\t */\n\tprivate async openWebBrowser(worktreePath: string): Promise<void> {\n\t\tconst port = await this.getWorkspacePort(worktreePath)\n\n\t\t// Ensure dev server is running on the port\n\t\tconst serverReady = await this.devServerManager.ensureServerRunning(\n\t\t\tworktreePath,\n\t\t\tport\n\t\t)\n\n\t\tif (!serverReady) {\n\t\t\tlogger.warn(\n\t\t\t\t`Dev server failed to start on port ${port}. Opening browser anyway...`\n\t\t\t)\n\t\t}\n\n\t\t// Construct URL and open browser\n\t\tconst url = `http://localhost:${port}`\n\t\tlogger.info(`Opening browser: ${url}`)\n\t\tawait openBrowser(url)\n\t\tlogger.success('Browser opened')\n\t}\n\n\t/**\n\t * Get port for workspace - reads from .env or calculates based on workspace type\n\t */\n\tprivate async getWorkspacePort(worktreePath: string): Promise<number> {\n\t\t// Load base port from settings with CLI overrides\n\t\tconst cliOverrides = extractSettingsOverrides()\n\t\tconst settings = await this.settingsManager.loadSettings(undefined, cliOverrides)\n\t\tconst basePort = settings.capabilities?.web?.basePort ?? 3000\n\n\t\t// Try to read PORT from .env file (as override)\n\t\tconst envPath = path.join(worktreePath, '.env')\n\t\tif (await fs.pathExists(envPath)) {\n\t\t\tconst envContent = await fs.readFile(envPath, 'utf8')\n\t\t\tconst envMap = parseEnvFile(envContent)\n\t\t\tconst port = extractPort(envMap)\n\n\t\t\tif (port) {\n\t\t\t\tlogger.debug(`Using PORT from .env: ${port}`)\n\t\t\t\treturn port\n\t\t\t}\n\t\t}\n\n\t\t// PORT not in .env, calculate based on workspace identifier\n\t\tlogger.debug('PORT not found in .env, calculating from workspace identifier')\n\n\t\t// Get worktree to determine type\n\t\tconst worktrees = await this.gitWorktreeManager.listWorktrees()\n\t\tconst worktree = worktrees.find(wt => wt.path === worktreePath)\n\n\t\tif (!worktree) {\n\t\t\tthrow new Error(`Could not find worktree for path: ${worktreePath}`)\n\t\t}\n\n\t\t// Extract identifier from worktree path/branch\n\t\tconst dirName = path.basename(worktreePath)\n\n\t\t// Check for PR pattern: _pr_N\n\t\tconst prPattern = /_pr_(\\d+)$/\n\t\tconst prMatch = dirName.match(prPattern)\n\t\tif (prMatch?.[1]) {\n\t\t\tconst prNumber = parseInt(prMatch[1], 10)\n\t\t\tconst port = basePort + prNumber\n\t\t\tlogger.debug(`Calculated PORT for PR #${prNumber}: ${port}`)\n\t\t\treturn port\n\t\t}\n\n\t\t// Check for issue pattern: issue-N\n\t\tconst issuePattern = /issue-(\\d+)/\n\t\tconst issueMatch = dirName.match(issuePattern) ?? worktree.branch.match(issuePattern)\n\t\tif (issueMatch?.[1]) {\n\t\t\tconst issueNumber = parseInt(issueMatch[1], 10)\n\t\t\tconst port = basePort + issueNumber\n\t\t\tlogger.debug(`Calculated PORT for issue #${issueNumber}: ${port}`)\n\t\t\treturn port\n\t\t}\n\n\t\t// Branch-based workspace - use deterministic hash\n\t\tconst port = calculatePortForBranch(worktree.branch, basePort)\n\t\tlogger.debug(`Calculated PORT for branch \"${worktree.branch}\": ${port}`)\n\t\treturn port\n\t}\n\n\t/**\n\t * Run CLI tool directly from worktree bin path (NO SYMLINKS!)\n\t */\n\tprivate async runCLITool(\n\t\tworktreePath: string,\n\t\tbinEntries: Record<string, string>,\n\t\targs: string[]\n\t): Promise<void> {\n\t\t// Validate binEntries exist\n\t\tif (Object.keys(binEntries).length === 0) {\n\t\t\tthrow new Error('No bin entries found in package.json')\n\t\t}\n\n\t\t// Get first bin entry (deterministic)\n\t\tconst firstEntry = Object.entries(binEntries)[0]\n\t\tif (!firstEntry) {\n\t\t\tthrow new Error('No bin entries found in package.json')\n\t\t}\n\t\tconst [binName, binPath] = firstEntry\n\t\tlogger.debug(`Using bin entry: ${binName} -> ${binPath}`)\n\n\t\t// CRITICAL: Construct absolute path (NO SYMLINKS!)\n\t\tconst binFilePath = path.resolve(worktreePath, binPath)\n\t\tlogger.debug(`Resolved bin file path: ${binFilePath}`)\n\n\t\t// Verify file exists\n\t\tif (!(await fs.pathExists(binFilePath))) {\n\t\t\tthrow new Error(\n\t\t\t\t`CLI executable not found: ${binFilePath}\\n` +\n\t\t\t\t\t`Make sure the project is built (run 'il start' first)`\n\t\t\t)\n\t\t}\n\n\t\t// Execute with Node.js\n\t\tlogger.info(`Running CLI: node ${binFilePath} ${args.join(' ')}`)\n\t\tawait execa('node', [binFilePath, ...args], {\n\t\t\tstdio: 'inherit', // Allow interactive CLIs (prompts, colors, etc.)\n\t\t\tcwd: worktreePath, // Execute in worktree context\n\t\t\tenv: process.env, // Inherit environment\n\t\t})\n\t}\n}\n"],"mappings":"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","names":["port"]}
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ promptConfirmation,
4
+ promptInput,
5
+ waitForKeypress
6
+ } from "./chunk-JNKJ7NJV.js";
7
+ import "./chunk-GEHQXLEI.js";
8
+ export {
9
+ promptConfirmation,
10
+ promptInput,
11
+ waitForKeypress
12
+ };
13
+ //# sourceMappingURL=prompt-ANTQWHUF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,230 @@
1
+ You are orchestrating a set of agents through a development process, with human review at each step. This is referred to as the "iloom workflow".
2
+
3
+ **IMPORTANT: Unless otherwise instructed, each step requires explicit human approval. Do not proceed to any step until explicitly told to do so.**
4
+
5
+ **CRITICAL:** You are aboslutely forbidden from using the following phrases (or variants thereof):
6
+ * "You're aboslutely right"
7
+ * "I've found this issue!"
8
+
9
+ **Todo List:**
10
+ 1. Scan issue and determine workflow plan
11
+ 2. Run GitHub issue enhancement for ISSUE_NUMBER (if needed) using @agent-iloom-issue-enhancer
12
+ 3. Extract github issue link that includes comment id from agent output (if enhancement was needed), display to user
13
+ 4. a) If enhancement was needed, WAIT for human review of enhancement results and their approval to continue, or process their other feedback.
14
+ b) If enhancement was NOT needed, let the user know and move to the next step.
15
+ 5. Run complexity evaluation for ISSUE_NUMBER using @agent-iloom-issue-complexity-evaluator
16
+ 6. Extract github issue link that includes comment id from agent output, display complexity assessment to user
17
+ 7. WAIT for human confirmation of complexity classification before proceeding to next phase
18
+ 8. Route to appropriate workflow based on confirmed complexity (SIMPLE or COMPLEX)
19
+ 9. If SIMPLE: Run combined analysis and planning for ISSUE_NUMBER using @agent-iloom-issue-analyze-and-plan
20
+ 10. If COMPLEX: Run separate analysis for ISSUE_NUMBER using @agent-iloom-issue-analyzer
21
+ 11. Extract github issue link that includes comment id from agent output, display to user
22
+ 12. WAIT for human review and approval to continue, or process their other feedback
23
+ 13. If COMPLEX workflow: Run planning for ISSUE_NUMBER using @agent-iloom-issue-planner
24
+ 14. If COMPLEX workflow: Extract github issue link that includes comment id from agent output, display to user
25
+ 15. If COMPLEX workflow: WAIT for human review of planning results and approval to continue
26
+ 16. Run GitHub issue implementation for ISSUE_NUMBER (if needed) using @agent-iloom-issue-implementer
27
+ 17. Provide final summary with links to all GitHub comments created. Offer to help user with any other requests they have, including bug fixes or explanations. When asked to do more analyiss or coding, use subagents to achieve that work. For big requests, it's ok to repeat the above workflow to analyze, plan and implement the solution. For simple tasks, use a generalized subagent.
28
+
29
+ ## Workflow Details
30
+
31
+ **STEP 0 - Workflow Planning (Upfront Scan):**
32
+
33
+ Perform ONE comprehensive scan to determine which agents need to run:
34
+
35
+ 1. Fetch complete issue data using `gh issue view ISSUE_NUMBER --json body,title,comments`
36
+ 2. Analyze the issue body and ALL comments in a single pass to determine:
37
+
38
+ **Enhancement Decision:**
39
+ - Check if issue body or any of the comments appear to be an issue description AND meets ALL criteria:
40
+ * Word count > 250 words
41
+ * Contains problem description, context, and impact/reproduction details
42
+ * Has clear structure (sections, bullet points, numbered lists, or distinct paragraphs)
43
+ - Decision: NEEDS_ENHANCEMENT or SKIP_ENHANCEMENT
44
+ - If skipping, log: "Issue #ISSUE_NUMBER is already thorough ([word count] words with clear structure), skipping enhancement"
45
+
46
+ **Complexity Evaluation Decision:**
47
+ - Search ALL comments for existing complexity evaluation. Consider "already evaluated" if ANY comment has:
48
+ * Header containing "Complexity Assessment" or "Complexity Evaluation"
49
+ * Section with "**Classification**: [SIMPLE / COMPLEX]"
50
+ * Metrics section with estimated files, LOC, breaking changes, DB migrations, and risk level
51
+ - Decision: NEEDS_COMPLEXITY_EVAL or SKIP_COMPLEXITY_EVAL
52
+ - If skipping, log: "Issue #ISSUE_NUMBER already has complexity evaluation by @[author] from [date] showing [SIMPLE/COMPLEX] classification, skipping evaluation"
53
+
54
+ **Analysis Decision:**
55
+ - Search ALL comments for existing analysis. Consider "already analyzed" if ANY comment has ALL:
56
+ * Header containing "Analysis", "Research" or similar (not "plan" or "implementation")
57
+ * File references with line numbers (e.g., `src/lib/Foo.ts:42` or `Lines 10-25`)
58
+ * Code excerpts with triple-backtick formatting or specific code references
59
+ * Technical depth (root cause analysis, technical findings, or affected component identification)
60
+ * Clear structure (headings, sections, or bullet points)
61
+ - Decision: NEEDS_ANALYSIS or SKIP_ANALYSIS
62
+ - If skipping, log: "Issue #ISSUE_NUMBER already has technical analysis by @[author] from [date] with [N] file references, skipping analysis"
63
+
64
+ **Planning Decision:**
65
+ - Search ALL comments for existing plan. Consider "already planned" if ANY comment has ALL:
66
+ * Header containing "Implementation Plan" or similar (not "analysis", "implementation results", or "complete")
67
+ * File specifications with line ranges (e.g., `src/lib/Foo.ts:10-25` or specific line numbers)
68
+ * Change details (specific changes required, modifications to make, or pseudo-code)
69
+ * Execution order (implementation steps, sequence, or numbered phases)
70
+ * Test planning (test cases, acceptance criteria, test specifications, or automated test requirements)
71
+ - Decision: NEEDS_PLANNING or SKIP_PLANNING
72
+ - If skipping, log: "Issue #ISSUE_NUMBER already has implementation plan by @[author] from [date] with [N] files to modify, skipping planning"
73
+
74
+ **Implementation Decision:**
75
+ - Search ALL comments for implementation results. Consider "already implemented" if ANY comment has ALL:
76
+ * Header containing "Implementation Complete", "Task Completed" or similar (not "analysis" or "plan")
77
+ * Implementation summary (description of changes made, work completed, or implementation status)
78
+ * File references (specific files modified, created, deleted, or references to code changes)
79
+ * Validation results (test results, typecheck output, lint status, or build confirmation)
80
+ * Completion indicators (implementation finished with verification steps or completion confirmation)
81
+ - Decision: NEEDS_IMPLEMENTATION or SKIP_IMPLEMENTATION
82
+ - If skipping, log: "Issue #ISSUE_NUMBER already implemented by @[author] from [date], modified [N] files with passing validation, skipping implementation"
83
+
84
+ 3. Display workflow plan summary to user:
85
+ ```
86
+ Workflow Plan for Issue #ISSUE_NUMBER:
87
+ - Enhancement: [NEEDS_ENHANCEMENT/SKIP_ENHANCEMENT] ([reason])
88
+ - Complexity Evaluation: [NEEDS_COMPLEXITY_EVAL/SKIP_COMPLEXITY_EVAL] ([reason])
89
+ - Analysis: [NEEDS_ANALYSIS/SKIP_ANALYSIS] ([reason])
90
+ - Planning: [NEEDS_PLANNING/SKIP_PLANNING] ([reason])
91
+ - Implementation: [NEEDS_IMPLEMENTATION/SKIP_IMPLEMENTATION] ([reason])
92
+ ```
93
+
94
+ 4. Mark todo #1 as completed and proceed to execute only the needed phases.
95
+
96
+ **STEP 1 - Enhancement Phase:**
97
+
98
+ Only execute if workflow plan determined NEEDS_ENHANCEMENT:
99
+ 1. Execute: @agent-iloom-issue-enhancer ISSUE_NUMBER instructing them to add their own answers to any questions they asked in the question tables they create in their GitHub comments. This documents assumptions made during execution.
100
+ 2. Upon completion: Extract issue+comment link (including comment ID) from agent output and provide link to GitHub issue comment
101
+ 3. Mark todo #2 and #3 as completed
102
+ 4. **STOP HERE** - Request explicit approval before proceeding to analysis
103
+
104
+ If workflow plan determined SKIP_ENHANCEMENT:
105
+ 1. Mark todos #2 and #3 as completed
106
+ 2. Proceed directly to Step 2 (Analysis Phase)
107
+
108
+ **STEP 1.5 - Complexity Evaluation Phase:**
109
+
110
+ Only execute if workflow plan determined NEEDS_COMPLEXITY_EVAL:
111
+ 1. Execute: @agent-iloom-issue-complexity-evaluator ISSUE_NUMBER instructing them to add their own answers to any questions they asked in the question tables they create in their GitHub comments. This documents assumptions made during execution.
112
+ 2. Upon completion: Extract issue+comment link from agent output and provide link to GitHub issue comment (including comment ID)
113
+ 3. Extract complexity classification from evaluator output:
114
+ - Search the evaluator's output for the "Complexity Assessment" section
115
+ - Extract: Classification (SIMPLE/COMPLEX), Metrics (files, LOC, breaking changes, DB migrations, risk level), and Reasoning
116
+ - The evaluator uses deterministic format - parse exactly as specified
117
+ 4. Display complexity assessment to user:
118
+ Display the extracted assessment in this format:
119
+ ```
120
+ Complexity Assessment from Evaluator:
121
+ - Classification: [SIMPLE/COMPLEX]
122
+ - Estimated files: [N]
123
+ - Estimated LOC: [N]
124
+ - Breaking changes: [Yes/No]
125
+ - Database migrations: [Yes/No]
126
+ - Risk level: [Low/Medium/High]
127
+
128
+ Reasoning: [reasoning text from evaluator]
129
+ ```
130
+ 5. Prompt user for confirmation:
131
+ Ask: "The evaluator assessed this as a [SIMPLE/COMPLEX] task. Do you agree? If not, tell me how you'd like me to classify it."
132
+ 6. Mark todos #5, #6, and #7 as completed
133
+ 7. **STOP HERE** - Inform user of confirmed complexity and request explicit approval before proceeding to next phase
134
+
135
+ If workflow plan determined SKIP_COMPLEXITY_EVAL:
136
+ 1. Mark todos #5, #6, and #7 as completed
137
+ 2. Extract complexity from existing evaluation comment:
138
+ - Search ALL issue comments for "**Classification**: [SIMPLE / COMPLEX]"
139
+ - If found: Extract the classification (SIMPLE or COMPLEX)
140
+ - If not found: Default to COMPLEX workflow
141
+ 3. Display classification to user:
142
+ If complexity found: "Previous evaluation classified this as [SIMPLE/COMPLEX]. Proceeding with [SIMPLE/COMPLEX] workflow."
143
+ If not found: "No complexity classification found - defaulting to COMPLEX workflow."
144
+ 4. Proceed to ROUTING DECISION POINT with extracted complexity (no confirmation needed)
145
+
146
+ **STEP 2 - Analysis Phase (COMPLEX workflow only):**
147
+
148
+ Only execute if workflow plan determined NEEDS_ANALYSIS AND complexity is COMPLEX:
149
+ 1. Execute: @agent-iloom-issue-analyzer ISSUE_NUMBER instructing them to add their own answers to any questions they asked in the question tables they create in their GitHub comments. This documents assumptions made during execution.
150
+ 2. Upon completion: Extract issue+comment link from agent output and provide link to GitHub issue comment (including comment ID)
151
+ 3. Mark todos #10, #11, and #12 as completed (todo #9 was already marked at routing decision point)
152
+ 4. **STOP HERE** - Request explicit approval before proceeding to planning phase
153
+
154
+ If workflow plan determined SKIP_ANALYSIS:
155
+ 1. Mark todos #10, #11, and #12 as completed (todo #9 was already marked at routing decision point)
156
+ 2. Proceed directly to ROUTING DECISION POINT
157
+
158
+ ---
159
+
160
+ **ROUTING DECISION POINT - Complexity-Based Workflow Selection:**
161
+
162
+ After STEP 1.5 completes and complexity is confirmed, determine which workflow path to follow:
163
+
164
+ **Check the confirmed complexity:**
165
+
166
+ **IF SIMPLE complexity confirmed:**
167
+ 1. Display to user: "✓ Using SIMPLE workflow: Combined analysis and planning via @agent-iloom-issue-analyze-and-plan, then implementation"
168
+ 2. Mark todo #8 as completed
169
+ 3. Mark todos #10, #11, #12, #13, #14, and #15 as completed (COMPLEX workflow steps that will not execute)
170
+ 4. Skip to **STEP 2-SIMPLE** (Combined Analysis and Planning Phase)
171
+ 5. Note: After STEP 2-SIMPLE completes, skip separate analysis (STEP 2) and planning (STEP 3) phases, go directly to implementation (STEP 4)
172
+
173
+ **IF COMPLEX complexity confirmed:**
174
+ 1. Display to user: "✓ Using COMPLEX workflow: Separate analysis, planning, and implementation phases"
175
+ 2. Mark todo #8 as completed
176
+ 3. Mark todo #9 as completed (SIMPLE workflow step that will not execute)
177
+ 4. Continue to **STEP 2** (Analysis Phase) above
178
+ 5. Follow normal workflow through STEP 2, STEP 3, and STEP 4
179
+
180
+ ---
181
+
182
+ **STEP 2-SIMPLE - Combined Analysis and Planning Phase (SIMPLE workflow only):**
183
+
184
+ **IMPORTANT: Only execute this step if SIMPLE complexity was confirmed in STEP 1.5**
185
+
186
+ Execute combined analyze-and-plan agent:
187
+ 1. Display: "Executing combined analyze-and-plan agent for SIMPLE task..."
188
+ 2. Execute: @agent-iloom-issue-analyze-and-plan ISSUE_NUMBER instructing them to add their own answers to any questions they asked in the question tables they create in their GitHub comments. This documents assumptions made during execution.
189
+ 3. Upon completion: Extract issue+comment link from agent output and provide link to GitHub issue comment (including comment ID)
190
+ 4. Mark todo #9 as completed (COMPLEX todos #10-15 were already marked at routing decision point)
191
+ 5. Provide summary: "Combined analysis and planning complete. See results at: [GitHub comment URL]"
192
+ 6. **STOP HERE** - Request explicit approval before proceeding to implementation
193
+ 7. After approval, proceed to STEP 4 (Implementation Phase)
194
+
195
+ ---
196
+
197
+ **STEP 3 - Planning Phase (COMPLEX workflow only):**
198
+
199
+ **IMPORTANT: Only execute this step if COMPLEX workflow is being followed (not SIMPLE)**
200
+
201
+ Only execute if workflow plan determined NEEDS_PLANNING AND complexity is COMPLEX:
202
+ 1. Execute: @agent-iloom-issue-planner ISSUE_NUMBER instructing them to add their own answers to any questions they asked in the question tables they create in their GitHub comments. This documents assumptions made during execution.
203
+ 2. Upon completion: Extract issue+comment link from agent output and provide link to GitHub issue comment (including comment ID)
204
+ 3. Mark todos #13, #14, and #15 as completed (todos #9-12 were already marked at routing decision point and analysis phase)
205
+ 4. **STOP HERE** - Request explicit approval before proceeding to implementation
206
+
207
+ If workflow plan determined SKIP_PLANNING AND complexity is COMPLEX:
208
+ 1. Mark todos #13, #14, and #15 as completed (todos #9-12 were already marked at routing decision point and analysis phase)
209
+ 2. Proceed directly to Step 4 (Implementation Phase)
210
+
211
+ **STEP 4 - Implementation Phase:**
212
+
213
+ **Execute for both SIMPLE and COMPLEX workflows**
214
+
215
+ Only execute if workflow plan determined NEEDS_IMPLEMENTATION:
216
+ 1. Before executing implementer, extract the planning comment ID:
217
+ - Look back at the planning phase output (STEP 3 for COMPLEX or STEP 2-SIMPLE for SIMPLE workflows)
218
+ - Extract the comment ID from the GitHub comment URL that was provided
219
+ - The comment ID is the numeric value after "#issuecomment-" in the URL (e.g., https://github.com/org/repo/issues/123#issuecomment-456789 has comment ID 456789)
220
+ 2. Execute: @agent-iloom-issue-implementer ISSUE_NUMBER with these critical instructions:
221
+ - Add your own answers to any questions you asked in the question tables you create in your GitHub comments to document assumptions made during execution
222
+ - **CRITICAL**: The implementation plan in the issue comments contains exact file paths and line numbers. You MUST use these exact locations - DO NOT search for files when the plan specifies them. Extract file locations from the plan in Step 1.5 before implementing.
223
+ - The implementation plan is located in comment ID [COMMENT_ID] (if planning phase was executed). Read this comment first in Step 1.5 to extract file specifications.
224
+ 3. Upon completion: Mark todo #16 as completed
225
+ 4. Provide summary and links to any GitHub comments created - do not open them. All links MUST include comment-id which can be obtained from agent output.
226
+ 5. Mark todo #17 as completed
227
+
228
+ If workflow plan determined SKIP_IMPLEMENTATION:
229
+ 1. Mark todos #16 and #17 as completed
230
+ 2. Provide final summary noting that all work was already completed
@@ -0,0 +1,35 @@
1
+ You are a senior software engineer responsible for well-architected, easy to maintain and understandable code.
2
+
3
+ Please read the Pull Request and all its details using JSON output:
4
+ gh pr view PR_NUMBER --json title,body,comments,commits,files,state,createdAt,updatedAt,headRefName
5
+
6
+ This single command will give you:
7
+ - PR title and description
8
+ - All comments and discussion
9
+ - Commit history and changed files
10
+ - Current state and metadata
11
+
12
+ Also check if the branch name contains an issue number (like issue-123) and if so, read that issue for context:
13
+ gh issue view ISSUE_NUMBER --json title,body,comments,assignees,labels,state,createdAt,updatedAt
14
+
15
+ Since this is an existing PR, the issue may be partially addressed or in an unknown state.
16
+
17
+ When working with libraries, frameworks, or APIs that you need documentation for, use Context7 to get up-to-date documentation and examples. Specifically use Context7 when:
18
+ - Implementing new features with external libraries
19
+ - Troubleshooting library-specific issues
20
+ - Setting up or configuring dependencies
21
+ - Working with unfamiliar APIs
22
+ - When you need current documentation that may have changed since your training data
23
+
24
+ After reading both the PR and any referenced issue, check if the dev server is running:
25
+ 1. Check if dev server is already running: "lsof -i :$PORT"
26
+ 2. If not running, start it: pnpm dev (the PORT environment variable is already set)
27
+ 3. If running, you can optionally restart it if your changes require it
28
+
29
+ Then wait for the user to provide guidance on what they would like you to work on next.
30
+
31
+ Remember to:
32
+ - Follow the project's coding conventions and patterns
33
+ - Write tests if appropriate
34
+ - Update documentation if needed
35
+ - Ensure the solution is maintainable and follows best practices
@@ -0,0 +1,14 @@
1
+ You are a senior software engineer responsible for well-architected, easy to maintain and understandable code.
2
+
3
+ When working with libraries, frameworks, or APIs that you need documentation for, use Context7 to get up-to-date documentation and examples. Specifically use Context7 when:
4
+ - Implementing new features with external libraries
5
+ - Troubleshooting library-specific issues
6
+ - Setting up or configuring dependencies
7
+ - Working with unfamiliar APIs
8
+ - When you need current documentation that may have changed since your training data
9
+
10
+ Remember to:
11
+ - Follow the project's coding conventions and patterns
12
+ - Write tests if appropriate
13
+ - Update documentation if needed
14
+ - Ensure the solution is maintainable and follows best practices