@iloom/cli 0.3.4 → 0.4.1
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 +13 -3
- package/dist/{BranchNamingService-A77VI6AI.js → BranchNamingService-GCCWB3LK.js} +4 -3
- package/dist/ClaudeContextManager-DK77227F.js +16 -0
- package/dist/ClaudeService-W3SA7HVG.js +15 -0
- package/dist/GitHubService-RPM27GWD.js +12 -0
- package/dist/{LoomLauncher-ZV3ZZIBA.js → LoomLauncher-S3YGJRJQ.js} +43 -27
- package/dist/LoomLauncher-S3YGJRJQ.js.map +1 -0
- package/dist/PromptTemplateManager-2TDZAUC6.js +9 -0
- package/dist/README.md +13 -3
- package/dist/{SettingsManager-I2LRCW2A.js → SettingsManager-FJFU6JJD.js} +7 -3
- package/dist/SettingsMigrationManager-EH3J2TCN.js +10 -0
- package/dist/{chunk-5Q3NDNNV.js → chunk-2W2FBL5G.js} +153 -6
- package/dist/chunk-2W2FBL5G.js.map +1 -0
- package/dist/{chunk-OXAM2WVC.js → chunk-55TB3FSG.js} +21 -1
- package/dist/chunk-55TB3FSG.js.map +1 -0
- package/dist/chunk-6UIGZD2N.js +20 -0
- package/dist/chunk-6UIGZD2N.js.map +1 -0
- package/dist/{chunk-RIEO2WML.js → chunk-74VMN2KC.js} +26 -2
- package/dist/chunk-74VMN2KC.js.map +1 -0
- package/dist/{chunk-2MAIX45J.js → chunk-BIIQHEXJ.js} +104 -43
- package/dist/chunk-BIIQHEXJ.js.map +1 -0
- package/dist/{chunk-UAN4A3YU.js → chunk-G6CIIJLT.js} +11 -11
- package/dist/{chunk-DLHA5VQ3.js → chunk-HD5SUKI2.js} +36 -179
- package/dist/chunk-HD5SUKI2.js.map +1 -0
- package/dist/{chunk-2IJEMXOB.js → chunk-IARWMDAX.js} +427 -428
- package/dist/chunk-IARWMDAX.js.map +1 -0
- package/dist/chunk-IJ7IGJT3.js +192 -0
- package/dist/chunk-IJ7IGJT3.js.map +1 -0
- package/dist/{chunk-2CXREBLZ.js → chunk-JC5HXN75.js} +8 -6
- package/dist/chunk-JC5HXN75.js.map +1 -0
- package/dist/{chunk-3RUPPQRG.js → chunk-KO2FOMHL.js} +43 -2
- package/dist/{chunk-3RUPPQRG.js.map → chunk-KO2FOMHL.js.map} +1 -1
- package/dist/{chunk-4XIDC3NF.js → chunk-MD6HA5IK.js} +2 -2
- package/dist/{chunk-OC4H6HJD.js → chunk-O7WHXLCB.js} +2 -2
- package/dist/{chunk-M7JJCX53.js → chunk-OEGECBFS.js} +20 -20
- package/dist/chunk-OEGECBFS.js.map +1 -0
- package/dist/{chunk-MKWYLDFK.js → chunk-OF7BNW4D.js} +43 -3
- package/dist/chunk-OF7BNW4D.js.map +1 -0
- package/dist/{chunk-PGPI5LR4.js → chunk-POI7KLBH.js} +7 -21
- package/dist/chunk-POI7KLBH.js.map +1 -0
- package/dist/{chunk-PA6Q6AWM.js → chunk-PSFVTBM7.js} +2 -2
- package/dist/chunk-QHA67Q7A.js +281 -0
- package/dist/chunk-QHA67Q7A.js.map +1 -0
- package/dist/{chunk-SUOXY5WJ.js → chunk-QIUJPPJQ.js} +5 -5
- package/dist/chunk-QIUJPPJQ.js.map +1 -0
- package/dist/{chunk-ZM3CFL5L.js → chunk-QRBOPFAA.js} +3 -3
- package/dist/{chunk-OYF4VIFI.js → chunk-RUC7OULH.js} +147 -22
- package/dist/chunk-RUC7OULH.js.map +1 -0
- package/dist/{chunk-CE26YH2U.js → chunk-SJ2GZ6RF.js} +48 -50
- package/dist/chunk-SJ2GZ6RF.js.map +1 -0
- package/dist/{chunk-SSCQCCJ7.js → chunk-THF25ICZ.js} +2 -2
- package/dist/chunk-TMZAVPGF.js +667 -0
- package/dist/chunk-TMZAVPGF.js.map +1 -0
- package/dist/{chunk-5VK4NRSF.js → chunk-UNXRACJ7.js} +35 -36
- package/dist/chunk-UNXRACJ7.js.map +1 -0
- package/dist/{chunk-AKUJXDNW.js → chunk-UPUAQYAW.js} +3 -3
- package/dist/{chunk-GEHQXLEI.js → chunk-UYVWLISQ.js} +18 -35
- package/dist/chunk-UYVWLISQ.js.map +1 -0
- package/dist/{chunk-OSCLCMDG.js → chunk-UYWAESOT.js} +3 -3
- package/dist/{chunk-RW54ZMBM.js → chunk-VAYGNQTE.js} +2 -2
- package/dist/{chunk-ZT3YZB4K.js → chunk-VBFDVGAE.js} +12 -12
- package/dist/chunk-VBFDVGAE.js.map +1 -0
- package/dist/{chunk-IFB4Z76W.js → chunk-VTXCGKV5.js} +13 -12
- package/dist/chunk-VTXCGKV5.js.map +1 -0
- package/dist/{chunk-CDZERT7Z.js → chunk-VWNS6DH5.js} +48 -4
- package/dist/chunk-VWNS6DH5.js.map +1 -0
- package/dist/{chunk-CFFQ2Z7A.js → chunk-WUQQNE63.js} +2 -2
- package/dist/{chunk-UJL4HI2R.js → chunk-Z5NXYJIG.js} +20 -2
- package/dist/chunk-Z5NXYJIG.js.map +1 -0
- package/dist/{claude-W52VKI6L.js → claude-ACVXNB6N.js} +8 -5
- package/dist/{cleanup-H4VXU3C3.js → cleanup-KDLVTT7M.js} +133 -122
- package/dist/cleanup-KDLVTT7M.js.map +1 -0
- package/dist/cli.js +953 -430
- package/dist/cli.js.map +1 -1
- package/dist/{color-F7RU6B6Z.js → color-ZPIIUADB.js} +3 -3
- package/dist/{contribute-Y7IQV5QY.js → contribute-HY372S6F.js} +8 -6
- package/dist/{contribute-Y7IQV5QY.js.map → contribute-HY372S6F.js.map} +1 -1
- package/dist/dev-server-JCJGQ3PV.js +298 -0
- package/dist/dev-server-JCJGQ3PV.js.map +1 -0
- package/dist/{feedback-XTUCKJNT.js → feedback-7PVBQNLJ.js} +13 -12
- package/dist/{feedback-XTUCKJNT.js.map → feedback-7PVBQNLJ.js.map} +1 -1
- package/dist/{git-IYA53VIC.js → git-4BVOOOOV.js} +16 -4
- package/dist/hooks/iloom-hook.js +258 -0
- package/dist/{ignite-T74RYXCA.js → ignite-3B264M7K.js} +245 -39
- package/dist/ignite-3B264M7K.js.map +1 -0
- package/dist/index.d.ts +461 -124
- package/dist/index.js +743 -210
- package/dist/index.js.map +1 -1
- package/dist/init-LBA6NUK2.js +21 -0
- package/dist/{installation-detector-VARGFFRZ.js → installation-detector-6R6YOFVZ.js} +3 -3
- package/dist/mcp/issue-management-server.js +2 -1
- package/dist/mcp/issue-management-server.js.map +1 -1
- package/dist/neon-helpers-L5CXQ5CT.js +11 -0
- package/dist/{open-UMXANW5S.js → open-OGCV32Z4.js} +15 -13
- package/dist/{open-UMXANW5S.js.map → open-OGCV32Z4.js.map} +1 -1
- package/dist/projects-P55273AB.js +73 -0
- package/dist/projects-P55273AB.js.map +1 -0
- package/dist/{prompt-QALMYTVC.js → prompt-A7GGRHSY.js} +3 -3
- package/dist/prompts/init-prompt.txt +49 -0
- package/dist/prompts/issue-prompt.txt +110 -8
- package/dist/prompts/regular-prompt.txt +90 -0
- package/dist/prompts/session-summary-prompt.txt +82 -0
- package/dist/{rebase-VJ2VKR6R.js → rebase-4T5FQHNH.js} +11 -9
- package/dist/{rebase-VJ2VKR6R.js.map → rebase-4T5FQHNH.js.map} +1 -1
- package/dist/{remote-VUNCQZ6J.js → remote-73TZ2ADI.js} +3 -3
- package/dist/{run-MJYY4PUT.js → run-HNOP6WE2.js} +15 -13
- package/dist/{run-MJYY4PUT.js.map → run-HNOP6WE2.js.map} +1 -1
- package/dist/schema/settings.schema.json +49 -0
- package/dist/shell-DE3HKJSM.js +240 -0
- package/dist/shell-DE3HKJSM.js.map +1 -0
- package/dist/summary-GDT7DTRI.js +244 -0
- package/dist/summary-GDT7DTRI.js.map +1 -0
- package/dist/{test-git-IT5EWQ5C.js → test-git-YMAE57UP.js} +6 -4
- package/dist/{test-git-IT5EWQ5C.js.map → test-git-YMAE57UP.js.map} +1 -1
- package/dist/{test-prefix-NPWDPUUH.js → test-prefix-YCKL6CMT.js} +6 -4
- package/dist/{test-prefix-NPWDPUUH.js.map → test-prefix-YCKL6CMT.js.map} +1 -1
- package/dist/{test-tabs-PRMRSHKI.js → test-tabs-3SCJWRKT.js} +4 -4
- package/dist/{test-webserver-DAHONWCS.js → test-webserver-VPNLAFZ3.js} +2 -2
- package/dist/{update-4TDDUR5K.js → update-LETF5ASC.js} +4 -4
- package/dist/{update-notifier-QEX3CJHA.js → update-notifier-H55ZK7NU.js} +3 -3
- package/package.json +6 -6
- package/dist/ClaudeContextManager-BN7RE5ZQ.js +0 -15
- package/dist/ClaudeService-DLYLJUPA.js +0 -14
- package/dist/GitHubService-FZHHBOFG.js +0 -11
- package/dist/LoomLauncher-ZV3ZZIBA.js.map +0 -1
- package/dist/PromptTemplateManager-6HH3PVXV.js +0 -9
- package/dist/SettingsMigrationManager-TJ7UWZG5.js +0 -10
- package/dist/chunk-2CXREBLZ.js.map +0 -1
- package/dist/chunk-2IJEMXOB.js.map +0 -1
- package/dist/chunk-2MAIX45J.js.map +0 -1
- package/dist/chunk-5Q3NDNNV.js.map +0 -1
- package/dist/chunk-5VK4NRSF.js.map +0 -1
- package/dist/chunk-CDZERT7Z.js.map +0 -1
- package/dist/chunk-CE26YH2U.js.map +0 -1
- package/dist/chunk-DLHA5VQ3.js.map +0 -1
- package/dist/chunk-GEHQXLEI.js.map +0 -1
- package/dist/chunk-IFB4Z76W.js.map +0 -1
- package/dist/chunk-M7JJCX53.js.map +0 -1
- package/dist/chunk-MKWYLDFK.js.map +0 -1
- package/dist/chunk-OXAM2WVC.js.map +0 -1
- package/dist/chunk-OYF4VIFI.js.map +0 -1
- package/dist/chunk-PGPI5LR4.js.map +0 -1
- package/dist/chunk-RIEO2WML.js.map +0 -1
- package/dist/chunk-SUOXY5WJ.js.map +0 -1
- package/dist/chunk-UJL4HI2R.js.map +0 -1
- package/dist/chunk-ZT3YZB4K.js.map +0 -1
- package/dist/cleanup-H4VXU3C3.js.map +0 -1
- package/dist/ignite-T74RYXCA.js.map +0 -1
- package/dist/init-4FHTAM3F.js +0 -19
- package/dist/logger-MKYH4UDV.js +0 -12
- package/dist/neon-helpers-77PBPGJ5.js +0 -10
- package/dist/update-notifier-QEX3CJHA.js.map +0 -1
- /package/dist/{BranchNamingService-A77VI6AI.js.map → BranchNamingService-GCCWB3LK.js.map} +0 -0
- /package/dist/{ClaudeContextManager-BN7RE5ZQ.js.map → ClaudeContextManager-DK77227F.js.map} +0 -0
- /package/dist/{ClaudeService-DLYLJUPA.js.map → ClaudeService-W3SA7HVG.js.map} +0 -0
- /package/dist/{GitHubService-FZHHBOFG.js.map → GitHubService-RPM27GWD.js.map} +0 -0
- /package/dist/{PromptTemplateManager-6HH3PVXV.js.map → PromptTemplateManager-2TDZAUC6.js.map} +0 -0
- /package/dist/{SettingsManager-I2LRCW2A.js.map → SettingsManager-FJFU6JJD.js.map} +0 -0
- /package/dist/{SettingsMigrationManager-TJ7UWZG5.js.map → SettingsMigrationManager-EH3J2TCN.js.map} +0 -0
- /package/dist/{chunk-UAN4A3YU.js.map → chunk-G6CIIJLT.js.map} +0 -0
- /package/dist/{chunk-4XIDC3NF.js.map → chunk-MD6HA5IK.js.map} +0 -0
- /package/dist/{chunk-OC4H6HJD.js.map → chunk-O7WHXLCB.js.map} +0 -0
- /package/dist/{chunk-PA6Q6AWM.js.map → chunk-PSFVTBM7.js.map} +0 -0
- /package/dist/{chunk-ZM3CFL5L.js.map → chunk-QRBOPFAA.js.map} +0 -0
- /package/dist/{chunk-SSCQCCJ7.js.map → chunk-THF25ICZ.js.map} +0 -0
- /package/dist/{chunk-AKUJXDNW.js.map → chunk-UPUAQYAW.js.map} +0 -0
- /package/dist/{chunk-OSCLCMDG.js.map → chunk-UYWAESOT.js.map} +0 -0
- /package/dist/{chunk-RW54ZMBM.js.map → chunk-VAYGNQTE.js.map} +0 -0
- /package/dist/{chunk-CFFQ2Z7A.js.map → chunk-WUQQNE63.js.map} +0 -0
- /package/dist/{claude-W52VKI6L.js.map → claude-ACVXNB6N.js.map} +0 -0
- /package/dist/{color-F7RU6B6Z.js.map → color-ZPIIUADB.js.map} +0 -0
- /package/dist/{git-IYA53VIC.js.map → git-4BVOOOOV.js.map} +0 -0
- /package/dist/{init-4FHTAM3F.js.map → init-LBA6NUK2.js.map} +0 -0
- /package/dist/{installation-detector-VARGFFRZ.js.map → installation-detector-6R6YOFVZ.js.map} +0 -0
- /package/dist/{logger-MKYH4UDV.js.map → neon-helpers-L5CXQ5CT.js.map} +0 -0
- /package/dist/{neon-helpers-77PBPGJ5.js.map → prompt-A7GGRHSY.js.map} +0 -0
- /package/dist/{prompt-QALMYTVC.js.map → remote-73TZ2ADI.js.map} +0 -0
- /package/dist/{test-tabs-PRMRSHKI.js.map → test-tabs-3SCJWRKT.js.map} +0 -0
- /package/dist/{test-webserver-DAHONWCS.js.map → test-webserver-VPNLAFZ3.js.map} +0 -0
- /package/dist/{update-4TDDUR5K.js.map → update-LETF5ASC.js.map} +0 -0
- /package/dist/{remote-VUNCQZ6J.js.map → update-notifier-H55ZK7NU.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -1,63 +1,62 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
SessionSummaryService
|
|
4
|
+
} from "./chunk-TMZAVPGF.js";
|
|
2
5
|
import {
|
|
3
6
|
CLIIsolationManager,
|
|
4
7
|
DatabaseManager,
|
|
5
8
|
EnvironmentManager,
|
|
6
9
|
LoomManager,
|
|
7
|
-
MetadataManager,
|
|
8
10
|
ResourceCleanup
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import {
|
|
11
|
-
IdentifierParser
|
|
12
|
-
} from "./chunk-OXAM2WVC.js";
|
|
13
|
-
import {
|
|
14
|
-
ProcessManager
|
|
15
|
-
} from "./chunk-VU3QMIP2.js";
|
|
11
|
+
} from "./chunk-IARWMDAX.js";
|
|
16
12
|
import {
|
|
17
13
|
InitCommand,
|
|
18
14
|
ShellCompletion
|
|
19
|
-
} from "./chunk-
|
|
20
|
-
import
|
|
21
|
-
getConfiguredRepoFromSettings,
|
|
22
|
-
getEffectivePRTargetRemote,
|
|
23
|
-
hasMultipleRemotes,
|
|
24
|
-
parseGitRemotes
|
|
25
|
-
} from "./chunk-PA6Q6AWM.js";
|
|
26
|
-
import "./chunk-OSCLCMDG.js";
|
|
15
|
+
} from "./chunk-G6CIIJLT.js";
|
|
16
|
+
import "./chunk-UYWAESOT.js";
|
|
27
17
|
import {
|
|
28
18
|
IssueEnhancementService,
|
|
29
19
|
capitalizeFirstLetter
|
|
30
|
-
} from "./chunk-
|
|
31
|
-
import {
|
|
32
|
-
openBrowser
|
|
33
|
-
} from "./chunk-YETJNRQM.js";
|
|
20
|
+
} from "./chunk-VTXCGKV5.js";
|
|
34
21
|
import {
|
|
35
22
|
MergeManager
|
|
36
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-BIIQHEXJ.js";
|
|
37
24
|
import {
|
|
38
25
|
FirstRunManager,
|
|
39
26
|
IssueTrackerFactory,
|
|
40
27
|
generateIssueManagementMcpConfig
|
|
41
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-HD5SUKI2.js";
|
|
29
|
+
import "./chunk-QHA67Q7A.js";
|
|
42
30
|
import {
|
|
43
31
|
AgentManager
|
|
44
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-O7WHXLCB.js";
|
|
33
|
+
import {
|
|
34
|
+
IdentifierParser
|
|
35
|
+
} from "./chunk-55TB3FSG.js";
|
|
36
|
+
import {
|
|
37
|
+
ProcessManager
|
|
38
|
+
} from "./chunk-VU3QMIP2.js";
|
|
39
|
+
import {
|
|
40
|
+
openBrowser
|
|
41
|
+
} from "./chunk-YETJNRQM.js";
|
|
45
42
|
import {
|
|
46
43
|
GitWorktreeManager
|
|
47
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-JC5HXN75.js";
|
|
48
45
|
import {
|
|
49
46
|
detectPackageManager,
|
|
50
47
|
installDependencies,
|
|
51
48
|
runScript
|
|
52
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-VBFDVGAE.js";
|
|
53
50
|
import {
|
|
54
51
|
ClaudeContextManager
|
|
55
|
-
} from "./chunk-
|
|
56
|
-
import "./chunk-
|
|
57
|
-
import
|
|
52
|
+
} from "./chunk-UPUAQYAW.js";
|
|
53
|
+
import "./chunk-POI7KLBH.js";
|
|
54
|
+
import {
|
|
55
|
+
extractSettingsOverrides
|
|
56
|
+
} from "./chunk-GYCR2LOU.js";
|
|
58
57
|
import {
|
|
59
58
|
DefaultBranchNamingService
|
|
60
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-QIUJPPJQ.js";
|
|
61
60
|
import {
|
|
62
61
|
ProjectCapabilityDetector
|
|
63
62
|
} from "./chunk-EBISESAP.js";
|
|
@@ -65,45 +64,58 @@ import {
|
|
|
65
64
|
hasScript,
|
|
66
65
|
readPackageJson
|
|
67
66
|
} from "./chunk-2ZPFJQ3B.js";
|
|
68
|
-
import {
|
|
69
|
-
extractSettingsOverrides
|
|
70
|
-
} from "./chunk-GYCR2LOU.js";
|
|
71
67
|
import {
|
|
72
68
|
createNeonProviderFromSettings
|
|
73
|
-
} from "./chunk-
|
|
69
|
+
} from "./chunk-UNXRACJ7.js";
|
|
70
|
+
import {
|
|
71
|
+
getConfiguredRepoFromSettings,
|
|
72
|
+
getEffectivePRTargetRemote,
|
|
73
|
+
hasMultipleRemotes,
|
|
74
|
+
parseGitRemotes
|
|
75
|
+
} from "./chunk-PSFVTBM7.js";
|
|
74
76
|
import {
|
|
75
77
|
executeGitCommand,
|
|
76
78
|
extractIssueNumber,
|
|
77
79
|
findMainWorktreePathWithSettings,
|
|
80
|
+
getMergeTargetBranch,
|
|
78
81
|
getRepoRoot,
|
|
79
82
|
pushBranchToRemote
|
|
80
|
-
} from "./chunk-
|
|
83
|
+
} from "./chunk-2W2FBL5G.js";
|
|
84
|
+
import {
|
|
85
|
+
MetadataManager
|
|
86
|
+
} from "./chunk-IJ7IGJT3.js";
|
|
81
87
|
import {
|
|
82
88
|
SettingsManager
|
|
83
|
-
} from "./chunk-
|
|
89
|
+
} from "./chunk-VWNS6DH5.js";
|
|
84
90
|
import {
|
|
85
91
|
GitHubService
|
|
86
|
-
} from "./chunk-
|
|
92
|
+
} from "./chunk-OEGECBFS.js";
|
|
87
93
|
import {
|
|
88
94
|
executeGhCommand
|
|
89
|
-
} from "./chunk-
|
|
95
|
+
} from "./chunk-KO2FOMHL.js";
|
|
90
96
|
import {
|
|
91
97
|
promptCommitAction,
|
|
92
98
|
promptConfirmation,
|
|
93
99
|
waitForKeypress
|
|
94
|
-
} from "./chunk-
|
|
95
|
-
import "./chunk-
|
|
100
|
+
} from "./chunk-SJ2GZ6RF.js";
|
|
101
|
+
import "./chunk-WUQQNE63.js";
|
|
96
102
|
import {
|
|
97
103
|
detectClaudeCli,
|
|
98
104
|
launchClaude
|
|
99
|
-
} from "./chunk-
|
|
100
|
-
import "./chunk-
|
|
105
|
+
} from "./chunk-RUC7OULH.js";
|
|
106
|
+
import "./chunk-VAYGNQTE.js";
|
|
101
107
|
import {
|
|
102
108
|
loadEnvIntoProcess
|
|
103
|
-
} from "./chunk-
|
|
109
|
+
} from "./chunk-Z5NXYJIG.js";
|
|
110
|
+
import {
|
|
111
|
+
getLogger,
|
|
112
|
+
withLogger
|
|
113
|
+
} from "./chunk-6UIGZD2N.js";
|
|
114
|
+
import "./chunk-74VMN2KC.js";
|
|
104
115
|
import {
|
|
116
|
+
createStderrLogger,
|
|
105
117
|
logger
|
|
106
|
-
} from "./chunk-
|
|
118
|
+
} from "./chunk-UYVWLISQ.js";
|
|
107
119
|
|
|
108
120
|
// src/cli.ts
|
|
109
121
|
import { program, Option } from "commander";
|
|
@@ -158,7 +170,7 @@ async function launchFirstRunSetup() {
|
|
|
158
170
|
logger.info(
|
|
159
171
|
"iloom will now launch an interactive configuration session with Claude."
|
|
160
172
|
);
|
|
161
|
-
const { waitForKeypress: waitForKeypress2 } = await import("./prompt-
|
|
173
|
+
const { waitForKeypress: waitForKeypress2 } = await import("./prompt-A7GGRHSY.js");
|
|
162
174
|
await waitForKeypress2("Press any key to start configuration...");
|
|
163
175
|
const initCommand = new InitCommand();
|
|
164
176
|
await initCommand.execute(
|
|
@@ -181,10 +193,10 @@ var StartCommand = class {
|
|
|
181
193
|
this.providedLoomManager = loomManager;
|
|
182
194
|
const envResult = loadEnvIntoProcess();
|
|
183
195
|
if (envResult.error) {
|
|
184
|
-
|
|
196
|
+
getLogger().debug(`Environment loading warning: ${envResult.error.message}`);
|
|
185
197
|
}
|
|
186
198
|
if (envResult.parsed) {
|
|
187
|
-
|
|
199
|
+
getLogger().debug(`Loaded ${Object.keys(envResult.parsed).length} environment variables`);
|
|
188
200
|
}
|
|
189
201
|
}
|
|
190
202
|
/**
|
|
@@ -228,36 +240,40 @@ var StartCommand = class {
|
|
|
228
240
|
* Main entry point for the start command
|
|
229
241
|
*/
|
|
230
242
|
async execute(input) {
|
|
231
|
-
var _a, _b, _c, _d;
|
|
243
|
+
var _a, _b, _c, _d, _e;
|
|
244
|
+
const isJsonMode = input.options.json === true;
|
|
232
245
|
try {
|
|
233
246
|
const initialSettings = await this.settingsManager.loadSettings();
|
|
234
|
-
if (process.env.FORCE_FIRST_TIME_SETUP === "true" || await needsFirstRunSetup()) {
|
|
247
|
+
if (!isJsonMode && (process.env.FORCE_FIRST_TIME_SETUP === "true" || await needsFirstRunSetup())) {
|
|
235
248
|
await launchFirstRunSetup();
|
|
236
249
|
const newSettings = await this.settingsManager.loadSettings();
|
|
237
250
|
const newProvider = ((_a = newSettings.issueManagement) == null ? void 0 : _a.provider) ?? "github";
|
|
238
251
|
if (newProvider !== this.issueTracker.providerName) {
|
|
239
|
-
|
|
252
|
+
getLogger().debug(`Reinitializing issue tracker: provider changed to "${newProvider}"`);
|
|
240
253
|
this.issueTracker = IssueTrackerFactory.create(newSettings);
|
|
241
254
|
}
|
|
242
255
|
}
|
|
243
256
|
let repo;
|
|
244
257
|
if (this.issueTracker.providerName === "github" && await hasMultipleRemotes()) {
|
|
245
258
|
repo = await getConfiguredRepoFromSettings(initialSettings);
|
|
246
|
-
|
|
259
|
+
getLogger().info(`Using GitHub repository: ${repo}`);
|
|
247
260
|
}
|
|
248
261
|
const loomManager = await this.initializeLoomManager();
|
|
249
262
|
let parentLoom = await this.detectParentLoom(loomManager);
|
|
250
263
|
const parsed = await this.parseInput(input.identifier, repo);
|
|
251
264
|
await this.validateInput(parsed, repo);
|
|
252
265
|
if (parentLoom) {
|
|
253
|
-
const { isInteractiveEnvironment, promptConfirmation: promptConfirmation2 } = await import("./prompt-
|
|
266
|
+
const { isInteractiveEnvironment, promptConfirmation: promptConfirmation2 } = await import("./prompt-A7GGRHSY.js");
|
|
254
267
|
const parentDisplay = parentLoom.type === "issue" ? `issue #${parentLoom.identifier}` : parentLoom.type === "pr" ? `PR #${parentLoom.identifier}` : `branch ${parentLoom.identifier}`;
|
|
255
268
|
if (input.options.childLoom === true) {
|
|
256
|
-
|
|
269
|
+
getLogger().info(`Creating as child loom of ${parentDisplay} (--child-loom flag)`);
|
|
257
270
|
} else if (input.options.childLoom === false) {
|
|
258
271
|
parentLoom = null;
|
|
259
|
-
|
|
272
|
+
getLogger().info("Creating as independent loom (--no-child-loom flag)");
|
|
260
273
|
} else {
|
|
274
|
+
if (isJsonMode) {
|
|
275
|
+
throw new Error("JSON mode requires explicit --child-loom or --no-child-loom flag when running from inside a loom");
|
|
276
|
+
}
|
|
261
277
|
let createAsChild = true;
|
|
262
278
|
if (isInteractiveEnvironment()) {
|
|
263
279
|
createAsChild = await promptConfirmation2(
|
|
@@ -266,19 +282,19 @@ var StartCommand = class {
|
|
|
266
282
|
// Default yes
|
|
267
283
|
);
|
|
268
284
|
} else {
|
|
269
|
-
|
|
285
|
+
getLogger().error(`Non-interactive environment detected, use either --child-loom or --no-child-loom to specify behavior`);
|
|
270
286
|
process.exit(1);
|
|
271
287
|
}
|
|
272
288
|
if (!createAsChild) {
|
|
273
289
|
parentLoom = null;
|
|
274
|
-
|
|
290
|
+
getLogger().info("Creating as independent loom");
|
|
275
291
|
}
|
|
276
292
|
}
|
|
277
293
|
} else if (input.options.childLoom === true) {
|
|
278
|
-
|
|
294
|
+
getLogger().debug("--child-loom flag provided but not running from inside an existing loom (ignored)");
|
|
279
295
|
}
|
|
280
296
|
if (parsed.type === "description") {
|
|
281
|
-
|
|
297
|
+
getLogger().info("Creating GitHub issue from description...");
|
|
282
298
|
const title = capitalizeFirstLetter(parsed.originalInput);
|
|
283
299
|
const body = input.options.body ? capitalizeFirstLetter(input.options.body) : "";
|
|
284
300
|
const result = await this.issueTracker.createIssue(
|
|
@@ -287,17 +303,20 @@ var StartCommand = class {
|
|
|
287
303
|
body
|
|
288
304
|
// Use capitalized body or empty
|
|
289
305
|
);
|
|
290
|
-
|
|
306
|
+
getLogger().success(`Created issue #${result.number}: ${result.url}`);
|
|
291
307
|
parsed.type = "issue";
|
|
292
308
|
parsed.number = result.number;
|
|
293
309
|
}
|
|
294
310
|
if (input.options.oneShot === "bypassPermissions") {
|
|
295
|
-
|
|
311
|
+
if (isJsonMode) {
|
|
312
|
+
throw new Error("JSON mode does not support bypassPermissions confirmation prompt");
|
|
313
|
+
}
|
|
314
|
+
const { promptConfirmation: promptConfirmation2 } = await import("./prompt-A7GGRHSY.js");
|
|
296
315
|
const confirmed = await promptConfirmation2(
|
|
297
|
-
"
|
|
316
|
+
"WARNING: bypassPermissions mode will allow Claude to execute all tool calls without confirmation. This can be dangerous. Do you want to proceed?"
|
|
298
317
|
);
|
|
299
318
|
if (!confirmed) {
|
|
300
|
-
|
|
319
|
+
getLogger().info("Operation cancelled by user");
|
|
301
320
|
process.exit(0);
|
|
302
321
|
}
|
|
303
322
|
}
|
|
@@ -308,13 +327,13 @@ var StartCommand = class {
|
|
|
308
327
|
const { extractRawSetArguments, getExecutablePath } = await import("./cli-overrides-XFZWY7CM.js");
|
|
309
328
|
const setArguments = extractRawSetArguments();
|
|
310
329
|
const executablePath = getExecutablePath();
|
|
311
|
-
|
|
330
|
+
getLogger().info(`Validated input: ${this.formatParsedInput(parsed)}`);
|
|
312
331
|
const identifier = parsed.type === "branch" ? parsed.branchName ?? "" : parsed.number ?? 0;
|
|
313
332
|
const enableClaude = input.options.claude ?? (workflowConfig == null ? void 0 : workflowConfig.startAiAgent) ?? true;
|
|
314
333
|
const enableCode = input.options.code ?? (workflowConfig == null ? void 0 : workflowConfig.startIde) ?? true;
|
|
315
334
|
const enableDevServer = input.options.devServer ?? (workflowConfig == null ? void 0 : workflowConfig.startDevServer) ?? true;
|
|
316
335
|
const enableTerminal = input.options.terminal ?? (workflowConfig == null ? void 0 : workflowConfig.startTerminal) ?? false;
|
|
317
|
-
|
|
336
|
+
getLogger().debug("Final workflow config values:", {
|
|
318
337
|
enableClaude,
|
|
319
338
|
enableCode,
|
|
320
339
|
enableDevServer,
|
|
@@ -335,19 +354,31 @@ var StartCommand = class {
|
|
|
335
354
|
...executablePath && { executablePath }
|
|
336
355
|
}
|
|
337
356
|
});
|
|
338
|
-
|
|
339
|
-
|
|
357
|
+
getLogger().success(`Created loom: ${loom.id} at ${loom.path}`);
|
|
358
|
+
getLogger().info(` Branch: ${loom.branch}`);
|
|
340
359
|
if ((_c = loom.capabilities) == null ? void 0 : _c.includes("web")) {
|
|
341
|
-
|
|
360
|
+
getLogger().info(` Port: ${loom.port}`);
|
|
342
361
|
}
|
|
343
362
|
if ((_d = loom.issueData) == null ? void 0 : _d.title) {
|
|
344
|
-
|
|
363
|
+
getLogger().info(` Title: ${loom.issueData.title}`);
|
|
364
|
+
}
|
|
365
|
+
if (isJsonMode) {
|
|
366
|
+
return {
|
|
367
|
+
id: loom.id,
|
|
368
|
+
path: loom.path,
|
|
369
|
+
branch: loom.branch,
|
|
370
|
+
type: parsed.type,
|
|
371
|
+
identifier: loom.identifier,
|
|
372
|
+
...loom.port !== void 0 && { port: loom.port },
|
|
373
|
+
...((_e = loom.issueData) == null ? void 0 : _e.title) && { title: loom.issueData.title },
|
|
374
|
+
...loom.capabilities && { capabilities: loom.capabilities }
|
|
375
|
+
};
|
|
345
376
|
}
|
|
346
377
|
} catch (error) {
|
|
347
378
|
if (error instanceof Error) {
|
|
348
|
-
|
|
379
|
+
getLogger().error(`${error.message}`);
|
|
349
380
|
} else {
|
|
350
|
-
|
|
381
|
+
getLogger().error("An unknown error occurred");
|
|
351
382
|
}
|
|
352
383
|
throw error;
|
|
353
384
|
}
|
|
@@ -440,7 +471,7 @@ var StartCommand = class {
|
|
|
440
471
|
}
|
|
441
472
|
const pr = await this.issueTracker.fetchPR(parsed.number, repo);
|
|
442
473
|
await this.issueTracker.validatePRState(pr);
|
|
443
|
-
|
|
474
|
+
getLogger().debug(`Validated PR #${parsed.number}`);
|
|
444
475
|
break;
|
|
445
476
|
}
|
|
446
477
|
case "issue": {
|
|
@@ -449,7 +480,7 @@ var StartCommand = class {
|
|
|
449
480
|
}
|
|
450
481
|
const issue = await this.issueTracker.fetchIssue(parsed.number, repo);
|
|
451
482
|
await this.issueTracker.validateIssueState(issue);
|
|
452
|
-
|
|
483
|
+
getLogger().debug(`Validated issue #${parsed.number}`);
|
|
453
484
|
break;
|
|
454
485
|
}
|
|
455
486
|
case "branch": {
|
|
@@ -461,11 +492,11 @@ var StartCommand = class {
|
|
|
461
492
|
"Invalid branch name. Use only letters, numbers, hyphens, underscores, and slashes"
|
|
462
493
|
);
|
|
463
494
|
}
|
|
464
|
-
|
|
495
|
+
getLogger().debug(`Validated branch name: ${parsed.branchName}`);
|
|
465
496
|
break;
|
|
466
497
|
}
|
|
467
498
|
case "description": {
|
|
468
|
-
|
|
499
|
+
getLogger().debug("Detected description input", {
|
|
469
500
|
length: parsed.originalInput.length
|
|
470
501
|
});
|
|
471
502
|
break;
|
|
@@ -520,7 +551,7 @@ var StartCommand = class {
|
|
|
520
551
|
if (!parentLoom) {
|
|
521
552
|
return null;
|
|
522
553
|
}
|
|
523
|
-
|
|
554
|
+
getLogger().debug(`Detected parent loom: ${parentLoom.type} ${parentLoom.identifier} at ${parentLoom.path}`);
|
|
524
555
|
const result = {
|
|
525
556
|
type: parentLoom.type,
|
|
526
557
|
identifier: parentLoom.identifier,
|
|
@@ -534,12 +565,12 @@ var StartCommand = class {
|
|
|
534
565
|
const databaseBranch = await loomManager.getDatabaseBranchForLoom(parentLoom.path);
|
|
535
566
|
if (databaseBranch) {
|
|
536
567
|
result.databaseBranch = databaseBranch;
|
|
537
|
-
|
|
568
|
+
getLogger().debug(`Detected parent database branch: ${databaseBranch}`);
|
|
538
569
|
}
|
|
539
570
|
}
|
|
540
571
|
return result;
|
|
541
572
|
} catch (error) {
|
|
542
|
-
|
|
573
|
+
getLogger().debug(`Failed to detect parent loom: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
543
574
|
return null;
|
|
544
575
|
}
|
|
545
576
|
}
|
|
@@ -556,20 +587,23 @@ var AddIssueCommand = class {
|
|
|
556
587
|
* 1. Validate description format
|
|
557
588
|
* 2. Skip enhancement if body provided, otherwise enhance description with Claude Code
|
|
558
589
|
* 3. Create GitHub issue
|
|
559
|
-
* 4. Wait for keypress and open browser for review
|
|
560
|
-
* 5. Return issue number
|
|
590
|
+
* 4. Wait for keypress and open browser for review (unless --json mode)
|
|
591
|
+
* 5. Return issue number or full result object (when --json)
|
|
561
592
|
*/
|
|
562
593
|
async execute(input) {
|
|
563
594
|
const description = capitalizeFirstLetter(input.description);
|
|
564
595
|
const body = input.options.body ? capitalizeFirstLetter(input.options.body) : void 0;
|
|
565
|
-
|
|
596
|
+
const isJsonMode = input.options.json === true;
|
|
597
|
+
if (!isJsonMode && (process.env.FORCE_FIRST_TIME_SETUP === "true" || await needsFirstRunSetup())) {
|
|
566
598
|
await launchFirstRunSetup();
|
|
567
599
|
}
|
|
568
600
|
const settings = await this.settingsManager.loadSettings();
|
|
569
601
|
let repo;
|
|
570
602
|
if (this.enhancementService.issueTracker.providerName === "github" && await hasMultipleRemotes()) {
|
|
571
603
|
repo = await getConfiguredRepoFromSettings(settings);
|
|
572
|
-
|
|
604
|
+
if (!isJsonMode) {
|
|
605
|
+
getLogger().info(`Using GitHub repository: ${repo}`);
|
|
606
|
+
}
|
|
573
607
|
}
|
|
574
608
|
if (!description || !this.enhancementService.validateDescription(description)) {
|
|
575
609
|
throw new Error("Description is required and must be more than 30 characters with at least 3 words");
|
|
@@ -580,6 +614,15 @@ var AddIssueCommand = class {
|
|
|
580
614
|
issueBody,
|
|
581
615
|
repo
|
|
582
616
|
);
|
|
617
|
+
if (isJsonMode) {
|
|
618
|
+
const resultData = {
|
|
619
|
+
url: result.url,
|
|
620
|
+
id: typeof result.number === "string" ? parseInt(result.number, 10) : result.number,
|
|
621
|
+
title: description,
|
|
622
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
623
|
+
};
|
|
624
|
+
return resultData;
|
|
625
|
+
}
|
|
583
626
|
await this.enhancementService.waitForReviewAndOpen(result.number);
|
|
584
627
|
return result.number;
|
|
585
628
|
}
|
|
@@ -599,25 +642,31 @@ var EnhanceCommand = class {
|
|
|
599
642
|
* 3. Load agent configurations
|
|
600
643
|
* 4. Invoke Claude CLI with enhancer agent
|
|
601
644
|
* 5. Parse response to determine outcome
|
|
602
|
-
* 6. Handle browser interaction based on outcome
|
|
645
|
+
* 6. Handle browser interaction based on outcome (unless --json mode)
|
|
646
|
+
* 7. Return result object when --json mode
|
|
603
647
|
*/
|
|
604
648
|
async execute(input) {
|
|
605
649
|
const { issueNumber, options } = input;
|
|
606
650
|
const { author } = options;
|
|
607
|
-
|
|
651
|
+
const isJsonMode = options.json === true;
|
|
652
|
+
if (!isJsonMode && (process.env.FORCE_FIRST_TIME_SETUP === "true" || await needsFirstRunSetup())) {
|
|
608
653
|
await launchFirstRunSetup();
|
|
609
654
|
}
|
|
610
655
|
const settings = await this.settingsManager.loadSettings();
|
|
611
656
|
let repo;
|
|
612
657
|
if (this.issueTracker.providerName === "github" && await hasMultipleRemotes()) {
|
|
613
658
|
repo = await getConfiguredRepoFromSettings(settings);
|
|
614
|
-
|
|
659
|
+
if (!isJsonMode) {
|
|
660
|
+
getLogger().info(`Using GitHub repository: ${repo}`);
|
|
661
|
+
}
|
|
615
662
|
}
|
|
616
663
|
this.validateIssueNumber(issueNumber);
|
|
617
|
-
|
|
664
|
+
if (!isJsonMode) {
|
|
665
|
+
getLogger().info(`Fetching issue #${issueNumber}...`);
|
|
666
|
+
}
|
|
618
667
|
const issue = await this.issueTracker.fetchIssue(issueNumber, repo);
|
|
619
|
-
|
|
620
|
-
|
|
668
|
+
getLogger().debug("Issue fetched successfully", { number: issue.number, title: issue.title });
|
|
669
|
+
getLogger().debug("Loading agent configurations...");
|
|
621
670
|
const loadedAgents = await this.agentManager.loadAgents(settings);
|
|
622
671
|
const agents = this.agentManager.formatForCli(loadedAgents);
|
|
623
672
|
let mcpConfig;
|
|
@@ -626,7 +675,7 @@ var EnhanceCommand = class {
|
|
|
626
675
|
try {
|
|
627
676
|
const provider = this.issueTracker.providerName;
|
|
628
677
|
mcpConfig = await generateIssueManagementMcpConfig("issue", repo, provider, settings);
|
|
629
|
-
|
|
678
|
+
getLogger().debug("Generated MCP configuration for issue management:", { mcpConfig });
|
|
630
679
|
allowedTools = [
|
|
631
680
|
"mcp__issue_management__get_issue",
|
|
632
681
|
"mcp__issue_management__get_comment",
|
|
@@ -634,11 +683,13 @@ var EnhanceCommand = class {
|
|
|
634
683
|
"mcp__issue_management__update_comment"
|
|
635
684
|
];
|
|
636
685
|
disallowedTools = ["Bash(gh api:*)"];
|
|
637
|
-
|
|
686
|
+
getLogger().debug("Configured tool filtering for issue workflow", { allowedTools, disallowedTools });
|
|
638
687
|
} catch (error) {
|
|
639
|
-
|
|
688
|
+
getLogger().warn(`Failed to generate MCP config: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
689
|
+
}
|
|
690
|
+
if (!isJsonMode) {
|
|
691
|
+
getLogger().info("Invoking enhancer agent. This may take a moment...");
|
|
640
692
|
}
|
|
641
|
-
logger.info("Invoking enhancer agent. This may take a moment...");
|
|
642
693
|
const prompt = this.constructPrompt(issueNumber, author);
|
|
643
694
|
const response = await launchClaude(prompt, {
|
|
644
695
|
headless: true,
|
|
@@ -649,16 +700,36 @@ var EnhanceCommand = class {
|
|
|
649
700
|
...disallowedTools && { disallowedTools }
|
|
650
701
|
});
|
|
651
702
|
const result = this.parseEnhancerResponse(response);
|
|
703
|
+
if (isJsonMode) {
|
|
704
|
+
const commentId = result.url ? this.extractCommentId(result.url) : 0;
|
|
705
|
+
const resultData = {
|
|
706
|
+
url: result.url ?? issue.url,
|
|
707
|
+
id: commentId,
|
|
708
|
+
title: issue.title,
|
|
709
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
710
|
+
enhanced: result.enhanced
|
|
711
|
+
};
|
|
712
|
+
return resultData;
|
|
713
|
+
}
|
|
652
714
|
if (!result.enhanced) {
|
|
653
|
-
|
|
715
|
+
getLogger().success("Issue already has thorough description. No enhancement needed.");
|
|
654
716
|
return;
|
|
655
717
|
}
|
|
656
|
-
|
|
657
|
-
|
|
718
|
+
getLogger().success(`Issue #${issueNumber} enhanced successfully!`);
|
|
719
|
+
getLogger().info(`Enhanced specification available at: ${result.url}`);
|
|
658
720
|
if (!options.noBrowser && result.url) {
|
|
659
721
|
await this.promptAndOpenBrowser(result.url);
|
|
660
722
|
}
|
|
661
723
|
}
|
|
724
|
+
/**
|
|
725
|
+
* Extract comment ID from GitHub comment URL
|
|
726
|
+
* @param url - GitHub comment URL (e.g., https://github.com/owner/repo/issues/123#issuecomment-456789)
|
|
727
|
+
* @returns Comment ID as number, or 0 if not found
|
|
728
|
+
*/
|
|
729
|
+
extractCommentId(url) {
|
|
730
|
+
const match = url.match(/issuecomment-(\d+)/);
|
|
731
|
+
return (match == null ? void 0 : match[1]) ? parseInt(match[1], 10) : 0;
|
|
732
|
+
}
|
|
662
733
|
/**
|
|
663
734
|
* Validate that issue number is a valid positive integer
|
|
664
735
|
*/
|
|
@@ -702,7 +773,7 @@ IMPORTANT: When you create your analysis comment, tag @${author} in the "Questio
|
|
|
702
773
|
throw new Error("No response from enhancer agent");
|
|
703
774
|
}
|
|
704
775
|
const trimmed = response.trim();
|
|
705
|
-
|
|
776
|
+
getLogger().debug(`RESPONSE FROM ENHANCER AGENT: '${trimmed}'`);
|
|
706
777
|
if (trimmed.toLowerCase().startsWith("permission denied:")) {
|
|
707
778
|
const errorMessage = trimmed.substring("permission denied:".length).trim();
|
|
708
779
|
throw new Error(`Permission denied: ${errorMessage}`);
|
|
@@ -727,18 +798,20 @@ IMPORTANT: When you create your analysis comment, tag @${author} in the "Questio
|
|
|
727
798
|
"Press q to quit or any other key to view the enhanced issue in a web browser..."
|
|
728
799
|
);
|
|
729
800
|
if (key.toLowerCase() === "q") {
|
|
730
|
-
|
|
801
|
+
getLogger().info("Skipping browser opening");
|
|
731
802
|
return;
|
|
732
803
|
}
|
|
733
804
|
await openBrowser(commentUrl);
|
|
734
805
|
} catch (error) {
|
|
735
|
-
|
|
806
|
+
getLogger().warn(`Failed to open browser: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
736
807
|
}
|
|
737
808
|
}
|
|
738
809
|
};
|
|
739
810
|
|
|
740
811
|
// src/lib/ValidationRunner.ts
|
|
741
812
|
var ValidationRunner = class {
|
|
813
|
+
constructor() {
|
|
814
|
+
}
|
|
742
815
|
/**
|
|
743
816
|
* Run all validations in sequence: typecheck → lint → test
|
|
744
817
|
* Fails fast on first error
|
|
@@ -781,14 +854,22 @@ var ValidationRunner = class {
|
|
|
781
854
|
}
|
|
782
855
|
/**
|
|
783
856
|
* Run typecheck validation
|
|
857
|
+
* Prefers 'compile' script over 'typecheck' if both exist
|
|
784
858
|
*/
|
|
785
859
|
async runTypecheck(worktreePath, dryRun) {
|
|
786
860
|
const stepStartTime = Date.now();
|
|
861
|
+
let scriptToRun = null;
|
|
787
862
|
try {
|
|
788
863
|
const pkgJson = await readPackageJson(worktreePath);
|
|
864
|
+
const hasCompileScript = hasScript(pkgJson, "compile");
|
|
789
865
|
const hasTypecheckScript = hasScript(pkgJson, "typecheck");
|
|
790
|
-
if (
|
|
791
|
-
|
|
866
|
+
if (hasCompileScript) {
|
|
867
|
+
scriptToRun = "compile";
|
|
868
|
+
} else if (hasTypecheckScript) {
|
|
869
|
+
scriptToRun = "typecheck";
|
|
870
|
+
}
|
|
871
|
+
if (!scriptToRun) {
|
|
872
|
+
getLogger().debug("Skipping typecheck - no compile or typecheck script found");
|
|
792
873
|
return {
|
|
793
874
|
step: "typecheck",
|
|
794
875
|
passed: true,
|
|
@@ -798,7 +879,7 @@ var ValidationRunner = class {
|
|
|
798
879
|
}
|
|
799
880
|
} catch (error) {
|
|
800
881
|
if (error instanceof Error && error.message.includes("package.json not found")) {
|
|
801
|
-
|
|
882
|
+
getLogger().debug("Skipping typecheck - no package.json found (non-Node.js project)");
|
|
802
883
|
return {
|
|
803
884
|
step: "typecheck",
|
|
804
885
|
passed: true,
|
|
@@ -810,42 +891,43 @@ var ValidationRunner = class {
|
|
|
810
891
|
}
|
|
811
892
|
const packageManager = await detectPackageManager(worktreePath);
|
|
812
893
|
if (dryRun) {
|
|
813
|
-
const command = packageManager === "npm" ?
|
|
814
|
-
|
|
894
|
+
const command = packageManager === "npm" ? `npm run ${scriptToRun}` : `${packageManager} ${scriptToRun}`;
|
|
895
|
+
getLogger().info(`[DRY RUN] Would run: ${command}`);
|
|
815
896
|
return {
|
|
816
|
-
step:
|
|
897
|
+
step: scriptToRun,
|
|
817
898
|
passed: true,
|
|
818
899
|
skipped: false,
|
|
819
900
|
duration: Date.now() - stepStartTime
|
|
820
901
|
};
|
|
821
902
|
}
|
|
822
|
-
|
|
903
|
+
getLogger().info(`Running ${scriptToRun}...`);
|
|
823
904
|
try {
|
|
824
|
-
await runScript(
|
|
825
|
-
|
|
905
|
+
await runScript(scriptToRun, worktreePath, [], { quiet: true });
|
|
906
|
+
getLogger().success(`${scriptToRun.charAt(0).toUpperCase() + scriptToRun.slice(1)} passed`);
|
|
826
907
|
return {
|
|
827
|
-
step:
|
|
908
|
+
step: scriptToRun,
|
|
828
909
|
passed: true,
|
|
829
910
|
skipped: false,
|
|
830
911
|
duration: Date.now() - stepStartTime
|
|
831
912
|
};
|
|
832
913
|
} catch {
|
|
833
914
|
const fixed = await this.attemptClaudeFix(
|
|
834
|
-
|
|
915
|
+
scriptToRun,
|
|
835
916
|
worktreePath,
|
|
836
917
|
packageManager
|
|
837
918
|
);
|
|
838
919
|
if (fixed) {
|
|
839
920
|
return {
|
|
840
|
-
step:
|
|
921
|
+
step: scriptToRun,
|
|
841
922
|
passed: true,
|
|
842
923
|
skipped: false,
|
|
843
924
|
duration: Date.now() - stepStartTime
|
|
844
925
|
};
|
|
845
926
|
}
|
|
846
|
-
const runCommand = packageManager === "npm" ?
|
|
927
|
+
const runCommand = packageManager === "npm" ? `npm run ${scriptToRun}` : `${packageManager} ${scriptToRun}`;
|
|
928
|
+
const stepLabel = scriptToRun.charAt(0).toUpperCase() + scriptToRun.slice(1);
|
|
847
929
|
throw new Error(
|
|
848
|
-
`Error:
|
|
930
|
+
`Error: ${stepLabel} failed.
|
|
849
931
|
Fix type errors before merging.
|
|
850
932
|
|
|
851
933
|
Run '${runCommand}' to see detailed errors.`
|
|
@@ -861,7 +943,7 @@ Run '${runCommand}' to see detailed errors.`
|
|
|
861
943
|
const pkgJson = await readPackageJson(worktreePath);
|
|
862
944
|
const hasLintScript = hasScript(pkgJson, "lint");
|
|
863
945
|
if (!hasLintScript) {
|
|
864
|
-
|
|
946
|
+
getLogger().debug("Skipping lint - no lint script found");
|
|
865
947
|
return {
|
|
866
948
|
step: "lint",
|
|
867
949
|
passed: true,
|
|
@@ -871,7 +953,7 @@ Run '${runCommand}' to see detailed errors.`
|
|
|
871
953
|
}
|
|
872
954
|
} catch (error) {
|
|
873
955
|
if (error instanceof Error && error.message.includes("package.json not found")) {
|
|
874
|
-
|
|
956
|
+
getLogger().debug("Skipping lint - no package.json found (non-Node.js project)");
|
|
875
957
|
return {
|
|
876
958
|
step: "lint",
|
|
877
959
|
passed: true,
|
|
@@ -884,7 +966,7 @@ Run '${runCommand}' to see detailed errors.`
|
|
|
884
966
|
const packageManager = await detectPackageManager(worktreePath);
|
|
885
967
|
if (dryRun) {
|
|
886
968
|
const command = packageManager === "npm" ? "npm run lint" : `${packageManager} lint`;
|
|
887
|
-
|
|
969
|
+
getLogger().info(`[DRY RUN] Would run: ${command}`);
|
|
888
970
|
return {
|
|
889
971
|
step: "lint",
|
|
890
972
|
passed: true,
|
|
@@ -892,10 +974,10 @@ Run '${runCommand}' to see detailed errors.`
|
|
|
892
974
|
duration: Date.now() - stepStartTime
|
|
893
975
|
};
|
|
894
976
|
}
|
|
895
|
-
|
|
977
|
+
getLogger().info("Running lint...");
|
|
896
978
|
try {
|
|
897
979
|
await runScript("lint", worktreePath, [], { quiet: true });
|
|
898
|
-
|
|
980
|
+
getLogger().success("Linting passed");
|
|
899
981
|
return {
|
|
900
982
|
step: "lint",
|
|
901
983
|
passed: true,
|
|
@@ -934,7 +1016,7 @@ Run '${runCommand}' to see detailed errors.`
|
|
|
934
1016
|
const pkgJson = await readPackageJson(worktreePath);
|
|
935
1017
|
const hasTestScript = hasScript(pkgJson, "test");
|
|
936
1018
|
if (!hasTestScript) {
|
|
937
|
-
|
|
1019
|
+
getLogger().debug("Skipping tests - no test script found");
|
|
938
1020
|
return {
|
|
939
1021
|
step: "test",
|
|
940
1022
|
passed: true,
|
|
@@ -944,7 +1026,7 @@ Run '${runCommand}' to see detailed errors.`
|
|
|
944
1026
|
}
|
|
945
1027
|
} catch (error) {
|
|
946
1028
|
if (error instanceof Error && error.message.includes("package.json not found")) {
|
|
947
|
-
|
|
1029
|
+
getLogger().debug("Skipping tests - no package.json found (non-Node.js project)");
|
|
948
1030
|
return {
|
|
949
1031
|
step: "test",
|
|
950
1032
|
passed: true,
|
|
@@ -957,7 +1039,7 @@ Run '${runCommand}' to see detailed errors.`
|
|
|
957
1039
|
const packageManager = await detectPackageManager(worktreePath);
|
|
958
1040
|
if (dryRun) {
|
|
959
1041
|
const command = packageManager === "npm" ? "npm run test" : `${packageManager} test`;
|
|
960
|
-
|
|
1042
|
+
getLogger().info(`[DRY RUN] Would run: ${command}`);
|
|
961
1043
|
return {
|
|
962
1044
|
step: "test",
|
|
963
1045
|
passed: true,
|
|
@@ -965,10 +1047,10 @@ Run '${runCommand}' to see detailed errors.`
|
|
|
965
1047
|
duration: Date.now() - stepStartTime
|
|
966
1048
|
};
|
|
967
1049
|
}
|
|
968
|
-
|
|
1050
|
+
getLogger().info("Running tests...");
|
|
969
1051
|
try {
|
|
970
1052
|
await runScript("test", worktreePath, [], { quiet: true });
|
|
971
|
-
|
|
1053
|
+
getLogger().success("Tests passed");
|
|
972
1054
|
return {
|
|
973
1055
|
step: "test",
|
|
974
1056
|
passed: true,
|
|
@@ -1002,7 +1084,7 @@ Run '${runCommand}' to see detailed errors.`
|
|
|
1002
1084
|
* Attempt to fix validation errors using Claude
|
|
1003
1085
|
* Pattern based on MergeManager.attemptClaudeConflictResolution
|
|
1004
1086
|
*
|
|
1005
|
-
* @param validationType - Type of validation that failed ('typecheck' | 'lint' | 'test')
|
|
1087
|
+
* @param validationType - Type of validation that failed ('compile' | 'typecheck' | 'lint' | 'test')
|
|
1006
1088
|
* @param worktreePath - Path to the worktree
|
|
1007
1089
|
* @param packageManager - Detected package manager
|
|
1008
1090
|
* @returns true if Claude fixed the issue, false otherwise
|
|
@@ -1010,13 +1092,13 @@ Run '${runCommand}' to see detailed errors.`
|
|
|
1010
1092
|
async attemptClaudeFix(validationType, worktreePath, packageManager) {
|
|
1011
1093
|
const isClaudeAvailable = await detectClaudeCli();
|
|
1012
1094
|
if (!isClaudeAvailable) {
|
|
1013
|
-
|
|
1095
|
+
getLogger().debug("Claude CLI not available, skipping auto-fix");
|
|
1014
1096
|
return false;
|
|
1015
1097
|
}
|
|
1016
1098
|
const validationCommand = this.getValidationCommand(validationType, packageManager);
|
|
1017
1099
|
const prompt = this.getClaudePrompt(validationType, validationCommand);
|
|
1018
1100
|
const validationTypeCapitalized = validationType.charAt(0).toUpperCase() + validationType.slice(1);
|
|
1019
|
-
|
|
1101
|
+
getLogger().info(`Launching Claude to help fix ${validationTypeCapitalized} errors...`);
|
|
1020
1102
|
try {
|
|
1021
1103
|
await launchClaude(prompt, {
|
|
1022
1104
|
addDir: worktreePath,
|
|
@@ -1027,17 +1109,17 @@ Run '${runCommand}' to see detailed errors.`
|
|
|
1027
1109
|
model: "sonnet"
|
|
1028
1110
|
// Use Sonnet model
|
|
1029
1111
|
});
|
|
1030
|
-
|
|
1112
|
+
getLogger().info(`Re-running ${validationTypeCapitalized} after Claude's fixes...`);
|
|
1031
1113
|
try {
|
|
1032
1114
|
await runScript(validationType, worktreePath, [], { quiet: true });
|
|
1033
|
-
|
|
1115
|
+
getLogger().success(`${validationTypeCapitalized} passed after Claude auto-fix`);
|
|
1034
1116
|
return true;
|
|
1035
1117
|
} catch {
|
|
1036
|
-
|
|
1118
|
+
getLogger().warn(`${validationTypeCapitalized} still failing after Claude's help`);
|
|
1037
1119
|
return false;
|
|
1038
1120
|
}
|
|
1039
1121
|
} catch (error) {
|
|
1040
|
-
|
|
1122
|
+
getLogger().warn("Claude auto-fix failed", {
|
|
1041
1123
|
error: error instanceof Error ? error.message : String(error)
|
|
1042
1124
|
});
|
|
1043
1125
|
return false;
|
|
@@ -1058,8 +1140,9 @@ Run '${runCommand}' to see detailed errors.`
|
|
|
1058
1140
|
*/
|
|
1059
1141
|
getClaudePrompt(validationType, validationCommand) {
|
|
1060
1142
|
switch (validationType) {
|
|
1143
|
+
case "compile":
|
|
1061
1144
|
case "typecheck":
|
|
1062
|
-
return `There are TypeScript errors in this codebase. Please analyze the
|
|
1145
|
+
return `There are TypeScript errors in this codebase. Please analyze the ${validationType} output, identify all type errors, and fix them. Run '${validationCommand}' to see the errors, then make the necessary code changes to resolve all type issues. When you are done, tell the user to quit using /exit to continue the validation process.`;
|
|
1063
1146
|
case "lint":
|
|
1064
1147
|
return `There are ESLint errors in this codebase. Please analyze the linting output, identify all linting issues, and fix them. Run '${validationCommand}' to see the errors, then make the necessary code changes to resolve all linting issues. Focus on code quality, consistency, and following the project's linting rules. When you are done, tell the user to quit using /exit to continue the validation process.`;
|
|
1065
1148
|
case "test":
|
|
@@ -1068,6 +1151,54 @@ Run '${runCommand}' to see detailed errors.`
|
|
|
1068
1151
|
}
|
|
1069
1152
|
};
|
|
1070
1153
|
|
|
1154
|
+
// src/utils/vscode.ts
|
|
1155
|
+
import { execa } from "execa";
|
|
1156
|
+
function isRunningInVSCode() {
|
|
1157
|
+
return process.env.TERM_PROGRAM === "vscode";
|
|
1158
|
+
}
|
|
1159
|
+
function isRunningInCursor() {
|
|
1160
|
+
return !!process.env.CURSOR_TRACE_ID;
|
|
1161
|
+
}
|
|
1162
|
+
function isRunningInAntigravity() {
|
|
1163
|
+
return !!process.env.ANTIGRAVITY_CLI_ALIAS;
|
|
1164
|
+
}
|
|
1165
|
+
async function isVSCodeAvailable() {
|
|
1166
|
+
try {
|
|
1167
|
+
await execa("command", ["-v", "code"], {
|
|
1168
|
+
shell: true,
|
|
1169
|
+
timeout: 5e3
|
|
1170
|
+
});
|
|
1171
|
+
return true;
|
|
1172
|
+
} catch (error) {
|
|
1173
|
+
logger.debug("VSCode CLI not available", { error });
|
|
1174
|
+
return false;
|
|
1175
|
+
}
|
|
1176
|
+
}
|
|
1177
|
+
async function isCursorAvailable() {
|
|
1178
|
+
try {
|
|
1179
|
+
await execa("command", ["-v", "cursor"], {
|
|
1180
|
+
shell: true,
|
|
1181
|
+
timeout: 5e3
|
|
1182
|
+
});
|
|
1183
|
+
return true;
|
|
1184
|
+
} catch (error) {
|
|
1185
|
+
logger.debug("Cursor CLI not available", { error });
|
|
1186
|
+
return false;
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
async function isAntigravityAvailable() {
|
|
1190
|
+
try {
|
|
1191
|
+
await execa("command", ["-v", "agy"], {
|
|
1192
|
+
shell: true,
|
|
1193
|
+
timeout: 5e3
|
|
1194
|
+
});
|
|
1195
|
+
return true;
|
|
1196
|
+
} catch (error) {
|
|
1197
|
+
logger.debug("Antigravity CLI not available", { error });
|
|
1198
|
+
return false;
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1071
1202
|
// src/types/index.ts
|
|
1072
1203
|
var UserAbortedCommitError = class extends Error {
|
|
1073
1204
|
constructor(message = "User aborted the commit") {
|
|
@@ -1077,7 +1208,12 @@ var UserAbortedCommitError = class extends Error {
|
|
|
1077
1208
|
};
|
|
1078
1209
|
|
|
1079
1210
|
// src/lib/CommitManager.ts
|
|
1211
|
+
import { writeFile, readFile as readFile2, unlink } from "fs/promises";
|
|
1212
|
+
import { join } from "path";
|
|
1213
|
+
import { execa as execa2 } from "execa";
|
|
1080
1214
|
var CommitManager = class {
|
|
1215
|
+
constructor() {
|
|
1216
|
+
}
|
|
1081
1217
|
/**
|
|
1082
1218
|
* Detect uncommitted changes in a worktree
|
|
1083
1219
|
* Parses git status --porcelain output into structured GitStatus
|
|
@@ -1106,11 +1242,11 @@ var CommitManager = class {
|
|
|
1106
1242
|
*/
|
|
1107
1243
|
async commitChanges(worktreePath, options) {
|
|
1108
1244
|
if (options.dryRun) {
|
|
1109
|
-
|
|
1110
|
-
|
|
1245
|
+
getLogger().info("[DRY RUN] Would run: git add -A");
|
|
1246
|
+
getLogger().info("[DRY RUN] Would generate commit message with Claude (if available)");
|
|
1111
1247
|
const fallbackMessage = this.generateFallbackMessage(options);
|
|
1112
1248
|
const verifyFlag = options.skipVerify ? " --no-verify" : "";
|
|
1113
|
-
|
|
1249
|
+
getLogger().info(`[DRY RUN] Would commit with message${verifyFlag}: ${fallbackMessage}`);
|
|
1114
1250
|
return;
|
|
1115
1251
|
}
|
|
1116
1252
|
await executeGitCommand(["add", "-A"], { cwd: worktreePath });
|
|
@@ -1119,12 +1255,12 @@ var CommitManager = class {
|
|
|
1119
1255
|
try {
|
|
1120
1256
|
message = await this.generateClaudeCommitMessage(worktreePath, options.issueNumber);
|
|
1121
1257
|
} catch (error) {
|
|
1122
|
-
|
|
1258
|
+
getLogger().debug("Claude commit message generation failed, using fallback", { error });
|
|
1123
1259
|
}
|
|
1124
1260
|
}
|
|
1125
1261
|
message ??= this.generateFallbackMessage(options);
|
|
1126
1262
|
if (options.skipVerify) {
|
|
1127
|
-
|
|
1263
|
+
getLogger().warn("Skipping pre-commit hooks (--no-verify configured in settings)");
|
|
1128
1264
|
}
|
|
1129
1265
|
try {
|
|
1130
1266
|
if (options.noReview || options.message) {
|
|
@@ -1145,17 +1281,25 @@ var CommitManager = class {
|
|
|
1145
1281
|
}
|
|
1146
1282
|
await executeGitCommand(commitArgs, { cwd: worktreePath });
|
|
1147
1283
|
} else {
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1284
|
+
getLogger().info("Opening editor for commit message review...");
|
|
1285
|
+
if (isRunningInAntigravity() && await isAntigravityAvailable()) {
|
|
1286
|
+
await this.commitWithExternalEditor(worktreePath, message, options, "agy", "Antigravity");
|
|
1287
|
+
} else if (isRunningInCursor() && await isCursorAvailable()) {
|
|
1288
|
+
await this.commitWithExternalEditor(worktreePath, message, options, "cursor", "Cursor");
|
|
1289
|
+
} else if (isRunningInVSCode() && await isVSCodeAvailable()) {
|
|
1290
|
+
await this.commitWithExternalEditor(worktreePath, message, options, "code", "VSCode");
|
|
1291
|
+
} else {
|
|
1292
|
+
const commitArgs = ["commit", "-e", "-m", message];
|
|
1293
|
+
if (options.skipVerify) {
|
|
1294
|
+
commitArgs.push("--no-verify");
|
|
1295
|
+
}
|
|
1296
|
+
await executeGitCommand(commitArgs, {
|
|
1297
|
+
cwd: worktreePath,
|
|
1298
|
+
stdio: "inherit",
|
|
1299
|
+
timeout: 3e5
|
|
1300
|
+
// 5 minutes for interactive editing
|
|
1301
|
+
});
|
|
1152
1302
|
}
|
|
1153
|
-
await executeGitCommand(commitArgs, {
|
|
1154
|
-
cwd: worktreePath,
|
|
1155
|
-
stdio: "inherit",
|
|
1156
|
-
timeout: 3e5
|
|
1157
|
-
// 5 minutes for interactive editing
|
|
1158
|
-
});
|
|
1159
1303
|
}
|
|
1160
1304
|
}
|
|
1161
1305
|
} catch (error) {
|
|
@@ -1163,12 +1307,51 @@ var CommitManager = class {
|
|
|
1163
1307
|
throw error;
|
|
1164
1308
|
}
|
|
1165
1309
|
if (error instanceof Error && error.message.includes("nothing to commit")) {
|
|
1166
|
-
|
|
1310
|
+
getLogger().info("No changes to commit");
|
|
1167
1311
|
return;
|
|
1168
1312
|
}
|
|
1169
1313
|
throw error;
|
|
1170
1314
|
}
|
|
1171
1315
|
}
|
|
1316
|
+
/**
|
|
1317
|
+
* Commit with external editor CLI (VSCode, Cursor, Antigravity, etc.)
|
|
1318
|
+
* Handles file creation, editing, and commit to ensure the file opens
|
|
1319
|
+
* in the current editor window (preserves IPC context)
|
|
1320
|
+
*/
|
|
1321
|
+
async commitWithExternalEditor(worktreePath, message, options, cliCommand, editorName) {
|
|
1322
|
+
const commitMsgPath = join(worktreePath, ".COMMIT_EDITMSG");
|
|
1323
|
+
const initialContent = `${message}
|
|
1324
|
+
|
|
1325
|
+
# Please enter the commit message for your changes. Lines starting
|
|
1326
|
+
# with '#' will be ignored, and an empty message aborts the commit.
|
|
1327
|
+
#
|
|
1328
|
+
# Save and close the file to complete the commit.
|
|
1329
|
+
`;
|
|
1330
|
+
await writeFile(commitMsgPath, initialContent, "utf-8");
|
|
1331
|
+
try {
|
|
1332
|
+
getLogger().debug(`Opening commit message in ${editorName}: ${commitMsgPath}`);
|
|
1333
|
+
await execa2(cliCommand, ["--wait", commitMsgPath], {
|
|
1334
|
+
cwd: worktreePath,
|
|
1335
|
+
stdio: "inherit"
|
|
1336
|
+
});
|
|
1337
|
+
const editedContent = await readFile2(commitMsgPath, "utf-8");
|
|
1338
|
+
const finalMessage = editedContent.split("\n").filter((line) => !line.startsWith("#")).join("\n").trim();
|
|
1339
|
+
if (!finalMessage) {
|
|
1340
|
+
throw new UserAbortedCommitError();
|
|
1341
|
+
}
|
|
1342
|
+
const commitArgs = ["commit", "-F", commitMsgPath];
|
|
1343
|
+
if (options.skipVerify) {
|
|
1344
|
+
commitArgs.push("--no-verify");
|
|
1345
|
+
}
|
|
1346
|
+
await writeFile(commitMsgPath, finalMessage, "utf-8");
|
|
1347
|
+
await executeGitCommand(commitArgs, { cwd: worktreePath });
|
|
1348
|
+
} finally {
|
|
1349
|
+
try {
|
|
1350
|
+
await unlink(commitMsgPath);
|
|
1351
|
+
} catch {
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1172
1355
|
/**
|
|
1173
1356
|
* Generate simple fallback commit message when Claude unavailable
|
|
1174
1357
|
* Used as fallback for Claude-powered commit messages
|
|
@@ -1222,61 +1405,62 @@ Fixes #${options.issueNumber}`;
|
|
|
1222
1405
|
*/
|
|
1223
1406
|
async generateClaudeCommitMessage(worktreePath, issueNumber) {
|
|
1224
1407
|
const startTime = Date.now();
|
|
1225
|
-
|
|
1408
|
+
getLogger().info("Starting Claude commit message generation...", {
|
|
1226
1409
|
worktreePath: worktreePath.split("/").pop(),
|
|
1227
1410
|
// Just show the folder name for privacy
|
|
1228
1411
|
issueNumber
|
|
1229
1412
|
});
|
|
1230
|
-
|
|
1413
|
+
getLogger().debug("Checking Claude CLI availability...");
|
|
1231
1414
|
const isClaudeAvailable = await detectClaudeCli();
|
|
1232
1415
|
if (!isClaudeAvailable) {
|
|
1233
|
-
|
|
1416
|
+
getLogger().info("Claude CLI not available, skipping Claude commit message generation");
|
|
1234
1417
|
return null;
|
|
1235
1418
|
}
|
|
1236
|
-
|
|
1237
|
-
|
|
1419
|
+
getLogger().debug("Claude CLI is available");
|
|
1420
|
+
getLogger().debug("Building commit message prompt...");
|
|
1238
1421
|
const prompt = this.buildCommitMessagePrompt(issueNumber);
|
|
1239
|
-
|
|
1240
|
-
|
|
1422
|
+
getLogger().debug("Prompt built", { promptLength: prompt.length });
|
|
1423
|
+
getLogger().debug("Claude prompt content:", {
|
|
1241
1424
|
prompt,
|
|
1242
1425
|
truncatedPreview: prompt.substring(0, 500) + (prompt.length > 500 ? "...[truncated]" : "")
|
|
1243
1426
|
});
|
|
1244
1427
|
try {
|
|
1245
|
-
|
|
1428
|
+
getLogger().info("Calling Claude CLI for commit message generation...");
|
|
1246
1429
|
const claudeStartTime = Date.now();
|
|
1247
1430
|
const claudeOptions = {
|
|
1248
1431
|
headless: true,
|
|
1249
1432
|
addDir: worktreePath,
|
|
1250
1433
|
model: "claude-haiku-4-5-20251001",
|
|
1251
1434
|
// Fast, cost-effective model
|
|
1252
|
-
timeout: 12e4
|
|
1435
|
+
timeout: 12e4,
|
|
1253
1436
|
// 120 second timeout
|
|
1437
|
+
appendSystemPrompt: "Output only the requested content. Never include preamble, analysis, or meta-commentary. Your response is used verbatim."
|
|
1254
1438
|
};
|
|
1255
|
-
|
|
1439
|
+
getLogger().debug("Claude CLI call parameters:", {
|
|
1256
1440
|
options: claudeOptions,
|
|
1257
1441
|
worktreePathForAnalysis: worktreePath,
|
|
1258
1442
|
addDirContents: "Will include entire worktree directory for analysis"
|
|
1259
1443
|
});
|
|
1260
1444
|
const result = await launchClaude(prompt, claudeOptions);
|
|
1261
1445
|
const claudeDuration = Date.now() - claudeStartTime;
|
|
1262
|
-
|
|
1446
|
+
getLogger().debug("Claude API call completed", { duration: `${claudeDuration}ms` });
|
|
1263
1447
|
if (typeof result !== "string") {
|
|
1264
|
-
|
|
1448
|
+
getLogger().warn("Claude returned non-string result", { resultType: typeof result });
|
|
1265
1449
|
return null;
|
|
1266
1450
|
}
|
|
1267
|
-
|
|
1451
|
+
getLogger().debug("Raw Claude output received", {
|
|
1268
1452
|
outputLength: result.length,
|
|
1269
1453
|
preview: result.substring(0, 200) + (result.length > 200 ? "..." : "")
|
|
1270
1454
|
});
|
|
1271
|
-
|
|
1455
|
+
getLogger().debug("Sanitizing Claude output...");
|
|
1272
1456
|
const sanitized = this.sanitizeClaudeOutput(result);
|
|
1273
|
-
|
|
1457
|
+
getLogger().debug("Output sanitized", {
|
|
1274
1458
|
originalLength: result.length,
|
|
1275
1459
|
sanitizedLength: sanitized.length,
|
|
1276
1460
|
sanitized: sanitized.substring(0, 200) + (sanitized.length > 200 ? "..." : "")
|
|
1277
1461
|
});
|
|
1278
1462
|
if (!sanitized) {
|
|
1279
|
-
|
|
1463
|
+
getLogger().warn("Claude returned empty message after sanitization");
|
|
1280
1464
|
return null;
|
|
1281
1465
|
}
|
|
1282
1466
|
let finalMessage = sanitized;
|
|
@@ -1285,13 +1469,13 @@ Fixes #${options.issueNumber}`;
|
|
|
1285
1469
|
finalMessage = `${finalMessage}
|
|
1286
1470
|
|
|
1287
1471
|
Fixes #${issueNumber}`;
|
|
1288
|
-
|
|
1472
|
+
getLogger().debug(`Added "Fixes #${issueNumber}" trailer to commit message`);
|
|
1289
1473
|
} else {
|
|
1290
|
-
|
|
1474
|
+
getLogger().debug(`"Fixes #${issueNumber}" already present in commit message`);
|
|
1291
1475
|
}
|
|
1292
1476
|
}
|
|
1293
1477
|
const totalDuration = Date.now() - startTime;
|
|
1294
|
-
|
|
1478
|
+
getLogger().info("Claude commit message generated successfully", {
|
|
1295
1479
|
message: finalMessage,
|
|
1296
1480
|
totalDuration: `${totalDuration}ms`,
|
|
1297
1481
|
claudeApiDuration: `${claudeDuration}ms`
|
|
@@ -1301,12 +1485,12 @@ Fixes #${issueNumber}`;
|
|
|
1301
1485
|
const totalDuration = Date.now() - startTime;
|
|
1302
1486
|
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
1303
1487
|
if (errorMessage.includes("timed out") || errorMessage.includes("timeout")) {
|
|
1304
|
-
|
|
1488
|
+
getLogger().warn("Claude commit message generation timed out after 45 seconds", {
|
|
1305
1489
|
totalDuration: `${totalDuration}ms`,
|
|
1306
1490
|
worktreePath: worktreePath.split("/").pop()
|
|
1307
1491
|
});
|
|
1308
1492
|
} else {
|
|
1309
|
-
|
|
1493
|
+
getLogger().warn("Failed to generate commit message with Claude", {
|
|
1310
1494
|
error: errorMessage,
|
|
1311
1495
|
totalDuration: `${totalDuration}ms`,
|
|
1312
1496
|
worktreePath: worktreePath.split("/").pop()
|
|
@@ -1418,7 +1602,7 @@ var BuildRunner = class {
|
|
|
1418
1602
|
const pkgJson = await readPackageJson(buildPath);
|
|
1419
1603
|
const hasBuildScript = hasScript(pkgJson, "build");
|
|
1420
1604
|
if (!hasBuildScript) {
|
|
1421
|
-
|
|
1605
|
+
getLogger().debug("Skipping build - no build script found");
|
|
1422
1606
|
return {
|
|
1423
1607
|
success: true,
|
|
1424
1608
|
skipped: true,
|
|
@@ -1428,7 +1612,7 @@ var BuildRunner = class {
|
|
|
1428
1612
|
}
|
|
1429
1613
|
} catch (error) {
|
|
1430
1614
|
if (error instanceof Error && error.message.includes("package.json not found")) {
|
|
1431
|
-
|
|
1615
|
+
getLogger().debug("Skipping build - no package.json found (non-Node.js project)");
|
|
1432
1616
|
return {
|
|
1433
1617
|
success: true,
|
|
1434
1618
|
skipped: true,
|
|
@@ -1441,7 +1625,7 @@ var BuildRunner = class {
|
|
|
1441
1625
|
const capabilities = await this.capabilityDetector.detectCapabilities(buildPath);
|
|
1442
1626
|
const isCLIProject = capabilities.capabilities.includes("cli");
|
|
1443
1627
|
if (!isCLIProject) {
|
|
1444
|
-
|
|
1628
|
+
getLogger().debug("Skipping build - not a CLI project (no bin field)");
|
|
1445
1629
|
return {
|
|
1446
1630
|
success: true,
|
|
1447
1631
|
skipped: true,
|
|
@@ -1452,17 +1636,17 @@ var BuildRunner = class {
|
|
|
1452
1636
|
const packageManager = await detectPackageManager(buildPath);
|
|
1453
1637
|
if (options.dryRun) {
|
|
1454
1638
|
const command = packageManager === "npm" ? "npm run build" : `${packageManager} build`;
|
|
1455
|
-
|
|
1639
|
+
getLogger().info(`[DRY RUN] Would run: ${command}`);
|
|
1456
1640
|
return {
|
|
1457
1641
|
success: true,
|
|
1458
1642
|
skipped: false,
|
|
1459
1643
|
duration: Date.now() - startTime
|
|
1460
1644
|
};
|
|
1461
1645
|
}
|
|
1462
|
-
|
|
1646
|
+
getLogger().info("Running build...");
|
|
1463
1647
|
try {
|
|
1464
1648
|
await runScript("build", buildPath, [], { quiet: true });
|
|
1465
|
-
|
|
1649
|
+
getLogger().success("Build completed successfully");
|
|
1466
1650
|
return {
|
|
1467
1651
|
success: true,
|
|
1468
1652
|
skipped: false,
|
|
@@ -1502,7 +1686,7 @@ var PRManager = class {
|
|
|
1502
1686
|
}
|
|
1503
1687
|
return null;
|
|
1504
1688
|
} catch (error) {
|
|
1505
|
-
|
|
1689
|
+
getLogger().debug("Error checking for existing PR", { error });
|
|
1506
1690
|
return null;
|
|
1507
1691
|
}
|
|
1508
1692
|
}
|
|
@@ -1529,7 +1713,7 @@ var PRManager = class {
|
|
|
1529
1713
|
}
|
|
1530
1714
|
}
|
|
1531
1715
|
} catch (error) {
|
|
1532
|
-
|
|
1716
|
+
getLogger().debug("Claude PR body generation failed, using template", { error });
|
|
1533
1717
|
}
|
|
1534
1718
|
}
|
|
1535
1719
|
let body = "This PR contains changes from the iloom workflow.\n\n";
|
|
@@ -1647,7 +1831,7 @@ Start your response immediately with the PR body text.
|
|
|
1647
1831
|
const originRemote = remotes.find((r) => r.name === "origin");
|
|
1648
1832
|
if (originRemote) {
|
|
1649
1833
|
headValue = `${originRemote.owner}:${branchName}`;
|
|
1650
|
-
|
|
1834
|
+
getLogger().debug(`Fork workflow detected, using head: ${headValue}`);
|
|
1651
1835
|
}
|
|
1652
1836
|
}
|
|
1653
1837
|
const args = ["pr", "create", "--head", headValue, "--title", title, "--body", body, "--base", baseBranch];
|
|
@@ -1686,9 +1870,9 @@ Then retry: il finish`
|
|
|
1686
1870
|
async openPRInBrowser(url) {
|
|
1687
1871
|
try {
|
|
1688
1872
|
await openBrowser(url);
|
|
1689
|
-
|
|
1873
|
+
getLogger().debug("Opened PR in browser", { url });
|
|
1690
1874
|
} catch (error) {
|
|
1691
|
-
|
|
1875
|
+
getLogger().warn("Failed to open PR in browser", { error });
|
|
1692
1876
|
}
|
|
1693
1877
|
}
|
|
1694
1878
|
/**
|
|
@@ -1704,7 +1888,7 @@ Then retry: il finish`
|
|
|
1704
1888
|
async createOrOpenPR(branchName, title, issueNumber, baseBranch, worktreePath, openInBrowser) {
|
|
1705
1889
|
const existingPR = await this.checkForExistingPR(branchName, worktreePath);
|
|
1706
1890
|
if (existingPR) {
|
|
1707
|
-
|
|
1891
|
+
getLogger().info(`Pull request already exists: ${existingPR.url}`);
|
|
1708
1892
|
if (openInBrowser) {
|
|
1709
1893
|
await this.openPRInBrowser(existingPR.url);
|
|
1710
1894
|
}
|
|
@@ -1715,7 +1899,7 @@ Then retry: il finish`
|
|
|
1715
1899
|
};
|
|
1716
1900
|
}
|
|
1717
1901
|
const body = await this.generatePRBody(issueNumber, worktreePath);
|
|
1718
|
-
|
|
1902
|
+
getLogger().info("Creating pull request...");
|
|
1719
1903
|
const url = await this.createPR(branchName, title, body, baseBranch, worktreePath);
|
|
1720
1904
|
const prNumber = this.extractPRNumberFromUrl(url);
|
|
1721
1905
|
if (openInBrowser) {
|
|
@@ -1747,10 +1931,10 @@ var FinishCommand = class {
|
|
|
1747
1931
|
constructor(issueTracker, gitWorktreeManager, validationRunner, commitManager, mergeManager, identifierParser, resourceCleanup, buildRunner, settingsManager, loomManager) {
|
|
1748
1932
|
const envResult = loadEnvIntoProcess();
|
|
1749
1933
|
if (envResult.error) {
|
|
1750
|
-
|
|
1934
|
+
getLogger().debug(`Environment loading warning: ${envResult.error.message}`);
|
|
1751
1935
|
}
|
|
1752
1936
|
if (envResult.parsed) {
|
|
1753
|
-
|
|
1937
|
+
getLogger().debug(`Loaded ${Object.keys(envResult.parsed).length} environment variables`);
|
|
1754
1938
|
}
|
|
1755
1939
|
this.issueTracker = issueTracker;
|
|
1756
1940
|
this.gitWorktreeManager = gitWorktreeManager ?? new GitWorktreeManager();
|
|
@@ -1781,7 +1965,7 @@ var FinishCommand = class {
|
|
|
1781
1965
|
const neonProvider = createNeonProviderFromSettings(settings);
|
|
1782
1966
|
const databaseManager = new DatabaseManager(neonProvider, environmentManager, databaseUrlEnvVarName);
|
|
1783
1967
|
const cliIsolationManager = new CLIIsolationManager();
|
|
1784
|
-
const { DefaultBranchNamingService: DefaultBranchNamingService2 } = await import("./BranchNamingService-
|
|
1968
|
+
const { DefaultBranchNamingService: DefaultBranchNamingService2 } = await import("./BranchNamingService-GCCWB3LK.js");
|
|
1785
1969
|
this.loomManager ??= new LoomManager(
|
|
1786
1970
|
this.gitWorktreeManager,
|
|
1787
1971
|
this.issueTracker,
|
|
@@ -1826,12 +2010,12 @@ var FinishCommand = class {
|
|
|
1826
2010
|
targetBranch = worktree == null ? void 0 : worktree.branch;
|
|
1827
2011
|
}
|
|
1828
2012
|
if (!targetBranch) {
|
|
1829
|
-
|
|
2013
|
+
getLogger().debug(`Cannot determine target branch for child loom check`);
|
|
1830
2014
|
return;
|
|
1831
2015
|
}
|
|
1832
2016
|
const hasChildLooms = await this.loomManager.checkAndWarnChildLooms(targetBranch);
|
|
1833
2017
|
if (hasChildLooms) {
|
|
1834
|
-
|
|
2018
|
+
getLogger().error("Cannot finish loom while child looms exist. Please 'finish' or 'cleanup' child looms first.");
|
|
1835
2019
|
process.exit(1);
|
|
1836
2020
|
}
|
|
1837
2021
|
}
|
|
@@ -1839,42 +2023,53 @@ var FinishCommand = class {
|
|
|
1839
2023
|
* Main entry point for finish command
|
|
1840
2024
|
*/
|
|
1841
2025
|
async execute(input) {
|
|
1842
|
-
var _a;
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
await this.
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
const worktree = worktrees[0];
|
|
1856
|
-
if (!worktree) {
|
|
1857
|
-
throw new Error("No worktree found");
|
|
1858
|
-
}
|
|
1859
|
-
if (parsed.type === "pr") {
|
|
1860
|
-
if (!parsed.number) {
|
|
1861
|
-
throw new Error("Invalid PR number");
|
|
1862
|
-
}
|
|
1863
|
-
if (!this.issueTracker.supportsPullRequests || !this.issueTracker.fetchPR) {
|
|
1864
|
-
throw new Error("Issue tracker does not support pull requests");
|
|
1865
|
-
}
|
|
1866
|
-
const pr = await this.issueTracker.fetchPR(parsed.number, repo);
|
|
1867
|
-
await this.executePRWorkflow(parsed, input.options, worktree, pr);
|
|
1868
|
-
} else {
|
|
1869
|
-
await this.executeIssueWorkflow(parsed, input.options, worktree);
|
|
2026
|
+
var _a, _b;
|
|
2027
|
+
const isJsonMode = input.options.json === true;
|
|
2028
|
+
const result = {
|
|
2029
|
+
success: false,
|
|
2030
|
+
type: "issue",
|
|
2031
|
+
identifier: "",
|
|
2032
|
+
dryRun: input.options.dryRun ?? false,
|
|
2033
|
+
operations: []
|
|
2034
|
+
};
|
|
2035
|
+
if (isJsonMode) {
|
|
2036
|
+
const settings2 = await this.settingsManager.loadSettings();
|
|
2037
|
+
if (((_a = settings2.mergeBehavior) == null ? void 0 : _a.mode) === "github-pr" && input.options.cleanup === void 0) {
|
|
2038
|
+
throw new Error("JSON mode with github-pr workflow requires --cleanup or --no-cleanup flag. Use: il finish --json --cleanup <identifier>");
|
|
1870
2039
|
}
|
|
1871
|
-
}
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
2040
|
+
}
|
|
2041
|
+
const settings = await this.settingsManager.loadSettings();
|
|
2042
|
+
let repo;
|
|
2043
|
+
const needsRepo = ((_b = settings.mergeBehavior) == null ? void 0 : _b.mode) === "github-pr" || this.issueTracker.providerName === "github";
|
|
2044
|
+
if (needsRepo && await hasMultipleRemotes()) {
|
|
2045
|
+
repo = await getConfiguredRepoFromSettings(settings);
|
|
2046
|
+
getLogger().info(`Using GitHub repository: ${repo}`);
|
|
2047
|
+
}
|
|
2048
|
+
const parsed = await this.parseInput(input.identifier, input.options);
|
|
2049
|
+
result.type = parsed.type;
|
|
2050
|
+
result.identifier = parsed.number ?? parsed.branchName ?? "";
|
|
2051
|
+
await this.checkForChildLooms(parsed);
|
|
2052
|
+
const worktrees = await this.validateInput(parsed, input.options, repo);
|
|
2053
|
+
getLogger().info(`Validated input: ${this.formatParsedInput(parsed)}`);
|
|
2054
|
+
const worktree = worktrees[0];
|
|
2055
|
+
if (!worktree) {
|
|
2056
|
+
throw new Error("No worktree found");
|
|
2057
|
+
}
|
|
2058
|
+
if (parsed.type === "pr") {
|
|
2059
|
+
if (!parsed.number) {
|
|
2060
|
+
throw new Error("Invalid PR number");
|
|
1876
2061
|
}
|
|
1877
|
-
|
|
2062
|
+
if (!this.issueTracker.supportsPullRequests || !this.issueTracker.fetchPR) {
|
|
2063
|
+
throw new Error("Issue tracker does not support pull requests");
|
|
2064
|
+
}
|
|
2065
|
+
const pr = await this.issueTracker.fetchPR(parsed.number, repo);
|
|
2066
|
+
await this.executePRWorkflow(parsed, input.options, worktree, pr, result);
|
|
2067
|
+
} else {
|
|
2068
|
+
await this.executeIssueWorkflow(parsed, input.options, worktree, result);
|
|
2069
|
+
}
|
|
2070
|
+
result.success = true;
|
|
2071
|
+
if (isJsonMode) {
|
|
2072
|
+
return result;
|
|
1878
2073
|
}
|
|
1879
2074
|
}
|
|
1880
2075
|
/**
|
|
@@ -1937,7 +2132,7 @@ var FinishCommand = class {
|
|
|
1937
2132
|
const prMatch = currentDir.match(prPattern);
|
|
1938
2133
|
if (prMatch == null ? void 0 : prMatch[1]) {
|
|
1939
2134
|
const prNumber = parseInt(prMatch[1], 10);
|
|
1940
|
-
|
|
2135
|
+
getLogger().debug(`Auto-detected PR #${prNumber} from directory: ${currentDir}`);
|
|
1941
2136
|
return {
|
|
1942
2137
|
type: "pr",
|
|
1943
2138
|
number: prNumber,
|
|
@@ -1947,7 +2142,7 @@ var FinishCommand = class {
|
|
|
1947
2142
|
}
|
|
1948
2143
|
const issueNumber = extractIssueNumber(currentDir);
|
|
1949
2144
|
if (issueNumber !== null) {
|
|
1950
|
-
|
|
2145
|
+
getLogger().debug(
|
|
1951
2146
|
`Auto-detected issue #${issueNumber} from directory: ${currentDir}`
|
|
1952
2147
|
);
|
|
1953
2148
|
return {
|
|
@@ -1966,7 +2161,7 @@ var FinishCommand = class {
|
|
|
1966
2161
|
}
|
|
1967
2162
|
const branchIssueNumber = extractIssueNumber(currentBranch);
|
|
1968
2163
|
if (branchIssueNumber !== null) {
|
|
1969
|
-
|
|
2164
|
+
getLogger().debug(
|
|
1970
2165
|
`Auto-detected issue #${branchIssueNumber} from branch: ${currentBranch}`
|
|
1971
2166
|
);
|
|
1972
2167
|
return {
|
|
@@ -1996,7 +2191,7 @@ var FinishCommand = class {
|
|
|
1996
2191
|
throw new Error("Issue tracker does not support pull requests");
|
|
1997
2192
|
}
|
|
1998
2193
|
const pr = await this.issueTracker.fetchPR(parsed.number);
|
|
1999
|
-
|
|
2194
|
+
getLogger().debug(`Validated PR #${parsed.number} (state: ${pr.state})`);
|
|
2000
2195
|
return await this.findWorktreeForIdentifier(parsed);
|
|
2001
2196
|
}
|
|
2002
2197
|
case "issue": {
|
|
@@ -2009,7 +2204,7 @@ var FinishCommand = class {
|
|
|
2009
2204
|
`Issue #${parsed.number} is closed. Use --force to finish anyway.`
|
|
2010
2205
|
);
|
|
2011
2206
|
}
|
|
2012
|
-
|
|
2207
|
+
getLogger().debug(`Validated issue #${parsed.number} (state: ${issue.state})`);
|
|
2013
2208
|
return await this.findWorktreeForIdentifier(parsed);
|
|
2014
2209
|
}
|
|
2015
2210
|
case "branch": {
|
|
@@ -2021,7 +2216,7 @@ var FinishCommand = class {
|
|
|
2021
2216
|
"Invalid branch name. Use only letters, numbers, hyphens, underscores, and slashes"
|
|
2022
2217
|
);
|
|
2023
2218
|
}
|
|
2024
|
-
|
|
2219
|
+
getLogger().debug(`Validated branch name: ${parsed.branchName}`);
|
|
2025
2220
|
return await this.findWorktreeForIdentifier(parsed);
|
|
2026
2221
|
}
|
|
2027
2222
|
default: {
|
|
@@ -2080,7 +2275,7 @@ var FinishCommand = class {
|
|
|
2080
2275
|
`No worktree found for ${this.formatParsedInput(parsed)}. Use 'il list' to see available worktrees.`
|
|
2081
2276
|
);
|
|
2082
2277
|
}
|
|
2083
|
-
|
|
2278
|
+
getLogger().debug(`Found worktree: ${worktree.path}`);
|
|
2084
2279
|
return [worktree];
|
|
2085
2280
|
}
|
|
2086
2281
|
/**
|
|
@@ -2109,23 +2304,38 @@ var FinishCommand = class {
|
|
|
2109
2304
|
* Execute workflow for issues and branches (merge into main)
|
|
2110
2305
|
* This is the traditional workflow: validate → commit → rebase → merge → cleanup
|
|
2111
2306
|
*/
|
|
2112
|
-
async executeIssueWorkflow(parsed, options, worktree) {
|
|
2307
|
+
async executeIssueWorkflow(parsed, options, worktree, result) {
|
|
2113
2308
|
var _a, _b;
|
|
2114
2309
|
if (!options.dryRun) {
|
|
2115
|
-
|
|
2310
|
+
getLogger().info("Running pre-merge validations...");
|
|
2116
2311
|
await this.validationRunner.runValidations(worktree.path, {
|
|
2117
2312
|
dryRun: options.dryRun ?? false
|
|
2118
2313
|
});
|
|
2119
|
-
|
|
2314
|
+
getLogger().success("All validations passed");
|
|
2315
|
+
result.operations.push({
|
|
2316
|
+
type: "validation",
|
|
2317
|
+
message: "Pre-merge validations passed",
|
|
2318
|
+
success: true
|
|
2319
|
+
});
|
|
2120
2320
|
} else {
|
|
2121
|
-
|
|
2321
|
+
getLogger().info("[DRY RUN] Would run pre-merge validations");
|
|
2322
|
+
result.operations.push({
|
|
2323
|
+
type: "validation",
|
|
2324
|
+
message: "Would run pre-merge validations (dry-run)",
|
|
2325
|
+
success: true
|
|
2326
|
+
});
|
|
2122
2327
|
}
|
|
2123
2328
|
const gitStatus = await this.commitManager.detectUncommittedChanges(worktree.path);
|
|
2124
2329
|
if (gitStatus.hasUncommittedChanges) {
|
|
2125
2330
|
if (options.dryRun) {
|
|
2126
|
-
|
|
2331
|
+
getLogger().info("[DRY RUN] Would auto-commit uncommitted changes (validation passed)");
|
|
2332
|
+
result.operations.push({
|
|
2333
|
+
type: "commit",
|
|
2334
|
+
message: "Would auto-commit uncommitted changes (dry-run)",
|
|
2335
|
+
success: true
|
|
2336
|
+
});
|
|
2127
2337
|
} else {
|
|
2128
|
-
|
|
2338
|
+
getLogger().info("Validation passed, auto-committing uncommitted changes...");
|
|
2129
2339
|
const settings2 = await this.settingsManager.loadSettings(worktree.path);
|
|
2130
2340
|
const skipVerify = ((_b = (_a = settings2.workflows) == null ? void 0 : _a.issue) == null ? void 0 : _b.noVerify) ?? false;
|
|
2131
2341
|
const commitOptions = {
|
|
@@ -2137,17 +2347,27 @@ var FinishCommand = class {
|
|
|
2137
2347
|
}
|
|
2138
2348
|
try {
|
|
2139
2349
|
await this.commitManager.commitChanges(worktree.path, commitOptions);
|
|
2140
|
-
|
|
2350
|
+
getLogger().success("Changes committed successfully");
|
|
2351
|
+
result.operations.push({
|
|
2352
|
+
type: "commit",
|
|
2353
|
+
message: "Changes committed successfully",
|
|
2354
|
+
success: true
|
|
2355
|
+
});
|
|
2141
2356
|
} catch (error) {
|
|
2142
2357
|
if (error instanceof UserAbortedCommitError) {
|
|
2143
|
-
|
|
2358
|
+
getLogger().info("Commit aborted by user");
|
|
2359
|
+
result.operations.push({
|
|
2360
|
+
type: "commit",
|
|
2361
|
+
message: "Commit aborted by user",
|
|
2362
|
+
success: false
|
|
2363
|
+
});
|
|
2144
2364
|
return;
|
|
2145
2365
|
}
|
|
2146
2366
|
throw error;
|
|
2147
2367
|
}
|
|
2148
2368
|
}
|
|
2149
2369
|
} else {
|
|
2150
|
-
|
|
2370
|
+
getLogger().debug("No uncommitted changes found");
|
|
2151
2371
|
}
|
|
2152
2372
|
const settings = await this.settingsManager.loadSettings(worktree.path);
|
|
2153
2373
|
const mergeBehavior = settings.mergeBehavior ?? { mode: "local" };
|
|
@@ -2157,32 +2377,43 @@ var FinishCommand = class {
|
|
|
2157
2377
|
`The 'github-pr' merge mode requires a GitHub-compatible issue tracker. Your current provider (${this.issueTracker.providerName}) does not support pull requests. Either change mergeBehavior.mode to 'local' in your settings, or use GitHub as your issue tracker.`
|
|
2158
2378
|
);
|
|
2159
2379
|
}
|
|
2160
|
-
await this.executeGitHubPRWorkflow(parsed, options, worktree, settings);
|
|
2380
|
+
await this.executeGitHubPRWorkflow(parsed, options, worktree, settings, result);
|
|
2161
2381
|
return;
|
|
2162
2382
|
}
|
|
2163
|
-
|
|
2383
|
+
getLogger().info("Rebasing branch on main...");
|
|
2164
2384
|
const mergeOptions = {
|
|
2165
2385
|
dryRun: options.dryRun ?? false,
|
|
2166
2386
|
force: options.force ?? false
|
|
2167
2387
|
};
|
|
2168
2388
|
await this.mergeManager.rebaseOnMain(worktree.path, mergeOptions);
|
|
2169
|
-
|
|
2170
|
-
|
|
2389
|
+
getLogger().success("Branch rebased successfully");
|
|
2390
|
+
result.operations.push({
|
|
2391
|
+
type: "rebase",
|
|
2392
|
+
message: "Branch rebased on main",
|
|
2393
|
+
success: true
|
|
2394
|
+
});
|
|
2395
|
+
getLogger().info("Performing fast-forward merge...");
|
|
2171
2396
|
await this.mergeManager.performFastForwardMerge(worktree.branch, worktree.path, mergeOptions);
|
|
2172
|
-
|
|
2397
|
+
getLogger().success("Fast-forward merge completed successfully");
|
|
2398
|
+
result.operations.push({
|
|
2399
|
+
type: "merge",
|
|
2400
|
+
message: "Fast-forward merge completed",
|
|
2401
|
+
success: true
|
|
2402
|
+
});
|
|
2173
2403
|
if (options.dryRun) {
|
|
2174
|
-
|
|
2404
|
+
getLogger().info("[DRY RUN] Would install dependencies in main worktree");
|
|
2175
2405
|
} else {
|
|
2176
|
-
|
|
2406
|
+
getLogger().info("Installing dependencies in main worktree...");
|
|
2177
2407
|
const mainWorktreePath = await findMainWorktreePathWithSettings(worktree.path, this.settingsManager);
|
|
2178
2408
|
await installDependencies(mainWorktreePath, true, true);
|
|
2179
2409
|
}
|
|
2180
2410
|
if (!options.skipBuild) {
|
|
2181
|
-
await this.runPostMergeBuild(worktree.path, options);
|
|
2411
|
+
await this.runPostMergeBuild(worktree.path, options, result);
|
|
2182
2412
|
} else {
|
|
2183
|
-
|
|
2413
|
+
getLogger().debug("Skipping build verification (--skip-build flag provided)");
|
|
2184
2414
|
}
|
|
2185
|
-
await this.
|
|
2415
|
+
await this.generateSessionSummaryIfConfigured(parsed, worktree, options);
|
|
2416
|
+
await this.performPostMergeCleanup(parsed, options, worktree, result);
|
|
2186
2417
|
}
|
|
2187
2418
|
/**
|
|
2188
2419
|
* Execute workflow for Pull Requests
|
|
@@ -2190,27 +2421,37 @@ var FinishCommand = class {
|
|
|
2190
2421
|
* - OPEN: Commit changes, push to remote, keep worktree active
|
|
2191
2422
|
* - CLOSED/MERGED: Skip to cleanup
|
|
2192
2423
|
*/
|
|
2193
|
-
async executePRWorkflow(parsed, options, worktree, pr) {
|
|
2424
|
+
async executePRWorkflow(parsed, options, worktree, pr, result) {
|
|
2194
2425
|
var _a, _b;
|
|
2195
2426
|
if (pr.state === "closed" || pr.state === "merged") {
|
|
2196
|
-
|
|
2427
|
+
getLogger().info(`PR #${parsed.number} is ${pr.state.toUpperCase()} - skipping to cleanup`);
|
|
2197
2428
|
const gitStatus = await this.commitManager.detectUncommittedChanges(worktree.path);
|
|
2198
2429
|
if (gitStatus.hasUncommittedChanges && !options.force) {
|
|
2199
|
-
|
|
2430
|
+
getLogger().warn("PR has uncommitted changes");
|
|
2200
2431
|
throw new Error(
|
|
2201
2432
|
"Cannot cleanup PR with uncommitted changes. Commit or stash changes, then run again with --force to cleanup anyway."
|
|
2202
2433
|
);
|
|
2203
2434
|
}
|
|
2204
|
-
await this.performPRCleanup(parsed, options, worktree);
|
|
2205
|
-
|
|
2435
|
+
await this.performPRCleanup(parsed, options, worktree, pr.state, result);
|
|
2436
|
+
getLogger().success(`PR #${parsed.number} cleanup completed`);
|
|
2437
|
+
result.operations.push({
|
|
2438
|
+
type: "cleanup",
|
|
2439
|
+
message: `PR #${parsed.number} cleanup completed`,
|
|
2440
|
+
success: true
|
|
2441
|
+
});
|
|
2206
2442
|
} else {
|
|
2207
|
-
|
|
2443
|
+
getLogger().info(`PR #${parsed.number} is OPEN - will push changes and keep worktree active`);
|
|
2208
2444
|
const gitStatus = await this.commitManager.detectUncommittedChanges(worktree.path);
|
|
2209
2445
|
if (gitStatus.hasUncommittedChanges) {
|
|
2210
2446
|
if (options.dryRun) {
|
|
2211
|
-
|
|
2447
|
+
getLogger().info("[DRY RUN] Would commit uncommitted changes");
|
|
2448
|
+
result.operations.push({
|
|
2449
|
+
type: "commit",
|
|
2450
|
+
message: "Would commit uncommitted changes (dry-run)",
|
|
2451
|
+
success: true
|
|
2452
|
+
});
|
|
2212
2453
|
} else {
|
|
2213
|
-
|
|
2454
|
+
getLogger().info("Committing uncommitted changes...");
|
|
2214
2455
|
const settings = await this.settingsManager.loadSettings(worktree.path);
|
|
2215
2456
|
const skipVerify = ((_b = (_a = settings.workflows) == null ? void 0 : _a.pr) == null ? void 0 : _b.noVerify) ?? false;
|
|
2216
2457
|
try {
|
|
@@ -2219,43 +2460,54 @@ var FinishCommand = class {
|
|
|
2219
2460
|
skipVerify
|
|
2220
2461
|
// Do NOT pass issueNumber for PRs - no "Fixes #" trailer needed
|
|
2221
2462
|
});
|
|
2222
|
-
|
|
2463
|
+
getLogger().success("Changes committed");
|
|
2464
|
+
result.operations.push({
|
|
2465
|
+
type: "commit",
|
|
2466
|
+
message: "Changes committed successfully",
|
|
2467
|
+
success: true
|
|
2468
|
+
});
|
|
2223
2469
|
} catch (error) {
|
|
2224
2470
|
if (error instanceof UserAbortedCommitError) {
|
|
2225
|
-
|
|
2471
|
+
getLogger().info("Commit aborted by user");
|
|
2472
|
+
result.operations.push({
|
|
2473
|
+
type: "commit",
|
|
2474
|
+
message: "Commit aborted by user",
|
|
2475
|
+
success: false
|
|
2476
|
+
});
|
|
2226
2477
|
return;
|
|
2227
2478
|
}
|
|
2228
2479
|
throw error;
|
|
2229
2480
|
}
|
|
2230
2481
|
}
|
|
2231
2482
|
} else {
|
|
2232
|
-
|
|
2483
|
+
getLogger().debug("No uncommitted changes found");
|
|
2233
2484
|
}
|
|
2234
2485
|
if (options.dryRun) {
|
|
2235
|
-
|
|
2486
|
+
getLogger().info(`[DRY RUN] Would push changes to origin/${pr.branch}`);
|
|
2236
2487
|
} else {
|
|
2237
|
-
|
|
2488
|
+
getLogger().info("Pushing changes to remote...");
|
|
2238
2489
|
await pushBranchToRemote(pr.branch, worktree.path, {
|
|
2239
2490
|
dryRun: false
|
|
2240
2491
|
});
|
|
2241
|
-
|
|
2492
|
+
getLogger().success(`Changes pushed to PR #${parsed.number}`);
|
|
2242
2493
|
}
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2494
|
+
getLogger().success(`PR #${parsed.number} updated successfully`);
|
|
2495
|
+
getLogger().info("Worktree remains active for continued work");
|
|
2496
|
+
getLogger().info(`To cleanup when done: il cleanup ${parsed.number}`);
|
|
2497
|
+
result.prUrl = pr.url;
|
|
2246
2498
|
}
|
|
2247
2499
|
}
|
|
2248
2500
|
/**
|
|
2249
2501
|
* Execute workflow for GitHub PR creation (github-pr merge mode)
|
|
2250
2502
|
* Validates → Commits → Pushes → Creates PR → Prompts for cleanup
|
|
2251
2503
|
*/
|
|
2252
|
-
async executeGitHubPRWorkflow(parsed, options, worktree, settings) {
|
|
2504
|
+
async executeGitHubPRWorkflow(parsed, options, worktree, settings, finishResult) {
|
|
2253
2505
|
if (options.dryRun) {
|
|
2254
|
-
|
|
2506
|
+
getLogger().info("[DRY RUN] Would push branch to origin");
|
|
2255
2507
|
} else {
|
|
2256
|
-
|
|
2508
|
+
getLogger().info("Pushing branch to origin...");
|
|
2257
2509
|
await pushBranchToRemote(worktree.branch, worktree.path, { dryRun: false });
|
|
2258
|
-
|
|
2510
|
+
getLogger().success("Branch pushed successfully");
|
|
2259
2511
|
}
|
|
2260
2512
|
const prManager = new PRManager(settings);
|
|
2261
2513
|
let prTitle = `Work from ${worktree.branch}`;
|
|
@@ -2264,17 +2516,22 @@ var FinishCommand = class {
|
|
|
2264
2516
|
const issue = await this.issueTracker.fetchIssue(parsed.number);
|
|
2265
2517
|
prTitle = issue.title;
|
|
2266
2518
|
} catch (error) {
|
|
2267
|
-
|
|
2519
|
+
getLogger().debug("Could not fetch issue title, using branch name", { error });
|
|
2268
2520
|
}
|
|
2269
2521
|
}
|
|
2522
|
+
const baseBranch = await getMergeTargetBranch(worktree.path);
|
|
2270
2523
|
if (options.dryRun) {
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2524
|
+
getLogger().info("[DRY RUN] Would create GitHub PR");
|
|
2525
|
+
getLogger().info(` Title: ${prTitle}`);
|
|
2526
|
+
getLogger().info(` Base: ${baseBranch}`);
|
|
2527
|
+
finishResult.operations.push({
|
|
2528
|
+
type: "pr-creation",
|
|
2529
|
+
message: "Would create GitHub PR (dry-run)",
|
|
2530
|
+
success: true
|
|
2531
|
+
});
|
|
2274
2532
|
} else {
|
|
2275
|
-
const baseBranch = settings.mainBranch ?? "main";
|
|
2276
2533
|
const openInBrowser = options.noBrowser !== true;
|
|
2277
|
-
const
|
|
2534
|
+
const prResult = await prManager.createOrOpenPR(
|
|
2278
2535
|
worktree.branch,
|
|
2279
2536
|
prTitle,
|
|
2280
2537
|
parsed.type === "issue" ? parsed.number : void 0,
|
|
@@ -2282,40 +2539,52 @@ var FinishCommand = class {
|
|
|
2282
2539
|
worktree.path,
|
|
2283
2540
|
openInBrowser
|
|
2284
2541
|
);
|
|
2285
|
-
if (
|
|
2286
|
-
|
|
2542
|
+
if (prResult.wasExisting) {
|
|
2543
|
+
getLogger().success(`Existing pull request: ${prResult.url}`);
|
|
2544
|
+
finishResult.operations.push({
|
|
2545
|
+
type: "pr-creation",
|
|
2546
|
+
message: `Found existing pull request`,
|
|
2547
|
+
success: true
|
|
2548
|
+
});
|
|
2287
2549
|
} else {
|
|
2288
|
-
|
|
2550
|
+
getLogger().success(`Pull request created: ${prResult.url}`);
|
|
2551
|
+
finishResult.operations.push({
|
|
2552
|
+
type: "pr-creation",
|
|
2553
|
+
message: `Pull request created`,
|
|
2554
|
+
success: true
|
|
2555
|
+
});
|
|
2289
2556
|
}
|
|
2290
|
-
|
|
2557
|
+
finishResult.prUrl = prResult.url;
|
|
2558
|
+
await this.generateSessionSummaryIfConfigured(parsed, worktree, options);
|
|
2559
|
+
await this.handlePRCleanupPrompt(parsed, options, worktree, finishResult);
|
|
2291
2560
|
}
|
|
2292
2561
|
}
|
|
2293
2562
|
/**
|
|
2294
2563
|
* Handle cleanup prompt after PR creation
|
|
2295
2564
|
* Respects --cleanup and --no-cleanup flags, otherwise prompts user
|
|
2296
2565
|
*/
|
|
2297
|
-
async handlePRCleanupPrompt(parsed, options, worktree) {
|
|
2566
|
+
async handlePRCleanupPrompt(parsed, options, worktree, finishResult) {
|
|
2298
2567
|
if (options.cleanup === true) {
|
|
2299
|
-
|
|
2300
|
-
await this.performWorktreeCleanup(parsed, options, worktree);
|
|
2568
|
+
getLogger().info("Cleaning up worktree (--cleanup flag)...");
|
|
2569
|
+
await this.performWorktreeCleanup(parsed, options, worktree, finishResult);
|
|
2301
2570
|
} else if (options.cleanup === false) {
|
|
2302
|
-
|
|
2303
|
-
|
|
2571
|
+
getLogger().info("Worktree kept active for continued work (--no-cleanup flag)");
|
|
2572
|
+
getLogger().info(`To cleanup later: il cleanup ${parsed.originalInput}`);
|
|
2304
2573
|
} else {
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2574
|
+
getLogger().info("");
|
|
2575
|
+
getLogger().info("PR created successfully. Would you like to clean up the worktree?");
|
|
2576
|
+
getLogger().info(` Worktree: ${worktree.path}`);
|
|
2577
|
+
getLogger().info(` Branch: ${worktree.branch}`);
|
|
2578
|
+
getLogger().info("");
|
|
2310
2579
|
const shouldCleanup = await promptConfirmation(
|
|
2311
2580
|
"Clean up worktree now?",
|
|
2312
2581
|
false
|
|
2313
2582
|
// Default to keeping worktree (safer option)
|
|
2314
2583
|
);
|
|
2315
2584
|
if (shouldCleanup) {
|
|
2316
|
-
await this.performWorktreeCleanup(parsed, options, worktree);
|
|
2585
|
+
await this.performWorktreeCleanup(parsed, options, worktree, finishResult);
|
|
2317
2586
|
} else {
|
|
2318
|
-
|
|
2587
|
+
getLogger().info("Worktree kept active. Run `il cleanup` when ready.");
|
|
2319
2588
|
}
|
|
2320
2589
|
}
|
|
2321
2590
|
}
|
|
@@ -2323,7 +2592,7 @@ var FinishCommand = class {
|
|
|
2323
2592
|
* Perform worktree cleanup (used by GitHub PR workflow)
|
|
2324
2593
|
* Similar to performPostMergeCleanup but for PR workflow
|
|
2325
2594
|
*/
|
|
2326
|
-
async performWorktreeCleanup(parsed, options, worktree) {
|
|
2595
|
+
async performWorktreeCleanup(parsed, options, worktree, finishResult) {
|
|
2327
2596
|
const cleanupInput = {
|
|
2328
2597
|
type: parsed.type,
|
|
2329
2598
|
originalInput: parsed.originalInput,
|
|
@@ -2339,56 +2608,98 @@ var FinishCommand = class {
|
|
|
2339
2608
|
force: options.force ?? false
|
|
2340
2609
|
};
|
|
2341
2610
|
try {
|
|
2342
|
-
|
|
2611
|
+
getLogger().info("Starting worktree cleanup...");
|
|
2343
2612
|
await this.ensureResourceCleanup();
|
|
2344
2613
|
if (!this.resourceCleanup) {
|
|
2345
2614
|
throw new Error("Failed to initialize ResourceCleanup");
|
|
2346
2615
|
}
|
|
2347
|
-
const
|
|
2348
|
-
this.reportCleanupResults(
|
|
2349
|
-
|
|
2350
|
-
|
|
2616
|
+
const cleanupResult = await this.resourceCleanup.cleanupWorktree(cleanupInput, cleanupOptions);
|
|
2617
|
+
this.reportCleanupResults(cleanupResult);
|
|
2618
|
+
finishResult.cleanupResult = cleanupResult;
|
|
2619
|
+
if (!cleanupResult.success) {
|
|
2620
|
+
getLogger().warn("Some cleanup operations failed - manual cleanup may be required");
|
|
2351
2621
|
this.showManualCleanupInstructions(worktree);
|
|
2622
|
+
finishResult.operations.push({
|
|
2623
|
+
type: "cleanup",
|
|
2624
|
+
message: "Worktree cleanup partially failed",
|
|
2625
|
+
success: false
|
|
2626
|
+
});
|
|
2352
2627
|
} else {
|
|
2353
|
-
|
|
2628
|
+
getLogger().success("Worktree cleanup completed successfully");
|
|
2629
|
+
finishResult.operations.push({
|
|
2630
|
+
type: "cleanup",
|
|
2631
|
+
message: "Worktree cleanup completed",
|
|
2632
|
+
success: true
|
|
2633
|
+
});
|
|
2354
2634
|
}
|
|
2355
2635
|
if (this.isRunningFromWithinWorktree(worktree.path)) {
|
|
2356
2636
|
this.showTerminalCloseWarning(worktree);
|
|
2357
2637
|
}
|
|
2358
2638
|
} catch (error) {
|
|
2359
2639
|
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
2360
|
-
|
|
2361
|
-
|
|
2640
|
+
getLogger().warn(`Cleanup failed: ${errorMessage}`);
|
|
2641
|
+
getLogger().warn("Manual cleanup may be required");
|
|
2362
2642
|
this.showManualCleanupInstructions(worktree);
|
|
2643
|
+
finishResult.operations.push({
|
|
2644
|
+
type: "cleanup",
|
|
2645
|
+
message: "Worktree cleanup failed",
|
|
2646
|
+
success: false,
|
|
2647
|
+
error: errorMessage
|
|
2648
|
+
});
|
|
2363
2649
|
}
|
|
2364
2650
|
}
|
|
2365
2651
|
/**
|
|
2366
2652
|
* Perform cleanup for closed/merged PRs
|
|
2367
2653
|
* Similar to performPostMergeCleanup but with different messaging
|
|
2654
|
+
*
|
|
2655
|
+
* Safety check behavior differs based on PR state:
|
|
2656
|
+
* - MERGED: Skip safety checks - work is safely in main branch
|
|
2657
|
+
* - CLOSED (not merged): Enable safety checks - PR was rejected/abandoned,
|
|
2658
|
+
* local commits may not exist anywhere else
|
|
2659
|
+
*
|
|
2660
|
+
* @param parsed - Parsed input identifying the PR
|
|
2661
|
+
* @param options - Finish options
|
|
2662
|
+
* @param worktree - The worktree to clean up
|
|
2663
|
+
* @param prState - The PR state ('closed' or 'merged')
|
|
2664
|
+
* @param finishResult - Result object to populate
|
|
2368
2665
|
*/
|
|
2369
|
-
async performPRCleanup(parsed, options, worktree) {
|
|
2666
|
+
async performPRCleanup(parsed, options, worktree, prState, finishResult) {
|
|
2370
2667
|
const cleanupInput = {
|
|
2371
2668
|
type: parsed.type,
|
|
2372
2669
|
originalInput: parsed.originalInput,
|
|
2373
2670
|
...parsed.number !== void 0 && { number: parsed.number },
|
|
2374
2671
|
...parsed.branchName !== void 0 && { branchName: parsed.branchName }
|
|
2375
2672
|
};
|
|
2673
|
+
const isMerged = prState === "merged";
|
|
2376
2674
|
const cleanupOptions = {
|
|
2377
2675
|
dryRun: options.dryRun ?? false,
|
|
2378
2676
|
deleteBranch: true,
|
|
2379
2677
|
// Delete branch for closed/merged PRs
|
|
2380
2678
|
keepDatabase: false,
|
|
2381
|
-
force: options.force ?? false
|
|
2679
|
+
force: options.force ?? false,
|
|
2680
|
+
// For merged PRs: skip merge check (work is in main)
|
|
2681
|
+
// For closed PRs: enable merge check (may have unpushed local commits)
|
|
2682
|
+
checkMergeSafety: !isMerged,
|
|
2683
|
+
// Skip remote branch check for MERGED PRs because:
|
|
2684
|
+
// 1. The PR is merged - the work is safely in main
|
|
2685
|
+
// 2. GitHub may have auto-deleted the branch after merge
|
|
2686
|
+
// 3. The user may have manually deleted the remote branch post-merge
|
|
2687
|
+
//
|
|
2688
|
+
// For CLOSED PRs, we rely on checkMergeSafety to verify no unpushed commits
|
|
2689
|
+
// rather than checkRemoteBranch, since the remote branch may still exist
|
|
2690
|
+
// but local may have additional commits
|
|
2691
|
+
checkRemoteBranch: false
|
|
2382
2692
|
};
|
|
2383
2693
|
try {
|
|
2384
2694
|
await this.ensureResourceCleanup();
|
|
2385
2695
|
if (!this.resourceCleanup) {
|
|
2386
2696
|
throw new Error("Failed to initialize ResourceCleanup");
|
|
2387
2697
|
}
|
|
2388
|
-
const
|
|
2389
|
-
this.reportCleanupResults(
|
|
2390
|
-
|
|
2391
|
-
|
|
2698
|
+
const cleanupResult = await this.resourceCleanup.cleanupWorktree(cleanupInput, cleanupOptions);
|
|
2699
|
+
this.reportCleanupResults(cleanupResult);
|
|
2700
|
+
finishResult.cleanupResult = cleanupResult;
|
|
2701
|
+
if (!cleanupResult.success) {
|
|
2702
|
+
getLogger().warn("Some cleanup operations failed - manual cleanup may be required");
|
|
2392
2703
|
this.showManualCleanupInstructions(worktree);
|
|
2393
2704
|
} else {
|
|
2394
2705
|
if (this.isRunningFromWithinWorktree(worktree.path)) {
|
|
@@ -2397,29 +2708,86 @@ var FinishCommand = class {
|
|
|
2397
2708
|
}
|
|
2398
2709
|
} catch (error) {
|
|
2399
2710
|
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
2400
|
-
|
|
2711
|
+
getLogger().warn(`Cleanup failed: ${errorMessage}`);
|
|
2401
2712
|
this.showManualCleanupInstructions(worktree);
|
|
2402
2713
|
throw error;
|
|
2403
2714
|
}
|
|
2404
2715
|
}
|
|
2716
|
+
/**
|
|
2717
|
+
* Generate and post session summary if configured
|
|
2718
|
+
*
|
|
2719
|
+
* Non-blocking: Catches all errors and logs warnings instead of throwing
|
|
2720
|
+
* This ensures the finish workflow continues even if summary generation fails
|
|
2721
|
+
*
|
|
2722
|
+
* In dry-run mode: generates summary and shows preview, but doesn't post
|
|
2723
|
+
*/
|
|
2724
|
+
async generateSessionSummaryIfConfigured(parsed, worktree, options) {
|
|
2725
|
+
if (parsed.type === "branch") {
|
|
2726
|
+
return;
|
|
2727
|
+
}
|
|
2728
|
+
this.sessionSummaryService ??= new SessionSummaryService(
|
|
2729
|
+
void 0,
|
|
2730
|
+
// Use default PromptTemplateManager
|
|
2731
|
+
void 0,
|
|
2732
|
+
// Use default MetadataManager
|
|
2733
|
+
this.settingsManager
|
|
2734
|
+
);
|
|
2735
|
+
if (options.dryRun) {
|
|
2736
|
+
try {
|
|
2737
|
+
const result = await this.sessionSummaryService.generateSummary(
|
|
2738
|
+
worktree.path,
|
|
2739
|
+
worktree.branch,
|
|
2740
|
+
parsed.type,
|
|
2741
|
+
parsed.number
|
|
2742
|
+
);
|
|
2743
|
+
const preview = result.summary.slice(0, 100).replace(/\n/g, " ");
|
|
2744
|
+
getLogger().info(`[DRY RUN] Would post session summary: "${preview}..."`);
|
|
2745
|
+
} catch (error) {
|
|
2746
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2747
|
+
getLogger().warn(`[DRY RUN] Session summary generation failed: ${errorMessage}`);
|
|
2748
|
+
}
|
|
2749
|
+
return;
|
|
2750
|
+
}
|
|
2751
|
+
await this.sessionSummaryService.generateAndPostSummary({
|
|
2752
|
+
worktreePath: worktree.path,
|
|
2753
|
+
issueNumber: parsed.number ?? 0,
|
|
2754
|
+
branchName: worktree.branch,
|
|
2755
|
+
loomType: parsed.type
|
|
2756
|
+
});
|
|
2757
|
+
}
|
|
2405
2758
|
/**
|
|
2406
2759
|
* Run post-merge build verification for CLI projects
|
|
2407
2760
|
* Runs in main worktree to verify merged code builds successfully
|
|
2408
2761
|
*/
|
|
2409
|
-
async runPostMergeBuild(worktreePath, options) {
|
|
2762
|
+
async runPostMergeBuild(worktreePath, options, finishResult) {
|
|
2410
2763
|
const mainWorktreePath = await findMainWorktreePathWithSettings(worktreePath, this.settingsManager);
|
|
2411
2764
|
if (options.dryRun) {
|
|
2412
|
-
|
|
2765
|
+
getLogger().info("[DRY RUN] Would run post-merge build");
|
|
2766
|
+
finishResult.operations.push({
|
|
2767
|
+
type: "build",
|
|
2768
|
+
message: "Would run post-merge build (dry-run)",
|
|
2769
|
+
success: true
|
|
2770
|
+
});
|
|
2413
2771
|
return;
|
|
2414
2772
|
}
|
|
2415
|
-
|
|
2416
|
-
const
|
|
2773
|
+
getLogger().info("Running post-merge build...");
|
|
2774
|
+
const buildResult = await this.buildRunner.runBuild(mainWorktreePath, {
|
|
2417
2775
|
dryRun: options.dryRun ?? false
|
|
2418
2776
|
});
|
|
2419
|
-
if (
|
|
2420
|
-
|
|
2777
|
+
if (buildResult.skipped) {
|
|
2778
|
+
getLogger().debug(`Build skipped: ${buildResult.reason}`);
|
|
2779
|
+
finishResult.operations.push({
|
|
2780
|
+
type: "build",
|
|
2781
|
+
message: `Build skipped: ${buildResult.reason}`,
|
|
2782
|
+
success: true
|
|
2783
|
+
});
|
|
2421
2784
|
} else {
|
|
2422
|
-
|
|
2785
|
+
getLogger().success("Post-merge build completed successfully");
|
|
2786
|
+
finishResult.operations.push({
|
|
2787
|
+
type: "build",
|
|
2788
|
+
message: "Post-merge build completed",
|
|
2789
|
+
success: true
|
|
2790
|
+
});
|
|
2423
2791
|
}
|
|
2424
2792
|
}
|
|
2425
2793
|
/**
|
|
@@ -2427,7 +2795,7 @@ var FinishCommand = class {
|
|
|
2427
2795
|
* Converts ParsedFinishInput to ParsedInput and calls ResourceCleanup
|
|
2428
2796
|
* Handles failures gracefully without throwing
|
|
2429
2797
|
*/
|
|
2430
|
-
async performPostMergeCleanup(parsed, options, worktree) {
|
|
2798
|
+
async performPostMergeCleanup(parsed, options, worktree, finishResult) {
|
|
2431
2799
|
await this.ensureResourceCleanup();
|
|
2432
2800
|
if (!this.loomManager) {
|
|
2433
2801
|
throw new Error("Failed to initialize LoomManager");
|
|
@@ -2448,26 +2816,43 @@ var FinishCommand = class {
|
|
|
2448
2816
|
force: options.force ?? false
|
|
2449
2817
|
};
|
|
2450
2818
|
try {
|
|
2451
|
-
|
|
2819
|
+
getLogger().info("Starting post-merge cleanup...");
|
|
2452
2820
|
if (!this.resourceCleanup) {
|
|
2453
2821
|
throw new Error("Failed to initialize ResourceCleanup");
|
|
2454
2822
|
}
|
|
2455
|
-
const
|
|
2456
|
-
this.reportCleanupResults(
|
|
2457
|
-
|
|
2458
|
-
|
|
2823
|
+
const cleanupResult = await this.resourceCleanup.cleanupWorktree(cleanupInput, cleanupOptions);
|
|
2824
|
+
this.reportCleanupResults(cleanupResult);
|
|
2825
|
+
finishResult.cleanupResult = cleanupResult;
|
|
2826
|
+
if (!cleanupResult.success) {
|
|
2827
|
+
getLogger().warn("Some cleanup operations failed - manual cleanup may be required");
|
|
2459
2828
|
this.showManualCleanupInstructions(worktree);
|
|
2829
|
+
finishResult.operations.push({
|
|
2830
|
+
type: "cleanup",
|
|
2831
|
+
message: "Post-merge cleanup partially failed",
|
|
2832
|
+
success: false
|
|
2833
|
+
});
|
|
2460
2834
|
} else {
|
|
2461
|
-
|
|
2835
|
+
getLogger().success("Post-merge cleanup completed successfully");
|
|
2836
|
+
finishResult.operations.push({
|
|
2837
|
+
type: "cleanup",
|
|
2838
|
+
message: "Post-merge cleanup completed",
|
|
2839
|
+
success: true
|
|
2840
|
+
});
|
|
2462
2841
|
}
|
|
2463
2842
|
if (this.isRunningFromWithinWorktree(worktree.path)) {
|
|
2464
2843
|
this.showTerminalCloseWarning(worktree);
|
|
2465
2844
|
}
|
|
2466
2845
|
} catch (error) {
|
|
2467
2846
|
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
2468
|
-
|
|
2469
|
-
|
|
2847
|
+
getLogger().warn(`Cleanup failed: ${errorMessage}`);
|
|
2848
|
+
getLogger().warn("Merge completed successfully, but manual cleanup is required");
|
|
2470
2849
|
this.showManualCleanupInstructions(worktree);
|
|
2850
|
+
finishResult.operations.push({
|
|
2851
|
+
type: "cleanup",
|
|
2852
|
+
message: "Post-merge cleanup failed",
|
|
2853
|
+
success: false,
|
|
2854
|
+
error: errorMessage
|
|
2855
|
+
});
|
|
2471
2856
|
}
|
|
2472
2857
|
}
|
|
2473
2858
|
/**
|
|
@@ -2477,14 +2862,14 @@ var FinishCommand = class {
|
|
|
2477
2862
|
if (result.operations.length === 0) {
|
|
2478
2863
|
return;
|
|
2479
2864
|
}
|
|
2480
|
-
|
|
2865
|
+
getLogger().info("Cleanup operations:");
|
|
2481
2866
|
for (const op of result.operations) {
|
|
2482
2867
|
const status = op.success ? "\u2713" : "\u2717";
|
|
2483
2868
|
const message = op.error ? `${op.message}: ${op.error}` : op.message;
|
|
2484
2869
|
if (op.success) {
|
|
2485
|
-
|
|
2870
|
+
getLogger().info(` ${status} ${message}`);
|
|
2486
2871
|
} else {
|
|
2487
|
-
|
|
2872
|
+
getLogger().warn(` ${status} ${message}`);
|
|
2488
2873
|
}
|
|
2489
2874
|
}
|
|
2490
2875
|
}
|
|
@@ -2492,10 +2877,10 @@ var FinishCommand = class {
|
|
|
2492
2877
|
* Show manual cleanup instructions when cleanup fails
|
|
2493
2878
|
*/
|
|
2494
2879
|
showManualCleanupInstructions(worktree) {
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2880
|
+
getLogger().info("\nManual cleanup commands:");
|
|
2881
|
+
getLogger().info(` 1. Remove worktree: git worktree remove ${worktree.path}`);
|
|
2882
|
+
getLogger().info(` 2. Delete branch: git branch -d ${worktree.branch}`);
|
|
2883
|
+
getLogger().info(` 3. Check dev servers: lsof -i :PORT (and kill if needed)`);
|
|
2499
2884
|
}
|
|
2500
2885
|
/**
|
|
2501
2886
|
* Check if current working directory is within the target worktree
|
|
@@ -2509,17 +2894,17 @@ var FinishCommand = class {
|
|
|
2509
2894
|
* Display warning to close terminal/IDE when running from within finished loom
|
|
2510
2895
|
*/
|
|
2511
2896
|
showTerminalCloseWarning(worktree) {
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2897
|
+
getLogger().info("");
|
|
2898
|
+
getLogger().info("You are currently in the directory of the loom that was just finished.");
|
|
2899
|
+
getLogger().info("Please close this terminal and any IDE/terminal windows using this directory.");
|
|
2900
|
+
getLogger().info(`Directory: ${worktree.path}`);
|
|
2516
2901
|
}
|
|
2517
2902
|
};
|
|
2518
2903
|
|
|
2519
2904
|
// src/utils/package-info.ts
|
|
2520
2905
|
import { readFileSync } from "fs";
|
|
2521
2906
|
import { fileURLToPath } from "url";
|
|
2522
|
-
import { dirname, join } from "path";
|
|
2907
|
+
import { dirname, join as join2 } from "path";
|
|
2523
2908
|
function getPackageInfo(scriptPath) {
|
|
2524
2909
|
try {
|
|
2525
2910
|
let basePath;
|
|
@@ -2530,7 +2915,7 @@ function getPackageInfo(scriptPath) {
|
|
|
2530
2915
|
basePath = __filename2;
|
|
2531
2916
|
}
|
|
2532
2917
|
const __dirname = dirname(basePath);
|
|
2533
|
-
const packageJsonPath =
|
|
2918
|
+
const packageJsonPath = join2(__dirname, "..", "package.json");
|
|
2534
2919
|
const packageJsonContent = readFileSync(packageJsonPath, "utf8");
|
|
2535
2920
|
const packageJson2 = JSON.parse(packageJsonContent);
|
|
2536
2921
|
return packageJson2;
|
|
@@ -2606,7 +2991,8 @@ function formatLoomForJson(worktree, mainWorktreePath, metadata) {
|
|
|
2606
2991
|
description: (metadata == null ? void 0 : metadata.description) ?? null,
|
|
2607
2992
|
created_at: (metadata == null ? void 0 : metadata.created_at) ?? null,
|
|
2608
2993
|
issueTracker: (metadata == null ? void 0 : metadata.issueTracker) ?? null,
|
|
2609
|
-
colorHex: (metadata == null ? void 0 : metadata.colorHex) ?? null
|
|
2994
|
+
colorHex: (metadata == null ? void 0 : metadata.colorHex) ?? null,
|
|
2995
|
+
projectPath: (metadata == null ? void 0 : metadata.projectPath) ?? null
|
|
2610
2996
|
};
|
|
2611
2997
|
}
|
|
2612
2998
|
function formatLoomsForJson(worktrees, mainWorktreePath, metadata) {
|
|
@@ -2631,14 +3017,14 @@ program.name("iloom").description(packageJson.description).version(packageJson.v
|
|
|
2631
3017
|
process.exit(0);
|
|
2632
3018
|
}
|
|
2633
3019
|
try {
|
|
2634
|
-
const { checkAndNotifyUpdate } = await import("./update-notifier-
|
|
2635
|
-
const { detectInstallationMethod } = await import("./installation-detector-
|
|
3020
|
+
const { checkAndNotifyUpdate } = await import("./update-notifier-H55ZK7NU.js");
|
|
3021
|
+
const { detectInstallationMethod } = await import("./installation-detector-6R6YOFVZ.js");
|
|
2636
3022
|
const installMethod = detectInstallationMethod(__filename);
|
|
2637
3023
|
await checkAndNotifyUpdate(packageJson.version, packageJson.name, installMethod);
|
|
2638
3024
|
} catch {
|
|
2639
3025
|
}
|
|
2640
3026
|
try {
|
|
2641
|
-
const { SettingsMigrationManager } = await import("./SettingsMigrationManager-
|
|
3027
|
+
const { SettingsMigrationManager } = await import("./SettingsMigrationManager-EH3J2TCN.js");
|
|
2642
3028
|
const migrationManager = new SettingsMigrationManager();
|
|
2643
3029
|
await migrationManager.migrateSettingsIfNeeded();
|
|
2644
3030
|
} catch (error) {
|
|
@@ -2728,21 +3114,21 @@ async function autoLaunchInitForMultipleRemotes() {
|
|
|
2728
3114
|
logger.info("iloom will now launch an interactive configuration session with Claude");
|
|
2729
3115
|
logger.info("to help you select which remote to use for GitHub operations.");
|
|
2730
3116
|
logger.info("");
|
|
2731
|
-
const { waitForKeypress: waitForKeypress2 } = await import("./prompt-
|
|
3117
|
+
const { waitForKeypress: waitForKeypress2 } = await import("./prompt-A7GGRHSY.js");
|
|
2732
3118
|
await waitForKeypress2("Press any key to start configuration...");
|
|
2733
3119
|
logger.info("");
|
|
2734
3120
|
try {
|
|
2735
|
-
const { InitCommand: InitCommand2 } = await import("./init-
|
|
3121
|
+
const { InitCommand: InitCommand2 } = await import("./init-LBA6NUK2.js");
|
|
2736
3122
|
const initCommand = new InitCommand2();
|
|
2737
3123
|
const customInitialMessage = "Help me configure which git remote iloom should use for GitHub operations. I have multiple remotes and need to select the correct one.";
|
|
2738
3124
|
await initCommand.execute(customInitialMessage);
|
|
2739
3125
|
logger.info("");
|
|
2740
3126
|
logger.info("Configuration complete! Continuing with your original command...");
|
|
2741
3127
|
logger.info("");
|
|
2742
|
-
const { SettingsManager: SettingsManager2 } = await import("./SettingsManager-
|
|
3128
|
+
const { SettingsManager: SettingsManager2 } = await import("./SettingsManager-FJFU6JJD.js");
|
|
2743
3129
|
const settingsManager = new SettingsManager2();
|
|
2744
3130
|
const settings = await settingsManager.loadSettings();
|
|
2745
|
-
const { hasMultipleRemotes: hasMultipleRemotes2 } = await import("./remote-
|
|
3131
|
+
const { hasMultipleRemotes: hasMultipleRemotes2 } = await import("./remote-73TZ2ADI.js");
|
|
2746
3132
|
const multipleRemotes = await hasMultipleRemotes2();
|
|
2747
3133
|
if (multipleRemotes && !((_b = (_a = settings.issueManagement) == null ? void 0 : _a.github) == null ? void 0 : _b.remote)) {
|
|
2748
3134
|
logger.error("Configuration incomplete: GitHub remote is still not configured.");
|
|
@@ -2758,50 +3144,82 @@ async function autoLaunchInitForMultipleRemotes() {
|
|
|
2758
3144
|
}
|
|
2759
3145
|
var shellCompletion = new ShellCompletion();
|
|
2760
3146
|
shellCompletion.init();
|
|
2761
|
-
program.command("start").alias("new").alias("create").alias("up").description("Create isolated workspace for an issue/PR").argument("[identifier]", "Issue number, PR number, or branch name (optional - will prompt if not provided)").option("--claude", "Enable Claude integration (default: true)").option("--no-claude", "Disable Claude integration").option("--code", "Enable VSCode (default: true)").option("--no-code", "Disable VSCode").option("--dev-server", "Enable dev server in terminal (default: true)").option("--no-dev-server", "Disable dev server").option("--terminal", "Enable terminal without dev server (default: false)").option("--no-terminal", "Disable terminal").option("--child-loom", "Force create as child loom (skip prompt)").option("--no-child-loom", "Force create as independent loom (skip prompt)").option("--body <text>", "Body text for issue (skips AI enhancement)").addOption(
|
|
3147
|
+
program.command("start").alias("new").alias("create").alias("up").description("Create isolated workspace for an issue/PR").argument("[identifier]", "Issue number, PR number, or branch name (optional - will prompt if not provided)").option("--claude", "Enable Claude integration (default: true)").option("--no-claude", "Disable Claude integration").option("--code", "Enable VSCode (default: true)").option("--no-code", "Disable VSCode").option("--dev-server", "Enable dev server in terminal (default: true)").option("--no-dev-server", "Disable dev server").option("--terminal", "Enable terminal without dev server (default: false)").option("--no-terminal", "Disable terminal").option("--child-loom", "Force create as child loom (skip prompt)").option("--no-child-loom", "Force create as independent loom (skip prompt)").option("--body <text>", "Body text for issue (skips AI enhancement)").option("--json", "Output result as JSON").addOption(
|
|
2762
3148
|
new Option("--one-shot <mode>", "One-shot automation mode").choices(["default", "noReview", "bypassPermissions"]).default("default")
|
|
2763
3149
|
).action(async (identifier, options) => {
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
3150
|
+
const executeAction = async () => {
|
|
3151
|
+
try {
|
|
3152
|
+
let finalIdentifier = identifier;
|
|
3153
|
+
if (!finalIdentifier) {
|
|
3154
|
+
if (options.json) {
|
|
3155
|
+
logger.error("JSON mode requires identifier argument");
|
|
3156
|
+
process.exit(1);
|
|
3157
|
+
}
|
|
3158
|
+
const { promptInput } = await import("./prompt-A7GGRHSY.js");
|
|
3159
|
+
finalIdentifier = await promptInput("Enter issue number, PR number (pr/123), or branch name");
|
|
3160
|
+
if (!(finalIdentifier == null ? void 0 : finalIdentifier.trim())) {
|
|
3161
|
+
logger.error("Identifier is required");
|
|
3162
|
+
process.exit(1);
|
|
3163
|
+
}
|
|
3164
|
+
}
|
|
3165
|
+
const settingsManager = new SettingsManager();
|
|
3166
|
+
const settings = await settingsManager.loadSettings();
|
|
3167
|
+
const issueTracker = IssueTrackerFactory.create(settings);
|
|
3168
|
+
const command = new StartCommand(issueTracker, void 0, void 0, settingsManager);
|
|
3169
|
+
const result = await command.execute({ identifier: finalIdentifier, options });
|
|
3170
|
+
if (options.json && result) {
|
|
3171
|
+
console.log(JSON.stringify(result, null, 2));
|
|
2772
3172
|
}
|
|
3173
|
+
process.exit(0);
|
|
3174
|
+
} catch (error) {
|
|
3175
|
+
logger.error(`Failed to start workspace: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3176
|
+
process.exit(1);
|
|
2773
3177
|
}
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
const
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
logger.error(`Failed to start workspace: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2781
|
-
process.exit(1);
|
|
3178
|
+
};
|
|
3179
|
+
if (options.json) {
|
|
3180
|
+
const jsonLogger = createStderrLogger();
|
|
3181
|
+
await withLogger(jsonLogger, executeAction);
|
|
3182
|
+
} else {
|
|
3183
|
+
await executeAction();
|
|
2782
3184
|
}
|
|
2783
3185
|
});
|
|
2784
|
-
program.command("add-issue").alias("a").description("Create and enhance GitHub issue without starting workspace").argument("<description>", "Natural language description of the issue (>50 chars, >2 spaces)").option("--body <text>", "Body text for issue (skips AI enhancement)").action(async (description, options) => {
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
3186
|
+
program.command("add-issue").alias("a").description("Create and enhance GitHub issue without starting workspace").argument("<description>", "Natural language description of the issue (>50 chars, >2 spaces)").option("--body <text>", "Body text for issue (skips AI enhancement)").option("--json", "Output result as JSON").action(async (description, options) => {
|
|
3187
|
+
const executeAction = async () => {
|
|
3188
|
+
try {
|
|
3189
|
+
const settingsManager = new SettingsManager();
|
|
3190
|
+
const settings = await settingsManager.loadSettings();
|
|
3191
|
+
const issueTracker = IssueTrackerFactory.create(settings);
|
|
3192
|
+
const enhancementService = new IssueEnhancementService(issueTracker, new AgentManager(), settingsManager);
|
|
3193
|
+
const command = new AddIssueCommand(enhancementService, settingsManager);
|
|
3194
|
+
const result = await command.execute({
|
|
3195
|
+
description,
|
|
3196
|
+
options: {
|
|
3197
|
+
...options.body && { body: options.body },
|
|
3198
|
+
...options.json && { json: options.json }
|
|
3199
|
+
}
|
|
3200
|
+
});
|
|
3201
|
+
if (options.json && result) {
|
|
3202
|
+
console.log(JSON.stringify(result, null, 2));
|
|
3203
|
+
} else if (result) {
|
|
3204
|
+
const issueNumber = typeof result === "object" ? result.id : result;
|
|
3205
|
+
logger.success(`Issue #${issueNumber} created successfully`);
|
|
3206
|
+
}
|
|
3207
|
+
process.exit(0);
|
|
3208
|
+
} catch (error) {
|
|
3209
|
+
logger.error(`Failed to create issue: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3210
|
+
process.exit(1);
|
|
3211
|
+
}
|
|
3212
|
+
};
|
|
3213
|
+
if (options.json) {
|
|
3214
|
+
const jsonLogger = createStderrLogger();
|
|
3215
|
+
await withLogger(jsonLogger, executeAction);
|
|
3216
|
+
} else {
|
|
3217
|
+
await executeAction();
|
|
2800
3218
|
}
|
|
2801
3219
|
});
|
|
2802
3220
|
program.command("feedback").alias("f").description("Submit feedback/bug report to iloom-cli repository").argument("<description>", "Natural language description of feedback (>50 chars, >2 spaces)").option("--body <text>", "Body text for feedback (added after diagnostics)").action(async (description, options) => {
|
|
2803
3221
|
try {
|
|
2804
|
-
const { FeedbackCommand } = await import("./feedback-
|
|
3222
|
+
const { FeedbackCommand } = await import("./feedback-7PVBQNLJ.js");
|
|
2805
3223
|
const command = new FeedbackCommand();
|
|
2806
3224
|
const feedbackOptions = {};
|
|
2807
3225
|
if (options.body !== void 0) {
|
|
@@ -2818,41 +3236,70 @@ program.command("feedback").alias("f").description("Submit feedback/bug report t
|
|
|
2818
3236
|
process.exit(1);
|
|
2819
3237
|
}
|
|
2820
3238
|
});
|
|
2821
|
-
program.command("enhance").description("Apply enhancement agent to existing GitHub issue").argument("<issue-number>", "GitHub issue identifier to enhance", parseIssueIdentifier).option("--no-browser", "Skip browser opening prompt").option("--author <username>", "GitHub username to tag in questions (for CI usage)").action(async (issueNumber, options) => {
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
3239
|
+
program.command("enhance").description("Apply enhancement agent to existing GitHub issue").argument("<issue-number>", "GitHub issue identifier to enhance", parseIssueIdentifier).option("--no-browser", "Skip browser opening prompt").option("--author <username>", "GitHub username to tag in questions (for CI usage)").option("--json", "Output result as JSON").action(async (issueNumber, options) => {
|
|
3240
|
+
const executeAction = async () => {
|
|
3241
|
+
try {
|
|
3242
|
+
const settingsManager = new SettingsManager();
|
|
3243
|
+
const settings = await settingsManager.loadSettings();
|
|
3244
|
+
const issueTracker = IssueTrackerFactory.create(settings);
|
|
3245
|
+
const command = new EnhanceCommand(issueTracker);
|
|
3246
|
+
const result = await command.execute({
|
|
3247
|
+
issueNumber,
|
|
3248
|
+
options: {
|
|
3249
|
+
noBrowser: options.browser === false,
|
|
3250
|
+
...options.author && { author: options.author },
|
|
3251
|
+
...options.json && { json: options.json }
|
|
3252
|
+
}
|
|
3253
|
+
});
|
|
3254
|
+
if (options.json && result) {
|
|
3255
|
+
console.log(JSON.stringify(result, null, 2));
|
|
3256
|
+
} else {
|
|
3257
|
+
logger.success(`Enhancement process completed for issue #${issueNumber}`);
|
|
2832
3258
|
}
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
3259
|
+
process.exit(0);
|
|
3260
|
+
} catch (error) {
|
|
3261
|
+
logger.error(`Failed to enhance issue: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3262
|
+
process.exit(1);
|
|
3263
|
+
}
|
|
3264
|
+
};
|
|
3265
|
+
if (options.json) {
|
|
3266
|
+
const jsonLogger = createStderrLogger();
|
|
3267
|
+
await withLogger(jsonLogger, executeAction);
|
|
3268
|
+
} else {
|
|
3269
|
+
await executeAction();
|
|
2839
3270
|
}
|
|
2840
3271
|
});
|
|
2841
|
-
program.command("finish").alias("dn").description("Merge work and cleanup workspace").argument("[identifier]", "Issue number, PR number, or branch name (auto-detected if omitted)").option("-f, --force", "Skip confirmation prompts").option("-n, --dry-run", "Preview actions without executing").option("--pr <number>", "Treat input as PR number", parseFloat).option("--skip-build", "Skip post-merge build verification").option("--no-browser", "Skip opening PR in browser (github-pr mode only)").option("--cleanup", "Clean up worktree after PR creation (github-pr mode only)").option("--no-cleanup", "Keep worktree after PR creation (github-pr mode only)").action(async (identifier, options) => {
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
3272
|
+
program.command("finish").alias("dn").description("Merge work and cleanup workspace").argument("[identifier]", "Issue number, PR number, or branch name (auto-detected if omitted)").option("-f, --force", "Skip confirmation prompts").option("-n, --dry-run", "Preview actions without executing").option("--pr <number>", "Treat input as PR number", parseFloat).option("--skip-build", "Skip post-merge build verification").option("--no-browser", "Skip opening PR in browser (github-pr mode only)").option("--cleanup", "Clean up worktree after PR creation (github-pr mode only)").option("--no-cleanup", "Keep worktree after PR creation (github-pr mode only)").option("--json", "Output result as JSON").action(async (identifier, options) => {
|
|
3273
|
+
const executeAction = async () => {
|
|
3274
|
+
try {
|
|
3275
|
+
const settingsManager = new SettingsManager();
|
|
3276
|
+
const settings = await settingsManager.loadSettings();
|
|
3277
|
+
const issueTracker = IssueTrackerFactory.create(settings);
|
|
3278
|
+
const command = new FinishCommand(issueTracker);
|
|
3279
|
+
const result = await command.execute({ identifier, options });
|
|
3280
|
+
if (options.json && result) {
|
|
3281
|
+
console.log(JSON.stringify(result, null, 2));
|
|
3282
|
+
}
|
|
3283
|
+
process.exit(0);
|
|
3284
|
+
} catch (error) {
|
|
3285
|
+
if (options.json) {
|
|
3286
|
+
console.log(JSON.stringify({ success: false, error: error instanceof Error ? error.message : "Unknown error" }, null, 2));
|
|
3287
|
+
} else {
|
|
3288
|
+
logger.error(`Failed to finish workspace: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3289
|
+
}
|
|
3290
|
+
process.exit(1);
|
|
3291
|
+
}
|
|
3292
|
+
};
|
|
3293
|
+
if (options.json) {
|
|
3294
|
+
const jsonLogger = createStderrLogger();
|
|
3295
|
+
await withLogger(jsonLogger, executeAction);
|
|
3296
|
+
} else {
|
|
3297
|
+
await executeAction();
|
|
2851
3298
|
}
|
|
2852
3299
|
});
|
|
2853
3300
|
program.command("rebase").description("Rebase current branch on main with Claude-assisted conflict resolution").option("-f, --force", "Skip confirmation prompts").option("-n, --dry-run", "Preview actions without executing").action(async (options) => {
|
|
2854
3301
|
try {
|
|
2855
|
-
const { RebaseCommand } = await import("./rebase-
|
|
3302
|
+
const { RebaseCommand } = await import("./rebase-4T5FQHNH.js");
|
|
2856
3303
|
const command = new RebaseCommand();
|
|
2857
3304
|
await command.execute(options);
|
|
2858
3305
|
} catch (error) {
|
|
@@ -2864,7 +3311,7 @@ program.command("spin").alias("ignite").description("Launch Claude with auto-det
|
|
|
2864
3311
|
new Option("--one-shot <mode>", "One-shot automation mode").choices(["default", "noReview", "bypassPermissions"]).default("default")
|
|
2865
3312
|
).action(async (options) => {
|
|
2866
3313
|
try {
|
|
2867
|
-
const { IgniteCommand } = await import("./ignite-
|
|
3314
|
+
const { IgniteCommand } = await import("./ignite-3B264M7K.js");
|
|
2868
3315
|
const command = new IgniteCommand();
|
|
2869
3316
|
await command.execute(options.oneShot ?? "default");
|
|
2870
3317
|
} catch (error) {
|
|
@@ -2875,7 +3322,7 @@ program.command("spin").alias("ignite").description("Launch Claude with auto-det
|
|
|
2875
3322
|
program.command("open").description("Open workspace in browser or run CLI tool").argument("[identifier]", "Issue number, PR number, or branch name (auto-detected if omitted)").allowUnknownOption().action(async (identifier, _options, command) => {
|
|
2876
3323
|
try {
|
|
2877
3324
|
const args = (command == null ? void 0 : command.args) ? command.args.slice(identifier ? 1 : 0) : [];
|
|
2878
|
-
const { OpenCommand } = await import("./open-
|
|
3325
|
+
const { OpenCommand } = await import("./open-OGCV32Z4.js");
|
|
2879
3326
|
const cmd = new OpenCommand();
|
|
2880
3327
|
const input = identifier ? { identifier, args } : { args };
|
|
2881
3328
|
await cmd.execute(input);
|
|
@@ -2887,7 +3334,7 @@ program.command("open").description("Open workspace in browser or run CLI tool")
|
|
|
2887
3334
|
program.command("run").description("Run CLI tool or open workspace in browser").argument("[identifier]", "Issue number, PR number, or branch name (auto-detected if omitted)").allowUnknownOption().action(async (identifier, _options, command) => {
|
|
2888
3335
|
try {
|
|
2889
3336
|
const args = (command == null ? void 0 : command.args) ? command.args.slice(identifier ? 1 : 0) : [];
|
|
2890
|
-
const { RunCommand } = await import("./run-
|
|
3337
|
+
const { RunCommand } = await import("./run-HNOP6WE2.js");
|
|
2891
3338
|
const cmd = new RunCommand();
|
|
2892
3339
|
const input = identifier ? { identifier, args } : { args };
|
|
2893
3340
|
await cmd.execute(input);
|
|
@@ -2896,22 +3343,58 @@ program.command("run").description("Run CLI tool or open workspace in browser").
|
|
|
2896
3343
|
process.exit(1);
|
|
2897
3344
|
}
|
|
2898
3345
|
});
|
|
2899
|
-
program.command("
|
|
3346
|
+
program.command("dev-server").alias("dev").description("Start dev server for workspace (foreground)").argument("[identifier]", "Issue number, PR number, or branch name (auto-detected if omitted)").option("--json", "Output as JSON").action(async (identifier, options) => {
|
|
2900
3347
|
try {
|
|
2901
|
-
const {
|
|
2902
|
-
const
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
};
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
3348
|
+
const { DevServerCommand } = await import("./dev-server-JCJGQ3PV.js");
|
|
3349
|
+
const cmd = new DevServerCommand();
|
|
3350
|
+
await cmd.execute({ identifier, json: options == null ? void 0 : options.json });
|
|
3351
|
+
} catch (error) {
|
|
3352
|
+
logger.error(`Failed to start dev server: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3353
|
+
process.exit(1);
|
|
3354
|
+
}
|
|
3355
|
+
});
|
|
3356
|
+
program.command("shell").alias("terminal").description("Open interactive shell with workspace environment").argument("[identifier]", "Issue number, PR number, or branch name (auto-detected if omitted)").action(async (identifier) => {
|
|
3357
|
+
try {
|
|
3358
|
+
const { ShellCommand } = await import("./shell-DE3HKJSM.js");
|
|
3359
|
+
const cmd = new ShellCommand();
|
|
3360
|
+
await cmd.execute({ identifier });
|
|
2910
3361
|
} catch (error) {
|
|
2911
|
-
logger.error(`Failed to
|
|
3362
|
+
logger.error(`Failed to open shell: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2912
3363
|
process.exit(1);
|
|
2913
3364
|
}
|
|
2914
3365
|
});
|
|
3366
|
+
program.command("cleanup").alias("remove").alias("clean").description("Remove workspaces").argument("[identifier]", "Branch name or issue number to cleanup (auto-detected)").option("-l, --list", "List all worktrees").option("-a, --all", "Remove all worktrees (interactive confirmation)").option("-i, --issue <number>", "Cleanup by issue number", parseInt).option("-f, --force", "Skip confirmations and force removal").option("--dry-run", "Show what would be done without doing it").option("--json", "Output result as JSON").action(async (identifier, options) => {
|
|
3367
|
+
const executeAction = async () => {
|
|
3368
|
+
try {
|
|
3369
|
+
const { CleanupCommand } = await import("./cleanup-KDLVTT7M.js");
|
|
3370
|
+
const command = new CleanupCommand();
|
|
3371
|
+
const input = {
|
|
3372
|
+
options: options ?? {}
|
|
3373
|
+
};
|
|
3374
|
+
if (identifier) {
|
|
3375
|
+
input.identifier = identifier;
|
|
3376
|
+
}
|
|
3377
|
+
const result = await command.execute(input);
|
|
3378
|
+
if ((options == null ? void 0 : options.json) && result) {
|
|
3379
|
+
console.log(JSON.stringify(result, null, 2));
|
|
3380
|
+
}
|
|
3381
|
+
process.exit(0);
|
|
3382
|
+
} catch (error) {
|
|
3383
|
+
if (options == null ? void 0 : options.json) {
|
|
3384
|
+
console.log(JSON.stringify({ success: false, error: error instanceof Error ? error.message : "Unknown error" }, null, 2));
|
|
3385
|
+
} else {
|
|
3386
|
+
logger.error(error instanceof Error ? error.message : "Unknown error");
|
|
3387
|
+
}
|
|
3388
|
+
process.exit(1);
|
|
3389
|
+
}
|
|
3390
|
+
};
|
|
3391
|
+
if (options == null ? void 0 : options.json) {
|
|
3392
|
+
const jsonLogger = createStderrLogger();
|
|
3393
|
+
await withLogger(jsonLogger, executeAction);
|
|
3394
|
+
} else {
|
|
3395
|
+
await executeAction();
|
|
3396
|
+
}
|
|
3397
|
+
});
|
|
2915
3398
|
program.command("list").description("Show active workspaces").option("--json", "Output as JSON").action(async (options) => {
|
|
2916
3399
|
try {
|
|
2917
3400
|
const manager = new GitWorktreeManager();
|
|
@@ -2955,9 +3438,20 @@ program.command("list").description("Show active workspaces").option("--json", "
|
|
|
2955
3438
|
process.exit(1);
|
|
2956
3439
|
}
|
|
2957
3440
|
});
|
|
3441
|
+
program.command("projects").description("List configured iloom projects").option("--json", "Output as JSON (default behavior)").action(async (options) => {
|
|
3442
|
+
try {
|
|
3443
|
+
const { ProjectsCommand } = await import("./projects-P55273AB.js");
|
|
3444
|
+
const command = new ProjectsCommand();
|
|
3445
|
+
const result = await command.execute(options);
|
|
3446
|
+
console.log(JSON.stringify(result, null, 2));
|
|
3447
|
+
} catch (error) {
|
|
3448
|
+
logger.error(`Failed to list projects: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3449
|
+
process.exit(1);
|
|
3450
|
+
}
|
|
3451
|
+
});
|
|
2958
3452
|
program.command("init").alias("config").description("Initialize iloom configuration and setup shell autocomplete").argument("[prompt]", 'Custom initial message to send to Claude (defaults to "Help me configure iloom settings.")').action(async (prompt) => {
|
|
2959
3453
|
try {
|
|
2960
|
-
const { InitCommand: InitCommand2 } = await import("./init-
|
|
3454
|
+
const { InitCommand: InitCommand2 } = await import("./init-LBA6NUK2.js");
|
|
2961
3455
|
const command = new InitCommand2();
|
|
2962
3456
|
const trimmedPrompt = prompt == null ? void 0 : prompt.trim();
|
|
2963
3457
|
const customPrompt = trimmedPrompt && trimmedPrompt.length > 0 ? trimmedPrompt : void 0;
|
|
@@ -2969,7 +3463,7 @@ program.command("init").alias("config").description("Initialize iloom configurat
|
|
|
2969
3463
|
});
|
|
2970
3464
|
program.command("contribute").description("Set up local development environment for contributing to iloom").action(async () => {
|
|
2971
3465
|
try {
|
|
2972
|
-
const { ContributeCommand } = await import("./contribute-
|
|
3466
|
+
const { ContributeCommand } = await import("./contribute-HY372S6F.js");
|
|
2973
3467
|
const command = new ContributeCommand();
|
|
2974
3468
|
await command.execute();
|
|
2975
3469
|
} catch (error) {
|
|
@@ -2979,7 +3473,7 @@ program.command("contribute").description("Set up local development environment
|
|
|
2979
3473
|
});
|
|
2980
3474
|
program.command("update").description("Update iloom-cli to the latest version").option("--dry-run", "Show what would be done without actually updating").action(async (options) => {
|
|
2981
3475
|
try {
|
|
2982
|
-
const { UpdateCommand } = await import("./update-
|
|
3476
|
+
const { UpdateCommand } = await import("./update-LETF5ASC.js");
|
|
2983
3477
|
const command = new UpdateCommand();
|
|
2984
3478
|
await command.execute(options);
|
|
2985
3479
|
} catch (error) {
|
|
@@ -2989,8 +3483,8 @@ program.command("update").description("Update iloom-cli to the latest version").
|
|
|
2989
3483
|
});
|
|
2990
3484
|
program.command("test-github").description("Test GitHub integration (Issue #3)").argument("<identifier>", "Issue number or PR number").option("--no-claude", "Skip Claude for branch name generation").action(async (identifier, options) => {
|
|
2991
3485
|
try {
|
|
2992
|
-
const { GitHubService: GitHubService2 } = await import("./GitHubService-
|
|
2993
|
-
const { DefaultBranchNamingService: DefaultBranchNamingService2 } = await import("./BranchNamingService-
|
|
3486
|
+
const { GitHubService: GitHubService2 } = await import("./GitHubService-RPM27GWD.js");
|
|
3487
|
+
const { DefaultBranchNamingService: DefaultBranchNamingService2 } = await import("./BranchNamingService-GCCWB3LK.js");
|
|
2994
3488
|
logger.info("Testing GitHub Integration\n");
|
|
2995
3489
|
const service = new GitHubService2();
|
|
2996
3490
|
const branchNaming = new DefaultBranchNamingService2({ useClaude: options.claude !== false });
|
|
@@ -3048,10 +3542,10 @@ program.command("test-github").description("Test GitHub integration (Issue #3)")
|
|
|
3048
3542
|
});
|
|
3049
3543
|
program.command("test-claude").description("Test Claude integration (Issue #10)").option("--detect", "Test Claude CLI detection").option("--version", "Get Claude CLI version").option("--branch <title>", "Test branch name generation with given title").option("--issue <number>", "Issue number for branch generation", "123").option("--launch <prompt>", "Launch Claude with a prompt (headless)").option("--interactive", "Launch Claude interactively (requires --launch)").option("--template <name>", "Test template loading").action(async (options) => {
|
|
3050
3544
|
try {
|
|
3051
|
-
const { detectClaudeCli: detectClaudeCli2, getClaudeVersion, generateBranchName, launchClaude: launchClaude2 } = await import("./claude-
|
|
3052
|
-
const { PromptTemplateManager } = await import("./PromptTemplateManager-
|
|
3053
|
-
const { ClaudeService } = await import("./ClaudeService-
|
|
3054
|
-
const { ClaudeContextManager: ClaudeContextManager2 } = await import("./ClaudeContextManager-
|
|
3545
|
+
const { detectClaudeCli: detectClaudeCli2, getClaudeVersion, generateBranchName, launchClaude: launchClaude2 } = await import("./claude-ACVXNB6N.js");
|
|
3546
|
+
const { PromptTemplateManager } = await import("./PromptTemplateManager-2TDZAUC6.js");
|
|
3547
|
+
const { ClaudeService } = await import("./ClaudeService-W3SA7HVG.js");
|
|
3548
|
+
const { ClaudeContextManager: ClaudeContextManager2 } = await import("./ClaudeContextManager-DK77227F.js");
|
|
3055
3549
|
logger.info("Testing Claude Integration\n");
|
|
3056
3550
|
if (options.detect) {
|
|
3057
3551
|
logger.info("Detecting Claude CLI...");
|
|
@@ -3186,7 +3680,7 @@ program.command("test-claude").description("Test Claude integration (Issue #10)"
|
|
|
3186
3680
|
});
|
|
3187
3681
|
program.command("test-webserver").description("Test if a web server is running on a workspace port").argument("<issue-number>", "Issue number (port will be calculated as 3000 + issue number)", parseInt).option("--kill", "Kill the web server if detected").action(async (issueNumber, options) => {
|
|
3188
3682
|
try {
|
|
3189
|
-
const { TestWebserverCommand } = await import("./test-webserver-
|
|
3683
|
+
const { TestWebserverCommand } = await import("./test-webserver-VPNLAFZ3.js");
|
|
3190
3684
|
const command = new TestWebserverCommand();
|
|
3191
3685
|
await command.execute({ issueNumber, options });
|
|
3192
3686
|
} catch (error) {
|
|
@@ -3199,7 +3693,7 @@ program.command("test-webserver").description("Test if a web server is running o
|
|
|
3199
3693
|
});
|
|
3200
3694
|
program.command("test-git").description("Test Git integration - findMainWorktreePath() function (reads .iloom/settings.json)").action(async () => {
|
|
3201
3695
|
try {
|
|
3202
|
-
const { TestGitCommand } = await import("./test-git-
|
|
3696
|
+
const { TestGitCommand } = await import("./test-git-YMAE57UP.js");
|
|
3203
3697
|
const command = new TestGitCommand();
|
|
3204
3698
|
await command.execute();
|
|
3205
3699
|
} catch (error) {
|
|
@@ -3212,7 +3706,7 @@ program.command("test-git").description("Test Git integration - findMainWorktree
|
|
|
3212
3706
|
});
|
|
3213
3707
|
program.command("test-tabs").description("Test iTerm2 dual tab functionality - opens two tabs with test commands").action(async () => {
|
|
3214
3708
|
try {
|
|
3215
|
-
const { TestTabsCommand } = await import("./test-tabs-
|
|
3709
|
+
const { TestTabsCommand } = await import("./test-tabs-3SCJWRKT.js");
|
|
3216
3710
|
const command = new TestTabsCommand();
|
|
3217
3711
|
await command.execute();
|
|
3218
3712
|
} catch (error) {
|
|
@@ -3225,7 +3719,7 @@ program.command("test-tabs").description("Test iTerm2 dual tab functionality - o
|
|
|
3225
3719
|
});
|
|
3226
3720
|
program.command("test-prefix").description("Test worktree prefix configuration - preview worktree paths (reads .iloom/settings.json)").action(async () => {
|
|
3227
3721
|
try {
|
|
3228
|
-
const { TestPrefixCommand } = await import("./test-prefix-
|
|
3722
|
+
const { TestPrefixCommand } = await import("./test-prefix-YCKL6CMT.js");
|
|
3229
3723
|
const command = new TestPrefixCommand();
|
|
3230
3724
|
await command.execute();
|
|
3231
3725
|
} catch (error) {
|
|
@@ -3236,11 +3730,40 @@ program.command("test-prefix").description("Test worktree prefix configuration -
|
|
|
3236
3730
|
process.exit(1);
|
|
3237
3731
|
}
|
|
3238
3732
|
});
|
|
3733
|
+
program.command("summary").description("Generate Claude session summary for a loom").argument("[identifier]", "Issue number, PR number (pr/123), or branch name (auto-detected if omitted)").option("--with-comment", "Post summary as a comment to the issue/PR").option("--json", "Output result as JSON").action(async (identifier, options) => {
|
|
3734
|
+
const executeAction = async () => {
|
|
3735
|
+
try {
|
|
3736
|
+
const { SummaryCommand } = await import("./summary-GDT7DTRI.js");
|
|
3737
|
+
const command = new SummaryCommand();
|
|
3738
|
+
const result = await command.execute({ identifier, options });
|
|
3739
|
+
if (options.json && result) {
|
|
3740
|
+
console.log(JSON.stringify(result, null, 2));
|
|
3741
|
+
}
|
|
3742
|
+
process.exit(0);
|
|
3743
|
+
} catch (error) {
|
|
3744
|
+
if (options.json) {
|
|
3745
|
+
console.log(JSON.stringify({ error: error instanceof Error ? error.message : "Unknown error" }, null, 2));
|
|
3746
|
+
} else {
|
|
3747
|
+
logger.error(`Summary failed: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3748
|
+
if (error instanceof Error && error.stack) {
|
|
3749
|
+
logger.debug(error.stack);
|
|
3750
|
+
}
|
|
3751
|
+
}
|
|
3752
|
+
process.exit(1);
|
|
3753
|
+
}
|
|
3754
|
+
};
|
|
3755
|
+
if (options.json) {
|
|
3756
|
+
const jsonLogger = createStderrLogger();
|
|
3757
|
+
await withLogger(jsonLogger, executeAction);
|
|
3758
|
+
} else {
|
|
3759
|
+
await executeAction();
|
|
3760
|
+
}
|
|
3761
|
+
});
|
|
3239
3762
|
program.command("test-neon").description("Test Neon integration and debug configuration").action(async () => {
|
|
3240
3763
|
var _a;
|
|
3241
3764
|
try {
|
|
3242
|
-
const { SettingsManager: SettingsManager2 } = await import("./SettingsManager-
|
|
3243
|
-
const { createNeonProviderFromSettings: createNeonProviderFromSettings2 } = await import("./neon-helpers-
|
|
3765
|
+
const { SettingsManager: SettingsManager2 } = await import("./SettingsManager-FJFU6JJD.js");
|
|
3766
|
+
const { createNeonProviderFromSettings: createNeonProviderFromSettings2 } = await import("./neon-helpers-L5CXQ5CT.js");
|
|
3244
3767
|
logger.info("Testing Neon Integration\n");
|
|
3245
3768
|
logger.info("1. Settings Configuration:");
|
|
3246
3769
|
const settingsManager = new SettingsManager2();
|