@iloom/cli 0.7.3 → 0.7.5

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 (101) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +6 -4
  3. package/dist/{BranchNamingService-FLPUUFOB.js → BranchNamingService-AO7BPIUJ.js} +2 -2
  4. package/dist/{ClaudeContextManager-KE5TBZVZ.js → ClaudeContextManager-Y2YJC6BU.js} +4 -4
  5. package/dist/{ClaudeService-CRSETT3A.js → ClaudeService-NDVFQRKC.js} +3 -3
  6. package/dist/{LoomLauncher-NL65LSKP.js → LoomLauncher-U2B3VHPC.js} +4 -4
  7. package/dist/{PRManager-2ABCWXHW.js → PRManager-6ZJZRG5Z.js} +4 -4
  8. package/dist/README.md +6 -4
  9. package/dist/agents/iloom-issue-analyze-and-plan.md +1 -1
  10. package/dist/agents/iloom-issue-analyzer.md +1 -1
  11. package/dist/agents/iloom-issue-complexity-evaluator.md +1 -1
  12. package/dist/agents/iloom-issue-enhancer.md +1 -1
  13. package/dist/agents/iloom-issue-implementer.md +1 -1
  14. package/dist/agents/iloom-issue-planner.md +1 -1
  15. package/dist/agents/iloom-issue-reviewer.md +1 -1
  16. package/dist/{chunk-FM4KBPVA.js → chunk-3K3WY3BN.js} +2 -118
  17. package/dist/chunk-3K3WY3BN.js.map +1 -0
  18. package/dist/{chunk-6TL3BYH6.js → chunk-64HCHVJM.js} +2 -2
  19. package/dist/{chunk-QQFBMCAH.js → chunk-77VLG2KP.js} +20 -17
  20. package/dist/chunk-77VLG2KP.js.map +1 -0
  21. package/dist/{chunk-FEAJR6PN.js → chunk-C7YW5IMS.js} +2 -2
  22. package/dist/{chunk-DAOS6EC3.js → chunk-CAXFWFV6.js} +5 -3
  23. package/dist/{chunk-DAOS6EC3.js.map → chunk-CAXFWFV6.js.map} +1 -1
  24. package/dist/chunk-CFQVOTHO.js +111 -0
  25. package/dist/chunk-CFQVOTHO.js.map +1 -0
  26. package/dist/{chunk-AFRICMSW.js → chunk-ENMTWE74.js} +2 -2
  27. package/dist/{chunk-FP7G7DG3.js → chunk-IGKPPACU.js} +8 -3
  28. package/dist/chunk-IGKPPACU.js.map +1 -0
  29. package/dist/{chunk-CNSTXBJ3.js → chunk-KSXA2NOJ.js} +9 -5
  30. package/dist/chunk-KSXA2NOJ.js.map +1 -0
  31. package/dist/{chunk-GJMEKEI5.js → chunk-LZBSLO6S.js} +76 -1
  32. package/dist/chunk-LZBSLO6S.js.map +1 -0
  33. package/dist/{chunk-YQNSZKKT.js → chunk-NEPH2O4C.js} +8 -4
  34. package/dist/chunk-NEPH2O4C.js.map +1 -0
  35. package/dist/{chunk-KVS4XGBQ.js → chunk-O36JLYNW.js} +2 -2
  36. package/dist/{chunk-C3AKFAIR.js → chunk-Q457PKGH.js} +2 -2
  37. package/dist/{chunk-EPPPDVHD.js → chunk-TB6475EW.js} +6 -4
  38. package/dist/chunk-TB6475EW.js.map +1 -0
  39. package/dist/{chunk-HVQNVRAF.js → chunk-VYKKWU36.js} +96 -3
  40. package/dist/chunk-VYKKWU36.js.map +1 -0
  41. package/dist/{chunk-453NC377.js → chunk-WZYBHD7P.js} +3 -106
  42. package/dist/chunk-WZYBHD7P.js.map +1 -0
  43. package/dist/chunk-XAMBIVXE.js +121 -0
  44. package/dist/chunk-XAMBIVXE.js.map +1 -0
  45. package/dist/{claude-6H36IBHO.js → claude-V4HRPR4Z.js} +2 -2
  46. package/dist/{cleanup-77U5ATYI.js → cleanup-DB7EFBF3.js} +9 -6
  47. package/dist/{cleanup-77U5ATYI.js.map → cleanup-DB7EFBF3.js.map} +1 -1
  48. package/dist/cli.js +104 -156
  49. package/dist/cli.js.map +1 -1
  50. package/dist/{commit-ONRXU67O.js → commit-NGMDWWAP.js} +4 -4
  51. package/dist/{dev-server-UKAPBGUR.js → dev-server-OAP3RZC6.js} +4 -3
  52. package/dist/{dev-server-UKAPBGUR.js.map → dev-server-OAP3RZC6.js.map} +1 -1
  53. package/dist/{feedback-K3A4QUSG.js → feedback-ZLAX3BVL.js} +4 -3
  54. package/dist/{feedback-K3A4QUSG.js.map → feedback-ZLAX3BVL.js.map} +1 -1
  55. package/dist/{ignite-YUAOJ5PP.js → ignite-HA2OJF6Z.js} +26 -40
  56. package/dist/ignite-HA2OJF6Z.js.map +1 -0
  57. package/dist/index.js +4 -1
  58. package/dist/index.js.map +1 -1
  59. package/dist/{init-XQQMFDM6.js → init-S6IEGRSX.js} +3 -3
  60. package/dist/mcp/issue-management-server.js +157 -9
  61. package/dist/mcp/issue-management-server.js.map +1 -1
  62. package/dist/{open-QI63XQ4F.js → open-IN3LUZXX.js} +4 -3
  63. package/dist/{open-QI63XQ4F.js.map → open-IN3LUZXX.js.map} +1 -1
  64. package/dist/{projects-TWY4RT2Z.js → projects-CTRTTMSK.js} +25 -9
  65. package/dist/projects-CTRTTMSK.js.map +1 -0
  66. package/dist/prompts/issue-prompt.txt +16 -0
  67. package/dist/prompts/pr-prompt.txt +33 -13
  68. package/dist/prompts/regular-prompt.txt +7 -0
  69. package/dist/{rebase-QYCRF7JG.js → rebase-RLEVFHWN.js} +3 -3
  70. package/dist/{run-YDVYORT2.js → run-QEIS2EH2.js} +4 -3
  71. package/dist/{run-YDVYORT2.js.map → run-QEIS2EH2.js.map} +1 -1
  72. package/dist/{summary-G6L3VAKK.js → summary-2KLNHVTN.js} +4 -4
  73. package/dist/{test-webserver-NRMGT2HB.js → test-webserver-J6SMNLU2.js} +3 -2
  74. package/dist/{test-webserver-NRMGT2HB.js.map → test-webserver-J6SMNLU2.js.map} +1 -1
  75. package/package.json +1 -1
  76. package/dist/chunk-453NC377.js.map +0 -1
  77. package/dist/chunk-CNSTXBJ3.js.map +0 -1
  78. package/dist/chunk-EPPPDVHD.js.map +0 -1
  79. package/dist/chunk-FM4KBPVA.js.map +0 -1
  80. package/dist/chunk-FP7G7DG3.js.map +0 -1
  81. package/dist/chunk-GJMEKEI5.js.map +0 -1
  82. package/dist/chunk-HVQNVRAF.js.map +0 -1
  83. package/dist/chunk-QQFBMCAH.js.map +0 -1
  84. package/dist/chunk-YQNSZKKT.js.map +0 -1
  85. package/dist/ignite-YUAOJ5PP.js.map +0 -1
  86. package/dist/projects-TWY4RT2Z.js.map +0 -1
  87. /package/dist/{BranchNamingService-FLPUUFOB.js.map → BranchNamingService-AO7BPIUJ.js.map} +0 -0
  88. /package/dist/{ClaudeContextManager-KE5TBZVZ.js.map → ClaudeContextManager-Y2YJC6BU.js.map} +0 -0
  89. /package/dist/{ClaudeService-CRSETT3A.js.map → ClaudeService-NDVFQRKC.js.map} +0 -0
  90. /package/dist/{LoomLauncher-NL65LSKP.js.map → LoomLauncher-U2B3VHPC.js.map} +0 -0
  91. /package/dist/{PRManager-2ABCWXHW.js.map → PRManager-6ZJZRG5Z.js.map} +0 -0
  92. /package/dist/{chunk-6TL3BYH6.js.map → chunk-64HCHVJM.js.map} +0 -0
  93. /package/dist/{chunk-FEAJR6PN.js.map → chunk-C7YW5IMS.js.map} +0 -0
  94. /package/dist/{chunk-AFRICMSW.js.map → chunk-ENMTWE74.js.map} +0 -0
  95. /package/dist/{chunk-KVS4XGBQ.js.map → chunk-O36JLYNW.js.map} +0 -0
  96. /package/dist/{chunk-C3AKFAIR.js.map → chunk-Q457PKGH.js.map} +0 -0
  97. /package/dist/{claude-6H36IBHO.js.map → claude-V4HRPR4Z.js.map} +0 -0
  98. /package/dist/{commit-ONRXU67O.js.map → commit-NGMDWWAP.js.map} +0 -0
  99. /package/dist/{init-XQQMFDM6.js.map → init-S6IEGRSX.js.map} +0 -0
  100. /package/dist/{rebase-QYCRF7JG.js.map → rebase-RLEVFHWN.js.map} +0 -0
  101. /package/dist/{summary-G6L3VAKK.js.map → summary-2KLNHVTN.js.map} +0 -0
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  SessionSummaryService
4
- } from "./chunk-CNSTXBJ3.js";
4
+ } from "./chunk-KSXA2NOJ.js";
5
5
  import "./chunk-NXMDEL3F.js";
6
6
  import {
7
7
  CLIIsolationManager,
@@ -9,18 +9,18 @@ import {
9
9
  EnvironmentManager,
10
10
  LoomManager,
11
11
  ResourceCleanup
12
- } from "./chunk-QQFBMCAH.js";
12
+ } from "./chunk-77VLG2KP.js";
13
13
  import {
14
14
  BuildRunner,
15
15
  MergeManager
16
- } from "./chunk-DAOS6EC3.js";
16
+ } from "./chunk-CAXFWFV6.js";
17
17
  import {
18
- IssueTrackerFactory,
19
- generateIssueManagementMcpConfig
20
- } from "./chunk-FM4KBPVA.js";
18
+ IssueTrackerFactory
19
+ } from "./chunk-3K3WY3BN.js";
21
20
  import {
22
21
  ProcessManager
23
- } from "./chunk-453NC377.js";
22
+ } from "./chunk-WZYBHD7P.js";
23
+ import "./chunk-CFQVOTHO.js";
24
24
  import {
25
25
  IdentifierParser
26
26
  } from "./chunk-5V74K5ZA.js";
@@ -30,7 +30,7 @@ import {
30
30
  import {
31
31
  InitCommand,
32
32
  ShellCompletion
33
- } from "./chunk-FEAJR6PN.js";
33
+ } from "./chunk-C7YW5IMS.js";
34
34
  import {
35
35
  FirstRunManager
36
36
  } from "./chunk-Q7POFB5Q.js";
@@ -38,7 +38,8 @@ import "./chunk-F2PWIRV4.js";
38
38
  import {
39
39
  IssueEnhancementService,
40
40
  capitalizeFirstLetter
41
- } from "./chunk-HVQNVRAF.js";
41
+ } from "./chunk-VYKKWU36.js";
42
+ import "./chunk-XAMBIVXE.js";
42
43
  import {
43
44
  ProjectCapabilityDetector
44
45
  } from "./chunk-7GLZVDPQ.js";
@@ -49,7 +50,7 @@ import {
49
50
  CommitManager,
50
51
  UserAbortedCommitError,
51
52
  ValidationRunner
52
- } from "./chunk-YQNSZKKT.js";
53
+ } from "./chunk-NEPH2O4C.js";
53
54
  import {
54
55
  installDependencies
55
56
  } from "./chunk-RD7I2Q2F.js";
@@ -59,13 +60,13 @@ import {
59
60
  import "./chunk-XPKN3QWY.js";
60
61
  import {
61
62
  PRManager
62
- } from "./chunk-EPPPDVHD.js";
63
+ } from "./chunk-TB6475EW.js";
63
64
  import {
64
65
  openBrowser
65
66
  } from "./chunk-YETJNRQM.js";
66
67
  import {
67
68
  IssueManagementProviderFactory
68
- } from "./chunk-GJMEKEI5.js";
69
+ } from "./chunk-LZBSLO6S.js";
69
70
  import "./chunk-HBJITKSZ.js";
70
71
  import {
71
72
  getConfiguredRepoFromSettings,
@@ -78,15 +79,15 @@ import {
78
79
  } from "./chunk-O7VL5N6S.js";
79
80
  import {
80
81
  ClaudeContextManager
81
- } from "./chunk-6TL3BYH6.js";
82
- import "./chunk-KVS4XGBQ.js";
82
+ } from "./chunk-64HCHVJM.js";
83
+ import "./chunk-O36JLYNW.js";
83
84
  import "./chunk-TIYJEEVO.js";
84
85
  import {
85
86
  extractSettingsOverrides
86
87
  } from "./chunk-GYCR2LOU.js";
87
88
  import {
88
89
  DefaultBranchNamingService
89
- } from "./chunk-C3AKFAIR.js";
90
+ } from "./chunk-Q457PKGH.js";
90
91
  import {
91
92
  GitCommandError,
92
93
  executeGitCommand,
@@ -116,9 +117,7 @@ import {
116
117
  waitForKeypress
117
118
  } from "./chunk-ZX3GTM7O.js";
118
119
  import "./chunk-433MOLAU.js";
119
- import {
120
- launchClaude
121
- } from "./chunk-FP7G7DG3.js";
120
+ import "./chunk-IGKPPACU.js";
122
121
  import {
123
122
  getLogger,
124
123
  withLogger
@@ -195,6 +194,7 @@ async function launchFirstRunSetup() {
195
194
  var StartCommand = class {
196
195
  constructor(issueTracker, loomManager, _agentManager, settingsManager) {
197
196
  this.loomManager = null;
197
+ this.githubService = null;
198
198
  this.issueTracker = issueTracker;
199
199
  this.settingsManager = settingsManager ?? new SettingsManager();
200
200
  this.providedLoomManager = loomManager;
@@ -206,6 +206,14 @@ var StartCommand = class {
206
206
  getLogger().debug(`Loaded ${Object.keys(envResult.parsed).length} environment variables`);
207
207
  }
208
208
  }
209
+ /**
210
+ * Get or create a GitHubService instance for PR operations
211
+ * Used when the configured issue tracker doesn't support PRs (e.g., Linear)
212
+ */
213
+ getGitHubService() {
214
+ this.githubService ??= new GitHubService();
215
+ return this.githubService;
216
+ }
209
217
  /**
210
218
  * Initialize LoomManager with the main worktree path
211
219
  * Uses lazy initialization to ensure we have the correct path
@@ -400,7 +408,7 @@ var StartCommand = class {
400
408
  throw new Error("Missing required argument: identifier");
401
409
  }
402
410
  const spaceCount = (trimmedIdentifier.match(/ /g) ?? []).length;
403
- if (trimmedIdentifier.length > 25 && spaceCount > 2) {
411
+ if (trimmedIdentifier.length > 25 && spaceCount >= 1) {
404
412
  return {
405
413
  type: "description",
406
414
  originalInput: hasLeadingSpace ? " " + trimmedIdentifier : trimmedIdentifier
@@ -438,24 +446,42 @@ var StartCommand = class {
438
446
  const numericMatch = trimmedIdentifier.match(numericPattern);
439
447
  if (numericMatch == null ? void 0 : numericMatch[1]) {
440
448
  const number = parseInt(numericMatch[1], 10);
441
- const detection = await this.issueTracker.detectInputType(
442
- trimmedIdentifier,
443
- repo
444
- );
445
- if (detection.type === "pr") {
446
- return {
447
- type: "pr",
448
- number: detection.identifier ? parseInt(detection.identifier, 10) : number,
449
- originalInput: trimmedIdentifier
450
- };
451
- } else if (detection.type === "issue") {
452
- return {
453
- type: "issue",
454
- number: detection.identifier ? parseInt(detection.identifier, 10) : number,
455
- originalInput: trimmedIdentifier
456
- };
449
+ if (this.issueTracker.supportsPullRequests) {
450
+ const detection = await this.issueTracker.detectInputType(
451
+ trimmedIdentifier,
452
+ repo
453
+ );
454
+ if (detection.type === "pr") {
455
+ return {
456
+ type: "pr",
457
+ number: detection.identifier ? parseInt(detection.identifier, 10) : number,
458
+ originalInput: trimmedIdentifier
459
+ };
460
+ } else if (detection.type === "issue") {
461
+ return {
462
+ type: "issue",
463
+ number: detection.identifier ? parseInt(detection.identifier, 10) : number,
464
+ originalInput: trimmedIdentifier
465
+ };
466
+ } else {
467
+ throw new Error(`Could not find issue or PR #${number}`);
468
+ }
457
469
  } else {
458
- throw new Error(`Could not find issue or PR #${number}`);
470
+ const githubService = this.getGitHubService();
471
+ const detection = await githubService.detectInputType(trimmedIdentifier, repo);
472
+ if (detection.type === "pr") {
473
+ return {
474
+ type: "pr",
475
+ number: detection.identifier ? parseInt(detection.identifier, 10) : number,
476
+ originalInput: trimmedIdentifier
477
+ };
478
+ } else {
479
+ return {
480
+ type: "issue",
481
+ number,
482
+ originalInput: trimmedIdentifier
483
+ };
484
+ }
459
485
  }
460
486
  }
461
487
  return {
@@ -473,11 +499,14 @@ var StartCommand = class {
473
499
  if (!parsed.number) {
474
500
  throw new Error("Invalid PR number");
475
501
  }
476
- if (!this.issueTracker.supportsPullRequests || !this.issueTracker.fetchPR || !this.issueTracker.validatePRState) {
477
- throw new Error("Issue tracker does not support pull requests");
502
+ if (this.issueTracker.supportsPullRequests && this.issueTracker.fetchPR && this.issueTracker.validatePRState) {
503
+ const pr = await this.issueTracker.fetchPR(parsed.number, repo);
504
+ await this.issueTracker.validatePRState(pr);
505
+ } else {
506
+ const githubService = this.getGitHubService();
507
+ const pr = await githubService.fetchPR(parsed.number, repo);
508
+ await githubService.validatePRState(pr);
478
509
  }
479
- const pr = await this.issueTracker.fetchPR(parsed.number, repo);
480
- await this.issueTracker.validatePRState(pr);
481
510
  getLogger().debug(`Validated PR #${parsed.number}`);
482
511
  break;
483
512
  }
@@ -641,20 +670,18 @@ var AddIssueCommand = class {
641
670
 
642
671
  // src/commands/enhance.ts
643
672
  var EnhanceCommand = class {
644
- constructor(issueTracker, agentManager, settingsManager) {
673
+ constructor(issueTracker, enhancementService, settingsManager) {
645
674
  this.issueTracker = issueTracker;
646
- this.agentManager = agentManager ?? new AgentManager();
675
+ this.enhancementService = enhancementService;
647
676
  this.settingsManager = settingsManager ?? new SettingsManager();
648
677
  }
649
678
  /**
650
679
  * Execute the enhance command workflow:
651
680
  * 1. Validate issue number
652
681
  * 2. Fetch issue to verify it exists
653
- * 3. Load agent configurations
654
- * 4. Invoke Claude CLI with enhancer agent
655
- * 5. Parse response to determine outcome
656
- * 6. Handle browser interaction based on outcome (unless --json mode)
657
- * 7. Return result object when --json mode
682
+ * 3. Invoke enhancement service
683
+ * 4. Handle browser interaction based on outcome (unless --json mode)
684
+ * 5. Return result object when --json mode
658
685
  */
659
686
  async execute(input) {
660
687
  const { issueNumber, options } = input;
@@ -677,41 +704,13 @@ var EnhanceCommand = class {
677
704
  }
678
705
  const issue = await this.issueTracker.fetchIssue(issueNumber, repo);
679
706
  getLogger().debug("Issue fetched successfully", { number: issue.number, title: issue.title });
680
- getLogger().debug("Loading agent configurations...");
681
- const loadedAgents = await this.agentManager.loadAgents(settings);
682
- const agents = this.agentManager.formatForCli(loadedAgents);
683
- let mcpConfig;
684
- let allowedTools;
685
- let disallowedTools;
686
- try {
687
- const provider = this.issueTracker.providerName;
688
- mcpConfig = await generateIssueManagementMcpConfig("issue", repo, provider, settings);
689
- getLogger().debug("Generated MCP configuration for issue management:", { mcpConfig });
690
- allowedTools = [
691
- "mcp__issue_management__get_issue",
692
- "mcp__issue_management__get_comment",
693
- "mcp__issue_management__create_comment",
694
- "mcp__issue_management__update_comment",
695
- "mcp__issue_management__create_issue"
696
- ];
697
- disallowedTools = ["Bash(gh api:*)"];
698
- getLogger().debug("Configured tool filtering for issue workflow", { allowedTools, disallowedTools });
699
- } catch (error) {
700
- getLogger().warn(`Failed to generate MCP config: ${error instanceof Error ? error.message : "Unknown error"}`);
701
- }
702
707
  if (!isJsonMode) {
703
708
  getLogger().info("Invoking enhancer agent. This may take a moment...");
704
709
  }
705
- const prompt = this.constructPrompt(issueNumber, author);
706
- const response = await launchClaude(prompt, {
707
- headless: true,
708
- model: "sonnet",
709
- agents,
710
- ...mcpConfig && { mcpConfig },
711
- ...allowedTools && { allowedTools },
712
- ...disallowedTools && { disallowedTools }
713
- });
714
- const result = this.parseEnhancerResponse(response);
710
+ const enhanceOptions = {};
711
+ if (author !== void 0) enhanceOptions.author = author;
712
+ if (repo !== void 0) enhanceOptions.repo = repo;
713
+ const result = await this.enhancementService.enhanceExistingIssue(issueNumber, enhanceOptions);
715
714
  if (isJsonMode) {
716
715
  const commentId = result.url ? this.extractCommentId(result.url) : 0;
717
716
  const resultData = {
@@ -758,48 +757,6 @@ var EnhanceCommand = class {
758
757
  throw new Error("Issue identifier cannot be empty");
759
758
  }
760
759
  }
761
- /**
762
- * Construct the prompt for the orchestrating Claude instance.
763
- * This prompt is very clear about expected output format to ensure reliable parsing.
764
- */
765
- constructPrompt(issueNumber, author) {
766
- const authorInstruction = author ? `
767
- IMPORTANT: When you create your analysis comment, tag @${author} in the "Questions for Reporter" section if you have questions.
768
- ` : "";
769
- return `Execute @agent-iloom-issue-enhancer ${issueNumber}${authorInstruction}
770
-
771
- ## OUTPUT REQUIREMENTS
772
- * If the issue was not enhanced, return ONLY: "No enhancement needed"
773
- * If the issue WAS enhanced, return ONLY: <FULL URL OF THE COMMENT INCLUDING COMMENT ID>
774
- * If you encounter permission/authentication/access errors, return ONLY: "Permission denied: <specific error description>"
775
- * IMPORTANT: Return ONLY one of the above - DO NOT include commentary such as "I created a comment at <URL>" or "I examined the issue and found no enhancement was necessary"
776
- * CONTEXT: Your output is going to be parsed programmatically, so adherence to the output requirements is CRITICAL.`;
777
- }
778
- /**
779
- * Parse the response from the enhancer agent.
780
- * Returns either { enhanced: false } or { enhanced: true, url: "..." }
781
- * Throws specific errors for permission issues.
782
- */
783
- parseEnhancerResponse(response) {
784
- if (!response || typeof response !== "string") {
785
- throw new Error("No response from enhancer agent");
786
- }
787
- const trimmed = response.trim();
788
- getLogger().debug(`RESPONSE FROM ENHANCER AGENT: '${trimmed}'`);
789
- if (trimmed.toLowerCase().startsWith("permission denied:")) {
790
- const errorMessage = trimmed.substring("permission denied:".length).trim();
791
- throw new Error(`Permission denied: ${errorMessage}`);
792
- }
793
- if (trimmed.toLowerCase().includes("no enhancement needed")) {
794
- return { enhanced: false };
795
- }
796
- const urlPattern = /https:\/\/github\.com\/[^/]+\/[^/]+\/issues\/\d+#issuecomment-\d+/;
797
- const match = trimmed.match(urlPattern);
798
- if (match) {
799
- return { enhanced: true, url: match[0] };
800
- }
801
- throw new Error(`Unexpected response from enhancer agent: ${trimmed}`);
802
- }
803
760
  /**
804
761
  * Prompt user and open browser to view enhanced issue.
805
762
  * Matches the pattern from the issue specification.
@@ -860,7 +817,7 @@ var FinishCommand = class {
860
817
  const neonProvider = createNeonProviderFromSettings(settings);
861
818
  const databaseManager = new DatabaseManager(neonProvider, environmentManager, databaseUrlEnvVarName);
862
819
  const cliIsolationManager = new CLIIsolationManager();
863
- const { DefaultBranchNamingService: DefaultBranchNamingService2 } = await import("./BranchNamingService-FLPUUFOB.js");
820
+ const { DefaultBranchNamingService: DefaultBranchNamingService2 } = await import("./BranchNamingService-AO7BPIUJ.js");
864
821
  this.loomManager ??= new LoomManager(
865
822
  this.gitWorktreeManager,
866
823
  this.issueTracker,
@@ -1283,20 +1240,10 @@ var FinishCommand = class {
1283
1240
  const settings = await this.settingsManager.loadSettings(worktree.path);
1284
1241
  const mergeBehavior = settings.mergeBehavior ?? { mode: "local" };
1285
1242
  if (mergeBehavior.mode === "github-pr") {
1286
- if (!this.issueTracker.supportsPullRequests) {
1287
- throw new Error(
1288
- `The 'github-pr' merge mode requires a GitHub-compatible issue tracker. Your current provider (${this.issueTracker.providerName}) does not support pull requests. Either change mergeBehavior.mode to 'local' in your settings, or use GitHub as your issue tracker.`
1289
- );
1290
- }
1291
1243
  await this.executeGitHubPRWorkflow(parsed, options, worktree, settings, result);
1292
1244
  return;
1293
1245
  }
1294
1246
  if (mergeBehavior.mode === "github-draft-pr") {
1295
- if (!this.issueTracker.supportsPullRequests) {
1296
- throw new Error(
1297
- `The 'github-draft-pr' merge mode requires a GitHub-compatible issue tracker. Your provider (${this.issueTracker.providerName}) does not support pull requests.`
1298
- );
1299
- }
1300
1247
  const { MetadataManager: MetadataManager3 } = await import("./MetadataManager-XJ2YB762.js");
1301
1248
  const metadataManager2 = new MetadataManager3();
1302
1249
  const metadata = await metadataManager2.readMetadata(worktree.path);
@@ -2229,7 +2176,7 @@ function parseIssueIdentifier(value) {
2229
2176
  const parsed = parseInt(value, 10);
2230
2177
  return !isNaN(parsed) && String(parsed) === value ? parsed : value;
2231
2178
  }
2232
- program.name("iloom").description(packageJson.description).version(packageJson.version).option("--debug", "Enable debug output (default: based on ILOOM_DEBUG env var)").option("--completion", "Output shell completion script for current shell").option("--set <key=value>", "Override any setting using dot notation (repeatable, e.g., --set workflows.issue.startIde=false)").allowUnknownOption().hook("preAction", async (thisCommand, actionCommand) => {
2179
+ program.name("iloom").description(packageJson.description).version(packageJson.version).option("--debug", "Enable debug output (default: based on ILOOM_DEBUG env var)").option("--completion", "Output shell completion script for current shell").option("--set <key=value>", "Override any setting using dot notation (repeatable, e.g., --set workflows.issue.startIde=false)").allowUnknownOption().addHelpText("afterAll", "\nBy using iloom, you agree to our Terms of Service: https://iloom.ai/terms").hook("preAction", async (thisCommand, actionCommand) => {
2233
2180
  const options = thisCommand.opts();
2234
2181
  const envDebug = process.env.ILOOM_DEBUG === "true";
2235
2182
  const debugEnabled = options.debug !== void 0 ? options.debug : envDebug;
@@ -2262,7 +2209,7 @@ program.name("iloom").description(packageJson.description).version(packageJson.v
2262
2209
  }
2263
2210
  await validateSettingsForCommand(actionCommand);
2264
2211
  await validateGhCliForCommand(actionCommand);
2265
- await validateIdeForStartCommand(thisCommand);
2212
+ await validateIdeForStartCommand(actionCommand);
2266
2213
  });
2267
2214
  async function validateSettingsForCommand(command) {
2268
2215
  var _a, _b;
@@ -2345,7 +2292,7 @@ async function validateGhCliForCommand(command) {
2345
2292
  }
2346
2293
  async function validateIdeForStartCommand(command) {
2347
2294
  var _a, _b;
2348
- const commandName = command.args[0] ?? "";
2295
+ const commandName = command.name();
2349
2296
  if (commandName !== "start") {
2350
2297
  return;
2351
2298
  }
@@ -2389,7 +2336,7 @@ async function autoLaunchInitForMultipleRemotes() {
2389
2336
  await waitForKeypress2("Press any key to start configuration...");
2390
2337
  logger.info("");
2391
2338
  try {
2392
- const { InitCommand: InitCommand2 } = await import("./init-XQQMFDM6.js");
2339
+ const { InitCommand: InitCommand2 } = await import("./init-S6IEGRSX.js");
2393
2340
  const initCommand = new InitCommand2();
2394
2341
  const customInitialMessage = "Help me configure which git remote iloom should use for GitHub operations. I have multiple remotes and need to select the correct one.";
2395
2342
  await initCommand.execute(customInitialMessage);
@@ -2490,7 +2437,7 @@ program.command("add-issue").alias("a").description("Create and enhance GitHub i
2490
2437
  });
2491
2438
  program.command("feedback").alias("f").description("Submit feedback/bug report to iloom-cli repository").argument("<description>", "Feedback title (>30 chars, >2 spaces; or any non-empty text when --body provided)").option("--body <text>", "Body text for feedback (added after diagnostics)").action(async (description, options) => {
2492
2439
  try {
2493
- const { FeedbackCommand } = await import("./feedback-K3A4QUSG.js");
2440
+ const { FeedbackCommand } = await import("./feedback-ZLAX3BVL.js");
2494
2441
  const command = new FeedbackCommand();
2495
2442
  const feedbackOptions = {};
2496
2443
  if (options.body !== void 0) {
@@ -2513,7 +2460,8 @@ program.command("enhance").description("Apply enhancement agent to existing GitH
2513
2460
  const settingsManager = new SettingsManager();
2514
2461
  const settings = await settingsManager.loadSettings();
2515
2462
  const issueTracker = IssueTrackerFactory.create(settings);
2516
- const command = new EnhanceCommand(issueTracker);
2463
+ const enhancementService = new IssueEnhancementService(issueTracker, new AgentManager(), settingsManager);
2464
+ const command = new EnhanceCommand(issueTracker, enhancementService, settingsManager);
2517
2465
  const result = await command.execute({
2518
2466
  issueNumber,
2519
2467
  options: {
@@ -2574,7 +2522,7 @@ program.command("finish").alias("dn").description("Merge work and cleanup worksp
2574
2522
  program.command("commit").alias("c").description("Commit all uncommitted files with issue reference").option("-m, --message <text>", "Custom commit message (skip Claude generation)").option("--fixes", 'Use "Fixes #N" trailer instead of "Refs #N" (closes issue)').option("--no-review", "Skip commit message review prompt").option("--json", "Output result as JSON (implies --no-review)").option("--wip-commit", "Quick WIP commit: skip validations and pre-commit hooks").action(async (options) => {
2575
2523
  const executeAction = async () => {
2576
2524
  try {
2577
- const { CommitCommand } = await import("./commit-ONRXU67O.js");
2525
+ const { CommitCommand } = await import("./commit-NGMDWWAP.js");
2578
2526
  const command = new CommitCommand();
2579
2527
  const noReview = options.review === false || options.json === true;
2580
2528
  const result = await command.execute({
@@ -2609,7 +2557,7 @@ program.command("commit").alias("c").description("Commit all uncommitted files w
2609
2557
  });
2610
2558
  program.command("rebase").description("Rebase current branch on main with Claude-assisted conflict resolution").option("-f, --force", "Skip confirmation prompts").option("-n, --dry-run", "Preview actions without executing").action(async (options) => {
2611
2559
  try {
2612
- const { RebaseCommand } = await import("./rebase-QYCRF7JG.js");
2560
+ const { RebaseCommand } = await import("./rebase-RLEVFHWN.js");
2613
2561
  const command = new RebaseCommand();
2614
2562
  await command.execute(options);
2615
2563
  } catch (error) {
@@ -2621,7 +2569,7 @@ program.command("spin").alias("ignite").description("Launch Claude with auto-det
2621
2569
  new Option("--one-shot <mode>", "One-shot automation mode").choices(["default", "noReview", "bypassPermissions"]).default("default")
2622
2570
  ).action(async (options) => {
2623
2571
  try {
2624
- const { IgniteCommand } = await import("./ignite-YUAOJ5PP.js");
2572
+ const { IgniteCommand } = await import("./ignite-HA2OJF6Z.js");
2625
2573
  const command = new IgniteCommand();
2626
2574
  await command.execute(options.oneShot ?? "default");
2627
2575
  } catch (error) {
@@ -2632,7 +2580,7 @@ program.command("spin").alias("ignite").description("Launch Claude with auto-det
2632
2580
  program.command("open").description("Open workspace in browser or run CLI tool").argument("[identifier]", "Issue number, PR number, or branch name (auto-detected if omitted)").allowUnknownOption().action(async (identifier, _options, command) => {
2633
2581
  try {
2634
2582
  const args = (command == null ? void 0 : command.args) ? command.args.slice(identifier ? 1 : 0) : [];
2635
- const { OpenCommand } = await import("./open-QI63XQ4F.js");
2583
+ const { OpenCommand } = await import("./open-IN3LUZXX.js");
2636
2584
  const cmd = new OpenCommand();
2637
2585
  const input = identifier ? { identifier, args } : { args };
2638
2586
  await cmd.execute(input);
@@ -2644,7 +2592,7 @@ program.command("open").description("Open workspace in browser or run CLI tool")
2644
2592
  program.command("run").description("Run CLI tool or open workspace in browser").argument("[identifier]", "Issue number, PR number, or branch name (auto-detected if omitted)").allowUnknownOption().action(async (identifier, _options, command) => {
2645
2593
  try {
2646
2594
  const args = (command == null ? void 0 : command.args) ? command.args.slice(identifier ? 1 : 0) : [];
2647
- const { RunCommand } = await import("./run-YDVYORT2.js");
2595
+ const { RunCommand } = await import("./run-QEIS2EH2.js");
2648
2596
  const cmd = new RunCommand();
2649
2597
  const input = identifier ? { identifier, args } : { args };
2650
2598
  await cmd.execute(input);
@@ -2655,7 +2603,7 @@ program.command("run").description("Run CLI tool or open workspace in browser").
2655
2603
  });
2656
2604
  program.command("dev-server").alias("dev").description("Start dev server for workspace (foreground)").argument("[identifier]", "Issue number, PR number, or branch name (auto-detected if omitted)").option("--json", "Output as JSON").action(async (identifier, options) => {
2657
2605
  try {
2658
- const { DevServerCommand } = await import("./dev-server-UKAPBGUR.js");
2606
+ const { DevServerCommand } = await import("./dev-server-OAP3RZC6.js");
2659
2607
  const cmd = new DevServerCommand();
2660
2608
  await cmd.execute({ identifier, json: options == null ? void 0 : options.json });
2661
2609
  } catch (error) {
@@ -2716,7 +2664,7 @@ program.command("compile").alias("typecheck").description("Run the compile or ty
2716
2664
  program.command("cleanup").alias("remove").alias("clean").description("Remove workspaces").argument("[identifier]", "Branch name or issue number to cleanup (auto-detected)").option("-l, --list", "List all worktrees").option("-a, --all", "Remove all worktrees (interactive confirmation)").option("-i, --issue <number>", "Cleanup by issue number", parseInt).option("-f, --force", "Skip confirmations and force removal").option("--dry-run", "Show what would be done without doing it").option("--json", "Output result as JSON").option("--defer <ms>", "Wait specified milliseconds before cleanup", parseInt).action(async (identifier, options) => {
2717
2665
  const executeAction = async () => {
2718
2666
  try {
2719
- const { CleanupCommand } = await import("./cleanup-77U5ATYI.js");
2667
+ const { CleanupCommand } = await import("./cleanup-DB7EFBF3.js");
2720
2668
  const command = new CleanupCommand();
2721
2669
  const input = {
2722
2670
  options: options ?? {}
@@ -2939,7 +2887,7 @@ program.command("list").description("Show active workspaces").option("--json", "
2939
2887
  });
2940
2888
  program.command("projects").description("List configured iloom projects").option("--json", "Output as JSON (default behavior)").action(async (options) => {
2941
2889
  try {
2942
- const { ProjectsCommand } = await import("./projects-TWY4RT2Z.js");
2890
+ const { ProjectsCommand } = await import("./projects-CTRTTMSK.js");
2943
2891
  const command = new ProjectsCommand();
2944
2892
  const result = await command.execute(options);
2945
2893
  console.log(JSON.stringify(result, null, 2));
@@ -2950,7 +2898,7 @@ program.command("projects").description("List configured iloom projects").option
2950
2898
  });
2951
2899
  program.command("init").alias("config").description("Initialize iloom configuration").argument("[prompt]", 'Custom initial message to send to Claude (defaults to "Help me configure iloom settings.")').action(async (prompt) => {
2952
2900
  try {
2953
- const { InitCommand: InitCommand2 } = await import("./init-XQQMFDM6.js");
2901
+ const { InitCommand: InitCommand2 } = await import("./init-S6IEGRSX.js");
2954
2902
  const command = new InitCommand2();
2955
2903
  const trimmedPrompt = prompt == null ? void 0 : prompt.trim();
2956
2904
  const customPrompt = trimmedPrompt && trimmedPrompt.length > 0 ? trimmedPrompt : void 0;
@@ -2983,7 +2931,7 @@ program.command("update").description("Update iloom-cli to the latest version").
2983
2931
  program.command("test-github").description("Test GitHub integration (Issue #3)").argument("<identifier>", "Issue number or PR number").option("--no-claude", "Skip Claude for branch name generation").action(async (identifier, options) => {
2984
2932
  try {
2985
2933
  const { GitHubService: GitHubService2 } = await import("./GitHubService-O7U4UQ7N.js");
2986
- const { DefaultBranchNamingService: DefaultBranchNamingService2 } = await import("./BranchNamingService-FLPUUFOB.js");
2934
+ const { DefaultBranchNamingService: DefaultBranchNamingService2 } = await import("./BranchNamingService-AO7BPIUJ.js");
2987
2935
  logger.info("Testing GitHub Integration\n");
2988
2936
  const service = new GitHubService2();
2989
2937
  const branchNaming = new DefaultBranchNamingService2({ useClaude: options.claude !== false });
@@ -3041,10 +2989,10 @@ program.command("test-github").description("Test GitHub integration (Issue #3)")
3041
2989
  });
3042
2990
  program.command("test-claude").description("Test Claude integration (Issue #10)").option("--detect", "Test Claude CLI detection").option("--version", "Get Claude CLI version").option("--branch <title>", "Test branch name generation with given title").option("--issue <number>", "Issue number for branch generation", "123").option("--launch <prompt>", "Launch Claude with a prompt (headless)").option("--interactive", "Launch Claude interactively (requires --launch)").option("--template <name>", "Test template loading").action(async (options) => {
3043
2991
  try {
3044
- const { detectClaudeCli, getClaudeVersion, generateBranchName, launchClaude: launchClaude2 } = await import("./claude-6H36IBHO.js");
2992
+ const { detectClaudeCli, getClaudeVersion, generateBranchName, launchClaude } = await import("./claude-V4HRPR4Z.js");
3045
2993
  const { PromptTemplateManager } = await import("./PromptTemplateManager-7L3HJQQU.js");
3046
- const { ClaudeService } = await import("./ClaudeService-CRSETT3A.js");
3047
- const { ClaudeContextManager: ClaudeContextManager2 } = await import("./ClaudeContextManager-KE5TBZVZ.js");
2994
+ const { ClaudeService } = await import("./ClaudeService-NDVFQRKC.js");
2995
+ const { ClaudeContextManager: ClaudeContextManager2 } = await import("./ClaudeContextManager-Y2YJC6BU.js");
3048
2996
  logger.info("Testing Claude Integration\n");
3049
2997
  if (options.detect) {
3050
2998
  logger.info("Detecting Claude CLI...");
@@ -3077,11 +3025,11 @@ program.command("test-claude").description("Test Claude integration (Issue #10)"
3077
3025
  logger.info(` Mode: ${options.interactive ? "Interactive" : "Headless"}`);
3078
3026
  if (options.interactive) {
3079
3027
  logger.info(" Launching Claude in new terminal...");
3080
- await launchClaude2(options.launch, { headless: false });
3028
+ await launchClaude(options.launch, { headless: false });
3081
3029
  logger.info(" (Claude should open in a separate process)");
3082
3030
  } else {
3083
3031
  logger.info(" Waiting for response...");
3084
- const result = await launchClaude2(options.launch, { headless: true });
3032
+ const result = await launchClaude(options.launch, { headless: true });
3085
3033
  if (result) {
3086
3034
  logger.success(" Response:");
3087
3035
  logger.info(` ${result.split("\n").join("\n ")}`);
@@ -3155,7 +3103,7 @@ program.command("test-claude").description("Test Claude integration (Issue #10)"
3155
3103
  logger.info("\n7. Testing Claude launch (headless)...");
3156
3104
  logger.info(' Sending test prompt: "Say hello"');
3157
3105
  try {
3158
- const result = await launchClaude2("Say hello", { headless: true });
3106
+ const result = await launchClaude("Say hello", { headless: true });
3159
3107
  if (result) {
3160
3108
  logger.success(" Claude responded successfully");
3161
3109
  logger.info(` Response preview: ${result.substring(0, 100)}...`);
@@ -3179,7 +3127,7 @@ program.command("test-claude").description("Test Claude integration (Issue #10)"
3179
3127
  });
3180
3128
  program.command("test-webserver").description("Test if a web server is running on a workspace port").argument("<issue-number>", "Issue number (port will be calculated as 3000 + issue number)", parseInt).option("--kill", "Kill the web server if detected").action(async (issueNumber, options) => {
3181
3129
  try {
3182
- const { TestWebserverCommand } = await import("./test-webserver-NRMGT2HB.js");
3130
+ const { TestWebserverCommand } = await import("./test-webserver-J6SMNLU2.js");
3183
3131
  const command = new TestWebserverCommand();
3184
3132
  await command.execute({ issueNumber, options });
3185
3133
  } catch (error) {
@@ -3232,7 +3180,7 @@ program.command("test-prefix").description("Test worktree prefix configuration -
3232
3180
  program.command("summary").description("Generate Claude session summary for a loom").argument("[identifier]", "Issue number, PR number (pr/123), or branch name (auto-detected if omitted)").option("--with-comment", "Post summary as a comment to the issue/PR").option("--json", "Output result as JSON").action(async (identifier, options) => {
3233
3181
  const executeAction = async () => {
3234
3182
  try {
3235
- const { SummaryCommand } = await import("./summary-G6L3VAKK.js");
3183
+ const { SummaryCommand } = await import("./summary-2KLNHVTN.js");
3236
3184
  const command = new SummaryCommand();
3237
3185
  const result = await command.execute({ identifier, options });
3238
3186
  if (options.json && result) {