@iloom/cli 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -0
- package/dist/{BranchNamingService-TOM2KAUT.js → BranchNamingService-GCCWB3LK.js} +2 -2
- package/dist/ClaudeContextManager-DQFKIMEP.js +16 -0
- package/dist/ClaudeService-CJS32WG2.js +15 -0
- package/dist/{LoomLauncher-SJBZFZXE.js → LoomLauncher-4UG2E4CD.js} +40 -32
- package/dist/LoomLauncher-4UG2E4CD.js.map +1 -0
- package/dist/MetadataManager-WXUVXKUS.js +10 -0
- package/dist/PRManager-7DSIMCAD.js +16 -0
- package/dist/{PromptTemplateManager-2TDZAUC6.js → PromptTemplateManager-72FEOGT6.js} +2 -2
- package/dist/README.md +24 -0
- package/dist/{SettingsManager-FJFU6JJD.js → SettingsManager-XPR4TEQL.js} +2 -2
- package/dist/agents/iloom-issue-analyze-and-plan.md +41 -7
- package/dist/agents/iloom-issue-analyzer.md +38 -8
- package/dist/agents/iloom-issue-complexity-evaluator.md +45 -15
- package/dist/agents/iloom-issue-enhancer.md +60 -18
- package/dist/agents/iloom-issue-implementer.md +29 -7
- package/dist/agents/iloom-issue-planner.md +36 -7
- package/dist/agents/iloom-issue-reviewer.md +30 -7
- package/dist/{chunk-M5XUCTTJ.js → chunk-3CMGCRB5.js} +2 -2
- package/dist/{chunk-KM3W7YQX.js → chunk-4YTILIIH.js} +8 -9
- package/dist/chunk-4YTILIIH.js.map +1 -0
- package/dist/{chunk-HVGQP44L.js → chunk-AS2IRKLU.js} +2 -2
- package/dist/{chunk-ADDNFQJ4.js → chunk-CDQEK2WD.js} +6 -6
- package/dist/{chunk-74VMN2KC.js → chunk-DKQ4SUII.js} +16 -1
- package/dist/chunk-DKQ4SUII.js.map +1 -0
- package/dist/{chunk-LTNDJMTH.js → chunk-GVRO4PWE.js} +13 -9
- package/dist/chunk-GVRO4PWE.js.map +1 -0
- package/dist/{chunk-HHDSIE72.js → chunk-HABINPX2.js} +72 -16
- package/dist/{chunk-HHDSIE72.js.map → chunk-HABINPX2.js.map} +1 -1
- package/dist/{chunk-TR5MC2U6.js → chunk-LN4H3A6A.js} +66 -7
- package/dist/chunk-LN4H3A6A.js.map +1 -0
- package/dist/{chunk-VWNS6DH5.js → chunk-OOU3DKNT.js} +13 -7
- package/dist/chunk-OOU3DKNT.js.map +1 -0
- package/dist/chunk-P2ZQ5LKB.js +347 -0
- package/dist/chunk-P2ZQ5LKB.js.map +1 -0
- package/dist/{chunk-P2WZIDF3.js → chunk-QIUJPPJQ.js} +2 -2
- package/dist/{chunk-HD5SUKI2.js → chunk-RFUOIUQF.js} +49 -6
- package/dist/{chunk-HD5SUKI2.js.map → chunk-RFUOIUQF.js.map} +1 -1
- package/dist/{chunk-OF7BNW4D.js → chunk-RJKMF6BC.js} +30 -4
- package/dist/chunk-RJKMF6BC.js.map +1 -0
- package/dist/{chunk-O7WHXLCB.js → chunk-RNZMHJK7.js} +18 -4
- package/dist/chunk-RNZMHJK7.js.map +1 -0
- package/dist/{chunk-75B2HZZ5.js → chunk-RUC7OULH.js} +2 -2
- package/dist/{chunk-F4J6KEL6.js → chunk-S65T4O6I.js} +2 -2
- package/dist/{chunk-NFVFVYAP.js → chunk-T5IIUG4Z.js} +109 -20
- package/dist/chunk-T5IIUG4Z.js.map +1 -0
- package/dist/{chunk-JJUPY5MM.js → chunk-VAYGNQTE.js} +2 -2
- package/dist/{chunk-S44CHE3G.js → chunk-VTXCGKV5.js} +2 -2
- package/dist/{chunk-MLS5FAV7.js → chunk-YZTDGPFB.js} +21 -1
- package/dist/chunk-YZTDGPFB.js.map +1 -0
- package/dist/{chunk-3NFBZRPR.js → chunk-Z5NXYJIG.js} +19 -1
- package/dist/chunk-Z5NXYJIG.js.map +1 -0
- package/dist/{claude-X7EBJRB2.js → claude-ACVXNB6N.js} +4 -4
- package/dist/{cleanup-7QVPYBJJ.js → cleanup-MIDJVSIU.js} +18 -18
- package/dist/cli.js +293 -372
- package/dist/cli.js.map +1 -1
- package/dist/{contribute-RZYCYUDX.js → contribute-RS3DO3WP.js} +4 -4
- package/dist/{dev-server-LOY7YWCP.js → dev-server-ASH7HJVI.js} +28 -14
- package/dist/dev-server-ASH7HJVI.js.map +1 -0
- package/dist/{feedback-562KPG5U.js → feedback-RVIGHBJG.js} +9 -8
- package/dist/{feedback-562KPG5U.js.map → feedback-RVIGHBJG.js.map} +1 -1
- package/dist/{git-OXJACVAU.js → git-OQAPUPLP.js} +16 -6
- package/dist/git-OQAPUPLP.js.map +1 -0
- package/dist/{ignite-VSIPGKKG.js → ignite-XJALWFAT.js} +60 -25
- package/dist/ignite-XJALWFAT.js.map +1 -0
- package/dist/index.d.ts +60 -7
- package/dist/index.js +107 -7
- package/dist/index.js.map +1 -1
- package/dist/init-F6PFMSU5.js +21 -0
- package/dist/init-F6PFMSU5.js.map +1 -0
- package/dist/mcp/recap-server.js +264 -0
- package/dist/mcp/recap-server.js.map +1 -0
- package/dist/{open-CX7HUE26.js → open-KW4NTLXH.js} +15 -16
- package/dist/{open-CX7HUE26.js.map → open-KW4NTLXH.js.map} +1 -1
- package/dist/{projects-6DTNDVLH.js → projects-QEAEBAT2.js} +2 -2
- package/dist/prompts/init-prompt.txt +31 -72
- package/dist/prompts/issue-prompt.txt +115 -15
- package/dist/prompts/pr-prompt.txt +49 -1
- package/dist/prompts/regular-prompt.txt +80 -20
- package/dist/{rebase-55URTXZC.js → rebase-WZHHE5LU.js} +9 -9
- package/dist/recap-33NPZ3ZO.js +117 -0
- package/dist/recap-33NPZ3ZO.js.map +1 -0
- package/dist/{run-DP2U2CA2.js → run-HRYQ7TR7.js} +15 -16
- package/dist/{run-DP2U2CA2.js.map → run-HRYQ7TR7.js.map} +1 -1
- package/dist/schema/settings.schema.json +13 -2
- package/dist/shell-JMU5XTHW.js +240 -0
- package/dist/shell-JMU5XTHW.js.map +1 -0
- package/dist/{summary-J3CJSM7L.js → summary-4SSGGH7N.js} +20 -12
- package/dist/summary-4SSGGH7N.js.map +1 -0
- package/dist/{test-git-QLAIBJLX.js → test-git-6SAIRBUD.js} +4 -4
- package/dist/{test-prefix-6YM2ZOON.js → test-prefix-RLVRK5ZD.js} +4 -4
- package/dist/{test-tabs-JGO3VOXJ.js → test-tabs-3SCJWRKT.js} +3 -3
- package/package.json +1 -1
- package/dist/ClaudeContextManager-VEGJTS5E.js +0 -16
- package/dist/ClaudeService-ICSHJMQ5.js +0 -15
- package/dist/LoomLauncher-SJBZFZXE.js.map +0 -1
- package/dist/chunk-3NFBZRPR.js.map +0 -1
- package/dist/chunk-74VMN2KC.js.map +0 -1
- package/dist/chunk-KM3W7YQX.js.map +0 -1
- package/dist/chunk-LTNDJMTH.js.map +0 -1
- package/dist/chunk-MLS5FAV7.js.map +0 -1
- package/dist/chunk-NFVFVYAP.js.map +0 -1
- package/dist/chunk-O7WHXLCB.js.map +0 -1
- package/dist/chunk-OF7BNW4D.js.map +0 -1
- package/dist/chunk-QRBOPFAA.js +0 -48
- package/dist/chunk-QRBOPFAA.js.map +0 -1
- package/dist/chunk-TR5MC2U6.js.map +0 -1
- package/dist/chunk-VWNS6DH5.js.map +0 -1
- package/dist/dev-server-LOY7YWCP.js.map +0 -1
- package/dist/ignite-VSIPGKKG.js.map +0 -1
- package/dist/init-SCR2LQ4A.js +0 -21
- package/dist/summary-J3CJSM7L.js.map +0 -1
- /package/dist/{BranchNamingService-TOM2KAUT.js.map → BranchNamingService-GCCWB3LK.js.map} +0 -0
- /package/dist/{ClaudeContextManager-VEGJTS5E.js.map → ClaudeContextManager-DQFKIMEP.js.map} +0 -0
- /package/dist/{ClaudeService-ICSHJMQ5.js.map → ClaudeService-CJS32WG2.js.map} +0 -0
- /package/dist/{PromptTemplateManager-2TDZAUC6.js.map → MetadataManager-WXUVXKUS.js.map} +0 -0
- /package/dist/{SettingsManager-FJFU6JJD.js.map → PRManager-7DSIMCAD.js.map} +0 -0
- /package/dist/{claude-X7EBJRB2.js.map → PromptTemplateManager-72FEOGT6.js.map} +0 -0
- /package/dist/{git-OXJACVAU.js.map → SettingsManager-XPR4TEQL.js.map} +0 -0
- /package/dist/{chunk-M5XUCTTJ.js.map → chunk-3CMGCRB5.js.map} +0 -0
- /package/dist/{chunk-HVGQP44L.js.map → chunk-AS2IRKLU.js.map} +0 -0
- /package/dist/{chunk-ADDNFQJ4.js.map → chunk-CDQEK2WD.js.map} +0 -0
- /package/dist/{chunk-P2WZIDF3.js.map → chunk-QIUJPPJQ.js.map} +0 -0
- /package/dist/{chunk-75B2HZZ5.js.map → chunk-RUC7OULH.js.map} +0 -0
- /package/dist/{chunk-F4J6KEL6.js.map → chunk-S65T4O6I.js.map} +0 -0
- /package/dist/{chunk-JJUPY5MM.js.map → chunk-VAYGNQTE.js.map} +0 -0
- /package/dist/{chunk-S44CHE3G.js.map → chunk-VTXCGKV5.js.map} +0 -0
- /package/dist/{init-SCR2LQ4A.js.map → claude-ACVXNB6N.js.map} +0 -0
- /package/dist/{cleanup-7QVPYBJJ.js.map → cleanup-MIDJVSIU.js.map} +0 -0
- /package/dist/{contribute-RZYCYUDX.js.map → contribute-RS3DO3WP.js.map} +0 -0
- /package/dist/{projects-6DTNDVLH.js.map → projects-QEAEBAT2.js.map} +0 -0
- /package/dist/{rebase-55URTXZC.js.map → rebase-WZHHE5LU.js.map} +0 -0
- /package/dist/{test-git-QLAIBJLX.js.map → test-git-6SAIRBUD.js.map} +0 -0
- /package/dist/{test-prefix-6YM2ZOON.js.map → test-prefix-RLVRK5ZD.js.map} +0 -0
- /package/dist/{test-tabs-JGO3VOXJ.js.map → test-tabs-3SCJWRKT.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -1,97 +1,102 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
SessionSummaryService
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-HABINPX2.js";
|
|
5
|
+
import {
|
|
6
|
+
FirstRunManager,
|
|
7
|
+
IssueTrackerFactory,
|
|
8
|
+
generateIssueManagementMcpConfig
|
|
9
|
+
} from "./chunk-RFUOIUQF.js";
|
|
10
|
+
import "./chunk-QHA67Q7A.js";
|
|
5
11
|
import {
|
|
6
12
|
CLIIsolationManager,
|
|
7
13
|
DatabaseManager,
|
|
8
14
|
EnvironmentManager,
|
|
9
15
|
LoomManager,
|
|
10
16
|
ResourceCleanup
|
|
11
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-T5IIUG4Z.js";
|
|
18
|
+
import {
|
|
19
|
+
detectPackageManager,
|
|
20
|
+
installDependencies,
|
|
21
|
+
runScript
|
|
22
|
+
} from "./chunk-VBFDVGAE.js";
|
|
23
|
+
import {
|
|
24
|
+
ProcessManager
|
|
25
|
+
} from "./chunk-VU3QMIP2.js";
|
|
26
|
+
import {
|
|
27
|
+
IdentifierParser
|
|
28
|
+
} from "./chunk-AS2IRKLU.js";
|
|
29
|
+
import {
|
|
30
|
+
createNeonProviderFromSettings
|
|
31
|
+
} from "./chunk-UNXRACJ7.js";
|
|
12
32
|
import {
|
|
13
33
|
InitCommand,
|
|
14
34
|
ShellCompletion
|
|
15
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-4YTILIIH.js";
|
|
16
36
|
import "./chunk-UYWAESOT.js";
|
|
17
37
|
import {
|
|
18
38
|
IssueEnhancementService,
|
|
19
39
|
capitalizeFirstLetter
|
|
20
|
-
} from "./chunk-
|
|
21
|
-
import {
|
|
22
|
-
MergeManager
|
|
23
|
-
} from "./chunk-LTNDJMTH.js";
|
|
24
|
-
import {
|
|
25
|
-
FirstRunManager,
|
|
26
|
-
IssueTrackerFactory,
|
|
27
|
-
generateIssueManagementMcpConfig
|
|
28
|
-
} from "./chunk-HD5SUKI2.js";
|
|
29
|
-
import "./chunk-QHA67Q7A.js";
|
|
40
|
+
} from "./chunk-VTXCGKV5.js";
|
|
30
41
|
import {
|
|
31
42
|
AgentManager
|
|
32
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-RNZMHJK7.js";
|
|
33
44
|
import {
|
|
34
|
-
|
|
35
|
-
} from "./chunk-
|
|
45
|
+
ProjectCapabilityDetector
|
|
46
|
+
} from "./chunk-EBISESAP.js";
|
|
36
47
|
import {
|
|
37
|
-
|
|
38
|
-
|
|
48
|
+
hasScript,
|
|
49
|
+
readPackageJson
|
|
50
|
+
} from "./chunk-2ZPFJQ3B.js";
|
|
39
51
|
import {
|
|
40
|
-
|
|
41
|
-
} from "./chunk-
|
|
52
|
+
MergeManager
|
|
53
|
+
} from "./chunk-GVRO4PWE.js";
|
|
42
54
|
import {
|
|
43
55
|
GitWorktreeManager
|
|
44
|
-
} from "./chunk-
|
|
45
|
-
import {
|
|
46
|
-
detectPackageManager,
|
|
47
|
-
installDependencies,
|
|
48
|
-
runScript
|
|
49
|
-
} from "./chunk-VBFDVGAE.js";
|
|
56
|
+
} from "./chunk-3CMGCRB5.js";
|
|
50
57
|
import {
|
|
51
|
-
|
|
52
|
-
} from "./chunk-
|
|
53
|
-
import "./chunk-ADDNFQJ4.js";
|
|
58
|
+
PRManager
|
|
59
|
+
} from "./chunk-P2ZQ5LKB.js";
|
|
54
60
|
import {
|
|
55
|
-
|
|
56
|
-
} from "./chunk-
|
|
61
|
+
openBrowser
|
|
62
|
+
} from "./chunk-YETJNRQM.js";
|
|
57
63
|
import {
|
|
58
|
-
|
|
59
|
-
|
|
64
|
+
getConfiguredRepoFromSettings,
|
|
65
|
+
hasMultipleRemotes
|
|
66
|
+
} from "./chunk-PSFVTBM7.js";
|
|
60
67
|
import {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
68
|
+
ClaudeContextManager
|
|
69
|
+
} from "./chunk-S65T4O6I.js";
|
|
70
|
+
import "./chunk-CDQEK2WD.js";
|
|
71
|
+
import "./chunk-DKQ4SUII.js";
|
|
64
72
|
import {
|
|
65
73
|
extractSettingsOverrides
|
|
66
74
|
} from "./chunk-GYCR2LOU.js";
|
|
67
75
|
import {
|
|
68
|
-
|
|
69
|
-
} from "./chunk-
|
|
70
|
-
import {
|
|
71
|
-
getConfiguredRepoFromSettings,
|
|
72
|
-
getEffectivePRTargetRemote,
|
|
73
|
-
hasMultipleRemotes,
|
|
74
|
-
parseGitRemotes
|
|
75
|
-
} from "./chunk-PSFVTBM7.js";
|
|
76
|
+
DefaultBranchNamingService
|
|
77
|
+
} from "./chunk-QIUJPPJQ.js";
|
|
76
78
|
import {
|
|
77
79
|
executeGitCommand,
|
|
78
80
|
extractIssueNumber,
|
|
79
81
|
findMainWorktreePathWithSettings,
|
|
82
|
+
findPlaceholderCommitSha,
|
|
83
|
+
getMergeTargetBranch,
|
|
80
84
|
getRepoRoot,
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
} from "./chunk-
|
|
85
|
+
isPlaceholderCommit,
|
|
86
|
+
pushBranchToRemote,
|
|
87
|
+
removePlaceholderCommitFromHead,
|
|
88
|
+
removePlaceholderCommitFromHistory
|
|
89
|
+
} from "./chunk-LN4H3A6A.js";
|
|
86
90
|
import {
|
|
87
91
|
SettingsManager
|
|
88
|
-
} from "./chunk-
|
|
92
|
+
} from "./chunk-OOU3DKNT.js";
|
|
93
|
+
import {
|
|
94
|
+
MetadataManager
|
|
95
|
+
} from "./chunk-YZTDGPFB.js";
|
|
89
96
|
import {
|
|
90
97
|
GitHubService
|
|
91
98
|
} from "./chunk-OEGECBFS.js";
|
|
92
|
-
import
|
|
93
|
-
executeGhCommand
|
|
94
|
-
} from "./chunk-KO2FOMHL.js";
|
|
99
|
+
import "./chunk-KO2FOMHL.js";
|
|
95
100
|
import {
|
|
96
101
|
promptCommitAction,
|
|
97
102
|
promptConfirmation,
|
|
@@ -101,16 +106,15 @@ import "./chunk-WUQQNE63.js";
|
|
|
101
106
|
import {
|
|
102
107
|
detectClaudeCli,
|
|
103
108
|
launchClaude
|
|
104
|
-
} from "./chunk-
|
|
105
|
-
import "./chunk-
|
|
109
|
+
} from "./chunk-RUC7OULH.js";
|
|
110
|
+
import "./chunk-VAYGNQTE.js";
|
|
106
111
|
import {
|
|
107
112
|
loadEnvIntoProcess
|
|
108
|
-
} from "./chunk-
|
|
113
|
+
} from "./chunk-Z5NXYJIG.js";
|
|
109
114
|
import {
|
|
110
115
|
getLogger,
|
|
111
116
|
withLogger
|
|
112
117
|
} from "./chunk-6UIGZD2N.js";
|
|
113
|
-
import "./chunk-74VMN2KC.js";
|
|
114
118
|
import {
|
|
115
119
|
createStderrLogger,
|
|
116
120
|
logger
|
|
@@ -1155,6 +1159,12 @@ import { execa } from "execa";
|
|
|
1155
1159
|
function isRunningInVSCode() {
|
|
1156
1160
|
return process.env.TERM_PROGRAM === "vscode";
|
|
1157
1161
|
}
|
|
1162
|
+
function isRunningInCursor() {
|
|
1163
|
+
return !!process.env.CURSOR_TRACE_ID;
|
|
1164
|
+
}
|
|
1165
|
+
function isRunningInAntigravity() {
|
|
1166
|
+
return !!process.env.ANTIGRAVITY_CLI_ALIAS;
|
|
1167
|
+
}
|
|
1158
1168
|
async function isVSCodeAvailable() {
|
|
1159
1169
|
try {
|
|
1160
1170
|
await execa("command", ["-v", "code"], {
|
|
@@ -1167,6 +1177,30 @@ async function isVSCodeAvailable() {
|
|
|
1167
1177
|
return false;
|
|
1168
1178
|
}
|
|
1169
1179
|
}
|
|
1180
|
+
async function isCursorAvailable() {
|
|
1181
|
+
try {
|
|
1182
|
+
await execa("command", ["-v", "cursor"], {
|
|
1183
|
+
shell: true,
|
|
1184
|
+
timeout: 5e3
|
|
1185
|
+
});
|
|
1186
|
+
return true;
|
|
1187
|
+
} catch (error) {
|
|
1188
|
+
logger.debug("Cursor CLI not available", { error });
|
|
1189
|
+
return false;
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
async function isAntigravityAvailable() {
|
|
1193
|
+
try {
|
|
1194
|
+
await execa("command", ["-v", "agy"], {
|
|
1195
|
+
shell: true,
|
|
1196
|
+
timeout: 5e3
|
|
1197
|
+
});
|
|
1198
|
+
return true;
|
|
1199
|
+
} catch (error) {
|
|
1200
|
+
logger.debug("Antigravity CLI not available", { error });
|
|
1201
|
+
return false;
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1170
1204
|
|
|
1171
1205
|
// src/types/index.ts
|
|
1172
1206
|
var UserAbortedCommitError = class extends Error {
|
|
@@ -1251,8 +1285,12 @@ var CommitManager = class {
|
|
|
1251
1285
|
await executeGitCommand(commitArgs, { cwd: worktreePath });
|
|
1252
1286
|
} else {
|
|
1253
1287
|
getLogger().info("Opening editor for commit message review...");
|
|
1254
|
-
if (
|
|
1255
|
-
await this.
|
|
1288
|
+
if (isRunningInAntigravity() && await isAntigravityAvailable()) {
|
|
1289
|
+
await this.commitWithExternalEditor(worktreePath, message, options, "agy", "Antigravity");
|
|
1290
|
+
} else if (isRunningInCursor() && await isCursorAvailable()) {
|
|
1291
|
+
await this.commitWithExternalEditor(worktreePath, message, options, "cursor", "Cursor");
|
|
1292
|
+
} else if (isRunningInVSCode() && await isVSCodeAvailable()) {
|
|
1293
|
+
await this.commitWithExternalEditor(worktreePath, message, options, "code", "VSCode");
|
|
1256
1294
|
} else {
|
|
1257
1295
|
const commitArgs = ["commit", "-e", "-m", message];
|
|
1258
1296
|
if (options.skipVerify) {
|
|
@@ -1279,10 +1317,11 @@ var CommitManager = class {
|
|
|
1279
1317
|
}
|
|
1280
1318
|
}
|
|
1281
1319
|
/**
|
|
1282
|
-
* Commit with
|
|
1283
|
-
*
|
|
1320
|
+
* Commit with external editor CLI (VSCode, Cursor, Antigravity, etc.)
|
|
1321
|
+
* Handles file creation, editing, and commit to ensure the file opens
|
|
1322
|
+
* in the current editor window (preserves IPC context)
|
|
1284
1323
|
*/
|
|
1285
|
-
async
|
|
1324
|
+
async commitWithExternalEditor(worktreePath, message, options, cliCommand, editorName) {
|
|
1286
1325
|
const commitMsgPath = join(worktreePath, ".COMMIT_EDITMSG");
|
|
1287
1326
|
const initialContent = `${message}
|
|
1288
1327
|
|
|
@@ -1293,8 +1332,8 @@ var CommitManager = class {
|
|
|
1293
1332
|
`;
|
|
1294
1333
|
await writeFile(commitMsgPath, initialContent, "utf-8");
|
|
1295
1334
|
try {
|
|
1296
|
-
getLogger().debug(`Opening commit message in
|
|
1297
|
-
await execa2(
|
|
1335
|
+
getLogger().debug(`Opening commit message in ${editorName}: ${commitMsgPath}`);
|
|
1336
|
+
await execa2(cliCommand, ["--wait", commitMsgPath], {
|
|
1298
1337
|
cwd: worktreePath,
|
|
1299
1338
|
stdio: "inherit"
|
|
1300
1339
|
});
|
|
@@ -1628,267 +1667,6 @@ Run '${runCommand}' to see detailed errors.`
|
|
|
1628
1667
|
}
|
|
1629
1668
|
};
|
|
1630
1669
|
|
|
1631
|
-
// src/lib/PRManager.ts
|
|
1632
|
-
var PRManager = class {
|
|
1633
|
-
constructor(settings) {
|
|
1634
|
-
this.settings = settings;
|
|
1635
|
-
}
|
|
1636
|
-
/**
|
|
1637
|
-
* Check if a PR already exists for the given branch
|
|
1638
|
-
* @param branchName - Branch to check
|
|
1639
|
-
* @param cwd - Working directory
|
|
1640
|
-
* @returns Existing PR info or null if none found
|
|
1641
|
-
*/
|
|
1642
|
-
async checkForExistingPR(branchName, cwd) {
|
|
1643
|
-
try {
|
|
1644
|
-
const prList = await executeGhCommand(
|
|
1645
|
-
["pr", "list", "--head", branchName, "--state", "open", "--json", "number,url"],
|
|
1646
|
-
cwd ? { cwd } : void 0
|
|
1647
|
-
);
|
|
1648
|
-
if (prList.length > 0) {
|
|
1649
|
-
return prList[0] ?? null;
|
|
1650
|
-
}
|
|
1651
|
-
return null;
|
|
1652
|
-
} catch (error) {
|
|
1653
|
-
getLogger().debug("Error checking for existing PR", { error });
|
|
1654
|
-
return null;
|
|
1655
|
-
}
|
|
1656
|
-
}
|
|
1657
|
-
/**
|
|
1658
|
-
* Generate PR body using Claude if available, otherwise use simple template
|
|
1659
|
-
* @param issueNumber - Issue number to include in body
|
|
1660
|
-
* @param worktreePath - Path to worktree for context
|
|
1661
|
-
* @returns PR body markdown
|
|
1662
|
-
*/
|
|
1663
|
-
async generatePRBody(issueNumber, worktreePath) {
|
|
1664
|
-
const hasClaudeCli = await detectClaudeCli();
|
|
1665
|
-
if (hasClaudeCli) {
|
|
1666
|
-
try {
|
|
1667
|
-
const prompt = this.buildPRBodyPrompt(issueNumber);
|
|
1668
|
-
const body2 = await launchClaude(prompt, {
|
|
1669
|
-
headless: true,
|
|
1670
|
-
addDir: worktreePath,
|
|
1671
|
-
timeout: 3e4
|
|
1672
|
-
});
|
|
1673
|
-
if (body2 && typeof body2 === "string" && body2.trim()) {
|
|
1674
|
-
const sanitized = this.sanitizeClaudeOutput(body2);
|
|
1675
|
-
if (sanitized) {
|
|
1676
|
-
return sanitized;
|
|
1677
|
-
}
|
|
1678
|
-
}
|
|
1679
|
-
} catch (error) {
|
|
1680
|
-
getLogger().debug("Claude PR body generation failed, using template", { error });
|
|
1681
|
-
}
|
|
1682
|
-
}
|
|
1683
|
-
let body = "This PR contains changes from the iloom workflow.\n\n";
|
|
1684
|
-
if (issueNumber) {
|
|
1685
|
-
body += `Fixes #${issueNumber}`;
|
|
1686
|
-
}
|
|
1687
|
-
return body;
|
|
1688
|
-
}
|
|
1689
|
-
/**
|
|
1690
|
-
* Build structured XML prompt for PR body generation
|
|
1691
|
-
* Uses XML format for clear task definition and output expectations
|
|
1692
|
-
*/
|
|
1693
|
-
buildPRBodyPrompt(issueNumber) {
|
|
1694
|
-
const issueContext = issueNumber ? `
|
|
1695
|
-
<IssueContext>
|
|
1696
|
-
This PR is associated with GitHub issue #${issueNumber}.
|
|
1697
|
-
Include "Fixes #${issueNumber}" at the end of the body on its own line.
|
|
1698
|
-
</IssueContext>` : "";
|
|
1699
|
-
return `<Task>
|
|
1700
|
-
You are a software engineer writing a pull request body for this repository.
|
|
1701
|
-
Examine the changes in the git repository and generate a concise, professional PR description.
|
|
1702
|
-
</Task>
|
|
1703
|
-
|
|
1704
|
-
<Requirements>
|
|
1705
|
-
<Format>Write 2-3 sentences summarizing what was changed and why.${issueNumber ? `
|
|
1706
|
-
|
|
1707
|
-
End with "Fixes #${issueNumber}" on its own line.` : ""}</Format>
|
|
1708
|
-
<Tone>Professional and concise</Tone>
|
|
1709
|
-
<Focus>Summarize the changes and their purpose</Focus>
|
|
1710
|
-
<NoMeta>CRITICAL: Do NOT include ANY explanatory text, analysis, or meta-commentary. Output ONLY the raw PR body text.</NoMeta>
|
|
1711
|
-
<Examples>
|
|
1712
|
-
Good: "Add user authentication with JWT tokens to secure the API endpoints. This includes login and registration endpoints with proper password hashing.
|
|
1713
|
-
|
|
1714
|
-
Fixes #42"
|
|
1715
|
-
Good: "Fix navigation bug in sidebar menu that caused incorrect highlighting on nested routes."
|
|
1716
|
-
Bad: "Here's the PR body:
|
|
1717
|
-
|
|
1718
|
-
---
|
|
1719
|
-
|
|
1720
|
-
Add user authentication..."
|
|
1721
|
-
Bad: "Based on the changes, I'll write: Fix navigation bug..."
|
|
1722
|
-
</Examples>
|
|
1723
|
-
${issueContext}
|
|
1724
|
-
</Requirements>
|
|
1725
|
-
|
|
1726
|
-
<Output>
|
|
1727
|
-
IMPORTANT: Your entire response will be used directly as the GitHub pull request body.
|
|
1728
|
-
Do not include any explanatory text, headers, or separators before or after the body.
|
|
1729
|
-
Start your response immediately with the PR body text.
|
|
1730
|
-
</Output>`;
|
|
1731
|
-
}
|
|
1732
|
-
/**
|
|
1733
|
-
* Sanitize Claude output to remove meta-commentary and clean formatting
|
|
1734
|
-
* Handles cases where Claude includes explanatory text despite instructions
|
|
1735
|
-
*/
|
|
1736
|
-
sanitizeClaudeOutput(rawOutput) {
|
|
1737
|
-
let cleaned = rawOutput.trim();
|
|
1738
|
-
const metaPatterns = [
|
|
1739
|
-
/^.*?based on.*?changes.*?:/i,
|
|
1740
|
-
/^.*?looking at.*?files.*?:/i,
|
|
1741
|
-
/^.*?examining.*?:/i,
|
|
1742
|
-
/^.*?analyzing.*?:/i,
|
|
1743
|
-
/^.*?i'll.*?generate.*?:/i,
|
|
1744
|
-
/^.*?let me.*?:/i,
|
|
1745
|
-
/^.*?here.*?is.*?(?:the\s+)?(?:pr|pull request).*?body.*?:/i,
|
|
1746
|
-
/^.*?here's.*?(?:the\s+)?(?:pr|pull request).*?body.*?:/i
|
|
1747
|
-
];
|
|
1748
|
-
for (const pattern of metaPatterns) {
|
|
1749
|
-
cleaned = cleaned.replace(pattern, "").trim();
|
|
1750
|
-
}
|
|
1751
|
-
cleaned = cleaned.replace(/^[-=]{3,}\s*/m, "").trim();
|
|
1752
|
-
if (cleaned.includes(":")) {
|
|
1753
|
-
const colonIndex = cleaned.indexOf(":");
|
|
1754
|
-
const beforeColon = cleaned.substring(0, colonIndex).trim().toLowerCase();
|
|
1755
|
-
const metaIndicators = [
|
|
1756
|
-
"here is the pr body",
|
|
1757
|
-
"here is the pull request body",
|
|
1758
|
-
"pr body",
|
|
1759
|
-
"pull request body",
|
|
1760
|
-
"here is",
|
|
1761
|
-
"here's",
|
|
1762
|
-
"the body should be",
|
|
1763
|
-
"i suggest",
|
|
1764
|
-
"my suggestion"
|
|
1765
|
-
];
|
|
1766
|
-
const isMetaCommentary = metaIndicators.some((indicator) => beforeColon.includes(indicator));
|
|
1767
|
-
if (isMetaCommentary) {
|
|
1768
|
-
const afterColon = cleaned.substring(colonIndex + 1).trim();
|
|
1769
|
-
const afterSeparator = afterColon.replace(/^[-=]{3,}\s*/m, "").trim();
|
|
1770
|
-
if (afterSeparator && afterSeparator.length > 10) {
|
|
1771
|
-
cleaned = afterSeparator;
|
|
1772
|
-
}
|
|
1773
|
-
}
|
|
1774
|
-
}
|
|
1775
|
-
if (cleaned.startsWith('"') && cleaned.endsWith('"') || cleaned.startsWith("'") && cleaned.endsWith("'")) {
|
|
1776
|
-
cleaned = cleaned.slice(1, -1).trim();
|
|
1777
|
-
}
|
|
1778
|
-
return cleaned;
|
|
1779
|
-
}
|
|
1780
|
-
/**
|
|
1781
|
-
* Create a GitHub PR for the branch
|
|
1782
|
-
* @param branchName - Branch to create PR from (used as --head)
|
|
1783
|
-
* @param title - PR title
|
|
1784
|
-
* @param body - PR body
|
|
1785
|
-
* @param baseBranch - Base branch to target (usually main/master)
|
|
1786
|
-
* @param cwd - Working directory
|
|
1787
|
-
* @returns PR URL
|
|
1788
|
-
*/
|
|
1789
|
-
async createPR(branchName, title, body, baseBranch, cwd) {
|
|
1790
|
-
try {
|
|
1791
|
-
const targetRemote = await getEffectivePRTargetRemote(this.settings, cwd);
|
|
1792
|
-
let headValue = branchName;
|
|
1793
|
-
if (targetRemote !== "origin") {
|
|
1794
|
-
const remotes = await parseGitRemotes(cwd);
|
|
1795
|
-
const originRemote = remotes.find((r) => r.name === "origin");
|
|
1796
|
-
if (originRemote) {
|
|
1797
|
-
headValue = `${originRemote.owner}:${branchName}`;
|
|
1798
|
-
getLogger().debug(`Fork workflow detected, using head: ${headValue}`);
|
|
1799
|
-
}
|
|
1800
|
-
}
|
|
1801
|
-
const args = ["pr", "create", "--head", headValue, "--title", title, "--body", body, "--base", baseBranch];
|
|
1802
|
-
if (targetRemote !== "origin") {
|
|
1803
|
-
const repo = await getConfiguredRepoFromSettings(this.settings, cwd);
|
|
1804
|
-
args.push("--repo", repo);
|
|
1805
|
-
}
|
|
1806
|
-
const result = await executeGhCommand(args, cwd ? { cwd } : void 0);
|
|
1807
|
-
const url = typeof result === "string" ? result.trim() : String(result).trim();
|
|
1808
|
-
if (!url.includes("github.com") || !url.includes("/pull/")) {
|
|
1809
|
-
throw new Error(`Unexpected response from gh pr create: ${url}`);
|
|
1810
|
-
}
|
|
1811
|
-
return url;
|
|
1812
|
-
} catch (error) {
|
|
1813
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1814
|
-
if (errorMessage.includes("Head sha can't be blank") || errorMessage.includes("No commits between")) {
|
|
1815
|
-
throw new Error(
|
|
1816
|
-
`Failed to create pull request: ${errorMessage}
|
|
1817
|
-
|
|
1818
|
-
This error typically occurs when:
|
|
1819
|
-
- The branch was not fully pushed to the remote
|
|
1820
|
-
- There's a race condition between push and PR creation
|
|
1821
|
-
- The branch has no commits ahead of the base branch
|
|
1822
|
-
|
|
1823
|
-
Try running: git push -u origin ${branchName}
|
|
1824
|
-
Then retry: il finish`
|
|
1825
|
-
);
|
|
1826
|
-
}
|
|
1827
|
-
throw new Error(`Failed to create pull request: ${errorMessage}`);
|
|
1828
|
-
}
|
|
1829
|
-
}
|
|
1830
|
-
/**
|
|
1831
|
-
* Open PR URL in browser
|
|
1832
|
-
* @param url - PR URL to open
|
|
1833
|
-
*/
|
|
1834
|
-
async openPRInBrowser(url) {
|
|
1835
|
-
try {
|
|
1836
|
-
await openBrowser(url);
|
|
1837
|
-
getLogger().debug("Opened PR in browser", { url });
|
|
1838
|
-
} catch (error) {
|
|
1839
|
-
getLogger().warn("Failed to open PR in browser", { error });
|
|
1840
|
-
}
|
|
1841
|
-
}
|
|
1842
|
-
/**
|
|
1843
|
-
* Complete PR workflow: check for existing, create if needed, optionally open in browser
|
|
1844
|
-
* @param branchName - Branch to create PR from
|
|
1845
|
-
* @param title - PR title
|
|
1846
|
-
* @param issueNumber - Optional issue number for body generation
|
|
1847
|
-
* @param baseBranch - Base branch to target
|
|
1848
|
-
* @param worktreePath - Path to worktree
|
|
1849
|
-
* @param openInBrowser - Whether to open PR in browser
|
|
1850
|
-
* @returns PR creation result
|
|
1851
|
-
*/
|
|
1852
|
-
async createOrOpenPR(branchName, title, issueNumber, baseBranch, worktreePath, openInBrowser) {
|
|
1853
|
-
const existingPR = await this.checkForExistingPR(branchName, worktreePath);
|
|
1854
|
-
if (existingPR) {
|
|
1855
|
-
getLogger().info(`Pull request already exists: ${existingPR.url}`);
|
|
1856
|
-
if (openInBrowser) {
|
|
1857
|
-
await this.openPRInBrowser(existingPR.url);
|
|
1858
|
-
}
|
|
1859
|
-
return {
|
|
1860
|
-
url: existingPR.url,
|
|
1861
|
-
number: existingPR.number,
|
|
1862
|
-
wasExisting: true
|
|
1863
|
-
};
|
|
1864
|
-
}
|
|
1865
|
-
const body = await this.generatePRBody(issueNumber, worktreePath);
|
|
1866
|
-
getLogger().info("Creating pull request...");
|
|
1867
|
-
const url = await this.createPR(branchName, title, body, baseBranch, worktreePath);
|
|
1868
|
-
const prNumber = this.extractPRNumberFromUrl(url);
|
|
1869
|
-
if (openInBrowser) {
|
|
1870
|
-
await this.openPRInBrowser(url);
|
|
1871
|
-
}
|
|
1872
|
-
return {
|
|
1873
|
-
url,
|
|
1874
|
-
number: prNumber,
|
|
1875
|
-
wasExisting: false
|
|
1876
|
-
};
|
|
1877
|
-
}
|
|
1878
|
-
/**
|
|
1879
|
-
* Extract PR number from GitHub PR URL
|
|
1880
|
-
* @param url - PR URL (e.g., https://github.com/owner/repo/pull/123)
|
|
1881
|
-
* @returns PR number
|
|
1882
|
-
*/
|
|
1883
|
-
extractPRNumberFromUrl(url) {
|
|
1884
|
-
const match = url.match(/\/pull\/(\d+)/);
|
|
1885
|
-
if (match == null ? void 0 : match[1]) {
|
|
1886
|
-
return parseInt(match[1], 10);
|
|
1887
|
-
}
|
|
1888
|
-
throw new Error(`Could not extract PR number from URL: ${url}`);
|
|
1889
|
-
}
|
|
1890
|
-
};
|
|
1891
|
-
|
|
1892
1670
|
// src/commands/finish.ts
|
|
1893
1671
|
import path3 from "path";
|
|
1894
1672
|
var FinishCommand = class {
|
|
@@ -1929,7 +1707,7 @@ var FinishCommand = class {
|
|
|
1929
1707
|
const neonProvider = createNeonProviderFromSettings(settings);
|
|
1930
1708
|
const databaseManager = new DatabaseManager(neonProvider, environmentManager, databaseUrlEnvVarName);
|
|
1931
1709
|
const cliIsolationManager = new CLIIsolationManager();
|
|
1932
|
-
const { DefaultBranchNamingService: DefaultBranchNamingService2 } = await import("./BranchNamingService-
|
|
1710
|
+
const { DefaultBranchNamingService: DefaultBranchNamingService2 } = await import("./BranchNamingService-GCCWB3LK.js");
|
|
1933
1711
|
this.loomManager ??= new LoomManager(
|
|
1934
1712
|
this.gitWorktreeManager,
|
|
1935
1713
|
this.issueTracker,
|
|
@@ -2266,10 +2044,22 @@ var FinishCommand = class {
|
|
|
2266
2044
|
}
|
|
2267
2045
|
/**
|
|
2268
2046
|
* Execute workflow for issues and branches (merge into main)
|
|
2269
|
-
* This is the
|
|
2047
|
+
* This is the workflow: rebase → validate → commit → merge → cleanup
|
|
2270
2048
|
*/
|
|
2271
2049
|
async executeIssueWorkflow(parsed, options, worktree, result) {
|
|
2272
|
-
var _a, _b;
|
|
2050
|
+
var _a, _b, _c;
|
|
2051
|
+
getLogger().info("Rebasing branch on main...");
|
|
2052
|
+
const mergeOptions = {
|
|
2053
|
+
dryRun: options.dryRun ?? false,
|
|
2054
|
+
force: options.force ?? false
|
|
2055
|
+
};
|
|
2056
|
+
await this.mergeManager.rebaseOnMain(worktree.path, mergeOptions);
|
|
2057
|
+
getLogger().success("Branch rebased successfully");
|
|
2058
|
+
result.operations.push({
|
|
2059
|
+
type: "rebase",
|
|
2060
|
+
message: "Branch rebased on main",
|
|
2061
|
+
success: true
|
|
2062
|
+
});
|
|
2273
2063
|
if (!options.dryRun) {
|
|
2274
2064
|
getLogger().info("Running pre-merge validations...");
|
|
2275
2065
|
await this.validationRunner.runValidations(worktree.path, {
|
|
@@ -2344,18 +2134,92 @@ var FinishCommand = class {
|
|
|
2344
2134
|
await this.executeGitHubPRWorkflow(parsed, options, worktree, settings, result);
|
|
2345
2135
|
return;
|
|
2346
2136
|
}
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2137
|
+
if (mergeBehavior.mode === "github-draft-pr") {
|
|
2138
|
+
if (!this.issueTracker.supportsPullRequests) {
|
|
2139
|
+
throw new Error(
|
|
2140
|
+
`The 'github-draft-pr' merge mode requires a GitHub-compatible issue tracker. Your provider (${this.issueTracker.providerName}) does not support pull requests.`
|
|
2141
|
+
);
|
|
2142
|
+
}
|
|
2143
|
+
const { MetadataManager: MetadataManager2 } = await import("./MetadataManager-WXUVXKUS.js");
|
|
2144
|
+
const metadataManager = new MetadataManager2();
|
|
2145
|
+
const metadata = await metadataManager.readMetadata(worktree.path);
|
|
2146
|
+
getLogger().debug(`Draft PR mode: worktree=${worktree.path}, draftPrNumber=${(metadata == null ? void 0 : metadata.draftPrNumber) ?? "none"}`);
|
|
2147
|
+
if (!(metadata == null ? void 0 : metadata.draftPrNumber)) {
|
|
2148
|
+
getLogger().warn("No draft PR found in metadata, creating new PR...");
|
|
2149
|
+
await this.executeGitHubPRWorkflow(parsed, options, worktree, settings, result);
|
|
2150
|
+
return;
|
|
2151
|
+
}
|
|
2152
|
+
const isHeadPlaceholder = await isPlaceholderCommit(worktree.path);
|
|
2153
|
+
const placeholderSha = await findPlaceholderCommitSha(worktree.path);
|
|
2154
|
+
getLogger().debug(`Placeholder detection: isHead=${isHeadPlaceholder}, sha=${placeholderSha ?? "none"}`);
|
|
2155
|
+
if (isHeadPlaceholder) {
|
|
2156
|
+
const commitCount = await executeGitCommand(
|
|
2157
|
+
["rev-list", "--count", "HEAD"],
|
|
2158
|
+
{ cwd: worktree.path }
|
|
2159
|
+
);
|
|
2160
|
+
if (parseInt(commitCount.trim(), 10) <= 1) {
|
|
2161
|
+
throw new Error(
|
|
2162
|
+
"Cannot finish draft PR: no changes have been committed.\nPlease make at least one commit before finishing."
|
|
2163
|
+
);
|
|
2164
|
+
}
|
|
2165
|
+
if (!options.dryRun) {
|
|
2166
|
+
getLogger().info("Removing placeholder commit from HEAD...");
|
|
2167
|
+
await removePlaceholderCommitFromHead(worktree.path);
|
|
2168
|
+
} else {
|
|
2169
|
+
getLogger().info("[DRY RUN] Would remove placeholder commit from HEAD");
|
|
2170
|
+
}
|
|
2171
|
+
} else if (placeholderSha) {
|
|
2172
|
+
const commitsAfterPlaceholder = await executeGitCommand(
|
|
2173
|
+
["rev-list", "--count", `${placeholderSha}..HEAD`],
|
|
2174
|
+
{ cwd: worktree.path }
|
|
2175
|
+
);
|
|
2176
|
+
if (parseInt(commitsAfterPlaceholder.trim(), 10) === 0) {
|
|
2177
|
+
throw new Error(
|
|
2178
|
+
"Cannot finish draft PR: no changes have been committed after the placeholder.\nPlease make at least one commit before finishing."
|
|
2179
|
+
);
|
|
2180
|
+
}
|
|
2181
|
+
if (!options.dryRun) {
|
|
2182
|
+
getLogger().info("Removing placeholder commit from history...");
|
|
2183
|
+
await removePlaceholderCommitFromHistory(worktree.path, placeholderSha);
|
|
2184
|
+
} else {
|
|
2185
|
+
getLogger().info("[DRY RUN] Would remove placeholder commit from history");
|
|
2186
|
+
}
|
|
2187
|
+
}
|
|
2188
|
+
const needsForceWithLease = isHeadPlaceholder || placeholderSha;
|
|
2189
|
+
if (!options.dryRun) {
|
|
2190
|
+
getLogger().info("Pushing final commits to remote...");
|
|
2191
|
+
if (needsForceWithLease) {
|
|
2192
|
+
await executeGitCommand(["push", "--force-with-lease", "origin", worktree.branch], { cwd: worktree.path });
|
|
2193
|
+
} else {
|
|
2194
|
+
await pushBranchToRemote(worktree.branch, worktree.path, { dryRun: false });
|
|
2195
|
+
}
|
|
2196
|
+
} else {
|
|
2197
|
+
if (needsForceWithLease) {
|
|
2198
|
+
getLogger().info("[DRY RUN] Would force push final commits to remote (history rewritten)");
|
|
2199
|
+
} else {
|
|
2200
|
+
getLogger().info("[DRY RUN] Would push final commits to remote");
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
2203
|
+
const prManager = new PRManager(settings);
|
|
2204
|
+
if (!options.dryRun) {
|
|
2205
|
+
await prManager.markPRReady(metadata.draftPrNumber, worktree.path);
|
|
2206
|
+
getLogger().success(`PR #${metadata.draftPrNumber} marked as ready for review`);
|
|
2207
|
+
} else {
|
|
2208
|
+
getLogger().info(`[DRY RUN] Would mark PR #${metadata.draftPrNumber} as ready for review`);
|
|
2209
|
+
}
|
|
2210
|
+
const prUrl = (_c = metadata.prUrls) == null ? void 0 : _c[String(metadata.draftPrNumber)];
|
|
2211
|
+
if (prUrl) {
|
|
2212
|
+
result.prUrl = prUrl;
|
|
2213
|
+
}
|
|
2214
|
+
result.operations.push({
|
|
2215
|
+
type: "pr-ready",
|
|
2216
|
+
message: `PR #${metadata.draftPrNumber} marked as ready for review`,
|
|
2217
|
+
success: true
|
|
2218
|
+
});
|
|
2219
|
+
await this.generateSessionSummaryIfConfigured(parsed, worktree, options, metadata.draftPrNumber);
|
|
2220
|
+
await this.handlePRCleanupPrompt(parsed, options, worktree, result);
|
|
2221
|
+
return;
|
|
2222
|
+
}
|
|
2359
2223
|
getLogger().info("Performing fast-forward merge...");
|
|
2360
2224
|
await this.mergeManager.performFastForwardMerge(worktree.branch, worktree.path, mergeOptions);
|
|
2361
2225
|
getLogger().success("Fast-forward merge completed successfully");
|
|
@@ -2483,17 +2347,17 @@ var FinishCommand = class {
|
|
|
2483
2347
|
getLogger().debug("Could not fetch issue title, using branch name", { error });
|
|
2484
2348
|
}
|
|
2485
2349
|
}
|
|
2350
|
+
const baseBranch = await getMergeTargetBranch(worktree.path);
|
|
2486
2351
|
if (options.dryRun) {
|
|
2487
2352
|
getLogger().info("[DRY RUN] Would create GitHub PR");
|
|
2488
2353
|
getLogger().info(` Title: ${prTitle}`);
|
|
2489
|
-
getLogger().info(` Base: ${
|
|
2354
|
+
getLogger().info(` Base: ${baseBranch}`);
|
|
2490
2355
|
finishResult.operations.push({
|
|
2491
2356
|
type: "pr-creation",
|
|
2492
2357
|
message: "Would create GitHub PR (dry-run)",
|
|
2493
2358
|
success: true
|
|
2494
2359
|
});
|
|
2495
2360
|
} else {
|
|
2496
|
-
const baseBranch = settings.mainBranch ?? "main";
|
|
2497
2361
|
const openInBrowser = options.noBrowser !== true;
|
|
2498
2362
|
const prResult = await prManager.createOrOpenPR(
|
|
2499
2363
|
worktree.branch,
|
|
@@ -2519,7 +2383,7 @@ var FinishCommand = class {
|
|
|
2519
2383
|
});
|
|
2520
2384
|
}
|
|
2521
2385
|
finishResult.prUrl = prResult.url;
|
|
2522
|
-
await this.generateSessionSummaryIfConfigured(parsed, worktree, options);
|
|
2386
|
+
await this.generateSessionSummaryIfConfigured(parsed, worktree, options, prResult.number);
|
|
2523
2387
|
await this.handlePRCleanupPrompt(parsed, options, worktree, finishResult);
|
|
2524
2388
|
}
|
|
2525
2389
|
}
|
|
@@ -2542,8 +2406,8 @@ var FinishCommand = class {
|
|
|
2542
2406
|
getLogger().info("");
|
|
2543
2407
|
const shouldCleanup = await promptConfirmation(
|
|
2544
2408
|
"Clean up worktree now?",
|
|
2545
|
-
|
|
2546
|
-
// Default to keeping worktree
|
|
2409
|
+
true
|
|
2410
|
+
// Default to keeping worktree - won't delete if unmerged changes
|
|
2547
2411
|
);
|
|
2548
2412
|
if (shouldCleanup) {
|
|
2549
2413
|
await this.performWorktreeCleanup(parsed, options, worktree, finishResult);
|
|
@@ -2684,8 +2548,13 @@ var FinishCommand = class {
|
|
|
2684
2548
|
* This ensures the finish workflow continues even if summary generation fails
|
|
2685
2549
|
*
|
|
2686
2550
|
* In dry-run mode: generates summary and shows preview, but doesn't post
|
|
2551
|
+
*
|
|
2552
|
+
* @param parsed - The parsed input identifying the issue/PR being finished
|
|
2553
|
+
* @param worktree - The worktree being finished
|
|
2554
|
+
* @param options - Finish options (including dryRun flag)
|
|
2555
|
+
* @param prNumber - Optional PR number - when provided, summary is posted to the PR instead of the issue
|
|
2687
2556
|
*/
|
|
2688
|
-
async generateSessionSummaryIfConfigured(parsed, worktree, options) {
|
|
2557
|
+
async generateSessionSummaryIfConfigured(parsed, worktree, options, prNumber) {
|
|
2689
2558
|
if (parsed.type === "branch") {
|
|
2690
2559
|
return;
|
|
2691
2560
|
}
|
|
@@ -2716,7 +2585,8 @@ var FinishCommand = class {
|
|
|
2716
2585
|
worktreePath: worktree.path,
|
|
2717
2586
|
issueNumber: parsed.number ?? 0,
|
|
2718
2587
|
branchName: worktree.branch,
|
|
2719
|
-
loomType: parsed.type
|
|
2588
|
+
loomType: parsed.type,
|
|
2589
|
+
...prNumber !== void 0 && { prNumber }
|
|
2720
2590
|
});
|
|
2721
2591
|
}
|
|
2722
2592
|
/**
|
|
@@ -2955,7 +2825,10 @@ function formatLoomForJson(worktree, mainWorktreePath, metadata) {
|
|
|
2955
2825
|
description: (metadata == null ? void 0 : metadata.description) ?? null,
|
|
2956
2826
|
created_at: (metadata == null ? void 0 : metadata.created_at) ?? null,
|
|
2957
2827
|
issueTracker: (metadata == null ? void 0 : metadata.issueTracker) ?? null,
|
|
2958
|
-
colorHex: (metadata == null ? void 0 : metadata.colorHex) ?? null
|
|
2828
|
+
colorHex: (metadata == null ? void 0 : metadata.colorHex) ?? null,
|
|
2829
|
+
projectPath: (metadata == null ? void 0 : metadata.projectPath) ?? null,
|
|
2830
|
+
issueUrls: (metadata == null ? void 0 : metadata.issueUrls) ?? {},
|
|
2831
|
+
prUrls: (metadata == null ? void 0 : metadata.prUrls) ?? {}
|
|
2959
2832
|
};
|
|
2960
2833
|
}
|
|
2961
2834
|
function formatLoomsForJson(worktrees, mainWorktreePath, metadata) {
|
|
@@ -3003,6 +2876,7 @@ async function validateSettingsForCommand(command) {
|
|
|
3003
2876
|
if (bypassCommands.includes(commandName)) {
|
|
3004
2877
|
return;
|
|
3005
2878
|
}
|
|
2879
|
+
const warnOnlyCommands = ["list", "projects"];
|
|
3006
2880
|
try {
|
|
3007
2881
|
const settingsManager = new SettingsManager();
|
|
3008
2882
|
const settings = await settingsManager.loadSettings();
|
|
@@ -3012,6 +2886,10 @@ async function validateSettingsForCommand(command) {
|
|
|
3012
2886
|
return;
|
|
3013
2887
|
}
|
|
3014
2888
|
} catch (error) {
|
|
2889
|
+
if (warnOnlyCommands.includes(commandName)) {
|
|
2890
|
+
logger.warn(`Configuration warning: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
2891
|
+
return;
|
|
2892
|
+
}
|
|
3015
2893
|
logger.error(`Configuration error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3016
2894
|
logger.info("Please fix your .iloom/settings.json file and try again.");
|
|
3017
2895
|
process.exit(1);
|
|
@@ -3081,14 +2959,14 @@ async function autoLaunchInitForMultipleRemotes() {
|
|
|
3081
2959
|
await waitForKeypress2("Press any key to start configuration...");
|
|
3082
2960
|
logger.info("");
|
|
3083
2961
|
try {
|
|
3084
|
-
const { InitCommand: InitCommand2 } = await import("./init-
|
|
2962
|
+
const { InitCommand: InitCommand2 } = await import("./init-F6PFMSU5.js");
|
|
3085
2963
|
const initCommand = new InitCommand2();
|
|
3086
2964
|
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.";
|
|
3087
2965
|
await initCommand.execute(customInitialMessage);
|
|
3088
2966
|
logger.info("");
|
|
3089
2967
|
logger.info("Configuration complete! Continuing with your original command...");
|
|
3090
2968
|
logger.info("");
|
|
3091
|
-
const { SettingsManager: SettingsManager2 } = await import("./SettingsManager-
|
|
2969
|
+
const { SettingsManager: SettingsManager2 } = await import("./SettingsManager-XPR4TEQL.js");
|
|
3092
2970
|
const settingsManager = new SettingsManager2();
|
|
3093
2971
|
const settings = await settingsManager.loadSettings();
|
|
3094
2972
|
const { hasMultipleRemotes: hasMultipleRemotes2 } = await import("./remote-73TZ2ADI.js");
|
|
@@ -3182,7 +3060,7 @@ program.command("add-issue").alias("a").description("Create and enhance GitHub i
|
|
|
3182
3060
|
});
|
|
3183
3061
|
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) => {
|
|
3184
3062
|
try {
|
|
3185
|
-
const { FeedbackCommand } = await import("./feedback-
|
|
3063
|
+
const { FeedbackCommand } = await import("./feedback-RVIGHBJG.js");
|
|
3186
3064
|
const command = new FeedbackCommand();
|
|
3187
3065
|
const feedbackOptions = {};
|
|
3188
3066
|
if (options.body !== void 0) {
|
|
@@ -3262,7 +3140,7 @@ program.command("finish").alias("dn").description("Merge work and cleanup worksp
|
|
|
3262
3140
|
});
|
|
3263
3141
|
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) => {
|
|
3264
3142
|
try {
|
|
3265
|
-
const { RebaseCommand } = await import("./rebase-
|
|
3143
|
+
const { RebaseCommand } = await import("./rebase-WZHHE5LU.js");
|
|
3266
3144
|
const command = new RebaseCommand();
|
|
3267
3145
|
await command.execute(options);
|
|
3268
3146
|
} catch (error) {
|
|
@@ -3274,7 +3152,7 @@ program.command("spin").alias("ignite").description("Launch Claude with auto-det
|
|
|
3274
3152
|
new Option("--one-shot <mode>", "One-shot automation mode").choices(["default", "noReview", "bypassPermissions"]).default("default")
|
|
3275
3153
|
).action(async (options) => {
|
|
3276
3154
|
try {
|
|
3277
|
-
const { IgniteCommand } = await import("./ignite-
|
|
3155
|
+
const { IgniteCommand } = await import("./ignite-XJALWFAT.js");
|
|
3278
3156
|
const command = new IgniteCommand();
|
|
3279
3157
|
await command.execute(options.oneShot ?? "default");
|
|
3280
3158
|
} catch (error) {
|
|
@@ -3285,7 +3163,7 @@ program.command("spin").alias("ignite").description("Launch Claude with auto-det
|
|
|
3285
3163
|
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) => {
|
|
3286
3164
|
try {
|
|
3287
3165
|
const args = (command == null ? void 0 : command.args) ? command.args.slice(identifier ? 1 : 0) : [];
|
|
3288
|
-
const { OpenCommand } = await import("./open-
|
|
3166
|
+
const { OpenCommand } = await import("./open-KW4NTLXH.js");
|
|
3289
3167
|
const cmd = new OpenCommand();
|
|
3290
3168
|
const input = identifier ? { identifier, args } : { args };
|
|
3291
3169
|
await cmd.execute(input);
|
|
@@ -3297,7 +3175,7 @@ program.command("open").description("Open workspace in browser or run CLI tool")
|
|
|
3297
3175
|
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) => {
|
|
3298
3176
|
try {
|
|
3299
3177
|
const args = (command == null ? void 0 : command.args) ? command.args.slice(identifier ? 1 : 0) : [];
|
|
3300
|
-
const { RunCommand } = await import("./run-
|
|
3178
|
+
const { RunCommand } = await import("./run-HRYQ7TR7.js");
|
|
3301
3179
|
const cmd = new RunCommand();
|
|
3302
3180
|
const input = identifier ? { identifier, args } : { args };
|
|
3303
3181
|
await cmd.execute(input);
|
|
@@ -3308,7 +3186,7 @@ program.command("run").description("Run CLI tool or open workspace in browser").
|
|
|
3308
3186
|
});
|
|
3309
3187
|
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) => {
|
|
3310
3188
|
try {
|
|
3311
|
-
const { DevServerCommand } = await import("./dev-server-
|
|
3189
|
+
const { DevServerCommand } = await import("./dev-server-ASH7HJVI.js");
|
|
3312
3190
|
const cmd = new DevServerCommand();
|
|
3313
3191
|
await cmd.execute({ identifier, json: options == null ? void 0 : options.json });
|
|
3314
3192
|
} catch (error) {
|
|
@@ -3316,10 +3194,20 @@ program.command("dev-server").alias("dev").description("Start dev server for wor
|
|
|
3316
3194
|
process.exit(1);
|
|
3317
3195
|
}
|
|
3318
3196
|
});
|
|
3197
|
+
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) => {
|
|
3198
|
+
try {
|
|
3199
|
+
const { ShellCommand } = await import("./shell-JMU5XTHW.js");
|
|
3200
|
+
const cmd = new ShellCommand();
|
|
3201
|
+
await cmd.execute({ identifier });
|
|
3202
|
+
} catch (error) {
|
|
3203
|
+
logger.error(`Failed to open shell: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3204
|
+
process.exit(1);
|
|
3205
|
+
}
|
|
3206
|
+
});
|
|
3319
3207
|
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) => {
|
|
3320
3208
|
const executeAction = async () => {
|
|
3321
3209
|
try {
|
|
3322
|
-
const { CleanupCommand } = await import("./cleanup-
|
|
3210
|
+
const { CleanupCommand } = await import("./cleanup-MIDJVSIU.js");
|
|
3323
3211
|
const command = new CleanupCommand();
|
|
3324
3212
|
const input = {
|
|
3325
3213
|
options: options ?? {}
|
|
@@ -3359,7 +3247,11 @@ program.command("list").description("Show active workspaces").option("--json", "
|
|
|
3359
3247
|
metadata.set(worktree.path, loomMetadata);
|
|
3360
3248
|
}
|
|
3361
3249
|
if (options.json) {
|
|
3362
|
-
|
|
3250
|
+
let mainWorktreePath;
|
|
3251
|
+
try {
|
|
3252
|
+
mainWorktreePath = await findMainWorktreePathWithSettings();
|
|
3253
|
+
} catch {
|
|
3254
|
+
}
|
|
3363
3255
|
console.log(JSON.stringify(formatLoomsForJson(worktrees, mainWorktreePath, metadata), null, 2));
|
|
3364
3256
|
return;
|
|
3365
3257
|
}
|
|
@@ -3393,7 +3285,7 @@ program.command("list").description("Show active workspaces").option("--json", "
|
|
|
3393
3285
|
});
|
|
3394
3286
|
program.command("projects").description("List configured iloom projects").option("--json", "Output as JSON (default behavior)").action(async (options) => {
|
|
3395
3287
|
try {
|
|
3396
|
-
const { ProjectsCommand } = await import("./projects-
|
|
3288
|
+
const { ProjectsCommand } = await import("./projects-QEAEBAT2.js");
|
|
3397
3289
|
const command = new ProjectsCommand();
|
|
3398
3290
|
const result = await command.execute(options);
|
|
3399
3291
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -3402,9 +3294,9 @@ program.command("projects").description("List configured iloom projects").option
|
|
|
3402
3294
|
process.exit(1);
|
|
3403
3295
|
}
|
|
3404
3296
|
});
|
|
3405
|
-
program.command("init").alias("config").description("Initialize iloom configuration
|
|
3297
|
+
program.command("init").alias("config").description("Initialize iloom configuration").argument("[prompt]", 'Custom initial message to send to Claude (defaults to "Help me configure iloom settings.")').action(async (prompt) => {
|
|
3406
3298
|
try {
|
|
3407
|
-
const { InitCommand: InitCommand2 } = await import("./init-
|
|
3299
|
+
const { InitCommand: InitCommand2 } = await import("./init-F6PFMSU5.js");
|
|
3408
3300
|
const command = new InitCommand2();
|
|
3409
3301
|
const trimmedPrompt = prompt == null ? void 0 : prompt.trim();
|
|
3410
3302
|
const customPrompt = trimmedPrompt && trimmedPrompt.length > 0 ? trimmedPrompt : void 0;
|
|
@@ -3416,7 +3308,7 @@ program.command("init").alias("config").description("Initialize iloom configurat
|
|
|
3416
3308
|
});
|
|
3417
3309
|
program.command("contribute").description("Set up local development environment for contributing to iloom").action(async () => {
|
|
3418
3310
|
try {
|
|
3419
|
-
const { ContributeCommand } = await import("./contribute-
|
|
3311
|
+
const { ContributeCommand } = await import("./contribute-RS3DO3WP.js");
|
|
3420
3312
|
const command = new ContributeCommand();
|
|
3421
3313
|
await command.execute();
|
|
3422
3314
|
} catch (error) {
|
|
@@ -3437,7 +3329,7 @@ program.command("update").description("Update iloom-cli to the latest version").
|
|
|
3437
3329
|
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) => {
|
|
3438
3330
|
try {
|
|
3439
3331
|
const { GitHubService: GitHubService2 } = await import("./GitHubService-RPM27GWD.js");
|
|
3440
|
-
const { DefaultBranchNamingService: DefaultBranchNamingService2 } = await import("./BranchNamingService-
|
|
3332
|
+
const { DefaultBranchNamingService: DefaultBranchNamingService2 } = await import("./BranchNamingService-GCCWB3LK.js");
|
|
3441
3333
|
logger.info("Testing GitHub Integration\n");
|
|
3442
3334
|
const service = new GitHubService2();
|
|
3443
3335
|
const branchNaming = new DefaultBranchNamingService2({ useClaude: options.claude !== false });
|
|
@@ -3495,10 +3387,10 @@ program.command("test-github").description("Test GitHub integration (Issue #3)")
|
|
|
3495
3387
|
});
|
|
3496
3388
|
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) => {
|
|
3497
3389
|
try {
|
|
3498
|
-
const { detectClaudeCli: detectClaudeCli2, getClaudeVersion, generateBranchName, launchClaude: launchClaude2 } = await import("./claude-
|
|
3499
|
-
const { PromptTemplateManager } = await import("./PromptTemplateManager-
|
|
3500
|
-
const { ClaudeService } = await import("./ClaudeService-
|
|
3501
|
-
const { ClaudeContextManager: ClaudeContextManager2 } = await import("./ClaudeContextManager-
|
|
3390
|
+
const { detectClaudeCli: detectClaudeCli2, getClaudeVersion, generateBranchName, launchClaude: launchClaude2 } = await import("./claude-ACVXNB6N.js");
|
|
3391
|
+
const { PromptTemplateManager } = await import("./PromptTemplateManager-72FEOGT6.js");
|
|
3392
|
+
const { ClaudeService } = await import("./ClaudeService-CJS32WG2.js");
|
|
3393
|
+
const { ClaudeContextManager: ClaudeContextManager2 } = await import("./ClaudeContextManager-DQFKIMEP.js");
|
|
3502
3394
|
logger.info("Testing Claude Integration\n");
|
|
3503
3395
|
if (options.detect) {
|
|
3504
3396
|
logger.info("Detecting Claude CLI...");
|
|
@@ -3646,7 +3538,7 @@ program.command("test-webserver").description("Test if a web server is running o
|
|
|
3646
3538
|
});
|
|
3647
3539
|
program.command("test-git").description("Test Git integration - findMainWorktreePath() function (reads .iloom/settings.json)").action(async () => {
|
|
3648
3540
|
try {
|
|
3649
|
-
const { TestGitCommand } = await import("./test-git-
|
|
3541
|
+
const { TestGitCommand } = await import("./test-git-6SAIRBUD.js");
|
|
3650
3542
|
const command = new TestGitCommand();
|
|
3651
3543
|
await command.execute();
|
|
3652
3544
|
} catch (error) {
|
|
@@ -3659,7 +3551,7 @@ program.command("test-git").description("Test Git integration - findMainWorktree
|
|
|
3659
3551
|
});
|
|
3660
3552
|
program.command("test-tabs").description("Test iTerm2 dual tab functionality - opens two tabs with test commands").action(async () => {
|
|
3661
3553
|
try {
|
|
3662
|
-
const { TestTabsCommand } = await import("./test-tabs-
|
|
3554
|
+
const { TestTabsCommand } = await import("./test-tabs-3SCJWRKT.js");
|
|
3663
3555
|
const command = new TestTabsCommand();
|
|
3664
3556
|
await command.execute();
|
|
3665
3557
|
} catch (error) {
|
|
@@ -3672,7 +3564,7 @@ program.command("test-tabs").description("Test iTerm2 dual tab functionality - o
|
|
|
3672
3564
|
});
|
|
3673
3565
|
program.command("test-prefix").description("Test worktree prefix configuration - preview worktree paths (reads .iloom/settings.json)").action(async () => {
|
|
3674
3566
|
try {
|
|
3675
|
-
const { TestPrefixCommand } = await import("./test-prefix-
|
|
3567
|
+
const { TestPrefixCommand } = await import("./test-prefix-RLVRK5ZD.js");
|
|
3676
3568
|
const command = new TestPrefixCommand();
|
|
3677
3569
|
await command.execute();
|
|
3678
3570
|
} catch (error) {
|
|
@@ -3686,7 +3578,7 @@ program.command("test-prefix").description("Test worktree prefix configuration -
|
|
|
3686
3578
|
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) => {
|
|
3687
3579
|
const executeAction = async () => {
|
|
3688
3580
|
try {
|
|
3689
|
-
const { SummaryCommand } = await import("./summary-
|
|
3581
|
+
const { SummaryCommand } = await import("./summary-4SSGGH7N.js");
|
|
3690
3582
|
const command = new SummaryCommand();
|
|
3691
3583
|
const result = await command.execute({ identifier, options });
|
|
3692
3584
|
if (options.json && result) {
|
|
@@ -3712,10 +3604,39 @@ program.command("summary").description("Generate Claude session summary for a lo
|
|
|
3712
3604
|
await executeAction();
|
|
3713
3605
|
}
|
|
3714
3606
|
});
|
|
3607
|
+
program.command("recap").description("Get recap for a loom (defaults to current directory)").argument("[identifier]", "Issue number, PR number (pr/123), or branch name (auto-detected if omitted)").option("--json", "Output as JSON with filePath for file watching").action(async (identifier, options) => {
|
|
3608
|
+
const executeAction = async () => {
|
|
3609
|
+
try {
|
|
3610
|
+
const { RecapCommand } = await import("./recap-33NPZ3ZO.js");
|
|
3611
|
+
const command = new RecapCommand();
|
|
3612
|
+
const result = await command.execute({ identifier, json: options.json });
|
|
3613
|
+
if (options.json && result) {
|
|
3614
|
+
console.log(JSON.stringify(result, null, 2));
|
|
3615
|
+
}
|
|
3616
|
+
process.exit(0);
|
|
3617
|
+
} catch (error) {
|
|
3618
|
+
if (options.json) {
|
|
3619
|
+
console.log(JSON.stringify({ error: error instanceof Error ? error.message : "Unknown error" }, null, 2));
|
|
3620
|
+
} else {
|
|
3621
|
+
logger.error(`Recap failed: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
3622
|
+
if (error instanceof Error && error.stack) {
|
|
3623
|
+
logger.debug(error.stack);
|
|
3624
|
+
}
|
|
3625
|
+
}
|
|
3626
|
+
process.exit(1);
|
|
3627
|
+
}
|
|
3628
|
+
};
|
|
3629
|
+
if (options.json) {
|
|
3630
|
+
const jsonLogger = createStderrLogger();
|
|
3631
|
+
await withLogger(jsonLogger, executeAction);
|
|
3632
|
+
} else {
|
|
3633
|
+
await executeAction();
|
|
3634
|
+
}
|
|
3635
|
+
});
|
|
3715
3636
|
program.command("test-neon").description("Test Neon integration and debug configuration").action(async () => {
|
|
3716
3637
|
var _a;
|
|
3717
3638
|
try {
|
|
3718
|
-
const { SettingsManager: SettingsManager2 } = await import("./SettingsManager-
|
|
3639
|
+
const { SettingsManager: SettingsManager2 } = await import("./SettingsManager-XPR4TEQL.js");
|
|
3719
3640
|
const { createNeonProviderFromSettings: createNeonProviderFromSettings2 } = await import("./neon-helpers-L5CXQ5CT.js");
|
|
3720
3641
|
logger.info("Testing Neon Integration\n");
|
|
3721
3642
|
logger.info("1. Settings Configuration:");
|