opencode-swarm 7.107.6 → 7.108.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/{capability-probe-wsjzcp48.js → capability-probe-sh9bwh39.js} +2 -1
- package/dist/cli/{config-doctor-kdq3vae4.js → config-doctor-q354tb2w.js} +2 -2
- package/dist/cli/core-vev13ej2.js +34 -0
- package/dist/cli/{curator-drift-ed7p5mfy.js → curator-drift-fdfgj9qf.js} +3 -3
- package/dist/cli/{curator-jpwvkpdv.js → curator-js92gc8a.js} +24 -20
- package/dist/cli/curator-llm-factory-n70bxf40.js +40 -0
- package/dist/cli/{dispatch-anmxxhen.js → dispatch-zr1xja4t.js} +2 -2
- package/dist/cli/{evidence-summary-service-6zsgw7x7.js → evidence-summary-service-bjhr75v0.js} +9 -7
- package/dist/cli/{gate-evidence-pgr7d942.js → gate-evidence-v6ds8rcp.js} +5 -4
- package/dist/cli/guardrail-explain-sn2a4pb7.js +41 -0
- package/dist/cli/{guardrail-log-fjypsmek.js → guardrail-log-8mqqsssq.js} +4 -4
- package/dist/cli/hive-promoter-3hh8ph4a.js +48 -0
- package/dist/cli/{index-9b7qp18e.js → index-1cn967sa.js} +2 -2
- package/dist/cli/{index-572t1qff.js → index-1emhz3zb.js} +1378 -2013
- package/dist/cli/{index-n1sptn1w.js → index-2nt4mq9n.js} +1 -1
- package/dist/cli/{index-6h82c2h0.js → index-48mc4d48.js} +1056 -192
- package/dist/cli/{index-bq8kd9r9.js → index-5gnp8fyw.js} +3 -3
- package/dist/cli/index-5mkc2f9z.js +154 -0
- package/dist/cli/{index-0kxc7t16.js → index-6jng9c8t.js} +1 -1
- package/dist/cli/{index-57rthc1z.js → index-7jyndvsy.js} +2 -2
- package/dist/cli/{index-b9v501fr.js → index-7xgqky26.js} +33 -5
- package/dist/cli/{index-4r5z8sgw.js → index-85bacexr.js} +2 -2
- package/dist/cli/{index-bpgqbwmf.js → index-9qxntjtx.js} +6 -6
- package/dist/cli/index-f1qyj61w.js +418 -0
- package/dist/cli/{index-wvxhynxq.js → index-fm7xz1ne.js} +1 -1
- package/dist/cli/{index-dfdg4ws5.js → index-fz1jgbvw.js} +6 -6
- package/dist/cli/{index-pchpahdf.js → index-h4c4rrwx.js} +20 -3
- package/dist/cli/{index-kxm3bdjh.js → index-mmny81g1.js} +6 -6
- package/dist/cli/{index-v4fcn4tr.js → index-q1exe2b3.js} +2 -198
- package/dist/cli/{index-57ymmh7h.js → index-r3j3458j.js} +4 -4
- package/dist/cli/{index-3naa2ajc.js → index-vvk2g744.js} +10 -156
- package/dist/cli/{index-zej8cy0j.js → index-vx76tcxe.js} +1 -1
- package/dist/cli/{index-xmarctsf.js → index-wg0665ft.js} +7 -7
- package/dist/cli/{index-4vsgp5a8.js → index-wj4jeavn.js} +1 -1
- package/dist/cli/index-wvrj16f0.js +206 -0
- package/dist/cli/{index-h28wfp7n.js → index-x06d2qqm.js} +28 -24
- package/dist/cli/index-x2q0gnt8.js +254 -0
- package/dist/cli/{index-xg18az81.js → index-yw8qpf51.js} +1 -1
- package/dist/cli/index.js +24 -20
- package/dist/cli/{knowledge-escalator-3sgwrgy9.js → knowledge-escalator-6v7sjprx.js} +8 -7
- package/dist/cli/{knowledge-events-kfc6xmkw.js → knowledge-events-6n3x3he2.js} +6 -5
- package/dist/cli/{knowledge-store-kyacem71.js → knowledge-store-exkw6yb1.js} +6 -5
- package/dist/cli/{knowledge-validator-ez3ws8ef.js → knowledge-validator-exymfcb9.js} +7 -6
- package/dist/cli/{pending-delegations-vfnpm8zt.js → pending-delegations-yyz3fcfn.js} +5 -4
- package/dist/cli/{pr-subscriptions-bpvazmsw.js → pr-subscriptions-vv8byxe6.js} +6 -5
- package/dist/cli/{schema-x0ekqzvs.js → schema-x17zmd03.js} +1 -1
- package/dist/cli/scope-persistence-6m5nsp1r.js +20 -0
- package/dist/cli/{skill-generator-x83re96d.js → skill-generator-mx9br4ty.js} +9 -8
- package/dist/commands/_shared/url-security.d.ts +13 -3
- package/dist/commands/close.d.ts +11 -0
- package/dist/commands/lanes.d.ts +35 -0
- package/dist/commands/registry.d.ts +7 -0
- package/dist/config/schema.d.ts +102 -0
- package/dist/git/branch.d.ts +53 -7
- package/dist/git/index.d.ts +5 -1
- package/dist/git/pr.d.ts +35 -2
- package/dist/hooks/delegation-gate/worktree-isolation.d.ts +118 -2
- package/dist/hooks/delegation-gate/worktree-merge-status.d.ts +17 -0
- package/dist/hooks/init-orphan-recovery-advisory.d.ts +58 -0
- package/dist/hooks/init-orphan-recovery.d.ts +65 -0
- package/dist/index.js +427 -416
- package/dist/sandbox/executor.d.ts +11 -1
- package/dist/sandbox/linux/bubblewrap-executor.d.ts +3 -1
- package/dist/sandbox/macos/sandbox-exec-executor.d.ts +3 -1
- package/dist/sandbox/win32/native-sandbox-executor.d.ts +1 -1
- package/dist/sandbox/win32/restricted-environment-executor.d.ts +4 -1
- package/dist/turbo/lean/runner.d.ts +11 -20
- package/dist/turbo/lean/worktree.d.ts +9 -3
- package/dist/utils/bun-compat.d.ts +30 -0
- package/dist/worktree/core.d.ts +55 -0
- package/dist/worktree/merge.d.ts +5 -1
- package/dist/worktree/types.d.ts +38 -0
- package/package.json +1 -1
- package/dist/cli/curator-llm-factory-9y15npd5.js +0 -36
- package/dist/cli/guardrail-explain-jk0amzae.js +0 -37
- package/dist/cli/hive-promoter-j2krbdn9.js +0 -44
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
log
|
|
4
|
+
} from "./index-zgwm4ryv.js";
|
|
5
|
+
import {
|
|
6
|
+
bunSpawn
|
|
7
|
+
} from "./index-7xgqky26.js";
|
|
8
|
+
import {
|
|
9
|
+
__require
|
|
10
|
+
} from "./index-a76rekgs.js";
|
|
11
|
+
|
|
12
|
+
// src/worktree/core.ts
|
|
13
|
+
import * as fs from "fs";
|
|
14
|
+
import * as fsPromises from "fs/promises";
|
|
15
|
+
import * as os from "os";
|
|
16
|
+
import * as path from "path";
|
|
17
|
+
var _internals = {
|
|
18
|
+
bunSpawn,
|
|
19
|
+
platform: process.platform,
|
|
20
|
+
sleep: (ms) => new Promise((resolve2) => setTimeout(resolve2, ms)),
|
|
21
|
+
osTmpdir: () => os.tmpdir(),
|
|
22
|
+
getCoreLongPaths: async (directory) => {
|
|
23
|
+
const result = await runGit(["config", "core.longpaths"], directory);
|
|
24
|
+
if (result.exitCode !== 0) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const value = result.stdout.trim().toLowerCase();
|
|
28
|
+
return value === "" ? undefined : value;
|
|
29
|
+
},
|
|
30
|
+
fs: {
|
|
31
|
+
existsSync: fs.existsSync,
|
|
32
|
+
cp: fsPromises.cp,
|
|
33
|
+
cpSync: fs.cpSync,
|
|
34
|
+
symlinkSync: fs.symlinkSync
|
|
35
|
+
},
|
|
36
|
+
writeScopeToDisk: async (directory, taskId, files) => {
|
|
37
|
+
const { writeScopeToDisk: realWrite } = await import("./scope-persistence-6m5nsp1r.js");
|
|
38
|
+
return realWrite(directory, taskId, files);
|
|
39
|
+
},
|
|
40
|
+
writeLaneProfileToDisk: async (_worktreePath, _laneIndex, _envOverrides) => {
|
|
41
|
+
return writeLaneProfileToDiskReal(_worktreePath, _laneIndex, _envOverrides);
|
|
42
|
+
},
|
|
43
|
+
removeLaneProfileFromDisk: async (_worktreePath, _laneIndex) => {
|
|
44
|
+
return removeLaneProfileFromDiskReal(_worktreePath, _laneIndex);
|
|
45
|
+
},
|
|
46
|
+
removeWorktree
|
|
47
|
+
};
|
|
48
|
+
async function writeLaneProfileToDiskReal(worktreePath, laneIndex, envOverrides) {
|
|
49
|
+
const lines = [];
|
|
50
|
+
for (const [key, value] of Object.entries(envOverrides)) {
|
|
51
|
+
if (value === null)
|
|
52
|
+
continue;
|
|
53
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key))
|
|
54
|
+
continue;
|
|
55
|
+
if (value.includes(`
|
|
56
|
+
`) || value.includes("\r")) {
|
|
57
|
+
log("writeLaneProfileToDisk: skipping env var with newline in value", {
|
|
58
|
+
key
|
|
59
|
+
});
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
lines.push(`${key}=${value}`);
|
|
63
|
+
}
|
|
64
|
+
if (lines.length === 0)
|
|
65
|
+
return;
|
|
66
|
+
const lanesDir = path.join(worktreePath, ".swarm", "lanes");
|
|
67
|
+
await fs.promises.mkdir(lanesDir, { recursive: true });
|
|
68
|
+
const envPath = path.join(lanesDir, `${laneIndex}.env`);
|
|
69
|
+
await fs.promises.writeFile(envPath, `${lines.join(`
|
|
70
|
+
`)}
|
|
71
|
+
`, "utf-8");
|
|
72
|
+
}
|
|
73
|
+
async function removeLaneProfileFromDiskReal(worktreePath, laneIndex) {
|
|
74
|
+
const envPath = path.join(worktreePath, ".swarm", "lanes", `${laneIndex}.env`);
|
|
75
|
+
try {
|
|
76
|
+
await fs.promises.unlink(envPath);
|
|
77
|
+
} catch (err) {
|
|
78
|
+
if (err.code !== "ENOENT") {
|
|
79
|
+
console.warn(`[worktree] Failed to remove lane profile ${envPath}: ${err.message}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
var WORKTREE_TIMEOUT_MS = 30000;
|
|
84
|
+
var WIN_PATH_BUDGET = 250;
|
|
85
|
+
async function runGit(args, cwd, timeoutMs = WORKTREE_TIMEOUT_MS) {
|
|
86
|
+
const proc = _internals.bunSpawn(["git", ...args], {
|
|
87
|
+
cwd,
|
|
88
|
+
timeout: timeoutMs,
|
|
89
|
+
stdin: "ignore",
|
|
90
|
+
stdout: "pipe",
|
|
91
|
+
stderr: "pipe",
|
|
92
|
+
env: { ...process.env, LC_ALL: "C" }
|
|
93
|
+
});
|
|
94
|
+
try {
|
|
95
|
+
const exitCode = await proc.exited;
|
|
96
|
+
const stdout = await proc.stdout.text();
|
|
97
|
+
const stderr = await proc.stderr.text();
|
|
98
|
+
return { exitCode, stdout, stderr };
|
|
99
|
+
} finally {
|
|
100
|
+
try {
|
|
101
|
+
proc.kill();
|
|
102
|
+
} catch {}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
async function checkPathBudget(worktreeRoot, directory) {
|
|
106
|
+
if (_internals.platform !== "win32") {
|
|
107
|
+
return { ok: true };
|
|
108
|
+
}
|
|
109
|
+
let longPaths;
|
|
110
|
+
try {
|
|
111
|
+
longPaths = await _internals.getCoreLongPaths(directory);
|
|
112
|
+
} catch {}
|
|
113
|
+
if (longPaths === "true") {
|
|
114
|
+
return { ok: true };
|
|
115
|
+
}
|
|
116
|
+
const proc = _internals.bunSpawn(["git", "ls-files"], {
|
|
117
|
+
cwd: directory,
|
|
118
|
+
timeout: WORKTREE_TIMEOUT_MS,
|
|
119
|
+
stdin: "ignore",
|
|
120
|
+
stdout: "pipe",
|
|
121
|
+
stderr: "ignore",
|
|
122
|
+
env: { ...process.env, LC_ALL: "C" }
|
|
123
|
+
});
|
|
124
|
+
try {
|
|
125
|
+
const exitCode = await proc.exited;
|
|
126
|
+
const stdout = await proc.stdout.text();
|
|
127
|
+
if (exitCode !== 0 || stdout.trim().length === 0) {
|
|
128
|
+
return { ok: true };
|
|
129
|
+
}
|
|
130
|
+
const files = stdout.split(/\r?\n/);
|
|
131
|
+
let longest = 0;
|
|
132
|
+
for (const file of files) {
|
|
133
|
+
if (file.length > longest) {
|
|
134
|
+
longest = file.length;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const totalPathLength = worktreeRoot.length + 1 + longest;
|
|
138
|
+
if (totalPathLength >= WIN_PATH_BUDGET) {
|
|
139
|
+
return {
|
|
140
|
+
ok: false,
|
|
141
|
+
error: `Total path budget exceeded: worktree root "${worktreeRoot}" (${worktreeRoot.length} chars) + longest file "${files.find((f) => f.length === longest)}" (${longest} chars) = ${totalPathLength} chars (budget: ${WIN_PATH_BUDGET})`,
|
|
142
|
+
suggestion: "Set config.worktree_dir to a shorter absolute path, or let the auto-shorten feature relocate the worktree to the system temp directory."
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
return { ok: true };
|
|
146
|
+
} finally {
|
|
147
|
+
try {
|
|
148
|
+
proc.kill();
|
|
149
|
+
} catch {}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
function shortenWorktreePath(_directory, sessionId, laneId) {
|
|
153
|
+
let tmp = _internals.osTmpdir();
|
|
154
|
+
try {
|
|
155
|
+
tmp = fs.realpathSync(tmp);
|
|
156
|
+
} catch {}
|
|
157
|
+
return path.join(tmp, "swwt", sessionId, laneId);
|
|
158
|
+
}
|
|
159
|
+
function makeWorktreeBranchName(sessionId, id, options) {
|
|
160
|
+
if (options.branchStyle === "legacy-lane" && options.purpose === "lane") {
|
|
161
|
+
return `swarm-lane/${sessionId}/${id}`;
|
|
162
|
+
}
|
|
163
|
+
return `swarm/${options.purpose}/${sessionId}/${id}`;
|
|
164
|
+
}
|
|
165
|
+
async function provisionWorktree(directory, id, sessionId, options) {
|
|
166
|
+
const branchName = makeWorktreeBranchName(sessionId, id, options);
|
|
167
|
+
let worktreePath = options.worktreeDir ? path.resolve(directory, options.worktreeDir, sessionId, id) : path.resolve(path.dirname(directory), ".swarm-worktrees", sessionId, id);
|
|
168
|
+
const budgetResult = await checkPathBudget(worktreePath, directory);
|
|
169
|
+
if (budgetResult.ok === false) {
|
|
170
|
+
if (options.worktreeDir) {
|
|
171
|
+
console.warn(`[swarm] Path budget warning: ${budgetResult.error} ${budgetResult.suggestion}`);
|
|
172
|
+
} else {
|
|
173
|
+
const shortPath = shortenWorktreePath(directory, sessionId, id);
|
|
174
|
+
const shortBudget = await checkPathBudget(shortPath, directory);
|
|
175
|
+
if (shortBudget.ok === false) {
|
|
176
|
+
return { error: budgetResult.error };
|
|
177
|
+
}
|
|
178
|
+
worktreePath = shortPath;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
const checkResult = await runGit(["show-ref", "--verify", "--quiet", `refs/heads/${branchName}`], directory);
|
|
182
|
+
if (checkResult.exitCode === 0) {
|
|
183
|
+
const listResult = await runGit(["worktree", "list", "--porcelain"], directory);
|
|
184
|
+
const normalizeGitPath = (p) => {
|
|
185
|
+
const lexical = p.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
186
|
+
try {
|
|
187
|
+
return fs.realpathSync(p).replace(/\\/g, "/").replace(/\/+$/, "");
|
|
188
|
+
} catch {
|
|
189
|
+
return lexical;
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
const expectedPath = normalizeGitPath(worktreePath);
|
|
193
|
+
const entries = [];
|
|
194
|
+
let current = { path: "", branch: undefined };
|
|
195
|
+
if (listResult.exitCode !== 0) {
|
|
196
|
+
const raw = listResult.stderr.trim() || listResult.stdout.trim();
|
|
197
|
+
const bounded = raw.length > 500 ? `${raw.slice(0, 500)}... (truncated)` : raw;
|
|
198
|
+
return {
|
|
199
|
+
error: `worktree enumeration failed: ${bounded}`
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
for (const rawLine of listResult.stdout.split(`
|
|
203
|
+
`)) {
|
|
204
|
+
const line = rawLine.trim();
|
|
205
|
+
if (line.startsWith("worktree ")) {
|
|
206
|
+
if (current.path)
|
|
207
|
+
entries.push(current);
|
|
208
|
+
current = {
|
|
209
|
+
path: normalizeGitPath(line.slice("worktree ".length)),
|
|
210
|
+
branch: undefined
|
|
211
|
+
};
|
|
212
|
+
} else if (line.startsWith("branch ")) {
|
|
213
|
+
current.branch = line.slice("branch ".length);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
if (current.path)
|
|
217
|
+
entries.push(current);
|
|
218
|
+
const branchIsActiveSomewhere = entries.some((e) => e.branch === `refs/heads/${branchName}`);
|
|
219
|
+
const expectedPathIsRegistered = entries.some((e) => e.path === expectedPath);
|
|
220
|
+
if (branchIsActiveSomewhere || expectedPathIsRegistered) {
|
|
221
|
+
return {
|
|
222
|
+
error: `Branch already exists and worktree is active: ${branchName} (owned by another session)`
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
console.warn(`[swarm] adopting existing branch ${branchName} (stale worktree)`);
|
|
226
|
+
const adoptResult = await runGit(["worktree", "add", "-f", worktreePath, branchName], directory);
|
|
227
|
+
if (adoptResult.exitCode !== 0) {
|
|
228
|
+
return {
|
|
229
|
+
error: `Failed to adopt existing worktree: ${adoptResult.stderr.trim() || adoptResult.stdout.trim()}`
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
return {
|
|
233
|
+
worktreePath,
|
|
234
|
+
branchName,
|
|
235
|
+
purpose: options.purpose,
|
|
236
|
+
id,
|
|
237
|
+
sessionId
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
const addResult = await runGit(["worktree", "add", "-b", branchName, worktreePath, "HEAD"], directory);
|
|
241
|
+
if (addResult.exitCode !== 0) {
|
|
242
|
+
return {
|
|
243
|
+
error: `Failed to create worktree: ${addResult.stderr.trim() || addResult.stdout.trim()}`
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
const strategy = options.depsStrategy ?? "skip";
|
|
247
|
+
if (strategy !== "skip") {
|
|
248
|
+
const hostDepDir = path.join(directory, "node_modules");
|
|
249
|
+
const laneDepDir = path.join(worktreePath, "node_modules");
|
|
250
|
+
if (_internals.fs.existsSync(hostDepDir)) {
|
|
251
|
+
try {
|
|
252
|
+
if (strategy === "copy") {
|
|
253
|
+
await _internals.fs.cp(hostDepDir, laneDepDir, {
|
|
254
|
+
recursive: true,
|
|
255
|
+
force: true
|
|
256
|
+
});
|
|
257
|
+
} else if (strategy === "link") {
|
|
258
|
+
const isWindows = _internals.platform === "win32";
|
|
259
|
+
_internals.fs.symlinkSync(hostDepDir, laneDepDir, isWindows ? "junction" : "dir");
|
|
260
|
+
}
|
|
261
|
+
} catch (e) {
|
|
262
|
+
console.warn(`[swarm] deps_strategy '${strategy}' preparation failed for ${id}: ${e instanceof Error ? e.message : String(e)}`);
|
|
263
|
+
}
|
|
264
|
+
} else {
|
|
265
|
+
return {
|
|
266
|
+
error: `WORKTREE_DEPS_STRATEGY_HOST_DIR_MISSING: deps_strategy ${strategy} requires node_modules at ${hostDepDir} but it does not exist`
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
if (options.scope?.taskId && Array.isArray(options.scope.files)) {
|
|
271
|
+
try {
|
|
272
|
+
await _internals.writeScopeToDisk(worktreePath, options.scope.taskId, options.scope.files);
|
|
273
|
+
} catch {}
|
|
274
|
+
}
|
|
275
|
+
if (options.laneProfile) {
|
|
276
|
+
try {
|
|
277
|
+
await _internals.writeLaneProfileToDisk(worktreePath, options.laneProfile.laneIndex, options.laneProfile.envOverrides);
|
|
278
|
+
} catch {}
|
|
279
|
+
}
|
|
280
|
+
return {
|
|
281
|
+
worktreePath,
|
|
282
|
+
branchName,
|
|
283
|
+
purpose: options.purpose,
|
|
284
|
+
id,
|
|
285
|
+
sessionId
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
async function removeWorktree(worktreePath, projectRoot) {
|
|
289
|
+
const isWindows = _internals.platform === "win32";
|
|
290
|
+
const MAX_RETRIES = 4;
|
|
291
|
+
const RETRY_DELAY_MS = 2000;
|
|
292
|
+
let lastError = "";
|
|
293
|
+
for (let attempt = 0;attempt < MAX_RETRIES; attempt++) {
|
|
294
|
+
const result = await runGit(["worktree", "remove", worktreePath], projectRoot);
|
|
295
|
+
if (result.exitCode === 0) {
|
|
296
|
+
return { success: true };
|
|
297
|
+
}
|
|
298
|
+
lastError = result.stderr.trim() || result.stdout.trim();
|
|
299
|
+
if (isWindows && (lastError.includes("EBUSY") || lastError.includes("EPERM")) && attempt < MAX_RETRIES - 1) {
|
|
300
|
+
await _internals.sleep(RETRY_DELAY_MS);
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
return { error: lastError };
|
|
304
|
+
}
|
|
305
|
+
return { error: lastError };
|
|
306
|
+
}
|
|
307
|
+
async function isCleanWorktree(worktreePath) {
|
|
308
|
+
const [statusResult, untrackedResult] = await Promise.all([
|
|
309
|
+
runGit(["status", "--porcelain"], worktreePath),
|
|
310
|
+
runGit(["ls-files", "--others", "--exclude-standard"], worktreePath)
|
|
311
|
+
]);
|
|
312
|
+
if (statusResult.exitCode !== 0 || untrackedResult.exitCode !== 0) {
|
|
313
|
+
return false;
|
|
314
|
+
}
|
|
315
|
+
const hasChanges = statusResult.stdout.trim().length > 0;
|
|
316
|
+
const hasUntracked = untrackedResult.stdout.trim().length > 0;
|
|
317
|
+
return !hasChanges && !hasUntracked;
|
|
318
|
+
}
|
|
319
|
+
async function autoCommitDirty(worktreePath) {
|
|
320
|
+
const COMMIT_MESSAGE = "swarm-lane: auto-commit before cleanup";
|
|
321
|
+
const addResult = await runGit(["add", "-A"], worktreePath);
|
|
322
|
+
if (addResult.exitCode !== 0) {
|
|
323
|
+
return {
|
|
324
|
+
committed: false,
|
|
325
|
+
reason: `git add failed: ${addResult.stderr.trim() || addResult.stdout.trim()}`
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
const commitResult = await runGit(["commit", "-m", COMMIT_MESSAGE], worktreePath);
|
|
329
|
+
if (commitResult.exitCode !== 0) {
|
|
330
|
+
const stderr = commitResult.stderr.trim();
|
|
331
|
+
const stdout = commitResult.stdout.trim();
|
|
332
|
+
if (stderr.includes("nothing to commit") || stdout.includes("nothing to commit") || stderr.includes("nothing added to commit")) {
|
|
333
|
+
return { committed: false, reason: "Nothing to commit" };
|
|
334
|
+
}
|
|
335
|
+
return {
|
|
336
|
+
committed: false,
|
|
337
|
+
reason: `git commit failed: ${stderr || stdout}`
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
return { committed: true, message: COMMIT_MESSAGE };
|
|
341
|
+
}
|
|
342
|
+
var SAFE_CLEAN_PATTERNS = [
|
|
343
|
+
"dist/",
|
|
344
|
+
"build/",
|
|
345
|
+
".turbo/",
|
|
346
|
+
"coverage/",
|
|
347
|
+
"node_modules/.cache/",
|
|
348
|
+
".log",
|
|
349
|
+
".tmp",
|
|
350
|
+
".o",
|
|
351
|
+
".pyc",
|
|
352
|
+
".class"
|
|
353
|
+
];
|
|
354
|
+
function isSafeToClean(candidatePath) {
|
|
355
|
+
const normalized = candidatePath.replace(/\\/g, "/").toLowerCase();
|
|
356
|
+
return SAFE_CLEAN_PATTERNS.some((pattern) => {
|
|
357
|
+
const p = pattern.toLowerCase();
|
|
358
|
+
if (p.endsWith("/")) {
|
|
359
|
+
return normalized.startsWith(p) || normalized.includes(`/${p}`);
|
|
360
|
+
}
|
|
361
|
+
return normalized.endsWith(p);
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
async function cleanUntrackedFiles(worktreePath) {
|
|
365
|
+
const dryRun = await runGit(["clean", "-fdn"], worktreePath);
|
|
366
|
+
if (dryRun.exitCode === 0) {
|
|
367
|
+
const candidates = dryRun.stdout.trim().split(`
|
|
368
|
+
`).map((line) => {
|
|
369
|
+
const match = line.match(/^Would remove (.+)$/);
|
|
370
|
+
return match ? match[1].trim() : "";
|
|
371
|
+
}).filter((p) => p.length > 0);
|
|
372
|
+
const unsafePaths = candidates.filter((p) => !isSafeToClean(p));
|
|
373
|
+
if (unsafePaths.length > 0) {
|
|
374
|
+
console.warn(`[swarm:cleanUntrackedFiles] Skipping clean \u2014 untracked source files detected: ${unsafePaths.join(", ")}`);
|
|
375
|
+
return {
|
|
376
|
+
cleaned: false,
|
|
377
|
+
error: "untracked source files detected \u2014 skipping clean to prevent data loss"
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
const result = await runGit(["clean", "-fd"], worktreePath);
|
|
382
|
+
if (result.exitCode !== 0) {
|
|
383
|
+
return {
|
|
384
|
+
cleaned: false,
|
|
385
|
+
error: result.stderr.trim() || result.stdout.trim()
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
return { cleaned: true };
|
|
389
|
+
}
|
|
390
|
+
async function assertCleanWorkingTree(directory) {
|
|
391
|
+
const [statusResult, untrackedResult] = await Promise.all([
|
|
392
|
+
runGit(["status", "--porcelain"], directory),
|
|
393
|
+
runGit(["ls-files", "--others", "--exclude-standard"], directory)
|
|
394
|
+
]);
|
|
395
|
+
if (statusResult.exitCode !== 0) {
|
|
396
|
+
return {
|
|
397
|
+
clean: false,
|
|
398
|
+
error: `Unable to verify working tree cleanliness: ${statusResult.stderr.trim() || statusResult.stdout.trim()}`
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
if (untrackedResult.exitCode !== 0) {
|
|
402
|
+
return {
|
|
403
|
+
clean: false,
|
|
404
|
+
error: `Unable to verify working tree cleanliness: ${untrackedResult.stderr.trim() || untrackedResult.stdout.trim()}`
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
const hasChanges = statusResult.stdout.trim().length > 0;
|
|
408
|
+
const hasUntracked = untrackedResult.stdout.trim().length > 0;
|
|
409
|
+
if (hasChanges || hasUntracked) {
|
|
410
|
+
return {
|
|
411
|
+
clean: false,
|
|
412
|
+
error: "Working tree has uncommitted changes. Please commit or stash before provisioning worktrees. Run 'git status' for details."
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
return { clean: true };
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
export { _internals, writeLaneProfileToDiskReal, removeLaneProfileFromDiskReal, checkPathBudget, shortenWorktreePath, makeWorktreeBranchName, provisionWorktree, removeWorktree, isCleanWorktree, autoCommitDirty, cleanUntrackedFiles, assertCleanWorkingTree };
|
|
@@ -6,20 +6,20 @@ import {
|
|
|
6
6
|
resolveSwarmKnowledgePath,
|
|
7
7
|
resolveSwarmRejectedPath,
|
|
8
8
|
transactKnowledge
|
|
9
|
-
} from "./index-
|
|
9
|
+
} from "./index-wg0665ft.js";
|
|
10
10
|
import {
|
|
11
11
|
resolveKnowledgeStoreDir
|
|
12
|
-
} from "./index-
|
|
13
|
-
import {
|
|
14
|
-
atomicWriteFile
|
|
15
|
-
} from "./index-9b7qp18e.js";
|
|
12
|
+
} from "./index-2nt4mq9n.js";
|
|
16
13
|
import {
|
|
17
14
|
init_logger,
|
|
18
15
|
warn
|
|
19
16
|
} from "./index-zgwm4ryv.js";
|
|
17
|
+
import {
|
|
18
|
+
atomicWriteFile
|
|
19
|
+
} from "./index-1cn967sa.js";
|
|
20
20
|
import {
|
|
21
21
|
require_proper_lockfile
|
|
22
|
-
} from "./index-
|
|
22
|
+
} from "./index-vvk2g744.js";
|
|
23
23
|
import {
|
|
24
24
|
__toESM
|
|
25
25
|
} from "./index-a76rekgs.js";
|
|
@@ -1956,7 +1956,16 @@ var WorktreeIsolationConfigSchema = exports_external.object({
|
|
|
1956
1956
|
policy: exports_external.enum(["auto", "required", "disabled"]).default("auto"),
|
|
1957
1957
|
merge_strategy: exports_external.enum(["merge", "rebase", "cherry-pick"]).default("merge"),
|
|
1958
1958
|
worktree_dir: exports_external.string().optional(),
|
|
1959
|
-
deps_strategy: exports_external.enum(["skip", "copy", "link"]).default("skip")
|
|
1959
|
+
deps_strategy: exports_external.enum(["skip", "copy", "link"]).default("skip"),
|
|
1960
|
+
serialization_release_after_dispatches: exports_external.number().int().positive().default(5),
|
|
1961
|
+
serialization_release_after_ms: exports_external.number().int().positive().default(60000),
|
|
1962
|
+
runtime_isolation: exports_external.object({
|
|
1963
|
+
enabled: exports_external.boolean().default(false),
|
|
1964
|
+
port_base: exports_external.number().int().nonnegative().max(65535).optional(),
|
|
1965
|
+
port_stride: exports_external.number().int().positive().default(1),
|
|
1966
|
+
env_overrides: exports_external.record(exports_external.string(), exports_external.string()).optional(),
|
|
1967
|
+
cache_redirects: exports_external.record(exports_external.string(), exports_external.string()).optional()
|
|
1968
|
+
}).optional()
|
|
1960
1969
|
});
|
|
1961
1970
|
var LeanTurboConfigSchema = exports_external.object({
|
|
1962
1971
|
max_parallel_coders: exports_external.number().int().min(1).max(6).default(4),
|
|
@@ -1967,9 +1976,17 @@ var LeanTurboConfigSchema = exports_external.object({
|
|
|
1967
1976
|
phase_critic: exports_external.boolean().default(true),
|
|
1968
1977
|
integrated_diff_required: exports_external.boolean().default(true),
|
|
1969
1978
|
allow_docs_only_without_reviewer: exports_external.boolean().default(false),
|
|
1970
|
-
worktree_isolation: exports_external.boolean().default(
|
|
1979
|
+
worktree_isolation: exports_external.boolean().default(true),
|
|
1971
1980
|
merge_strategy: exports_external.enum(["merge", "rebase", "cherry-pick"]).default("merge").optional(),
|
|
1972
|
-
worktree_dir: exports_external.string().optional()
|
|
1981
|
+
worktree_dir: exports_external.string().optional(),
|
|
1982
|
+
deps_strategy: exports_external.enum(["skip", "copy", "link"]).optional(),
|
|
1983
|
+
runtime_isolation: exports_external.object({
|
|
1984
|
+
enabled: exports_external.boolean().default(false),
|
|
1985
|
+
port_base: exports_external.number().int().nonnegative().max(65535).optional(),
|
|
1986
|
+
port_stride: exports_external.number().int().positive().default(1),
|
|
1987
|
+
env_overrides: exports_external.record(exports_external.string(), exports_external.string()).optional(),
|
|
1988
|
+
cache_redirects: exports_external.record(exports_external.string(), exports_external.string()).optional()
|
|
1989
|
+
}).optional()
|
|
1973
1990
|
});
|
|
1974
1991
|
var EpicConfigSchema = exports_external.object({
|
|
1975
1992
|
cochange: exports_external.object({
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
import {
|
|
3
3
|
resolveKnowledgeStoreDir
|
|
4
|
-
} from "./index-
|
|
5
|
-
import {
|
|
6
|
-
atomicWriteFile
|
|
7
|
-
} from "./index-9b7qp18e.js";
|
|
4
|
+
} from "./index-2nt4mq9n.js";
|
|
8
5
|
import {
|
|
9
6
|
init_logger,
|
|
10
7
|
warn
|
|
11
8
|
} from "./index-zgwm4ryv.js";
|
|
9
|
+
import {
|
|
10
|
+
atomicWriteFile
|
|
11
|
+
} from "./index-1cn967sa.js";
|
|
12
12
|
import {
|
|
13
13
|
require_proper_lockfile
|
|
14
|
-
} from "./index-
|
|
14
|
+
} from "./index-vvk2g744.js";
|
|
15
15
|
import {
|
|
16
16
|
__require,
|
|
17
17
|
__toESM
|
|
@@ -594,7 +594,7 @@ async function applyKnowledgeVerdictFeedback(directory, options) {
|
|
|
594
594
|
deltas.push({ id, delta });
|
|
595
595
|
}
|
|
596
596
|
if (deltas.length > 0) {
|
|
597
|
-
const { bumpKnowledgeConfidenceBatch } = await import("./knowledge-store-
|
|
597
|
+
const { bumpKnowledgeConfidenceBatch } = await import("./knowledge-store-exkw6yb1.js");
|
|
598
598
|
await bumpKnowledgeConfidenceBatch(directory, deltas, options?.floorOptions);
|
|
599
599
|
}
|
|
600
600
|
return {
|