@iloom/cli 0.9.2 → 0.10.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.
- package/LICENSE +1 -1
- package/README.md +159 -40
- package/dist/{BranchNamingService-K6XNWQ6C.js → BranchNamingService-ECJHBB67.js} +2 -2
- package/dist/ClaudeContextManager-QXX6ZFST.js +14 -0
- package/dist/ClaudeService-NJNK2SUH.js +13 -0
- package/dist/{GitHubService-TGWJN4V4.js → GitHubService-MEHKHUQP.js} +4 -4
- package/dist/IssueTrackerFactory-NG53YX5S.js +14 -0
- package/dist/{LoomLauncher-73NXL2CL.js → LoomLauncher-L64HHS3T.js} +9 -9
- package/dist/{MetadataManager-W3C54UYT.js → MetadataManager-5QZSTKNN.js} +2 -2
- package/dist/{ProjectCapabilityDetector-N5L7T4IY.js → ProjectCapabilityDetector-5KSYUTBJ.js} +3 -3
- package/dist/{PromptTemplateManager-36YLQRHP.js → PromptTemplateManager-DULSVRRE.js} +2 -2
- package/dist/README.md +159 -40
- package/dist/{SettingsManager-AW3JTJHD.js → SettingsManager-BQDQA3FK.js} +4 -2
- package/dist/agents/iloom-artifact-reviewer.md +11 -0
- package/dist/agents/iloom-code-reviewer.md +14 -0
- package/dist/agents/iloom-issue-analyze-and-plan.md +55 -12
- package/dist/agents/iloom-issue-analyzer.md +49 -6
- package/dist/agents/iloom-issue-complexity-evaluator.md +47 -6
- package/dist/agents/iloom-issue-enhancer.md +86 -7
- package/dist/agents/iloom-issue-implementer.md +48 -7
- package/dist/agents/iloom-issue-planner.md +115 -62
- package/dist/{build-THZI572G.js → build-5GO3XW26.js} +9 -9
- package/dist/{chunk-NUACL52E.js → chunk-3D7WQM7I.js} +2 -2
- package/dist/chunk-4232AHNQ.js +35 -0
- package/dist/chunk-4232AHNQ.js.map +1 -0
- package/dist/{chunk-QN47QVBX.js → chunk-4WJNIR5O.js} +1 -1
- package/dist/chunk-4WJNIR5O.js.map +1 -0
- package/dist/{chunk-A7NJF73J.js → chunk-5MWV33NN.js} +4 -4
- package/dist/{chunk-3I4ONZRT.js → chunk-6EU6TCF6.js} +10 -10
- package/dist/chunk-6EU6TCF6.js.map +1 -0
- package/dist/{chunk-CWRI4JC3.js → chunk-FB47TIJG.js} +29 -11
- package/dist/chunk-FB47TIJG.js.map +1 -0
- package/dist/chunk-HEXKPKCK.js +1396 -0
- package/dist/chunk-HEXKPKCK.js.map +1 -0
- package/dist/{chunk-KAYXR544.js → chunk-J5S7DFYC.js} +2 -2
- package/dist/{chunk-ULSWCPQG.js → chunk-JO2LZ6EQ.js} +476 -5
- package/dist/chunk-JO2LZ6EQ.js.map +1 -0
- package/dist/{chunk-KBEIQP4G.js → chunk-KB64WNBZ.js} +43 -3
- package/dist/chunk-KB64WNBZ.js.map +1 -0
- package/dist/{chunk-OFDN5NKS.js → chunk-KXDRI47U.js} +69 -12
- package/dist/chunk-KXDRI47U.js.map +1 -0
- package/dist/{chunk-R4YWBGY6.js → chunk-LXLMMXXY.js} +54 -14
- package/dist/chunk-LXLMMXXY.js.map +1 -0
- package/dist/{chunk-AR5QKYNE.js → chunk-MNHZB4Z2.js} +4 -4
- package/dist/{chunk-TL72BGP6.js → chunk-MORRVYPT.js} +2 -2
- package/dist/{chunk-KJTVU3HZ.js → chunk-NRSWLOAZ.js} +8 -8
- package/dist/chunk-NRSWLOAZ.js.map +1 -0
- package/dist/{chunk-FO5GGFOV.js → chunk-ONQYPICO.js} +13 -5
- package/dist/chunk-ONQYPICO.js.map +1 -0
- package/dist/{chunk-7ZEHSSUP.js → chunk-P4O6EH46.js} +4 -4
- package/dist/chunk-QZWEJVWV.js +207 -0
- package/dist/chunk-QZWEJVWV.js.map +1 -0
- package/dist/chunk-RSYT7MVI.js +202 -0
- package/dist/chunk-RSYT7MVI.js.map +1 -0
- package/dist/{chunk-Z2TWEXR7.js → chunk-RYWFS37M.js} +6 -6
- package/dist/chunk-RYWFS37M.js.map +1 -0
- package/dist/{chunk-B7U6OKUR.js → chunk-SF2P22EE.js} +11 -3
- package/dist/chunk-SF2P22EE.js.map +1 -0
- package/dist/{chunk-6IIL5M2L.js → chunk-SN3SQCFK.js} +10 -8
- package/dist/{chunk-6IIL5M2L.js.map → chunk-SN3SQCFK.js.map} +1 -1
- package/dist/{chunk-SOSQILHO.js → chunk-UD3WJDIV.js} +92 -82
- package/dist/chunk-UD3WJDIV.js.map +1 -0
- package/dist/{chunk-KXGQYLFZ.js → chunk-UKBAJ2QQ.js} +61 -7
- package/dist/chunk-UKBAJ2QQ.js.map +1 -0
- package/dist/{chunk-W6DP5RVR.js → chunk-UVD4CZKS.js} +3 -3
- package/dist/chunk-UWGVCXRF.js +207 -0
- package/dist/chunk-UWGVCXRF.js.map +1 -0
- package/dist/{chunk-NWMORW3U.js → chunk-VECNX6VX.js} +2 -2
- package/dist/{chunk-4CO6KG5S.js → chunk-VG45TUYK.js} +53 -7
- package/dist/{chunk-4CO6KG5S.js.map → chunk-VG45TUYK.js.map} +1 -1
- package/dist/{chunk-TC7APDKU.js → chunk-VGGST52X.js} +2 -2
- package/dist/{chunk-4LKGCFGG.js → chunk-WWKOVDWC.js} +2 -2
- package/dist/{chunk-YKFCCV6S.js → chunk-WY4QBK43.js} +7 -7
- package/dist/chunk-WY4QBK43.js.map +1 -0
- package/dist/chunk-Y4YZTHZE.js +73 -0
- package/dist/chunk-Y4YZTHZE.js.map +1 -0
- package/dist/{chunk-VOGGLPG5.js → chunk-YQ57ORTV.js} +14 -1
- package/dist/chunk-YQ57ORTV.js.map +1 -0
- package/dist/{chunk-RI2YL6TK.js → chunk-YYAKPQBT.js} +65 -18
- package/dist/chunk-YYAKPQBT.js.map +1 -0
- package/dist/{chunk-IZIYLYPK.js → chunk-ZEWU5PZK.js} +2 -2
- package/dist/{chunk-VPTAX5TR.js → chunk-ZHPNZC75.js} +12 -12
- package/dist/chunk-ZHPNZC75.js.map +1 -0
- package/dist/{chunk-DGG2VY7B.js → chunk-ZW2LKWWE.js} +9 -9
- package/dist/chunk-ZW2LKWWE.js.map +1 -0
- package/dist/{claude-TP2QO3BU.js → claude-P3NQR6IJ.js} +2 -2
- package/dist/{cleanup-PJRIFFU4.js → cleanup-6UCPVMFG.js} +81 -32
- package/dist/cleanup-6UCPVMFG.js.map +1 -0
- package/dist/cli.js +638 -349
- package/dist/cli.js.map +1 -1
- package/dist/{commit-IVP3M4HG.js → commit-L3EPY5QG.js} +21 -20
- package/dist/commit-L3EPY5QG.js.map +1 -0
- package/dist/{compile-R2J65HBQ.js → compile-ZS4HYRX5.js} +9 -9
- package/dist/{contribute-VDZXHK5Y.js → contribute-ORDDQGSL.js} +14 -6
- package/dist/contribute-ORDDQGSL.js.map +1 -0
- package/dist/{dev-server-7F622OEO.js → dev-server-FYZ2AQIH.js} +29 -15
- package/dist/dev-server-FYZ2AQIH.js.map +1 -0
- package/dist/{feedback-E7VET7CL.js → feedback-TMBXSCM5.js} +15 -15
- package/dist/{git-2QDQ2X2S.js → git-ET64COO3.js} +4 -4
- package/dist/hooks/iloom-hook.js +15 -0
- package/dist/ignite-CGOV3TD4.js +1393 -0
- package/dist/ignite-CGOV3TD4.js.map +1 -0
- package/dist/index.d.ts +382 -53
- package/dist/index.js +1167 -36
- package/dist/index.js.map +1 -1
- package/dist/{init-676DHF6R.js → init-GFQ5W7GK.js} +57 -21
- package/dist/init-GFQ5W7GK.js.map +1 -0
- package/dist/{issues-PJSOLOBJ.js → issues-T4ZZSPEG.js} +61 -20
- package/dist/issues-T4ZZSPEG.js.map +1 -0
- package/dist/{lint-CJM7BAIM.js → lint-6TQXDZ3T.js} +9 -9
- package/dist/mcp/issue-management-server.js +2471 -256
- package/dist/mcp/issue-management-server.js.map +1 -1
- package/dist/mcp/recap-server.js +144 -21
- package/dist/mcp/recap-server.js.map +1 -1
- package/dist/{neon-helpers-VVFFTLXE.js → neon-helpers-CQN2PB4S.js} +3 -3
- package/dist/neon-helpers-CQN2PB4S.js.map +1 -0
- package/dist/{open-544H7JF5.js → open-5QZGXQRF.js} +15 -15
- package/dist/open-5QZGXQRF.js.map +1 -0
- package/dist/{plan-Q7ELXDLC.js → plan-U7ZQWLFY.js} +41 -25
- package/dist/plan-U7ZQWLFY.js.map +1 -0
- package/dist/{projects-LH362JZQ.js → projects-2UOXFLNZ.js} +4 -4
- package/dist/prompts/CLAUDE.md +62 -0
- package/dist/prompts/init-prompt.txt +347 -26
- package/dist/prompts/issue-prompt.txt +427 -54
- package/dist/prompts/plan-prompt.txt +97 -16
- package/dist/prompts/pr-prompt.txt +44 -1
- package/dist/prompts/regular-prompt.txt +42 -1
- package/dist/prompts/session-summary-prompt.txt +14 -0
- package/dist/prompts/swarm-orchestrator-prompt.txt +437 -0
- package/dist/{rebase-YND35CIE.js → rebase-DWIB77KV.js} +10 -10
- package/dist/{recap-3W7COH7D.js → recap-MX63HAKV.js} +47 -19
- package/dist/recap-MX63HAKV.js.map +1 -0
- package/dist/{run-QUXJKDQQ.js → run-O3TFNQFC.js} +15 -15
- package/dist/run-O3TFNQFC.js.map +1 -0
- package/dist/schema/package-iloom.schema.json +58 -0
- package/dist/schema/settings.schema.json +115 -15
- package/dist/{shell-QGECBLST.js → shell-G6VC2CYR.js} +14 -7
- package/dist/shell-G6VC2CYR.js.map +1 -0
- package/dist/{summary-G2T4452H.js → summary-FWHAX55O.js} +27 -25
- package/dist/summary-FWHAX55O.js.map +1 -0
- package/dist/{test-EA5NQFDC.js → test-F7JNJZYP.js} +9 -9
- package/dist/{test-git-M7LSLEFL.js → test-git-BTAOIUE2.js} +4 -4
- package/dist/test-jira-CHYNV33F.js +96 -0
- package/dist/test-jira-CHYNV33F.js.map +1 -0
- package/dist/{test-prefix-64NAAUON.js → test-prefix-Q6TFSU6F.js} +4 -4
- package/dist/{test-webserver-OK6Z5FJM.js → test-webserver-EONCG7E7.js} +6 -6
- package/dist/{vscode-AR5NNXXI.js → vscode-VA5X4P25.js} +7 -7
- package/package.json +5 -1
- package/dist/ClaudeContextManager-HR5JQKAI.js +0 -14
- package/dist/ClaudeService-TK7FMC2X.js +0 -13
- package/dist/chunk-3I4ONZRT.js.map +0 -1
- package/dist/chunk-B7U6OKUR.js.map +0 -1
- package/dist/chunk-CWRI4JC3.js.map +0 -1
- package/dist/chunk-DGG2VY7B.js.map +0 -1
- package/dist/chunk-FJDRTVJX.js +0 -520
- package/dist/chunk-FJDRTVJX.js.map +0 -1
- package/dist/chunk-FO5GGFOV.js.map +0 -1
- package/dist/chunk-KBEIQP4G.js.map +0 -1
- package/dist/chunk-KJTVU3HZ.js.map +0 -1
- package/dist/chunk-KXGQYLFZ.js.map +0 -1
- package/dist/chunk-OFDN5NKS.js.map +0 -1
- package/dist/chunk-QN47QVBX.js.map +0 -1
- package/dist/chunk-R4YWBGY6.js.map +0 -1
- package/dist/chunk-RI2YL6TK.js.map +0 -1
- package/dist/chunk-SOSQILHO.js.map +0 -1
- package/dist/chunk-ULSWCPQG.js.map +0 -1
- package/dist/chunk-VOGGLPG5.js.map +0 -1
- package/dist/chunk-VPTAX5TR.js.map +0 -1
- package/dist/chunk-WHI5KEOX.js +0 -121
- package/dist/chunk-WHI5KEOX.js.map +0 -1
- package/dist/chunk-YKFCCV6S.js.map +0 -1
- package/dist/chunk-Z2TWEXR7.js.map +0 -1
- package/dist/cleanup-PJRIFFU4.js.map +0 -1
- package/dist/commit-IVP3M4HG.js.map +0 -1
- package/dist/contribute-VDZXHK5Y.js.map +0 -1
- package/dist/dev-server-7F622OEO.js.map +0 -1
- package/dist/ignite-IW35CDBD.js +0 -784
- package/dist/ignite-IW35CDBD.js.map +0 -1
- package/dist/init-676DHF6R.js.map +0 -1
- package/dist/issues-PJSOLOBJ.js.map +0 -1
- package/dist/open-544H7JF5.js.map +0 -1
- package/dist/plan-Q7ELXDLC.js.map +0 -1
- package/dist/recap-3W7COH7D.js.map +0 -1
- package/dist/run-QUXJKDQQ.js.map +0 -1
- package/dist/shell-QGECBLST.js.map +0 -1
- package/dist/summary-G2T4452H.js.map +0 -1
- /package/dist/{BranchNamingService-K6XNWQ6C.js.map → BranchNamingService-ECJHBB67.js.map} +0 -0
- /package/dist/{ClaudeContextManager-HR5JQKAI.js.map → ClaudeContextManager-QXX6ZFST.js.map} +0 -0
- /package/dist/{ClaudeService-TK7FMC2X.js.map → ClaudeService-NJNK2SUH.js.map} +0 -0
- /package/dist/{GitHubService-TGWJN4V4.js.map → GitHubService-MEHKHUQP.js.map} +0 -0
- /package/dist/{MetadataManager-W3C54UYT.js.map → IssueTrackerFactory-NG53YX5S.js.map} +0 -0
- /package/dist/{LoomLauncher-73NXL2CL.js.map → LoomLauncher-L64HHS3T.js.map} +0 -0
- /package/dist/{ProjectCapabilityDetector-N5L7T4IY.js.map → MetadataManager-5QZSTKNN.js.map} +0 -0
- /package/dist/{PromptTemplateManager-36YLQRHP.js.map → ProjectCapabilityDetector-5KSYUTBJ.js.map} +0 -0
- /package/dist/{SettingsManager-AW3JTJHD.js.map → PromptTemplateManager-DULSVRRE.js.map} +0 -0
- /package/dist/{claude-TP2QO3BU.js.map → SettingsManager-BQDQA3FK.js.map} +0 -0
- /package/dist/{build-THZI572G.js.map → build-5GO3XW26.js.map} +0 -0
- /package/dist/{chunk-NUACL52E.js.map → chunk-3D7WQM7I.js.map} +0 -0
- /package/dist/{chunk-A7NJF73J.js.map → chunk-5MWV33NN.js.map} +0 -0
- /package/dist/{chunk-KAYXR544.js.map → chunk-J5S7DFYC.js.map} +0 -0
- /package/dist/{chunk-AR5QKYNE.js.map → chunk-MNHZB4Z2.js.map} +0 -0
- /package/dist/{chunk-TL72BGP6.js.map → chunk-MORRVYPT.js.map} +0 -0
- /package/dist/{chunk-7ZEHSSUP.js.map → chunk-P4O6EH46.js.map} +0 -0
- /package/dist/{chunk-W6DP5RVR.js.map → chunk-UVD4CZKS.js.map} +0 -0
- /package/dist/{chunk-NWMORW3U.js.map → chunk-VECNX6VX.js.map} +0 -0
- /package/dist/{chunk-TC7APDKU.js.map → chunk-VGGST52X.js.map} +0 -0
- /package/dist/{chunk-4LKGCFGG.js.map → chunk-WWKOVDWC.js.map} +0 -0
- /package/dist/{chunk-IZIYLYPK.js.map → chunk-ZEWU5PZK.js.map} +0 -0
- /package/dist/{git-2QDQ2X2S.js.map → claude-P3NQR6IJ.js.map} +0 -0
- /package/dist/{compile-R2J65HBQ.js.map → compile-ZS4HYRX5.js.map} +0 -0
- /package/dist/{feedback-E7VET7CL.js.map → feedback-TMBXSCM5.js.map} +0 -0
- /package/dist/{neon-helpers-VVFFTLXE.js.map → git-ET64COO3.js.map} +0 -0
- /package/dist/{lint-CJM7BAIM.js.map → lint-6TQXDZ3T.js.map} +0 -0
- /package/dist/{projects-LH362JZQ.js.map → projects-2UOXFLNZ.js.map} +0 -0
- /package/dist/{rebase-YND35CIE.js.map → rebase-DWIB77KV.js.map} +0 -0
- /package/dist/{test-EA5NQFDC.js.map → test-F7JNJZYP.js.map} +0 -0
- /package/dist/{test-git-M7LSLEFL.js.map → test-git-BTAOIUE2.js.map} +0 -0
- /package/dist/{test-prefix-64NAAUON.js.map → test-prefix-Q6TFSU6F.js.map} +0 -0
- /package/dist/{test-webserver-OK6Z5FJM.js.map → test-webserver-EONCG7E7.js.map} +0 -0
- /package/dist/{vscode-AR5NNXXI.js.map → vscode-VA5X4P25.js.map} +0 -0
|
@@ -2,33 +2,34 @@
|
|
|
2
2
|
import {
|
|
3
3
|
CommitManager,
|
|
4
4
|
ValidationRunner
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-ZHPNZC75.js";
|
|
6
6
|
import {
|
|
7
7
|
IssueManagementProviderFactory
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-JO2LZ6EQ.js";
|
|
9
|
+
import "./chunk-4232AHNQ.js";
|
|
10
|
+
import "./chunk-WWKOVDWC.js";
|
|
11
11
|
import {
|
|
12
12
|
GitWorktreeManager
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-
|
|
13
|
+
} from "./chunk-VGGST52X.js";
|
|
14
|
+
import "./chunk-YQ57ORTV.js";
|
|
15
|
+
import "./chunk-ONQYPICO.js";
|
|
15
16
|
import {
|
|
16
17
|
extractIssueNumber,
|
|
17
18
|
getWorktreeRoot,
|
|
18
19
|
isValidGitRepo
|
|
19
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-MNHZB4Z2.js";
|
|
20
21
|
import {
|
|
21
22
|
SettingsManager
|
|
22
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-YYAKPQBT.js";
|
|
23
24
|
import {
|
|
24
25
|
MetadataManager
|
|
25
|
-
} from "./chunk-
|
|
26
|
-
import "./chunk-
|
|
27
|
-
import "./chunk-
|
|
28
|
-
import "./chunk-FO5GGFOV.js";
|
|
26
|
+
} from "./chunk-KB64WNBZ.js";
|
|
27
|
+
import "./chunk-HEXKPKCK.js";
|
|
28
|
+
import "./chunk-VG45TUYK.js";
|
|
29
29
|
import {
|
|
30
30
|
getLogger
|
|
31
31
|
} from "./chunk-6MLEBAYZ.js";
|
|
32
|
+
import "./chunk-7JDMYTFZ.js";
|
|
32
33
|
import "./chunk-VT4PDUYT.js";
|
|
33
34
|
|
|
34
35
|
// src/commands/commit.ts
|
|
@@ -104,7 +105,7 @@ var CommitCommand = class {
|
|
|
104
105
|
}
|
|
105
106
|
const settings = await this.settingsManager.loadSettings(worktreePath);
|
|
106
107
|
const providerType = ((_a = settings.issueManagement) == null ? void 0 : _a.provider) ?? "github";
|
|
107
|
-
const issuePrefix = IssueManagementProviderFactory.create(providerType).issuePrefix;
|
|
108
|
+
const issuePrefix = IssueManagementProviderFactory.create(providerType, settings).issuePrefix;
|
|
108
109
|
const shouldSkipVerify = input.wipCommit === true || validationPassed && (((_c = (_b = settings.workflows) == null ? void 0 : _b.issue) == null ? void 0 : _c.noVerify) ?? false);
|
|
109
110
|
let commitMessage = input.message;
|
|
110
111
|
if (input.wipCommit && !input.message) {
|
|
@@ -180,7 +181,7 @@ var CommitCommand = class {
|
|
|
180
181
|
* Similar to SummaryCommand.autoDetectFromCurrentDirectory()
|
|
181
182
|
*/
|
|
182
183
|
async autoDetectIssue(worktreePath) {
|
|
183
|
-
var _a, _b, _c, _d, _e;
|
|
184
|
+
var _a, _b, _c, _d, _e, _f;
|
|
184
185
|
const logger = getLogger();
|
|
185
186
|
const currentDir = path.basename(worktreePath);
|
|
186
187
|
const prPattern = /_pr_(\d+)$/;
|
|
@@ -199,7 +200,7 @@ var CommitCommand = class {
|
|
|
199
200
|
logger.debug(`Auto-detected issue #${issueNumber} from directory: ${currentDir}`);
|
|
200
201
|
const metadata2 = await this.metadataManager.readMetadata(worktreePath);
|
|
201
202
|
return {
|
|
202
|
-
issueNumber: ((_b = metadata2 == null ? void 0 : metadata2.issue_numbers) == null ? void 0 : _b[0]) ?? issueNumber,
|
|
203
|
+
issueNumber: (metadata2 == null ? void 0 : metadata2.issueKey) ?? ((_b = metadata2 == null ? void 0 : metadata2.issue_numbers) == null ? void 0 : _b[0]) ?? issueNumber,
|
|
203
204
|
loomType: (metadata2 == null ? void 0 : metadata2.issueType) ?? "issue"
|
|
204
205
|
};
|
|
205
206
|
}
|
|
@@ -211,7 +212,7 @@ var CommitCommand = class {
|
|
|
211
212
|
logger.debug(`Auto-detected issue #${branchIssueNumber} from branch: ${currentBranch}`);
|
|
212
213
|
const metadata2 = await this.metadataManager.readMetadata(worktreePath);
|
|
213
214
|
return {
|
|
214
|
-
issueNumber: ((_c = metadata2 == null ? void 0 : metadata2.issue_numbers) == null ? void 0 : _c[0]) ?? branchIssueNumber,
|
|
215
|
+
issueNumber: (metadata2 == null ? void 0 : metadata2.issueKey) ?? ((_c = metadata2 == null ? void 0 : metadata2.issue_numbers) == null ? void 0 : _c[0]) ?? branchIssueNumber,
|
|
215
216
|
loomType: (metadata2 == null ? void 0 : metadata2.issueType) ?? "issue"
|
|
216
217
|
};
|
|
217
218
|
}
|
|
@@ -220,9 +221,9 @@ var CommitCommand = class {
|
|
|
220
221
|
const metadata = await this.metadataManager.readMetadata(worktreePath);
|
|
221
222
|
let resolvedIssueNumber;
|
|
222
223
|
const loomType = (metadata == null ? void 0 : metadata.issueType) ?? "branch";
|
|
223
|
-
if (loomType === "issue" && ((_d = metadata == null ? void 0 : metadata.issue_numbers) == null ? void 0 : _d[0])) {
|
|
224
|
-
resolvedIssueNumber = metadata.issue_numbers[0];
|
|
225
|
-
} else if (loomType === "pr" && ((
|
|
224
|
+
if (loomType === "issue" && ((metadata == null ? void 0 : metadata.issueKey) || ((_d = metadata == null ? void 0 : metadata.issue_numbers) == null ? void 0 : _d[0]))) {
|
|
225
|
+
resolvedIssueNumber = (metadata == null ? void 0 : metadata.issueKey) ?? ((_e = metadata == null ? void 0 : metadata.issue_numbers) == null ? void 0 : _e[0]);
|
|
226
|
+
} else if (loomType === "pr" && ((_f = metadata == null ? void 0 : metadata.pr_numbers) == null ? void 0 : _f[0])) {
|
|
226
227
|
resolvedIssueNumber = metadata.pr_numbers[0];
|
|
227
228
|
}
|
|
228
229
|
return {
|
|
@@ -235,4 +236,4 @@ export {
|
|
|
235
236
|
CommitCommand,
|
|
236
237
|
WorktreeValidationError
|
|
237
238
|
};
|
|
238
|
-
//# sourceMappingURL=commit-
|
|
239
|
+
//# sourceMappingURL=commit-L3EPY5QG.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, settings).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\ttimeout: settings.git?.commitTimeout,\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' | 'epic'\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 key from metadata for more accuracy (canonical case)\n\t\t\tconst metadata = await this.metadataManager.readMetadata(worktreePath)\n\t\t\treturn {\n\t\t\t\tissueNumber: metadata?.issueKey ?? 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?.issueKey ?? 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?.issueKey || metadata?.issue_numbers?.[0])) {\n\t\t\tresolvedIssueNumber = metadata?.issueKey ?? 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-
|
|
5
|
-
import "./chunk-YKFCCV6S.js";
|
|
4
|
+
} from "./chunk-NRSWLOAZ.js";
|
|
6
5
|
import {
|
|
7
6
|
runScript
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-WWKOVDWC.js";
|
|
8
|
+
import "./chunk-WY4QBK43.js";
|
|
9
|
+
import "./chunk-VGGST52X.js";
|
|
10
10
|
import {
|
|
11
11
|
getPackageScripts
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-YQ57ORTV.js";
|
|
13
|
+
import "./chunk-MNHZB4Z2.js";
|
|
14
|
+
import "./chunk-YYAKPQBT.js";
|
|
15
|
+
import "./chunk-KB64WNBZ.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-
|
|
57
|
+
//# sourceMappingURL=compile-ZS4HYRX5.js.map
|
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
TelemetryService
|
|
4
|
+
} from "./chunk-RSYT7MVI.js";
|
|
2
5
|
import {
|
|
3
6
|
FirstRunManager
|
|
4
7
|
} from "./chunk-Q7POFB5Q.js";
|
|
5
8
|
import {
|
|
6
9
|
executeGitCommand
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
+
} from "./chunk-MNHZB4Z2.js";
|
|
11
|
+
import "./chunk-YYAKPQBT.js";
|
|
12
|
+
import "./chunk-KB64WNBZ.js";
|
|
10
13
|
import {
|
|
11
14
|
checkGhAuth,
|
|
12
15
|
executeGhCommand
|
|
13
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-VG45TUYK.js";
|
|
17
|
+
import "./chunk-6MLEBAYZ.js";
|
|
14
18
|
import {
|
|
15
19
|
promptInput
|
|
16
20
|
} from "./chunk-7JDMYTFZ.js";
|
|
17
|
-
import "./chunk-6MLEBAYZ.js";
|
|
18
21
|
import {
|
|
19
22
|
logger
|
|
20
23
|
} from "./chunk-VT4PDUYT.js";
|
|
@@ -136,6 +139,11 @@ var ContributeCommand = class {
|
|
|
136
139
|
* @param repository - Optional repository in various formats (owner/repo, github.com/owner/repo, or full URL)
|
|
137
140
|
*/
|
|
138
141
|
async execute(repository) {
|
|
142
|
+
try {
|
|
143
|
+
TelemetryService.getInstance().track("contribute.started", { tracker: "github" });
|
|
144
|
+
} catch (error) {
|
|
145
|
+
logger.debug(`Failed to track contribute.started telemetry: ${error instanceof Error ? error.message : String(error)}`);
|
|
146
|
+
}
|
|
139
147
|
let repoPath;
|
|
140
148
|
if (repository) {
|
|
141
149
|
repoPath = parseGitHubRepoUrl(repository);
|
|
@@ -327,4 +335,4 @@ export {
|
|
|
327
335
|
validateDirectoryPath,
|
|
328
336
|
validateRepoExists
|
|
329
337
|
};
|
|
330
|
-
//# sourceMappingURL=contribute-
|
|
338
|
+
//# sourceMappingURL=contribute-ORDDQGSL.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/commands/contribute.ts"],"sourcesContent":["import { logger } from '../utils/logger.js'\nimport { checkGhAuth, executeGhCommand } from '../utils/github.js'\nimport { executeGitCommand } from '../utils/git.js'\nimport { promptInput } from '../utils/prompt.js'\nimport { existsSync, accessSync, constants } from 'fs'\nimport { writeFile, mkdir } from 'fs/promises'\nimport path from 'path'\nimport { InitCommand } from './init.js'\nimport chalk from 'chalk'\nimport { FirstRunManager } from '../utils/FirstRunManager.js'\nimport { TelemetryService } from '../lib/TelemetryService.js'\n\nconst DEFAULT_REPO = 'iloom-ai/iloom-cli'\n\n// Maximum path length for most file systems\nconst MAX_PATH_LENGTH = 255\n\n// Reserved names on Windows (also avoid on all platforms for portability)\nconst RESERVED_NAMES = [\n\t'CON', 'PRN', 'AUX', 'NUL',\n\t'COM1', 'COM2', 'COM3', 'COM4', 'COM5', 'COM6', 'COM7', 'COM8', 'COM9',\n\t'LPT1', 'LPT2', 'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9',\n]\n\n// Invalid characters for directory names (cross-platform)\n// eslint-disable-next-line no-control-regex\nconst INVALID_CHARS_PATTERN = /[<>:\"|?*\\x00-\\x1f]/\n\n\n/**\n * Validation result for directory input\n */\ninterface DirectoryValidationResult {\n\tisValid: boolean\n\terror?: string\n}\n\n/**\n * Validate directory name format\n * @param directoryName - The directory name (not full path)\n * @returns Validation result with error message if invalid\n */\nexport function validateDirectoryName(directoryName: string): DirectoryValidationResult {\n\t// Check for empty or whitespace-only\n\tif (!directoryName || directoryName.trim() === '') {\n\t\treturn { isValid: false, error: 'Directory name cannot be empty' }\n\t}\n\n\tconst trimmed = directoryName.trim()\n\tconst baseName = path.basename(trimmed)\n\n\t// Check for invalid characters\n\tif (INVALID_CHARS_PATTERN.test(baseName)) {\n\t\treturn { isValid: false, error: 'Directory name contains invalid characters (<>:\"|?*)' }\n\t}\n\n\t// Check for reserved names (case-insensitive)\n\tif (RESERVED_NAMES.includes(baseName.toUpperCase())) {\n\t\treturn { isValid: false, error: `\"${baseName}\" is a reserved name and cannot be used` }\n\t}\n\n\t// Check for names that start/end with dots or spaces (problematic on some systems)\n\tif (baseName.startsWith('.') && baseName === '.') {\n\t\treturn { isValid: false, error: 'Directory name cannot be just a dot' }\n\t}\n\tif (baseName.endsWith('.') || baseName.endsWith(' ')) {\n\t\treturn { isValid: false, error: 'Directory name cannot end with a dot or space' }\n\t}\n\n\treturn { isValid: true }\n}\n\n/**\n * Parse GitHub repository URL in multiple formats and return normalized 'owner/repo' format\n * Supported formats:\n * - Full URL: https://github.com/owner/repo\n * - Shortened: github.com/owner/repo\n * - Direct: owner/repo\n * @param input - The repository URL/identifier to parse\n * @returns Normalized 'owner/repo' format\n * @throws Error if input doesn't match any supported format\n */\nexport function parseGitHubRepoUrl(input: string): string {\n\tconst trimmed = input.trim()\n\n\t// Pattern 1: Full URL - https://github.com/owner/repo or http://github.com/owner/repo\n\tconst fullUrlMatch = trimmed.match(/^https?:\\/\\/github\\.com\\/([^/]+)\\/([^/]+?)(?:\\.git)?$/i)\n\tif (fullUrlMatch) {\n\t\treturn `${fullUrlMatch[1]}/${fullUrlMatch[2]}`\n\t}\n\n\t// Pattern 2: Shortened URL - github.com/owner/repo\n\tconst shortUrlMatch = trimmed.match(/^github\\.com\\/([^/]+)\\/([^/]+?)(?:\\.git)?$/i)\n\tif (shortUrlMatch) {\n\t\treturn `${shortUrlMatch[1]}/${shortUrlMatch[2]}`\n\t}\n\n\t// Pattern 3: Direct format - owner/repo (must have exactly one slash, no other special chars)\n\tconst directMatch = trimmed.match(/^([a-zA-Z0-9_.-]+)\\/([a-zA-Z0-9_.-]+)$/)\n\tif (directMatch) {\n\t\treturn `${directMatch[1]}/${directMatch[2]}`\n\t}\n\n\tthrow new Error(\n\t\t`Invalid repository format: \"${input}\". ` +\n\t\t`Expected formats: \"owner/repo\", \"github.com/owner/repo\", or \"https://github.com/owner/repo\"`\n\t)\n}\n\n/**\n * Validate that a GitHub repository exists\n * @param repoPath - Repository in 'owner/repo' format\n * @returns true if repository exists, false otherwise\n * @throws Error for unexpected API errors (not 404)\n */\nexport async function validateRepoExists(repoPath: string): Promise<boolean> {\n\ttry {\n\t\tawait executeGhCommand(['api', `repos/${repoPath}`])\n\t\treturn true\n\t} catch (error) {\n\t\t// 404 means repo doesn't exist or user doesn't have access\n\t\tif (error instanceof Error && error.message.includes('Not Found')) {\n\t\t\treturn false\n\t\t}\n\t\t// Re-throw unexpected errors\n\t\tthrow error\n\t}\n}\n\n/**\n * Validate full directory path\n * @param directoryPath - The full directory path\n * @returns Validation result with error message if invalid\n */\nexport function validateDirectoryPath(directoryPath: string): DirectoryValidationResult {\n\t// First validate the directory name component\n\tconst nameValidation = validateDirectoryName(directoryPath)\n\tif (!nameValidation.isValid) {\n\t\treturn nameValidation\n\t}\n\n\tconst trimmed = directoryPath.trim()\n\tconst absolutePath = path.resolve(trimmed)\n\n\t// Check path length\n\tif (absolutePath.length > MAX_PATH_LENGTH) {\n\t\treturn {\n\t\t\tisValid: false,\n\t\t\terror: `Path is too long (${absolutePath.length} characters). Maximum is ${MAX_PATH_LENGTH} characters.`\n\t\t}\n\t}\n\n\t// Check if directory already exists\n\tif (existsSync(absolutePath)) {\n\t\treturn { isValid: false, error: `Directory already exists: ${trimmed}` }\n\t}\n\n\t// Check if parent directory exists\n\tconst parentDir = path.dirname(absolutePath)\n\tif (!existsSync(parentDir)) {\n\t\treturn { isValid: false, error: `Parent directory does not exist: ${parentDir}` }\n\t}\n\n\t// Check if parent directory is writable\n\ttry {\n\t\taccessSync(parentDir, constants.W_OK)\n\t} catch {\n\t\treturn { isValid: false, error: `Parent directory is not writable: ${parentDir}` }\n\t}\n\n\treturn { isValid: true }\n}\n\n\n/**\n * ContributeCommand - Set up local development environment for contributing to iloom\n * Implements issue #220: streamlined contributor onboarding workflow\n */\nexport class ContributeCommand {\n\tconstructor(_initCommand?: InitCommand) {}\n\n\t/**\n\t * Main entry point for the contribute command\n\t * Automates fork creation, cloning, and upstream configuration\n\t * @param repository - Optional repository in various formats (owner/repo, github.com/owner/repo, or full URL)\n\t */\n\tpublic async execute(repository?: string): Promise<void> {\n\t\t// Track contribute.started telemetry event\n\t\ttry {\n\t\t\tTelemetryService.getInstance().track('contribute.started', { tracker: 'github' })\n\t\t} catch (error: unknown) {\n\t\t\tlogger.debug(`Failed to track contribute.started telemetry: ${error instanceof Error ? error.message : String(error)}`)\n\t\t}\n\n\t\t// Parse and validate repository if provided, otherwise use default\n\t\tlet repoPath: string\n\t\tif (repository) {\n\t\t\trepoPath = parseGitHubRepoUrl(repository)\n\t\t\tlogger.info(`Validating repository ${chalk.cyan(repoPath)}...`)\n\t\t\tconst exists = await validateRepoExists(repoPath)\n\t\t\tif (!exists) {\n\t\t\t\tthrow new Error(`Repository not found: ${repoPath}. Please check the repository exists and you have access.`)\n\t\t\t}\n\t\t} else {\n\t\t\trepoPath = DEFAULT_REPO\n\t\t}\n\n\t\t// Extract owner and repo name from path (guaranteed to be valid format after parseGitHubRepoUrl)\n\t\tconst parts = repoPath.split('/')\n\t\tconst owner = parts[0] as string\n\t\tconst repoName = parts[1] as string\n\t\tconst upstreamUrl = `https://github.com/${repoPath}.git`\n\n\t\tlogger.info(chalk.bold(`Setting up contributor environment for ${chalk.cyan(repoPath)}...`))\n\n\t\t// Step 1: Verify gh CLI authenticated\n\t\tconst username = await this.getAuthenticatedUsername()\n\t\tlogger.success(`Authenticated as ${chalk.cyan(username)}`)\n\n\t\t// Step 2: Check for existing fork\n\t\tconst hasFork = await this.forkExists(username, repoName)\n\n\t\t// Step 3: Create fork if needed\n\t\tif (!hasFork) {\n\t\t\tlogger.info(`Creating fork of ${repoPath}...`)\n\t\t\tawait this.createFork(repoPath)\n\t\t\tlogger.success('Fork created successfully')\n\t\t} else {\n\t\t\tlogger.info('Using existing fork')\n\t\t}\n\n\t\t// Step 4: Prompt for directory with validation and retry loop\n\t\tconst directory = await this.promptForDirectory(repoName)\n\n\t\t// Handle cancelled input\n\t\tif (!directory) {\n\t\t\tlogger.info('Setup cancelled by user')\n\t\t\tprocess.exit(0)\n\t\t}\n\n\t\tconst absolutePath = path.resolve(directory)\n\n\t\t// Step 5: Clone repository (gh CLI handles SSH/HTTPS automatically based on git config)\n\t\tlogger.info(`Cloning repository to ${directory}...`)\n\t\tawait this.cloneRepository(username, repoName, directory)\n\t\tlogger.success('Repository cloned successfully')\n\n\t\t// Step 6: Add upstream remote if it doesn't exist\n\t\tawait this.addUpstreamRemote(absolutePath, upstreamUrl)\n\n\t\t// Step 7: Configure settings\n\t\tlogger.info('Configuring iloom settings...')\n\t\tawait this.configureSettings(absolutePath)\n\t\tlogger.success('Settings configured')\n\n\t\tlogger.success(chalk.bold.green('\\nContributor environment setup complete!'))\n\t\tlogger.info(`\\nNext steps:`)\n\t\tlogger.info(` 1. cd ${directory}`)\n\t\tif (repoPath === DEFAULT_REPO) {\n\t\t\tlogger.info(` 2. pnpm install`)\n\t\t\tlogger.info(` 3. iloom start <issue_number>`)\n\t\t} else {\n\t\t\tlogger.info(` 2. See README.md or CONTRIBUTING.md for setup instructions`)\n\t\t\tlogger.info(` 3. If this is not a JavaScript/TypeScript project, run:`)\n\t\t\tlogger.info(` iloom init \"help me set up iloom for this non-javascript/typescript project\"`)\n\t\t}\n\t\tlogger.info(`\\nHappy contributing to ${owner}/${repoName}!`)\n\t}\n\n\t/**\n\t * Get authenticated GitHub username\n\t * @throws Error if not authenticated\n\t */\n\tprivate async getAuthenticatedUsername(): Promise<string> {\n\t\tconst authStatus = await checkGhAuth()\n\n\t\tif (!authStatus.hasAuth) {\n\t\t\tthrow new Error(\n\t\t\t\t'GitHub CLI is not authenticated. Please run: gh auth login'\n\t\t\t)\n\t\t}\n\n\t\tif (!authStatus.username) {\n\t\t\t// Try to fetch username from gh api if not in auth status\n\t\t\ttry {\n\t\t\t\tconst user = await executeGhCommand<{ login: string }>(['api', 'user', '--json', 'login'])\n\t\t\t\treturn user.login\n\t\t\t} catch (error) {\n\t\t\t\tconst message = error instanceof Error ? error.message : String(error)\n\t\t\t\tthrow new Error(`Unable to determine GitHub username: ${message}`)\n\t\t\t}\n\t\t}\n\n\t\treturn authStatus.username\n\t}\n\n\t/**\n\t * Check if user already has a fork of the target repository\n\t * @param username - GitHub username\n\t * @param repoName - Repository name (e.g., 'iloom-cli' from 'iloom-ai/iloom-cli')\n\t */\n\tprivate async forkExists(username: string, repoName: string): Promise<boolean> {\n\t\ttry {\n\t\t\tawait executeGhCommand(['api', `repos/${username}/${repoName}`])\n\t\t\treturn true\n\t\t} catch (error) {\n\t\t\t// 404 means no fork exists\n\t\t\tif (error instanceof Error && error.message.includes('Not Found')) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t// Re-throw unexpected errors\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t/**\n\t * Create a fork of the target repository without cloning\n\t * @param repoPath - Full repository path (e.g., 'iloom-ai/iloom-cli')\n\t */\n\tprivate async createFork(repoPath: string): Promise<void> {\n\t\tawait executeGhCommand(['repo', 'fork', repoPath, '--clone=false'])\n\t}\n\n\n\t/**\n\t * Clone the repository using simplified gh CLI approach\n\t * @param username - GitHub username\n\t * @param repoName - Repository name (e.g., 'iloom-cli')\n\t * @param directory - Target directory for clone\n\t */\n\tprivate async cloneRepository(\n\t\tusername: string,\n\t\trepoName: string,\n\t\tdirectory: string\n\t): Promise<void> {\n\t\tconst repoIdentifier = `${username}/${repoName}`\n\t\t// Always use gh repo clone - it handles SSH/HTTPS based on user's git config\n\t\tawait executeGhCommand(['repo', 'clone', repoIdentifier, directory])\n\t}\n\n\t/**\n\t * Add upstream remote if it doesn't already exist\n\t * @param directory - Cloned repository directory\n\t * @param upstreamUrl - URL for the upstream remote\n\t */\n\tprivate async addUpstreamRemote(directory: string, upstreamUrl: string): Promise<void> {\n\t\ttry {\n\t\t\t// Check if upstream remote exists\n\t\t\tawait executeGitCommand(['remote', 'get-url', 'upstream'], { cwd: directory })\n\t\t\tlogger.info('Upstream remote already configured')\n\t\t} catch {\n\t\t\t// Upstream doesn't exist, add it\n\t\t\tlogger.info('Adding upstream remote...')\n\t\t\tawait executeGitCommand(\n\t\t\t\t['remote', 'add', 'upstream', upstreamUrl],\n\t\t\t\t{ cwd: directory }\n\t\t\t)\n\t\t\tlogger.success('Upstream remote configured')\n\t\t}\n\t}\n\n\t/**\n\t * Prompt for directory with validation and retry loop\n\t * @param repoName - Repository name for default directory suggestion\n\t * @returns The validated directory path, or null if user cancels\n\t */\n\tprivate async promptForDirectory(repoName: string): Promise<string | null> {\n\t\tconst maxRetries = 3\n\t\tlet attempts = 0\n\t\tconst defaultDir = `./${repoName}`\n\n\t\twhile (attempts < maxRetries) {\n\t\t\tconst directory = await promptInput(\n\t\t\t\t'Where should the repository be cloned?',\n\t\t\t\tdefaultDir\n\t\t\t)\n\n\t\t\t// Handle empty input (user cancelled by entering empty string after exhausting default)\n\t\t\tif (!directory || directory.trim() === '') {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tconst trimmed = directory.trim()\n\n\t\t\t// Validate the directory path\n\t\t\tconst validation = validateDirectoryPath(trimmed)\n\t\t\tif (validation.isValid) {\n\t\t\t\treturn trimmed\n\t\t\t}\n\n\t\t\t// Show error and increment attempts\n\t\t\tattempts++\n\t\t\tif (attempts < maxRetries) {\n\t\t\t\tlogger.error(`${validation.error}`)\n\t\t\t\tlogger.info(`Please try again (${maxRetries - attempts} attempts remaining)`)\n\t\t\t} else {\n\t\t\t\tlogger.error(`${validation.error}`)\n\t\t\t\tlogger.error('Maximum retry attempts reached')\n\t\t\t\tthrow new Error(`Invalid directory after ${maxRetries} attempts: ${validation.error}`)\n\t\t\t}\n\t\t}\n\n\t\treturn null\n\t}\n\n\n\t/**\n\t * Configure .iloom/settings.json with upstream remote\n\t */\n\tprivate async configureSettings(directory: string): Promise<void> {\n\t\tconst iloomDir = path.join(directory, '.iloom')\n\t\tconst settingsPath = path.join(iloomDir, 'settings.local.json')\n\n\t\t// Create .iloom directory\n\t\tawait mkdir(iloomDir, { recursive: true })\n\n\t\t// Create settings.json with upstream remote configuration and github-pr mode\n\t\tconst settings = {\n\t\t\tissueManagement: {\n\t\t\t\tgithub: {\n\t\t\t\t\tremote: 'upstream',\n\t\t\t\t},\n\t\t\t},\n\t\t\tmergeBehavior: {\n\t\t\t\tmode: 'github-draft-pr',\n\t\t\t},\n\t\t}\n\n\t\tawait writeFile(settingsPath, JSON.stringify(settings, null, 2) + '\\n')\n\n\t\t// Mark project as configured for il projects list and VSCode extension detection\n\t\tconst firstRunManager = new FirstRunManager()\n\t\tawait firstRunManager.markProjectAsConfigured(directory)\n\t\tlogger.debug('Project marked as configured', { directory })\n\t}\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,32 +1,34 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
DevServerManager
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-5MWV33NN.js";
|
|
5
|
+
import "./chunk-ZEWU5PZK.js";
|
|
6
6
|
import {
|
|
7
7
|
getWorkspacePort
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-3D7WQM7I.js";
|
|
9
|
+
import "./chunk-WWKOVDWC.js";
|
|
9
10
|
import {
|
|
10
11
|
IdentifierParser
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-4LKGCFGG.js";
|
|
12
|
+
} from "./chunk-WY4QBK43.js";
|
|
13
13
|
import {
|
|
14
14
|
GitWorktreeManager
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-VGGST52X.js";
|
|
16
|
+
import {
|
|
17
|
+
ProjectCapabilityDetector
|
|
18
|
+
} from "./chunk-MORRVYPT.js";
|
|
19
|
+
import "./chunk-YQ57ORTV.js";
|
|
16
20
|
import {
|
|
17
21
|
extractSettingsOverrides
|
|
18
22
|
} from "./chunk-GYCR2LOU.js";
|
|
19
|
-
import {
|
|
20
|
-
ProjectCapabilityDetector
|
|
21
|
-
} from "./chunk-TL72BGP6.js";
|
|
22
|
-
import "./chunk-VOGGLPG5.js";
|
|
23
23
|
import {
|
|
24
24
|
extractIssueNumber
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-MNHZB4Z2.js";
|
|
26
26
|
import {
|
|
27
27
|
SettingsManager
|
|
28
|
-
} from "./chunk-
|
|
29
|
-
import
|
|
28
|
+
} from "./chunk-YYAKPQBT.js";
|
|
29
|
+
import {
|
|
30
|
+
MetadataManager
|
|
31
|
+
} from "./chunk-KB64WNBZ.js";
|
|
30
32
|
import "./chunk-6MLEBAYZ.js";
|
|
31
33
|
import {
|
|
32
34
|
isNoEnvFilesFoundError,
|
|
@@ -37,12 +39,13 @@ import {
|
|
|
37
39
|
// src/commands/dev-server.ts
|
|
38
40
|
import path from "path";
|
|
39
41
|
var DevServerCommand = class {
|
|
40
|
-
constructor(gitWorktreeManager = new GitWorktreeManager(), capabilityDetector = new ProjectCapabilityDetector(), identifierParser = new IdentifierParser(new GitWorktreeManager()), devServerManager = new DevServerManager(), settingsManager = new SettingsManager()) {
|
|
42
|
+
constructor(gitWorktreeManager = new GitWorktreeManager(), capabilityDetector = new ProjectCapabilityDetector(), identifierParser = new IdentifierParser(new GitWorktreeManager()), devServerManager = new DevServerManager(), settingsManager = new SettingsManager(), metadataManager = new MetadataManager()) {
|
|
41
43
|
this.gitWorktreeManager = gitWorktreeManager;
|
|
42
44
|
this.capabilityDetector = capabilityDetector;
|
|
43
45
|
this.identifierParser = identifierParser;
|
|
44
46
|
this.devServerManager = devServerManager;
|
|
45
47
|
this.settingsManager = settingsManager;
|
|
48
|
+
this.metadataManager = metadataManager;
|
|
46
49
|
}
|
|
47
50
|
/**
|
|
48
51
|
* Output JSON to stdout (used for --json flag)
|
|
@@ -68,6 +71,11 @@ var DevServerCommand = class {
|
|
|
68
71
|
logger.warn(`Failed to load env files: ${envResult.error.message}`);
|
|
69
72
|
}
|
|
70
73
|
}
|
|
74
|
+
envOverrides.ILOOM_LOOM = this.formatLoomIdentifier(parsed);
|
|
75
|
+
const metadata = await this.metadataManager.readMetadata(worktree.path);
|
|
76
|
+
if (metadata == null ? void 0 : metadata.colorHex) {
|
|
77
|
+
envOverrides.ILOOM_COLOR_HEX = metadata.colorHex;
|
|
78
|
+
}
|
|
71
79
|
const { capabilities } = await this.capabilityDetector.detectCapabilities(worktree.path);
|
|
72
80
|
logger.debug(`Detected capabilities: ${capabilities.join(", ")}`);
|
|
73
81
|
if (!capabilities.includes("web")) {
|
|
@@ -252,8 +260,14 @@ var DevServerCommand = class {
|
|
|
252
260
|
}
|
|
253
261
|
return `branch "${parsed.branchName}"${autoLabel}`;
|
|
254
262
|
}
|
|
263
|
+
/**
|
|
264
|
+
* Format loom identifier for ILOOM_LOOM env var
|
|
265
|
+
*/
|
|
266
|
+
formatLoomIdentifier(parsed) {
|
|
267
|
+
return parsed.originalInput;
|
|
268
|
+
}
|
|
255
269
|
};
|
|
256
270
|
export {
|
|
257
271
|
DevServerCommand
|
|
258
272
|
};
|
|
259
|
-
//# sourceMappingURL=dev-server-
|
|
273
|
+
//# sourceMappingURL=dev-server-FYZ2AQIH.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 { MetadataManager } from '../lib/MetadataManager.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' | 'epic'\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\tprivate metadataManager = new MetadataManager()\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// 3b. Set ILOOM_LOOM for loom identification\n\t\tenvOverrides.ILOOM_LOOM = this.formatLoomIdentifier(parsed)\n\n\t\t// 3c. Set ILOOM_COLOR_HEX from loom metadata if available\n\t\tconst metadata = await this.metadataManager.readMetadata(worktree.path)\n\t\tif (metadata?.colorHex) {\n\t\t\tenvOverrides.ILOOM_COLOR_HEX = metadata.colorHex\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\t/**\n\t * Format loom identifier for ILOOM_LOOM env var\n\t */\n\tprivate formatLoomIdentifier(parsed: ParsedDevServerInput): string {\n\t\treturn parsed.originalInput\n\t}\n}\n"],"mappings":"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","names":["message"]}
|
|
@@ -2,29 +2,29 @@
|
|
|
2
2
|
import {
|
|
3
3
|
IssueEnhancementService,
|
|
4
4
|
capitalizeFirstLetter
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-FB47TIJG.js";
|
|
6
|
+
import "./chunk-UWGVCXRF.js";
|
|
7
7
|
import "./chunk-YETJNRQM.js";
|
|
8
|
+
import {
|
|
9
|
+
ProjectCapabilityDetector
|
|
10
|
+
} from "./chunk-MORRVYPT.js";
|
|
11
|
+
import "./chunk-YQ57ORTV.js";
|
|
8
12
|
import {
|
|
9
13
|
AgentManager
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-QN47QVBX.js";
|
|
14
|
+
} from "./chunk-SF2P22EE.js";
|
|
12
15
|
import {
|
|
13
|
-
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
16
|
+
getClaudeVersion
|
|
17
|
+
} from "./chunk-ONQYPICO.js";
|
|
18
|
+
import "./chunk-4WJNIR5O.js";
|
|
16
19
|
import {
|
|
17
20
|
SettingsManager
|
|
18
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-YYAKPQBT.js";
|
|
19
22
|
import {
|
|
20
23
|
GitHubService
|
|
21
|
-
} from "./chunk-
|
|
22
|
-
import "./chunk-
|
|
23
|
-
import "./chunk-7JDMYTFZ.js";
|
|
24
|
-
import {
|
|
25
|
-
getClaudeVersion
|
|
26
|
-
} from "./chunk-FO5GGFOV.js";
|
|
24
|
+
} from "./chunk-KXDRI47U.js";
|
|
25
|
+
import "./chunk-VG45TUYK.js";
|
|
27
26
|
import "./chunk-6MLEBAYZ.js";
|
|
27
|
+
import "./chunk-7JDMYTFZ.js";
|
|
28
28
|
import {
|
|
29
29
|
logger
|
|
30
30
|
} from "./chunk-VT4PDUYT.js";
|
|
@@ -165,4 +165,4 @@ ${userBody}`;
|
|
|
165
165
|
export {
|
|
166
166
|
FeedbackCommand
|
|
167
167
|
};
|
|
168
|
-
//# sourceMappingURL=feedback-
|
|
168
|
+
//# sourceMappingURL=feedback-TMBXSCM5.js.map
|
|
@@ -34,9 +34,9 @@ import {
|
|
|
34
34
|
pushBranchToRemote,
|
|
35
35
|
removePlaceholderCommitFromHead,
|
|
36
36
|
removePlaceholderCommitFromHistory
|
|
37
|
-
} from "./chunk-
|
|
38
|
-
import "./chunk-
|
|
39
|
-
import "./chunk-
|
|
37
|
+
} from "./chunk-MNHZB4Z2.js";
|
|
38
|
+
import "./chunk-YYAKPQBT.js";
|
|
39
|
+
import "./chunk-KB64WNBZ.js";
|
|
40
40
|
import "./chunk-6MLEBAYZ.js";
|
|
41
41
|
import "./chunk-VT4PDUYT.js";
|
|
42
42
|
export {
|
|
@@ -75,4 +75,4 @@ export {
|
|
|
75
75
|
removePlaceholderCommitFromHead,
|
|
76
76
|
removePlaceholderCommitFromHistory
|
|
77
77
|
};
|
|
78
|
-
//# sourceMappingURL=git-
|
|
78
|
+
//# sourceMappingURL=git-ET64COO3.js.map
|
package/dist/hooks/iloom-hook.js
CHANGED
|
@@ -308,6 +308,20 @@ async function main() {
|
|
|
308
308
|
|
|
309
309
|
// Special handling for UserPromptSubmit - output JSON additionalContext instead of broadcasting
|
|
310
310
|
if (status === 'user_prompt_submit') {
|
|
311
|
+
// In swarm mode, agents handle their own workflow — only remind about code reviewer
|
|
312
|
+
if (process.env.ILOOM_SWARM === '1') {
|
|
313
|
+
const swarmReminder = `**REMINDER**: When the user requests a code review, use \`@agent-iloom-code-reviewer\`.`;
|
|
314
|
+
const output = {
|
|
315
|
+
hookSpecificOutput: {
|
|
316
|
+
hookEventName: 'UserPromptSubmit',
|
|
317
|
+
additionalContext: swarmReminder
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
console.log(JSON.stringify(output));
|
|
321
|
+
debug('UserPromptSubmit: swarm mode, output code reviewer reminder');
|
|
322
|
+
process.exit(0);
|
|
323
|
+
}
|
|
324
|
+
|
|
311
325
|
const reminder = `**REMINDER**: You MUST USE subagents to preserve your context window for ongoing conversation.
|
|
312
326
|
|
|
313
327
|
| Request Type | Action |
|
|
@@ -319,6 +333,7 @@ async function main() {
|
|
|
319
333
|
| 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\` - IN THIS CASE IT'S OK TO CREATE/UPDATE ISSUE COMMENTS |
|
|
320
334
|
| New features / complex changes | \`@agent-iloom-issue-analyze-and-plan\` → if approved, \`@agent-iloom-issue-implementer\` - IN THIS CASE IT'S OK TO CREATE/UPDATE ISSUE COMMENTS |
|
|
321
335
|
| Deep questions (how/why something works) | \`@agent-iloom-issue-analyzer\` |
|
|
336
|
+
| Code review request | \`@agent-iloom-code-reviewer\` |
|
|
322
337
|
|
|
323
338
|
Regarding creating/updating comments - if it's a trivial fix or quick answer, DO NOT create or update issue comments to avoid polluting the issue history. Only create/update comments for complex changes or new features as outlined above.`;
|
|
324
339
|
|