@iloom/cli 0.6.1 → 0.7.0

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 (177) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +35 -18
  3. package/dist/{BranchNamingService-B5PVRR7F.js → BranchNamingService-FLPUUFOB.js} +2 -2
  4. package/dist/ClaudeContextManager-KE5TBZVZ.js +14 -0
  5. package/dist/ClaudeService-CRSETT3A.js +13 -0
  6. package/dist/{GitHubService-S2OGUTDR.js → GitHubService-O7U4UQ7N.js} +3 -3
  7. package/dist/{LoomLauncher-5LFM4LXB.js → LoomLauncher-NL65LSKP.js} +6 -6
  8. package/dist/{MetadataManager-DFI73J3G.js → MetadataManager-XJ2YB762.js} +2 -2
  9. package/dist/PRManager-2ABCWXHW.js +16 -0
  10. package/dist/{ProjectCapabilityDetector-S5FLNCFI.js → ProjectCapabilityDetector-UZYW32SY.js} +3 -3
  11. package/dist/{PromptTemplateManager-C3DK6XZL.js → PromptTemplateManager-7L3HJQQU.js} +2 -2
  12. package/dist/README.md +35 -18
  13. package/dist/{SettingsManager-35F5RUJH.js → SettingsManager-YU4VYPTW.js} +2 -2
  14. package/dist/agents/iloom-issue-analyze-and-plan.md +42 -17
  15. package/dist/agents/iloom-issue-analyzer.md +14 -14
  16. package/dist/agents/iloom-issue-complexity-evaluator.md +38 -15
  17. package/dist/agents/iloom-issue-enhancer.md +15 -15
  18. package/dist/agents/iloom-issue-implementer.md +44 -15
  19. package/dist/agents/iloom-issue-planner.md +121 -17
  20. package/dist/agents/iloom-issue-reviewer.md +15 -15
  21. package/dist/{build-FJVYP7EV.js → build-O2EJHDEW.js} +9 -9
  22. package/dist/{chunk-ZPSTA5PR.js → chunk-3CDWFEGL.js} +2 -2
  23. package/dist/{chunk-VU3QMIP2.js → chunk-453NC377.js} +91 -15
  24. package/dist/chunk-453NC377.js.map +1 -0
  25. package/dist/{chunk-UQIXZ3BA.js → chunk-5V74K5ZA.js} +2 -2
  26. package/dist/{chunk-7WANFUIK.js → chunk-6TL3BYH6.js} +2 -2
  27. package/dist/{chunk-5TXLVEXT.js → chunk-C3AKFAIR.js} +2 -2
  28. package/dist/{chunk-K7SEEHKO.js → chunk-CNSTXBJ3.js} +7 -419
  29. package/dist/chunk-CNSTXBJ3.js.map +1 -0
  30. package/dist/{chunk-VDA5JMB4.js → chunk-EPPPDVHD.js} +21 -8
  31. package/dist/chunk-EPPPDVHD.js.map +1 -0
  32. package/dist/{chunk-LVBRMTE6.js → chunk-FEAJR6PN.js} +6 -6
  33. package/dist/{chunk-6YSFTPKW.js → chunk-FM4KBPVA.js} +18 -13
  34. package/dist/chunk-FM4KBPVA.js.map +1 -0
  35. package/dist/{chunk-AEIMYF4P.js → chunk-FP7G7DG3.js} +6 -2
  36. package/dist/chunk-FP7G7DG3.js.map +1 -0
  37. package/dist/{chunk-LT3SGBR7.js → chunk-GCPAZSGV.js} +36 -2
  38. package/dist/{chunk-LT3SGBR7.js.map → chunk-GCPAZSGV.js.map} +1 -1
  39. package/dist/chunk-GJMEKEI5.js +517 -0
  40. package/dist/chunk-GJMEKEI5.js.map +1 -0
  41. package/dist/{chunk-64O2UIWO.js → chunk-GV5X6XUE.js} +4 -4
  42. package/dist/{chunk-7Q66W4OH.js → chunk-HBJITKSZ.js} +37 -1
  43. package/dist/chunk-HBJITKSZ.js.map +1 -0
  44. package/dist/{chunk-7HIRPCKU.js → chunk-HVQNVRAF.js} +2 -2
  45. package/dist/{chunk-BXCPJJYM.js → chunk-ITN64ENQ.js} +1 -1
  46. package/dist/chunk-ITN64ENQ.js.map +1 -0
  47. package/dist/{chunk-6U6VI4SZ.js → chunk-KVS4XGBQ.js} +4 -4
  48. package/dist/{chunk-AXX3QIKK.js → chunk-LLWX3PCW.js} +2 -2
  49. package/dist/{chunk-2A7WQKBE.js → chunk-LQBLDI47.js} +96 -6
  50. package/dist/chunk-LQBLDI47.js.map +1 -0
  51. package/dist/{chunk-SN3Z6EZO.js → chunk-N7FVXZNI.js} +2 -2
  52. package/dist/chunk-NTIZLX42.js +822 -0
  53. package/dist/chunk-NTIZLX42.js.map +1 -0
  54. package/dist/{chunk-I75JMBNB.js → chunk-S7YMZQUD.js} +31 -43
  55. package/dist/chunk-S7YMZQUD.js.map +1 -0
  56. package/dist/chunk-TIYJEEVO.js +79 -0
  57. package/dist/chunk-TIYJEEVO.js.map +1 -0
  58. package/dist/{chunk-EK3XCAAS.js → chunk-UDRZY65Y.js} +2 -2
  59. package/dist/{chunk-3PT7RKL5.js → chunk-USJSNHGG.js} +2 -2
  60. package/dist/{chunk-CFUWQHCJ.js → chunk-VWGKGNJP.js} +114 -35
  61. package/dist/chunk-VWGKGNJP.js.map +1 -0
  62. package/dist/{chunk-F6WVM437.js → chunk-WFQ5CLTR.js} +6 -3
  63. package/dist/chunk-WFQ5CLTR.js.map +1 -0
  64. package/dist/{chunk-TRQ76ISK.js → chunk-Z6BO53V7.js} +9 -9
  65. package/dist/{chunk-GEXP5IOF.js → chunk-ZA575VLF.js} +21 -8
  66. package/dist/chunk-ZA575VLF.js.map +1 -0
  67. package/dist/{claude-H33OQMXO.js → claude-6H36IBHO.js} +4 -2
  68. package/dist/{cleanup-BRUAINKE.js → cleanup-ZPOMRSNN.js} +20 -16
  69. package/dist/cleanup-ZPOMRSNN.js.map +1 -0
  70. package/dist/cli.js +341 -954
  71. package/dist/cli.js.map +1 -1
  72. package/dist/commit-6S2RIA2K.js +237 -0
  73. package/dist/commit-6S2RIA2K.js.map +1 -0
  74. package/dist/{compile-ULNO5F7Q.js → compile-LRMAADUT.js} +9 -9
  75. package/dist/{contribute-Q6GX6AXK.js → contribute-GXKOIA42.js} +5 -5
  76. package/dist/{dev-server-4RCDJ5MU.js → dev-server-GREJUEKW.js} +22 -74
  77. package/dist/dev-server-GREJUEKW.js.map +1 -0
  78. package/dist/{feedback-O4Q55SVS.js → feedback-G7G5QCY4.js} +10 -10
  79. package/dist/{git-FVMGBHC2.js → git-ENLT2VNI.js} +6 -4
  80. package/dist/hooks/iloom-hook.js +30 -2
  81. package/dist/{ignite-VHV65WEZ.js → ignite-YUAOJ5PP.js} +20 -20
  82. package/dist/ignite-YUAOJ5PP.js.map +1 -0
  83. package/dist/index.d.ts +71 -27
  84. package/dist/index.js +196 -266
  85. package/dist/index.js.map +1 -1
  86. package/dist/init-XQQMFDM6.js +21 -0
  87. package/dist/{lint-5JMCWE4Y.js → lint-OFVN7FT6.js} +9 -9
  88. package/dist/mcp/issue-management-server.js +359 -13
  89. package/dist/mcp/issue-management-server.js.map +1 -1
  90. package/dist/mcp/recap-server.js +13 -4
  91. package/dist/mcp/recap-server.js.map +1 -1
  92. package/dist/{open-WHVUYGPY.js → open-MCWQAPSZ.js} +25 -76
  93. package/dist/open-MCWQAPSZ.js.map +1 -0
  94. package/dist/{projects-SA76I4TZ.js → projects-PQOTWUII.js} +11 -4
  95. package/dist/projects-PQOTWUII.js.map +1 -0
  96. package/dist/prompts/init-prompt.txt +62 -51
  97. package/dist/prompts/issue-prompt.txt +132 -63
  98. package/dist/prompts/pr-prompt.txt +3 -3
  99. package/dist/prompts/regular-prompt.txt +16 -18
  100. package/dist/prompts/session-summary-prompt.txt +13 -13
  101. package/dist/{rebase-Y4AS6LQW.js → rebase-RKQED567.js} +53 -8
  102. package/dist/rebase-RKQED567.js.map +1 -0
  103. package/dist/{recap-VOOUXOGP.js → recap-ZKGHZCX6.js} +6 -6
  104. package/dist/{run-NCRK5NPR.js → run-CCG24PBC.js} +25 -76
  105. package/dist/run-CCG24PBC.js.map +1 -0
  106. package/dist/schema/settings.schema.json +14 -3
  107. package/dist/{shell-SBLXVOVJ.js → shell-2NNSIU34.js} +6 -6
  108. package/dist/{summary-CVFAMDOJ.js → summary-G6L3VAKK.js} +11 -10
  109. package/dist/{summary-CVFAMDOJ.js.map → summary-G6L3VAKK.js.map} +1 -1
  110. package/dist/{test-3KIVXI6J.js → test-QZDOEUIO.js} +9 -9
  111. package/dist/{test-git-ZB6AGGRW.js → test-git-E2BLXR6M.js} +4 -4
  112. package/dist/{test-prefix-FBGXKMPA.js → test-prefix-A7JGGYAA.js} +4 -4
  113. package/dist/{test-webserver-YVQD42W6.js → test-webserver-NRMGT2HB.js} +29 -8
  114. package/dist/test-webserver-NRMGT2HB.js.map +1 -0
  115. package/package.json +3 -1
  116. package/dist/ClaudeContextManager-6J2EB4QU.js +0 -14
  117. package/dist/ClaudeService-O2PB22GX.js +0 -13
  118. package/dist/PRManager-GB3FOJ2W.js +0 -14
  119. package/dist/chunk-2A7WQKBE.js.map +0 -1
  120. package/dist/chunk-6YSFTPKW.js.map +0 -1
  121. package/dist/chunk-7Q66W4OH.js.map +0 -1
  122. package/dist/chunk-AEIMYF4P.js.map +0 -1
  123. package/dist/chunk-BXCPJJYM.js.map +0 -1
  124. package/dist/chunk-CFUWQHCJ.js.map +0 -1
  125. package/dist/chunk-F6WVM437.js.map +0 -1
  126. package/dist/chunk-GEXP5IOF.js.map +0 -1
  127. package/dist/chunk-I75JMBNB.js.map +0 -1
  128. package/dist/chunk-K7SEEHKO.js.map +0 -1
  129. package/dist/chunk-VDA5JMB4.js.map +0 -1
  130. package/dist/chunk-VU3QMIP2.js.map +0 -1
  131. package/dist/chunk-W6WVRHJ6.js +0 -251
  132. package/dist/chunk-W6WVRHJ6.js.map +0 -1
  133. package/dist/cleanup-BRUAINKE.js.map +0 -1
  134. package/dist/dev-server-4RCDJ5MU.js.map +0 -1
  135. package/dist/ignite-VHV65WEZ.js.map +0 -1
  136. package/dist/init-UTYRHNJJ.js +0 -21
  137. package/dist/open-WHVUYGPY.js.map +0 -1
  138. package/dist/projects-SA76I4TZ.js.map +0 -1
  139. package/dist/rebase-Y4AS6LQW.js.map +0 -1
  140. package/dist/run-NCRK5NPR.js.map +0 -1
  141. package/dist/test-webserver-YVQD42W6.js.map +0 -1
  142. /package/dist/{BranchNamingService-B5PVRR7F.js.map → BranchNamingService-FLPUUFOB.js.map} +0 -0
  143. /package/dist/{ClaudeContextManager-6J2EB4QU.js.map → ClaudeContextManager-KE5TBZVZ.js.map} +0 -0
  144. /package/dist/{ClaudeService-O2PB22GX.js.map → ClaudeService-CRSETT3A.js.map} +0 -0
  145. /package/dist/{GitHubService-S2OGUTDR.js.map → GitHubService-O7U4UQ7N.js.map} +0 -0
  146. /package/dist/{LoomLauncher-5LFM4LXB.js.map → LoomLauncher-NL65LSKP.js.map} +0 -0
  147. /package/dist/{MetadataManager-DFI73J3G.js.map → MetadataManager-XJ2YB762.js.map} +0 -0
  148. /package/dist/{PRManager-GB3FOJ2W.js.map → PRManager-2ABCWXHW.js.map} +0 -0
  149. /package/dist/{ProjectCapabilityDetector-S5FLNCFI.js.map → ProjectCapabilityDetector-UZYW32SY.js.map} +0 -0
  150. /package/dist/{PromptTemplateManager-C3DK6XZL.js.map → PromptTemplateManager-7L3HJQQU.js.map} +0 -0
  151. /package/dist/{SettingsManager-35F5RUJH.js.map → SettingsManager-YU4VYPTW.js.map} +0 -0
  152. /package/dist/{build-FJVYP7EV.js.map → build-O2EJHDEW.js.map} +0 -0
  153. /package/dist/{chunk-ZPSTA5PR.js.map → chunk-3CDWFEGL.js.map} +0 -0
  154. /package/dist/{chunk-UQIXZ3BA.js.map → chunk-5V74K5ZA.js.map} +0 -0
  155. /package/dist/{chunk-7WANFUIK.js.map → chunk-6TL3BYH6.js.map} +0 -0
  156. /package/dist/{chunk-5TXLVEXT.js.map → chunk-C3AKFAIR.js.map} +0 -0
  157. /package/dist/{chunk-LVBRMTE6.js.map → chunk-FEAJR6PN.js.map} +0 -0
  158. /package/dist/{chunk-64O2UIWO.js.map → chunk-GV5X6XUE.js.map} +0 -0
  159. /package/dist/{chunk-7HIRPCKU.js.map → chunk-HVQNVRAF.js.map} +0 -0
  160. /package/dist/{chunk-6U6VI4SZ.js.map → chunk-KVS4XGBQ.js.map} +0 -0
  161. /package/dist/{chunk-AXX3QIKK.js.map → chunk-LLWX3PCW.js.map} +0 -0
  162. /package/dist/{chunk-SN3Z6EZO.js.map → chunk-N7FVXZNI.js.map} +0 -0
  163. /package/dist/{chunk-EK3XCAAS.js.map → chunk-UDRZY65Y.js.map} +0 -0
  164. /package/dist/{chunk-3PT7RKL5.js.map → chunk-USJSNHGG.js.map} +0 -0
  165. /package/dist/{chunk-TRQ76ISK.js.map → chunk-Z6BO53V7.js.map} +0 -0
  166. /package/dist/{claude-H33OQMXO.js.map → claude-6H36IBHO.js.map} +0 -0
  167. /package/dist/{compile-ULNO5F7Q.js.map → compile-LRMAADUT.js.map} +0 -0
  168. /package/dist/{contribute-Q6GX6AXK.js.map → contribute-GXKOIA42.js.map} +0 -0
  169. /package/dist/{feedback-O4Q55SVS.js.map → feedback-G7G5QCY4.js.map} +0 -0
  170. /package/dist/{git-FVMGBHC2.js.map → git-ENLT2VNI.js.map} +0 -0
  171. /package/dist/{init-UTYRHNJJ.js.map → init-XQQMFDM6.js.map} +0 -0
  172. /package/dist/{lint-5JMCWE4Y.js.map → lint-OFVN7FT6.js.map} +0 -0
  173. /package/dist/{recap-VOOUXOGP.js.map → recap-ZKGHZCX6.js.map} +0 -0
  174. /package/dist/{shell-SBLXVOVJ.js.map → shell-2NNSIU34.js.map} +0 -0
  175. /package/dist/{test-3KIVXI6J.js.map → test-QZDOEUIO.js.map} +0 -0
  176. /package/dist/{test-git-ZB6AGGRW.js.map → test-git-E2BLXR6M.js.map} +0 -0
  177. /package/dist/{test-prefix-FBGXKMPA.js.map → test-prefix-A7JGGYAA.js.map} +0 -0
@@ -0,0 +1,237 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ CommitManager,
4
+ ValidationRunner
5
+ } from "./chunk-NTIZLX42.js";
6
+ import "./chunk-LLWX3PCW.js";
7
+ import {
8
+ GitWorktreeManager
9
+ } from "./chunk-UDRZY65Y.js";
10
+ import "./chunk-ITN64ENQ.js";
11
+ import {
12
+ IssueManagementProviderFactory
13
+ } from "./chunk-GJMEKEI5.js";
14
+ import "./chunk-HBJITKSZ.js";
15
+ import {
16
+ extractIssueNumber,
17
+ getWorktreeRoot,
18
+ isValidGitRepo
19
+ } from "./chunk-ZA575VLF.js";
20
+ import {
21
+ SettingsManager
22
+ } from "./chunk-WFQ5CLTR.js";
23
+ import {
24
+ MetadataManager
25
+ } from "./chunk-VWGKGNJP.js";
26
+ import "./chunk-GCPAZSGV.js";
27
+ import "./chunk-ZX3GTM7O.js";
28
+ import "./chunk-FP7G7DG3.js";
29
+ import {
30
+ getLogger
31
+ } from "./chunk-6MLEBAYZ.js";
32
+ import "./chunk-VT4PDUYT.js";
33
+
34
+ // src/commands/commit.ts
35
+ import path from "path";
36
+ var WorktreeValidationError = class extends Error {
37
+ constructor(message, suggestion) {
38
+ super(message);
39
+ this.suggestion = suggestion;
40
+ this.name = "WorktreeValidationError";
41
+ }
42
+ };
43
+ var CommitCommand = class {
44
+ constructor(gitWorktreeManager = new GitWorktreeManager(), commitManager = new CommitManager(), settingsManager = new SettingsManager(), metadataManager = new MetadataManager(), validationRunner = new ValidationRunner()) {
45
+ this.gitWorktreeManager = gitWorktreeManager;
46
+ this.commitManager = commitManager;
47
+ this.settingsManager = settingsManager;
48
+ this.metadataManager = metadataManager;
49
+ this.validationRunner = validationRunner;
50
+ }
51
+ /**
52
+ * Execute the commit command
53
+ *
54
+ * @param input - Command input containing options
55
+ * @returns CommitResult when in JSON mode, void otherwise
56
+ */
57
+ async execute(input) {
58
+ var _a, _b, _c;
59
+ const logger = getLogger();
60
+ process.env.ILOOM = "1";
61
+ let worktreePath;
62
+ try {
63
+ worktreePath = await this.validateWorktreeContext();
64
+ } catch (error) {
65
+ if (error instanceof WorktreeValidationError) {
66
+ logger.error(error.message);
67
+ logger.info(error.suggestion);
68
+ throw error;
69
+ }
70
+ throw error;
71
+ }
72
+ const detected = await this.autoDetectIssue(worktreePath);
73
+ let trailerType = "Refs";
74
+ if (input.fixes) {
75
+ if (detected.loomType === "branch") {
76
+ logger.warn("--fixes flag ignored: not in an issue or PR worktree");
77
+ } else {
78
+ trailerType = "Fixes";
79
+ }
80
+ }
81
+ const status = await this.commitManager.detectUncommittedChanges(worktreePath);
82
+ if (!status.hasUncommittedChanges) {
83
+ logger.info("No uncommitted changes to commit");
84
+ if (input.json) {
85
+ return {
86
+ success: true,
87
+ trailerType,
88
+ issueNumber: detected.issueNumber
89
+ };
90
+ }
91
+ return;
92
+ }
93
+ let validationPassed = false;
94
+ if (!input.wipCommit) {
95
+ logger.info("Running pre-commit validations...");
96
+ const validationResult = await this.validationRunner.runValidations(worktreePath, {
97
+ dryRun: false
98
+ });
99
+ if (!validationResult.success) {
100
+ throw new Error("Validation failed. Fix errors before committing.");
101
+ }
102
+ logger.success("All validations passed");
103
+ validationPassed = true;
104
+ }
105
+ const settings = await this.settingsManager.loadSettings(worktreePath);
106
+ const providerType = ((_a = settings.issueManagement) == null ? void 0 : _a.provider) ?? "github";
107
+ const issuePrefix = IssueManagementProviderFactory.create(providerType).issuePrefix;
108
+ const shouldSkipVerify = input.wipCommit === true || validationPassed && (((_c = (_b = settings.workflows) == null ? void 0 : _b.issue) == null ? void 0 : _c.noVerify) ?? false);
109
+ let commitMessage = input.message;
110
+ if (input.wipCommit && !input.message) {
111
+ if (detected.issueNumber !== void 0) {
112
+ commitMessage = `WIP commit for Issue ${issuePrefix}${detected.issueNumber}`;
113
+ } else {
114
+ commitMessage = "WIP commit";
115
+ }
116
+ logger.debug(`Using hardcoded WIP message: ${commitMessage}`);
117
+ }
118
+ const commitOptions = {
119
+ issuePrefix,
120
+ skipVerify: shouldSkipVerify,
121
+ skipVerifySilent: input.wipCommit === true,
122
+ // Don't warn for --wip-commit
123
+ noReview: input.noReview ?? false,
124
+ trailerType,
125
+ ...commitMessage && { message: commitMessage },
126
+ ...detected.issueNumber !== void 0 && { issueNumber: detected.issueNumber }
127
+ };
128
+ const commitResult = await this.commitManager.commitChanges(worktreePath, commitOptions);
129
+ logger.success("Changes committed successfully");
130
+ if (input.json) {
131
+ return {
132
+ success: true,
133
+ trailerType,
134
+ issueNumber: detected.issueNumber,
135
+ message: commitResult == null ? void 0 : commitResult.message
136
+ };
137
+ }
138
+ }
139
+ /**
140
+ * Validate that the current directory is within an iloom-managed worktree
141
+ * Returns the worktree root path if valid
142
+ * @throws WorktreeValidationError if validation fails
143
+ */
144
+ async validateWorktreeContext() {
145
+ const currentDir = process.cwd();
146
+ const isGitRepo = await isValidGitRepo(currentDir);
147
+ if (!isGitRepo) {
148
+ throw new WorktreeValidationError(
149
+ "Not a git repository.",
150
+ "Run 'il commit' from within an iloom worktree created by 'il start'."
151
+ );
152
+ }
153
+ const worktreeRoot = await getWorktreeRoot(currentDir);
154
+ if (!worktreeRoot) {
155
+ throw new WorktreeValidationError(
156
+ "Could not determine repository root.",
157
+ "Run 'il commit' from within an iloom worktree created by 'il start'."
158
+ );
159
+ }
160
+ const worktrees = await this.gitWorktreeManager.listWorktrees();
161
+ const currentWorktree = worktrees.find((wt) => wt.path === worktreeRoot);
162
+ if (!currentWorktree) {
163
+ throw new WorktreeValidationError(
164
+ "This directory is not an iloom worktree.",
165
+ "Run 'il commit' from within a worktree created by 'il start <issue>'. Use 'il list' to see available worktrees."
166
+ );
167
+ }
168
+ const isMain = await this.gitWorktreeManager.isMainWorktree(currentWorktree, this.settingsManager);
169
+ if (isMain) {
170
+ throw new WorktreeValidationError(
171
+ "Cannot use il commit from the main worktree.",
172
+ "Navigate to a feature worktree created by 'il start <issue>' and run 'il commit' from there."
173
+ );
174
+ }
175
+ return worktreeRoot;
176
+ }
177
+ /**
178
+ * Auto-detect issue from current directory
179
+ * Similar to SummaryCommand.autoDetectFromCurrentDirectory()
180
+ */
181
+ async autoDetectIssue(worktreePath) {
182
+ var _a, _b, _c, _d, _e;
183
+ const logger = getLogger();
184
+ const currentDir = path.basename(worktreePath);
185
+ const prPattern = /_pr_(\d+)$/;
186
+ const prMatch = currentDir.match(prPattern);
187
+ if (prMatch == null ? void 0 : prMatch[1]) {
188
+ const prNumber = parseInt(prMatch[1], 10);
189
+ logger.debug(`Auto-detected PR #${prNumber} from directory: ${currentDir}`);
190
+ const metadata2 = await this.metadataManager.readMetadata(worktreePath);
191
+ return {
192
+ issueNumber: ((_a = metadata2 == null ? void 0 : metadata2.pr_numbers) == null ? void 0 : _a[0]) ?? prNumber,
193
+ loomType: "pr"
194
+ };
195
+ }
196
+ const issueNumber = extractIssueNumber(currentDir);
197
+ if (issueNumber !== null) {
198
+ logger.debug(`Auto-detected issue #${issueNumber} from directory: ${currentDir}`);
199
+ const metadata2 = await this.metadataManager.readMetadata(worktreePath);
200
+ return {
201
+ issueNumber: ((_b = metadata2 == null ? void 0 : metadata2.issue_numbers) == null ? void 0 : _b[0]) ?? issueNumber,
202
+ loomType: (metadata2 == null ? void 0 : metadata2.issueType) ?? "issue"
203
+ };
204
+ }
205
+ const repoInfo = await this.gitWorktreeManager.getRepoInfo();
206
+ const currentBranch = repoInfo.currentBranch;
207
+ if (currentBranch) {
208
+ const branchIssueNumber = extractIssueNumber(currentBranch);
209
+ if (branchIssueNumber !== null) {
210
+ logger.debug(`Auto-detected issue #${branchIssueNumber} from branch: ${currentBranch}`);
211
+ const metadata2 = await this.metadataManager.readMetadata(worktreePath);
212
+ return {
213
+ issueNumber: ((_c = metadata2 == null ? void 0 : metadata2.issue_numbers) == null ? void 0 : _c[0]) ?? branchIssueNumber,
214
+ loomType: (metadata2 == null ? void 0 : metadata2.issueType) ?? "issue"
215
+ };
216
+ }
217
+ }
218
+ logger.debug("No issue number detected, treating as branch loom");
219
+ const metadata = await this.metadataManager.readMetadata(worktreePath);
220
+ let resolvedIssueNumber;
221
+ const loomType = (metadata == null ? void 0 : metadata.issueType) ?? "branch";
222
+ if (loomType === "issue" && ((_d = metadata == null ? void 0 : metadata.issue_numbers) == null ? void 0 : _d[0])) {
223
+ resolvedIssueNumber = metadata.issue_numbers[0];
224
+ } else if (loomType === "pr" && ((_e = metadata == null ? void 0 : metadata.pr_numbers) == null ? void 0 : _e[0])) {
225
+ resolvedIssueNumber = metadata.pr_numbers[0];
226
+ }
227
+ return {
228
+ issueNumber: resolvedIssueNumber,
229
+ loomType
230
+ };
231
+ }
232
+ };
233
+ export {
234
+ CommitCommand,
235
+ WorktreeValidationError
236
+ };
237
+ //# sourceMappingURL=commit-6S2RIA2K.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/commit.ts"],"sourcesContent":["import path from 'path'\nimport { GitWorktreeManager } from '../lib/GitWorktreeManager.js'\nimport { CommitManager } from '../lib/CommitManager.js'\nimport { SettingsManager } from '../lib/SettingsManager.js'\nimport { MetadataManager } from '../lib/MetadataManager.js'\nimport { ValidationRunner } from '../lib/ValidationRunner.js'\nimport { IssueManagementProviderFactory } from '../mcp/IssueManagementProviderFactory.js'\nimport { getLogger } from '../utils/logger-context.js'\nimport { extractIssueNumber, isValidGitRepo, getWorktreeRoot } from '../utils/git.js'\nimport type { CommitOptions } from '../types/index.js'\n\n/**\n * Input options for the commit command\n */\nexport interface CommitCommandInput {\n\tmessage?: string | undefined // Custom commit message (skip Claude generation)\n\tfixes?: boolean | undefined // Use \"Fixes #N\" trailer instead of \"Refs #N\"\n\tnoReview?: boolean | undefined // Skip commit message review prompt\n\tjson?: boolean | undefined // Output result as JSON\n\twipCommit?: boolean | undefined // Quick WIP commit: skip validations and pre-commit hooks\n}\n\n/**\n * Result of commit operation (returned in JSON mode)\n */\nexport interface CommitResult {\n\tsuccess: boolean\n\tcommitHash?: string | undefined\n\tmessage?: string | undefined\n\tfilesChanged?: number | undefined\n\tissueNumber?: string | number | undefined\n\ttrailerType: 'Refs' | 'Fixes'\n}\n\n/**\n * Error thrown when the commit command is run from an invalid location\n */\nexport class WorktreeValidationError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic readonly suggestion: string\n\t) {\n\t\tsuper(message)\n\t\tthis.name = 'WorktreeValidationError'\n\t}\n}\n\n/**\n * CommitCommand: Commit all uncommitted files with issue reference\n *\n * This command:\n * 1. Validates the current directory is an iloom-managed worktree\n * 2. Auto-detects the issue number from the worktree path/branch\n * 3. Commits all uncommitted changes with a Claude-generated or fallback message\n * 4. Uses \"Refs #N\" trailer by default (keeps issue open)\n * 5. Uses \"Fixes #N\" trailer with --fixes flag (closes issue)\n */\nexport class CommitCommand {\n\tconstructor(\n\t\tprivate gitWorktreeManager = new GitWorktreeManager(),\n\t\tprivate commitManager = new CommitManager(),\n\t\tprivate settingsManager = new SettingsManager(),\n\t\tprivate metadataManager = new MetadataManager(),\n\t\tprivate validationRunner = new ValidationRunner()\n\t) {}\n\n\t/**\n\t * Execute the commit command\n\t *\n\t * @param input - Command input containing options\n\t * @returns CommitResult when in JSON mode, void otherwise\n\t */\n\tasync execute(input: CommitCommandInput): Promise<CommitResult | void> {\n\t\tconst logger = getLogger()\n\n\t\t// Set ILOOM=1 so hooks know this is an iloom session\n\t\tprocess.env.ILOOM = '1'\n\n\t\t// Step 1: Validate worktree context\n\t\tlet worktreePath: string\n\t\ttry {\n\t\t\tworktreePath = await this.validateWorktreeContext()\n\t\t} catch (error) {\n\t\t\tif (error instanceof WorktreeValidationError) {\n\t\t\t\tlogger.error(error.message)\n\t\t\t\tlogger.info(error.suggestion)\n\t\t\t\tthrow error\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\n\t\t// Step 2: Auto-detect issue from current directory\n\t\tconst detected = await this.autoDetectIssue(worktreePath)\n\n\t\t// Step 3: Determine trailer type\n\t\tlet trailerType: 'Refs' | 'Fixes' = 'Refs' // Default to Refs\n\t\tif (input.fixes) {\n\t\t\tif (detected.loomType === 'branch') {\n\t\t\t\t// Warn and ignore --fixes for branch looms (no issue to close)\n\t\t\t\tlogger.warn('--fixes flag ignored: not in an issue or PR worktree')\n\t\t\t} else {\n\t\t\t\ttrailerType = 'Fixes'\n\t\t\t}\n\t\t}\n\n\t\t// Step 4: Check for uncommitted changes\n\t\tconst status = await this.commitManager.detectUncommittedChanges(worktreePath)\n\t\tif (!status.hasUncommittedChanges) {\n\t\t\tlogger.info('No uncommitted changes to commit')\n\t\t\tif (input.json) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\ttrailerType,\n\t\t\t\t\tissueNumber: detected.issueNumber,\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\t// Step 5: Run validations unless --wip-commit is specified\n\t\tlet validationPassed = false\n\t\tif (!input.wipCommit) {\n\t\t\tlogger.info('Running pre-commit validations...')\n\t\t\tconst validationResult = await this.validationRunner.runValidations(worktreePath, {\n\t\t\t\tdryRun: false,\n\t\t\t})\n\t\t\tif (!validationResult.success) {\n\t\t\t\tthrow new Error('Validation failed. Fix errors before committing.')\n\t\t\t}\n\t\t\tlogger.success('All validations passed')\n\t\t\tvalidationPassed = true\n\t\t}\n\n\t\t// Step 6: Load settings to get issue prefix\n\t\tconst settings = await this.settingsManager.loadSettings(worktreePath)\n\t\tconst providerType = settings.issueManagement?.provider ?? 'github'\n\t\tconst issuePrefix = IssueManagementProviderFactory.create(providerType).issuePrefix\n\n\t\t// Determine whether to skip pre-commit hooks:\n\t\t// - With --wip-commit: always skip hooks (quick WIP commit)\n\t\t// - Otherwise: skip hooks only if validation passed AND noVerify setting is enabled\n\t\tconst shouldSkipVerify = input.wipCommit === true || (validationPassed && (settings.workflows?.issue?.noVerify ?? false))\n\n\t\t// Step 7: Determine commit message\n\t\t// For --wip-commit without a custom message, use a hardcoded WIP message to skip Claude generation\n\t\tlet commitMessage: string | undefined = input.message\n\t\tif (input.wipCommit && !input.message) {\n\t\t\tif (detected.issueNumber !== undefined) {\n\t\t\t\tcommitMessage = `WIP commit for Issue ${issuePrefix}${detected.issueNumber}`\n\t\t\t} else {\n\t\t\t\tcommitMessage = 'WIP commit'\n\t\t\t}\n\t\t\tlogger.debug(`Using hardcoded WIP message: ${commitMessage}`)\n\t\t}\n\n\t\t// Step 8: Build commit options\n\t\tconst commitOptions: CommitOptions = {\n\t\t\tissuePrefix,\n\t\t\tskipVerify: shouldSkipVerify,\n\t\t\tskipVerifySilent: input.wipCommit === true, // Don't warn for --wip-commit\n\t\t\tnoReview: input.noReview ?? false,\n\t\t\ttrailerType,\n\t\t\t...(commitMessage && { message: commitMessage }),\n\t\t\t...(detected.issueNumber !== undefined && { issueNumber: detected.issueNumber }),\n\t\t}\n\n\t\t// Step 9: Commit changes\n\t\tconst commitResult = await this.commitManager.commitChanges(worktreePath, commitOptions)\n\t\tlogger.success('Changes committed successfully')\n\n\t\t// Step 10: Return result in JSON mode\n\t\tif (input.json) {\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\ttrailerType,\n\t\t\t\tissueNumber: detected.issueNumber,\n\t\t\t\tmessage: commitResult?.message,\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Validate that the current directory is within an iloom-managed worktree\n\t * Returns the worktree root path if valid\n\t * @throws WorktreeValidationError if validation fails\n\t */\n\tprivate async validateWorktreeContext(): Promise<string> {\n\t\tconst currentDir = process.cwd()\n\n\t\t// Step 1: Check if we're in a git repository at all\n\t\tconst isGitRepo = await isValidGitRepo(currentDir)\n\t\tif (!isGitRepo) {\n\t\t\tthrow new WorktreeValidationError(\n\t\t\t\t'Not a git repository.',\n\t\t\t\t\"Run 'il commit' from within an iloom worktree created by 'il start'.\"\n\t\t\t)\n\t\t}\n\n\t\t// Step 2: Get the worktree root (handles subdirectories)\n\t\tconst worktreeRoot = await getWorktreeRoot(currentDir)\n\t\tif (!worktreeRoot) {\n\t\t\tthrow new WorktreeValidationError(\n\t\t\t\t'Could not determine repository root.',\n\t\t\t\t\"Run 'il commit' from within an iloom worktree created by 'il start'.\"\n\t\t\t)\n\t\t}\n\n\t\t// Step 3: Check if this path is a registered git worktree\n\t\tconst worktrees = await this.gitWorktreeManager.listWorktrees()\n\t\tconst currentWorktree = worktrees.find(wt => wt.path === worktreeRoot)\n\n\t\tif (!currentWorktree) {\n\t\t\tthrow new WorktreeValidationError(\n\t\t\t\t'This directory is not an iloom worktree.',\n\t\t\t\t\"Run 'il commit' from within a worktree created by 'il start <issue>'. Use 'il list' to see available worktrees.\"\n\t\t\t)\n\t\t}\n\n\t\t// Step 4: Check if this is the main worktree (we shouldn't commit from main with issue trailers)\n\t\tconst isMain = await this.gitWorktreeManager.isMainWorktree(currentWorktree, this.settingsManager)\n\t\tif (isMain) {\n\t\t\tthrow new WorktreeValidationError(\n\t\t\t\t'Cannot use il commit from the main worktree.',\n\t\t\t\t\"Navigate to a feature worktree created by 'il start <issue>' and run 'il commit' from there.\"\n\t\t\t)\n\t\t}\n\n\t\treturn worktreeRoot\n\t}\n\n\t/**\n\t * Auto-detect issue from current directory\n\t * Similar to SummaryCommand.autoDetectFromCurrentDirectory()\n\t */\n\tprivate async autoDetectIssue(worktreePath: string): Promise<{\n\t\tissueNumber: string | number | undefined\n\t\tloomType: 'issue' | 'pr' | 'branch'\n\t}> {\n\t\tconst logger = getLogger()\n\t\tconst currentDir = path.basename(worktreePath)\n\n\t\t// Check for PR worktree pattern: _pr_N suffix\n\t\tconst prPattern = /_pr_(\\d+)$/\n\t\tconst prMatch = currentDir.match(prPattern)\n\n\t\tif (prMatch?.[1]) {\n\t\t\tconst prNumber = parseInt(prMatch[1], 10)\n\t\t\tlogger.debug(`Auto-detected PR #${prNumber} from directory: ${currentDir}`)\n\n\t\t\t// Try to get issue number from metadata\n\t\t\tconst metadata = await this.metadataManager.readMetadata(worktreePath)\n\t\t\treturn {\n\t\t\t\tissueNumber: metadata?.pr_numbers?.[0] ?? prNumber,\n\t\t\t\tloomType: 'pr',\n\t\t\t}\n\t\t}\n\n\t\t// Check for issue pattern in directory name\n\t\tconst issueNumber = extractIssueNumber(currentDir)\n\n\t\tif (issueNumber !== null) {\n\t\t\tlogger.debug(`Auto-detected issue #${issueNumber} from directory: ${currentDir}`)\n\n\t\t\t// Try to get issue number from metadata for more accuracy\n\t\t\tconst metadata = await this.metadataManager.readMetadata(worktreePath)\n\t\t\treturn {\n\t\t\t\tissueNumber: metadata?.issue_numbers?.[0] ?? issueNumber,\n\t\t\t\tloomType: metadata?.issueType ?? 'issue',\n\t\t\t}\n\t\t}\n\n\t\t// Fallback: get current branch name and try to extract issue\n\t\tconst repoInfo = await this.gitWorktreeManager.getRepoInfo()\n\t\tconst currentBranch = repoInfo.currentBranch\n\n\t\tif (currentBranch) {\n\t\t\tconst branchIssueNumber = extractIssueNumber(currentBranch)\n\t\t\tif (branchIssueNumber !== null) {\n\t\t\t\tlogger.debug(`Auto-detected issue #${branchIssueNumber} from branch: ${currentBranch}`)\n\n\t\t\t\tconst metadata = await this.metadataManager.readMetadata(worktreePath)\n\t\t\t\treturn {\n\t\t\t\t\tissueNumber: metadata?.issue_numbers?.[0] ?? branchIssueNumber,\n\t\t\t\t\tloomType: metadata?.issueType ?? 'issue',\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// No issue detected - treat as branch loom\n\t\tlogger.debug('No issue number detected, treating as branch loom')\n\t\tconst metadata = await this.metadataManager.readMetadata(worktreePath)\n\n\t\t// For branch looms, try to get issue number from metadata\n\t\tlet resolvedIssueNumber: string | number | undefined\n\t\tconst loomType = metadata?.issueType ?? 'branch'\n\n\t\tif (loomType === 'issue' && metadata?.issue_numbers?.[0]) {\n\t\t\tresolvedIssueNumber = metadata.issue_numbers[0]\n\t\t} else if (loomType === 'pr' && metadata?.pr_numbers?.[0]) {\n\t\t\tresolvedIssueNumber = metadata.pr_numbers[0]\n\t\t}\n\n\t\treturn {\n\t\t\tissueNumber: resolvedIssueNumber,\n\t\t\tloomType,\n\t\t}\n\t}\n}\n"],"mappings":"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","names":["metadata"]}
@@ -1,18 +1,18 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ScriptCommandBase
4
- } from "./chunk-TRQ76ISK.js";
4
+ } from "./chunk-Z6BO53V7.js";
5
+ import "./chunk-5V74K5ZA.js";
5
6
  import {
6
7
  runScript
7
- } from "./chunk-AXX3QIKK.js";
8
- import "./chunk-UQIXZ3BA.js";
8
+ } from "./chunk-LLWX3PCW.js";
9
+ import "./chunk-UDRZY65Y.js";
9
10
  import {
10
11
  getPackageScripts
11
- } from "./chunk-BXCPJJYM.js";
12
- import "./chunk-EK3XCAAS.js";
13
- import "./chunk-GEXP5IOF.js";
14
- import "./chunk-F6WVM437.js";
15
- import "./chunk-CFUWQHCJ.js";
12
+ } from "./chunk-ITN64ENQ.js";
13
+ import "./chunk-ZA575VLF.js";
14
+ import "./chunk-WFQ5CLTR.js";
15
+ import "./chunk-VWGKGNJP.js";
16
16
  import "./chunk-6MLEBAYZ.js";
17
17
  import {
18
18
  logger
@@ -54,4 +54,4 @@ var CompileCommand = class extends ScriptCommandBase {
54
54
  export {
55
55
  CompileCommand
56
56
  };
57
- //# sourceMappingURL=compile-ULNO5F7Q.js.map
57
+ //# sourceMappingURL=compile-LRMAADUT.js.map
@@ -4,13 +4,13 @@ import {
4
4
  } from "./chunk-Q7POFB5Q.js";
5
5
  import {
6
6
  executeGitCommand
7
- } from "./chunk-GEXP5IOF.js";
8
- import "./chunk-F6WVM437.js";
9
- import "./chunk-CFUWQHCJ.js";
7
+ } from "./chunk-ZA575VLF.js";
8
+ import "./chunk-WFQ5CLTR.js";
9
+ import "./chunk-VWGKGNJP.js";
10
10
  import {
11
11
  checkGhAuth,
12
12
  executeGhCommand
13
- } from "./chunk-LT3SGBR7.js";
13
+ } from "./chunk-GCPAZSGV.js";
14
14
  import {
15
15
  promptInput
16
16
  } from "./chunk-ZX3GTM7O.js";
@@ -327,4 +327,4 @@ export {
327
327
  validateDirectoryPath,
328
328
  validateRepoExists
329
329
  };
330
- //# sourceMappingURL=contribute-Q6GX6AXK.js.map
330
+ //# sourceMappingURL=contribute-GXKOIA42.js.map
@@ -1,44 +1,40 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  DevServerManager
4
- } from "./chunk-64O2UIWO.js";
4
+ } from "./chunk-GV5X6XUE.js";
5
5
  import {
6
- calculatePortForBranch
7
- } from "./chunk-VU3QMIP2.js";
8
- import "./chunk-AXX3QIKK.js";
6
+ getWorkspacePort
7
+ } from "./chunk-453NC377.js";
9
8
  import {
10
9
  IdentifierParser
11
- } from "./chunk-UQIXZ3BA.js";
10
+ } from "./chunk-5V74K5ZA.js";
12
11
  import {
13
12
  ProjectCapabilityDetector
14
- } from "./chunk-ZPSTA5PR.js";
15
- import "./chunk-BXCPJJYM.js";
13
+ } from "./chunk-3CDWFEGL.js";
14
+ import "./chunk-LLWX3PCW.js";
16
15
  import {
17
16
  GitWorktreeManager
18
- } from "./chunk-EK3XCAAS.js";
17
+ } from "./chunk-UDRZY65Y.js";
18
+ import "./chunk-ITN64ENQ.js";
19
19
  import {
20
20
  extractSettingsOverrides
21
21
  } from "./chunk-GYCR2LOU.js";
22
22
  import {
23
23
  extractIssueNumber
24
- } from "./chunk-GEXP5IOF.js";
24
+ } from "./chunk-ZA575VLF.js";
25
25
  import {
26
26
  SettingsManager
27
- } from "./chunk-F6WVM437.js";
28
- import "./chunk-CFUWQHCJ.js";
27
+ } from "./chunk-WFQ5CLTR.js";
28
+ import "./chunk-VWGKGNJP.js";
29
29
  import "./chunk-6MLEBAYZ.js";
30
30
  import {
31
- extractPort,
32
- findEnvFileContainingVariable,
33
31
  isNoEnvFilesFoundError,
34
32
  loadWorkspaceEnv,
35
- logger,
36
- parseEnvFile
33
+ logger
37
34
  } from "./chunk-VT4PDUYT.js";
38
35
 
39
36
  // src/commands/dev-server.ts
40
37
  import path from "path";
41
- import fs from "fs-extra";
42
38
  var DevServerCommand = class {
43
39
  constructor(gitWorktreeManager = new GitWorktreeManager(), capabilityDetector = new ProjectCapabilityDetector(), identifierParser = new IdentifierParser(new GitWorktreeManager()), devServerManager = new DevServerManager(), settingsManager = new SettingsManager()) {
44
40
  this.gitWorktreeManager = gitWorktreeManager;
@@ -54,6 +50,7 @@ var DevServerCommand = class {
54
50
  process.stdout.write(JSON.stringify(data, null, 2) + "\n");
55
51
  }
56
52
  async execute(input) {
53
+ var _a, _b;
57
54
  const parsed = input.identifier ? await this.parseExplicitInput(input.identifier) : await this.autoDetectFromCurrentDirectory();
58
55
  logger.debug(`Parsed input: ${JSON.stringify(parsed)}`);
59
56
  const worktree = await this.findWorktreeForIdentifier(parsed);
@@ -87,7 +84,14 @@ var DevServerCommand = class {
87
84
  message: message2
88
85
  };
89
86
  }
90
- const port = await this.getWorkspacePort(worktree.path);
87
+ const cliOverrides = extractSettingsOverrides();
88
+ const settingsForPort = await this.settingsManager.loadSettings(void 0, cliOverrides);
89
+ const port = await getWorkspacePort({
90
+ worktreePath: worktree.path,
91
+ worktreeBranch: worktree.branch,
92
+ basePort: (_b = (_a = settingsForPort.capabilities) == null ? void 0 : _a.web) == null ? void 0 : _b.basePort,
93
+ checkEnvFile: true
94
+ });
91
95
  const url = `http://localhost:${port}`;
92
96
  const isRunning = await this.devServerManager.isServerRunning(port);
93
97
  if (isRunning) {
@@ -247,64 +251,8 @@ var DevServerCommand = class {
247
251
  }
248
252
  return `branch "${parsed.branchName}"${autoLabel}`;
249
253
  }
250
- /**
251
- * Get port for workspace - reads from dotenv-flow files or calculates based on workspace type
252
- */
253
- async getWorkspacePort(worktreePath) {
254
- var _a, _b;
255
- const cliOverrides = extractSettingsOverrides();
256
- const settings = await this.settingsManager.loadSettings(void 0, cliOverrides);
257
- const basePort = ((_b = (_a = settings.capabilities) == null ? void 0 : _a.web) == null ? void 0 : _b.basePort) ?? 3e3;
258
- const envFile = await findEnvFileContainingVariable(
259
- worktreePath,
260
- "PORT",
261
- async (p) => fs.pathExists(p),
262
- async (p, varName) => {
263
- const content = await fs.readFile(p, "utf8");
264
- const envMap = parseEnvFile(content);
265
- return envMap.get(varName) ?? null;
266
- }
267
- );
268
- if (envFile) {
269
- const envPath = path.join(worktreePath, envFile);
270
- const envContent = await fs.readFile(envPath, "utf8");
271
- const envMap = parseEnvFile(envContent);
272
- const port2 = extractPort(envMap);
273
- if (port2) {
274
- logger.debug(`Using PORT from ${envFile}: ${port2}`);
275
- return port2;
276
- }
277
- }
278
- logger.debug("PORT not found in any dotenv-flow file, calculating from workspace identifier");
279
- const worktrees = await this.gitWorktreeManager.listWorktrees();
280
- const worktree = worktrees.find((wt) => wt.path === worktreePath);
281
- if (!worktree) {
282
- throw new Error(`Could not find worktree for path: ${worktreePath}`);
283
- }
284
- const dirName = path.basename(worktreePath);
285
- const prPattern = /_pr_(\d+)$/;
286
- const prMatch = dirName.match(prPattern);
287
- if (prMatch == null ? void 0 : prMatch[1]) {
288
- const prNumber = parseInt(prMatch[1], 10);
289
- const port2 = basePort + prNumber;
290
- logger.debug(`Calculated PORT for PR #${prNumber}: ${port2}`);
291
- return port2;
292
- }
293
- const issueId = extractIssueNumber(dirName) ?? extractIssueNumber(worktree.branch);
294
- if (issueId !== null) {
295
- const issueNumber = parseInt(issueId, 10);
296
- if (!isNaN(issueNumber)) {
297
- const port2 = basePort + issueNumber;
298
- logger.debug(`Calculated PORT for issue #${issueId}: ${port2}`);
299
- return port2;
300
- }
301
- }
302
- const port = calculatePortForBranch(worktree.branch, basePort);
303
- logger.debug(`Calculated PORT for branch "${worktree.branch}": ${port}`);
304
- return port;
305
- }
306
254
  };
307
255
  export {
308
256
  DevServerCommand
309
257
  };
310
- //# sourceMappingURL=dev-server-4RCDJ5MU.js.map
258
+ //# sourceMappingURL=dev-server-GREJUEKW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/dev-server.ts"],"sourcesContent":["import path from 'path'\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 { loadWorkspaceEnv, isNoEnvFilesFoundError } from '../utils/env.js'\nimport { getWorkspacePort } from '../utils/port.js'\nimport { extractIssueNumber } from '../utils/git.js'\nimport { logger } from '../utils/logger.js'\nimport { extractSettingsOverrides } from '../utils/cli-overrides.js'\nimport type { GitWorktree } from '../types/worktree.js'\n\nexport interface DevServerCommandInput {\n\tidentifier?: string | undefined\n\tjson?: boolean | undefined\n}\n\nexport interface DevServerResult {\n\tstatus: 'started' | 'already_running' | 'no_web_capability'\n\turl?: string\n\tport?: number\n\tpid?: number\n\tmessage: string\n}\n\ninterface ParsedDevServerInput {\n\ttype: 'issue' | 'pr' | 'branch'\n\tnumber?: string | number\n\tbranchName?: string\n\toriginalInput: string\n\tautoDetected: boolean\n}\n\n/**\n * DevServerCommand - Start dev server for workspace in foreground mode\n * Runs in foreground (blocking terminal until user stops it)\n */\nexport class DevServerCommand {\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\t/**\n\t * Output JSON to stdout (used for --json flag)\n\t */\n\tprivate outputJson(data: DevServerResult | Record<string, unknown>): void {\n\t\tprocess.stdout.write(JSON.stringify(data, null, 2) + '\\n')\n\t}\n\n\tasync execute(input: DevServerCommandInput): Promise<DevServerResult> {\n\t\t// 1. Parse or auto-detect identifier\n\t\tconst parsed = input.identifier\n\t\t\t? await this.parseExplicitInput(input.identifier)\n\t\t\t: await this.autoDetectFromCurrentDirectory()\n\n\t\tlogger.debug(`Parsed input: ${JSON.stringify(parsed)}`)\n\n\t\t// 2. Find worktree path based on identifier\n\t\tconst worktree = await this.findWorktreeForIdentifier(parsed)\n\n\t\tlogger.debug(`Found worktree at: ${worktree.path}`)\n\n\t\t// 3. Load settings to check sourceEnvOnStart\n\t\tconst settings = await this.settingsManager.loadSettings()\n\t\tconst shouldLoadEnv = settings.sourceEnvOnStart ?? false\n\n\t\t// Build environment variables\n\t\tlet envOverrides: Record<string, string> = {}\n\n\t\tif (shouldLoadEnv) {\n\t\t\tconst envResult = loadWorkspaceEnv(worktree.path)\n\t\t\tif (envResult.parsed) {\n\t\t\t\tenvOverrides = envResult.parsed\n\t\t\t}\n\t\t\tif (envResult.error && !isNoEnvFilesFoundError(envResult.error)) {\n\t\t\t\tlogger.warn(`Failed to load env files: ${envResult.error.message}`)\n\t\t\t}\n\t\t}\n\n\t\t// 4. Detect project capabilities\n\t\tconst { capabilities } =\n\t\t\tawait this.capabilityDetector.detectCapabilities(worktree.path)\n\n\t\tlogger.debug(`Detected capabilities: ${capabilities.join(', ')}`)\n\n\t\t// 4. If no web capability, return gracefully with info message\n\t\tif (!capabilities.includes('web')) {\n\t\t\tconst message = 'No web capability detected in this workspace. Dev server not started.'\n\t\t\tif (input.json) {\n\t\t\t\tthis.outputJson({\n\t\t\t\t\tstatus: 'no_web_capability',\n\t\t\t\t\tmessage,\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\tlogger.info(message)\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tstatus: 'no_web_capability',\n\t\t\t\tmessage,\n\t\t\t}\n\t\t}\n\n\t\t// 5. Get port for workspace\n\t\tconst cliOverrides = extractSettingsOverrides()\n\t\tconst settingsForPort = await this.settingsManager.loadSettings(undefined, cliOverrides)\n\t\tconst port = await getWorkspacePort({\n\t\t\tworktreePath: worktree.path,\n\t\t\tworktreeBranch: worktree.branch,\n\t\t\tbasePort: settingsForPort.capabilities?.web?.basePort,\n\t\t\tcheckEnvFile: true,\n\t\t})\n\t\tconst url = `http://localhost:${port}`\n\n\t\t// 6. Check if server already running\n\t\tconst isRunning = await this.devServerManager.isServerRunning(port)\n\n\t\tif (isRunning) {\n\t\t\tconst message = `Dev server already running at ${url}`\n\t\t\tif (input.json) {\n\t\t\t\tthis.outputJson({\n\t\t\t\t\tstatus: 'already_running',\n\t\t\t\t\turl,\n\t\t\t\t\tport,\n\t\t\t\t\tmessage,\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\tlogger.info(message)\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tstatus: 'already_running',\n\t\t\t\turl,\n\t\t\t\tport,\n\t\t\t\tmessage,\n\t\t\t}\n\t\t}\n\n\t\t// 7. Start server in foreground\n\t\tconst message = `Starting dev server at ${url}`\n\t\tif (!input.json) {\n\t\t\tlogger.info(message)\n\t\t}\n\n\t\tlet finalResult: DevServerResult = {\n\t\t\tstatus: 'started',\n\t\t\turl,\n\t\t\tport,\n\t\t\tmessage,\n\t\t}\n\n\t\t// This will block until user stops the server (Ctrl+C)\n\t\t// In JSON mode, redirect npm output to stderr so JSON can go to stdout\n\t\tconst processInfo = await this.devServerManager.runServerForeground(\n\t\t\tworktree.path,\n\t\t\tport,\n\t\t\t!!input.json,\n\t\t\t// Callback called immediately when process starts (for JSON output)\n\t\t\t(pid) => {\n\t\t\t\tif (input.json && pid) {\n\t\t\t\t\tfinalResult.pid = pid\n\t\t\t\t\tthis.outputJson(finalResult)\n\t\t\t\t}\n\t\t\t},\n\t\t\tenvOverrides\n\t\t)\n\n\t\tif (processInfo.pid) {\n\t\t\tfinalResult.pid = processInfo.pid\n\t\t}\n\n\t\treturn finalResult\n\t}\n\n\t/**\n\t * Parse explicit identifier input\n\t */\n\tprivate async parseExplicitInput(identifier: string): Promise<ParsedDevServerInput> {\n\t\tconst parsed = await this.identifierParser.parseForPatternDetection(identifier)\n\n\t\t// Description type should never reach dev-server command\n\t\tif (parsed.type === 'description') {\n\t\t\tthrow new Error('Description input type is not supported in dev-server command')\n\t\t}\n\n\t\tconst result: ParsedDevServerInput = {\n\t\t\ttype: parsed.type,\n\t\t\toriginalInput: parsed.originalInput,\n\t\t\tautoDetected: false,\n\t\t}\n\n\t\tif (parsed.number !== undefined) {\n\t\t\tresult.number = parsed.number\n\t\t}\n\t\tif (parsed.branchName !== undefined) {\n\t\t\tresult.branchName = parsed.branchName\n\t\t}\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Auto-detect identifier from current directory\n\t */\n\tprivate async autoDetectFromCurrentDirectory(): Promise<ParsedDevServerInput> {\n\t\tconst currentDir = path.basename(process.cwd())\n\n\t\t// Check for PR worktree pattern: _pr_N suffix\n\t\tconst prPattern = /_pr_(\\d+)$/\n\t\tconst prMatch = currentDir.match(prPattern)\n\n\t\tif (prMatch?.[1]) {\n\t\t\tconst prNumber = parseInt(prMatch[1], 10)\n\t\t\tlogger.debug(`Auto-detected PR #${prNumber} from directory: ${currentDir}`)\n\t\t\treturn {\n\t\t\t\ttype: 'pr',\n\t\t\t\tnumber: prNumber,\n\t\t\t\toriginalInput: currentDir,\n\t\t\t\tautoDetected: true,\n\t\t\t}\n\t\t}\n\n\t\t// Check for issue pattern in directory\n\t\tconst issueNumber = extractIssueNumber(currentDir)\n\n\t\tif (issueNumber !== null) {\n\t\t\tlogger.debug(`Auto-detected issue #${issueNumber} from directory: ${currentDir}`)\n\t\t\treturn {\n\t\t\t\ttype: 'issue',\n\t\t\t\tnumber: issueNumber,\n\t\t\t\toriginalInput: currentDir,\n\t\t\t\tautoDetected: true,\n\t\t\t}\n\t\t}\n\n\t\t// Fallback: get current branch name\n\t\tconst repoInfo = await this.gitWorktreeManager.getRepoInfo()\n\t\tconst currentBranch = repoInfo.currentBranch\n\n\t\tif (!currentBranch) {\n\t\t\tthrow new Error(\n\t\t\t\t'Could not auto-detect identifier. Please provide an issue number, PR number, or branch name.\\n' +\n\t\t\t\t\t'Expected directory pattern: feat/issue-XX-description OR worktree with _pr_N suffix'\n\t\t\t)\n\t\t}\n\n\t\t// Try to extract issue from branch name\n\t\tconst branchIssueNumber = extractIssueNumber(currentBranch)\n\t\tif (branchIssueNumber !== null) {\n\t\t\tlogger.debug(`Auto-detected issue #${branchIssueNumber} from branch: ${currentBranch}`)\n\t\t\treturn {\n\t\t\t\ttype: 'issue',\n\t\t\t\tnumber: branchIssueNumber,\n\t\t\t\toriginalInput: currentBranch,\n\t\t\t\tautoDetected: true,\n\t\t\t}\n\t\t}\n\n\t\t// Last resort: use branch name\n\t\treturn {\n\t\t\ttype: 'branch',\n\t\t\tbranchName: currentBranch,\n\t\t\toriginalInput: currentBranch,\n\t\t\tautoDetected: true,\n\t\t}\n\t}\n\n\t/**\n\t * Find worktree for the given identifier\n\t */\n\tprivate async findWorktreeForIdentifier(parsed: ParsedDevServerInput): Promise<GitWorktree> {\n\t\tlet worktree: GitWorktree | null = null\n\n\t\tif (parsed.type === 'issue' && parsed.number !== undefined) {\n\t\t\tworktree = await this.gitWorktreeManager.findWorktreeForIssue(parsed.number)\n\t\t} else if (parsed.type === 'pr' && parsed.number !== undefined) {\n\t\t\tconst prNumber = typeof parsed.number === 'number' ? parsed.number : Number(parsed.number)\n\t\t\tif (isNaN(prNumber) || !isFinite(prNumber)) {\n\t\t\t\tthrow new Error(`Invalid PR number: ${parsed.number}. PR numbers must be numeric.`)\n\t\t\t}\n\t\t\tworktree = await this.gitWorktreeManager.findWorktreeForPR(prNumber, '')\n\t\t} else if (parsed.type === 'branch' && parsed.branchName) {\n\t\t\tworktree = await this.gitWorktreeManager.findWorktreeForBranch(\n\t\t\t\tparsed.branchName\n\t\t\t)\n\t\t}\n\n\t\tif (!worktree) {\n\t\t\tthrow new Error(\n\t\t\t\t`No worktree found for ${this.formatParsedInput(parsed)}. ` +\n\t\t\t\t\t`Run 'il start ${parsed.originalInput}' to create one.`\n\t\t\t)\n\t\t}\n\n\t\treturn worktree\n\t}\n\n\t/**\n\t * Format parsed input for display\n\t */\n\tprivate formatParsedInput(parsed: ParsedDevServerInput): 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"],"mappings":"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","names":["message"]}
@@ -2,27 +2,27 @@
2
2
  import {
3
3
  IssueEnhancementService,
4
4
  capitalizeFirstLetter
5
- } from "./chunk-7HIRPCKU.js";
5
+ } from "./chunk-HVQNVRAF.js";
6
6
  import {
7
7
  ProjectCapabilityDetector
8
- } from "./chunk-ZPSTA5PR.js";
9
- import "./chunk-BXCPJJYM.js";
8
+ } from "./chunk-3CDWFEGL.js";
10
9
  import {
11
10
  AgentManager
12
- } from "./chunk-SN3Z6EZO.js";
11
+ } from "./chunk-N7FVXZNI.js";
12
+ import "./chunk-ITN64ENQ.js";
13
13
  import "./chunk-YETJNRQM.js";
14
- import "./chunk-W6WVRHJ6.js";
14
+ import "./chunk-TIYJEEVO.js";
15
15
  import {
16
16
  SettingsManager
17
- } from "./chunk-F6WVM437.js";
17
+ } from "./chunk-WFQ5CLTR.js";
18
18
  import {
19
19
  GitHubService
20
- } from "./chunk-3PT7RKL5.js";
21
- import "./chunk-LT3SGBR7.js";
20
+ } from "./chunk-USJSNHGG.js";
21
+ import "./chunk-GCPAZSGV.js";
22
22
  import "./chunk-ZX3GTM7O.js";
23
23
  import {
24
24
  getClaudeVersion
25
- } from "./chunk-AEIMYF4P.js";
25
+ } from "./chunk-FP7G7DG3.js";
26
26
  import "./chunk-6MLEBAYZ.js";
27
27
  import {
28
28
  logger
@@ -164,4 +164,4 @@ ${userBody}`;
164
164
  export {
165
165
  FeedbackCommand
166
166
  };
167
- //# sourceMappingURL=feedback-O4Q55SVS.js.map
167
+ //# sourceMappingURL=feedback-G7G5QCY4.js.map
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ GitCommandError,
3
4
  PLACEHOLDER_COMMIT_PREFIX,
4
5
  branchExists,
5
6
  checkRemoteBranchStatus,
@@ -32,12 +33,13 @@ import {
32
33
  pushBranchToRemote,
33
34
  removePlaceholderCommitFromHead,
34
35
  removePlaceholderCommitFromHistory
35
- } from "./chunk-GEXP5IOF.js";
36
- import "./chunk-F6WVM437.js";
37
- import "./chunk-CFUWQHCJ.js";
36
+ } from "./chunk-ZA575VLF.js";
37
+ import "./chunk-WFQ5CLTR.js";
38
+ import "./chunk-VWGKGNJP.js";
38
39
  import "./chunk-6MLEBAYZ.js";
39
40
  import "./chunk-VT4PDUYT.js";
40
41
  export {
42
+ GitCommandError,
41
43
  PLACEHOLDER_COMMIT_PREFIX,
42
44
  branchExists,
43
45
  checkRemoteBranchStatus,
@@ -71,4 +73,4 @@ export {
71
73
  removePlaceholderCommitFromHead,
72
74
  removePlaceholderCommitFromHistory
73
75
  };
74
- //# sourceMappingURL=git-FVMGBHC2.js.map
76
+ //# sourceMappingURL=git-ENLT2VNI.js.map
@@ -36,8 +36,8 @@ const net = require('net');
36
36
  const path = require('path');
37
37
 
38
38
  // Debug logging - writes to /tmp/iloom-hook.log
39
- // Set ILOOM_HOOK_DEBUG=0 to disable (enabled by default for now)
40
- const DEBUG = process.env.ILOOM_HOOK_DEBUG !== '0';
39
+ // Set ILOOM_HOOK_DEBUG=1 to enable logging
40
+ const DEBUG = process.env.ILOOM_HOOK_DEBUG === '1';
41
41
  const LOG_FILE = '/tmp/iloom-hook.log';
42
42
 
43
43
  function debug(message, data = {}) {
@@ -141,6 +141,9 @@ function mapEventToStatus(eventName, notificationType) {
141
141
  // Other notification types - not relevant, skip
142
142
  return null;
143
143
 
144
+ case 'UserPromptSubmit':
145
+ return 'user_prompt_submit'; // Special marker for additionalContext output
146
+
144
147
  default:
145
148
  // Other events (SessionStart, SubagentStop, etc.) - not relevant, skip
146
149
  return null;
@@ -234,6 +237,31 @@ async function main() {
234
237
  process.exit(0);
235
238
  }
236
239
 
240
+ // Special handling for UserPromptSubmit - output JSON additionalContext instead of broadcasting
241
+ if (status === 'user_prompt_submit') {
242
+ const reminder = `**REMINDER**: You MUST USE subagents to preserve your context window for ongoing conversation.
243
+
244
+ | Request Type | Action |
245
+ |--------------|--------|
246
+ | Trivial (quick answer, single-line fix) | Handle directly |
247
+ | Bug investigation / analysis | \`@agent-iloom-issue-analyzer\` → present findings → offer to fix |
248
+ | Code changes | \`@agent-iloom-issue-implementer\` - TELL THE AGENT NOT TO MAKE/UPDATE ISSUE COMMENTS TO AVOID POLLUTION |
249
+ | On 3rd repeated attempt at fixing the same problem | \`@agent-iloom-issue-analyze-and-plan\` → if approved, \`@agent-iloom-issue-implementer\` - DO NOT PROVIDE ADDITIONAL GUIDANCE ABOUT ISSUE COMMENTS |
250
+ | On 4rd or more repeated attempt at fixing the same problem | \`@agent-iloom-issue-analyzer\` → if approved, \`@agent-iloom-issue-planner\` → if approved, \`@agent-iloom-issue-implementer\` - DO NOT PROVIDE ADDITIONAL GUIDANCE ABOUT ISSUE COMMENTS |
251
+ | New features / complex changes | \`@agent-iloom-issue-analyze-and-plan\` → if approved, \`@agent-iloom-issue-implementer\` |
252
+ | Deep questions (how/why something works) | \`@agent-iloom-issue-analyzer\` |`;
253
+
254
+ const output = {
255
+ hookSpecificOutput: {
256
+ hookEventName: 'UserPromptSubmit',
257
+ additionalContext: reminder
258
+ }
259
+ };
260
+ console.log(JSON.stringify(output));
261
+ debug('UserPromptSubmit: output additionalContext reminder');
262
+ process.exit(0);
263
+ }
264
+
237
265
  // Find all iloom sockets for broadcasting
238
266
  const allSockets = findAllIloomSockets();
239
267
  debug('Found iloom sockets', { count: allSockets.length, sockets: allSockets });