@iloom/cli 0.10.0 → 0.10.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/LICENSE +1 -1
- package/README.md +2 -2
- package/dist/{BranchNamingService-ECJHBB67.js → BranchNamingService-25KSZAEM.js} +2 -2
- package/dist/ClaudeContextManager-66GR4BGM.js +14 -0
- package/dist/ClaudeService-7KM5NA5Z.js +13 -0
- package/dist/{LoomLauncher-L64HHS3T.js → LoomLauncher-TDLZSYG2.js} +6 -6
- package/dist/{PromptTemplateManager-DULSVRRE.js → PromptTemplateManager-YOE2SIPG.js} +2 -2
- package/dist/README.md +2 -2
- package/dist/{SettingsManager-BQDQA3FK.js → SettingsManager-FNKCOZMQ.js} +2 -2
- package/dist/{build-5GO3XW26.js → build-VHGEMXBA.js} +6 -6
- package/dist/chunk-4E7LCFUG.js +24 -0
- package/dist/chunk-4E7LCFUG.js.map +1 -0
- package/dist/{chunk-MNHZB4Z2.js → chunk-4FGEGQW4.js} +3 -3
- package/dist/{chunk-LXLMMXXY.js → chunk-5FJWO4IT.js} +17 -12
- package/dist/chunk-5FJWO4IT.js.map +1 -0
- package/dist/{chunk-ZHPNZC75.js → chunk-5RPBYK5Q.js} +26 -21
- package/dist/chunk-5RPBYK5Q.js.map +1 -0
- package/dist/{chunk-WY4QBK43.js → chunk-63QWFWH3.js} +2 -2
- package/dist/{chunk-YYAKPQBT.js → chunk-7VHJNVLF.js} +19 -9
- package/dist/chunk-7VHJNVLF.js.map +1 -0
- package/dist/{chunk-SF2P22EE.js → chunk-C6HNNJIV.js} +2 -2
- package/dist/{chunk-5MWV33NN.js → chunk-CVCTIDDK.js} +2 -2
- package/dist/{chunk-RYWFS37M.js → chunk-E6KOWMKA.js} +2 -2
- package/dist/{chunk-6EU6TCF6.js → chunk-EVPZFV3K.js} +5 -5
- package/dist/{chunk-ZEWU5PZK.js → chunk-G5V75JD5.js} +2 -2
- package/dist/chunk-GRISNU6G.js +651 -0
- package/dist/chunk-GRISNU6G.js.map +1 -0
- package/dist/{chunk-VGGST52X.js → chunk-I5T677EA.js} +2 -2
- package/dist/{chunk-VECNX6VX.js → chunk-KIK2ZFAL.js} +2 -2
- package/dist/{chunk-FB47TIJG.js → chunk-KKV5WH5M.js} +4 -23
- package/dist/chunk-KKV5WH5M.js.map +1 -0
- package/dist/{chunk-ZW2LKWWE.js → chunk-KVHIAWVT.js} +3 -3
- package/dist/{chunk-3D7WQM7I.js → chunk-LLHXQS3C.js} +2 -2
- package/dist/{chunk-Y4YZTHZE.js → chunk-LUKXJSRI.js} +2 -2
- package/dist/{ignite-CGOV3TD4.js → chunk-OTGH2HRS.js} +105 -71
- package/dist/chunk-OTGH2HRS.js.map +1 -0
- package/dist/{chunk-J5S7DFYC.js → chunk-QVLPWNE3.js} +2 -2
- package/dist/chunk-RJ3VBUFK.js +781 -0
- package/dist/chunk-RJ3VBUFK.js.map +1 -0
- package/dist/{chunk-SN3SQCFK.js → chunk-S7PZA6IV.js} +4 -4
- package/dist/{chunk-UWGVCXRF.js → chunk-SKSYYBCU.js} +23 -1
- package/dist/chunk-SKSYYBCU.js.map +1 -0
- package/dist/{chunk-JO2LZ6EQ.js → chunk-SWSJWA2S.js} +2 -2
- package/dist/{chunk-ONQYPICO.js → chunk-UR5DGNUO.js} +60 -6
- package/dist/chunk-UR5DGNUO.js.map +1 -0
- package/dist/{chunk-4WJNIR5O.js → chunk-UUEW5KWB.js} +1 -1
- package/dist/chunk-UUEW5KWB.js.map +1 -0
- package/dist/{chunk-NRSWLOAZ.js → chunk-WXIM2WS7.js} +4 -4
- package/dist/{chunk-UD3WJDIV.js → chunk-ZNMPGMHY.js} +11 -774
- package/dist/chunk-ZNMPGMHY.js.map +1 -0
- package/dist/{claude-P3NQR6IJ.js → claude-7GGEWVEM.js} +2 -2
- package/dist/{cleanup-6UCPVMFG.js → cleanup-6PVAC4NI.js} +19 -17
- package/dist/{cleanup-6UCPVMFG.js.map → cleanup-6PVAC4NI.js.map} +1 -1
- package/dist/cli.js +154 -614
- package/dist/cli.js.map +1 -1
- package/dist/{commit-L3EPY5QG.js → commit-FZR5XDQG.js} +12 -10
- package/dist/commit-FZR5XDQG.js.map +1 -0
- package/dist/{compile-ZS4HYRX5.js → compile-7ALJHZ4N.js} +6 -6
- package/dist/{contribute-ORDDQGSL.js → contribute-5GKLK3BQ.js} +3 -3
- package/dist/{dev-server-FYZ2AQIH.js → dev-server-7SMIB7OF.js} +8 -8
- package/dist/{feedback-TMBXSCM5.js → feedback-G2GJFN2F.js} +10 -8
- package/dist/{feedback-TMBXSCM5.js.map → feedback-G2GJFN2F.js.map} +1 -1
- package/dist/{git-ET64COO3.js → git-GTLKAZRJ.js} +3 -3
- package/dist/ignite-H2O5Y5A2.js +34 -0
- package/dist/ignite-H2O5Y5A2.js.map +1 -0
- package/dist/index.d.ts +113 -18
- package/dist/index.js +177 -12
- package/dist/index.js.map +1 -1
- package/dist/{init-GFQ5W7GK.js → init-32YOKXRL.js} +8 -8
- package/dist/{issues-T4ZZSPEG.js → issues-4UUAQ5K6.js} +3 -3
- package/dist/{lint-6TQXDZ3T.js → lint-AAN2NZWG.js} +6 -6
- package/dist/mcp/harness-server.js +140 -0
- package/dist/mcp/harness-server.js.map +1 -0
- package/dist/mcp/issue-management-server.js +140 -18
- package/dist/mcp/issue-management-server.js.map +1 -1
- package/dist/{open-5QZGXQRF.js → open-FXWW3VI4.js} +8 -8
- package/dist/{plan-U7ZQWLFY.js → plan-RQ5FPIGF.js} +338 -36
- package/dist/plan-RQ5FPIGF.js.map +1 -0
- package/dist/prompts/CLAUDE.md +2 -2
- package/dist/prompts/init-prompt.txt +102 -27
- package/dist/prompts/issue-prompt.txt +46 -0
- package/dist/prompts/plan-prompt.txt +59 -19
- package/dist/prompts/swarm-orchestrator-prompt.txt +107 -80
- package/dist/{rebase-DWIB77KV.js → rebase-6NVLX5V7.js} +17 -8
- package/dist/rebase-6NVLX5V7.js.map +1 -0
- package/dist/{recap-MX63HAKV.js → recap-OMBOKJST.js} +6 -6
- package/dist/{run-O3TFNQFC.js → run-BBXLRIZB.js} +8 -8
- package/dist/schema/settings.schema.json +36 -2
- package/dist/{shell-G6VC2CYR.js → shell-RF7LTND5.js} +5 -5
- package/dist/{summary-FWHAX55O.js → summary-WTQZ7XG2.js} +9 -9
- package/dist/{test-F7JNJZYP.js → test-SGO6I5Z7.js} +6 -6
- package/dist/{test-git-BTAOIUE2.js → test-git-XM4TM65W.js} +3 -3
- package/dist/{test-jira-CHYNV33F.js → test-jira-LDTOYFSD.js} +3 -3
- package/dist/{test-prefix-Q6TFSU6F.js → test-prefix-GBO37XCN.js} +3 -3
- package/dist/{test-webserver-EONCG7E7.js → test-webserver-NZ3JTVLL.js} +5 -5
- package/dist/{vscode-VA5X4P25.js → vscode-6XUGHJKL.js} +5 -5
- package/package.json +1 -1
- package/dist/ClaudeContextManager-QXX6ZFST.js +0 -14
- package/dist/ClaudeService-NJNK2SUH.js +0 -13
- package/dist/chunk-4WJNIR5O.js.map +0 -1
- package/dist/chunk-FB47TIJG.js.map +0 -1
- package/dist/chunk-LXLMMXXY.js.map +0 -1
- package/dist/chunk-ONQYPICO.js.map +0 -1
- package/dist/chunk-UD3WJDIV.js.map +0 -1
- package/dist/chunk-UVD4CZKS.js +0 -101
- package/dist/chunk-UVD4CZKS.js.map +0 -1
- package/dist/chunk-UWGVCXRF.js.map +0 -1
- package/dist/chunk-YYAKPQBT.js.map +0 -1
- package/dist/chunk-ZHPNZC75.js.map +0 -1
- package/dist/commit-L3EPY5QG.js.map +0 -1
- package/dist/ignite-CGOV3TD4.js.map +0 -1
- package/dist/plan-U7ZQWLFY.js.map +0 -1
- package/dist/rebase-DWIB77KV.js.map +0 -1
- /package/dist/{BranchNamingService-ECJHBB67.js.map → BranchNamingService-25KSZAEM.js.map} +0 -0
- /package/dist/{ClaudeContextManager-QXX6ZFST.js.map → ClaudeContextManager-66GR4BGM.js.map} +0 -0
- /package/dist/{ClaudeService-NJNK2SUH.js.map → ClaudeService-7KM5NA5Z.js.map} +0 -0
- /package/dist/{LoomLauncher-L64HHS3T.js.map → LoomLauncher-TDLZSYG2.js.map} +0 -0
- /package/dist/{PromptTemplateManager-DULSVRRE.js.map → PromptTemplateManager-YOE2SIPG.js.map} +0 -0
- /package/dist/{SettingsManager-BQDQA3FK.js.map → SettingsManager-FNKCOZMQ.js.map} +0 -0
- /package/dist/{build-5GO3XW26.js.map → build-VHGEMXBA.js.map} +0 -0
- /package/dist/{chunk-MNHZB4Z2.js.map → chunk-4FGEGQW4.js.map} +0 -0
- /package/dist/{chunk-WY4QBK43.js.map → chunk-63QWFWH3.js.map} +0 -0
- /package/dist/{chunk-SF2P22EE.js.map → chunk-C6HNNJIV.js.map} +0 -0
- /package/dist/{chunk-5MWV33NN.js.map → chunk-CVCTIDDK.js.map} +0 -0
- /package/dist/{chunk-RYWFS37M.js.map → chunk-E6KOWMKA.js.map} +0 -0
- /package/dist/{chunk-6EU6TCF6.js.map → chunk-EVPZFV3K.js.map} +0 -0
- /package/dist/{chunk-ZEWU5PZK.js.map → chunk-G5V75JD5.js.map} +0 -0
- /package/dist/{chunk-VGGST52X.js.map → chunk-I5T677EA.js.map} +0 -0
- /package/dist/{chunk-VECNX6VX.js.map → chunk-KIK2ZFAL.js.map} +0 -0
- /package/dist/{chunk-ZW2LKWWE.js.map → chunk-KVHIAWVT.js.map} +0 -0
- /package/dist/{chunk-3D7WQM7I.js.map → chunk-LLHXQS3C.js.map} +0 -0
- /package/dist/{chunk-Y4YZTHZE.js.map → chunk-LUKXJSRI.js.map} +0 -0
- /package/dist/{chunk-J5S7DFYC.js.map → chunk-QVLPWNE3.js.map} +0 -0
- /package/dist/{chunk-SN3SQCFK.js.map → chunk-S7PZA6IV.js.map} +0 -0
- /package/dist/{chunk-JO2LZ6EQ.js.map → chunk-SWSJWA2S.js.map} +0 -0
- /package/dist/{chunk-NRSWLOAZ.js.map → chunk-WXIM2WS7.js.map} +0 -0
- /package/dist/{claude-P3NQR6IJ.js.map → claude-7GGEWVEM.js.map} +0 -0
- /package/dist/{compile-ZS4HYRX5.js.map → compile-7ALJHZ4N.js.map} +0 -0
- /package/dist/{contribute-ORDDQGSL.js.map → contribute-5GKLK3BQ.js.map} +0 -0
- /package/dist/{dev-server-FYZ2AQIH.js.map → dev-server-7SMIB7OF.js.map} +0 -0
- /package/dist/{git-ET64COO3.js.map → git-GTLKAZRJ.js.map} +0 -0
- /package/dist/{init-GFQ5W7GK.js.map → init-32YOKXRL.js.map} +0 -0
- /package/dist/{issues-T4ZZSPEG.js.map → issues-4UUAQ5K6.js.map} +0 -0
- /package/dist/{lint-6TQXDZ3T.js.map → lint-AAN2NZWG.js.map} +0 -0
- /package/dist/{open-5QZGXQRF.js.map → open-FXWW3VI4.js.map} +0 -0
- /package/dist/{recap-MX63HAKV.js.map → recap-OMBOKJST.js.map} +0 -0
- /package/dist/{run-O3TFNQFC.js.map → run-BBXLRIZB.js.map} +0 -0
- /package/dist/{shell-G6VC2CYR.js.map → shell-RF7LTND5.js.map} +0 -0
- /package/dist/{summary-FWHAX55O.js.map → summary-WTQZ7XG2.js.map} +0 -0
- /package/dist/{test-F7JNJZYP.js.map → test-SGO6I5Z7.js.map} +0 -0
- /package/dist/{test-git-BTAOIUE2.js.map → test-git-XM4TM65W.js.map} +0 -0
- /package/dist/{test-jira-CHYNV33F.js.map → test-jira-LDTOYFSD.js.map} +0 -0
- /package/dist/{test-prefix-Q6TFSU6F.js.map → test-prefix-GBO37XCN.js.map} +0 -0
- /package/dist/{test-webserver-EONCG7E7.js.map → test-webserver-NZ3JTVLL.js.map} +0 -0
- /package/dist/{vscode-VA5X4P25.js.map → vscode-6XUGHJKL.js.map} +0 -0
|
@@ -0,0 +1,651 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
CLIIsolationManager,
|
|
4
|
+
DatabaseManager,
|
|
5
|
+
EnvironmentManager,
|
|
6
|
+
LoomManager
|
|
7
|
+
} from "./chunk-ZNMPGMHY.js";
|
|
8
|
+
import {
|
|
9
|
+
buildDependencyMap,
|
|
10
|
+
fetchChildIssueDetails,
|
|
11
|
+
fetchChildIssues
|
|
12
|
+
} from "./chunk-QZWEJVWV.js";
|
|
13
|
+
import {
|
|
14
|
+
matchIssueIdentifier
|
|
15
|
+
} from "./chunk-63QWFWH3.js";
|
|
16
|
+
import {
|
|
17
|
+
createNeonProviderFromSettings
|
|
18
|
+
} from "./chunk-P4O6EH46.js";
|
|
19
|
+
import {
|
|
20
|
+
TelemetryService
|
|
21
|
+
} from "./chunk-RSYT7MVI.js";
|
|
22
|
+
import {
|
|
23
|
+
GitWorktreeManager
|
|
24
|
+
} from "./chunk-I5T677EA.js";
|
|
25
|
+
import {
|
|
26
|
+
FirstRunManager
|
|
27
|
+
} from "./chunk-Q7POFB5Q.js";
|
|
28
|
+
import {
|
|
29
|
+
capitalizeFirstLetter
|
|
30
|
+
} from "./chunk-4E7LCFUG.js";
|
|
31
|
+
import {
|
|
32
|
+
ProjectCapabilityDetector
|
|
33
|
+
} from "./chunk-MORRVYPT.js";
|
|
34
|
+
import {
|
|
35
|
+
getConfiguredRepoFromSettings,
|
|
36
|
+
hasMultipleRemotes
|
|
37
|
+
} from "./chunk-FXDYIV3K.js";
|
|
38
|
+
import {
|
|
39
|
+
ClaudeContextManager
|
|
40
|
+
} from "./chunk-E6KOWMKA.js";
|
|
41
|
+
import {
|
|
42
|
+
extractSettingsOverrides
|
|
43
|
+
} from "./chunk-GYCR2LOU.js";
|
|
44
|
+
import {
|
|
45
|
+
DefaultBranchNamingService
|
|
46
|
+
} from "./chunk-QVLPWNE3.js";
|
|
47
|
+
import {
|
|
48
|
+
findMainWorktreePathWithSettings,
|
|
49
|
+
getRepoRoot
|
|
50
|
+
} from "./chunk-4FGEGQW4.js";
|
|
51
|
+
import {
|
|
52
|
+
SettingsManager
|
|
53
|
+
} from "./chunk-7VHJNVLF.js";
|
|
54
|
+
import {
|
|
55
|
+
IssueTrackerFactory
|
|
56
|
+
} from "./chunk-UKBAJ2QQ.js";
|
|
57
|
+
import {
|
|
58
|
+
GitHubService
|
|
59
|
+
} from "./chunk-KXDRI47U.js";
|
|
60
|
+
import {
|
|
61
|
+
getLogger
|
|
62
|
+
} from "./chunk-6MLEBAYZ.js";
|
|
63
|
+
import {
|
|
64
|
+
isInteractiveEnvironment,
|
|
65
|
+
promptConfirmation,
|
|
66
|
+
waitForKeypress
|
|
67
|
+
} from "./chunk-7JDMYTFZ.js";
|
|
68
|
+
import {
|
|
69
|
+
loadEnvIntoProcess,
|
|
70
|
+
logger
|
|
71
|
+
} from "./chunk-VT4PDUYT.js";
|
|
72
|
+
|
|
73
|
+
// src/utils/first-run-setup.ts
|
|
74
|
+
import { existsSync } from "fs";
|
|
75
|
+
import { readFile } from "fs/promises";
|
|
76
|
+
import path from "path";
|
|
77
|
+
import chalk from "chalk";
|
|
78
|
+
async function getProjectRoot() {
|
|
79
|
+
const repoRoot = await getRepoRoot();
|
|
80
|
+
if (repoRoot) {
|
|
81
|
+
logger.debug(`getProjectRoot: Using git repo root: ${repoRoot}`);
|
|
82
|
+
return repoRoot;
|
|
83
|
+
}
|
|
84
|
+
const cwd = process.cwd();
|
|
85
|
+
logger.debug(`getProjectRoot: Not in git repo, using cwd: ${cwd}`);
|
|
86
|
+
return cwd;
|
|
87
|
+
}
|
|
88
|
+
async function needsFirstRunSetup() {
|
|
89
|
+
const projectRoot = await getProjectRoot();
|
|
90
|
+
const firstRunManager = new FirstRunManager();
|
|
91
|
+
const isConfigured = await firstRunManager.isProjectConfigured(projectRoot);
|
|
92
|
+
if (isConfigured) {
|
|
93
|
+
logger.debug("needsFirstRunSetup: Project is tracked as configured globally");
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
const iloomDir = path.join(projectRoot, ".iloom");
|
|
97
|
+
if (!existsSync(iloomDir)) {
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
const settingsPath = path.join(iloomDir, "settings.json");
|
|
101
|
+
const settingsLocalPath = path.join(iloomDir, "settings.local.json");
|
|
102
|
+
const hasSettings = await hasNonEmptySettings(settingsPath);
|
|
103
|
+
const hasLocalSettings = await hasNonEmptySettings(settingsLocalPath);
|
|
104
|
+
return !hasSettings && !hasLocalSettings;
|
|
105
|
+
}
|
|
106
|
+
async function hasNonEmptySettings(filePath) {
|
|
107
|
+
if (!existsSync(filePath)) return false;
|
|
108
|
+
try {
|
|
109
|
+
const content = await readFile(filePath, "utf-8");
|
|
110
|
+
const parsed = JSON.parse(content);
|
|
111
|
+
return Object.keys(parsed).length > 0;
|
|
112
|
+
} catch {
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function displayDefaultsBox() {
|
|
117
|
+
logger.info(chalk.bold("Default Configuration:"));
|
|
118
|
+
logger.info("");
|
|
119
|
+
logger.info(` ${chalk.cyan("Main Branch:")} main`);
|
|
120
|
+
logger.info(` ${chalk.cyan("IDE:")} vscode`);
|
|
121
|
+
logger.info(` ${chalk.cyan("Issue Tracker:")} GitHub Issues`);
|
|
122
|
+
logger.info(` ${chalk.cyan("Merge Mode:")} local ${chalk.dim("(merge locally)")}`);
|
|
123
|
+
logger.info(` ${chalk.cyan("Base Port:")} 3000`);
|
|
124
|
+
}
|
|
125
|
+
async function launchFirstRunSetup() {
|
|
126
|
+
logger.info("First-time project setup detected.");
|
|
127
|
+
logger.info("");
|
|
128
|
+
displayDefaultsBox();
|
|
129
|
+
logger.info("");
|
|
130
|
+
const acceptDefaults = await promptConfirmation(
|
|
131
|
+
"Are these defaults OK?",
|
|
132
|
+
true
|
|
133
|
+
// default to true, so Enter accepts
|
|
134
|
+
);
|
|
135
|
+
if (acceptDefaults) {
|
|
136
|
+
const projectRoot = await getProjectRoot();
|
|
137
|
+
const firstRunManager = new FirstRunManager();
|
|
138
|
+
await firstRunManager.markProjectAsConfigured(projectRoot);
|
|
139
|
+
logger.info(chalk.green("Configuration complete! Using defaults."));
|
|
140
|
+
logger.info("You can run `il init` anytime to customize settings.");
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
logger.info("");
|
|
144
|
+
logger.info("iloom will now launch an interactive configuration session with Claude.");
|
|
145
|
+
await waitForKeypress("Press any key to start configuration...");
|
|
146
|
+
const { InitCommand } = await import("./init-32YOKXRL.js");
|
|
147
|
+
const initCommand = new InitCommand();
|
|
148
|
+
await initCommand.execute(
|
|
149
|
+
"Help me configure iloom settings for this project. This is my first time using iloom here. Note: Your iloom command will execute once we are done with configuration changes."
|
|
150
|
+
);
|
|
151
|
+
logger.info("Configuration complete! Continuing with your original command...");
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// src/commands/start.ts
|
|
155
|
+
import path2 from "path";
|
|
156
|
+
var StartCommand = class {
|
|
157
|
+
constructor(issueTracker, loomManager, _agentManager, settingsManager) {
|
|
158
|
+
this.loomManager = null;
|
|
159
|
+
this.githubService = null;
|
|
160
|
+
this.issueTracker = issueTracker;
|
|
161
|
+
this.settingsManager = settingsManager ?? new SettingsManager();
|
|
162
|
+
this.providedLoomManager = loomManager;
|
|
163
|
+
const envResult = loadEnvIntoProcess();
|
|
164
|
+
if (envResult.error) {
|
|
165
|
+
getLogger().debug(`Environment loading warning: ${envResult.error.message}`);
|
|
166
|
+
}
|
|
167
|
+
if (envResult.parsed) {
|
|
168
|
+
getLogger().debug(`Loaded ${Object.keys(envResult.parsed).length} environment variables`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Get or create a GitHubService instance for PR operations
|
|
173
|
+
* Used when the configured issue tracker doesn't support PRs (e.g., Linear)
|
|
174
|
+
*/
|
|
175
|
+
getGitHubService() {
|
|
176
|
+
this.githubService ??= new GitHubService();
|
|
177
|
+
return this.githubService;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Initialize LoomManager with the main worktree path
|
|
181
|
+
* Uses lazy initialization to ensure we have the correct path
|
|
182
|
+
*/
|
|
183
|
+
async initializeLoomManager() {
|
|
184
|
+
var _a, _b;
|
|
185
|
+
if (this.loomManager) {
|
|
186
|
+
return this.loomManager;
|
|
187
|
+
}
|
|
188
|
+
if (this.providedLoomManager) {
|
|
189
|
+
this.loomManager = this.providedLoomManager;
|
|
190
|
+
return this.loomManager;
|
|
191
|
+
}
|
|
192
|
+
const mainWorktreePath = await findMainWorktreePathWithSettings();
|
|
193
|
+
const settings = await this.settingsManager.loadSettings();
|
|
194
|
+
const environmentManager = new EnvironmentManager();
|
|
195
|
+
const neonProvider = createNeonProviderFromSettings(settings);
|
|
196
|
+
const databaseUrlEnvVarName = ((_b = (_a = settings.capabilities) == null ? void 0 : _a.database) == null ? void 0 : _b.databaseUrlEnvVarName) ?? "DATABASE_URL";
|
|
197
|
+
const databaseManager = new DatabaseManager(neonProvider, environmentManager, databaseUrlEnvVarName);
|
|
198
|
+
const branchNaming = new DefaultBranchNamingService({ useClaude: true });
|
|
199
|
+
this.loomManager = new LoomManager(
|
|
200
|
+
new GitWorktreeManager(mainWorktreePath),
|
|
201
|
+
this.issueTracker,
|
|
202
|
+
branchNaming,
|
|
203
|
+
// Add branch naming service
|
|
204
|
+
environmentManager,
|
|
205
|
+
// Reuse same instance
|
|
206
|
+
new ClaudeContextManager(),
|
|
207
|
+
new ProjectCapabilityDetector(),
|
|
208
|
+
new CLIIsolationManager(),
|
|
209
|
+
this.settingsManager,
|
|
210
|
+
// Use same instance with CLI overrides
|
|
211
|
+
databaseManager
|
|
212
|
+
// Add database manager
|
|
213
|
+
);
|
|
214
|
+
return this.loomManager;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Main entry point for the start command
|
|
218
|
+
*/
|
|
219
|
+
async execute(input) {
|
|
220
|
+
var _a, _b, _c, _d, _e;
|
|
221
|
+
const isJsonMode = input.options.json === true;
|
|
222
|
+
try {
|
|
223
|
+
const initialSettings = await this.settingsManager.loadSettings();
|
|
224
|
+
if (!isJsonMode && (process.env.FORCE_FIRST_TIME_SETUP === "true" || await needsFirstRunSetup())) {
|
|
225
|
+
await launchFirstRunSetup();
|
|
226
|
+
const newSettings = await this.settingsManager.loadSettings();
|
|
227
|
+
const newProvider = ((_a = newSettings.issueManagement) == null ? void 0 : _a.provider) ?? "github";
|
|
228
|
+
if (newProvider !== this.issueTracker.providerName) {
|
|
229
|
+
getLogger().debug(`Reinitializing issue tracker: provider changed to "${newProvider}"`);
|
|
230
|
+
this.issueTracker = IssueTrackerFactory.create(newSettings);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
let repo;
|
|
234
|
+
if (this.issueTracker.providerName === "github" && await hasMultipleRemotes()) {
|
|
235
|
+
repo = await getConfiguredRepoFromSettings(initialSettings);
|
|
236
|
+
getLogger().info(`Using GitHub repository: ${repo}`);
|
|
237
|
+
}
|
|
238
|
+
const loomManager = await this.initializeLoomManager();
|
|
239
|
+
let parentLoom = await this.detectParentLoom(loomManager);
|
|
240
|
+
const parsed = await this.parseInput(input.identifier, repo);
|
|
241
|
+
await this.validateInput(parsed, repo);
|
|
242
|
+
if (parentLoom) {
|
|
243
|
+
const parentDisplay = parentLoom.type === "issue" ? `issue #${parentLoom.identifier}` : parentLoom.type === "pr" ? `PR #${parentLoom.identifier}` : `branch ${parentLoom.identifier}`;
|
|
244
|
+
if (input.options.childLoom === true) {
|
|
245
|
+
getLogger().info(`Creating as child loom of ${parentDisplay} (--child-loom flag)`);
|
|
246
|
+
} else if (input.options.childLoom === false) {
|
|
247
|
+
parentLoom = null;
|
|
248
|
+
getLogger().info("Creating as independent loom (--no-child-loom flag)");
|
|
249
|
+
} else {
|
|
250
|
+
if (isJsonMode) {
|
|
251
|
+
throw new Error("JSON mode requires explicit --child-loom or --no-child-loom flag when running from inside a loom");
|
|
252
|
+
}
|
|
253
|
+
let createAsChild = true;
|
|
254
|
+
if (isInteractiveEnvironment()) {
|
|
255
|
+
createAsChild = await promptConfirmation(
|
|
256
|
+
`You are not in your main worktree. Create as a child loom of ${parentDisplay}?`,
|
|
257
|
+
true
|
|
258
|
+
// Default yes
|
|
259
|
+
);
|
|
260
|
+
} else {
|
|
261
|
+
throw new Error("Non-interactive environment detected, use either --child-loom or --no-child-loom to specify behavior");
|
|
262
|
+
}
|
|
263
|
+
if (!createAsChild) {
|
|
264
|
+
parentLoom = null;
|
|
265
|
+
getLogger().info("Creating as independent loom");
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
} else if (input.options.childLoom === true) {
|
|
269
|
+
getLogger().debug("--child-loom flag provided but not running from inside an existing loom (ignored)");
|
|
270
|
+
}
|
|
271
|
+
if (parsed.type === "description") {
|
|
272
|
+
getLogger().info("Creating issue from description...");
|
|
273
|
+
const title = capitalizeFirstLetter(parsed.originalInput);
|
|
274
|
+
const body = input.options.body ? capitalizeFirstLetter(input.options.body) : "";
|
|
275
|
+
const result = await this.issueTracker.createIssue(
|
|
276
|
+
title,
|
|
277
|
+
// Use capitalized description as title
|
|
278
|
+
body
|
|
279
|
+
// Use capitalized body or empty
|
|
280
|
+
);
|
|
281
|
+
getLogger().success(`Created issue #${result.number}: ${result.url}`);
|
|
282
|
+
parsed.type = "issue";
|
|
283
|
+
parsed.number = result.number;
|
|
284
|
+
}
|
|
285
|
+
let childIssueNumbers = [];
|
|
286
|
+
let childIssues = [];
|
|
287
|
+
let dependencyMap = {};
|
|
288
|
+
if (parsed.type === "issue" && parsed.number) {
|
|
289
|
+
const settings2 = await this.settingsManager.loadSettings();
|
|
290
|
+
const epicIssueTracker = IssueTrackerFactory.create(settings2);
|
|
291
|
+
let children = [];
|
|
292
|
+
try {
|
|
293
|
+
children = await fetchChildIssues(String(parsed.number), epicIssueTracker, repo);
|
|
294
|
+
} catch (error) {
|
|
295
|
+
getLogger().warn(`Failed to check for child issues: ${error instanceof Error ? error.message : "Unknown error"}. Proceeding as normal loom.`);
|
|
296
|
+
}
|
|
297
|
+
if (children.length > 0) {
|
|
298
|
+
childIssueNumbers = children.map((c) => c.id);
|
|
299
|
+
let createAsEpic = false;
|
|
300
|
+
if (input.options.epic === true) {
|
|
301
|
+
createAsEpic = true;
|
|
302
|
+
getLogger().info(`Creating as epic loom with ${children.length} child issue(s) (--epic flag)`);
|
|
303
|
+
} else if (input.options.epic === false) {
|
|
304
|
+
createAsEpic = false;
|
|
305
|
+
getLogger().info("Creating as normal loom (--no-epic flag)");
|
|
306
|
+
} else {
|
|
307
|
+
if (isJsonMode) {
|
|
308
|
+
throw new Error("JSON mode requires explicit --epic or --no-epic flag when issue has child issues");
|
|
309
|
+
}
|
|
310
|
+
if (isInteractiveEnvironment()) {
|
|
311
|
+
createAsEpic = await promptConfirmation(
|
|
312
|
+
`This issue has ${children.length} child issue(s). Create as epic loom?`,
|
|
313
|
+
true
|
|
314
|
+
// Default yes
|
|
315
|
+
);
|
|
316
|
+
} else {
|
|
317
|
+
throw new Error("Non-interactive environment detected, use either --epic or --no-epic to specify behavior");
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
if (createAsEpic) {
|
|
321
|
+
parsed.type = "epic";
|
|
322
|
+
try {
|
|
323
|
+
const [details, depMap] = await Promise.all([
|
|
324
|
+
fetchChildIssueDetails(String(parsed.number), epicIssueTracker, repo),
|
|
325
|
+
buildDependencyMap(childIssueNumbers, settings2, repo)
|
|
326
|
+
]);
|
|
327
|
+
childIssues = details ?? [];
|
|
328
|
+
dependencyMap = depMap ?? {};
|
|
329
|
+
getLogger().info(`Fetched ${childIssues.length} child issue details and dependency map`);
|
|
330
|
+
} catch (error) {
|
|
331
|
+
parsed.type = "issue";
|
|
332
|
+
childIssueNumbers = [];
|
|
333
|
+
getLogger().warn(`Failed to fetch epic child data, reverting to normal loom: ${error instanceof Error ? error.message : String(error)}`);
|
|
334
|
+
}
|
|
335
|
+
} else {
|
|
336
|
+
childIssueNumbers = [];
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
if (input.options.oneShot === "bypassPermissions" && input.options.claude !== false && !isJsonMode) {
|
|
341
|
+
const confirmed = await promptConfirmation(
|
|
342
|
+
"WARNING: bypassPermissions mode will allow Claude to execute all tool calls without confirmation. This can be dangerous. Do you want to proceed?"
|
|
343
|
+
);
|
|
344
|
+
if (!confirmed) {
|
|
345
|
+
getLogger().info("Operation cancelled by user");
|
|
346
|
+
process.exit(0);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
const cliOverrides = extractSettingsOverrides();
|
|
350
|
+
const settings = await this.settingsManager.loadSettings(void 0, cliOverrides);
|
|
351
|
+
const workflowType = parsed.type === "branch" ? "regular" : parsed.type === "epic" ? "issue" : parsed.type;
|
|
352
|
+
const workflowConfig = (_b = settings.workflows) == null ? void 0 : _b[workflowType];
|
|
353
|
+
const { extractRawSetArguments, getExecutablePath } = await import("./cli-overrides-XFZWY7CM.js");
|
|
354
|
+
const setArguments = extractRawSetArguments();
|
|
355
|
+
const executablePath = getExecutablePath();
|
|
356
|
+
getLogger().info(`Validated input: ${this.formatParsedInput(parsed)}`);
|
|
357
|
+
const identifier = parsed.type === "branch" ? parsed.branchName ?? "" : parsed.number ?? 0;
|
|
358
|
+
const enableClaude = input.options.claude ?? (workflowConfig == null ? void 0 : workflowConfig.startAiAgent) ?? true;
|
|
359
|
+
const enableCode = input.options.code ?? (workflowConfig == null ? void 0 : workflowConfig.startIde) ?? true;
|
|
360
|
+
const enableDevServer = input.options.devServer ?? (workflowConfig == null ? void 0 : workflowConfig.startDevServer) ?? true;
|
|
361
|
+
const enableTerminal = input.options.terminal ?? (workflowConfig == null ? void 0 : workflowConfig.startTerminal) ?? false;
|
|
362
|
+
getLogger().debug("Final workflow config values:", {
|
|
363
|
+
enableClaude,
|
|
364
|
+
enableCode,
|
|
365
|
+
enableDevServer,
|
|
366
|
+
enableTerminal
|
|
367
|
+
});
|
|
368
|
+
const loom = await loomManager.createIloom({
|
|
369
|
+
type: parsed.type,
|
|
370
|
+
identifier,
|
|
371
|
+
originalInput: parsed.originalInput,
|
|
372
|
+
...parentLoom && { parentLoom },
|
|
373
|
+
options: {
|
|
374
|
+
enableClaude,
|
|
375
|
+
enableCode,
|
|
376
|
+
enableDevServer,
|
|
377
|
+
enableTerminal,
|
|
378
|
+
...input.options.oneShot && { oneShot: input.options.oneShot },
|
|
379
|
+
...setArguments.length > 0 && { setArguments },
|
|
380
|
+
...executablePath && { executablePath },
|
|
381
|
+
...childIssueNumbers.length > 0 && { childIssueNumbers },
|
|
382
|
+
...childIssues.length > 0 && { childIssues },
|
|
383
|
+
...Object.keys(dependencyMap).length > 0 && { dependencyMap }
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
getLogger().success(`Created loom: ${loom.id} at ${loom.path}`);
|
|
387
|
+
try {
|
|
388
|
+
const oneShotMap = {
|
|
389
|
+
noReview: "skip-reviews",
|
|
390
|
+
bypassPermissions: "yolo"
|
|
391
|
+
};
|
|
392
|
+
TelemetryService.getInstance().track("loom.created", {
|
|
393
|
+
source_type: parsed.type === "epic" ? "issue" : parsed.type,
|
|
394
|
+
tracker: this.issueTracker.providerName,
|
|
395
|
+
is_child_loom: !!parentLoom,
|
|
396
|
+
one_shot_mode: oneShotMap[input.options.oneShot ?? ""] ?? "default"
|
|
397
|
+
});
|
|
398
|
+
} catch (error) {
|
|
399
|
+
getLogger().debug(`Failed to track loom.created telemetry: ${error instanceof Error ? error.message : String(error)}`);
|
|
400
|
+
}
|
|
401
|
+
getLogger().info(` Branch: ${loom.branch}`);
|
|
402
|
+
if ((_c = loom.capabilities) == null ? void 0 : _c.includes("web")) {
|
|
403
|
+
getLogger().info(` Port: ${loom.port}`);
|
|
404
|
+
}
|
|
405
|
+
if ((_d = loom.issueData) == null ? void 0 : _d.title) {
|
|
406
|
+
getLogger().info(` Title: ${loom.issueData.title}`);
|
|
407
|
+
}
|
|
408
|
+
if (parsed.type === "epic") {
|
|
409
|
+
getLogger().info(` Epic: yes (${childIssueNumbers.length} child issue(s))`);
|
|
410
|
+
}
|
|
411
|
+
if (isJsonMode) {
|
|
412
|
+
return {
|
|
413
|
+
id: loom.id,
|
|
414
|
+
path: loom.path,
|
|
415
|
+
branch: loom.branch,
|
|
416
|
+
type: parsed.type,
|
|
417
|
+
identifier: loom.identifier,
|
|
418
|
+
...loom.port !== void 0 && { port: loom.port },
|
|
419
|
+
...((_e = loom.issueData) == null ? void 0 : _e.title) && { title: loom.issueData.title },
|
|
420
|
+
...loom.capabilities && { capabilities: loom.capabilities },
|
|
421
|
+
...childIssueNumbers.length > 0 && { childIssueNumbers }
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
} catch (error) {
|
|
425
|
+
if (error instanceof Error) {
|
|
426
|
+
getLogger().error(`${error.message}`);
|
|
427
|
+
} else {
|
|
428
|
+
getLogger().error("An unknown error occurred");
|
|
429
|
+
}
|
|
430
|
+
throw error;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Parse input to determine type and extract relevant data
|
|
435
|
+
*/
|
|
436
|
+
async parseInput(identifier, repo) {
|
|
437
|
+
const hasLeadingSpace = identifier.startsWith(" ");
|
|
438
|
+
const trimmedIdentifier = identifier.trim();
|
|
439
|
+
if (!trimmedIdentifier) {
|
|
440
|
+
throw new Error("Missing required argument: identifier");
|
|
441
|
+
}
|
|
442
|
+
const spaceCount = (trimmedIdentifier.match(/ /g) ?? []).length;
|
|
443
|
+
if (trimmedIdentifier.length > 15 && spaceCount >= 1) {
|
|
444
|
+
return {
|
|
445
|
+
type: "description",
|
|
446
|
+
originalInput: hasLeadingSpace ? " " + trimmedIdentifier : trimmedIdentifier
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
const prPattern = /^pr[/-](\d+)$/i;
|
|
450
|
+
const prMatch = trimmedIdentifier.match(prPattern);
|
|
451
|
+
if (prMatch == null ? void 0 : prMatch[1]) {
|
|
452
|
+
return {
|
|
453
|
+
type: "pr",
|
|
454
|
+
number: parseInt(prMatch[1], 10),
|
|
455
|
+
originalInput: trimmedIdentifier
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
const identifierMatch = matchIssueIdentifier(trimmedIdentifier);
|
|
459
|
+
if (identifierMatch.type === "project-key" && identifierMatch.identifier) {
|
|
460
|
+
const detection = await this.issueTracker.detectInputType(
|
|
461
|
+
trimmedIdentifier,
|
|
462
|
+
repo
|
|
463
|
+
);
|
|
464
|
+
if (detection.type === "issue" && detection.identifier) {
|
|
465
|
+
return {
|
|
466
|
+
type: "issue",
|
|
467
|
+
number: detection.identifier,
|
|
468
|
+
// Keep as string for project key identifiers
|
|
469
|
+
originalInput: trimmedIdentifier
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
throw new Error(
|
|
473
|
+
`Could not find issue matching identifier ${identifierMatch.identifier}`
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
if (identifierMatch.type === "numeric" && identifierMatch.identifier) {
|
|
477
|
+
const number = parseInt(identifierMatch.identifier, 10);
|
|
478
|
+
if (this.issueTracker.supportsPullRequests) {
|
|
479
|
+
const detection = await this.issueTracker.detectInputType(
|
|
480
|
+
trimmedIdentifier,
|
|
481
|
+
repo
|
|
482
|
+
);
|
|
483
|
+
if (detection.type === "pr") {
|
|
484
|
+
return {
|
|
485
|
+
type: "pr",
|
|
486
|
+
number: detection.identifier ? parseInt(detection.identifier, 10) : number,
|
|
487
|
+
originalInput: trimmedIdentifier
|
|
488
|
+
};
|
|
489
|
+
} else if (detection.type === "issue") {
|
|
490
|
+
return {
|
|
491
|
+
type: "issue",
|
|
492
|
+
number: detection.identifier ? parseInt(detection.identifier, 10) : number,
|
|
493
|
+
originalInput: trimmedIdentifier
|
|
494
|
+
};
|
|
495
|
+
} else {
|
|
496
|
+
throw new Error(`Could not find issue or PR #${number}`);
|
|
497
|
+
}
|
|
498
|
+
} else {
|
|
499
|
+
const githubService = this.getGitHubService();
|
|
500
|
+
const detection = await githubService.detectInputType(trimmedIdentifier, repo);
|
|
501
|
+
if (detection.type === "pr") {
|
|
502
|
+
return {
|
|
503
|
+
type: "pr",
|
|
504
|
+
number: detection.identifier ? parseInt(detection.identifier, 10) : number,
|
|
505
|
+
originalInput: trimmedIdentifier
|
|
506
|
+
};
|
|
507
|
+
} else {
|
|
508
|
+
return {
|
|
509
|
+
type: "issue",
|
|
510
|
+
number,
|
|
511
|
+
originalInput: trimmedIdentifier
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
return {
|
|
517
|
+
type: "branch",
|
|
518
|
+
branchName: trimmedIdentifier,
|
|
519
|
+
originalInput: trimmedIdentifier
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Validate the parsed input based on its type
|
|
524
|
+
*/
|
|
525
|
+
async validateInput(parsed, repo) {
|
|
526
|
+
switch (parsed.type) {
|
|
527
|
+
case "pr": {
|
|
528
|
+
if (!parsed.number) {
|
|
529
|
+
throw new Error("Invalid PR number");
|
|
530
|
+
}
|
|
531
|
+
if (this.issueTracker.supportsPullRequests && this.issueTracker.fetchPR && this.issueTracker.validatePRState) {
|
|
532
|
+
const pr = await this.issueTracker.fetchPR(parsed.number, repo);
|
|
533
|
+
await this.issueTracker.validatePRState(pr);
|
|
534
|
+
} else {
|
|
535
|
+
const githubService = this.getGitHubService();
|
|
536
|
+
const pr = await githubService.fetchPR(parsed.number, repo);
|
|
537
|
+
await githubService.validatePRState(pr);
|
|
538
|
+
}
|
|
539
|
+
getLogger().debug(`Validated PR #${parsed.number}`);
|
|
540
|
+
break;
|
|
541
|
+
}
|
|
542
|
+
case "issue": {
|
|
543
|
+
if (!parsed.number) {
|
|
544
|
+
throw new Error("Invalid issue number");
|
|
545
|
+
}
|
|
546
|
+
const issue = await this.issueTracker.fetchIssue(parsed.number, repo);
|
|
547
|
+
await this.issueTracker.validateIssueState(issue);
|
|
548
|
+
getLogger().debug(`Validated issue #${parsed.number}`);
|
|
549
|
+
break;
|
|
550
|
+
}
|
|
551
|
+
case "branch": {
|
|
552
|
+
if (!parsed.branchName) {
|
|
553
|
+
throw new Error("Invalid branch name");
|
|
554
|
+
}
|
|
555
|
+
if (!this.isValidBranchName(parsed.branchName)) {
|
|
556
|
+
throw new Error(
|
|
557
|
+
"Invalid branch name. Use only letters, numbers, hyphens, underscores, and slashes"
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
getLogger().debug(`Validated branch name: ${parsed.branchName}`);
|
|
561
|
+
break;
|
|
562
|
+
}
|
|
563
|
+
case "description": {
|
|
564
|
+
getLogger().debug("Detected description input", {
|
|
565
|
+
length: parsed.originalInput.length
|
|
566
|
+
});
|
|
567
|
+
break;
|
|
568
|
+
}
|
|
569
|
+
default: {
|
|
570
|
+
const unknownType = parsed;
|
|
571
|
+
throw new Error(`Unknown input type: ${unknownType.type}`);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* Validate branch name format
|
|
577
|
+
*/
|
|
578
|
+
isValidBranchName(branch) {
|
|
579
|
+
return /^[a-zA-Z0-9/_-]+$/.test(branch);
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* Format parsed input for display
|
|
583
|
+
*/
|
|
584
|
+
formatParsedInput(parsed) {
|
|
585
|
+
switch (parsed.type) {
|
|
586
|
+
case "pr":
|
|
587
|
+
return `PR #${parsed.number}`;
|
|
588
|
+
case "issue":
|
|
589
|
+
return `Issue #${parsed.number}`;
|
|
590
|
+
case "epic":
|
|
591
|
+
return `Epic #${parsed.number}`;
|
|
592
|
+
case "branch":
|
|
593
|
+
return `Branch '${parsed.branchName}'`;
|
|
594
|
+
case "description":
|
|
595
|
+
return `Description: ${parsed.originalInput.slice(0, 50)}...`;
|
|
596
|
+
default:
|
|
597
|
+
return "Unknown input";
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* Detect if running from inside an existing loom worktree
|
|
602
|
+
* Returns parent loom info if detected, null otherwise
|
|
603
|
+
*/
|
|
604
|
+
async detectParentLoom(loomManager) {
|
|
605
|
+
try {
|
|
606
|
+
const cwd = process.cwd();
|
|
607
|
+
const looms = await loomManager.listLooms();
|
|
608
|
+
if (!looms) {
|
|
609
|
+
return null;
|
|
610
|
+
}
|
|
611
|
+
const mainWorktreePath = await findMainWorktreePathWithSettings();
|
|
612
|
+
const parentLoom = looms.find((loom) => {
|
|
613
|
+
if (loom.path === mainWorktreePath) {
|
|
614
|
+
return false;
|
|
615
|
+
}
|
|
616
|
+
return cwd === loom.path || cwd.startsWith(loom.path + path2.sep);
|
|
617
|
+
});
|
|
618
|
+
if (!parentLoom) {
|
|
619
|
+
return null;
|
|
620
|
+
}
|
|
621
|
+
getLogger().debug(`Detected parent loom: ${parentLoom.type} ${parentLoom.identifier} at ${parentLoom.path}`);
|
|
622
|
+
const result = {
|
|
623
|
+
type: parentLoom.type,
|
|
624
|
+
identifier: parentLoom.identifier,
|
|
625
|
+
branchName: parentLoom.branch,
|
|
626
|
+
worktreePath: parentLoom.path
|
|
627
|
+
};
|
|
628
|
+
if (parentLoom.databaseBranch) {
|
|
629
|
+
result.databaseBranch = parentLoom.databaseBranch;
|
|
630
|
+
}
|
|
631
|
+
if (!result.databaseBranch) {
|
|
632
|
+
const databaseBranch = await loomManager.getDatabaseBranchForLoom(parentLoom.path);
|
|
633
|
+
if (databaseBranch) {
|
|
634
|
+
result.databaseBranch = databaseBranch;
|
|
635
|
+
getLogger().debug(`Detected parent database branch: ${databaseBranch}`);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
return result;
|
|
639
|
+
} catch (error) {
|
|
640
|
+
getLogger().debug(`Failed to detect parent loom: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
641
|
+
return null;
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
};
|
|
645
|
+
|
|
646
|
+
export {
|
|
647
|
+
needsFirstRunSetup,
|
|
648
|
+
launchFirstRunSetup,
|
|
649
|
+
StartCommand
|
|
650
|
+
};
|
|
651
|
+
//# sourceMappingURL=chunk-GRISNU6G.js.map
|