@iloom/cli 0.1.19 → 0.2.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/README.md +16 -0
- package/dist/ClaudeContextManager-LVCYRM6Q.js +13 -0
- package/dist/ClaudeService-WVTWB3DK.js +12 -0
- package/dist/{GitHubService-LWP4GKGH.js → GitHubService-7E2S5NNZ.js} +3 -3
- package/dist/{LoomLauncher-UMMLPIZO.js → LoomLauncher-CTSWJL35.js} +6 -6
- package/dist/README.md +16 -0
- package/dist/{SettingsManager-SKLUVE3K.js → SettingsManager-XOYCLH3D.js} +2 -2
- package/dist/{add-issue-X56V3XPB.js → add-issue-OBI325W7.js} +7 -7
- package/dist/{chunk-DEPYQRRB.js → chunk-2PLUQT6J.js} +2 -2
- package/dist/{chunk-VVH3ANF2.js → chunk-4IV6W4U5.js} +4 -4
- package/dist/{chunk-PV3GAXQO.js → chunk-6LEQW46Y.js} +2 -2
- package/dist/{chunk-VCMMAFXQ.js → chunk-CVLAZRNB.js} +2 -2
- package/dist/{chunk-FXV24OYZ.js → chunk-DJUGYNQE.js} +9 -2
- package/dist/{chunk-FXV24OYZ.js.map → chunk-DJUGYNQE.js.map} +1 -1
- package/dist/{chunk-KOCQAD2E.js → chunk-HBVFXN7R.js} +3 -3
- package/dist/{chunk-ELFT36PV.js → chunk-LHP6ROUM.js} +3 -3
- package/dist/{chunk-PXZBAC2M.js → chunk-MFU53H6J.js} +2 -2
- package/dist/{chunk-PR7FKQBG.js → chunk-RF2YI2XJ.js} +2 -2
- package/dist/{chunk-JXQXSC45.js → chunk-SWCRXDZC.js} +2 -2
- package/dist/{chunk-Q2KYPAH2.js → chunk-SYOSCMIT.js} +6 -6
- package/dist/{chunk-VYQLLHZ7.js → chunk-T3KEIB4D.js} +6 -2
- package/dist/{chunk-VYQLLHZ7.js.map → chunk-T3KEIB4D.js.map} +1 -1
- package/dist/{chunk-ZWXJBSUW.js → chunk-TS6DL67T.js} +2 -2
- package/dist/{chunk-IO4WFTL2.js → chunk-VETG35MF.js} +2 -2
- package/dist/{chunk-RSRO7564.js → chunk-ZE74H5BR.js} +28 -3
- package/dist/chunk-ZE74H5BR.js.map +1 -0
- package/dist/{claude-7LUVDZZ4.js → claude-ZIWDG4XG.js} +2 -2
- package/dist/{cleanup-ZHROIBSQ.js → cleanup-FEIVZSIV.js} +5 -5
- package/dist/cli.js +29 -29
- package/dist/cli.js.map +1 -1
- package/dist/{contribute-3MQJ3XAQ.js → contribute-EMZKCAC6.js} +6 -3
- package/dist/{contribute-3MQJ3XAQ.js.map → contribute-EMZKCAC6.js.map} +1 -1
- package/dist/{enhance-VGWUX474.js → enhance-MNA4ZGXW.js} +7 -7
- package/dist/{feedback-ZOUCCHN4.js → feedback-LFNMQBAZ.js} +6 -6
- package/dist/{finish-QJSK6Z7J.js → finish-TX5CJICB.js} +411 -17
- package/dist/finish-TX5CJICB.js.map +1 -0
- package/dist/{git-OUYMVYJX.js → git-WC6HZLOT.js} +2 -2
- package/dist/{ignite-HICLZEYU.js → ignite-MQWVJEAB.js} +7 -7
- package/dist/index.d.ts +20 -0
- package/dist/index.js +32 -3
- package/dist/index.js.map +1 -1
- package/dist/{init-UMKNHNV5.js → init-GJDYN2IK.js} +6 -6
- package/dist/mcp/{claude-YHHHLSXH.js → claude-NDFOCQQQ.js} +2 -2
- package/dist/mcp/{terminal-SDCMDVD7.js → terminal-OMNRFWB3.js} +28 -3
- package/dist/mcp/terminal-OMNRFWB3.js.map +1 -0
- package/dist/{open-ETZUFSE4.js → open-NXSN7XOC.js} +4 -4
- package/dist/prompts/init-prompt.txt +29 -0
- package/dist/{rebase-KBWFDZCN.js → rebase-DUNFOJVS.js} +6 -6
- package/dist/{remote-GJEZWRCC.js → remote-ZCXJVVNW.js} +4 -2
- package/dist/{run-4SVQ3WEU.js → run-O7ZK7CKA.js} +4 -4
- package/dist/schema/settings.schema.json +18 -0
- package/dist/{start-CT2ZEFP2.js → start-73I5W7WW.js} +15 -15
- package/dist/{terminal-3D6TUAKJ.js → terminal-BIRBZ4AZ.js} +2 -2
- package/dist/{test-git-MKZATGZN.js → test-git-T76HOTIA.js} +3 -3
- package/dist/{test-prefix-ZNLWDI3K.js → test-prefix-6HJUVQMH.js} +3 -3
- package/dist/{test-tabs-JRKY3QMM.js → test-tabs-RXDBZ6J7.js} +2 -2
- package/package.json +1 -1
- package/dist/ClaudeContextManager-JKR4WGNU.js +0 -13
- package/dist/ClaudeService-55DQGB7T.js +0 -12
- package/dist/chunk-RSRO7564.js.map +0 -1
- package/dist/finish-QJSK6Z7J.js.map +0 -1
- package/dist/mcp/terminal-SDCMDVD7.js.map +0 -1
- /package/dist/{ClaudeContextManager-JKR4WGNU.js.map → ClaudeContextManager-LVCYRM6Q.js.map} +0 -0
- /package/dist/{ClaudeService-55DQGB7T.js.map → ClaudeService-WVTWB3DK.js.map} +0 -0
- /package/dist/{GitHubService-LWP4GKGH.js.map → GitHubService-7E2S5NNZ.js.map} +0 -0
- /package/dist/{LoomLauncher-UMMLPIZO.js.map → LoomLauncher-CTSWJL35.js.map} +0 -0
- /package/dist/{SettingsManager-SKLUVE3K.js.map → SettingsManager-XOYCLH3D.js.map} +0 -0
- /package/dist/{add-issue-X56V3XPB.js.map → add-issue-OBI325W7.js.map} +0 -0
- /package/dist/{chunk-DEPYQRRB.js.map → chunk-2PLUQT6J.js.map} +0 -0
- /package/dist/{chunk-VVH3ANF2.js.map → chunk-4IV6W4U5.js.map} +0 -0
- /package/dist/{chunk-PV3GAXQO.js.map → chunk-6LEQW46Y.js.map} +0 -0
- /package/dist/{chunk-VCMMAFXQ.js.map → chunk-CVLAZRNB.js.map} +0 -0
- /package/dist/{chunk-KOCQAD2E.js.map → chunk-HBVFXN7R.js.map} +0 -0
- /package/dist/{chunk-ELFT36PV.js.map → chunk-LHP6ROUM.js.map} +0 -0
- /package/dist/{chunk-PXZBAC2M.js.map → chunk-MFU53H6J.js.map} +0 -0
- /package/dist/{chunk-PR7FKQBG.js.map → chunk-RF2YI2XJ.js.map} +0 -0
- /package/dist/{chunk-JXQXSC45.js.map → chunk-SWCRXDZC.js.map} +0 -0
- /package/dist/{chunk-Q2KYPAH2.js.map → chunk-SYOSCMIT.js.map} +0 -0
- /package/dist/{chunk-ZWXJBSUW.js.map → chunk-TS6DL67T.js.map} +0 -0
- /package/dist/{chunk-IO4WFTL2.js.map → chunk-VETG35MF.js.map} +0 -0
- /package/dist/{claude-7LUVDZZ4.js.map → claude-ZIWDG4XG.js.map} +0 -0
- /package/dist/{cleanup-ZHROIBSQ.js.map → cleanup-FEIVZSIV.js.map} +0 -0
- /package/dist/{enhance-VGWUX474.js.map → enhance-MNA4ZGXW.js.map} +0 -0
- /package/dist/{feedback-ZOUCCHN4.js.map → feedback-LFNMQBAZ.js.map} +0 -0
- /package/dist/{git-OUYMVYJX.js.map → git-WC6HZLOT.js.map} +0 -0
- /package/dist/{ignite-HICLZEYU.js.map → ignite-MQWVJEAB.js.map} +0 -0
- /package/dist/{init-UMKNHNV5.js.map → init-GJDYN2IK.js.map} +0 -0
- /package/dist/mcp/{claude-YHHHLSXH.js.map → claude-NDFOCQQQ.js.map} +0 -0
- /package/dist/{open-ETZUFSE4.js.map → open-NXSN7XOC.js.map} +0 -0
- /package/dist/{rebase-KBWFDZCN.js.map → rebase-DUNFOJVS.js.map} +0 -0
- /package/dist/{remote-GJEZWRCC.js.map → remote-ZCXJVVNW.js.map} +0 -0
- /package/dist/{run-4SVQ3WEU.js.map → run-O7ZK7CKA.js.map} +0 -0
- /package/dist/{start-CT2ZEFP2.js.map → start-73I5W7WW.js.map} +0 -0
- /package/dist/{terminal-3D6TUAKJ.js.map → terminal-BIRBZ4AZ.js.map} +0 -0
- /package/dist/{test-git-MKZATGZN.js.map → test-git-T76HOTIA.js.map} +0 -0
- /package/dist/{test-prefix-ZNLWDI3K.js.map → test-prefix-6HJUVQMH.js.map} +0 -0
- /package/dist/{test-tabs-JRKY3QMM.js.map → test-tabs-RXDBZ6J7.js.map} +0 -0
package/README.md
CHANGED
|
@@ -316,7 +316,17 @@ iloom start <issue-number | pr-number | issue-description | branch-name>
|
|
|
316
316
|
|
|
317
317
|
iloom finish
|
|
318
318
|
# AI assisted validation, commit, merge steps, as well as loom cleanup (run this from the loom directory)
|
|
319
|
+
# Behavior depends on mergeBehavior.mode setting:
|
|
320
|
+
# local (default): Merge locally and cleanup
|
|
321
|
+
# github-pr: Push branch, create PR, prompt for cleanup
|
|
319
322
|
# Alias: dn
|
|
323
|
+
# Options:
|
|
324
|
+
# -f, --force - Skip confirmation prompts
|
|
325
|
+
# -n, --dry-run - Preview actions without executing
|
|
326
|
+
# --skip-build - Skip post-merge build verification
|
|
327
|
+
# --no-browser - Skip opening PR in browser (github-pr mode only)
|
|
328
|
+
# --cleanup - Clean up worktree after PR creation (github-pr mode only)
|
|
329
|
+
# --no-cleanup - Keep worktree after PR creation (github-pr mode only)
|
|
320
330
|
|
|
321
331
|
iloom rebase
|
|
322
332
|
# Rebase current branch on main with Claude-assisted conflict resolution (run this from a loom directory)
|
|
@@ -443,6 +453,10 @@ This allows teams to share project defaults via `settings.json` while individual
|
|
|
443
453
|
```jsonc
|
|
444
454
|
{
|
|
445
455
|
"mainBranch": "main",
|
|
456
|
+
"mergeBehavior": {
|
|
457
|
+
"mode": "local", // or "github-pr" for PR-based workflows
|
|
458
|
+
"remote": "upstream" // optional, defaults to issueManagement.github.remote
|
|
459
|
+
},
|
|
446
460
|
"capabilities": {
|
|
447
461
|
"web": { "basePort": 3000 },
|
|
448
462
|
"database": { "databaseUrlEnvVarName": "DATABASE_URL" }
|
|
@@ -477,6 +491,8 @@ This allows teams to share project defaults via `settings.json` while individual
|
|
|
477
491
|
|
|
478
492
|
** Common configuration options:**
|
|
479
493
|
- `mainBranch` - Primary branch for merging (default: "main")
|
|
494
|
+
- `mergeBehavior.mode` - How to finish work: "local" (merge locally) or "github-pr" (create PR) (default: "local")
|
|
495
|
+
- `mergeBehavior.remote` - Remote to target for PRs (optional, defaults to `issueManagement.github.remote`)
|
|
480
496
|
- `capabilities.web.basePort` - Base port for dev servers (default: 3000)
|
|
481
497
|
- `capabilities.database.databaseUrlEnvVarName` - Name of environment variable for database connection URL (default: "DATABASE_URL")
|
|
482
498
|
- `databaseProviders.neon.projectId` - Neon project ID (found in project URL, e.g., "fantastic-fox-3566354")
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
ClaudeContextManager
|
|
4
|
+
} from "./chunk-2PLUQT6J.js";
|
|
5
|
+
import "./chunk-LHP6ROUM.js";
|
|
6
|
+
import "./chunk-MFU53H6J.js";
|
|
7
|
+
import "./chunk-PVAVNJKS.js";
|
|
8
|
+
import "./chunk-T3KEIB4D.js";
|
|
9
|
+
import "./chunk-GEHQXLEI.js";
|
|
10
|
+
export {
|
|
11
|
+
ClaudeContextManager
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=ClaudeContextManager-LVCYRM6Q.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
ClaudeService
|
|
4
|
+
} from "./chunk-LHP6ROUM.js";
|
|
5
|
+
import "./chunk-MFU53H6J.js";
|
|
6
|
+
import "./chunk-PVAVNJKS.js";
|
|
7
|
+
import "./chunk-T3KEIB4D.js";
|
|
8
|
+
import "./chunk-GEHQXLEI.js";
|
|
9
|
+
export {
|
|
10
|
+
ClaudeService
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=ClaudeService-WVTWB3DK.js.map
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
GitHubService
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-TS6DL67T.js";
|
|
5
|
+
import "./chunk-SWCRXDZC.js";
|
|
6
6
|
import "./chunk-JNKJ7NJV.js";
|
|
7
7
|
import "./chunk-GEHQXLEI.js";
|
|
8
8
|
export {
|
|
9
9
|
GitHubService
|
|
10
10
|
};
|
|
11
|
-
//# sourceMappingURL=GitHubService-
|
|
11
|
+
//# sourceMappingURL=GitHubService-7E2S5NNZ.js.map
|
|
@@ -5,18 +5,18 @@ import {
|
|
|
5
5
|
import "./chunk-BLCTGFZN.js";
|
|
6
6
|
import {
|
|
7
7
|
ClaudeContextManager
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-2PLUQT6J.js";
|
|
9
9
|
import {
|
|
10
10
|
openMultipleTerminalWindows,
|
|
11
11
|
openTerminalWindow
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-ZE74H5BR.js";
|
|
13
13
|
import {
|
|
14
14
|
generateColorFromBranchName
|
|
15
15
|
} from "./chunk-ZZZWQGTS.js";
|
|
16
|
-
import "./chunk-
|
|
17
|
-
import "./chunk-
|
|
16
|
+
import "./chunk-LHP6ROUM.js";
|
|
17
|
+
import "./chunk-MFU53H6J.js";
|
|
18
18
|
import "./chunk-PVAVNJKS.js";
|
|
19
|
-
import "./chunk-
|
|
19
|
+
import "./chunk-T3KEIB4D.js";
|
|
20
20
|
import {
|
|
21
21
|
logger
|
|
22
22
|
} from "./chunk-GEHQXLEI.js";
|
|
@@ -260,4 +260,4 @@ var LoomLauncher = class {
|
|
|
260
260
|
export {
|
|
261
261
|
LoomLauncher
|
|
262
262
|
};
|
|
263
|
-
//# sourceMappingURL=LoomLauncher-
|
|
263
|
+
//# sourceMappingURL=LoomLauncher-CTSWJL35.js.map
|
package/dist/README.md
CHANGED
|
@@ -316,7 +316,17 @@ iloom start <issue-number | pr-number | issue-description | branch-name>
|
|
|
316
316
|
|
|
317
317
|
iloom finish
|
|
318
318
|
# AI assisted validation, commit, merge steps, as well as loom cleanup (run this from the loom directory)
|
|
319
|
+
# Behavior depends on mergeBehavior.mode setting:
|
|
320
|
+
# local (default): Merge locally and cleanup
|
|
321
|
+
# github-pr: Push branch, create PR, prompt for cleanup
|
|
319
322
|
# Alias: dn
|
|
323
|
+
# Options:
|
|
324
|
+
# -f, --force - Skip confirmation prompts
|
|
325
|
+
# -n, --dry-run - Preview actions without executing
|
|
326
|
+
# --skip-build - Skip post-merge build verification
|
|
327
|
+
# --no-browser - Skip opening PR in browser (github-pr mode only)
|
|
328
|
+
# --cleanup - Clean up worktree after PR creation (github-pr mode only)
|
|
329
|
+
# --no-cleanup - Keep worktree after PR creation (github-pr mode only)
|
|
320
330
|
|
|
321
331
|
iloom rebase
|
|
322
332
|
# Rebase current branch on main with Claude-assisted conflict resolution (run this from a loom directory)
|
|
@@ -443,6 +453,10 @@ This allows teams to share project defaults via `settings.json` while individual
|
|
|
443
453
|
```jsonc
|
|
444
454
|
{
|
|
445
455
|
"mainBranch": "main",
|
|
456
|
+
"mergeBehavior": {
|
|
457
|
+
"mode": "local", // or "github-pr" for PR-based workflows
|
|
458
|
+
"remote": "upstream" // optional, defaults to issueManagement.github.remote
|
|
459
|
+
},
|
|
446
460
|
"capabilities": {
|
|
447
461
|
"web": { "basePort": 3000 },
|
|
448
462
|
"database": { "databaseUrlEnvVarName": "DATABASE_URL" }
|
|
@@ -477,6 +491,8 @@ This allows teams to share project defaults via `settings.json` while individual
|
|
|
477
491
|
|
|
478
492
|
** Common configuration options:**
|
|
479
493
|
- `mainBranch` - Primary branch for merging (default: "main")
|
|
494
|
+
- `mergeBehavior.mode` - How to finish work: "local" (merge locally) or "github-pr" (create PR) (default: "local")
|
|
495
|
+
- `mergeBehavior.remote` - Remote to target for PRs (optional, defaults to `issueManagement.github.remote`)
|
|
480
496
|
- `capabilities.web.basePort` - Base port for dev servers (default: 3000)
|
|
481
497
|
- `capabilities.database.databaseUrlEnvVarName` - Name of environment variable for database connection URL (default: "DATABASE_URL")
|
|
482
498
|
- `databaseProviders.neon.projectId` - Neon project ID (found in project URL, e.g., "fantastic-fox-3566354")
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
SettingsManager,
|
|
9
9
|
WorkflowPermissionSchema,
|
|
10
10
|
WorkflowsSettingsSchema
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-T3KEIB4D.js";
|
|
12
12
|
import "./chunk-GEHQXLEI.js";
|
|
13
13
|
export {
|
|
14
14
|
AgentSettingsSchema,
|
|
@@ -20,4 +20,4 @@ export {
|
|
|
20
20
|
WorkflowPermissionSchema,
|
|
21
21
|
WorkflowsSettingsSchema
|
|
22
22
|
};
|
|
23
|
-
//# sourceMappingURL=SettingsManager-
|
|
23
|
+
//# sourceMappingURL=SettingsManager-XOYCLH3D.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
IssueEnhancementService
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-RF2YI2XJ.js";
|
|
5
5
|
import {
|
|
6
6
|
AgentManager
|
|
7
7
|
} from "./chunk-OC4H6HJD.js";
|
|
@@ -9,15 +9,15 @@ import "./chunk-YETJNRQM.js";
|
|
|
9
9
|
import {
|
|
10
10
|
getConfiguredRepoFromSettings,
|
|
11
11
|
hasMultipleRemotes
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-DJUGYNQE.js";
|
|
13
13
|
import {
|
|
14
14
|
GitHubService
|
|
15
|
-
} from "./chunk-
|
|
16
|
-
import "./chunk-
|
|
17
|
-
import "./chunk-
|
|
15
|
+
} from "./chunk-TS6DL67T.js";
|
|
16
|
+
import "./chunk-SWCRXDZC.js";
|
|
17
|
+
import "./chunk-MFU53H6J.js";
|
|
18
18
|
import {
|
|
19
19
|
SettingsManager
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-T3KEIB4D.js";
|
|
21
21
|
import "./chunk-JNKJ7NJV.js";
|
|
22
22
|
import {
|
|
23
23
|
logger
|
|
@@ -66,4 +66,4 @@ var AddIssueCommand = class {
|
|
|
66
66
|
export {
|
|
67
67
|
AddIssueCommand
|
|
68
68
|
};
|
|
69
|
-
//# sourceMappingURL=add-issue-
|
|
69
|
+
//# sourceMappingURL=add-issue-OBI325W7.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
ClaudeService
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-LHP6ROUM.js";
|
|
5
5
|
import {
|
|
6
6
|
logger
|
|
7
7
|
} from "./chunk-GEHQXLEI.js";
|
|
@@ -63,4 +63,4 @@ var ClaudeContextManager = class {
|
|
|
63
63
|
export {
|
|
64
64
|
ClaudeContextManager
|
|
65
65
|
};
|
|
66
|
-
//# sourceMappingURL=chunk-
|
|
66
|
+
//# sourceMappingURL=chunk-2PLUQT6J.js.map
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
import {
|
|
3
3
|
detectClaudeCli,
|
|
4
4
|
launchClaude
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-MFU53H6J.js";
|
|
6
6
|
import {
|
|
7
7
|
SettingsManager
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-T3KEIB4D.js";
|
|
9
9
|
import {
|
|
10
10
|
executeGitCommand,
|
|
11
11
|
findMainWorktreePathWithSettings
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-HBVFXN7R.js";
|
|
13
13
|
import {
|
|
14
14
|
logger
|
|
15
15
|
} from "./chunk-GEHQXLEI.js";
|
|
@@ -304,4 +304,4 @@ To recover:
|
|
|
304
304
|
export {
|
|
305
305
|
MergeManager
|
|
306
306
|
};
|
|
307
|
-
//# sourceMappingURL=chunk-
|
|
307
|
+
//# sourceMappingURL=chunk-4IV6W4U5.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
GitWorktreeManager
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-VETG35MF.js";
|
|
5
5
|
import {
|
|
6
6
|
logger
|
|
7
7
|
} from "./chunk-GEHQXLEI.js";
|
|
@@ -229,4 +229,4 @@ Please consult your shell's documentation for setting up custom completions.
|
|
|
229
229
|
export {
|
|
230
230
|
ShellCompletion
|
|
231
231
|
};
|
|
232
|
-
//# sourceMappingURL=chunk-
|
|
232
|
+
//# sourceMappingURL=chunk-6LEQW46Y.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
getRepoInfo
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-SWCRXDZC.js";
|
|
5
5
|
import {
|
|
6
6
|
logger
|
|
7
7
|
} from "./chunk-GEHQXLEI.js";
|
|
@@ -51,4 +51,4 @@ async function generateGitHubCommentMcpConfig(contextType, repo) {
|
|
|
51
51
|
export {
|
|
52
52
|
generateGitHubCommentMcpConfig
|
|
53
53
|
};
|
|
54
|
-
//# sourceMappingURL=chunk-
|
|
54
|
+
//# sourceMappingURL=chunk-CVLAZRNB.js.map
|
|
@@ -73,11 +73,18 @@ async function validateConfiguredRemote(remoteName, cwd) {
|
|
|
73
73
|
);
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
|
+
async function getEffectivePRTargetRemote(settings, cwd) {
|
|
77
|
+
var _a, _b, _c;
|
|
78
|
+
const prRemote = ((_a = settings.mergeBehavior) == null ? void 0 : _a.remote) ?? ((_c = (_b = settings.issueManagement) == null ? void 0 : _b.github) == null ? void 0 : _c.remote) ?? "origin";
|
|
79
|
+
await validateConfiguredRemote(prRemote, cwd);
|
|
80
|
+
return prRemote;
|
|
81
|
+
}
|
|
76
82
|
|
|
77
83
|
export {
|
|
78
84
|
parseGitRemotes,
|
|
79
85
|
hasMultipleRemotes,
|
|
80
86
|
getConfiguredRepoFromSettings,
|
|
81
|
-
validateConfiguredRemote
|
|
87
|
+
validateConfiguredRemote,
|
|
88
|
+
getEffectivePRTargetRemote
|
|
82
89
|
};
|
|
83
|
-
//# sourceMappingURL=chunk-
|
|
90
|
+
//# sourceMappingURL=chunk-DJUGYNQE.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/remote.ts"],"sourcesContent":["import { execa } from 'execa'\nimport type { IloomSettings } from '../lib/SettingsManager.js'\n\n/**\n * Represents a parsed git remote\n */\nexport interface GitRemote {\n\tname: string\n\turl: string\n\towner: string\n\trepo: string\n}\n\n/**\n * Parse git remotes from `git remote -v` output\n * Deduplicates fetch/push entries and extracts owner/repo from URLs\n */\nexport async function parseGitRemotes(cwd?: string): Promise<GitRemote[]> {\n\tconst result = await execa('git', ['remote', '-v'], {\n\t\tcwd: cwd ?? process.cwd(),\n\t\tencoding: 'utf8',\n\t})\n\n\tconst lines = result.stdout.trim().split('\\n')\n\tconst remoteMap = new Map<string, GitRemote>()\n\n\tfor (const line of lines) {\n\t\t// Format: \"origin git@github.com:owner/repo.git (fetch)\"\n\t\t// Format: \"origin https://github.com/owner/repo.git (fetch)\"\n\t\tconst match = line.match(/^(\\S+)\\s+(\\S+)\\s+\\((fetch|push)\\)/)\n\t\tif (!match) continue\n\n\t\tconst name = match[1]\n\t\tconst url = match[2]\n\t\tif (!name || !url) continue\n\n\t\t// Skip if we already processed this remote\n\t\tif (remoteMap.has(name)) continue\n\n\t\t// Extract owner/repo from URL\n\t\tconst ownerRepo = extractOwnerRepoFromUrl(url)\n\t\tif (!ownerRepo) continue\n\n\t\tremoteMap.set(name, {\n\t\t\tname,\n\t\t\turl,\n\t\t\towner: ownerRepo.owner,\n\t\t\trepo: ownerRepo.repo,\n\t\t})\n\t}\n\n\treturn Array.from(remoteMap.values())\n}\n\n/**\n * Extract owner and repo from GitHub URL\n * Supports both HTTPS and SSH formats\n */\nfunction extractOwnerRepoFromUrl(url: string): { owner: string; repo: string } | null {\n\t// Remove .git suffix if present\n\tconst cleanUrl = url.replace(/\\.git$/, '')\n\n\t// HTTPS format: https://github.com/owner/repo\n\tconst httpsMatch = cleanUrl.match(/https?:\\/\\/github\\.com\\/([^/]+)\\/([^/]+)/)\n\tif (httpsMatch?.[1] && httpsMatch?.[2]) {\n\t\treturn { owner: httpsMatch[1], repo: httpsMatch[2] }\n\t}\n\n\t// SSH format: git@github.com:owner/repo\n\tconst sshMatch = cleanUrl.match(/git@github\\.com:([^/]+)\\/(.+)/)\n\tif (sshMatch?.[1] && sshMatch?.[2]) {\n\t\treturn { owner: sshMatch[1], repo: sshMatch[2] }\n\t}\n\n\treturn null\n}\n\n/**\n * Check if repository has multiple remotes\n */\nexport async function hasMultipleRemotes(cwd?: string): Promise<boolean> {\n\tconst remotes = await parseGitRemotes(cwd)\n\treturn remotes.length > 1\n}\n\n/**\n * Get configured repository string from settings\n * Returns \"owner/repo\" format for use with gh CLI --repo flag\n * Throws if configured remote not found\n */\nexport async function getConfiguredRepoFromSettings(\n\tsettings: IloomSettings,\n\tcwd?: string,\n): Promise<string> {\n\tconst remoteName = settings.issueManagement?.github?.remote\n\n\tif (!remoteName) {\n\t\tthrow new Error(\n\t\t\t'GitHub remote not configured. Run \"il init\" to configure which repository to use for GitHub operations.',\n\t\t)\n\t}\n\n\t// Validate configured remote exists\n\tawait validateConfiguredRemote(remoteName, cwd)\n\n\t// Parse remotes and find the configured one\n\tconst remotes = await parseGitRemotes(cwd)\n\tconst remote = remotes.find((r) => r.name === remoteName)\n\n\tif (!remote) {\n\t\tthrow new Error(\n\t\t\t`Configured remote \"${remoteName}\" not found in git remotes. Run \"il init\" to reconfigure.`,\n\t\t)\n\t}\n\n\treturn `${remote.owner}/${remote.repo}`\n}\n\n/**\n * Validate that a remote exists in git config\n * Throws if remote doesn't exist\n */\nexport async function validateConfiguredRemote(remoteName: string, cwd?: string): Promise<void> {\n\ttry {\n\t\tawait execa('git', ['remote', 'get-url', remoteName], {\n\t\t\tcwd: cwd ?? process.cwd(),\n\t\t\tencoding: 'utf8',\n\t\t})\n\t} catch {\n\t\tthrow new Error(\n\t\t\t`Remote \"${remoteName}\" does not exist in git configuration. Run \"il init\" to reconfigure.`,\n\t\t)\n\t}\n}\n"],"mappings":";;;AAAA,SAAS,aAAa;AAiBtB,eAAsB,gBAAgB,KAAoC;AACzE,QAAM,SAAS,MAAM,MAAM,OAAO,CAAC,UAAU,IAAI,GAAG;AAAA,IACnD,KAAK,OAAO,QAAQ,IAAI;AAAA,IACxB,UAAU;AAAA,EACX,CAAC;AAED,QAAM,QAAQ,OAAO,OAAO,KAAK,EAAE,MAAM,IAAI;AAC7C,QAAM,YAAY,oBAAI,IAAuB;AAE7C,aAAW,QAAQ,OAAO;AAGzB,UAAM,QAAQ,KAAK,MAAM,mCAAmC;AAC5D,QAAI,CAAC,MAAO;AAEZ,UAAM,OAAO,MAAM,CAAC;AACpB,UAAM,MAAM,MAAM,CAAC;AACnB,QAAI,CAAC,QAAQ,CAAC,IAAK;AAGnB,QAAI,UAAU,IAAI,IAAI,EAAG;AAGzB,UAAM,YAAY,wBAAwB,GAAG;AAC7C,QAAI,CAAC,UAAW;AAEhB,cAAU,IAAI,MAAM;AAAA,MACnB;AAAA,MACA;AAAA,MACA,OAAO,UAAU;AAAA,MACjB,MAAM,UAAU;AAAA,IACjB,CAAC;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,UAAU,OAAO,CAAC;AACrC;AAMA,SAAS,wBAAwB,KAAqD;AAErF,QAAM,WAAW,IAAI,QAAQ,UAAU,EAAE;AAGzC,QAAM,aAAa,SAAS,MAAM,0CAA0C;AAC5E,OAAI,yCAAa,QAAM,yCAAa,KAAI;AACvC,WAAO,EAAE,OAAO,WAAW,CAAC,GAAG,MAAM,WAAW,CAAC,EAAE;AAAA,EACpD;AAGA,QAAM,WAAW,SAAS,MAAM,+BAA+B;AAC/D,OAAI,qCAAW,QAAM,qCAAW,KAAI;AACnC,WAAO,EAAE,OAAO,SAAS,CAAC,GAAG,MAAM,SAAS,CAAC,EAAE;AAAA,EAChD;AAEA,SAAO;AACR;AAKA,eAAsB,mBAAmB,KAAgC;AACxE,QAAM,UAAU,MAAM,gBAAgB,GAAG;AACzC,SAAO,QAAQ,SAAS;AACzB;AAOA,eAAsB,8BACrB,UACA,KACkB;AA7FnB;AA8FC,QAAM,cAAa,oBAAS,oBAAT,mBAA0B,WAA1B,mBAAkC;AAErD,MAAI,CAAC,YAAY;AAChB,UAAM,IAAI;AAAA,MACT;AAAA,IACD;AAAA,EACD;AAGA,QAAM,yBAAyB,YAAY,GAAG;AAG9C,QAAM,UAAU,MAAM,gBAAgB,GAAG;AACzC,QAAM,SAAS,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,UAAU;AAExD,MAAI,CAAC,QAAQ;AACZ,UAAM,IAAI;AAAA,MACT,sBAAsB,UAAU;AAAA,IACjC;AAAA,EACD;AAEA,SAAO,GAAG,OAAO,KAAK,IAAI,OAAO,IAAI;AACtC;AAMA,eAAsB,yBAAyB,YAAoB,KAA6B;AAC/F,MAAI;AACH,UAAM,MAAM,OAAO,CAAC,UAAU,WAAW,UAAU,GAAG;AAAA,MACrD,KAAK,OAAO,QAAQ,IAAI;AAAA,MACxB,UAAU;AAAA,IACX,CAAC;AAAA,EACF,QAAQ;AACP,UAAM,IAAI;AAAA,MACT,WAAW,UAAU;AAAA,IACtB;AAAA,EACD;AACD;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/utils/remote.ts"],"sourcesContent":["import { execa } from 'execa'\nimport type { IloomSettings } from '../lib/SettingsManager.js'\n\n/**\n * Represents a parsed git remote\n */\nexport interface GitRemote {\n\tname: string\n\turl: string\n\towner: string\n\trepo: string\n}\n\n/**\n * Parse git remotes from `git remote -v` output\n * Deduplicates fetch/push entries and extracts owner/repo from URLs\n */\nexport async function parseGitRemotes(cwd?: string): Promise<GitRemote[]> {\n\tconst result = await execa('git', ['remote', '-v'], {\n\t\tcwd: cwd ?? process.cwd(),\n\t\tencoding: 'utf8',\n\t})\n\n\tconst lines = result.stdout.trim().split('\\n')\n\tconst remoteMap = new Map<string, GitRemote>()\n\n\tfor (const line of lines) {\n\t\t// Format: \"origin git@github.com:owner/repo.git (fetch)\"\n\t\t// Format: \"origin https://github.com/owner/repo.git (fetch)\"\n\t\tconst match = line.match(/^(\\S+)\\s+(\\S+)\\s+\\((fetch|push)\\)/)\n\t\tif (!match) continue\n\n\t\tconst name = match[1]\n\t\tconst url = match[2]\n\t\tif (!name || !url) continue\n\n\t\t// Skip if we already processed this remote\n\t\tif (remoteMap.has(name)) continue\n\n\t\t// Extract owner/repo from URL\n\t\tconst ownerRepo = extractOwnerRepoFromUrl(url)\n\t\tif (!ownerRepo) continue\n\n\t\tremoteMap.set(name, {\n\t\t\tname,\n\t\t\turl,\n\t\t\towner: ownerRepo.owner,\n\t\t\trepo: ownerRepo.repo,\n\t\t})\n\t}\n\n\treturn Array.from(remoteMap.values())\n}\n\n/**\n * Extract owner and repo from GitHub URL\n * Supports both HTTPS and SSH formats\n */\nfunction extractOwnerRepoFromUrl(url: string): { owner: string; repo: string } | null {\n\t// Remove .git suffix if present\n\tconst cleanUrl = url.replace(/\\.git$/, '')\n\n\t// HTTPS format: https://github.com/owner/repo\n\tconst httpsMatch = cleanUrl.match(/https?:\\/\\/github\\.com\\/([^/]+)\\/([^/]+)/)\n\tif (httpsMatch?.[1] && httpsMatch?.[2]) {\n\t\treturn { owner: httpsMatch[1], repo: httpsMatch[2] }\n\t}\n\n\t// SSH format: git@github.com:owner/repo\n\tconst sshMatch = cleanUrl.match(/git@github\\.com:([^/]+)\\/(.+)/)\n\tif (sshMatch?.[1] && sshMatch?.[2]) {\n\t\treturn { owner: sshMatch[1], repo: sshMatch[2] }\n\t}\n\n\treturn null\n}\n\n/**\n * Check if repository has multiple remotes\n */\nexport async function hasMultipleRemotes(cwd?: string): Promise<boolean> {\n\tconst remotes = await parseGitRemotes(cwd)\n\treturn remotes.length > 1\n}\n\n/**\n * Get configured repository string from settings\n * Returns \"owner/repo\" format for use with gh CLI --repo flag\n * Throws if configured remote not found\n */\nexport async function getConfiguredRepoFromSettings(\n\tsettings: IloomSettings,\n\tcwd?: string,\n): Promise<string> {\n\tconst remoteName = settings.issueManagement?.github?.remote\n\n\tif (!remoteName) {\n\t\tthrow new Error(\n\t\t\t'GitHub remote not configured. Run \"il init\" to configure which repository to use for GitHub operations.',\n\t\t)\n\t}\n\n\t// Validate configured remote exists\n\tawait validateConfiguredRemote(remoteName, cwd)\n\n\t// Parse remotes and find the configured one\n\tconst remotes = await parseGitRemotes(cwd)\n\tconst remote = remotes.find((r) => r.name === remoteName)\n\n\tif (!remote) {\n\t\tthrow new Error(\n\t\t\t`Configured remote \"${remoteName}\" not found in git remotes. Run \"il init\" to reconfigure.`,\n\t\t)\n\t}\n\n\treturn `${remote.owner}/${remote.repo}`\n}\n\n/**\n * Validate that a remote exists in git config\n * Throws if remote doesn't exist\n */\nexport async function validateConfiguredRemote(remoteName: string, cwd?: string): Promise<void> {\n\ttry {\n\t\tawait execa('git', ['remote', 'get-url', remoteName], {\n\t\t\tcwd: cwd ?? process.cwd(),\n\t\t\tencoding: 'utf8',\n\t\t})\n\t} catch {\n\t\tthrow new Error(\n\t\t\t`Remote \"${remoteName}\" does not exist in git configuration. Run \"il init\" to reconfigure.`,\n\t\t)\n\t}\n}\n\n/**\n * Get the effective PR target remote based on settings\n * Priority: mergeBehavior.remote > issueManagement.github.remote > 'origin'\n */\nexport async function getEffectivePRTargetRemote(\n\tsettings: IloomSettings,\n\tcwd?: string,\n): Promise<string> {\n\tconst prRemote =\n\t\tsettings.mergeBehavior?.remote ?? settings.issueManagement?.github?.remote ?? 'origin'\n\tawait validateConfiguredRemote(prRemote, cwd)\n\treturn prRemote\n}\n"],"mappings":";;;AAAA,SAAS,aAAa;AAiBtB,eAAsB,gBAAgB,KAAoC;AACzE,QAAM,SAAS,MAAM,MAAM,OAAO,CAAC,UAAU,IAAI,GAAG;AAAA,IACnD,KAAK,OAAO,QAAQ,IAAI;AAAA,IACxB,UAAU;AAAA,EACX,CAAC;AAED,QAAM,QAAQ,OAAO,OAAO,KAAK,EAAE,MAAM,IAAI;AAC7C,QAAM,YAAY,oBAAI,IAAuB;AAE7C,aAAW,QAAQ,OAAO;AAGzB,UAAM,QAAQ,KAAK,MAAM,mCAAmC;AAC5D,QAAI,CAAC,MAAO;AAEZ,UAAM,OAAO,MAAM,CAAC;AACpB,UAAM,MAAM,MAAM,CAAC;AACnB,QAAI,CAAC,QAAQ,CAAC,IAAK;AAGnB,QAAI,UAAU,IAAI,IAAI,EAAG;AAGzB,UAAM,YAAY,wBAAwB,GAAG;AAC7C,QAAI,CAAC,UAAW;AAEhB,cAAU,IAAI,MAAM;AAAA,MACnB;AAAA,MACA;AAAA,MACA,OAAO,UAAU;AAAA,MACjB,MAAM,UAAU;AAAA,IACjB,CAAC;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,UAAU,OAAO,CAAC;AACrC;AAMA,SAAS,wBAAwB,KAAqD;AAErF,QAAM,WAAW,IAAI,QAAQ,UAAU,EAAE;AAGzC,QAAM,aAAa,SAAS,MAAM,0CAA0C;AAC5E,OAAI,yCAAa,QAAM,yCAAa,KAAI;AACvC,WAAO,EAAE,OAAO,WAAW,CAAC,GAAG,MAAM,WAAW,CAAC,EAAE;AAAA,EACpD;AAGA,QAAM,WAAW,SAAS,MAAM,+BAA+B;AAC/D,OAAI,qCAAW,QAAM,qCAAW,KAAI;AACnC,WAAO,EAAE,OAAO,SAAS,CAAC,GAAG,MAAM,SAAS,CAAC,EAAE;AAAA,EAChD;AAEA,SAAO;AACR;AAKA,eAAsB,mBAAmB,KAAgC;AACxE,QAAM,UAAU,MAAM,gBAAgB,GAAG;AACzC,SAAO,QAAQ,SAAS;AACzB;AAOA,eAAsB,8BACrB,UACA,KACkB;AA7FnB;AA8FC,QAAM,cAAa,oBAAS,oBAAT,mBAA0B,WAA1B,mBAAkC;AAErD,MAAI,CAAC,YAAY;AAChB,UAAM,IAAI;AAAA,MACT;AAAA,IACD;AAAA,EACD;AAGA,QAAM,yBAAyB,YAAY,GAAG;AAG9C,QAAM,UAAU,MAAM,gBAAgB,GAAG;AACzC,QAAM,SAAS,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,UAAU;AAExD,MAAI,CAAC,QAAQ;AACZ,UAAM,IAAI;AAAA,MACT,sBAAsB,UAAU;AAAA,IACjC;AAAA,EACD;AAEA,SAAO,GAAG,OAAO,KAAK,IAAI,OAAO,IAAI;AACtC;AAMA,eAAsB,yBAAyB,YAAoB,KAA6B;AAC/F,MAAI;AACH,UAAM,MAAM,OAAO,CAAC,UAAU,WAAW,UAAU,GAAG;AAAA,MACrD,KAAK,OAAO,QAAQ,IAAI;AAAA,MACxB,UAAU;AAAA,IACX,CAAC;AAAA,EACF,QAAQ;AACP,UAAM,IAAI;AAAA,MACT,WAAW,UAAU;AAAA,IACtB;AAAA,EACD;AACD;AAMA,eAAsB,2BACrB,UACA,KACkB;AA9InB;AA+IC,QAAM,aACL,cAAS,kBAAT,mBAAwB,aAAU,oBAAS,oBAAT,mBAA0B,WAA1B,mBAAkC,WAAU;AAC/E,QAAM,yBAAyB,UAAU,GAAG;AAC5C,SAAO;AACR;","names":[]}
|
|
@@ -261,7 +261,7 @@ async function findMainWorktreePath(path2 = process.cwd(), options) {
|
|
|
261
261
|
}
|
|
262
262
|
async function findMainWorktreePathWithSettings(path2, settingsManager) {
|
|
263
263
|
if (!settingsManager) {
|
|
264
|
-
const { SettingsManager: SM } = await import("./SettingsManager-
|
|
264
|
+
const { SettingsManager: SM } = await import("./SettingsManager-XOYCLH3D.js");
|
|
265
265
|
settingsManager = new SM();
|
|
266
266
|
}
|
|
267
267
|
const settings = await settingsManager.loadSettings(path2);
|
|
@@ -296,7 +296,7 @@ async function getDefaultBranch(path2 = process.cwd()) {
|
|
|
296
296
|
}
|
|
297
297
|
async function findAllBranchesForIssue(issueNumber, path2 = process.cwd(), settingsManager) {
|
|
298
298
|
if (!settingsManager) {
|
|
299
|
-
const { SettingsManager: SM } = await import("./SettingsManager-
|
|
299
|
+
const { SettingsManager: SM } = await import("./SettingsManager-XOYCLH3D.js");
|
|
300
300
|
settingsManager = new SM();
|
|
301
301
|
}
|
|
302
302
|
const protectedBranches = await settingsManager.getProtectedBranches(path2);
|
|
@@ -434,4 +434,4 @@ export {
|
|
|
434
434
|
ensureRepositoryHasCommits,
|
|
435
435
|
pushBranchToRemote
|
|
436
436
|
};
|
|
437
|
-
//# sourceMappingURL=chunk-
|
|
437
|
+
//# sourceMappingURL=chunk-HBVFXN7R.js.map
|
|
@@ -4,13 +4,13 @@ import {
|
|
|
4
4
|
generateBranchName,
|
|
5
5
|
launchClaude,
|
|
6
6
|
launchClaudeInNewTerminalWindow
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-MFU53H6J.js";
|
|
8
8
|
import {
|
|
9
9
|
PromptTemplateManager
|
|
10
10
|
} from "./chunk-PVAVNJKS.js";
|
|
11
11
|
import {
|
|
12
12
|
SettingsManager
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-T3KEIB4D.js";
|
|
14
14
|
import {
|
|
15
15
|
logger
|
|
16
16
|
} from "./chunk-GEHQXLEI.js";
|
|
@@ -148,4 +148,4 @@ var ClaudeService = class {
|
|
|
148
148
|
export {
|
|
149
149
|
ClaudeService
|
|
150
150
|
};
|
|
151
|
-
//# sourceMappingURL=chunk-
|
|
151
|
+
//# sourceMappingURL=chunk-LHP6ROUM.js.map
|
|
@@ -161,7 +161,7 @@ async function launchClaudeInNewTerminalWindow(_prompt, options) {
|
|
|
161
161
|
if (!workspacePath) {
|
|
162
162
|
throw new Error("workspacePath is required for terminal window launch");
|
|
163
163
|
}
|
|
164
|
-
const { openTerminalWindow } = await import("./terminal-
|
|
164
|
+
const { openTerminalWindow } = await import("./terminal-BIRBZ4AZ.js");
|
|
165
165
|
const executable = executablePath ?? "iloom";
|
|
166
166
|
let launchCommand = `${executable} spin`;
|
|
167
167
|
if (oneShot !== "default") {
|
|
@@ -247,4 +247,4 @@ export {
|
|
|
247
247
|
launchClaudeInNewTerminalWindow,
|
|
248
248
|
generateBranchName
|
|
249
249
|
};
|
|
250
|
-
//# sourceMappingURL=chunk-
|
|
250
|
+
//# sourceMappingURL=chunk-MFU53H6J.js.map
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-YETJNRQM.js";
|
|
5
5
|
import {
|
|
6
6
|
launchClaude
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-MFU53H6J.js";
|
|
8
8
|
import {
|
|
9
9
|
waitForKeypress
|
|
10
10
|
} from "./chunk-JNKJ7NJV.js";
|
|
@@ -117,4 +117,4 @@ Press any key to open issue for editing...`;
|
|
|
117
117
|
export {
|
|
118
118
|
IssueEnhancementService
|
|
119
119
|
};
|
|
120
|
-
//# sourceMappingURL=chunk-
|
|
120
|
+
//# sourceMappingURL=chunk-RF2YI2XJ.js.map
|
|
@@ -159,7 +159,7 @@ var ClaudeBranchNameStrategy = class {
|
|
|
159
159
|
this.claudeModel = claudeModel;
|
|
160
160
|
}
|
|
161
161
|
async generate(issueNumber, title) {
|
|
162
|
-
const { generateBranchName } = await import("./claude-
|
|
162
|
+
const { generateBranchName } = await import("./claude-ZIWDG4XG.js");
|
|
163
163
|
return generateBranchName(title, issueNumber, this.claudeModel);
|
|
164
164
|
}
|
|
165
165
|
};
|
|
@@ -228,4 +228,4 @@ export {
|
|
|
228
228
|
createIssue,
|
|
229
229
|
getRepoInfo
|
|
230
230
|
};
|
|
231
|
-
//# sourceMappingURL=chunk-
|
|
231
|
+
//# sourceMappingURL=chunk-SWCRXDZC.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
SettingsManager
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-T3KEIB4D.js";
|
|
5
5
|
import {
|
|
6
6
|
logger
|
|
7
7
|
} from "./chunk-GEHQXLEI.js";
|
|
@@ -112,7 +112,7 @@ ${blockerMessage}`);
|
|
|
112
112
|
let mainWorktreePath = null;
|
|
113
113
|
if (!options.dryRun) {
|
|
114
114
|
try {
|
|
115
|
-
const { findMainWorktreePathWithSettings } = await import("./git-
|
|
115
|
+
const { findMainWorktreePathWithSettings } = await import("./git-WC6HZLOT.js");
|
|
116
116
|
mainWorktreePath = await findMainWorktreePathWithSettings(worktree.path, this.settingsManager);
|
|
117
117
|
} catch (error) {
|
|
118
118
|
logger.warn(
|
|
@@ -363,7 +363,7 @@ ${blockerMessage}`);
|
|
|
363
363
|
logger.info(`[DRY RUN] Would delete branch: ${branchName}`);
|
|
364
364
|
return true;
|
|
365
365
|
}
|
|
366
|
-
const { executeGitCommand, findMainWorktreePathWithSettings } = await import("./git-
|
|
366
|
+
const { executeGitCommand, findMainWorktreePathWithSettings } = await import("./git-WC6HZLOT.js");
|
|
367
367
|
try {
|
|
368
368
|
let workingDir = cwd ?? await findMainWorktreePathWithSettings(void 0, this.settingsManager);
|
|
369
369
|
const deleteFlag = options.force ? "-D" : "-d";
|
|
@@ -407,7 +407,7 @@ ${blockerMessage}`);
|
|
|
407
407
|
const shouldCleanup = await this.database.shouldUseDatabaseBranching(envFilePath);
|
|
408
408
|
let cwd;
|
|
409
409
|
try {
|
|
410
|
-
const { findMainWorktreePathWithSettings } = await import("./git-
|
|
410
|
+
const { findMainWorktreePathWithSettings } = await import("./git-WC6HZLOT.js");
|
|
411
411
|
cwd = await findMainWorktreePathWithSettings(worktreePath, this.settingsManager);
|
|
412
412
|
} catch (error) {
|
|
413
413
|
logger.debug(
|
|
@@ -467,7 +467,7 @@ ${blockerMessage}`);
|
|
|
467
467
|
if (isMain) {
|
|
468
468
|
blockers.push(`Cannot cleanup main worktree: "${worktree.branch}" @ "${worktree.path}"`);
|
|
469
469
|
}
|
|
470
|
-
const { hasUncommittedChanges } = await import("./git-
|
|
470
|
+
const { hasUncommittedChanges } = await import("./git-WC6HZLOT.js");
|
|
471
471
|
const hasChanges = await hasUncommittedChanges(worktree.path);
|
|
472
472
|
if (hasChanges) {
|
|
473
473
|
const blockerMessage = `Worktree has uncommitted changes.
|
|
@@ -542,4 +542,4 @@ Please resolve before cleanup - you have some options:
|
|
|
542
542
|
export {
|
|
543
543
|
ResourceCleanup
|
|
544
544
|
};
|
|
545
|
-
//# sourceMappingURL=chunk-
|
|
545
|
+
//# sourceMappingURL=chunk-SYOSCMIT.js.map
|
|
@@ -76,7 +76,11 @@ var IloomSettingsSchema = z.object({
|
|
|
76
76
|
github: z.object({
|
|
77
77
|
remote: z.string().min(1, "Remote name cannot be empty").describe("Git remote name to use for GitHub operations")
|
|
78
78
|
}).optional()
|
|
79
|
-
}).optional().describe("Issue management configuration")
|
|
79
|
+
}).optional().describe("Issue management configuration"),
|
|
80
|
+
mergeBehavior: z.object({
|
|
81
|
+
mode: z.enum(["local", "github-pr"]).default("local"),
|
|
82
|
+
remote: z.string().optional()
|
|
83
|
+
}).optional().describe("Merge behavior configuration: local (merge locally) or github-pr (create PR)")
|
|
80
84
|
});
|
|
81
85
|
var SettingsManager = class {
|
|
82
86
|
/**
|
|
@@ -236,4 +240,4 @@ export {
|
|
|
236
240
|
IloomSettingsSchema,
|
|
237
241
|
SettingsManager
|
|
238
242
|
};
|
|
239
|
-
//# sourceMappingURL=chunk-
|
|
243
|
+
//# sourceMappingURL=chunk-T3KEIB4D.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/SettingsManager.ts"],"sourcesContent":["import { readFile } from 'fs/promises'\nimport path from 'path'\nimport { z } from 'zod'\nimport deepmerge from 'deepmerge'\nimport { logger } from '../utils/logger.js'\n\n/**\n * Zod schema for agent settings\n */\nexport const AgentSettingsSchema = z.object({\n\tmodel: z\n\t\t.enum(['sonnet', 'opus', 'haiku'])\n\t\t.optional()\n\t\t.describe('Claude model shorthand: sonnet, opus, or haiku'),\n\t// Future: could add other per-agent overrides\n})\n\n/**\n * Zod schema for workflow permission configuration\n */\nexport const WorkflowPermissionSchema = z.object({\n\tpermissionMode: z\n\t\t.enum(['plan', 'acceptEdits', 'bypassPermissions', 'default'])\n\t\t.optional()\n\t\t.describe('Permission mode for Claude CLI in this workflow type'),\n\tnoVerify: z\n\t\t.boolean()\n\t\t.optional()\n\t\t.describe('Skip pre-commit hooks (--no-verify) when committing during finish workflow'),\n\tstartIde: z\n\t\t.boolean()\n\t\t.default(true)\n\t\t.describe('Launch IDE (code) when starting this workflow type'),\n\tstartDevServer: z\n\t\t.boolean()\n\t\t.default(true)\n\t\t.describe('Launch development server when starting this workflow type'),\n\tstartAiAgent: z\n\t\t.boolean()\n\t\t.default(true)\n\t\t.describe('Launch Claude AI agent when starting this workflow type'),\n\tstartTerminal: z\n\t\t.boolean()\n\t\t.default(false)\n\t\t.describe('Launch terminal window without dev server when starting this workflow type'),\n})\n\n/**\n * Zod schema for workflows settings\n */\nexport const WorkflowsSettingsSchema = z\n\t.object({\n\t\tissue: WorkflowPermissionSchema.optional(),\n\t\tpr: WorkflowPermissionSchema.optional(),\n\t\tregular: WorkflowPermissionSchema.optional(),\n\t})\n\t.optional()\n\n/**\n * Zod schema for capabilities settings\n */\nexport const CapabilitiesSettingsSchema = z\n\t.object({\n\t\tweb: z\n\t\t\t.object({\n\t\t\t\tbasePort: z\n\t\t\t\t\t.number()\n\t\t\t\t\t.min(1, 'Base port must be >= 1')\n\t\t\t\t\t.max(65535, 'Base port must be <= 65535')\n\t\t\t\t\t.optional()\n\t\t\t\t\t.describe('Base port for web workspace port calculations (default: 3000)'),\n\t\t\t})\n\t\t\t.optional(),\n\t\tdatabase: z\n\t\t\t.object({\n\t\t\t\tdatabaseUrlEnvVarName: z\n\t\t\t\t\t.string()\n\t\t\t\t\t.min(1, 'Database URL variable name cannot be empty')\n\t\t\t\t\t.regex(/^[A-Z_][A-Z0-9_]*$/, 'Must be valid env var name (uppercase, underscores)')\n\t\t\t\t\t.optional()\n\t\t\t\t\t.default('DATABASE_URL')\n\t\t\t\t\t.describe('Name of environment variable for database connection URL'),\n\t\t\t})\n\t\t\t.optional(),\n\t})\n\t.optional()\n\n/**\n * Zod schema for Neon database provider settings\n */\nexport const NeonSettingsSchema = z.object({\n\tprojectId: z\n\t\t.string()\n\t\t.min(1)\n\t\t.regex(/^[a-zA-Z0-9-]+$/, 'Neon project ID must contain only letters, numbers, and hyphens')\n\t\t.describe('Neon project ID found in your project URL (e.g., \"fantastic-fox-3566354\")'),\n\tparentBranch: z\n\t\t.string()\n\t\t.min(1)\n\t\t.describe('Branch from which new database branches are created'),\n})\n\n/**\n * Zod schema for database provider settings\n */\nexport const DatabaseProvidersSettingsSchema = z\n\t.object({\n\t\tneon: NeonSettingsSchema.optional().describe(\n\t\t\t'Neon database configuration. Requires Neon CLI installed and authenticated for database branching.',\n\t\t),\n\t})\n\t.optional()\n\n/**\n * Zod schema for iloom settings\n */\nexport const IloomSettingsSchema = z.object({\n\tmainBranch: z\n\t\t.string()\n\t\t.min(1, \"Settings 'mainBranch' cannot be empty\")\n\t\t.optional()\n\t\t.describe('Name of the main/primary branch for the repository'),\n\tworktreePrefix: z\n\t\t.string()\n\t\t.optional()\n\t\t.refine(\n\t\t\t(val) => {\n\t\t\t\tif (val === undefined) return true // undefined = use default calculation\n\t\t\t\tif (val === '') return true // empty string = no prefix mode\n\n\t\t\t\t// Allowlist: only alphanumeric, hyphens, underscores, and forward slashes\n\t\t\t\tconst allowedChars = /^[a-zA-Z0-9\\-_/]+$/\n\t\t\t\tif (!allowedChars.test(val)) return false\n\n\t\t\t\t// Reject if only special characters (no alphanumeric content)\n\t\t\t\tif (/^[-_/]+$/.test(val)) return false\n\n\t\t\t\t// Check each segment (split by /) contains at least one alphanumeric character\n\t\t\t\tconst segments = val.split('/')\n\t\t\t\tfor (const segment of segments) {\n\t\t\t\t\tif (segment && /^[-_]+$/.test(segment)) {\n\t\t\t\t\t\t// Segment exists but contains only hyphens/underscores\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true\n\t\t\t},\n\t\t\t{\n\t\t\t\tmessage:\n\t\t\t\t\t\"worktreePrefix contains invalid characters. Only alphanumeric characters, hyphens (-), underscores (_), and forward slashes (/) are allowed. Use forward slashes for nested directories.\",\n\t\t\t},\n\t\t)\n\t\t.describe(\n\t\t\t'Prefix for worktree directories. Empty string disables prefix. Defaults to <repo-name>-looms if not set.',\n\t\t),\n\tprotectedBranches: z\n\t\t.array(z.string().min(1, 'Protected branch name cannot be empty'))\n\t\t.optional()\n\t\t.describe('List of branches that cannot be deleted (defaults to [mainBranch, \"main\", \"master\", \"develop\"])'),\n\tworkflows: WorkflowsSettingsSchema.describe('Per-workflow-type permission configurations'),\n\tagents: z\n\t\t.record(z.string(), AgentSettingsSchema)\n\t\t.optional()\n\t\t.nullable()\n\t\t.describe(\n\t\t\t'Per-agent configuration overrides. Available agents: ' +\n\t\t\t\t'iloom-issue-analyzer (analyzes issues), ' +\n\t\t\t\t'iloom-issue-planner (creates implementation plans), ' +\n\t\t\t\t'iloom-issue-analyze-and-plan (combined analysis and planning), ' +\n\t\t\t\t'iloom-issue-complexity-evaluator (evaluates complexity), ' +\n\t\t\t\t'iloom-issue-enhancer (enhances issue descriptions), ' +\n\t\t\t\t'iloom-issue-implementer (implements code changes), ' +\n\t\t\t\t'iloom-issue-reviewer (reviews code changes against requirements)',\n\t\t),\n\tcapabilities: CapabilitiesSettingsSchema.describe('Project capability configurations'),\n\tdatabaseProviders: DatabaseProvidersSettingsSchema.describe('Database provider configurations'),\n\tissueManagement: z\n\t\t.object({\n\t\t\tgithub: z\n\t\t\t\t.object({\n\t\t\t\t\tremote: z\n\t\t\t\t\t\t.string()\n\t\t\t\t\t\t.min(1, 'Remote name cannot be empty')\n\t\t\t\t\t\t.describe('Git remote name to use for GitHub operations'),\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t})\n\t\t.optional()\n\t\t.describe('Issue management configuration'),\n})\n\n/**\n * TypeScript type for Neon settings derived from Zod schema\n */\nexport type NeonSettings = z.infer<typeof NeonSettingsSchema>\n\n/**\n * TypeScript type for database providers settings derived from Zod schema\n */\nexport type DatabaseProvidersSettings = z.infer<typeof DatabaseProvidersSettingsSchema>\n\n/**\n * TypeScript type for agent settings derived from Zod schema\n */\nexport type AgentSettings = z.infer<typeof AgentSettingsSchema>\n\n/**\n * TypeScript type for workflow permission configuration derived from Zod schema\n */\nexport type WorkflowPermission = z.infer<typeof WorkflowPermissionSchema>\n\n/**\n * TypeScript type for workflows settings derived from Zod schema\n */\nexport type WorkflowsSettings = z.infer<typeof WorkflowsSettingsSchema>\n\n/**\n * TypeScript type for capabilities settings derived from Zod schema\n */\nexport type CapabilitiesSettings = z.infer<typeof CapabilitiesSettingsSchema>\n\n/**\n * TypeScript type for iloom settings derived from Zod schema\n */\nexport type IloomSettings = z.infer<typeof IloomSettingsSchema>\n\n/**\n * Manages project-level settings from .iloom/settings.json\n */\nexport class SettingsManager {\n\t/**\n\t * Load settings from <PROJECT_ROOT>/.iloom/settings.json and settings.local.json\n\t * Merges settings.local.json over settings.json with priority\n\t * CLI overrides have highest priority if provided\n\t * Returns empty object if both files don't exist (not an error)\n\t */\n\tasync loadSettings(\n\t\tprojectRoot?: string,\n\t\tcliOverrides?: Partial<IloomSettings>,\n\t): Promise<IloomSettings> {\n\t\tconst root = this.getProjectRoot(projectRoot)\n\n\t\t// Load base settings from settings.json\n\t\tconst baseSettings = await this.loadSettingsFile(root, 'settings.json')\n\t\tconst baseSettingsPath = path.join(root, '.iloom', 'settings.json')\n\t\tlogger.debug(`📄 Base settings from ${baseSettingsPath}:`, JSON.stringify(baseSettings, null, 2))\n\n\t\t// Load local overrides from settings.local.json\n\t\tconst localSettings = await this.loadSettingsFile(root, 'settings.local.json')\n\t\tconst localSettingsPath = path.join(root, '.iloom', 'settings.local.json')\n\t\tlogger.debug(`📄 Local settings from ${localSettingsPath}:`, JSON.stringify(localSettings, null, 2))\n\n\t\t// Deep merge with priority: cliOverrides > localSettings > baseSettings\n\t\tlet merged = this.mergeSettings(baseSettings, localSettings)\n\t\tlogger.debug('🔄 After merging base + local settings:', JSON.stringify(merged, null, 2))\n\n\t\tif (cliOverrides && Object.keys(cliOverrides).length > 0) {\n\t\t\tlogger.debug('⚙️ CLI overrides to apply:', JSON.stringify(cliOverrides, null, 2))\n\t\t\tmerged = this.mergeSettings(merged, cliOverrides)\n\t\t\tlogger.debug('🔄 After applying CLI overrides:', JSON.stringify(merged, null, 2))\n\t\t}\n\n\t\t// Validate merged result\n\t\ttry {\n\t\t\tconst finalSettings = IloomSettingsSchema.parse(merged)\n\n\t\t\t// Debug: Log final merged configuration\n\t\t\tthis.logFinalConfiguration(finalSettings)\n\n\t\t\treturn finalSettings\n\t\t} catch (error) {\n\t\t\t// Show all Zod validation errors\n\t\t\tif (error instanceof z.ZodError) {\n\t\t\t\tconst errorMsg = this.formatAllZodErrors(error, '<merged settings>')\n\t\t\t\t// Enhance error message if CLI overrides were applied\n\t\t\t\tif (cliOverrides && Object.keys(cliOverrides).length > 0) {\n\t\t\t\t\tthrow new Error(`${errorMsg.message}\\n\\nNote: CLI overrides were applied. Check your --set arguments.`)\n\t\t\t\t}\n\t\t\t\tthrow errorMsg\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t/**\n\t * Log the final merged configuration for debugging\n\t */\n\tprivate logFinalConfiguration(settings: IloomSettings): void {\n\t\tlogger.debug('📋 Final merged configuration:', JSON.stringify(settings, null, 2))\n\t}\n\n\t/**\n\t * Load and parse a single settings file\n\t * Returns empty object if file doesn't exist (not an error)\n\t */\n\tprivate async loadSettingsFile(\n\t\tprojectRoot: string,\n\t\tfilename: string,\n\t): Promise<Partial<IloomSettings>> {\n\t\tconst settingsPath = path.join(projectRoot, '.iloom', filename)\n\n\t\ttry {\n\t\t\tconst content = await readFile(settingsPath, 'utf-8')\n\t\t\tlet parsed: unknown\n\n\t\t\ttry {\n\t\t\t\tparsed = JSON.parse(content)\n\t\t\t} catch (error) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Failed to parse settings file at ${settingsPath}: ${error instanceof Error ? error.message : 'Invalid JSON'}`,\n\t\t\t\t)\n\t\t\t}\n\n\t\t\t// Validate individual file with strict mode to catch unknown keys\n\t\t\t// Note: Schema already has all fields as optional, so no need for .partial()\n\t\t\ttry {\n\t\t\t\tconst validated = IloomSettingsSchema.strict().parse(parsed)\n\t\t\t\treturn validated\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof z.ZodError) {\n\t\t\t\t\tconst errorMsg = this.formatAllZodErrors(error, filename)\n\t\t\t\t\tthrow errorMsg\n\t\t\t\t}\n\t\t\t\tthrow error\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// File not found is not an error - return empty settings\n\t\t\tif ((error as { code?: string }).code === 'ENOENT') {\n\t\t\t\tlogger.debug(`No settings file found at ${settingsPath}, using defaults`)\n\t\t\t\treturn {}\n\t\t\t}\n\n\t\t\t// Re-throw parsing errors\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t/**\n\t * Deep merge two settings objects with priority to override\n\t * Uses deepmerge library with array replacement strategy\n\t */\n\tprivate mergeSettings(\n\t\tbase: Partial<IloomSettings>,\n\t\toverride: Partial<IloomSettings>,\n\t): IloomSettings {\n\t\t// Use deepmerge with array replacement (not concatenation)\n\t\treturn deepmerge(base, override, {\n\t\t\t// Replace arrays instead of concatenating them\n\t\t\tarrayMerge: (_destinationArray, sourceArray) => sourceArray,\n\t\t}) as IloomSettings\n\t}\n\n\t/**\n\t * Format all Zod validation errors into a single error message\n\t */\n\tprivate formatAllZodErrors(error: z.ZodError, settingsPath: string): Error {\n\t\tconst errorMessages = error.issues.map(issue => {\n\t\t\tconst path = issue.path.length > 0 ? issue.path.join('.') : 'root'\n\t\t\treturn ` - ${path}: ${issue.message}`\n\t\t})\n\n\t\treturn new Error(\n\t\t\t`Settings validation failed at ${settingsPath}:\\n${errorMessages.join('\\n')}`,\n\t\t)\n\t}\n\n\t/**\n\t * Validate settings structure and model names using Zod schema\n\t * This method is kept for testing purposes but uses Zod internally\n\t * @internal - Only used in tests via bracket notation\n\t */\n\t// @ts-expect-error - Used in tests via bracket notation, TypeScript can't detect this usage\n\tprivate validateSettings(settings: IloomSettings): void {\n\t\ttry {\n\t\t\tIloomSettingsSchema.parse(settings)\n\t\t} catch (error) {\n\t\t\tif (error instanceof z.ZodError) {\n\t\t\t\tthrow this.formatAllZodErrors(error, '<validation>')\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t/**\n\t * Get project root (defaults to process.cwd())\n\t */\n\tprivate getProjectRoot(projectRoot?: string): string {\n\t\treturn projectRoot ?? process.cwd()\n\t}\n\n\t/**\n\t * Get effective protected branches list with mainBranch always included\n\t *\n\t * This method provides a single source of truth for protected branches logic:\n\t * 1. Use configured protectedBranches if provided\n\t * 2. Otherwise use defaults: [mainBranch, 'main', 'master', 'develop']\n\t * 3. ALWAYS ensure mainBranch is included even if user configured custom list\n\t *\n\t * @param projectRoot - Optional project root directory (defaults to process.cwd())\n\t * @returns Array of protected branch names with mainBranch guaranteed to be included\n\t */\n\tasync getProtectedBranches(projectRoot?: string): Promise<string[]> {\n\t\tconst settings = await this.loadSettings(projectRoot)\n\t\tconst mainBranch = settings.mainBranch ?? 'main'\n\n\t\t// Build protected branches list:\n\t\t// 1. Use configured protectedBranches if provided\n\t\t// 2. Otherwise use defaults: [mainBranch, 'main', 'master', 'develop']\n\t\t// 3. ALWAYS ensure mainBranch is included even if user configured custom list\n\t\tlet protectedBranches: string[]\n\t\tif (settings.protectedBranches) {\n\t\t\t// Use configured list but ensure mainBranch is always included\n\t\t\tprotectedBranches = settings.protectedBranches.includes(mainBranch)\n\t\t\t\t? settings.protectedBranches\n\t\t\t\t: [mainBranch, ...settings.protectedBranches]\n\t\t} else {\n\t\t\t// Use defaults with current mainBranch\n\t\t\tprotectedBranches = [mainBranch, 'main', 'master', 'develop']\n\t\t}\n\n\t\treturn protectedBranches\n\t}\n}\n"],"mappings":"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","names":["path"]}
|
|
1
|
+
{"version":3,"sources":["../src/lib/SettingsManager.ts"],"sourcesContent":["import { readFile } from 'fs/promises'\nimport path from 'path'\nimport { z } from 'zod'\nimport deepmerge from 'deepmerge'\nimport { logger } from '../utils/logger.js'\n\n/**\n * Zod schema for agent settings\n */\nexport const AgentSettingsSchema = z.object({\n\tmodel: z\n\t\t.enum(['sonnet', 'opus', 'haiku'])\n\t\t.optional()\n\t\t.describe('Claude model shorthand: sonnet, opus, or haiku'),\n\t// Future: could add other per-agent overrides\n})\n\n/**\n * Zod schema for workflow permission configuration\n */\nexport const WorkflowPermissionSchema = z.object({\n\tpermissionMode: z\n\t\t.enum(['plan', 'acceptEdits', 'bypassPermissions', 'default'])\n\t\t.optional()\n\t\t.describe('Permission mode for Claude CLI in this workflow type'),\n\tnoVerify: z\n\t\t.boolean()\n\t\t.optional()\n\t\t.describe('Skip pre-commit hooks (--no-verify) when committing during finish workflow'),\n\tstartIde: z\n\t\t.boolean()\n\t\t.default(true)\n\t\t.describe('Launch IDE (code) when starting this workflow type'),\n\tstartDevServer: z\n\t\t.boolean()\n\t\t.default(true)\n\t\t.describe('Launch development server when starting this workflow type'),\n\tstartAiAgent: z\n\t\t.boolean()\n\t\t.default(true)\n\t\t.describe('Launch Claude AI agent when starting this workflow type'),\n\tstartTerminal: z\n\t\t.boolean()\n\t\t.default(false)\n\t\t.describe('Launch terminal window without dev server when starting this workflow type'),\n})\n\n/**\n * Zod schema for workflows settings\n */\nexport const WorkflowsSettingsSchema = z\n\t.object({\n\t\tissue: WorkflowPermissionSchema.optional(),\n\t\tpr: WorkflowPermissionSchema.optional(),\n\t\tregular: WorkflowPermissionSchema.optional(),\n\t})\n\t.optional()\n\n/**\n * Zod schema for capabilities settings\n */\nexport const CapabilitiesSettingsSchema = z\n\t.object({\n\t\tweb: z\n\t\t\t.object({\n\t\t\t\tbasePort: z\n\t\t\t\t\t.number()\n\t\t\t\t\t.min(1, 'Base port must be >= 1')\n\t\t\t\t\t.max(65535, 'Base port must be <= 65535')\n\t\t\t\t\t.optional()\n\t\t\t\t\t.describe('Base port for web workspace port calculations (default: 3000)'),\n\t\t\t})\n\t\t\t.optional(),\n\t\tdatabase: z\n\t\t\t.object({\n\t\t\t\tdatabaseUrlEnvVarName: z\n\t\t\t\t\t.string()\n\t\t\t\t\t.min(1, 'Database URL variable name cannot be empty')\n\t\t\t\t\t.regex(/^[A-Z_][A-Z0-9_]*$/, 'Must be valid env var name (uppercase, underscores)')\n\t\t\t\t\t.optional()\n\t\t\t\t\t.default('DATABASE_URL')\n\t\t\t\t\t.describe('Name of environment variable for database connection URL'),\n\t\t\t})\n\t\t\t.optional(),\n\t})\n\t.optional()\n\n/**\n * Zod schema for Neon database provider settings\n */\nexport const NeonSettingsSchema = z.object({\n\tprojectId: z\n\t\t.string()\n\t\t.min(1)\n\t\t.regex(/^[a-zA-Z0-9-]+$/, 'Neon project ID must contain only letters, numbers, and hyphens')\n\t\t.describe('Neon project ID found in your project URL (e.g., \"fantastic-fox-3566354\")'),\n\tparentBranch: z\n\t\t.string()\n\t\t.min(1)\n\t\t.describe('Branch from which new database branches are created'),\n})\n\n/**\n * Zod schema for database provider settings\n */\nexport const DatabaseProvidersSettingsSchema = z\n\t.object({\n\t\tneon: NeonSettingsSchema.optional().describe(\n\t\t\t'Neon database configuration. Requires Neon CLI installed and authenticated for database branching.',\n\t\t),\n\t})\n\t.optional()\n\n/**\n * Zod schema for iloom settings\n */\nexport const IloomSettingsSchema = z.object({\n\tmainBranch: z\n\t\t.string()\n\t\t.min(1, \"Settings 'mainBranch' cannot be empty\")\n\t\t.optional()\n\t\t.describe('Name of the main/primary branch for the repository'),\n\tworktreePrefix: z\n\t\t.string()\n\t\t.optional()\n\t\t.refine(\n\t\t\t(val) => {\n\t\t\t\tif (val === undefined) return true // undefined = use default calculation\n\t\t\t\tif (val === '') return true // empty string = no prefix mode\n\n\t\t\t\t// Allowlist: only alphanumeric, hyphens, underscores, and forward slashes\n\t\t\t\tconst allowedChars = /^[a-zA-Z0-9\\-_/]+$/\n\t\t\t\tif (!allowedChars.test(val)) return false\n\n\t\t\t\t// Reject if only special characters (no alphanumeric content)\n\t\t\t\tif (/^[-_/]+$/.test(val)) return false\n\n\t\t\t\t// Check each segment (split by /) contains at least one alphanumeric character\n\t\t\t\tconst segments = val.split('/')\n\t\t\t\tfor (const segment of segments) {\n\t\t\t\t\tif (segment && /^[-_]+$/.test(segment)) {\n\t\t\t\t\t\t// Segment exists but contains only hyphens/underscores\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn true\n\t\t\t},\n\t\t\t{\n\t\t\t\tmessage:\n\t\t\t\t\t\"worktreePrefix contains invalid characters. Only alphanumeric characters, hyphens (-), underscores (_), and forward slashes (/) are allowed. Use forward slashes for nested directories.\",\n\t\t\t},\n\t\t)\n\t\t.describe(\n\t\t\t'Prefix for worktree directories. Empty string disables prefix. Defaults to <repo-name>-looms if not set.',\n\t\t),\n\tprotectedBranches: z\n\t\t.array(z.string().min(1, 'Protected branch name cannot be empty'))\n\t\t.optional()\n\t\t.describe('List of branches that cannot be deleted (defaults to [mainBranch, \"main\", \"master\", \"develop\"])'),\n\tworkflows: WorkflowsSettingsSchema.describe('Per-workflow-type permission configurations'),\n\tagents: z\n\t\t.record(z.string(), AgentSettingsSchema)\n\t\t.optional()\n\t\t.nullable()\n\t\t.describe(\n\t\t\t'Per-agent configuration overrides. Available agents: ' +\n\t\t\t\t'iloom-issue-analyzer (analyzes issues), ' +\n\t\t\t\t'iloom-issue-planner (creates implementation plans), ' +\n\t\t\t\t'iloom-issue-analyze-and-plan (combined analysis and planning), ' +\n\t\t\t\t'iloom-issue-complexity-evaluator (evaluates complexity), ' +\n\t\t\t\t'iloom-issue-enhancer (enhances issue descriptions), ' +\n\t\t\t\t'iloom-issue-implementer (implements code changes), ' +\n\t\t\t\t'iloom-issue-reviewer (reviews code changes against requirements)',\n\t\t),\n\tcapabilities: CapabilitiesSettingsSchema.describe('Project capability configurations'),\n\tdatabaseProviders: DatabaseProvidersSettingsSchema.describe('Database provider configurations'),\n\tissueManagement: z\n\t\t.object({\n\t\t\tgithub: z\n\t\t\t\t.object({\n\t\t\t\t\tremote: z\n\t\t\t\t\t\t.string()\n\t\t\t\t\t\t.min(1, 'Remote name cannot be empty')\n\t\t\t\t\t\t.describe('Git remote name to use for GitHub operations'),\n\t\t\t\t})\n\t\t\t\t.optional(),\n\t\t})\n\t\t.optional()\n\t\t.describe('Issue management configuration'),\n\tmergeBehavior: z\n\t\t.object({\n\t\t\tmode: z.enum(['local', 'github-pr']).default('local'),\n\t\t\tremote: z.string().optional(),\n\t\t})\n\t\t.optional()\n\t\t.describe('Merge behavior configuration: local (merge locally) or github-pr (create PR)'),\n})\n\n/**\n * TypeScript type for Neon settings derived from Zod schema\n */\nexport type NeonSettings = z.infer<typeof NeonSettingsSchema>\n\n/**\n * TypeScript type for database providers settings derived from Zod schema\n */\nexport type DatabaseProvidersSettings = z.infer<typeof DatabaseProvidersSettingsSchema>\n\n/**\n * TypeScript type for agent settings derived from Zod schema\n */\nexport type AgentSettings = z.infer<typeof AgentSettingsSchema>\n\n/**\n * TypeScript type for workflow permission configuration derived from Zod schema\n */\nexport type WorkflowPermission = z.infer<typeof WorkflowPermissionSchema>\n\n/**\n * TypeScript type for workflows settings derived from Zod schema\n */\nexport type WorkflowsSettings = z.infer<typeof WorkflowsSettingsSchema>\n\n/**\n * TypeScript type for capabilities settings derived from Zod schema\n */\nexport type CapabilitiesSettings = z.infer<typeof CapabilitiesSettingsSchema>\n\n/**\n * TypeScript type for iloom settings derived from Zod schema\n */\nexport type IloomSettings = z.infer<typeof IloomSettingsSchema>\n\n/**\n * Manages project-level settings from .iloom/settings.json\n */\nexport class SettingsManager {\n\t/**\n\t * Load settings from <PROJECT_ROOT>/.iloom/settings.json and settings.local.json\n\t * Merges settings.local.json over settings.json with priority\n\t * CLI overrides have highest priority if provided\n\t * Returns empty object if both files don't exist (not an error)\n\t */\n\tasync loadSettings(\n\t\tprojectRoot?: string,\n\t\tcliOverrides?: Partial<IloomSettings>,\n\t): Promise<IloomSettings> {\n\t\tconst root = this.getProjectRoot(projectRoot)\n\n\t\t// Load base settings from settings.json\n\t\tconst baseSettings = await this.loadSettingsFile(root, 'settings.json')\n\t\tconst baseSettingsPath = path.join(root, '.iloom', 'settings.json')\n\t\tlogger.debug(`📄 Base settings from ${baseSettingsPath}:`, JSON.stringify(baseSettings, null, 2))\n\n\t\t// Load local overrides from settings.local.json\n\t\tconst localSettings = await this.loadSettingsFile(root, 'settings.local.json')\n\t\tconst localSettingsPath = path.join(root, '.iloom', 'settings.local.json')\n\t\tlogger.debug(`📄 Local settings from ${localSettingsPath}:`, JSON.stringify(localSettings, null, 2))\n\n\t\t// Deep merge with priority: cliOverrides > localSettings > baseSettings\n\t\tlet merged = this.mergeSettings(baseSettings, localSettings)\n\t\tlogger.debug('🔄 After merging base + local settings:', JSON.stringify(merged, null, 2))\n\n\t\tif (cliOverrides && Object.keys(cliOverrides).length > 0) {\n\t\t\tlogger.debug('⚙️ CLI overrides to apply:', JSON.stringify(cliOverrides, null, 2))\n\t\t\tmerged = this.mergeSettings(merged, cliOverrides)\n\t\t\tlogger.debug('🔄 After applying CLI overrides:', JSON.stringify(merged, null, 2))\n\t\t}\n\n\t\t// Validate merged result\n\t\ttry {\n\t\t\tconst finalSettings = IloomSettingsSchema.parse(merged)\n\n\t\t\t// Debug: Log final merged configuration\n\t\t\tthis.logFinalConfiguration(finalSettings)\n\n\t\t\treturn finalSettings\n\t\t} catch (error) {\n\t\t\t// Show all Zod validation errors\n\t\t\tif (error instanceof z.ZodError) {\n\t\t\t\tconst errorMsg = this.formatAllZodErrors(error, '<merged settings>')\n\t\t\t\t// Enhance error message if CLI overrides were applied\n\t\t\t\tif (cliOverrides && Object.keys(cliOverrides).length > 0) {\n\t\t\t\t\tthrow new Error(`${errorMsg.message}\\n\\nNote: CLI overrides were applied. Check your --set arguments.`)\n\t\t\t\t}\n\t\t\t\tthrow errorMsg\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t/**\n\t * Log the final merged configuration for debugging\n\t */\n\tprivate logFinalConfiguration(settings: IloomSettings): void {\n\t\tlogger.debug('📋 Final merged configuration:', JSON.stringify(settings, null, 2))\n\t}\n\n\t/**\n\t * Load and parse a single settings file\n\t * Returns empty object if file doesn't exist (not an error)\n\t */\n\tprivate async loadSettingsFile(\n\t\tprojectRoot: string,\n\t\tfilename: string,\n\t): Promise<Partial<IloomSettings>> {\n\t\tconst settingsPath = path.join(projectRoot, '.iloom', filename)\n\n\t\ttry {\n\t\t\tconst content = await readFile(settingsPath, 'utf-8')\n\t\t\tlet parsed: unknown\n\n\t\t\ttry {\n\t\t\t\tparsed = JSON.parse(content)\n\t\t\t} catch (error) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Failed to parse settings file at ${settingsPath}: ${error instanceof Error ? error.message : 'Invalid JSON'}`,\n\t\t\t\t)\n\t\t\t}\n\n\t\t\t// Validate individual file with strict mode to catch unknown keys\n\t\t\t// Note: Schema already has all fields as optional, so no need for .partial()\n\t\t\ttry {\n\t\t\t\tconst validated = IloomSettingsSchema.strict().parse(parsed)\n\t\t\t\treturn validated\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof z.ZodError) {\n\t\t\t\t\tconst errorMsg = this.formatAllZodErrors(error, filename)\n\t\t\t\t\tthrow errorMsg\n\t\t\t\t}\n\t\t\t\tthrow error\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// File not found is not an error - return empty settings\n\t\t\tif ((error as { code?: string }).code === 'ENOENT') {\n\t\t\t\tlogger.debug(`No settings file found at ${settingsPath}, using defaults`)\n\t\t\t\treturn {}\n\t\t\t}\n\n\t\t\t// Re-throw parsing errors\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t/**\n\t * Deep merge two settings objects with priority to override\n\t * Uses deepmerge library with array replacement strategy\n\t */\n\tprivate mergeSettings(\n\t\tbase: Partial<IloomSettings>,\n\t\toverride: Partial<IloomSettings>,\n\t): IloomSettings {\n\t\t// Use deepmerge with array replacement (not concatenation)\n\t\treturn deepmerge(base, override, {\n\t\t\t// Replace arrays instead of concatenating them\n\t\t\tarrayMerge: (_destinationArray, sourceArray) => sourceArray,\n\t\t}) as IloomSettings\n\t}\n\n\t/**\n\t * Format all Zod validation errors into a single error message\n\t */\n\tprivate formatAllZodErrors(error: z.ZodError, settingsPath: string): Error {\n\t\tconst errorMessages = error.issues.map(issue => {\n\t\t\tconst path = issue.path.length > 0 ? issue.path.join('.') : 'root'\n\t\t\treturn ` - ${path}: ${issue.message}`\n\t\t})\n\n\t\treturn new Error(\n\t\t\t`Settings validation failed at ${settingsPath}:\\n${errorMessages.join('\\n')}`,\n\t\t)\n\t}\n\n\t/**\n\t * Validate settings structure and model names using Zod schema\n\t * This method is kept for testing purposes but uses Zod internally\n\t * @internal - Only used in tests via bracket notation\n\t */\n\t// @ts-expect-error - Used in tests via bracket notation, TypeScript can't detect this usage\n\tprivate validateSettings(settings: IloomSettings): void {\n\t\ttry {\n\t\t\tIloomSettingsSchema.parse(settings)\n\t\t} catch (error) {\n\t\t\tif (error instanceof z.ZodError) {\n\t\t\t\tthrow this.formatAllZodErrors(error, '<validation>')\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t/**\n\t * Get project root (defaults to process.cwd())\n\t */\n\tprivate getProjectRoot(projectRoot?: string): string {\n\t\treturn projectRoot ?? process.cwd()\n\t}\n\n\t/**\n\t * Get effective protected branches list with mainBranch always included\n\t *\n\t * This method provides a single source of truth for protected branches logic:\n\t * 1. Use configured protectedBranches if provided\n\t * 2. Otherwise use defaults: [mainBranch, 'main', 'master', 'develop']\n\t * 3. ALWAYS ensure mainBranch is included even if user configured custom list\n\t *\n\t * @param projectRoot - Optional project root directory (defaults to process.cwd())\n\t * @returns Array of protected branch names with mainBranch guaranteed to be included\n\t */\n\tasync getProtectedBranches(projectRoot?: string): Promise<string[]> {\n\t\tconst settings = await this.loadSettings(projectRoot)\n\t\tconst mainBranch = settings.mainBranch ?? 'main'\n\n\t\t// Build protected branches list:\n\t\t// 1. Use configured protectedBranches if provided\n\t\t// 2. Otherwise use defaults: [mainBranch, 'main', 'master', 'develop']\n\t\t// 3. ALWAYS ensure mainBranch is included even if user configured custom list\n\t\tlet protectedBranches: string[]\n\t\tif (settings.protectedBranches) {\n\t\t\t// Use configured list but ensure mainBranch is always included\n\t\t\tprotectedBranches = settings.protectedBranches.includes(mainBranch)\n\t\t\t\t? settings.protectedBranches\n\t\t\t\t: [mainBranch, ...settings.protectedBranches]\n\t\t} else {\n\t\t\t// Use defaults with current mainBranch\n\t\t\tprotectedBranches = [mainBranch, 'main', 'master', 'develop']\n\t\t}\n\n\t\treturn protectedBranches\n\t}\n}\n"],"mappings":"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","names":["path"]}
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
fetchProjectList,
|
|
12
12
|
hasProjectScope,
|
|
13
13
|
updateProjectItemField
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-SWCRXDZC.js";
|
|
15
15
|
import {
|
|
16
16
|
promptConfirmation
|
|
17
17
|
} from "./chunk-JNKJ7NJV.js";
|
|
@@ -312,4 +312,4 @@ State: ${entity.state}`;
|
|
|
312
312
|
export {
|
|
313
313
|
GitHubService
|
|
314
314
|
};
|
|
315
|
-
//# sourceMappingURL=chunk-
|
|
315
|
+
//# sourceMappingURL=chunk-TS6DL67T.js.map
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
isPRBranch,
|
|
12
12
|
isValidGitRepo,
|
|
13
13
|
parseWorktreeList
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-HBVFXN7R.js";
|
|
15
15
|
|
|
16
16
|
// src/lib/GitWorktreeManager.ts
|
|
17
17
|
import path from "path";
|
|
@@ -386,4 +386,4 @@ var GitWorktreeManager = class {
|
|
|
386
386
|
export {
|
|
387
387
|
GitWorktreeManager
|
|
388
388
|
};
|
|
389
|
-
//# sourceMappingURL=chunk-
|
|
389
|
+
//# sourceMappingURL=chunk-VETG35MF.js.map
|