@iloom/cli 0.2.0 → 0.3.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 +234 -667
- package/dist/BranchNamingService-OMWKUYMM.js +13 -0
- package/dist/ClaudeContextManager-3VXA6UPR.js +13 -0
- package/dist/ClaudeService-6CPK43N4.js +12 -0
- package/dist/GitHubService-EBOETDIW.js +11 -0
- package/dist/{LoomLauncher-CTSWJL35.js → LoomLauncher-JF7JZMTZ.js} +63 -32
- package/dist/LoomLauncher-JF7JZMTZ.js.map +1 -0
- package/dist/ProjectCapabilityDetector-34LU7JJ4.js +9 -0
- package/dist/{PromptTemplateManager-WII75TKH.js → PromptTemplateManager-A52RUAMS.js} +2 -2
- package/dist/README.md +234 -667
- package/dist/{SettingsManager-XOYCLH3D.js → SettingsManager-ZCWJ56WP.js} +12 -4
- package/dist/SettingsMigrationManager-AGIIIPDQ.js +10 -0
- package/dist/agents/iloom-issue-analyze-and-plan.md +125 -35
- package/dist/agents/iloom-issue-analyzer.md +284 -32
- package/dist/agents/iloom-issue-complexity-evaluator.md +40 -21
- package/dist/agents/iloom-issue-enhancer.md +69 -48
- package/dist/agents/iloom-issue-implementer.md +36 -25
- package/dist/agents/iloom-issue-planner.md +35 -24
- package/dist/agents/iloom-issue-reviewer.md +62 -9
- package/dist/{chunk-SWCRXDZC.js → chunk-3RUPPQRG.js} +1 -18
- package/dist/chunk-3RUPPQRG.js.map +1 -0
- package/dist/{chunk-HBVFXN7R.js → chunk-4BGK7T6X.js} +26 -3
- package/dist/chunk-4BGK7T6X.js.map +1 -0
- package/dist/{chunk-6LEQW46Y.js → chunk-4E4LD3QR.js} +72 -2
- package/dist/{chunk-6LEQW46Y.js.map → chunk-4E4LD3QR.js.map} +1 -1
- package/dist/{chunk-CWR2SANQ.js → chunk-EBISESAP.js} +1 -1
- package/dist/{chunk-TS6DL67T.js → chunk-G2IEYOLQ.js} +11 -38
- package/dist/chunk-G2IEYOLQ.js.map +1 -0
- package/dist/chunk-HBYZH6GD.js +1989 -0
- package/dist/chunk-HBYZH6GD.js.map +1 -0
- package/dist/chunk-INW24J2W.js +55 -0
- package/dist/chunk-INW24J2W.js.map +1 -0
- package/dist/{chunk-ZMNQBJUI.js → chunk-IP7SMKIF.js} +61 -22
- package/dist/chunk-IP7SMKIF.js.map +1 -0
- package/dist/{chunk-4IV6W4U5.js → chunk-IXKLYTWO.js} +12 -12
- package/dist/chunk-IXKLYTWO.js.map +1 -0
- package/dist/{chunk-JNKJ7NJV.js → chunk-JKXJ7BGL.js} +6 -2
- package/dist/{chunk-JNKJ7NJV.js.map → chunk-JKXJ7BGL.js.map} +1 -1
- package/dist/{chunk-LAPY6NAE.js → chunk-JQFO7QQN.js} +68 -12
- package/dist/{chunk-LAPY6NAE.js.map → chunk-JQFO7QQN.js.map} +1 -1
- package/dist/{SettingsMigrationManager-MTQIMI54.js → chunk-KLBYVHPK.js} +3 -2
- package/dist/{chunk-USVVV3FP.js → chunk-MKWYLDFK.js} +5 -5
- package/dist/chunk-O5OH5MRX.js +396 -0
- package/dist/chunk-O5OH5MRX.js.map +1 -0
- package/dist/{chunk-DJUGYNQE.js → chunk-PA6Q6AWM.js} +16 -3
- package/dist/chunk-PA6Q6AWM.js.map +1 -0
- package/dist/chunk-RO26VS3W.js +444 -0
- package/dist/chunk-RO26VS3W.js.map +1 -0
- package/dist/{chunk-VETG35MF.js → chunk-TSKY3JI7.js} +3 -3
- package/dist/{chunk-VETG35MF.js.map → chunk-TSKY3JI7.js.map} +1 -1
- package/dist/{chunk-LHP6ROUM.js → chunk-U5QDY7ZD.js} +4 -16
- package/dist/chunk-U5QDY7ZD.js.map +1 -0
- package/dist/{chunk-SPYPLHMK.js → chunk-VU3QMIP2.js} +34 -2
- package/dist/chunk-VU3QMIP2.js.map +1 -0
- package/dist/{chunk-PVAVNJKS.js → chunk-WEN5C5DM.js} +10 -1
- package/dist/chunk-WEN5C5DM.js.map +1 -0
- package/dist/{chunk-2PLUQT6J.js → chunk-XPKDPZ5D.js} +2 -2
- package/dist/{chunk-RF2YI2XJ.js → chunk-ZBQVSHVT.js} +5 -5
- package/dist/chunk-ZBQVSHVT.js.map +1 -0
- package/dist/{chunk-GZP4UGGM.js → chunk-ZM3CFL5L.js} +2 -2
- package/dist/{chunk-BLCTGFZN.js → chunk-ZT3YZB4K.js} +3 -4
- package/dist/chunk-ZT3YZB4K.js.map +1 -0
- package/dist/{chunk-MFU53H6J.js → chunk-ZWFBBPJI.js} +6 -6
- package/dist/{chunk-MFU53H6J.js.map → chunk-ZWFBBPJI.js.map} +1 -1
- package/dist/{claude-ZIWDG4XG.js → claude-LUZ35IMK.js} +2 -2
- package/dist/{cleanup-FEIVZSIV.js → cleanup-3MONU4PU.js} +88 -27
- package/dist/cleanup-3MONU4PU.js.map +1 -0
- package/dist/cli.js +2511 -62
- package/dist/cli.js.map +1 -1
- package/dist/{contribute-EMZKCAC6.js → contribute-UWJAGIG7.js} +6 -6
- package/dist/{feedback-LFNMQBAZ.js → feedback-W3BXTGIM.js} +15 -14
- package/dist/{feedback-LFNMQBAZ.js.map → feedback-W3BXTGIM.js.map} +1 -1
- package/dist/{git-WC6HZLOT.js → git-34Z6QVDS.js} +4 -2
- package/dist/{ignite-MQWVJEAB.js → ignite-KVJEFXNO.js} +32 -27
- package/dist/ignite-KVJEFXNO.js.map +1 -0
- package/dist/index.d.ts +359 -45
- package/dist/index.js +1267 -503
- package/dist/index.js.map +1 -1
- package/dist/{init-GJDYN2IK.js → init-L55Q73H4.js} +104 -40
- package/dist/init-L55Q73H4.js.map +1 -0
- package/dist/mcp/issue-management-server.js +934 -0
- package/dist/mcp/issue-management-server.js.map +1 -0
- package/dist/{neon-helpers-ZVIRPKCI.js → neon-helpers-WPUACUVC.js} +3 -3
- package/dist/neon-helpers-WPUACUVC.js.map +1 -0
- package/dist/{open-NXSN7XOC.js → open-LNRZL3UU.js} +39 -36
- package/dist/open-LNRZL3UU.js.map +1 -0
- package/dist/{prompt-ANTQWHUF.js → prompt-7INJ7YRU.js} +4 -2
- package/dist/prompt-7INJ7YRU.js.map +1 -0
- package/dist/prompts/init-prompt.txt +541 -98
- package/dist/prompts/issue-prompt.txt +27 -27
- package/dist/{rebase-DUNFOJVS.js → rebase-C4WNCVGM.js} +6 -6
- package/dist/{remote-ZCXJVVNW.js → remote-VUNCQZ6J.js} +3 -2
- package/dist/remote-VUNCQZ6J.js.map +1 -0
- package/dist/{run-O7ZK7CKA.js → run-IOGNIOYN.js} +39 -36
- package/dist/run-IOGNIOYN.js.map +1 -0
- package/dist/schema/settings.schema.json +59 -3
- package/dist/{test-git-T76HOTIA.js → test-git-J7I5MFYH.js} +3 -3
- package/dist/{test-prefix-6HJUVQMH.js → test-prefix-ZCONBCBX.js} +3 -3
- package/dist/{test-webserver-M2I3EV4J.js → test-webserver-DAHONWCS.js} +4 -4
- package/dist/test-webserver-DAHONWCS.js.map +1 -0
- package/package.json +3 -2
- package/dist/ClaudeContextManager-LVCYRM6Q.js +0 -13
- package/dist/ClaudeService-WVTWB3DK.js +0 -12
- package/dist/GitHubService-7E2S5NNZ.js +0 -11
- package/dist/LoomLauncher-CTSWJL35.js.map +0 -1
- package/dist/add-issue-OBI325W7.js +0 -69
- package/dist/add-issue-OBI325W7.js.map +0 -1
- package/dist/chunk-4IV6W4U5.js.map +0 -1
- package/dist/chunk-BLCTGFZN.js.map +0 -1
- package/dist/chunk-CVLAZRNB.js +0 -54
- package/dist/chunk-CVLAZRNB.js.map +0 -1
- package/dist/chunk-DJUGYNQE.js.map +0 -1
- package/dist/chunk-H4E4THUZ.js +0 -55
- package/dist/chunk-H4E4THUZ.js.map +0 -1
- package/dist/chunk-H5LDRGVK.js +0 -642
- package/dist/chunk-H5LDRGVK.js.map +0 -1
- package/dist/chunk-HBVFXN7R.js.map +0 -1
- package/dist/chunk-LHP6ROUM.js.map +0 -1
- package/dist/chunk-PVAVNJKS.js.map +0 -1
- package/dist/chunk-RF2YI2XJ.js.map +0 -1
- package/dist/chunk-SPYPLHMK.js.map +0 -1
- package/dist/chunk-SWCRXDZC.js.map +0 -1
- package/dist/chunk-SYOSCMIT.js +0 -545
- package/dist/chunk-SYOSCMIT.js.map +0 -1
- package/dist/chunk-T3KEIB4D.js +0 -243
- package/dist/chunk-T3KEIB4D.js.map +0 -1
- package/dist/chunk-TS6DL67T.js.map +0 -1
- package/dist/chunk-ZMNQBJUI.js.map +0 -1
- package/dist/cleanup-FEIVZSIV.js.map +0 -1
- package/dist/enhance-MNA4ZGXW.js +0 -176
- package/dist/enhance-MNA4ZGXW.js.map +0 -1
- package/dist/finish-TX5CJICB.js +0 -1749
- package/dist/finish-TX5CJICB.js.map +0 -1
- package/dist/ignite-MQWVJEAB.js.map +0 -1
- package/dist/init-GJDYN2IK.js.map +0 -1
- package/dist/mcp/chunk-6SDFJ42P.js +0 -62
- package/dist/mcp/chunk-6SDFJ42P.js.map +0 -1
- package/dist/mcp/claude-NDFOCQQQ.js +0 -249
- package/dist/mcp/claude-NDFOCQQQ.js.map +0 -1
- package/dist/mcp/color-QS5BFCNN.js +0 -168
- package/dist/mcp/color-QS5BFCNN.js.map +0 -1
- package/dist/mcp/github-comment-server.js +0 -168
- package/dist/mcp/github-comment-server.js.map +0 -1
- package/dist/mcp/terminal-OMNRFWB3.js +0 -227
- package/dist/mcp/terminal-OMNRFWB3.js.map +0 -1
- package/dist/open-NXSN7XOC.js.map +0 -1
- package/dist/run-O7ZK7CKA.js.map +0 -1
- package/dist/start-73I5W7WW.js +0 -983
- package/dist/start-73I5W7WW.js.map +0 -1
- package/dist/test-webserver-M2I3EV4J.js.map +0 -1
- /package/dist/{ClaudeContextManager-LVCYRM6Q.js.map → BranchNamingService-OMWKUYMM.js.map} +0 -0
- /package/dist/{ClaudeService-WVTWB3DK.js.map → ClaudeContextManager-3VXA6UPR.js.map} +0 -0
- /package/dist/{GitHubService-7E2S5NNZ.js.map → ClaudeService-6CPK43N4.js.map} +0 -0
- /package/dist/{PromptTemplateManager-WII75TKH.js.map → GitHubService-EBOETDIW.js.map} +0 -0
- /package/dist/{SettingsManager-XOYCLH3D.js.map → ProjectCapabilityDetector-34LU7JJ4.js.map} +0 -0
- /package/dist/{claude-ZIWDG4XG.js.map → PromptTemplateManager-A52RUAMS.js.map} +0 -0
- /package/dist/{git-WC6HZLOT.js.map → SettingsManager-ZCWJ56WP.js.map} +0 -0
- /package/dist/{neon-helpers-ZVIRPKCI.js.map → SettingsMigrationManager-AGIIIPDQ.js.map} +0 -0
- /package/dist/{chunk-CWR2SANQ.js.map → chunk-EBISESAP.js.map} +0 -0
- /package/dist/{SettingsMigrationManager-MTQIMI54.js.map → chunk-KLBYVHPK.js.map} +0 -0
- /package/dist/{chunk-USVVV3FP.js.map → chunk-MKWYLDFK.js.map} +0 -0
- /package/dist/{chunk-2PLUQT6J.js.map → chunk-XPKDPZ5D.js.map} +0 -0
- /package/dist/{chunk-GZP4UGGM.js.map → chunk-ZM3CFL5L.js.map} +0 -0
- /package/dist/{prompt-ANTQWHUF.js.map → claude-LUZ35IMK.js.map} +0 -0
- /package/dist/{contribute-EMZKCAC6.js.map → contribute-UWJAGIG7.js.map} +0 -0
- /package/dist/{remote-ZCXJVVNW.js.map → git-34Z6QVDS.js.map} +0 -0
- /package/dist/{rebase-DUNFOJVS.js.map → rebase-C4WNCVGM.js.map} +0 -0
- /package/dist/{test-git-T76HOTIA.js.map → test-git-J7I5MFYH.js.map} +0 -0
- /package/dist/{test-prefix-6HJUVQMH.js.map → test-prefix-ZCONBCBX.js.map} +0 -0
package/dist/chunk-SYOSCMIT.js
DELETED
|
@@ -1,545 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
SettingsManager
|
|
4
|
-
} from "./chunk-T3KEIB4D.js";
|
|
5
|
-
import {
|
|
6
|
-
logger
|
|
7
|
-
} from "./chunk-GEHQXLEI.js";
|
|
8
|
-
|
|
9
|
-
// src/lib/ResourceCleanup.ts
|
|
10
|
-
import path from "path";
|
|
11
|
-
var ResourceCleanup = class {
|
|
12
|
-
constructor(gitWorktree, processManager, database, cliIsolation, settingsManager) {
|
|
13
|
-
this.gitWorktree = gitWorktree;
|
|
14
|
-
this.processManager = processManager;
|
|
15
|
-
this.database = database;
|
|
16
|
-
this.cliIsolation = cliIsolation;
|
|
17
|
-
this.settingsManager = settingsManager ?? new SettingsManager();
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Cleanup a worktree and associated resources
|
|
21
|
-
* Main orchestration method
|
|
22
|
-
*
|
|
23
|
-
* @param parsed - ParsedInput from IdentifierParser with type information
|
|
24
|
-
* @param options - Cleanup options
|
|
25
|
-
*/
|
|
26
|
-
async cleanupWorktree(parsed, options = {}) {
|
|
27
|
-
var _a;
|
|
28
|
-
const operations = [];
|
|
29
|
-
const errors = [];
|
|
30
|
-
const displayIdentifier = parsed.branchName ?? ((_a = parsed.number) == null ? void 0 : _a.toString()) ?? parsed.originalInput;
|
|
31
|
-
logger.info(`Starting cleanup for: ${displayIdentifier}`);
|
|
32
|
-
const number = parsed.number;
|
|
33
|
-
if (number !== void 0) {
|
|
34
|
-
const port = this.processManager.calculatePort(number);
|
|
35
|
-
if (options.dryRun) {
|
|
36
|
-
operations.push({
|
|
37
|
-
type: "dev-server",
|
|
38
|
-
success: true,
|
|
39
|
-
message: `[DRY RUN] Would check for dev server on port ${port}`
|
|
40
|
-
});
|
|
41
|
-
} else {
|
|
42
|
-
try {
|
|
43
|
-
const terminated = await this.terminateDevServer(port);
|
|
44
|
-
operations.push({
|
|
45
|
-
type: "dev-server",
|
|
46
|
-
success: true,
|
|
47
|
-
message: terminated ? `Dev server on port ${port} terminated` : `No dev server running on port ${port}`
|
|
48
|
-
});
|
|
49
|
-
} catch (error) {
|
|
50
|
-
const err = error instanceof Error ? error : new Error("Unknown error");
|
|
51
|
-
errors.push(err);
|
|
52
|
-
operations.push({
|
|
53
|
-
type: "dev-server",
|
|
54
|
-
success: false,
|
|
55
|
-
message: `Failed to terminate dev server`,
|
|
56
|
-
error: err.message
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
let worktree = null;
|
|
62
|
-
try {
|
|
63
|
-
if (parsed.type === "pr" && parsed.number !== void 0) {
|
|
64
|
-
worktree = await this.gitWorktree.findWorktreeForPR(parsed.number, "");
|
|
65
|
-
} else if (parsed.type === "issue" && parsed.number !== void 0) {
|
|
66
|
-
worktree = await this.gitWorktree.findWorktreeForIssue(parsed.number);
|
|
67
|
-
} else if (parsed.type === "branch" && parsed.branchName) {
|
|
68
|
-
worktree = await this.gitWorktree.findWorktreeForBranch(parsed.branchName);
|
|
69
|
-
}
|
|
70
|
-
if (!worktree) {
|
|
71
|
-
throw new Error(`No worktree found for identifier: ${displayIdentifier}`);
|
|
72
|
-
}
|
|
73
|
-
logger.debug(`Found worktree: path="${worktree.path}", branch="${worktree.branch}"`);
|
|
74
|
-
} catch (error) {
|
|
75
|
-
const err = error instanceof Error ? error : new Error("Unknown error");
|
|
76
|
-
errors.push(err);
|
|
77
|
-
return {
|
|
78
|
-
identifier: displayIdentifier,
|
|
79
|
-
success: false,
|
|
80
|
-
operations,
|
|
81
|
-
errors,
|
|
82
|
-
rollbackRequired: false
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
if (!options.force) {
|
|
86
|
-
const safety = await this.validateWorktreeSafety(worktree, parsed.originalInput);
|
|
87
|
-
if (!safety.isSafe) {
|
|
88
|
-
const blockerMessage = safety.blockers.join("\n\n");
|
|
89
|
-
throw new Error(`Cannot cleanup:
|
|
90
|
-
|
|
91
|
-
${blockerMessage}`);
|
|
92
|
-
}
|
|
93
|
-
if (safety.warnings.length > 0) {
|
|
94
|
-
safety.warnings.forEach((warning) => {
|
|
95
|
-
logger.warn(warning);
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
let databaseConfig = null;
|
|
100
|
-
if (!options.keepDatabase && worktree) {
|
|
101
|
-
const envFilePath = path.join(worktree.path, ".env");
|
|
102
|
-
try {
|
|
103
|
-
const shouldCleanup = this.database ? await this.database.shouldUseDatabaseBranching(envFilePath) : false;
|
|
104
|
-
databaseConfig = { shouldCleanup, envFilePath };
|
|
105
|
-
} catch (error) {
|
|
106
|
-
logger.warn(
|
|
107
|
-
`Failed to read database config from ${envFilePath}, skipping database cleanup: ${error instanceof Error ? error.message : String(error)}`
|
|
108
|
-
);
|
|
109
|
-
databaseConfig = { shouldCleanup: false, envFilePath };
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
let mainWorktreePath = null;
|
|
113
|
-
if (!options.dryRun) {
|
|
114
|
-
try {
|
|
115
|
-
const { findMainWorktreePathWithSettings } = await import("./git-WC6HZLOT.js");
|
|
116
|
-
mainWorktreePath = await findMainWorktreePathWithSettings(worktree.path, this.settingsManager);
|
|
117
|
-
} catch (error) {
|
|
118
|
-
logger.warn(
|
|
119
|
-
`Failed to find main worktree path: ${error instanceof Error ? error.message : String(error)}`
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
if (options.dryRun) {
|
|
124
|
-
operations.push({
|
|
125
|
-
type: "worktree",
|
|
126
|
-
success: true,
|
|
127
|
-
message: `[DRY RUN] Would remove worktree: ${worktree.path}`
|
|
128
|
-
});
|
|
129
|
-
} else {
|
|
130
|
-
try {
|
|
131
|
-
const worktreeOptions = {
|
|
132
|
-
removeDirectory: true,
|
|
133
|
-
removeBranch: false
|
|
134
|
-
// Handle branch separately
|
|
135
|
-
};
|
|
136
|
-
if (options.force !== void 0) {
|
|
137
|
-
worktreeOptions.force = options.force;
|
|
138
|
-
}
|
|
139
|
-
await this.gitWorktree.removeWorktree(worktree.path, worktreeOptions);
|
|
140
|
-
operations.push({
|
|
141
|
-
type: "worktree",
|
|
142
|
-
success: true,
|
|
143
|
-
message: `Worktree removed: ${worktree.path}`
|
|
144
|
-
});
|
|
145
|
-
} catch (error) {
|
|
146
|
-
const err = error instanceof Error ? error : new Error("Unknown error");
|
|
147
|
-
errors.push(err);
|
|
148
|
-
operations.push({
|
|
149
|
-
type: "worktree",
|
|
150
|
-
success: false,
|
|
151
|
-
message: `Failed to remove worktree`,
|
|
152
|
-
error: err.message
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
if (options.deleteBranch && worktree) {
|
|
157
|
-
if (options.dryRun) {
|
|
158
|
-
operations.push({
|
|
159
|
-
type: "branch",
|
|
160
|
-
success: true,
|
|
161
|
-
message: `[DRY RUN] Would delete branch: ${worktree.branch}`
|
|
162
|
-
});
|
|
163
|
-
} else {
|
|
164
|
-
try {
|
|
165
|
-
const branchOptions = { dryRun: false };
|
|
166
|
-
if (options.force !== void 0) {
|
|
167
|
-
branchOptions.force = options.force;
|
|
168
|
-
}
|
|
169
|
-
await this.deleteBranch(worktree.branch, branchOptions, mainWorktreePath ?? void 0);
|
|
170
|
-
operations.push({
|
|
171
|
-
type: "branch",
|
|
172
|
-
success: true,
|
|
173
|
-
message: `Branch deleted: ${worktree.branch}`
|
|
174
|
-
});
|
|
175
|
-
} catch (error) {
|
|
176
|
-
const err = error instanceof Error ? error : new Error("Unknown error");
|
|
177
|
-
errors.push(err);
|
|
178
|
-
operations.push({
|
|
179
|
-
type: "branch",
|
|
180
|
-
success: false,
|
|
181
|
-
message: `Failed to delete branch`,
|
|
182
|
-
error: err.message
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
const cliIdentifier = parsed.number ?? parsed.branchName;
|
|
188
|
-
if (this.cliIsolation && cliIdentifier !== void 0) {
|
|
189
|
-
if (options.dryRun) {
|
|
190
|
-
operations.push({
|
|
191
|
-
type: "cli-symlinks",
|
|
192
|
-
success: true,
|
|
193
|
-
message: `[DRY RUN] Would cleanup CLI symlinks for: ${cliIdentifier}`
|
|
194
|
-
});
|
|
195
|
-
} else {
|
|
196
|
-
try {
|
|
197
|
-
const removed = await this.cliIsolation.cleanupVersionedExecutables(cliIdentifier);
|
|
198
|
-
operations.push({
|
|
199
|
-
type: "cli-symlinks",
|
|
200
|
-
success: true,
|
|
201
|
-
message: removed.length > 0 ? `CLI symlinks removed: ${removed.length}` : "No CLI symlinks to cleanup"
|
|
202
|
-
});
|
|
203
|
-
} catch (error) {
|
|
204
|
-
const err = error instanceof Error ? error : new Error("Unknown error");
|
|
205
|
-
errors.push(err);
|
|
206
|
-
logger.warn(
|
|
207
|
-
`CLI symlink cleanup failed: ${err.message}`
|
|
208
|
-
);
|
|
209
|
-
operations.push({
|
|
210
|
-
type: "cli-symlinks",
|
|
211
|
-
success: false,
|
|
212
|
-
message: "CLI symlink cleanup failed (non-fatal)"
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
if (databaseConfig && worktree) {
|
|
218
|
-
if (options.dryRun) {
|
|
219
|
-
operations.push({
|
|
220
|
-
type: "database",
|
|
221
|
-
success: true,
|
|
222
|
-
message: `[DRY RUN] Would cleanup database branch for: ${worktree.branch}`
|
|
223
|
-
});
|
|
224
|
-
} else {
|
|
225
|
-
try {
|
|
226
|
-
if (databaseConfig.shouldCleanup && this.database) {
|
|
227
|
-
try {
|
|
228
|
-
const deletionResult = await this.database.deleteBranchIfConfigured(
|
|
229
|
-
worktree.branch,
|
|
230
|
-
databaseConfig.shouldCleanup,
|
|
231
|
-
false,
|
|
232
|
-
// isPreview
|
|
233
|
-
mainWorktreePath ?? void 0
|
|
234
|
-
);
|
|
235
|
-
if (deletionResult.deleted) {
|
|
236
|
-
logger.info(`Database branch deleted: ${worktree.branch}`);
|
|
237
|
-
operations.push({
|
|
238
|
-
type: "database",
|
|
239
|
-
success: true,
|
|
240
|
-
message: `Database branch deleted`,
|
|
241
|
-
deleted: true
|
|
242
|
-
});
|
|
243
|
-
} else if (deletionResult.notFound) {
|
|
244
|
-
logger.debug(`No database branch found for: ${worktree.branch}`);
|
|
245
|
-
operations.push({
|
|
246
|
-
type: "database",
|
|
247
|
-
success: true,
|
|
248
|
-
message: `No database branch found (skipped)`,
|
|
249
|
-
deleted: false
|
|
250
|
-
});
|
|
251
|
-
} else if (deletionResult.userDeclined) {
|
|
252
|
-
logger.info("Preview database deletion declined by user");
|
|
253
|
-
operations.push({
|
|
254
|
-
type: "database",
|
|
255
|
-
success: true,
|
|
256
|
-
message: `Database cleanup skipped (user declined)`,
|
|
257
|
-
deleted: false
|
|
258
|
-
});
|
|
259
|
-
} else if (!deletionResult.success) {
|
|
260
|
-
const errorMsg = deletionResult.error ?? "Unknown error";
|
|
261
|
-
errors.push(new Error(errorMsg));
|
|
262
|
-
logger.warn(`Database cleanup failed: ${errorMsg}`);
|
|
263
|
-
operations.push({
|
|
264
|
-
type: "database",
|
|
265
|
-
success: false,
|
|
266
|
-
// Non-fatal, but report error
|
|
267
|
-
message: `Database cleanup failed`,
|
|
268
|
-
error: errorMsg,
|
|
269
|
-
deleted: false
|
|
270
|
-
});
|
|
271
|
-
} else {
|
|
272
|
-
errors.push(new Error("Database cleanup in an unknown state"));
|
|
273
|
-
logger.warn("Database deletion returned unexpected result state");
|
|
274
|
-
operations.push({
|
|
275
|
-
type: "database",
|
|
276
|
-
success: false,
|
|
277
|
-
message: `Database cleanup in an unknown state`,
|
|
278
|
-
deleted: false
|
|
279
|
-
});
|
|
280
|
-
}
|
|
281
|
-
} catch (error) {
|
|
282
|
-
errors.push(error instanceof Error ? error : new Error(String(error)));
|
|
283
|
-
logger.warn(
|
|
284
|
-
`Unexpected database cleanup exception: ${error instanceof Error ? error.message : String(error)}`
|
|
285
|
-
);
|
|
286
|
-
operations.push({
|
|
287
|
-
type: "database",
|
|
288
|
-
success: false,
|
|
289
|
-
message: `Database cleanup failed`,
|
|
290
|
-
error: error instanceof Error ? error.message : String(error),
|
|
291
|
-
deleted: false
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
} else {
|
|
295
|
-
operations.push({
|
|
296
|
-
type: "database",
|
|
297
|
-
success: true,
|
|
298
|
-
message: `Database cleanup skipped (not available)`,
|
|
299
|
-
deleted: false
|
|
300
|
-
});
|
|
301
|
-
}
|
|
302
|
-
} catch (error) {
|
|
303
|
-
const err = error instanceof Error ? error : new Error("Unknown error");
|
|
304
|
-
errors.push(err);
|
|
305
|
-
operations.push({
|
|
306
|
-
type: "database",
|
|
307
|
-
success: false,
|
|
308
|
-
message: `Database cleanup failed`,
|
|
309
|
-
error: err.message,
|
|
310
|
-
deleted: false
|
|
311
|
-
});
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
const success = errors.length === 0;
|
|
316
|
-
return {
|
|
317
|
-
identifier: displayIdentifier,
|
|
318
|
-
branchName: worktree == null ? void 0 : worktree.branch,
|
|
319
|
-
success,
|
|
320
|
-
operations,
|
|
321
|
-
errors,
|
|
322
|
-
rollbackRequired: false
|
|
323
|
-
// Cleanup operations are generally not reversible
|
|
324
|
-
};
|
|
325
|
-
}
|
|
326
|
-
/**
|
|
327
|
-
* Terminate dev server on specified port
|
|
328
|
-
*/
|
|
329
|
-
async terminateDevServer(port) {
|
|
330
|
-
logger.debug(`Checking for dev server on port ${port}`);
|
|
331
|
-
const processInfo = await this.processManager.detectDevServer(port);
|
|
332
|
-
if (!processInfo) {
|
|
333
|
-
logger.debug(`No process found on port ${port}`);
|
|
334
|
-
return false;
|
|
335
|
-
}
|
|
336
|
-
if (!processInfo.isDevServer) {
|
|
337
|
-
logger.warn(
|
|
338
|
-
`Process on port ${port} (${processInfo.name}) doesn't appear to be a dev server, skipping`
|
|
339
|
-
);
|
|
340
|
-
return false;
|
|
341
|
-
}
|
|
342
|
-
logger.info(`Terminating dev server: ${processInfo.name} (PID: ${processInfo.pid})`);
|
|
343
|
-
await this.processManager.terminateProcess(processInfo.pid);
|
|
344
|
-
const isFree = await this.processManager.verifyPortFree(port);
|
|
345
|
-
if (!isFree) {
|
|
346
|
-
throw new Error(`Dev server may still be running on port ${port}`);
|
|
347
|
-
}
|
|
348
|
-
return true;
|
|
349
|
-
}
|
|
350
|
-
/**
|
|
351
|
-
* Delete a Git branch with safety checks
|
|
352
|
-
*
|
|
353
|
-
* @param branchName - Name of the branch to delete
|
|
354
|
-
* @param options - Delete options (force, dryRun)
|
|
355
|
-
* @param cwd - Working directory to execute git command from (defaults to finding main worktree)
|
|
356
|
-
*/
|
|
357
|
-
async deleteBranch(branchName, options = {}, cwd) {
|
|
358
|
-
const protectedBranches = await this.settingsManager.getProtectedBranches(cwd);
|
|
359
|
-
if (protectedBranches.includes(branchName)) {
|
|
360
|
-
throw new Error(`Cannot delete protected branch: ${branchName}`);
|
|
361
|
-
}
|
|
362
|
-
if (options.dryRun) {
|
|
363
|
-
logger.info(`[DRY RUN] Would delete branch: ${branchName}`);
|
|
364
|
-
return true;
|
|
365
|
-
}
|
|
366
|
-
const { executeGitCommand, findMainWorktreePathWithSettings } = await import("./git-WC6HZLOT.js");
|
|
367
|
-
try {
|
|
368
|
-
let workingDir = cwd ?? await findMainWorktreePathWithSettings(void 0, this.settingsManager);
|
|
369
|
-
const deleteFlag = options.force ? "-D" : "-d";
|
|
370
|
-
await executeGitCommand(["branch", deleteFlag, branchName], {
|
|
371
|
-
cwd: workingDir
|
|
372
|
-
});
|
|
373
|
-
logger.info(`Branch deleted: ${branchName}`);
|
|
374
|
-
return true;
|
|
375
|
-
} catch (error) {
|
|
376
|
-
if (options.force) {
|
|
377
|
-
throw error;
|
|
378
|
-
}
|
|
379
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
380
|
-
if (errorMessage.includes("not fully merged")) {
|
|
381
|
-
throw new Error(
|
|
382
|
-
`Cannot delete unmerged branch '${branchName}'. Use --force to delete anyway.`
|
|
383
|
-
);
|
|
384
|
-
}
|
|
385
|
-
throw error;
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
/**
|
|
389
|
-
* Cleanup database branch
|
|
390
|
-
* Gracefully handles missing DatabaseManager
|
|
391
|
-
*
|
|
392
|
-
* @deprecated This method is deprecated and should not be used for post-deletion cleanup.
|
|
393
|
-
* Use the pre-fetch mechanism in cleanupWorktree() instead.
|
|
394
|
-
* This method will fail if called after worktree deletion because
|
|
395
|
-
* it attempts to read the .env file which has been deleted.
|
|
396
|
-
*
|
|
397
|
-
* @param branchName - Name of the branch to delete
|
|
398
|
-
* @param worktreePath - Path to worktree (must still exist with .env file)
|
|
399
|
-
*/
|
|
400
|
-
async cleanupDatabase(branchName, worktreePath) {
|
|
401
|
-
if (!this.database) {
|
|
402
|
-
logger.debug("Database manager not available, skipping database cleanup");
|
|
403
|
-
return false;
|
|
404
|
-
}
|
|
405
|
-
try {
|
|
406
|
-
const envFilePath = path.join(worktreePath, ".env");
|
|
407
|
-
const shouldCleanup = await this.database.shouldUseDatabaseBranching(envFilePath);
|
|
408
|
-
let cwd;
|
|
409
|
-
try {
|
|
410
|
-
const { findMainWorktreePathWithSettings } = await import("./git-WC6HZLOT.js");
|
|
411
|
-
cwd = await findMainWorktreePathWithSettings(worktreePath, this.settingsManager);
|
|
412
|
-
} catch (error) {
|
|
413
|
-
logger.debug(
|
|
414
|
-
`Could not find main worktree path, using current directory: ${error instanceof Error ? error.message : String(error)}`
|
|
415
|
-
);
|
|
416
|
-
}
|
|
417
|
-
const result = await this.database.deleteBranchIfConfigured(
|
|
418
|
-
branchName,
|
|
419
|
-
shouldCleanup,
|
|
420
|
-
false,
|
|
421
|
-
// isPreview
|
|
422
|
-
cwd
|
|
423
|
-
);
|
|
424
|
-
if (result.deleted) {
|
|
425
|
-
logger.info(`Database branch deleted: ${branchName}`);
|
|
426
|
-
return true;
|
|
427
|
-
} else if (result.notFound) {
|
|
428
|
-
logger.debug(`No database branch found for: ${branchName}`);
|
|
429
|
-
return false;
|
|
430
|
-
} else if (result.userDeclined) {
|
|
431
|
-
logger.info("Preview database deletion declined by user");
|
|
432
|
-
return false;
|
|
433
|
-
} else if (!result.success) {
|
|
434
|
-
logger.warn(`Database cleanup failed: ${result.error ?? "Unknown error"}`);
|
|
435
|
-
return false;
|
|
436
|
-
} else {
|
|
437
|
-
logger.debug("Database deletion returned unexpected result");
|
|
438
|
-
return false;
|
|
439
|
-
}
|
|
440
|
-
} catch (error) {
|
|
441
|
-
logger.warn(
|
|
442
|
-
`Unexpected database cleanup error: ${error instanceof Error ? error.message : String(error)}`
|
|
443
|
-
);
|
|
444
|
-
return false;
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
/**
|
|
448
|
-
* Cleanup multiple worktrees
|
|
449
|
-
*/
|
|
450
|
-
async cleanupMultipleWorktrees(identifiers, options = {}) {
|
|
451
|
-
const results = [];
|
|
452
|
-
for (const identifier of identifiers) {
|
|
453
|
-
const parsed = this.parseIdentifier(identifier);
|
|
454
|
-
const result = await this.cleanupWorktree(parsed, options);
|
|
455
|
-
results.push(result);
|
|
456
|
-
}
|
|
457
|
-
return results;
|
|
458
|
-
}
|
|
459
|
-
/**
|
|
460
|
-
* Validate worktree safety given a worktree object
|
|
461
|
-
* Private method used internally when worktree is already known
|
|
462
|
-
*/
|
|
463
|
-
async validateWorktreeSafety(worktree, identifier) {
|
|
464
|
-
const warnings = [];
|
|
465
|
-
const blockers = [];
|
|
466
|
-
const isMain = await this.gitWorktree.isMainWorktree(worktree, this.settingsManager);
|
|
467
|
-
if (isMain) {
|
|
468
|
-
blockers.push(`Cannot cleanup main worktree: "${worktree.branch}" @ "${worktree.path}"`);
|
|
469
|
-
}
|
|
470
|
-
const { hasUncommittedChanges } = await import("./git-WC6HZLOT.js");
|
|
471
|
-
const hasChanges = await hasUncommittedChanges(worktree.path);
|
|
472
|
-
if (hasChanges) {
|
|
473
|
-
const blockerMessage = `Worktree has uncommitted changes.
|
|
474
|
-
|
|
475
|
-
Please resolve before cleanup - you have some options:
|
|
476
|
-
\u2022 Commit changes: cd ${worktree.path} && git commit -am "message"
|
|
477
|
-
\u2022 Stash changes: cd ${worktree.path} && git stash
|
|
478
|
-
\u2022 Force cleanup: il cleanup ${identifier} --force (WARNING: will discard changes)`;
|
|
479
|
-
blockers.push(blockerMessage);
|
|
480
|
-
}
|
|
481
|
-
return {
|
|
482
|
-
isSafe: blockers.length === 0,
|
|
483
|
-
warnings,
|
|
484
|
-
blockers
|
|
485
|
-
};
|
|
486
|
-
}
|
|
487
|
-
/**
|
|
488
|
-
* Validate cleanup safety
|
|
489
|
-
*/
|
|
490
|
-
async validateCleanupSafety(identifier) {
|
|
491
|
-
const warnings = [];
|
|
492
|
-
const blockers = [];
|
|
493
|
-
const worktrees = await this.gitWorktree.findWorktreesByIdentifier(identifier);
|
|
494
|
-
if (worktrees.length === 0) {
|
|
495
|
-
blockers.push(`No worktree found for: ${identifier}`);
|
|
496
|
-
return { isSafe: false, warnings, blockers };
|
|
497
|
-
}
|
|
498
|
-
const worktree = worktrees[0];
|
|
499
|
-
if (!worktree) {
|
|
500
|
-
blockers.push(`No worktree found for: ${identifier}`);
|
|
501
|
-
return { isSafe: false, warnings, blockers };
|
|
502
|
-
}
|
|
503
|
-
return await this.validateWorktreeSafety(worktree, identifier);
|
|
504
|
-
}
|
|
505
|
-
/**
|
|
506
|
-
* Parse identifier to determine type and extract number
|
|
507
|
-
* Helper method for port calculation
|
|
508
|
-
*/
|
|
509
|
-
parseIdentifier(identifier) {
|
|
510
|
-
const issueMatch = identifier.match(/issue-(\d+)/);
|
|
511
|
-
if (issueMatch == null ? void 0 : issueMatch[1]) {
|
|
512
|
-
return {
|
|
513
|
-
type: "issue",
|
|
514
|
-
number: parseInt(issueMatch[1], 10),
|
|
515
|
-
originalInput: identifier
|
|
516
|
-
};
|
|
517
|
-
}
|
|
518
|
-
const prMatch = identifier.match(/(?:pr|PR)[/-](\d+)/);
|
|
519
|
-
if (prMatch == null ? void 0 : prMatch[1]) {
|
|
520
|
-
return {
|
|
521
|
-
type: "pr",
|
|
522
|
-
number: parseInt(prMatch[1], 10),
|
|
523
|
-
originalInput: identifier
|
|
524
|
-
};
|
|
525
|
-
}
|
|
526
|
-
const numericMatch = identifier.match(/^#?(\d+)$/);
|
|
527
|
-
if (numericMatch == null ? void 0 : numericMatch[1]) {
|
|
528
|
-
return {
|
|
529
|
-
type: "issue",
|
|
530
|
-
number: parseInt(numericMatch[1], 10),
|
|
531
|
-
originalInput: identifier
|
|
532
|
-
};
|
|
533
|
-
}
|
|
534
|
-
return {
|
|
535
|
-
type: "branch",
|
|
536
|
-
branchName: identifier,
|
|
537
|
-
originalInput: identifier
|
|
538
|
-
};
|
|
539
|
-
}
|
|
540
|
-
};
|
|
541
|
-
|
|
542
|
-
export {
|
|
543
|
-
ResourceCleanup
|
|
544
|
-
};
|
|
545
|
-
//# sourceMappingURL=chunk-SYOSCMIT.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/ResourceCleanup.ts"],"sourcesContent":["import path from 'path'\nimport { GitWorktreeManager } from './GitWorktreeManager.js'\nimport { DatabaseManager } from './DatabaseManager.js'\nimport { ProcessManager } from './process/ProcessManager.js'\nimport { CLIIsolationManager } from './CLIIsolationManager.js'\nimport { SettingsManager } from './SettingsManager.js'\nimport { logger } from '../utils/logger.js'\nimport type {\n\tResourceCleanupOptions,\n\tCleanupResult,\n\tOperationResult,\n\tSafetyCheck,\n\tBranchDeleteOptions,\n} from '../types/cleanup.js'\nimport type { GitWorktree } from '../types/worktree.js'\nimport type { ParsedInput } from '../commands/start.js'\n\n/**\n * Manages resource cleanup for worktrees\n * Provides shared cleanup functionality for finish and cleanup commands\n */\nexport class ResourceCleanup {\n\tprivate settingsManager: SettingsManager\n\n\tconstructor(\n\t\tprivate gitWorktree: GitWorktreeManager,\n\t\tprivate processManager: ProcessManager,\n\t\tprivate database?: DatabaseManager,\n\t\tprivate cliIsolation?: CLIIsolationManager,\n\t\tsettingsManager?: SettingsManager\n\t) {\n\t\tthis.settingsManager = settingsManager ?? new SettingsManager()\n\t}\n\n\t/**\n\t * Cleanup a worktree and associated resources\n\t * Main orchestration method\n\t *\n\t * @param parsed - ParsedInput from IdentifierParser with type information\n\t * @param options - Cleanup options\n\t */\n\tasync cleanupWorktree(\n\t\tparsed: ParsedInput,\n\t\toptions: ResourceCleanupOptions = {}\n\t): Promise<CleanupResult> {\n\t\tconst operations: OperationResult[] = []\n\t\tconst errors: Error[] = []\n\n\t\tconst displayIdentifier = parsed.branchName ?? parsed.number?.toString() ?? parsed.originalInput\n\t\tlogger.info(`Starting cleanup for: ${displayIdentifier}`)\n\n\t\t// Extract number from ParsedInput for port calculation\n\t\tconst number = parsed.number\n\n\t\t// Step 1: Terminate dev server if applicable\n\t\tif (number !== undefined) {\n\t\t\tconst port = this.processManager.calculatePort(number)\n\n\t\t\tif (options.dryRun) {\n\t\t\t\toperations.push({\n\t\t\t\t\ttype: 'dev-server',\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tmessage: `[DRY RUN] Would check for dev server on port ${port}`,\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tconst terminated = await this.terminateDevServer(port)\n\t\t\t\t\toperations.push({\n\t\t\t\t\t\ttype: 'dev-server',\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\tmessage: terminated\n\t\t\t\t\t\t\t? `Dev server on port ${port} terminated`\n\t\t\t\t\t\t\t: `No dev server running on port ${port}`,\n\t\t\t\t\t})\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst err = error instanceof Error ? error : new Error('Unknown error')\n\t\t\t\t\terrors.push(err)\n\t\t\t\t\toperations.push({\n\t\t\t\t\t\ttype: 'dev-server',\n\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\tmessage: `Failed to terminate dev server`,\n\t\t\t\t\t\terror: err.message,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Step 2: Find worktree using specific methods based on type\n\t\tlet worktree: GitWorktree | null = null\n\t\ttry {\n\t\t\t// Use specific finding methods based on parsed type for precision\n\t\t\tif (parsed.type === 'pr' && parsed.number !== undefined) {\n\t\t\t\t// For PRs, pass empty string for branchName since we're detecting from path pattern\n\t\t\t\tworktree = await this.gitWorktree.findWorktreeForPR(parsed.number, '')\n\t\t\t} else if (parsed.type === 'issue' && parsed.number !== undefined) {\n\t\t\t\tworktree = await this.gitWorktree.findWorktreeForIssue(parsed.number)\n\t\t\t} else if (parsed.type === 'branch' && parsed.branchName) {\n\t\t\t\tworktree = await this.gitWorktree.findWorktreeForBranch(parsed.branchName)\n\t\t\t}\n\n\t\t\tif (!worktree) {\n\t\t\t\tthrow new Error(`No worktree found for identifier: ${displayIdentifier}`)\n\t\t\t}\n\n\t\t\tlogger.debug(`Found worktree: path=\"${worktree.path}\", branch=\"${worktree.branch}\"`)\n\t\t} catch (error) {\n\t\t\tconst err = error instanceof Error ? error : new Error('Unknown error')\n\t\t\terrors.push(err)\n\n\t\t\treturn {\n\t\t\t\tidentifier: displayIdentifier,\n\t\t\t\tsuccess: false,\n\t\t\t\toperations,\n\t\t\t\terrors,\n\t\t\t\trollbackRequired: false,\n\t\t\t}\n\t\t}\n\n\t\t// Step 2.5: Validate safety before proceeding with cleanup (unless force flag is set)\n\t\tif (!options.force) {\n\t\t\tconst safety = await this.validateWorktreeSafety(worktree, parsed.originalInput)\n\n\t\t\tif (!safety.isSafe) {\n\t\t\t\t// Format blocker messages for error output\n\t\t\t\tconst blockerMessage = safety.blockers.join('\\n\\n')\n\t\t\t\tthrow new Error(`Cannot cleanup:\\n\\n${blockerMessage}`)\n\t\t\t}\n\n\t\t\t// Log warnings if any\n\t\t\tif (safety.warnings.length > 0) {\n\t\t\t\tsafety.warnings.forEach(warning => {\n\t\t\t\t\tlogger.warn(warning)\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\t// Step 3: Pre-fetch database configuration before worktree removal\n\t\t// This config is used AFTER worktree deletion when env file no longer exists\n\t\tlet databaseConfig: { shouldCleanup: boolean; envFilePath: string } | null = null\n\t\tif (!options.keepDatabase && worktree) {\n\t\t\tconst envFilePath = path.join(worktree.path, '.env')\n\t\t\ttry {\n\t\t\t\t// Pre-check if database cleanup should happen by reading .env file now\n\t\t\t\tconst shouldCleanup = this.database\n\t\t\t\t\t? await this.database.shouldUseDatabaseBranching(envFilePath)\n\t\t\t\t\t: false\n\t\t\t\tdatabaseConfig = { shouldCleanup, envFilePath }\n\t\t\t} catch (error) {\n\t\t\t\t// If we can't read the config, we'll skip database cleanup\n\t\t\t\tlogger.warn(\n\t\t\t\t\t`Failed to read database config from ${envFilePath}, skipping database cleanup: ${\n\t\t\t\t\t\terror instanceof Error ? error.message : String(error)\n\t\t\t\t\t}`\n\t\t\t\t)\n\t\t\t\tdatabaseConfig = { shouldCleanup: false, envFilePath }\n\t\t\t}\n\t\t}\n\n\t\t// Step 3.5: Find main worktree path before deletion (needed for branch and database operations)\n\t\tlet mainWorktreePath: string | null = null\n\t\tif (!options.dryRun) {\n\t\t\ttry {\n\t\t\t\tconst { findMainWorktreePathWithSettings } = await import('../utils/git.js')\n\t\t\t\tmainWorktreePath = await findMainWorktreePathWithSettings(worktree.path, this.settingsManager)\n\t\t\t} catch (error) {\n\t\t\t\tlogger.warn(\n\t\t\t\t\t`Failed to find main worktree path: ${error instanceof Error ? error.message : String(error)}`\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\n\t\t// Step 4: Remove worktree\n\t\tif (options.dryRun) {\n\t\t\toperations.push({\n\t\t\t\ttype: 'worktree',\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage: `[DRY RUN] Would remove worktree: ${worktree.path}`,\n\t\t\t})\n\t\t} else {\n\t\t\ttry {\n\t\t\t\tconst worktreeOptions: { force?: boolean; removeDirectory: true; removeBranch: false } =\n\t\t\t\t\t{\n\t\t\t\t\t\tremoveDirectory: true,\n\t\t\t\t\t\tremoveBranch: false, // Handle branch separately\n\t\t\t\t\t}\n\t\t\t\tif (options.force !== undefined) {\n\t\t\t\t\tworktreeOptions.force = options.force\n\t\t\t\t}\n\t\t\t\tawait this.gitWorktree.removeWorktree(worktree.path, worktreeOptions)\n\n\t\t\t\toperations.push({\n\t\t\t\t\ttype: 'worktree',\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tmessage: `Worktree removed: ${worktree.path}`,\n\t\t\t\t})\n\t\t\t} catch (error) {\n\t\t\t\tconst err = error instanceof Error ? error : new Error('Unknown error')\n\t\t\t\terrors.push(err)\n\t\t\t\toperations.push({\n\t\t\t\t\ttype: 'worktree',\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\tmessage: `Failed to remove worktree`,\n\t\t\t\t\terror: err.message,\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\n\t\t// Step 5: Delete branch if requested\n\t\tif (options.deleteBranch && worktree) {\n\t\t\tif (options.dryRun) {\n\t\t\t\toperations.push({\n\t\t\t\t\ttype: 'branch',\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tmessage: `[DRY RUN] Would delete branch: ${worktree.branch}`,\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tconst branchOptions: BranchDeleteOptions = { dryRun: false }\n\t\t\t\t\tif (options.force !== undefined) {\n\t\t\t\t\t\tbranchOptions.force = options.force\n\t\t\t\t\t}\n\t\t\t\t\t// Pass main worktree path to ensure we can execute git commands\n\t\t\t\t\tawait this.deleteBranch(worktree.branch, branchOptions, mainWorktreePath ?? undefined)\n\n\t\t\t\t\toperations.push({\n\t\t\t\t\t\ttype: 'branch',\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\tmessage: `Branch deleted: ${worktree.branch}`,\n\t\t\t\t\t})\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst err = error instanceof Error ? error : new Error('Unknown error')\n\t\t\t\t\terrors.push(err)\n\t\t\t\t\toperations.push({\n\t\t\t\t\t\ttype: 'branch',\n\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\tmessage: `Failed to delete branch`,\n\t\t\t\t\t\terror: err.message,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Step 5.5: Cleanup CLI symlinks if CLI isolation is available\n\t\t// Derive identifier from parsed input (number for issue/PR, branchName for branch)\n\t\tconst cliIdentifier = parsed.number ?? parsed.branchName\n\t\tif (this.cliIsolation && cliIdentifier !== undefined) {\n\t\t\tif (options.dryRun) {\n\t\t\t\toperations.push({\n\t\t\t\t\ttype: 'cli-symlinks',\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tmessage: `[DRY RUN] Would cleanup CLI symlinks for: ${cliIdentifier}`,\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tconst removed = await this.cliIsolation.cleanupVersionedExecutables(cliIdentifier)\n\t\t\t\t\toperations.push({\n\t\t\t\t\t\ttype: 'cli-symlinks',\n\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\tmessage: removed.length > 0\n\t\t\t\t\t\t\t? `CLI symlinks removed: ${removed.length}`\n\t\t\t\t\t\t\t: 'No CLI symlinks to cleanup',\n\t\t\t\t\t})\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// Log warning but don't fail\n\t\t\t\t\tconst err = error instanceof Error ? error : new Error('Unknown error')\n\t\t\t\t\terrors.push(err)\n\t\t\t\t\tlogger.warn(\n\t\t\t\t\t\t`CLI symlink cleanup failed: ${err.message}`\n\t\t\t\t\t)\n\t\t\t\t\toperations.push({\n\t\t\t\t\t\ttype: 'cli-symlinks',\n\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\tmessage: 'CLI symlink cleanup failed (non-fatal)',\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Step 6: Cleanup database after worktree and branch removal (using pre-read config)\n\t\tif (databaseConfig && worktree) {\n\t\t\tif (options.dryRun) {\n\t\t\t\toperations.push({\n\t\t\t\t\ttype: 'database',\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tmessage: `[DRY RUN] Would cleanup database branch for: ${worktree.branch}`,\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tif (databaseConfig.shouldCleanup && this.database) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Call database deletion with pre-fetched shouldCleanup value and main worktree path\n\t\t\t\t\t\t\t// This avoids reading the already-deleted env file and running commands from deleted directories\n\t\t\t\t\t\t\tconst deletionResult = await this.database.deleteBranchIfConfigured(\n\t\t\t\t\t\t\t\tworktree.branch,\n\t\t\t\t\t\t\t\tdatabaseConfig.shouldCleanup,\n\t\t\t\t\t\t\t\tfalse, // isPreview\n\t\t\t\t\t\t\t\tmainWorktreePath ?? undefined\n\t\t\t\t\t\t\t)\n\n\t\t\t\t\t\t\t// Create operation result based on what actually happened\n\t\t\t\t\t\t\tif (deletionResult.deleted) {\n\t\t\t\t\t\t\t\t// Branch was actually deleted\n\t\t\t\t\t\t\t\tlogger.info(`Database branch deleted: ${worktree.branch}`)\n\t\t\t\t\t\t\t\toperations.push({\n\t\t\t\t\t\t\t\t\ttype: 'database',\n\t\t\t\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\t\t\t\tmessage: `Database branch deleted`,\n\t\t\t\t\t\t\t\t\tdeleted: true,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t} else if (deletionResult.notFound) {\n\t\t\t\t\t\t\t\t// Branch didn't exist - not an error, just nothing to delete\n\t\t\t\t\t\t\t\tlogger.debug(`No database branch found for: ${worktree.branch}`)\n\t\t\t\t\t\t\t\toperations.push({\n\t\t\t\t\t\t\t\t\ttype: 'database',\n\t\t\t\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\t\t\t\tmessage: `No database branch found (skipped)`,\n\t\t\t\t\t\t\t\t\tdeleted: false,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t} else if (deletionResult.userDeclined) {\n\t\t\t\t\t\t\t\t// User declined preview database deletion\n\t\t\t\t\t\t\t\tlogger.info('Preview database deletion declined by user')\n\t\t\t\t\t\t\t\toperations.push({\n\t\t\t\t\t\t\t\t\ttype: 'database',\n\t\t\t\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\t\t\t\tmessage: `Database cleanup skipped (user declined)`,\n\t\t\t\t\t\t\t\t\tdeleted: false,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t} else if (!deletionResult.success) {\n\t\t\t\t\t\t\t\t// Deletion failed with error\n\t\t\t\t\t\t\t\tconst errorMsg = deletionResult.error ?? 'Unknown error'\n\t\t\t\t\t\t\t\terrors.push(new Error(errorMsg))\n\t\t\t\t\t\t\t\tlogger.warn(`Database cleanup failed: ${errorMsg}`)\n\t\t\t\t\t\t\t\toperations.push({\n\t\t\t\t\t\t\t\t\ttype: 'database',\n\t\t\t\t\t\t\t\t\tsuccess: false, // Non-fatal, but report error\n\t\t\t\t\t\t\t\t\tmessage: `Database cleanup failed`,\n\t\t\t\t\t\t\t\t\terror: errorMsg,\n\t\t\t\t\t\t\t\t\tdeleted: false,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// Unexpected state - log for debugging\n\t\t\t\t\t\t\t\terrors.push(new Error('Database cleanup in an unknown state'))\n\t\t\t\t\t\t\t\tlogger.warn('Database deletion returned unexpected result state')\n\t\t\t\t\t\t\t\toperations.push({\n\t\t\t\t\t\t\t\t\ttype: 'database',\n\t\t\t\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\t\t\t\tmessage: `Database cleanup in an unknown state`,\n\t\t\t\t\t\t\t\t\tdeleted: false,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\t// Unexpected exception (shouldn't happen with result object pattern)\n\t\t\t\t\t\t\terrors.push(error instanceof Error ? error : new Error(String(error)))\n\t\t\t\t\t\t\tlogger.warn(\n\t\t\t\t\t\t\t\t`Unexpected database cleanup exception: ${error instanceof Error ? error.message : String(error)}`\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\toperations.push({\n\t\t\t\t\t\t\t\ttype: 'database',\n\t\t\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\t\t\tmessage: `Database cleanup failed`,\n\t\t\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t\t\t\tdeleted: false,\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// Database manager not available or not configured\n\t\t\t\t\t\toperations.push({\n\t\t\t\t\t\t\ttype: 'database',\n\t\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\t\tmessage: `Database cleanup skipped (not available)`,\n\t\t\t\t\t\t\tdeleted: false,\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// This catch block is for any unexpected errors in the outer logic\n\t\t\t\t\tconst err = error instanceof Error ? error : new Error('Unknown error')\n\t\t\t\t\terrors.push(err)\n\t\t\t\t\toperations.push({\n\t\t\t\t\t\ttype: 'database',\n\t\t\t\t\t\tsuccess: false,\n\t\t\t\t\t\tmessage: `Database cleanup failed`,\n\t\t\t\t\t\terror: err.message,\n\t\t\t\t\t\tdeleted: false,\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Calculate overall success\n\t\tconst success = errors.length === 0\n\n\t\treturn {\n\t\t\tidentifier: displayIdentifier,\n\t\t\tbranchName: worktree?.branch,\n\t\t\tsuccess,\n\t\t\toperations,\n\t\t\terrors,\n\t\t\trollbackRequired: false, // Cleanup operations are generally not reversible\n\t\t}\n\t}\n\n\t/**\n\t * Terminate dev server on specified port\n\t */\n\tasync terminateDevServer(port: number): Promise<boolean> {\n\t\tlogger.debug(`Checking for dev server on port ${port}`)\n\n\t\tconst processInfo = await this.processManager.detectDevServer(port)\n\n\t\tif (!processInfo) {\n\t\t\tlogger.debug(`No process found on port ${port}`)\n\t\t\treturn false\n\t\t}\n\n\t\tif (!processInfo.isDevServer) {\n\t\t\tlogger.warn(\n\t\t\t\t`Process on port ${port} (${processInfo.name}) doesn't appear to be a dev server, skipping`\n\t\t\t)\n\t\t\treturn false\n\t\t}\n\n\t\tlogger.info(`Terminating dev server: ${processInfo.name} (PID: ${processInfo.pid})`)\n\n\t\tawait this.processManager.terminateProcess(processInfo.pid)\n\n\t\t// Verify termination\n\t\tconst isFree = await this.processManager.verifyPortFree(port)\n\t\tif (!isFree) {\n\t\t\tthrow new Error(`Dev server may still be running on port ${port}`)\n\t\t}\n\n\t\treturn true\n\t}\n\n\t/**\n\t * Delete a Git branch with safety checks\n\t *\n\t * @param branchName - Name of the branch to delete\n\t * @param options - Delete options (force, dryRun)\n\t * @param cwd - Working directory to execute git command from (defaults to finding main worktree)\n\t */\n\tasync deleteBranch(\n\t\tbranchName: string,\n\t\toptions: BranchDeleteOptions = {},\n\t\tcwd?: string\n\t): Promise<boolean> {\n\t\t// Get protected branches list from centralized method\n\t\tconst protectedBranches = await this.settingsManager.getProtectedBranches(cwd)\n\n\t\t// Check for protected branches\n\t\tif (protectedBranches.includes(branchName)) {\n\t\t\tthrow new Error(`Cannot delete protected branch: ${branchName}`)\n\t\t}\n\n\t\tif (options.dryRun) {\n\t\t\tlogger.info(`[DRY RUN] Would delete branch: ${branchName}`)\n\t\t\treturn true\n\t\t}\n\n\t\t// Use GitWorktreeManager's removeWorktree with removeBranch option\n\t\t// Or execute git branch -D directly via executeGitCommand\n\t\tconst { executeGitCommand, findMainWorktreePathWithSettings } = await import('../utils/git.js')\n\n\t\ttry {\n\t\t\t// Use provided cwd, or find main worktree path as fallback\n\t\t\t// This ensures we're not running git commands from a deleted directory\n\t\t\tlet workingDir = cwd ?? await findMainWorktreePathWithSettings(undefined, this.settingsManager)\t\t\t\n\n\t\t\t// Use safe delete (-d) unless force is specified\n\t\t\tconst deleteFlag = options.force ? '-D' : '-d'\n\t\t\tawait executeGitCommand(['branch', deleteFlag, branchName], {\n\t\t\t\tcwd: workingDir\n\t\t\t})\n\n\t\t\tlogger.info(`Branch deleted: ${branchName}`)\n\t\t\treturn true\n\t\t} catch (error) {\n\t\t\tif (options.force) {\n\t\t\t\tthrow error\n\t\t\t}\n\n\t\t\t// For safe delete failures, check if it's actually an unmerged branch error\n\t\t\t// and provide helpful message only in that case, otherwise show the real error\n\t\t\tconst errorMessage = error instanceof Error ? error.message : String(error)\n\n\t\t\t// Git error for unmerged branch typically contains \"not fully merged\"\n\t\t\tif (errorMessage.includes('not fully merged')) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Cannot delete unmerged branch '${branchName}'. Use --force to delete anyway.`\n\t\t\t\t)\n\t\t\t}\n\n\t\t\t// For other errors (like branch doesn't exist), show the actual git error\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t/**\n\t * Cleanup database branch\n\t * Gracefully handles missing DatabaseManager\n\t *\n\t * @deprecated This method is deprecated and should not be used for post-deletion cleanup.\n\t * Use the pre-fetch mechanism in cleanupWorktree() instead.\n\t * This method will fail if called after worktree deletion because\n\t * it attempts to read the .env file which has been deleted.\n\t *\n\t * @param branchName - Name of the branch to delete\n\t * @param worktreePath - Path to worktree (must still exist with .env file)\n\t */\n\tasync cleanupDatabase(branchName: string, worktreePath: string): Promise<boolean> {\n\t\tif (!this.database) {\n\t\t\tlogger.debug('Database manager not available, skipping database cleanup')\n\t\t\treturn false\n\t\t}\n\n\t\ttry {\n\t\t\t// Pre-fetch configuration before deletion\n\t\t\tconst envFilePath = path.join(worktreePath, '.env')\n\t\t\tconst shouldCleanup = await this.database.shouldUseDatabaseBranching(envFilePath)\n\n\t\t\t// Find main worktree path to avoid running commands from potentially deleted directories\n\t\t\tlet cwd: string | undefined\n\t\t\ttry {\n\t\t\t\tconst { findMainWorktreePathWithSettings } = await import('../utils/git.js')\n\t\t\t\tcwd = await findMainWorktreePathWithSettings(worktreePath, this.settingsManager)\n\t\t\t} catch (error) {\n\t\t\t\t// If we can't find main worktree, commands will run from current directory\n\t\t\t\tlogger.debug(\n\t\t\t\t\t`Could not find main worktree path, using current directory: ${error instanceof Error ? error.message : String(error)}`\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tconst result = await this.database.deleteBranchIfConfigured(\n\t\t\t\tbranchName,\n\t\t\t\tshouldCleanup,\n\t\t\t\tfalse, // isPreview\n\t\t\t\tcwd\n\t\t\t)\n\n\t\t\t// Only return true if deletion actually occurred\n\t\t\tif (result.deleted) {\n\t\t\t\tlogger.info(`Database branch deleted: ${branchName}`)\n\t\t\t\treturn true\n\t\t\t} else if (result.notFound) {\n\t\t\t\tlogger.debug(`No database branch found for: ${branchName}`)\n\t\t\t\treturn false\n\t\t\t} else if (result.userDeclined) {\n\t\t\t\tlogger.info('Preview database deletion declined by user')\n\t\t\t\treturn false\n\t\t\t} else if (!result.success) {\n\t\t\t\tlogger.warn(`Database cleanup failed: ${result.error ?? 'Unknown error'}`)\n\t\t\t\treturn false\n\t\t\t} else {\n\t\t\t\t// Unexpected state\n\t\t\t\tlogger.debug('Database deletion returned unexpected result')\n\t\t\t\treturn false\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Unexpected exception\n\t\t\tlogger.warn(\n\t\t\t\t`Unexpected database cleanup error: ${error instanceof Error ? error.message : String(error)}`\n\t\t\t)\n\t\t\treturn false\n\t\t}\n\t}\n\n\t/**\n\t * Cleanup multiple worktrees\n\t */\n\tasync cleanupMultipleWorktrees(\n\t\tidentifiers: string[],\n\t\toptions: ResourceCleanupOptions = {}\n\t): Promise<CleanupResult[]> {\n\t\tconst results: CleanupResult[] = []\n\n\t\tfor (const identifier of identifiers) {\n\t\t\t// Parse the identifier to get ParsedInput format\n\t\t\tconst parsed = this.parseIdentifier(identifier)\n\t\t\tconst result = await this.cleanupWorktree(parsed, options)\n\t\t\tresults.push(result)\n\t\t}\n\n\t\treturn results\n\t}\n\n\t/**\n\t * Validate worktree safety given a worktree object\n\t * Private method used internally when worktree is already known\n\t */\n\tprivate async validateWorktreeSafety(\n\t\tworktree: GitWorktree,\n\t\tidentifier: string\n\t): Promise<SafetyCheck> {\n\t\tconst warnings: string[] = []\n\t\tconst blockers: string[] = []\n\n\t\t// Check if main worktree\n\t\tconst isMain = await this.gitWorktree.isMainWorktree(worktree, this.settingsManager)\n\t\tif (isMain) {\n\t\t\tblockers.push(`Cannot cleanup main worktree: \"${worktree.branch}\" @ \"${worktree.path}\"`)\n\t\t}\n\n\t\t// Check for uncommitted changes\n\t\tconst { hasUncommittedChanges } = await import('../utils/git.js')\n\t\tconst hasChanges = await hasUncommittedChanges(worktree.path)\n\t\tif (hasChanges) {\n\t\t\t// Create simple blocker message with actionable guidance\n\t\t\tconst blockerMessage =\n\t\t\t\t`Worktree has uncommitted changes.\\n\\n` +\n\t\t\t\t`Please resolve before cleanup - you have some options:\\n` +\n\t\t\t\t` • Commit changes: cd ${worktree.path} && git commit -am \"message\"\\n` +\n\t\t\t\t` • Stash changes: cd ${worktree.path} && git stash\\n` +\n\t\t\t\t` • Force cleanup: il cleanup ${identifier} --force (WARNING: will discard changes)`\n\n\t\t\tblockers.push(blockerMessage)\n\t\t}\n\n\t\treturn {\n\t\t\tisSafe: blockers.length === 0,\n\t\t\twarnings,\n\t\t\tblockers,\n\t\t}\n\t}\n\n\t/**\n\t * Validate cleanup safety\n\t */\n\tasync validateCleanupSafety(identifier: string): Promise<SafetyCheck> {\n\t\tconst warnings: string[] = []\n\t\tconst blockers: string[] = []\n\n\t\t// Find worktree\n\t\tconst worktrees = await this.gitWorktree.findWorktreesByIdentifier(identifier)\n\n\t\tif (worktrees.length === 0) {\n\t\t\tblockers.push(`No worktree found for: ${identifier}`)\n\t\t\treturn { isSafe: false, warnings, blockers }\n\t\t}\n\n\t\tconst worktree = worktrees[0]\n\t\tif (!worktree) {\n\t\t\tblockers.push(`No worktree found for: ${identifier}`)\n\t\t\treturn { isSafe: false, warnings, blockers }\n\t\t}\n\n\t\t// Delegate to private method that validates the worktree\n\t\treturn await this.validateWorktreeSafety(worktree, identifier)\n\t}\n\n\t/**\n\t * Parse identifier to determine type and extract number\n\t * Helper method for port calculation\n\t */\n\tprivate parseIdentifier(identifier: string): ParsedInput {\n\t\t// Check for issue pattern\n\t\tconst issueMatch = identifier.match(/issue-(\\d+)/)\n\t\tif (issueMatch?.[1]) {\n\t\t\treturn {\n\t\t\t\ttype: 'issue',\n\t\t\t\tnumber: parseInt(issueMatch[1], 10),\n\t\t\t\toriginalInput: identifier\n\t\t\t}\n\t\t}\n\n\t\t// Check for PR pattern\n\t\tconst prMatch = identifier.match(/(?:pr|PR)[/-](\\d+)/)\n\t\tif (prMatch?.[1]) {\n\t\t\treturn {\n\t\t\t\ttype: 'pr',\n\t\t\t\tnumber: parseInt(prMatch[1], 10),\n\t\t\t\toriginalInput: identifier\n\t\t\t}\n\t\t}\n\n\t\t// Check for numeric identifier\n\t\tconst numericMatch = identifier.match(/^#?(\\d+)$/)\n\t\tif (numericMatch?.[1]) {\n\t\t\t// Assume issue for numeric identifiers\n\t\t\treturn {\n\t\t\t\ttype: 'issue',\n\t\t\t\tnumber: parseInt(numericMatch[1], 10),\n\t\t\t\toriginalInput: identifier\n\t\t\t}\n\t\t}\n\n\t\t// Treat as branch name\n\t\treturn {\n\t\t\ttype: 'branch',\n\t\t\tbranchName: identifier,\n\t\t\toriginalInput: identifier\n\t\t}\n\t}\n}\n"],"mappings":"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","names":[]}
|