opencode-swarm 7.144.4 → 7.144.6

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.
Files changed (106) hide show
  1. package/.opencode/skills/swarm-pr-review/references/prompt-templates.md +2 -2
  2. package/dist/background/workspace-snapshot.d.ts +7 -0
  3. package/dist/cli/{capability-probe-f1paszww.js → capability-probe-976tt4ba.js} +6 -2
  4. package/dist/cli/{config-doctor-rw9zrjk6.js → config-doctor-4chz0b95.js} +2 -2
  5. package/dist/cli/{core-zjx9aqaf.js → core-p04nvknr.js} +4 -3
  6. package/dist/cli/{curation-policy-0wbrh11c.js → curation-policy-a511r0qz.js} +4 -4
  7. package/dist/cli/{curator-drift-2jbjv03a.js → curator-drift-ckjm272w.js} +2 -2
  8. package/dist/cli/curator-llm-factory-vc1mrc3r.js +63 -0
  9. package/dist/cli/{curator-g54a7wv0.js → curator-sxeh36gw.js} +33 -32
  10. package/dist/cli/{dispatch-1y1rnv1h.js → dispatch-ndxbsk98.js} +2 -2
  11. package/dist/cli/{evidence-summary-service-fnr5y54e.js → evidence-summary-service-spyxcgsx.js} +13 -12
  12. package/dist/cli/{gate-evidence-2xt1x07r.js → gate-evidence-nz0bwa15.js} +7 -6
  13. package/dist/cli/guardrail-explain-ass47kn8.js +64 -0
  14. package/dist/cli/{guardrail-log-5w4b9zrw.js → guardrail-log-fyzd55fp.js} +4 -4
  15. package/dist/cli/{hive-promoter-x63ehffd.js → hive-promoter-k8gtah3n.js} +33 -32
  16. package/dist/cli/{index-h98t1m88.js → index-01nhedm7.js} +29 -1
  17. package/dist/cli/{index-q4ed1jk7.js → index-42ezdzam.js} +1994 -1333
  18. package/dist/cli/{index-y8j8ehc8.js → index-68mqwvf5.js} +11 -5
  19. package/dist/cli/{index-1csyxv0f.js → index-6z5jtf7d.js} +2 -2
  20. package/dist/cli/{index-2m7mavaz.js → index-7zehmnv1.js} +2 -2
  21. package/dist/cli/index-9e6fdz2h.js +282 -0
  22. package/dist/cli/{index-mazgg5s2.js → index-9s8drsf9.js} +1 -1
  23. package/dist/cli/{index-b6e016tv.js → index-abtrcs16.js} +1 -1
  24. package/dist/cli/{index-8fwhhayc.js → index-b44qqqt2.js} +27 -18
  25. package/dist/cli/{index-yts89pqg.js → index-bac12jpv.js} +4 -4
  26. package/dist/cli/{index-psvxq93b.js → index-ckq719fr.js} +2 -2
  27. package/dist/cli/{index-k3cxyk66.js → index-cwtpqm5f.js} +1 -1
  28. package/dist/cli/{index-d12jd5mn.js → index-dj8cah6s.js} +1 -1
  29. package/dist/cli/{index-pw83zgny.js → index-dvybg11w.js} +3 -3
  30. package/dist/cli/{index-03pv47h2.js → index-ec1kywxg.js} +6 -6
  31. package/dist/cli/{index-74hpm6sh.js → index-f36ybbsv.js} +12 -6
  32. package/dist/cli/{index-az8etqpp.js → index-fgdhf6a5.js} +298 -1179
  33. package/dist/cli/{index-rn0eq85g.js → index-fv0s19g9.js} +1 -1
  34. package/dist/cli/{index-ywn7vtxp.js → index-h1p08s3n.js} +1 -1
  35. package/dist/cli/{index-nckg4gxb.js → index-h5krb653.js} +15 -4
  36. package/dist/cli/{index-bt9aa01f.js → index-hkdgkkhb.js} +1 -1
  37. package/dist/cli/{index-p7cm3gtj.js → index-jqvsh0g3.js} +35 -34
  38. package/dist/cli/{index-x6tp0hfr.js → index-n06653nr.js} +5 -5
  39. package/dist/cli/{index-jabkn643.js → index-n4hwcsbd.js} +2 -2
  40. package/dist/cli/{index-z6v7kwpa.js → index-q6bhmyxb.js} +1 -1
  41. package/dist/cli/{index-cz25e8xp.js → index-sqe3nqh5.js} +166 -34
  42. package/dist/cli/{index-q67jb94n.js → index-sswzhcqb.js} +1 -1
  43. package/dist/cli/{index-8j0va7jp.js → index-tq89td7b.js} +43 -22
  44. package/dist/cli/{index-dty5qgk2.js → index-vdha477y.js} +1 -1
  45. package/dist/cli/{index-zb0xcz9t.js → index-vngs0meh.js} +3 -3
  46. package/dist/cli/{index-fqcjragy.js → index-wknz5c8q.js} +1 -1
  47. package/dist/cli/{index-9qq7c18c.js → index-ytzz6pq1.js} +36 -1
  48. package/dist/cli/{index-4w5qdbk7.js → index-zde2mkmg.js} +6 -6
  49. package/dist/cli/{index-4nt52yr9.js → index-zj6t9zgx.js} +173 -25
  50. package/dist/cli/{index-btmsqv7p.js → index-zxr5r9b7.js} +5 -4
  51. package/dist/cli/index-zy7f84cs.js +1210 -0
  52. package/dist/cli/index.d.ts +11 -1
  53. package/dist/cli/index.js +61 -39
  54. package/dist/cli/{knowledge-escalator-ypg14d5r.js → knowledge-escalator-yaxzz0k5.js} +12 -11
  55. package/dist/cli/{knowledge-events-nkrym4wb.js → knowledge-events-rgcwewpn.js} +10 -9
  56. package/dist/cli/{knowledge-link-e4qgqmpx.js → knowledge-link-4cg4776a.js} +3 -3
  57. package/dist/cli/{knowledge-store-vh3nhtg2.js → knowledge-store-qf8t25sw.js} +4 -4
  58. package/dist/cli/{knowledge-validator-jrxvexv6.js → knowledge-validator-dx6zzcdf.js} +6 -6
  59. package/dist/cli/{pending-delegations-pw79c8ds.js → pending-delegations-9h1jmtw1.js} +3 -3
  60. package/dist/cli/{pr-subscriptions-fk628bhc.js → pr-subscriptions-8pg34pev.js} +3 -3
  61. package/dist/cli/{runner-b02sz2vx.js → runner-cqecp1na.js} +4 -4
  62. package/dist/cli/{scan-cursor-fp7w5jmc.js → scan-cursor-pbcaj8hj.js} +7 -5
  63. package/dist/cli/{schema-rptwqbm4.js → schema-tzcjwe8j.js} +3 -1
  64. package/dist/cli/{scope-persistence-0bkaxawa.js → scope-persistence-mjg4we75.js} +7 -6
  65. package/dist/cli/{skill-generator-nh8b4gjv.js → skill-generator-7jrzbaej.js} +14 -13
  66. package/dist/cli/{workspace-snapshot-w3tg4ne5.js → workspace-snapshot-d89zm6wm.js} +5 -2
  67. package/dist/cli/{worktree-collision-ownership-hqd9ypsz.js → worktree-collision-ownership-vy0kxa98.js} +26 -19
  68. package/dist/cli/{worktree-isolation-canf3rj8.js → worktree-isolation-awpkp0yh.js} +33 -32
  69. package/dist/cli/{worktree-provisioning-owner-g24xd417.js → worktree-provisioning-owner-zzkjycp1.js} +3 -3
  70. package/dist/commands/ci-simulate.d.ts +2 -0
  71. package/dist/config/cache-paths.d.ts +57 -0
  72. package/dist/config/evidence-schema.d.ts +3 -3
  73. package/dist/config/schema.d.ts +9 -0
  74. package/dist/git/branch.d.ts +2 -0
  75. package/dist/git/pr.d.ts +2 -0
  76. package/dist/hooks/delegation-gate/worktree-isolation.d.ts +7 -0
  77. package/dist/hooks/diff-scope.d.ts +7 -0
  78. package/dist/hooks/review-receipt-scope.d.ts +7 -0
  79. package/dist/hooks/reviewer-scope-lifecycle.d.ts +9 -0
  80. package/dist/hooks/semantic-diff-injection.d.ts +8 -0
  81. package/dist/index.js +599 -589
  82. package/dist/mutation/engine.d.ts +11 -0
  83. package/dist/review/diff-source.d.ts +2 -0
  84. package/dist/sandbox/capability-probe.d.ts +22 -0
  85. package/dist/sandbox/executor.d.ts +15 -0
  86. package/dist/sandbox/linux/bubblewrap-executor.d.ts +6 -0
  87. package/dist/sandbox/macos/sandbox-exec-executor.d.ts +41 -0
  88. package/dist/tools/checkpoint.d.ts +11 -0
  89. package/dist/tools/complexity-hotspots.d.ts +15 -0
  90. package/dist/tools/diff-summary.d.ts +12 -0
  91. package/dist/tools/dispatch-lanes.d.ts +8 -0
  92. package/dist/tools/gh-evidence.d.ts +17 -1
  93. package/dist/tools/knowledge-receipt.d.ts +1 -1
  94. package/dist/tools/pkg-audit.d.ts +13 -0
  95. package/dist/tools/prepare-pr-workflow-checkout.d.ts +1 -0
  96. package/dist/utils/bun-compat.d.ts +80 -3
  97. package/dist/utils/git-binary-missing-error.d.ts +80 -2
  98. package/dist/utils/git-executable.d.ts +179 -0
  99. package/dist/utils/gitignore-warning.d.ts +10 -0
  100. package/dist/workflow/coder-settlement.d.ts +18 -0
  101. package/dist/worktree/core.d.ts +8 -0
  102. package/dist/worktree/merge.d.ts +33 -0
  103. package/package.json +3 -2
  104. package/dist/cli/curator-llm-factory-xgb4pxmm.js +0 -62
  105. package/dist/cli/guardrail-explain-6wcgr9tz.js +0 -63
  106. package/dist/cli/index-q1exe2b3.js +0 -256
@@ -6,7 +6,7 @@ import {
6
6
  EvaluationRunV1Schema,
7
7
  GateAuditResultV1Schema,
8
8
  getProtectedEvaluationRunIds
9
- } from "./index-fqcjragy.js";
9
+ } from "./index-wknz5c8q.js";
10
10
  import {
11
11
  readEffectiveSpecSync
12
12
  } from "./index-9ss2m4rs.js";
@@ -14,11 +14,16 @@ import {
14
14
  getWorktreeMergeFailure
15
15
  } from "./index-zsrtt42s.js";
16
16
  import {
17
+ GitBinaryMissingError,
18
+ GitSpawnCwdError,
19
+ isGitBinaryMissing,
20
+ isSpawnCwdMissing,
21
+ isSpawnCwdUnreadable,
17
22
  isValidTaskId,
18
23
  readTaskEvidence,
19
24
  readTaskEvidenceRaw,
20
25
  sanitizeTaskId
21
- } from "./index-cz25e8xp.js";
26
+ } from "./index-sqe3nqh5.js";
22
27
  import {
23
28
  LedgerStaleWriterError,
24
29
  appendLedgerEvent,
@@ -38,14 +43,11 @@ import {
38
43
  replayFromLedgerWithStatus,
39
44
  takeSnapshotEvent,
40
45
  takeSnapshotWithRetry
41
- } from "./index-z6v7kwpa.js";
46
+ } from "./index-q6bhmyxb.js";
42
47
  import {
43
- _internals,
44
- buildDefaultPolicy,
45
- execute,
46
- init_runner_client,
47
- probe
48
- } from "./index-q1exe2b3.js";
48
+ init_executor,
49
+ isValidEnvKey
50
+ } from "./index-zy7f84cs.js";
49
51
  import {
50
52
  EVIDENCE_MAX_JSON_BYTES,
51
53
  EvidenceBundleSchema,
@@ -54,10 +56,16 @@ import {
54
56
  import {
55
57
  readSwarmFileAsync,
56
58
  validateSwarmPath
57
- } from "./index-rn0eq85g.js";
59
+ } from "./index-fv0s19g9.js";
58
60
  import {
59
61
  PlanSchema
60
- } from "./index-9qq7c18c.js";
62
+ } from "./index-ytzz6pq1.js";
63
+ import {
64
+ GIT_BINARY_ENV_VAR,
65
+ describeGitResolution,
66
+ init_git_executable,
67
+ resolveGitExecutable
68
+ } from "./index-9e6fdz2h.js";
61
69
  import {
62
70
  invalidateCachedArtifact,
63
71
  readCachedParsedFile
@@ -78,903 +86,13 @@ import {
78
86
  bunHash,
79
87
  bunWrite,
80
88
  mergeEnvForChild
81
- } from "./index-4nt52yr9.js";
89
+ } from "./index-zj6t9zgx.js";
82
90
  import {
83
91
  criticalWarn,
84
92
  error,
85
93
  init_logger,
86
94
  warn
87
95
  } from "./index-zgwm4ryv.js";
88
- import {
89
- __esm,
90
- __export,
91
- __require,
92
- __toCommonJS
93
- } from "./index-a76rekgs.js";
94
-
95
- // src/sandbox/linux/bubblewrap-executor.ts
96
- import { spawnSync } from "child_process";
97
- function probeBwrap() {
98
- try {
99
- const result = spawnSync("bwrap", ["--version"], {
100
- windowsHide: true,
101
- encoding: "utf-8",
102
- timeout: 5000,
103
- stdio: ["ignore", "pipe", "ignore"]
104
- });
105
- if (result.error) {
106
- const code = result.error.code;
107
- if (code && BWRAP_UNAVAILABLE_CODES.has(code)) {
108
- warn(`Sandbox disabled: bwrap error (${code}). Falling through to tool-layer enforcement.`);
109
- return false;
110
- }
111
- warn(`Sandbox disabled: bwrap spawn error (${result.error.message}). Falling through to tool-layer enforcement.`);
112
- return false;
113
- }
114
- return result.status === BWRAP_VERSION_EXIT && result.stdout.trim().length > 0;
115
- } catch (err) {
116
- const message = err instanceof Error ? err.message : String(err);
117
- warn(`Sandbox disabled: probe threw (${message}). Falling through to tool-layer enforcement.`);
118
- return false;
119
- }
120
- }
121
- function shellEscape(s) {
122
- return s.replace(/'/g, "'\\''");
123
- }
124
-
125
- class BubblewrapSandboxExecutor {
126
- mechanism = "Bubblewrap";
127
- _scopePaths;
128
- _tempDir;
129
- _available;
130
- _disabledReason;
131
- constructor(scopePaths = [], tempDir) {
132
- this._scopePaths = scopePaths;
133
- this._tempDir = tempDir;
134
- this._available = false;
135
- this._disabledReason = null;
136
- try {
137
- if (!_internals2.probeBwrap()) {
138
- this._disabledReason = "bwrap not available or not functional";
139
- warn(`Sandbox disabled: ${this._disabledReason}. Falling through to tool-layer enforcement.`);
140
- } else {
141
- this._available = true;
142
- }
143
- } catch (err) {
144
- const message = err instanceof Error ? err.message : String(err);
145
- this._disabledReason = `constructor threw: ${message}`;
146
- this._available = false;
147
- warn(`Sandbox disabled: ${this._disabledReason}. Falling through to tool-layer enforcement.`);
148
- }
149
- }
150
- isAvailable() {
151
- return this._available;
152
- }
153
- disable(reason) {
154
- this._available = false;
155
- this._disabledReason = reason;
156
- warn(`Sandbox disabled: ${reason}. Falling through to tool-layer enforcement.`);
157
- }
158
- wrapCommand(command, scopePaths, tempDir, envOverrides) {
159
- if (!this._available) {
160
- throw new SandboxError("Sandbox not available", "SANDBOX_UNAVAILABLE");
161
- }
162
- const temp = tempDir ?? this._tempDir ?? "/tmp";
163
- const allScopes = [...this._scopePaths, ...scopePaths];
164
- const bindArgs = allScopes.flatMap((p) => [
165
- "--bind",
166
- `'${shellEscape(p)}'`,
167
- `'${shellEscape(p)}'`
168
- ]);
169
- const envArgs = [];
170
- if (envOverrides) {
171
- for (const [key, value] of Object.entries(envOverrides)) {
172
- if (!isValidEnvKey(key)) {
173
- continue;
174
- }
175
- if (value === null) {
176
- envArgs.push("--unsetenv", key);
177
- } else {
178
- envArgs.push("--setenv", key, value);
179
- }
180
- }
181
- }
182
- const args = [
183
- "--unshare-user",
184
- "--unshare-net",
185
- "--unshare-ipc",
186
- "--die-with-parent",
187
- "--new-session",
188
- "--cap-drop",
189
- "ALL",
190
- ...bindArgs,
191
- "--dev",
192
- "/dev",
193
- "--size",
194
- String(TMPFS_SIZE_BYTES),
195
- "--tmpfs",
196
- `'${shellEscape(temp)}'`,
197
- "--ro-bind",
198
- "/etc",
199
- "/etc",
200
- "--ro-bind",
201
- "/usr",
202
- "/usr",
203
- "--ro-bind",
204
- "/lib",
205
- "/lib",
206
- "--ro-bind",
207
- "/lib64",
208
- "/lib64",
209
- "--proc",
210
- "/proc",
211
- "--unshare-pid",
212
- ...envArgs,
213
- "--",
214
- "bash",
215
- "-c",
216
- `'${shellEscape(command)}'`
217
- ];
218
- return `bwrap ${args.join(" ")}`;
219
- }
220
- getEnvOverrides() {
221
- return {};
222
- }
223
- }
224
- var BWRAP_VERSION_EXIT = 0, BWRAP_UNAVAILABLE_CODES, TMPFS_SIZE_BYTES = 524288000, _internals2;
225
- var init_bubblewrap_executor = __esm(() => {
226
- init_logger();
227
- init_executor();
228
- BWRAP_UNAVAILABLE_CODES = new Set(["ENOENT", "EACCES", "ENOSPC"]);
229
- _internals2 = {
230
- probeBwrap
231
- };
232
- });
233
-
234
- // src/sandbox/executors/bubblewrap.ts
235
- var exports_bubblewrap = {};
236
- __export(exports_bubblewrap, {
237
- BubblewrapSandboxExecutor: () => BubblewrapSandboxExecutor
238
- });
239
- var init_bubblewrap = __esm(() => {
240
- init_bubblewrap_executor();
241
- });
242
-
243
- // src/sandbox/macos/sandbox-exec-executor.ts
244
- import { spawnSync as spawnSync2 } from "child_process";
245
- import { mkdtempSync, writeFileSync } from "fs";
246
- import * as os from "os";
247
- import * as path from "path";
248
- function probeSandboxExec() {
249
- try {
250
- const result = spawnSync2("sandbox-exec", ["--version"], {
251
- windowsHide: true,
252
- encoding: "utf-8",
253
- timeout: 5000,
254
- stdio: ["ignore", "pipe", "ignore"]
255
- });
256
- if (result.error) {
257
- const code = result.error.code;
258
- if (code && SANDBOX_UNAVAILABLE_CODES.has(code)) {
259
- warn(`Sandbox disabled: sandbox-exec error (${code}). Falling through to tool-layer enforcement.`);
260
- return false;
261
- }
262
- warn(`Sandbox disabled: spawn error (${result.error.message}). Falling through to tool-layer enforcement.`);
263
- return false;
264
- }
265
- return result.status === 0;
266
- } catch (err) {
267
- const message = err instanceof Error ? err.message : String(err);
268
- warn(`Sandbox disabled: probe threw (${message}). Falling through to tool-layer enforcement.`);
269
- return false;
270
- }
271
- }
272
- function shellEscape2(s) {
273
- return s.replace(/'/g, "'\\''");
274
- }
275
- function sbplEscapePath(path2) {
276
- const withoutControlChars = path2.split("").filter((ch) => {
277
- const cp = ch.codePointAt(0);
278
- return cp >= 32 && cp !== 127;
279
- }).join("");
280
- return withoutControlChars.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
281
- }
282
- function buildSandboxProfile(scopePaths, tempDir, envOverrides) {
283
- const rwPaths = [...scopePaths];
284
- if (tempDir) {
285
- rwPaths.push(tempDir);
286
- }
287
- const rwAllowLines = rwPaths.map((p) => `(allow file-write* (subpath "${sbplEscapePath(p)}"))`).join(`
288
- `);
289
- const envLines = [];
290
- if (envOverrides) {
291
- for (const [key, value] of Object.entries(envOverrides)) {
292
- if (!isValidEnvKey(key)) {
293
- continue;
294
- }
295
- if (value === null) {
296
- envLines.push(`(unsetenv ${key})`);
297
- } else {
298
- const escaped = value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
299
- envLines.push(`(setenv ${key} "${escaped}")`);
300
- }
301
- }
302
- }
303
- const profile = `(version 1)
304
- (allow default)
305
- (allow file-read* (subpath "/usr"))
306
- (allow file-read* (subpath "/bin"))
307
- (allow file-read* (subpath "/sbin"))
308
- (allow file-read* (subpath "/lib"))
309
- (allow file-read* (subpath "/lib64"))
310
- (deny file-write*)
311
- ${rwAllowLines}
312
- ${envLines.join(`
313
- `)}`;
314
- return profile;
315
- }
316
-
317
- class MacOSSandboxExecutor {
318
- mechanism = "sandbox-exec";
319
- _scopePaths;
320
- _tempDir;
321
- _available;
322
- _disabledReason;
323
- constructor(scopePaths = [], tempDir) {
324
- if (process.platform !== "darwin") {
325
- throw new Error("MacOSSandboxExecutor not yet implemented");
326
- }
327
- this._scopePaths = scopePaths;
328
- this._tempDir = tempDir;
329
- this._available = false;
330
- this._disabledReason = null;
331
- try {
332
- if (!_internals3.probeSandboxExec()) {
333
- this._disabledReason = "sandbox-exec not available or not functional";
334
- warn(`Sandbox disabled: ${this._disabledReason}. Falling through to tool-layer enforcement.`);
335
- } else {
336
- this._available = true;
337
- }
338
- } catch (err) {
339
- const message = err instanceof Error ? err.message : String(err);
340
- this._disabledReason = `constructor threw: ${message}`;
341
- this._available = false;
342
- warn(`Sandbox disabled: ${this._disabledReason}. Falling through to tool-layer enforcement.`);
343
- }
344
- }
345
- isAvailable() {
346
- return this._available;
347
- }
348
- disable(reason) {
349
- this._disabledReason = reason;
350
- this._available = false;
351
- warn(`Sandbox disabled: ${reason}. Falling through to tool-layer enforcement.`);
352
- }
353
- wrapCommand(command, scopePaths, tempDir, envOverrides) {
354
- if (!this._available) {
355
- throw new SandboxError("Sandbox not available", "SANDBOX_UNAVAILABLE");
356
- }
357
- if (!_internals3.probeSandboxExec()) {
358
- this._available = false;
359
- this._disabledReason = "sandbox-exec became unavailable between calls";
360
- warn(`Sandbox disabled: ${this._disabledReason}. Falling through to tool-layer enforcement.`);
361
- throw new SandboxError("Sandbox not available", "SANDBOX_UNAVAILABLE");
362
- }
363
- const temp = tempDir ?? this._tempDir ?? os.tmpdir();
364
- const allScopes = [...this._scopePaths, ...scopePaths];
365
- const profile = buildSandboxProfile(allScopes, temp, envOverrides);
366
- let profilePath;
367
- try {
368
- const profileDir = mkdtempSync(path.join(os.tmpdir(), "sandbox-"));
369
- profilePath = path.join(profileDir, `profile-${process.pid}-${Date.now()}.sb`);
370
- writeFileSync(profilePath, profile, { mode: 384 });
371
- } catch (err) {
372
- const message = err instanceof Error ? err.message : String(err);
373
- warn(`Sandbox disabled: failed to write profile (${message}). Falling through to tool-layer enforcement.`);
374
- throw new SandboxError("Sandbox not available", "SANDBOX_UNAVAILABLE");
375
- }
376
- const escapedCommand = shellEscape2(command);
377
- const escapedProfilePath = shellEscape2(profilePath);
378
- return `sandbox-exec -f '${escapedProfilePath}' bash -c '${escapedCommand}'`;
379
- }
380
- getEnvOverrides() {
381
- return {
382
- DYLD_INSERT_LIBRARIES: null,
383
- DYLD_LIBRARY_PATH: null,
384
- DYLD_FRAMEWORK_PATH: null,
385
- DYLD_ROOT_PATH: null,
386
- PATH: "/usr/bin:/bin:/usr/sbin:/sbin"
387
- };
388
- }
389
- }
390
- var SANDBOX_UNAVAILABLE_CODES, _internals3;
391
- var init_sandbox_exec_executor = __esm(() => {
392
- init_logger();
393
- init_executor();
394
- SANDBOX_UNAVAILABLE_CODES = new Set(["ENOENT", "EACCES", "ENOSPC"]);
395
- _internals3 = {
396
- probeSandboxExec,
397
- buildSandboxProfile
398
- };
399
- });
400
-
401
- // src/sandbox/executors/macos.ts
402
- var exports_macos = {};
403
- __export(exports_macos, {
404
- MacOSSandboxExecutor: () => MacOSSandboxExecutor
405
- });
406
- var init_macos = __esm(() => {
407
- init_sandbox_exec_executor();
408
- });
409
-
410
- // src/sandbox/win32/edge-cases.ts
411
- function detectPowerShellEscape(command) {
412
- if (process.platform !== "win32")
413
- return false;
414
- const encodedCommandPattern = /-EncodedCommand/i;
415
- if (encodedCommandPattern.test(command)) {
416
- return true;
417
- }
418
- const encodedBase64Pattern = /-Enc(odedCommand)?\s+[A-Za-z0-9+/=]+/i;
419
- if (encodedBase64Pattern.test(command)) {
420
- return true;
421
- }
422
- const psExePattern = /powershell\.exe?\s+.*-(?:e(?:n(?:c(?:odedCommand)?)?)?|wmi|remote)/i;
423
- if (psExePattern.test(command)) {
424
- return true;
425
- }
426
- const iexPattern = /\biex\b/i;
427
- if (iexPattern.test(command)) {
428
- return true;
429
- }
430
- const invokeExpressionPattern = /Invoke-Expression/i;
431
- if (invokeExpressionPattern.test(command)) {
432
- return true;
433
- }
434
- const invokeCommandRemotePattern = /Invoke-Command\s+.*-ComputerName/i;
435
- if (invokeCommandRemotePattern.test(command)) {
436
- return true;
437
- }
438
- const psCommandPattern = /powershell.*-Command\s+["'].*\$/i;
439
- if (psCommandPattern.test(command)) {
440
- return true;
441
- }
442
- const execPolicyPattern = /-ExecutionPolicy\s+(?:Bypass|RemoteSigned|Unrestricted)/i;
443
- if (execPolicyPattern.test(command)) {
444
- return true;
445
- }
446
- const noProfilePattern = /-NoProfile\s+-/i;
447
- if (noProfilePattern.test(command)) {
448
- return true;
449
- }
450
- const automationPattern = /New-Object\s+.*Management\.Automation/i;
451
- if (automationPattern.test(command)) {
452
- return true;
453
- }
454
- const downloadPattern = /\[System\.Net\.(?:WebClient|Http).*\]\.(?:DownloadString|DownloadFile)/i;
455
- if (downloadPattern.test(command)) {
456
- return true;
457
- }
458
- const hiddenWindowPattern = /-WindowStyle\s+Hidden/i;
459
- if (hiddenWindowPattern.test(command)) {
460
- return true;
461
- }
462
- const scriptInjectionPattern = /\$(?:env|input|host)\b.*\|/i;
463
- if (scriptInjectionPattern.test(command)) {
464
- return true;
465
- }
466
- const obfuscatedIexPattern = /IEX|i:eX/i;
467
- if (obfuscatedIexPattern.test(command)) {
468
- return true;
469
- }
470
- return false;
471
- }
472
- var init_edge_cases = () => {};
473
-
474
- // src/sandbox/win32/restricted-environment-executor.ts
475
- import { Buffer as Buffer2 } from "buffer";
476
- import { spawnSync as spawnSync3 } from "child_process";
477
- import * as os2 from "os";
478
- import * as path2 from "path";
479
- function containsUnsafePathSyntax(value) {
480
- return [...value].some((character) => character.charCodeAt(0) < 32 || UNSAFE_PATH_CHARACTERS.has(character));
481
- }
482
- function getSafeSystemRoot() {
483
- const raw = process.env.SystemRoot;
484
- if (typeof raw !== "string" || !/^[A-Za-z]:[\\/]/.test(raw) || containsUnsafePathSyntax(raw.slice(2)) || raw.slice(3).split(/[\\/]+/).some((segment) => segment === "." || segment === "..")) {
485
- return DEFAULT_SYSTEM_ROOT;
486
- }
487
- const normalized = path2.win32.normalize(raw);
488
- return normalized.length > 3 ? normalized.replace(/\\+$/, "") : normalized;
489
- }
490
- function getWindowsExecutablePaths() {
491
- const systemRoot = getSafeSystemRoot();
492
- return {
493
- systemRoot,
494
- cmdExe: path2.win32.join(systemRoot, "System32", "cmd.exe"),
495
- powerShellExe: path2.win32.join(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe")
496
- };
497
- }
498
- function probeWindowsSandbox() {
499
- try {
500
- const result = spawnSync3(getWindowsExecutablePaths().cmdExe, ["/d", "/s", "/c", "echo ok"], {
501
- cwd: os2.tmpdir(),
502
- windowsHide: true,
503
- encoding: "utf-8",
504
- timeout: 5000,
505
- stdio: ["ignore", "pipe", "ignore"]
506
- });
507
- if (result.error) {
508
- const code = result.error.code;
509
- if (code && SANDBOX_UNAVAILABLE_CODES2.has(code)) {
510
- warn(`Sandbox disabled: spawn error (${code}). Falling through to tool-layer enforcement.`);
511
- return false;
512
- }
513
- warn(`Sandbox disabled: spawn error (${result.error.message}). Falling through to tool-layer enforcement.`);
514
- return false;
515
- }
516
- return result.status === 0;
517
- } catch (err) {
518
- const message = err instanceof Error ? err.message : String(err);
519
- warn(`Sandbox disabled: probe threw (${message}). Falling through to tool-layer enforcement.`);
520
- return false;
521
- }
522
- }
523
- function psSingleQuoteEscape(s) {
524
- return s.replace(/'/g, "''");
525
- }
526
- function normalizeInheritedPathEntry(rawEntry) {
527
- const entry = rawEntry.trim();
528
- if (!/^[A-Za-z]:[\\/]/.test(entry) || containsUnsafePathSyntax(entry.slice(2)) || entry.slice(3).split(/[\\/]+/).some((segment) => segment === "." || segment === "..")) {
529
- return null;
530
- }
531
- const normalized = path2.win32.normalize(entry);
532
- return normalized.length > 3 ? normalized.replace(/\\+$/, "") : normalized;
533
- }
534
- function getSafeWindowsPath() {
535
- const { systemRoot } = getWindowsExecutablePaths();
536
- const candidates = [
537
- path2.win32.join(systemRoot, "System32"),
538
- systemRoot,
539
- ...(process.env.PATH ?? "").split(";")
540
- ];
541
- const seen = new Set;
542
- const safeEntries = [];
543
- for (const candidate of candidates) {
544
- const normalized = normalizeInheritedPathEntry(candidate);
545
- if (!normalized)
546
- continue;
547
- const identity = normalized.toLowerCase();
548
- if (seen.has(identity))
549
- continue;
550
- seen.add(identity);
551
- safeEntries.push(normalized);
552
- }
553
- return safeEntries.join(";");
554
- }
555
- function isPowerShellNativeCommand(command) {
556
- return /^(?:Remove-Item|rm|del|erase|Copy-Item|cp|copy|Move-Item|mv|move|Rename-Item|ren|New-Item|ni|Get-Item|gi|Get-ChildItem|ls|dir|gci|Get-Content|cat|type|gc|Set-Content|sc|Add-Content|ac|Clear-Content|clc|Test-Path|Resolve-Path|Split-Path|Join-Path|Out-File|Get-Date)\b/i.test(command.trimStart());
557
- }
558
- function isSafePsCommandBody(command) {
559
- return !/[;&|`$()\r\n]/.test(command);
560
- }
561
- function isPathInScopes(command, scopes) {
562
- if (scopes.length === 0)
563
- return true;
564
- const pathPattern = /[A-Za-z]:(?:[^\\/:*?"<>|\r\n]+(?:\\[^\\/:*?"<>|\r\n]+)*)/g;
565
- const paths = command.match(pathPattern) || [];
566
- if (paths.length === 0)
567
- return true;
568
- const normalizedPaths = paths.map((p) => path2.win32.resolve(p));
569
- const normalizedScopes = scopes.map((s) => s.toLowerCase().replace(/\\+$/, ""));
570
- return normalizedPaths.every((p) => {
571
- const lower = p.toLowerCase();
572
- return normalizedScopes.some((scope) => lower.startsWith(scope));
573
- });
574
- }
575
-
576
- class WindowsSandboxExecutor {
577
- mechanism = "powershell-wrapper";
578
- _scopePaths;
579
- _tempDir;
580
- _available;
581
- _disabled;
582
- _disabledReason;
583
- constructor(scopePaths = [], tempDir) {
584
- this._scopePaths = scopePaths;
585
- this._tempDir = tempDir;
586
- this._available = false;
587
- this._disabled = false;
588
- this._disabledReason = null;
589
- try {
590
- if (!_internals4.probeWindowsSandbox()) {
591
- this._available = false;
592
- this._disabledReason = "Windows sandbox not available or not functional";
593
- warn(`Sandbox unavailable: ${this._disabledReason}. Falling through to tool-layer enforcement.`);
594
- } else {
595
- this._available = true;
596
- }
597
- } catch (err) {
598
- const message = err instanceof Error ? err.message : String(err);
599
- this._available = false;
600
- this._disabledReason = `constructor probe threw: ${message}`;
601
- warn(`Sandbox unavailable: ${this._disabledReason}. Falling through to tool-layer enforcement.`);
602
- }
603
- }
604
- isAvailable() {
605
- return this._available && !this._disabled;
606
- }
607
- disable(reason) {
608
- this._disabled = true;
609
- this._disabledReason = reason;
610
- warn(`Sandbox disabled: ${reason}. Falling through to tool-layer enforcement.`);
611
- }
612
- wrapCommand(command, scopePaths, tempDir, envOverrides) {
613
- if (!this.isAvailable()) {
614
- throw new SandboxError("Sandbox not available", "SANDBOX_UNAVAILABLE");
615
- }
616
- if (!_internals4.probeWindowsSandbox()) {
617
- this._available = false;
618
- this._disabledReason = "Windows sandbox became unavailable between calls";
619
- warn(`Sandbox disabled: ${this._disabledReason}. Falling through to tool-layer enforcement.`);
620
- throw new SandboxError("Sandbox not available", "SANDBOX_UNAVAILABLE");
621
- }
622
- const temp = tempDir ?? this._tempDir ?? os2.tmpdir();
623
- const _allScopes = [...this._scopePaths, ...scopePaths];
624
- if (detectPowerShellEscape(command)) {
625
- throw new SandboxError("Command contains PowerShell escape patterns", "DETECT_POWERSHELL_ESCAPE");
626
- }
627
- if (!isPathInScopes(command, _allScopes)) {
628
- throw new SandboxError("Command targets paths outside authorized scopes", "PATH_ESCAPE_SCOPE");
629
- }
630
- if (isPowerShellNativeCommand(command) && !isSafePsCommandBody(command)) {
631
- throw new SandboxError("PowerShell-native command body contains unsafe characters", "UNSAFE_PS_COMMAND");
632
- }
633
- const safePath = getSafeWindowsPath();
634
- const { cmdExe, powerShellExe } = getWindowsExecutablePaths();
635
- const commandBase64 = Buffer2.from(command, "utf8").toString("base64");
636
- const escapedTemp = psSingleQuoteEscape(temp);
637
- const escapedPath = psSingleQuoteEscape(safePath);
638
- const escapedCmdExe = psSingleQuoteEscape(cmdExe);
639
- const envOverrideLines = [];
640
- if (envOverrides) {
641
- for (const [key, value] of Object.entries(envOverrides)) {
642
- if (!isValidEnvKey(key)) {
643
- continue;
644
- }
645
- if (value === null) {
646
- envOverrideLines.push(`Remove-Item Env:${key} -Force -ErrorAction SilentlyContinue;`);
647
- } else {
648
- const psEscaped = psSingleQuoteEscape(value);
649
- envOverrideLines.push(`$env:${key} = '${psEscaped}';`);
650
- }
651
- }
652
- }
653
- const commandExec = isPowerShellNativeCommand(command) ? `Invoke-Expression $command;
654
- exit 0;` : `$batchPath = $null;
655
- $batchLocationPushed = $false;
656
- try {
657
- if ($command.Contains([char]13) -or $command.Contains([char]10)) {
658
- $batchName = 'opencode-swarm-' + [Guid]::NewGuid().ToString('N') + '.cmd';
659
- $batchPath = Join-Path $env:TEMP $batchName;
660
- [IO.File]::WriteAllText($batchPath, $command, [Text.UTF8Encoding]::new($false));
661
- Push-Location -LiteralPath $env:TEMP;
662
- $batchLocationPushed = $true;
663
- & '${escapedCmdExe}' /d /v:off /s /c ('call "' + $batchName + '"');
664
- } else {
665
- & '${escapedCmdExe}' /d /v:off /s /c $command;
666
- }
667
- $childExitCode = $LASTEXITCODE;
668
- } finally {
669
- if ($batchLocationPushed) {
670
- Pop-Location;
671
- }
672
- if ($null -ne $batchPath) {
673
- Remove-Item -LiteralPath $batchPath -Force -ErrorAction SilentlyContinue;
674
- }
675
- }
676
- if ($null -eq $childExitCode) {
677
- throw 'cmd.exe did not report an exit code';
678
- }
679
- exit [int]$childExitCode;`;
680
- const envOverrideBlock = envOverrideLines.length > 0 ? `
681
- ${envOverrideLines.join(`
682
- `)}` : "";
683
- const psScript = `
684
- $ErrorActionPreference = 'Stop';
685
- $ProgressPreference = 'SilentlyContinue';
686
- try {
687
- $env:TEMP = '${escapedTemp}';
688
- $env:TMP = '${escapedTemp}';
689
-
690
- $env:PATH = '${escapedPath}';
691
-
692
- $dangerousVars = @(
693
- 'LD_PRELOAD',
694
- 'DYLD_INSERT_LIBRARIES',
695
- 'DYLD_LIBRARY_PATH',
696
- 'DYLD_FRAMEWORK_PATH',
697
- 'DYLD_ROOT_PATH',
698
- 'DYLD_FORCE_FLAT_NAMESPACE'
699
- );
700
- foreach ($v in $dangerousVars) {
701
- if (Test-Path Env:$v) {
702
- Remove-Item Env:$v -Force -ErrorAction SilentlyContinue;
703
- }
704
- }
705
- ${envOverrideBlock}
706
-
707
- # Execute the command \u2014 PS-native cmdlets via Invoke-Expression, others via the standard command interpreter
708
- $commandBytes = [Convert]::FromBase64String('${commandBase64}');
709
- $command = [Text.Encoding]::UTF8.GetString($commandBytes);
710
- ${commandExec};
711
- } catch {
712
- [Console]::Error.WriteLine($_.Exception.Message);
713
- exit 1;
714
- }`;
715
- const encodedScript = Buffer2.from(psScript, "utf16le").toString("base64");
716
- const escapedPowerShellExe = psSingleQuoteEscape(powerShellExe);
717
- return `& '${escapedPowerShellExe}' -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass -WindowStyle Hidden -EncodedCommand ${encodedScript}; exit $LASTEXITCODE`;
718
- }
719
- getEnvOverrides() {
720
- return {
721
- PATH: getSafeWindowsPath(),
722
- TEMP: null,
723
- TMP: null,
724
- LD_PRELOAD: null,
725
- DYLD_INSERT_LIBRARIES: null,
726
- DYLD_LIBRARY_PATH: null,
727
- DYLD_FRAMEWORK_PATH: null,
728
- DYLD_ROOT_PATH: null,
729
- DYLD_FORCE_FLAT_NAMESPACE: null
730
- };
731
- }
732
- }
733
- var SANDBOX_UNAVAILABLE_CODES2, DEFAULT_SYSTEM_ROOT = "C:\\Windows", UNSAFE_PATH_CHARACTERS, _internals4;
734
- var init_restricted_environment_executor = __esm(() => {
735
- init_logger();
736
- init_executor();
737
- init_edge_cases();
738
- SANDBOX_UNAVAILABLE_CODES2 = new Set([
739
- "ENOENT",
740
- "EACCES",
741
- "EPERM",
742
- "ENOSPC"
743
- ]);
744
- UNSAFE_PATH_CHARACTERS = new Set([
745
- ":",
746
- '"',
747
- "'",
748
- ";",
749
- "&",
750
- "|",
751
- "<",
752
- ">",
753
- "^",
754
- "%",
755
- "!",
756
- "?",
757
- "*",
758
- "`",
759
- "$"
760
- ]);
761
- _internals4 = {
762
- probeWindowsSandbox
763
- };
764
- });
765
-
766
- // src/sandbox/win32/native-sandbox-executor.ts
767
- import * as crypto from "crypto";
768
- import * as fs from "fs";
769
- import * as os3 from "os";
770
- import * as path3 from "path";
771
-
772
- class NativeWindowsSandboxExecutor {
773
- mechanism;
774
- _probeResult;
775
- _fallbackExecutor;
776
- _strength;
777
- _disabled;
778
- _disabledReason;
779
- constructor(scopePaths = [], tempDir) {
780
- this._disabled = false;
781
- this._disabledReason = null;
782
- this._fallbackExecutor = new WindowsSandboxExecutor(scopePaths, tempDir);
783
- this._probeResult = probe();
784
- if (this._probeResult.available) {
785
- this._strength = "strong";
786
- this.mechanism = `native-runner/${this._probeResult.mode}`;
787
- } else if (this._fallbackExecutor.isAvailable()) {
788
- this._strength = "weak";
789
- this.mechanism = "powershell-wrapper";
790
- warn(`Native sandbox runner unavailable (${this._probeResult.error ?? "unknown"}); ` + "falling back to PowerShell environment restrictions (weak sandbox)");
791
- } else {
792
- this._strength = "none";
793
- this.mechanism = "none";
794
- }
795
- }
796
- get strength() {
797
- if (this._disabled)
798
- return "none";
799
- return this._strength;
800
- }
801
- isAvailable() {
802
- return !this._disabled && this._strength !== "none";
803
- }
804
- disable(reason) {
805
- this._disabled = true;
806
- this._disabledReason = reason;
807
- warn(`Sandbox disabled: ${reason}. Falling through to tool-layer enforcement.`);
808
- }
809
- wrapCommand(command, scopePaths, tempDir, envOverrides) {
810
- if (!this.isAvailable()) {
811
- throw new SandboxError("Sandbox not available", "SANDBOX_UNAVAILABLE");
812
- }
813
- if (this._strength === "strong") {
814
- return this._wrapWithRunner(command, scopePaths, tempDir, envOverrides);
815
- }
816
- return this._fallbackExecutor.wrapCommand(command, scopePaths, tempDir, envOverrides);
817
- }
818
- _wrapWithRunner(command, scopePaths, tempDir, _envOverrides) {
819
- const binary = _internals.findRunnerBinary();
820
- if (!binary) {
821
- throw new SandboxError("Runner binary not found", "RUNNER_NOT_FOUND");
822
- }
823
- const workspaceRoot = scopePaths[0] ?? process.cwd();
824
- const runId = `swarm-${crypto.randomUUID?.() ?? Date.now()}`;
825
- const policy = buildDefaultPolicy(workspaceRoot, runId);
826
- if (tempDir) {
827
- policy.temp_root = tempDir;
828
- }
829
- policy.workspace_roots = scopePaths.length > 0 ? scopePaths : [workspaceRoot];
830
- policy.writable_roots = policy.workspace_roots;
831
- if (_envOverrides) {
832
- for (const [key, value] of Object.entries(_envOverrides)) {
833
- if (!isValidEnvKey(key))
834
- continue;
835
- if (typeof value === "string") {
836
- policy.env_overrides[key] = value;
837
- }
838
- }
839
- }
840
- const policyJson = JSON.stringify(policy);
841
- const policyDir = path3.join(os3.tmpdir(), "swarm-sandbox-policies");
842
- try {
843
- fs.mkdirSync(policyDir, { recursive: true });
844
- } catch {}
845
- const policyFile = path3.join(policyDir, `${runId}.json`);
846
- fs.writeFileSync(policyFile, policyJson, "utf-8");
847
- const mode = this._probeResult.mode === "none" ? "auto" : this._probeResult.mode;
848
- const escapedBinary = binary.includes(" ") ? `"${binary}"` : binary;
849
- const escapedPolicyFile = policyFile.includes(" ") ? `"${policyFile}"` : policyFile;
850
- const escapedCommand = command.replace(/"/g, "\\\"");
851
- return `cmd /c "type ${escapedPolicyFile} | ${escapedBinary} --policy-stdin --mode ${mode} -- ${escapedCommand} & del ${escapedPolicyFile} 2>nul"`;
852
- }
853
- getEnvOverrides() {
854
- if (this._strength === "strong") {
855
- return {
856
- PATH: null,
857
- TEMP: null,
858
- TMP: null,
859
- LD_PRELOAD: null,
860
- DYLD_INSERT_LIBRARIES: null,
861
- DYLD_LIBRARY_PATH: null,
862
- DYLD_FRAMEWORK_PATH: null,
863
- DYLD_ROOT_PATH: null,
864
- DYLD_FORCE_FLAT_NAMESPACE: null
865
- };
866
- }
867
- return this._fallbackExecutor.getEnvOverrides();
868
- }
869
- async executeNative(command, workspaceRoot, runId) {
870
- if (this._strength !== "strong") {
871
- throw new SandboxError("Native execution requires strong sandbox (runner binary)", "NATIVE_UNAVAILABLE");
872
- }
873
- const policy = buildDefaultPolicy(workspaceRoot, runId);
874
- return execute(command, policy);
875
- }
876
- get hasNativeRunner() {
877
- return this._strength === "strong";
878
- }
879
- get disabledReason() {
880
- return this._disabledReason;
881
- }
882
- get probeResult() {
883
- return this._probeResult;
884
- }
885
- }
886
- var init_native_sandbox_executor = __esm(() => {
887
- init_logger();
888
- init_executor();
889
- init_restricted_environment_executor();
890
- init_runner_client();
891
- });
892
-
893
- // src/sandbox/executors/windows.ts
894
- var exports_windows = {};
895
- __export(exports_windows, {
896
- WindowsSandboxExecutor: () => NativeWindowsSandboxExecutor,
897
- LegacyWindowsSandboxExecutor: () => WindowsSandboxExecutor
898
- });
899
- var init_windows = __esm(() => {
900
- init_native_sandbox_executor();
901
- init_restricted_environment_executor();
902
- });
903
-
904
- // src/sandbox/executor.ts
905
- function isValidEnvKey(key) {
906
- return /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key);
907
- }
908
- async function getExecutor() {
909
- if (_cachedExecutorPromise !== undefined) {
910
- return _cachedExecutorPromise;
911
- }
912
- _cachedExecutorPromise = _createExecutor();
913
- return _cachedExecutorPromise;
914
- }
915
- async function _createExecutor() {
916
- const platform = process.platform;
917
- if (platform === "linux") {
918
- return _createLinuxExecutor();
919
- }
920
- if (platform === "darwin") {
921
- return _createMacOSExecutor();
922
- }
923
- if (platform === "win32") {
924
- return _createWindowsExecutor();
925
- }
926
- return null;
927
- }
928
- async function _createLinuxExecutor() {
929
- const { SandboxCapabilityProbe, isBubblewrapAvailable } = await import("./capability-probe-f1paszww.js");
930
- await new SandboxCapabilityProbe().detect();
931
- if (!isBubblewrapAvailable()) {
932
- return null;
933
- }
934
- try {
935
- const { BubblewrapSandboxExecutor: BubblewrapSandboxExecutor2 } = (init_bubblewrap(), __toCommonJS(exports_bubblewrap));
936
- return new BubblewrapSandboxExecutor2([]);
937
- } catch {
938
- return null;
939
- }
940
- }
941
- async function _createMacOSExecutor() {
942
- const { SandboxCapabilityProbe, isSandboxExecAvailable } = await import("./capability-probe-f1paszww.js");
943
- await new SandboxCapabilityProbe().detect();
944
- if (!isSandboxExecAvailable()) {
945
- return null;
946
- }
947
- try {
948
- const { MacOSSandboxExecutor: MacOSSandboxExecutor2 } = (init_macos(), __toCommonJS(exports_macos));
949
- return new MacOSSandboxExecutor2([]);
950
- } catch {
951
- return null;
952
- }
953
- }
954
- async function _createWindowsExecutor() {
955
- const { SandboxCapabilityProbe, isWindowsSandboxAvailable } = await import("./capability-probe-f1paszww.js");
956
- await new SandboxCapabilityProbe().detect();
957
- if (!isWindowsSandboxAvailable()) {
958
- return null;
959
- }
960
- try {
961
- const { WindowsSandboxExecutor: WindowsSandboxExecutor2 } = (init_windows(), __toCommonJS(exports_windows));
962
- return new WindowsSandboxExecutor2([]);
963
- } catch {
964
- return null;
965
- }
966
- }
967
- var SandboxError, _cachedExecutorPromise;
968
- var init_executor = __esm(() => {
969
- SandboxError = class SandboxError extends Error {
970
- code;
971
- constructor(message, code) {
972
- super(message);
973
- this.code = code;
974
- this.name = "SandboxError";
975
- }
976
- };
977
- });
978
96
 
979
97
  // src/plan/manager.ts
980
98
  import {
@@ -982,22 +100,22 @@ import {
982
100
  copyFileSync,
983
101
  existsSync as existsSync4,
984
102
  fsyncSync,
985
- mkdirSync as mkdirSync4,
103
+ mkdirSync as mkdirSync3,
986
104
  openSync,
987
105
  readdirSync,
988
106
  renameSync as renameSync2,
989
107
  unlinkSync as unlinkSync2,
990
- writeFileSync as writeFileSync4
108
+ writeFileSync as writeFileSync2
991
109
  } from "fs";
992
110
  import * as fsPromises from "fs/promises";
993
- import * as path8 from "path";
111
+ import * as path5 from "path";
994
112
 
995
113
  // src/db/task-checkpoint-receipt.ts
996
114
  import { createHash } from "crypto";
997
115
 
998
116
  // src/db/project-db.ts
999
- import { existsSync, mkdirSync as mkdirSync2 } from "fs";
1000
- import { join as join3, resolve } from "path";
117
+ import { existsSync, mkdirSync } from "fs";
118
+ import { join, resolve } from "path";
1001
119
  var MIGRATIONS = [
1002
120
  {
1003
121
  version: 1,
@@ -1151,7 +269,7 @@ function runProjectMigrations(db) {
1151
269
  }
1152
270
  }
1153
271
  function projectDbPath(directory) {
1154
- return join3(resolve(directory), ".swarm", "swarm.db");
272
+ return join(resolve(directory), ".swarm", "swarm.db");
1155
273
  }
1156
274
  function projectDbExists(directory) {
1157
275
  return existsSync(projectDbPath(directory));
@@ -1161,10 +279,10 @@ function getProjectDb(directory) {
1161
279
  const existing = _projectDbs.get(key);
1162
280
  if (existing)
1163
281
  return existing;
1164
- const swarmDir = join3(key, ".swarm");
1165
- mkdirSync2(swarmDir, { recursive: true });
282
+ const swarmDir = join(key, ".swarm");
283
+ mkdirSync(swarmDir, { recursive: true });
1166
284
  const Db = loadDatabaseCtor();
1167
- const db = new Db(join3(swarmDir, "swarm.db"));
285
+ const db = new Db(join(swarmDir, "swarm.db"));
1168
286
  db.run("PRAGMA journal_mode = WAL;");
1169
287
  db.run("PRAGMA synchronous = NORMAL;");
1170
288
  db.run("PRAGMA busy_timeout = 5000;");
@@ -1332,20 +450,8 @@ function updateTaskCheckpointReceipt(directory, descriptor, state, sha) {
1332
450
  init_executor();
1333
451
  import * as child_process from "child_process";
1334
452
  import * as fsSync from "fs";
1335
- import path4 from "path";
1336
-
1337
- // src/utils/git-binary-missing-error.ts
1338
- class GitBinaryMissingError extends Error {
1339
- name = "GitBinaryMissingError";
1340
- constructor(message = "git binary is not available", options) {
1341
- super(message, options);
1342
- }
1343
- }
1344
- function isGitBinaryMissing(err) {
1345
- return typeof err === "object" && err !== null && "code" in err && err.code === "ENOENT";
1346
- }
1347
-
1348
- // src/git/branch.ts
453
+ import path from "path";
454
+ init_git_executable();
1349
455
  init_logger();
1350
456
 
1351
457
  // src/utils/transient-retry.ts
@@ -1370,23 +476,7 @@ function transientBackoff(attempt) {
1370
476
  // src/git/branch.ts
1371
477
  var GIT_TIMEOUT_MS = 30000;
1372
478
  var GIT_MAX_BUFFER_BYTES = 5 * 1024 * 1024;
1373
- function unique(values) {
1374
- return [...new Set(values.filter(Boolean))];
1375
- }
1376
- function windowsGitCandidates() {
1377
- if (process.platform !== "win32")
1378
- return ["git"];
1379
- const roots = unique([
1380
- process.env.ProgramFiles ?? "",
1381
- process.env["ProgramFiles(x86)"] ?? "",
1382
- process.env.LOCALAPPDATA ? path4.join(process.env.LOCALAPPDATA, "Programs") : ""
1383
- ]);
1384
- const installed = roots.flatMap((root) => [
1385
- path4.join(root, "Git", "cmd", "git.exe"),
1386
- path4.join(root, "Git", "bin", "git.exe")
1387
- ]);
1388
- return unique(["git", ...installed]);
1389
- }
479
+ var MAX_RENDERED_GIT_CANDIDATES = 10;
1390
480
  function errorMessage(err) {
1391
481
  return err instanceof Error ? err.message : String(err);
1392
482
  }
@@ -1407,7 +497,7 @@ var __spawnSyncSeam = {
1407
497
  }
1408
498
  };
1409
499
  function readLaneEnvFileFromDiskSync(worktreePath, laneIndex) {
1410
- const envPath = path4.join(worktreePath, ".swarm", "lanes", `${laneIndex}.env`);
500
+ const envPath = path.join(worktreePath, ".swarm", "lanes", `${laneIndex}.env`);
1411
501
  let content;
1412
502
  try {
1413
503
  content = fsSync.readFileSync(envPath, "utf-8");
@@ -1431,43 +521,71 @@ function readLaneEnvFileFromDiskSync(worktreePath, laneIndex) {
1431
521
  }
1432
522
  return result;
1433
523
  }
524
+ function gitBinaryMissingMessage(cwd) {
525
+ const resolution = describeGitResolution();
526
+ const lines = [
527
+ `git executable is not available: spawning "${resolution.resolvedPath ?? "git"}" failed, and the working directory ${cwd} exists and is a directory.`
528
+ ];
529
+ if (resolution.attempts.length > 0) {
530
+ lines.push("Candidates tried:");
531
+ const shown = resolution.attempts.slice(0, MAX_RENDERED_GIT_CANDIDATES);
532
+ for (const attempt of shown) {
533
+ lines.push(` - [${attempt.source}] ${attempt.candidate}: ${attempt.accepted ? "accepted" : attempt.reason ?? "rejected"}`);
534
+ }
535
+ const omitted = resolution.attempts.length - shown.length;
536
+ if (omitted > 0)
537
+ lines.push(` ... and ${omitted} more`);
538
+ } else {
539
+ lines.push("No candidate probe results are recorded for this process (the resolver was pre-seeded or has not probed yet).");
540
+ }
541
+ lines.push(resolution.overrideValue ? `The configured override (${resolution.overrideSource ?? "unknown"}) "${resolution.overrideValue}" did not work \u2014 point the ${GIT_BINARY_ENV_VAR} environment variable, or the "git.binary" value in your USER config (a project .opencode config is ignored for this key), at a working git executable.` : `No override is configured. Set the ${GIT_BINARY_ENV_VAR} environment variable, or the "git.binary" value in your USER config (a project .opencode config is ignored for this key), to point at a working git executable.`);
542
+ return lines.join(`
543
+ `);
544
+ }
1434
545
  function gitExec(args, cwd, laneEnv, laneIndex) {
1435
546
  const resolvedLaneEnv = laneEnv ?? (laneIndex !== undefined ? readLaneEnvFileFromDiskSync(cwd, laneIndex) : undefined);
1436
- let missingGitError;
1437
547
  const subcommand = args[0];
1438
548
  const hardenedArgs = subcommand === "commit" || subcommand === "tag" ? ["-c", "commit.gpgsign=false", "-c", "tag.gpgsign=false", ...args] : args;
1439
- for (const command of windowsGitCandidates()) {
1440
- for (let attempt = 0;attempt < MAX_TRANSIENT_RETRIES; attempt++) {
1441
- const result = _internals5.spawnSync(command, hardenedArgs, {
1442
- cwd,
1443
- encoding: "utf-8",
1444
- timeout: GIT_TIMEOUT_MS,
1445
- windowsHide: true,
1446
- maxBuffer: GIT_MAX_BUFFER_BYTES,
1447
- stdio: ["ignore", "pipe", "pipe"],
1448
- env: { ...process.env, GIT_TERMINAL_PROMPT: "0" },
1449
- envOverrides: resolvedLaneEnv
1450
- });
1451
- if (!result.error && result.status === 0) {
1452
- return result.stdout;
549
+ const command = _internals.resolveGitExecutable();
550
+ for (let attempt = 0;attempt < MAX_TRANSIENT_RETRIES; attempt++) {
551
+ const result = _internals.spawnSync(command, hardenedArgs, {
552
+ cwd,
553
+ encoding: "utf-8",
554
+ timeout: GIT_TIMEOUT_MS,
555
+ windowsHide: true,
556
+ maxBuffer: GIT_MAX_BUFFER_BYTES,
557
+ stdio: ["ignore", "pipe", "pipe"],
558
+ env: { ...process.env, GIT_TERMINAL_PROMPT: "0" },
559
+ envOverrides: resolvedLaneEnv
560
+ });
561
+ if (!result.error && result.status === 0) {
562
+ return result.stdout;
563
+ }
564
+ if (result.error) {
565
+ if (isSpawnCwdMissing(result.error, cwd)) {
566
+ throw new GitSpawnCwdError(cwd, "missing", { cause: result.error });
1453
567
  }
1454
- if (result.error) {
1455
- if (isGitBinaryMissing(result.error)) {
1456
- missingGitError ??= result.error;
1457
- break;
1458
- }
1459
- if (isTransientSpawnError(result.error) && attempt < MAX_TRANSIENT_RETRIES - 1) {
1460
- transientBackoff(attempt);
1461
- continue;
1462
- }
1463
- throw new Error(errorMessage(result.error));
568
+ if (isSpawnCwdUnreadable(result.error, cwd)) {
569
+ throw new GitSpawnCwdError(cwd, "unreadable", {
570
+ cause: result.error
571
+ });
1464
572
  }
1465
- if (result.status !== 0) {
1466
- throw new Error(result.stderr || result.stdout || `git exited with ${result.status}`);
573
+ if (isGitBinaryMissing(result.error, cwd)) {
574
+ throw new GitBinaryMissingError(gitBinaryMissingMessage(cwd), {
575
+ cause: result.error
576
+ });
577
+ }
578
+ if (isTransientSpawnError(result.error) && attempt < MAX_TRANSIENT_RETRIES - 1) {
579
+ transientBackoff(attempt);
580
+ continue;
1467
581
  }
582
+ throw new Error(errorMessage(result.error));
583
+ }
584
+ if (result.status !== 0) {
585
+ throw new Error(result.stderr || result.stdout || `git exited with ${result.status}`);
1468
586
  }
1469
587
  }
1470
- throw new GitBinaryMissingError(process.platform === "win32" ? "git executable is not available on PATH or common Windows install locations" : "git executable is not available on PATH", { cause: missingGitError });
588
+ throw new GitBinaryMissingError(process.platform === "win32" ? "git executable is not available on PATH or common Windows install locations" : "git executable is not available on PATH");
1471
589
  }
1472
590
  function getGitRepositoryStatus(cwd) {
1473
591
  try {
@@ -1544,7 +662,7 @@ async function resetToRemoteBranch(cwd, options) {
1544
662
  const prunedBranches = [];
1545
663
  try {
1546
664
  const currentBranch = getCurrentBranch(cwd);
1547
- const defaultRemoteBranch = _internals5.detectDefaultRemoteBranch(cwd);
665
+ const defaultRemoteBranch = _internals.detectDefaultRemoteBranch(cwd);
1548
666
  if (!defaultRemoteBranch) {
1549
667
  return {
1550
668
  success: false,
@@ -1726,7 +844,7 @@ var GITIGNORED_BUILD_ARTIFACTS = ["dist"];
1726
844
  async function resetToMainAfterMerge(cwd, options) {
1727
845
  const warnings = [];
1728
846
  try {
1729
- const defaultBranch = _internals5.detectDefaultRemoteBranch(cwd);
847
+ const defaultBranch = _internals.detectDefaultRemoteBranch(cwd);
1730
848
  if (!defaultBranch) {
1731
849
  return {
1732
850
  success: false,
@@ -1753,7 +871,7 @@ async function resetToMainAfterMerge(cwd, options) {
1753
871
  }
1754
872
  if (currentBranch === defaultBranch) {
1755
873
  try {
1756
- const logOutput = _internals5.gitExec(["log", `${targetBranch}..HEAD`, "--oneline"], cwd);
874
+ const logOutput = _internals.gitExec(["log", `${targetBranch}..HEAD`, "--oneline"], cwd);
1757
875
  if (logOutput.trim().length > 0) {
1758
876
  return {
1759
877
  success: false,
@@ -1768,11 +886,11 @@ async function resetToMainAfterMerge(cwd, options) {
1768
886
  } catch {}
1769
887
  } else {
1770
888
  try {
1771
- _internals5.gitExec(["rev-parse", "--abbrev-ref", `${currentBranch}@{upstream}`], cwd);
889
+ _internals.gitExec(["rev-parse", "--abbrev-ref", `${currentBranch}@{upstream}`], cwd);
1772
890
  } catch {
1773
891
  try {
1774
- const localSha = _internals5.gitExec(["rev-parse", "HEAD"], cwd).trim();
1775
- const remoteSha = _internals5.gitExec(["rev-parse", targetBranch], cwd).trim();
892
+ const localSha = _internals.gitExec(["rev-parse", "HEAD"], cwd).trim();
893
+ const remoteSha = _internals.gitExec(["rev-parse", targetBranch], cwd).trim();
1776
894
  if (localSha !== remoteSha) {
1777
895
  return {
1778
896
  success: false,
@@ -1798,7 +916,7 @@ async function resetToMainAfterMerge(cwd, options) {
1798
916
  }
1799
917
  }
1800
918
  try {
1801
- _internals5.gitExec(["fetch", "--prune", "origin"], cwd);
919
+ _internals.gitExec(["fetch", "--prune", "origin"], cwd);
1802
920
  } catch (err) {
1803
921
  return {
1804
922
  success: false,
@@ -1814,7 +932,7 @@ async function resetToMainAfterMerge(cwd, options) {
1814
932
  let switchedBranch = false;
1815
933
  if (currentBranch !== defaultBranch) {
1816
934
  try {
1817
- _internals5.gitExec(["checkout", defaultBranch], cwd);
935
+ _internals.gitExec(["checkout", defaultBranch], cwd);
1818
936
  switchedBranch = true;
1819
937
  } catch (err) {
1820
938
  return {
@@ -1829,7 +947,7 @@ async function resetToMainAfterMerge(cwd, options) {
1829
947
  }
1830
948
  }
1831
949
  try {
1832
- _internals5.gitExec(["reset", "--hard", targetBranch], cwd);
950
+ _internals.gitExec(["reset", "--hard", targetBranch], cwd);
1833
951
  } catch (err) {
1834
952
  return {
1835
953
  success: false,
@@ -1849,7 +967,7 @@ async function resetToMainAfterMerge(cwd, options) {
1849
967
  await new Promise((resolve2) => setTimeout(resolve2, 500));
1850
968
  }
1851
969
  try {
1852
- _internals5.gitExec(["checkout", "--", "."], cwd);
970
+ _internals.gitExec(["checkout", "--", "."], cwd);
1853
971
  discardSucceeded = true;
1854
972
  break;
1855
973
  } catch {}
@@ -1860,18 +978,18 @@ async function resetToMainAfterMerge(cwd, options) {
1860
978
  changesDiscarded = discardSucceeded;
1861
979
  }
1862
980
  try {
1863
- _internals5.gitExec(["clean", "-fdX", "--", ...GITIGNORED_BUILD_ARTIFACTS], cwd);
981
+ _internals.gitExec(["clean", "-fdX", "--", ...GITIGNORED_BUILD_ARTIFACTS], cwd);
1864
982
  } catch {
1865
983
  warnings.push("Could not clean build artifacts");
1866
984
  }
1867
985
  let branchDeleted = false;
1868
986
  if (switchedBranch && previousBranch !== defaultBranch) {
1869
987
  try {
1870
- const mergedOutput = _internals5.gitExec(["branch", "--merged", defaultBranch], cwd);
988
+ const mergedOutput = _internals.gitExec(["branch", "--merged", defaultBranch], cwd);
1871
989
  const isMerged = mergedOutput.split(`
1872
990
  `).some((line) => line.trim() === previousBranch || line.trim() === `* ${previousBranch}`);
1873
991
  if (isMerged) {
1874
- _internals5.gitExec(["branch", "-d", previousBranch], cwd);
992
+ _internals.gitExec(["branch", "-d", previousBranch], cwd);
1875
993
  branchDeleted = true;
1876
994
  } else {
1877
995
  warnings.push(`Branch ${previousBranch} is not merged into ${defaultBranch} \u2014 keeping it`);
@@ -1882,7 +1000,7 @@ async function resetToMainAfterMerge(cwd, options) {
1882
1000
  }
1883
1001
  if (options?.pruneBranches) {
1884
1002
  try {
1885
- const mergedOutput = _internals5.gitExec(["branch", "--merged", defaultBranch], cwd);
1003
+ const mergedOutput = _internals.gitExec(["branch", "--merged", defaultBranch], cwd);
1886
1004
  const mergedLines = mergedOutput.split(`
1887
1005
  `);
1888
1006
  for (const line of mergedLines) {
@@ -1891,7 +1009,7 @@ async function resetToMainAfterMerge(cwd, options) {
1891
1009
  continue;
1892
1010
  }
1893
1011
  try {
1894
- _internals5.gitExec(["branch", "-d", trimmedLine], cwd);
1012
+ _internals.gitExec(["branch", "-d", trimmedLine], cwd);
1895
1013
  } catch {
1896
1014
  warnings.push(`Could not prune branch: ${trimmedLine}`);
1897
1015
  }
@@ -1921,7 +1039,7 @@ async function resetToMainAfterMerge(cwd, options) {
1921
1039
  };
1922
1040
  }
1923
1041
  }
1924
- var _internals5 = {
1042
+ var _internals = {
1925
1043
  gitExec,
1926
1044
  detectDefaultRemoteBranch,
1927
1045
  getDefaultBaseBranch,
@@ -1929,12 +1047,13 @@ var _internals5 = {
1929
1047
  resetToRemoteBranch,
1930
1048
  resetToMainAfterMerge,
1931
1049
  spawnSync: __spawnSyncSeam.spawnSync,
1932
- readLaneEnvFileFromDiskSync
1050
+ readLaneEnvFileFromDiskSync,
1051
+ resolveGitExecutable
1933
1052
  };
1934
1053
 
1935
1054
  // src/services/run-memory.ts
1936
- import * as crypto2 from "crypto";
1937
- import * as fs3 from "fs/promises";
1055
+ import * as crypto from "crypto";
1056
+ import * as fs2 from "fs/promises";
1938
1057
 
1939
1058
  // src/hooks/context-sanitizer.ts
1940
1059
  function sanitizeContextText(text) {
@@ -1948,8 +1067,8 @@ function sanitizeContextText(text) {
1948
1067
  init_logger();
1949
1068
 
1950
1069
  // src/utils/path-security.ts
1951
- import * as fs2 from "fs";
1952
- import * as path5 from "path";
1070
+ import * as fs from "fs";
1071
+ import * as path2 from "path";
1953
1072
  function containsPathTraversal(str) {
1954
1073
  if (/\.\.[/\\]/.test(str))
1955
1074
  return true;
@@ -2019,7 +1138,7 @@ function validateProjectDirectory(directory) {
2019
1138
  if (containsControlChars(directory)) {
2020
1139
  throw new Error("Invalid project directory: control characters detected");
2021
1140
  }
2022
- if (!path5.isAbsolute(directory) && !/^[A-Za-z]:[/\\]/.test(directory)) {
1141
+ if (!path2.isAbsolute(directory) && !/^[A-Za-z]:[/\\]/.test(directory)) {
2023
1142
  throw new Error("Invalid project directory: must be an absolute path");
2024
1143
  }
2025
1144
  assertNotSystemLocation(directory);
@@ -2044,7 +1163,7 @@ var DENIED_ROOT_SUBTREES = new Set([
2044
1163
  ]);
2045
1164
  var DENIED_EXACT_ROOT_CHILDREN = new Set(["users", "home", "root"]);
2046
1165
  function assertNotSystemLocation(directory) {
2047
- for (const parser of [path5.win32, path5.posix]) {
1166
+ for (const parser of [path2.win32, path2.posix]) {
2048
1167
  if (!parser.isAbsolute(directory))
2049
1168
  continue;
2050
1169
  const normalized = parser.normalize(directory);
@@ -2063,50 +1182,50 @@ function resolveNearestExistingCanonical(inputPath, resolver) {
2063
1182
  try {
2064
1183
  return resolver(inputPath);
2065
1184
  } catch {}
2066
- const lexicallyResolved = path5.resolve(inputPath);
2067
- let probe2 = lexicallyResolved;
1185
+ const lexicallyResolved = path2.resolve(inputPath);
1186
+ let probe = lexicallyResolved;
2068
1187
  const tail = [];
2069
1188
  for (let i = 0;i < 4096; i++) {
2070
- const parent = path5.dirname(probe2);
2071
- if (parent === probe2) {
1189
+ const parent = path2.dirname(probe);
1190
+ if (parent === probe) {
2072
1191
  return lexicallyResolved;
2073
1192
  }
2074
- tail.unshift(path5.basename(probe2));
2075
- probe2 = parent;
1193
+ tail.unshift(path2.basename(probe));
1194
+ probe = parent;
2076
1195
  try {
2077
- const canonicalAncestor = resolver(probe2);
2078
- return path5.normalize(path5.join(canonicalAncestor, ...tail));
1196
+ const canonicalAncestor = resolver(probe);
1197
+ return path2.normalize(path2.join(canonicalAncestor, ...tail));
2079
1198
  } catch {}
2080
1199
  }
2081
1200
  return lexicallyResolved;
2082
1201
  }
2083
1202
  function validateSymlinkBoundary(targetPath, rootPath) {
2084
- const realTarget = resolveNearestExistingCanonical(targetPath, _internals6.realpathSync);
2085
- const realRoot = resolveNearestExistingCanonical(rootPath, _internals6.realpathSync);
2086
- const normalizedTarget = path5.normalize(realTarget);
2087
- const normalizedRoot = path5.normalize(realRoot);
2088
- if (!normalizedTarget.startsWith(normalizedRoot + path5.sep) && normalizedTarget !== normalizedRoot) {
1203
+ const realTarget = resolveNearestExistingCanonical(targetPath, _internals2.realpathSync);
1204
+ const realRoot = resolveNearestExistingCanonical(rootPath, _internals2.realpathSync);
1205
+ const normalizedTarget = path2.normalize(realTarget);
1206
+ const normalizedRoot = path2.normalize(realRoot);
1207
+ if (!normalizedTarget.startsWith(normalizedRoot + path2.sep) && normalizedTarget !== normalizedRoot) {
2089
1208
  throw new Error(`Symlink resolution escaped boundary: ${realTarget} is not within ${realRoot}`);
2090
1209
  }
2091
1210
  }
2092
1211
  function isCanonicalPathWithinRoot(targetPath, rootPath) {
2093
1212
  let canonicalRoot;
2094
1213
  try {
2095
- canonicalRoot = fs2.realpathSync(rootPath);
1214
+ canonicalRoot = fs.realpathSync(rootPath);
2096
1215
  } catch {
2097
- canonicalRoot = path5.normalize(rootPath);
1216
+ canonicalRoot = path2.normalize(rootPath);
2098
1217
  }
2099
- let probe2 = path5.normalize(targetPath);
1218
+ let probe = path2.normalize(targetPath);
2100
1219
  for (let i = 0;i < 4096; i++) {
2101
1220
  try {
2102
- const canonicalProbe = fs2.realpathSync(probe2);
2103
- const relative2 = path5.relative(canonicalRoot, canonicalProbe);
2104
- return !relative2.startsWith("..") && !path5.isAbsolute(relative2);
1221
+ const canonicalProbe = fs.realpathSync(probe);
1222
+ const relative2 = path2.relative(canonicalRoot, canonicalProbe);
1223
+ return !relative2.startsWith("..") && !path2.isAbsolute(relative2);
2105
1224
  } catch {
2106
- const parent = path5.dirname(probe2);
2107
- if (parent === probe2)
1225
+ const parent = path2.dirname(probe);
1226
+ if (parent === probe)
2108
1227
  return false;
2109
- probe2 = parent;
1228
+ probe = parent;
2110
1229
  }
2111
1230
  }
2112
1231
  return false;
@@ -2115,7 +1234,7 @@ function validateTargetWithinRoot(filePath, root) {
2115
1234
  if (!filePath || filePath.trim() === "") {
2116
1235
  return "Empty path";
2117
1236
  }
2118
- if (path5.isAbsolute(filePath) || /^[A-Za-z]:[/\\]/.test(filePath)) {
1237
+ if (path2.isAbsolute(filePath) || /^[A-Za-z]:[/\\]/.test(filePath)) {
2119
1238
  return `Absolute path rejected: ${filePath}`;
2120
1239
  }
2121
1240
  if (containsPathTraversal(filePath)) {
@@ -2124,9 +1243,9 @@ function validateTargetWithinRoot(filePath, root) {
2124
1243
  if (containsControlChars(filePath)) {
2125
1244
  return `Control characters detected in path: ${filePath}`;
2126
1245
  }
2127
- const resolved = path5.resolve(root, filePath);
2128
- const relative2 = path5.relative(root, resolved);
2129
- if (relative2.startsWith("..") || path5.isAbsolute(relative2)) {
1246
+ const resolved = path2.resolve(root, filePath);
1247
+ const relative2 = path2.relative(root, resolved);
1248
+ if (relative2.startsWith("..") || path2.isAbsolute(relative2)) {
2130
1249
  return `Path escapes root: ${filePath}`;
2131
1250
  }
2132
1251
  if (!isCanonicalPathWithinRoot(resolved, root)) {
@@ -2134,8 +1253,8 @@ function validateTargetWithinRoot(filePath, root) {
2134
1253
  }
2135
1254
  return null;
2136
1255
  }
2137
- var _internals6 = {
2138
- realpathSync: fs2.realpathSync,
1256
+ var _internals2 = {
1257
+ realpathSync: fs.realpathSync,
2139
1258
  containsPathTraversal,
2140
1259
  containsControlChars,
2141
1260
  validateDirectory,
@@ -2150,7 +1269,7 @@ var RUN_MEMORY_FILENAME = "run-memory.jsonl";
2150
1269
  var MAX_SUMMARY_TOKENS = 500;
2151
1270
  function generateTaskFingerprint(taskId, fileTargets) {
2152
1271
  const sortedFiles = [...fileTargets].sort().join(",");
2153
- const hash = crypto2.createHash("sha256").update(taskId + sortedFiles).digest("hex");
1272
+ const hash = crypto.createHash("sha256").update(taskId + sortedFiles).digest("hex");
2154
1273
  return hash.slice(0, 8);
2155
1274
  }
2156
1275
  async function recordOutcome(directory, entry) {
@@ -2158,7 +1277,7 @@ async function recordOutcome(directory, entry) {
2158
1277
  const resolvedPath = validateSwarmPath(directory, RUN_MEMORY_FILENAME);
2159
1278
  const line = `${JSON.stringify(entry)}
2160
1279
  `;
2161
- await fs3.appendFile(resolvedPath, line, { encoding: "utf-8" });
1280
+ await fs2.appendFile(resolvedPath, line, { encoding: "utf-8" });
2162
1281
  }
2163
1282
  async function getTaskHistory(directory, taskId) {
2164
1283
  validateWorkspaceRoot(directory);
@@ -2185,14 +1304,14 @@ async function recordTaskAttempt(directory, input) {
2185
1304
  try {
2186
1305
  let history = [];
2187
1306
  try {
2188
- history = await _internals7.getTaskHistory(directory, input.taskId);
1307
+ history = await _internals3.getTaskHistory(directory, input.taskId);
2189
1308
  } catch (err) {
2190
1309
  warn(`[run-memory] history read for task ${input.taskId} failed; recording with attemptNumber 1: ${err instanceof Error ? err.message : String(err)}`);
2191
1310
  }
2192
1311
  const entry = {
2193
1312
  timestamp: new Date().toISOString(),
2194
1313
  taskId: input.taskId,
2195
- taskFingerprint: _internals7.generateTaskFingerprint(input.taskId, input.fileTargets ?? []),
1314
+ taskFingerprint: _internals3.generateTaskFingerprint(input.taskId, input.fileTargets ?? []),
2196
1315
  agent: input.agent,
2197
1316
  outcome: input.outcome,
2198
1317
  attemptNumber: history.length + 1
@@ -2206,7 +1325,7 @@ async function recordTaskAttempt(directory, input) {
2206
1325
  if (typeof input.durationMs === "number") {
2207
1326
  entry.durationMs = input.durationMs;
2208
1327
  }
2209
- await _internals7.recordOutcome(directory, entry);
1328
+ await _internals3.recordOutcome(directory, entry);
2210
1329
  } catch (err) {
2211
1330
  warn(`[run-memory] failed to record ${input.outcome} for task ${input.taskId}: ${err instanceof Error ? err.message : String(err)}`);
2212
1331
  }
@@ -2270,10 +1389,10 @@ async function getRunMemorySummary(directory) {
2270
1389
  if (entries.length === 0) {
2271
1390
  return null;
2272
1391
  }
2273
- const groups = _internals7.groupByTaskId(entries);
1392
+ const groups = _internals3.groupByTaskId(entries);
2274
1393
  const summaries = [];
2275
1394
  for (const [taskId, taskEntries] of groups) {
2276
- const summary = _internals7.summarizeTask(taskId, taskEntries);
1395
+ const summary = _internals3.summarizeTask(taskId, taskEntries);
2277
1396
  if (summary) {
2278
1397
  summaries.push(summary);
2279
1398
  }
@@ -2306,7 +1425,7 @@ Use this data to avoid repeating known failure patterns.`;
2306
1425
  }
2307
1426
  return prefix + summaryText + suffix;
2308
1427
  }
2309
- var _internals7 = {
1428
+ var _internals3 = {
2310
1429
  generateTaskFingerprint,
2311
1430
  recordOutcome,
2312
1431
  recordTaskAttempt,
@@ -2318,16 +1437,16 @@ var _internals7 = {
2318
1437
 
2319
1438
  // src/turbo/epic/state.ts
2320
1439
  init_logger();
2321
- import * as fs4 from "fs";
2322
- import * as path6 from "path";
1440
+ import * as fs3 from "fs";
1441
+ import * as path3 from "path";
2323
1442
  var STATE_FILE = "epic-state.json";
2324
1443
  function nowISO() {
2325
1444
  return new Date().toISOString();
2326
1445
  }
2327
1446
  function ensureSwarmDir(directory) {
2328
- const swarmDir = path6.resolve(directory, ".swarm");
2329
- if (!fs4.existsSync(swarmDir)) {
2330
- fs4.mkdirSync(swarmDir, { recursive: true });
1447
+ const swarmDir = path3.resolve(directory, ".swarm");
1448
+ if (!fs3.existsSync(swarmDir)) {
1449
+ fs3.mkdirSync(swarmDir, { recursive: true });
2331
1450
  }
2332
1451
  return swarmDir;
2333
1452
  }
@@ -2347,17 +1466,17 @@ function markStateUnreadable(directory, reason) {
2347
1466
  }
2348
1467
  function readPersisted(directory) {
2349
1468
  try {
2350
- const filePath = path6.join(directory, ".swarm", STATE_FILE);
2351
- if (!fs4.existsSync(filePath)) {
1469
+ const filePath = path3.join(directory, ".swarm", STATE_FILE);
1470
+ if (!fs3.existsSync(filePath)) {
2352
1471
  const seed = emptyPersisted();
2353
1472
  try {
2354
1473
  ensureSwarmDir(directory);
2355
- fs4.writeFileSync(filePath, `${JSON.stringify(seed, null, 2)}
1474
+ fs3.writeFileSync(filePath, `${JSON.stringify(seed, null, 2)}
2356
1475
  `, "utf-8");
2357
1476
  } catch {}
2358
1477
  return seed;
2359
1478
  }
2360
- const raw = fs4.readFileSync(filePath, "utf-8");
1479
+ const raw = fs3.readFileSync(filePath, "utf-8");
2361
1480
  const parsed = JSON.parse(raw);
2362
1481
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed) || parsed.version !== 1 || !parsed.sessions || typeof parsed.sessions !== "object" || Array.isArray(parsed.sessions)) {
2363
1482
  markStateUnreadable(directory, `malformed shape (version=${parsed?.version}, sessions type=${Array.isArray(parsed?.sessions) ? "array" : typeof parsed?.sessions})`);
@@ -2383,7 +1502,7 @@ function writePersisted(directory, persisted) {
2383
1502
  let payload;
2384
1503
  try {
2385
1504
  ensureSwarmDir(directory);
2386
- filePath = path6.join(directory, ".swarm", STATE_FILE);
1505
+ filePath = path3.join(directory, ".swarm", STATE_FILE);
2387
1506
  tmpPath = `${filePath}.tmp.${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
2388
1507
  persisted.updatedAt = nowISO();
2389
1508
  payload = `${JSON.stringify(persisted, null, 2)}
@@ -2394,14 +1513,14 @@ function writePersisted(directory, persisted) {
2394
1513
  throw new Error(`Epic state persistence prepare failed: ${msg}`);
2395
1514
  }
2396
1515
  try {
2397
- fs4.writeFileSync(tmpPath, payload, "utf-8");
2398
- fs4.renameSync(tmpPath, filePath);
1516
+ fs3.writeFileSync(tmpPath, payload, "utf-8");
1517
+ fs3.renameSync(tmpPath, filePath);
2399
1518
  } catch (error2) {
2400
1519
  const msg = error2 instanceof Error ? error2.message : String(error2);
2401
1520
  error(`[turbo/epic/state] Failed to persist ${STATE_FILE} atomically: ${msg}`);
2402
1521
  try {
2403
- if (fs4.existsSync(tmpPath))
2404
- fs4.unlinkSync(tmpPath);
1522
+ if (fs3.existsSync(tmpPath))
1523
+ fs3.unlinkSync(tmpPath);
2405
1524
  } catch {}
2406
1525
  throw new Error(`Epic state persistence failed: ${msg}`);
2407
1526
  }
@@ -2432,7 +1551,7 @@ function isEpicModeActive(directory, sessionID) {
2432
1551
  function isEpicModeActiveForProject(directory) {
2433
1552
  if (stateUnreadableMap.get(directory))
2434
1553
  return false;
2435
- if (!fs4.existsSync(path6.join(directory, ".swarm", STATE_FILE))) {
1554
+ if (!fs3.existsSync(path3.join(directory, ".swarm", STATE_FILE))) {
2436
1555
  return false;
2437
1556
  }
2438
1557
  const persisted = readPersisted(directory);
@@ -2483,11 +1602,11 @@ function isLockContentionError(err) {
2483
1602
  return INDEX_LOCK_ERROR_RE.test(msg);
2484
1603
  }
2485
1604
  async function commitTaskCompletion(directory, taskId, description, scopePaths) {
2486
- if (!_internals8.isGitRepo(directory)) {
1605
+ if (!_internals4.isGitRepo(directory)) {
2487
1606
  return { committed: false, reason: "no-git" };
2488
1607
  }
2489
1608
  try {
2490
- if (_internals8.hasExistingTaskCommit(directory, taskId)) {
1609
+ if (_internals4.hasExistingTaskCommit(directory, taskId)) {
2491
1610
  return { committed: true, reason: "idempotent-skip" };
2492
1611
  }
2493
1612
  } catch {}
@@ -2508,15 +1627,15 @@ async function commitTaskCompletion(directory, taskId, description, scopePaths)
2508
1627
  for (let attempt = 0;attempt <= INDEX_LOCK_BACKOFF_MS.length; attempt++) {
2509
1628
  try {
2510
1629
  if (paths.length > 0) {
2511
- _internals8.stageScopedPaths(directory, paths);
1630
+ _internals4.stageScopedPaths(directory, paths);
2512
1631
  }
2513
- _internals8.commitAllowEmpty(directory, message);
2514
- const sha = _internals8.gitHeadSha(directory);
1632
+ _internals4.commitAllowEmpty(directory, message);
1633
+ const sha = _internals4.gitHeadSha(directory);
2515
1634
  return { committed: true, reason: "success", sha };
2516
1635
  } catch (err) {
2517
1636
  lastError = err;
2518
1637
  if (attempt < INDEX_LOCK_BACKOFF_MS.length && isLockContentionError(err)) {
2519
- await _internals8.sleep(INDEX_LOCK_BACKOFF_MS[attempt]);
1638
+ await _internals4.sleep(INDEX_LOCK_BACKOFF_MS[attempt]);
2520
1639
  continue;
2521
1640
  }
2522
1641
  break;
@@ -2526,26 +1645,26 @@ async function commitTaskCompletion(directory, taskId, description, scopePaths)
2526
1645
  criticalWarn(`[epic:task-commit] commit for task ${taskId} failed (non-fatal): ${msg}`);
2527
1646
  return { committed: false, reason: "commit-failed", error: msg };
2528
1647
  }
2529
- var _internals8 = {
1648
+ var _internals4 = {
2530
1649
  isGitRepo: (cwd) => isGitRepo(cwd),
2531
1650
  stageScopedPaths: (cwd, paths) => {
2532
1651
  const CHUNK = 200;
2533
1652
  for (let i = 0;i < paths.length; i += CHUNK) {
2534
1653
  const chunk = paths.slice(i, i + CHUNK);
2535
- _internals5.gitExec(["add", "--", ...chunk, ":(exclude,glob)**/.swarm/**"], cwd);
1654
+ _internals.gitExec(["add", "--", ...chunk, ":(exclude,glob)**/.swarm/**"], cwd);
2536
1655
  }
2537
1656
  },
2538
1657
  commitAllowEmpty: (cwd, message) => {
2539
- _internals5.gitExec(["commit", "--allow-empty", "--no-verify", "-m", message], cwd);
1658
+ _internals.gitExec(["commit", "--allow-empty", "--no-verify", "-m", message], cwd);
2540
1659
  },
2541
1660
  gitHeadSha: (cwd) => {
2542
- return _internals5.gitExec(["rev-parse", "HEAD"], cwd).trim();
1661
+ return _internals.gitExec(["rev-parse", "HEAD"], cwd).trim();
2543
1662
  },
2544
1663
  sleep: (ms) => new Promise((resolve4) => setTimeout(resolve4, ms)),
2545
1664
  hasExistingTaskCommit: (cwd, taskId) => {
2546
1665
  const safeId = scrubTaskIdForGitSubject(taskId);
2547
1666
  const escaped = safeId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2548
- const output = _internals5.gitExec([
1667
+ const output = _internals.gitExec([
2549
1668
  "log",
2550
1669
  "--extended-regexp",
2551
1670
  `--grep=^swarm\\(task ${escaped}\\):`,
@@ -2558,8 +1677,8 @@ var _internals8 = {
2558
1677
  };
2559
1678
 
2560
1679
  // src/turbo/lean/conflicts.ts
2561
- import * as fs5 from "fs";
2562
- import * as path7 from "path";
1680
+ import * as fs4 from "fs";
1681
+ import * as path4 from "path";
2563
1682
 
2564
1683
  // src/utils/path.ts
2565
1684
  function normalizePath(p) {
@@ -2687,12 +1806,12 @@ function isProtectedPath(normalizedPath) {
2687
1806
  return false;
2688
1807
  }
2689
1808
  function readTaskScopes(directory, taskId) {
2690
- const scopePath = path7.join(directory, ".swarm", "scopes", `scope-${taskId}.json`);
1809
+ const scopePath = path4.join(directory, ".swarm", "scopes", `scope-${taskId}.json`);
2691
1810
  try {
2692
- if (!fs5.existsSync(scopePath)) {
1811
+ if (!fs4.existsSync(scopePath)) {
2693
1812
  return null;
2694
1813
  }
2695
- const raw = fs5.readFileSync(scopePath, "utf-8");
1814
+ const raw = fs4.readFileSync(scopePath, "utf-8");
2696
1815
  const parsed = JSON.parse(raw);
2697
1816
  if (!parsed || !Array.isArray(parsed.files)) {
2698
1817
  return null;
@@ -2706,15 +1825,15 @@ function readTaskScopes(directory, taskId) {
2706
1825
  // src/utils/spec-hash.ts
2707
1826
  import { createHash as createHash3 } from "crypto";
2708
1827
  import * as fsSync2 from "fs";
2709
- import { join as join7 } from "path";
1828
+ import { join as join5 } from "path";
2710
1829
  async function computeSpecHash(directory) {
2711
- const spec = _internals9.readEffectiveSpecSync(directory);
1830
+ const spec = _internals5.readEffectiveSpecSync(directory);
2712
1831
  if (!spec)
2713
1832
  return null;
2714
1833
  return createHash3("sha256").update(spec.content, "utf-8").digest("hex");
2715
1834
  }
2716
1835
  async function isSpecStale(directory, plan) {
2717
- const currentHash = await _internals9.computeSpecHash(directory);
1836
+ const currentHash = await _internals5.computeSpecHash(directory);
2718
1837
  if (!plan.specHash) {
2719
1838
  return { stale: false };
2720
1839
  }
@@ -2735,7 +1854,7 @@ async function isSpecStale(directory, plan) {
2735
1854
  return { stale: false };
2736
1855
  }
2737
1856
  function isObligationPreserving(directory) {
2738
- const snapshotPath = join7(directory, ".swarm", "spec-snapshot.md");
1857
+ const snapshotPath = join5(directory, ".swarm", "spec-snapshot.md");
2739
1858
  try {
2740
1859
  let recordedContent;
2741
1860
  try {
@@ -2743,7 +1862,7 @@ function isObligationPreserving(directory) {
2743
1862
  } catch {
2744
1863
  return false;
2745
1864
  }
2746
- const currentResult = _internals9.readEffectiveSpecSync(directory);
1865
+ const currentResult = _internals5.readEffectiveSpecSync(directory);
2747
1866
  if (!currentResult || !currentResult.content) {
2748
1867
  return false;
2749
1868
  }
@@ -2773,7 +1892,7 @@ function isObligationPreserving(directory) {
2773
1892
  return false;
2774
1893
  }
2775
1894
  }
2776
- var _internals9 = {
1895
+ var _internals5 = {
2777
1896
  computeSpecDiff,
2778
1897
  computeSpecHash,
2779
1898
  isObligationPreserving,
@@ -2781,7 +1900,7 @@ var _internals9 = {
2781
1900
  readEffectiveSpecSync
2782
1901
  };
2783
1902
  function computeSpecDiff(directory) {
2784
- const snapshotPath = join7(directory, ".swarm", "spec-snapshot.md");
1903
+ const snapshotPath = join5(directory, ".swarm", "spec-snapshot.md");
2785
1904
  let recordedContent;
2786
1905
  try {
2787
1906
  const snapshotSize = fsSync2.statSync(snapshotPath).size;
@@ -2793,7 +1912,7 @@ function computeSpecDiff(directory) {
2793
1912
  } catch {
2794
1913
  return null;
2795
1914
  }
2796
- const spec = _internals9.readEffectiveSpecSync(directory);
1915
+ const spec = _internals5.readEffectiveSpecSync(directory);
2797
1916
  if (!spec) {
2798
1917
  return null;
2799
1918
  }
@@ -2887,7 +2006,7 @@ var startupLedgerCheckedWorkspaces = new Set;
2887
2006
  var ledgerStaleWorkspaces = new Set;
2888
2007
  var recoveryMutexes = new Map;
2889
2008
  var PLAN_JSON_CACHE_NAMESPACE = "plan-json:validated:v1";
2890
- var _internals10 = {
2009
+ var _internals6 = {
2891
2010
  loadPlan,
2892
2011
  loadPlanJsonOnly,
2893
2012
  regeneratePlanMarkdown,
@@ -3028,7 +2147,7 @@ async function getLatestLedgerHash(directory) {
3028
2147
  }
3029
2148
  }
3030
2149
  async function surfaceLedgerStaleIfPersisted(directory, plan) {
3031
- const resolvedWorkspace = path8.resolve(directory);
2150
+ const resolvedWorkspace = path5.resolve(directory);
3032
2151
  if (!ledgerStaleWorkspaces.has(resolvedWorkspace)) {
3033
2152
  return plan;
3034
2153
  }
@@ -3047,7 +2166,7 @@ async function surfaceLedgerStaleIfPersisted(directory, plan) {
3047
2166
  return plan;
3048
2167
  }
3049
2168
  async function parsePlanJsonCached(directory) {
3050
- const planJsonPath = path8.resolve(directory, ".swarm", "plan.json");
2169
+ const planJsonPath = path5.resolve(directory, ".swarm", "plan.json");
3051
2170
  return readCachedParsedFile(planJsonPath, PLAN_JSON_CACHE_NAMESPACE, () => readSwarmFileAsync(directory, "plan.json"), (planJsonContent) => {
3052
2171
  if (planJsonContent.includes("\x00") || planJsonContent.includes("\uFFFD")) {
3053
2172
  throw new Error("Plan rejected: .swarm/plan.json contains null bytes or invalid encoding");
@@ -3109,13 +2228,13 @@ async function isPlanMdInSync(directory, plan, cache) {
3109
2228
  }
3110
2229
  async function regeneratePlanMarkdown(directory, plan) {
3111
2230
  assertProjectRoot(directory);
3112
- const swarmDir = path8.resolve(directory, ".swarm");
2231
+ const swarmDir = path5.resolve(directory, ".swarm");
3113
2232
  const contentHash = computePlanContentHash(plan);
3114
2233
  const markdown = derivePlanMarkdown(plan);
3115
2234
  const markdownWithHash = `<!-- PLAN_HASH: ${contentHash} -->
3116
2235
  ${markdown}`;
3117
- const mdPath = path8.join(swarmDir, "plan.md");
3118
- const mdTempPath = path8.join(swarmDir, `plan.md.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
2236
+ const mdPath = path5.join(swarmDir, "plan.md");
2237
+ const mdTempPath = path5.join(swarmDir, `plan.md.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
3119
2238
  try {
3120
2239
  await bunWrite(mdTempPath, markdownWithHash);
3121
2240
  renameSync2(mdTempPath, mdPath);
@@ -3140,7 +2259,7 @@ async function loadPlan(directory, cache) {
3140
2259
  const inSync = await isPlanMdInSync(directory, validated, cache);
3141
2260
  if (!inSync) {
3142
2261
  try {
3143
- await _internals10.regeneratePlanMarkdown(directory, validated);
2262
+ await _internals6.regeneratePlanMarkdown(directory, validated);
3144
2263
  } catch (regenError) {
3145
2264
  warn(`Failed to regenerate plan.md: ${regenError instanceof Error ? regenError.message : String(regenError)}. Proceeding with plan.json only.`);
3146
2265
  }
@@ -3148,7 +2267,7 @@ async function loadPlan(directory, cache) {
3148
2267
  if (await ledgerExists(directory)) {
3149
2268
  const planHash = computePlanHash(validated);
3150
2269
  const ledgerHash = await getLatestLedgerHash(directory);
3151
- const resolvedWorkspace = path8.resolve(directory);
2270
+ const resolvedWorkspace = path5.resolve(directory);
3152
2271
  if (!startupLedgerCheckedWorkspaces.has(resolvedWorkspace)) {
3153
2272
  startupLedgerCheckedWorkspaces.add(resolvedWorkspace);
3154
2273
  if (ledgerHash !== "" && planHash !== ledgerHash) {
@@ -3223,7 +2342,7 @@ async function loadPlan(directory, cache) {
3223
2342
  try {
3224
2343
  assertProjectRoot(directory);
3225
2344
  const diffInfo = computeSpecDiff(directory);
3226
- const specStalenessPath = path8.join(directory, ".swarm", "spec-staleness.json");
2345
+ const specStalenessPath = path5.join(directory, ".swarm", "spec-staleness.json");
3227
2346
  await fsPromises.writeFile(specStalenessPath, JSON.stringify({
3228
2347
  type: "spec_stale_detected",
3229
2348
  timestamp: new Date().toISOString(),
@@ -3239,7 +2358,7 @@ async function loadPlan(directory, cache) {
3239
2358
  } catch {}
3240
2359
  try {
3241
2360
  assertProjectRoot(directory);
3242
- const eventsPath = path8.join(directory, ".swarm", "events.jsonl");
2361
+ const eventsPath = path5.join(directory, ".swarm", "events.jsonl");
3243
2362
  const event = {
3244
2363
  type: "spec_stale_detected",
3245
2364
  timestamp: new Date().toISOString(),
@@ -3305,11 +2424,11 @@ async function loadPlan(directory, cache) {
3305
2424
  return migrated;
3306
2425
  }
3307
2426
  if (await ledgerExists(directory)) {
3308
- const resolvedDir = path8.resolve(directory);
2427
+ const resolvedDir = path5.resolve(directory);
3309
2428
  const existingMutex = recoveryMutexes.get(resolvedDir);
3310
2429
  if (existingMutex) {
3311
2430
  await existingMutex;
3312
- const postRecoveryPlan = await _internals10.loadPlanJsonOnly(directory);
2431
+ const postRecoveryPlan = await _internals6.loadPlanJsonOnly(directory);
3313
2432
  if (postRecoveryPlan)
3314
2433
  return postRecoveryPlan;
3315
2434
  }
@@ -3369,7 +2488,7 @@ async function loadPlan(directory, cache) {
3369
2488
  return null;
3370
2489
  }
3371
2490
  async function savePlanWithAutoAcknowledgedRemovals(directory, plan, source, reason, options) {
3372
- const existing = await _internals10.loadPlanJsonOnly(directory);
2491
+ const existing = await _internals6.loadPlanJsonOnly(directory);
3373
2492
  const newIds = new Set;
3374
2493
  for (const phase of plan.phases) {
3375
2494
  for (const task of phase.tasks)
@@ -3419,7 +2538,7 @@ async function savePlan(directory, plan, options) {
3419
2538
  }
3420
2539
  if (options?.preserveCompletedStatuses !== false) {
3421
2540
  try {
3422
- const currentPlan2 = await _internals10.loadPlanJsonOnly(directory);
2541
+ const currentPlan2 = await _internals6.loadPlanJsonOnly(directory);
3423
2542
  if (currentPlan2) {
3424
2543
  const completedTaskIds = new Set;
3425
2544
  for (const phase of currentPlan2.phases) {
@@ -3441,7 +2560,7 @@ async function savePlan(directory, plan, options) {
3441
2560
  } catch {}
3442
2561
  }
3443
2562
  derivePhaseStatusesInPlace(validated);
3444
- const currentPlan = await _internals10.loadPlanJsonOnly(directory);
2563
+ const currentPlan = await _internals6.loadPlanJsonOnly(directory);
3445
2564
  const planId = derivePlanId(validated);
3446
2565
  const planHashForInit = computePlanHash(validated);
3447
2566
  if (!await ledgerExists(directory)) {
@@ -3456,9 +2575,9 @@ async function savePlan(directory, plan, options) {
3456
2575
  } else {
3457
2576
  const existingEvents = await readLedgerEvents(directory);
3458
2577
  if (existingEvents.length > 0 && existingEvents[0].plan_id !== planId) {
3459
- const swarmDir2 = path8.resolve(directory, ".swarm");
3460
- const oldLedgerPath = path8.join(swarmDir2, "plan-ledger.jsonl");
3461
- const oldLedgerBackupPath = path8.join(swarmDir2, `plan-ledger.backup-${Date.now()}-${Math.floor(Math.random() * 1e9)}.jsonl`);
2578
+ const swarmDir2 = path5.resolve(directory, ".swarm");
2579
+ const oldLedgerPath = path5.join(swarmDir2, "plan-ledger.jsonl");
2580
+ const oldLedgerBackupPath = path5.join(swarmDir2, `plan-ledger.backup-${Date.now()}-${Math.floor(Math.random() * 1e9)}.jsonl`);
3462
2581
  let backupExists = false;
3463
2582
  if (existsSync4(oldLedgerPath)) {
3464
2583
  try {
@@ -3496,7 +2615,7 @@ async function savePlan(directory, plan, options) {
3496
2615
  }
3497
2616
  }
3498
2617
  if (initSucceeded && backupExists) {
3499
- const archivePath = path8.join(swarmDir2, `plan-ledger.archived-${Date.now()}-${Math.floor(Math.random() * 1e9)}.jsonl`);
2618
+ const archivePath = path5.join(swarmDir2, `plan-ledger.archived-${Date.now()}-${Math.floor(Math.random() * 1e9)}.jsonl`);
3500
2619
  try {
3501
2620
  renameSync2(oldLedgerBackupPath, archivePath);
3502
2621
  warn(`[savePlan] Ledger identity mismatch (was "${existingEvents[0].plan_id}", now "${planId}") \u2014 archived old ledger to ${archivePath} and reinitializing.`);
@@ -3521,7 +2640,7 @@ async function savePlan(directory, plan, options) {
3521
2640
  const toRemove = archivedSiblings.slice(0, archivedSiblings.length - MAX_ARCHIVED_SIBLINGS);
3522
2641
  for (const file of toRemove) {
3523
2642
  try {
3524
- unlinkSync2(path8.join(swarmDir2, file));
2643
+ unlinkSync2(path5.join(swarmDir2, file));
3525
2644
  } catch {}
3526
2645
  }
3527
2646
  }
@@ -3623,7 +2742,7 @@ async function savePlan(directory, plan, options) {
3623
2742
  expectedHash: currentHash,
3624
2743
  planHashAfter: hashAfter,
3625
2744
  verifyValid: async () => {
3626
- const onDisk = await _internals10.loadPlanJsonOnly(directory);
2745
+ const onDisk = await _internals6.loadPlanJsonOnly(directory);
3627
2746
  if (!onDisk)
3628
2747
  return true;
3629
2748
  for (const p of onDisk.phases) {
@@ -3661,7 +2780,7 @@ async function savePlan(directory, plan, options) {
3661
2780
  expectedHash: currentHash,
3662
2781
  planHashAfter: hashAfter,
3663
2782
  verifyValid: async () => {
3664
- const onDisk = await _internals10.loadPlanJsonOnly(directory);
2783
+ const onDisk = await _internals6.loadPlanJsonOnly(directory);
3665
2784
  if (!onDisk)
3666
2785
  return true;
3667
2786
  for (const p of onDisk.phases) {
@@ -3701,9 +2820,9 @@ async function savePlan(directory, plan, options) {
3701
2820
  source: "savePlan_manager"
3702
2821
  });
3703
2822
  }
3704
- const swarmDir = path8.resolve(directory, ".swarm");
3705
- const planPath = path8.join(swarmDir, "plan.json");
3706
- const tempPath = path8.join(swarmDir, `plan.json.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
2823
+ const swarmDir = path5.resolve(directory, ".swarm");
2824
+ const planPath = path5.join(swarmDir, "plan.json");
2825
+ const tempPath = path5.join(swarmDir, `plan.json.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
3707
2826
  try {
3708
2827
  await bunWrite(tempPath, JSON.stringify(projectedPlan, null, 2));
3709
2828
  renameSync2(tempPath, planPath);
@@ -3714,7 +2833,7 @@ async function savePlan(directory, plan, options) {
3714
2833
  }
3715
2834
  invalidateCachedArtifact(planPath);
3716
2835
  try {
3717
- const markerPath = path8.join(swarmDir, ".plan-write-marker");
2836
+ const markerPath = path5.join(swarmDir, ".plan-write-marker");
3718
2837
  const inProgressMarker = JSON.stringify({
3719
2838
  source: "plan_manager",
3720
2839
  timestamp: new Date().toISOString(),
@@ -3729,8 +2848,8 @@ async function savePlan(directory, plan, options) {
3729
2848
  const markdown = derivePlanMarkdown(projectedPlan);
3730
2849
  const markdownWithHash = `<!-- PLAN_HASH: ${contentHash} -->
3731
2850
  ${markdown}`;
3732
- const mdPath = path8.join(swarmDir, "plan.md");
3733
- const mdTempPath = path8.join(swarmDir, `plan.md.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
2851
+ const mdPath = path5.join(swarmDir, "plan.md");
2852
+ const mdTempPath = path5.join(swarmDir, `plan.md.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
3734
2853
  try {
3735
2854
  await bunWrite(mdTempPath, markdownWithHash);
3736
2855
  renameSync2(mdTempPath, mdPath);
@@ -3752,7 +2871,7 @@ ${markdown}`;
3752
2871
  } catch {}
3753
2872
  }
3754
2873
  try {
3755
- const markerPath = path8.join(swarmDir, ".plan-write-marker");
2874
+ const markerPath = path5.join(swarmDir, ".plan-write-marker");
3756
2875
  const tasksCount = projectedPlan.phases.reduce((sum, phase) => sum + phase.tasks.length, 0);
3757
2876
  const marker = JSON.stringify({
3758
2877
  source: "plan_manager",
@@ -3800,15 +2919,15 @@ async function rebuildPlan(directory, plan, options) {
3800
2919
  const targetPlan = plan ?? await replayFromLedger(directory);
3801
2920
  if (!targetPlan)
3802
2921
  return null;
3803
- const swarmDir = path8.join(directory, ".swarm");
3804
- const planPath = path8.join(swarmDir, "plan.json");
3805
- const mdPath = path8.join(swarmDir, "plan.md");
3806
- mkdirSync4(swarmDir, { recursive: true });
3807
- const tempPlanPath = path8.join(swarmDir, `plan.json.rebuild.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
2922
+ const swarmDir = path5.join(directory, ".swarm");
2923
+ const planPath = path5.join(swarmDir, "plan.json");
2924
+ const mdPath = path5.join(swarmDir, "plan.md");
2925
+ mkdirSync3(swarmDir, { recursive: true });
2926
+ const tempPlanPath = path5.join(swarmDir, `plan.json.rebuild.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
3808
2927
  {
3809
2928
  const fd = openSync(tempPlanPath, "w");
3810
2929
  try {
3811
- writeFileSync4(fd, JSON.stringify(targetPlan, null, 2), "utf8");
2930
+ writeFileSync2(fd, JSON.stringify(targetPlan, null, 2), "utf8");
3812
2931
  fsyncSync(fd);
3813
2932
  } finally {
3814
2933
  closeSync(fd);
@@ -3817,7 +2936,7 @@ async function rebuildPlan(directory, plan, options) {
3817
2936
  renameSync2(tempPlanPath, planPath);
3818
2937
  invalidateCachedArtifact(planPath);
3819
2938
  try {
3820
- const markerPath = path8.join(swarmDir, ".plan-write-marker");
2939
+ const markerPath = path5.join(swarmDir, ".plan-write-marker");
3821
2940
  const inProgressMarker = JSON.stringify({
3822
2941
  source: "plan_manager",
3823
2942
  timestamp: new Date().toISOString(),
@@ -3832,13 +2951,13 @@ async function rebuildPlan(directory, plan, options) {
3832
2951
  const markdown = derivePlanMarkdown(targetPlan);
3833
2952
  const markdownWithHash = `<!-- PLAN_HASH: ${contentHash} -->
3834
2953
  ${markdown}`;
3835
- const tempMdPath = path8.join(swarmDir, `plan.md.rebuild.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
2954
+ const tempMdPath = path5.join(swarmDir, `plan.md.rebuild.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
3836
2955
  await bunWrite(tempMdPath, markdownWithHash);
3837
2956
  renameSync2(tempMdPath, mdPath);
3838
2957
  invalidateCachedArtifact(mdPath);
3839
2958
  } finally {
3840
2959
  try {
3841
- const markerPath = path8.join(swarmDir, ".plan-write-marker");
2960
+ const markerPath = path5.join(swarmDir, ".plan-write-marker");
3842
2961
  const tasksCount = targetPlan.phases.reduce((sum, phase) => sum + phase.tasks.length, 0);
3843
2962
  const marker = JSON.stringify({
3844
2963
  source: "plan_manager",
@@ -3902,14 +3021,14 @@ async function closePlanTerminalState(directory, plan, options) {
3902
3021
  planHashAfter: hashAfter,
3903
3022
  source: "close_terminal"
3904
3023
  });
3905
- const swarmDir = path8.join(directory, ".swarm");
3906
- const planPath = path8.join(swarmDir, "plan.json");
3907
- const tempPlanPath = path8.join(swarmDir, `plan.json.close.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
3024
+ const swarmDir = path5.join(directory, ".swarm");
3025
+ const planPath = path5.join(swarmDir, "plan.json");
3026
+ const tempPlanPath = path5.join(swarmDir, `plan.json.close.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
3908
3027
  await bunWrite(tempPlanPath, JSON.stringify(validated, null, 2));
3909
3028
  renameSync2(tempPlanPath, planPath);
3910
3029
  invalidateCachedArtifact(planPath);
3911
3030
  try {
3912
- const markerPath = path8.join(swarmDir, ".plan-write-marker");
3031
+ const markerPath = path5.join(swarmDir, ".plan-write-marker");
3913
3032
  const inProgressMarker = JSON.stringify({
3914
3033
  source: "plan_manager_close",
3915
3034
  timestamp: new Date().toISOString(),
@@ -3920,18 +3039,18 @@ async function closePlanTerminalState(directory, plan, options) {
3920
3039
  await bunWrite(markerPath, inProgressMarker);
3921
3040
  } catch {}
3922
3041
  try {
3923
- const mdPath = path8.join(swarmDir, "plan.md");
3042
+ const mdPath = path5.join(swarmDir, "plan.md");
3924
3043
  const contentHash = computePlanContentHash(validated);
3925
3044
  const markdown = derivePlanMarkdown(validated);
3926
3045
  const markdownWithHash = `<!-- PLAN_HASH: ${contentHash} -->
3927
3046
  ${markdown}`;
3928
- const mdTempPath = path8.join(swarmDir, `plan.md.close.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
3047
+ const mdTempPath = path5.join(swarmDir, `plan.md.close.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
3929
3048
  await bunWrite(mdTempPath, markdownWithHash);
3930
3049
  renameSync2(mdTempPath, mdPath);
3931
3050
  invalidateCachedArtifact(mdPath);
3932
3051
  } finally {
3933
3052
  try {
3934
- const markerPath = path8.join(swarmDir, ".plan-write-marker");
3053
+ const markerPath = path5.join(swarmDir, ".plan-write-marker");
3935
3054
  const tasksCount = validated.phases.reduce((sum, phase) => sum + phase.tasks.length, 0);
3936
3055
  const marker = JSON.stringify({
3937
3056
  source: "plan_manager_close",
@@ -3959,7 +3078,7 @@ async function updateTaskStatus(directory, taskId, status, options) {
3959
3078
  return "pending";
3960
3079
  };
3961
3080
  {
3962
- const currentPlan = await _internals10.loadPlanJsonOnly(directory);
3081
+ const currentPlan = await _internals6.loadPlanJsonOnly(directory);
3963
3082
  if (currentPlan) {
3964
3083
  const currentTask = currentPlan.phases.flatMap((p) => p.tasks).find((t) => t.id === taskId);
3965
3084
  const settled = currentTask && currentTask.status !== "pending" && currentTask.status !== "in_progress";
@@ -3972,7 +3091,7 @@ async function updateTaskStatus(directory, taskId, status, options) {
3972
3091
  }
3973
3092
  const MAX_OUTER_RETRIES = 1;
3974
3093
  for (let attempt = 0;attempt <= MAX_OUTER_RETRIES; attempt++) {
3975
- const plan = await _internals10.loadPlan(directory);
3094
+ const plan = await _internals6.loadPlan(directory);
3976
3095
  if (plan === null) {
3977
3096
  throw new Error(`Plan not found in directory: ${directory}`);
3978
3097
  }
@@ -4003,7 +3122,7 @@ async function updateTaskStatus(directory, taskId, status, options) {
4003
3122
  if (status === "completed" || status === "blocked") {
4004
3123
  const recordedTask = updatedPlan.phases.flatMap((phase) => phase.tasks).find((candidate) => candidate.id === taskId);
4005
3124
  try {
4006
- await _internals10.recordTaskAttempt(directory, {
3125
+ await _internals6.recordTaskAttempt(directory, {
4007
3126
  taskId,
4008
3127
  agent: "plan-status",
4009
3128
  outcome: status === "completed" ? "pass" : "fail",
@@ -4014,8 +3133,8 @@ async function updateTaskStatus(directory, taskId, status, options) {
4014
3133
  warn(`[plan/manager] run-memory record for ${taskId} failed: ${err instanceof Error ? err.message : String(err)}`);
4015
3134
  }
4016
3135
  }
4017
- if (status === "completed" && _internals10.isGitRepo(directory) && _internals10.isEpicModeActiveForProject(directory)) {
4018
- const mergeFailure = _internals10.getWorktreeMergeFailure(taskId);
3136
+ if (status === "completed" && _internals6.isGitRepo(directory) && _internals6.isEpicModeActiveForProject(directory)) {
3137
+ const mergeFailure = _internals6.getWorktreeMergeFailure(taskId);
4019
3138
  if (mergeFailure) {
4020
3139
  criticalWarn(`[plan/manager] Rule 2 auto-commit SKIPPED for ${taskId}: worktree merge-back ${mergeFailure.outcome} at stage '${mergeFailure.stage}'. The task's changes are NOT in the main tree, so no completion marker is written (Rule 3 must not treat this task as satisfied). Resolve the preserved worktree, then re-run the task. Detail: ${mergeFailure.message}`);
4021
3140
  return updatedPlan;
@@ -4029,8 +3148,8 @@ async function updateTaskStatus(directory, taskId, status, options) {
4029
3148
  break;
4030
3149
  }
4031
3150
  }
4032
- const canonicalScope = _internals10.readTaskScopes(directory, taskId);
4033
- await _internals10.commitTaskCompletion(directory, taskId, taskDescription, canonicalScope ?? undefined);
3151
+ const canonicalScope = _internals6.readTaskScopes(directory, taskId);
3152
+ await _internals6.commitTaskCompletion(directory, taskId, taskDescription, canonicalScope ?? undefined);
4034
3153
  } catch (commitErr) {
4035
3154
  criticalWarn(`[plan/manager] Rule 2 auto-commit for ${taskId} threw (non-fatal): ${commitErr instanceof Error ? commitErr.message : String(commitErr)}`);
4036
3155
  }
@@ -4343,19 +3462,19 @@ function migrateLegacyPlan(planContent, swarmId) {
4343
3462
  // src/evidence/manager.ts
4344
3463
  init_zod();
4345
3464
  import {
4346
- mkdirSync as mkdirSync5,
3465
+ mkdirSync as mkdirSync4,
4347
3466
  readdirSync as readdirSync2,
4348
3467
  realpathSync as realpathSync2,
4349
3468
  renameSync as renameSync3,
4350
3469
  rmSync,
4351
3470
  statSync as statSync2
4352
3471
  } from "fs";
4353
- import * as fs8 from "fs/promises";
4354
- import * as path10 from "path";
3472
+ import * as fs7 from "fs/promises";
3473
+ import * as path7 from "path";
4355
3474
 
4356
3475
  // src/evaluation/retention.ts
4357
- import * as fs6 from "fs/promises";
4358
- import * as path9 from "path";
3476
+ import * as fs5 from "fs/promises";
3477
+ import * as path6 from "path";
4359
3478
  function artifactKey(artifact) {
4360
3479
  return `${artifact.namespace}/${artifact.id}`;
4361
3480
  }
@@ -4363,10 +3482,10 @@ function validId(value) {
4363
3482
  return /^[A-Za-z0-9][A-Za-z0-9._-]{0,159}$/.test(value);
4364
3483
  }
4365
3484
  async function evaluationRunCandidates(directory) {
4366
- const root = path9.join(directory, ".swarm", "evolution", "runs");
3485
+ const root = path6.join(directory, ".swarm", "evolution", "runs");
4367
3486
  let entries = [];
4368
3487
  try {
4369
- entries = await fs6.readdir(root, { withFileTypes: true });
3488
+ entries = await fs5.readdir(root, { withFileTypes: true });
4370
3489
  } catch (error2) {
4371
3490
  if (error2.code === "ENOENT") {
4372
3491
  return { candidates: [], corrupt: [] };
@@ -4382,9 +3501,9 @@ async function evaluationRunCandidates(directory) {
4382
3501
  if (!validId(id))
4383
3502
  continue;
4384
3503
  const artifact = { namespace: "evaluation-run", id };
4385
- const target = path9.join(root, entry.name);
3504
+ const target = path6.join(root, entry.name);
4386
3505
  try {
4387
- const run = EvaluationRunV1Schema.parse(JSON.parse(await fs6.readFile(target, "utf8")));
3506
+ const run = EvaluationRunV1Schema.parse(JSON.parse(await fs5.readFile(target, "utf8")));
4388
3507
  if (run.runId !== id)
4389
3508
  throw new Error("run id/path mismatch");
4390
3509
  candidates.push({
@@ -4400,10 +3519,10 @@ async function evaluationRunCandidates(directory) {
4400
3519
  return { candidates, corrupt };
4401
3520
  }
4402
3521
  async function gateAuditCandidates(directory) {
4403
- const root = path9.join(directory, ".swarm", "evidence", "gate-audit");
3522
+ const root = path6.join(directory, ".swarm", "evidence", "gate-audit");
4404
3523
  let entries = [];
4405
3524
  try {
4406
- entries = await fs6.readdir(root, { withFileTypes: true });
3525
+ entries = await fs5.readdir(root, { withFileTypes: true });
4407
3526
  } catch (error2) {
4408
3527
  if (error2.code === "ENOENT") {
4409
3528
  return { candidates: [], corrupt: [] };
@@ -4416,9 +3535,9 @@ async function gateAuditCandidates(directory) {
4416
3535
  if (!entry.isDirectory() || !validId(entry.name))
4417
3536
  continue;
4418
3537
  const artifact = { namespace: "gate-audit", id: entry.name };
4419
- const target = path9.join(root, entry.name);
3538
+ const target = path6.join(root, entry.name);
4420
3539
  try {
4421
- const result = GateAuditResultV1Schema.parse(JSON.parse(await fs6.readFile(path9.join(target, "results.json"), "utf8")));
3540
+ const result = GateAuditResultV1Schema.parse(JSON.parse(await fs5.readFile(path6.join(target, "results.json"), "utf8")));
4422
3541
  if (result.runId !== entry.name)
4423
3542
  throw new Error("run id/path mismatch");
4424
3543
  candidates.push({
@@ -4449,10 +3568,10 @@ async function protectedArtifacts(directory) {
4449
3568
  }
4450
3569
  async function removeCandidate(candidate) {
4451
3570
  if (candidate.kind === "directory") {
4452
- await fs6.rm(candidate.target, { recursive: true, force: true });
3571
+ await fs5.rm(candidate.target, { recursive: true, force: true });
4453
3572
  return;
4454
3573
  }
4455
- await fs6.unlink(candidate.target);
3574
+ await fs5.unlink(candidate.target);
4456
3575
  }
4457
3576
  var _retentionInternals = {
4458
3577
  protectedArtifacts,
@@ -4460,7 +3579,7 @@ var _retentionInternals = {
4460
3579
  };
4461
3580
  async function archiveEvaluationArtifacts(args) {
4462
3581
  assertProjectRoot(args.directory);
4463
- return withEvidenceLock(args.directory, path9.join("evolution", "retention-index"), "evaluation-retention", "archive", async () => {
3582
+ return withEvidenceLock(args.directory, path6.join("evolution", "retention-index"), "evaluation-retention", "archive", async () => {
4464
3583
  const inventory = await retentionCandidates(args.directory);
4465
3584
  let protectedKeys = await _retentionInternals.protectedArtifacts(args.directory);
4466
3585
  const protectedRefs = inventory.candidates.filter((candidate) => protectedKeys.has(artifactKey(candidate.artifact))).map((candidate) => candidate.artifact);
@@ -4509,7 +3628,7 @@ async function archiveEvaluationArtifacts(args) {
4509
3628
  }
4510
3629
 
4511
3630
  // src/evidence/documents-retention.ts
4512
- import * as fs7 from "fs";
3631
+ import * as fs6 from "fs";
4513
3632
  import * as fsp from "fs/promises";
4514
3633
  import * as readline from "readline";
4515
3634
  var EVIDENCE_CACHE_FILE = "evidence-cache/documents.jsonl";
@@ -4517,13 +3636,13 @@ var MAX_READ_BYTES = 100 * 1024 * 1024;
4517
3636
  var RENAME_MAX_ATTEMPTS = 5;
4518
3637
  var RENAME_BACKOFF_MS = 10;
4519
3638
  var RENAME_RETRY_CODES = new Set(["EPERM", "EBUSY", "ENOTEMPTY", "EACCES"]);
4520
- var _internals11 = {
3639
+ var _internals7 = {
4521
3640
  stat: (p) => fsp.stat(p),
4522
- createReadStream: (p, options) => fs7.createReadStream(p, options),
4523
- openSync: (p, flags) => fs7.openSync(p, flags),
4524
- writeSync: (fd, data, position) => fs7.writeSync(fd, data, position),
4525
- fsyncSync: (fd) => fs7.fsyncSync(fd),
4526
- closeSync: (fd) => fs7.closeSync(fd),
3641
+ createReadStream: (p, options) => fs6.createReadStream(p, options),
3642
+ openSync: (p, flags) => fs6.openSync(p, flags),
3643
+ writeSync: (fd, data, position) => fs6.writeSync(fd, data, position),
3644
+ fsyncSync: (fd) => fs6.fsyncSync(fd),
3645
+ closeSync: (fd) => fs6.closeSync(fd),
4527
3646
  renameWithRetry: atomicRenameWithRetry,
4528
3647
  unlink: (p) => fsp.unlink(p)
4529
3648
  };
@@ -4559,9 +3678,9 @@ function emptyResult(dryRun) {
4559
3678
  };
4560
3679
  }
4561
3680
  async function readCacheRows(filePath) {
4562
- const stat2 = await _internals11.stat(filePath);
3681
+ const stat2 = await _internals7.stat(filePath);
4563
3682
  const bytesBefore = stat2.size;
4564
- const stream = _internals11.createReadStream(filePath, {
3683
+ const stream = _internals7.createReadStream(filePath, {
4565
3684
  encoding: "utf8",
4566
3685
  highWaterMark: 64 * 1024
4567
3686
  });
@@ -4637,23 +3756,23 @@ async function rewriteAtomic(filePath, survivors) {
4637
3756
  `)}
4638
3757
  ` : "";
4639
3758
  let succeeded = false;
4640
- const fd = _internals11.openSync(tmpPath, "w");
3759
+ const fd = _internals7.openSync(tmpPath, "w");
4641
3760
  try {
4642
- _internals11.writeSync(fd, payload, 0);
4643
- _internals11.fsyncSync(fd);
4644
- _internals11.closeSync(fd);
4645
- await _internals11.renameWithRetry(tmpPath, filePath);
3761
+ _internals7.writeSync(fd, payload, 0);
3762
+ _internals7.fsyncSync(fd);
3763
+ _internals7.closeSync(fd);
3764
+ await _internals7.renameWithRetry(tmpPath, filePath);
4646
3765
  succeeded = true;
4647
3766
  } catch (err) {
4648
3767
  try {
4649
- _internals11.closeSync(fd);
3768
+ _internals7.closeSync(fd);
4650
3769
  } catch {}
4651
3770
  const msg = err instanceof Error ? err.message : String(err);
4652
3771
  throw new Error(`documents-cache rewrite failed: ${msg}`);
4653
3772
  } finally {
4654
3773
  if (!succeeded) {
4655
3774
  try {
4656
- await _internals11.unlink(tmpPath);
3775
+ await _internals7.unlink(tmpPath);
4657
3776
  } catch {}
4658
3777
  }
4659
3778
  }
@@ -4666,7 +3785,7 @@ async function pruneEvidenceDocuments(args) {
4666
3785
  const filePath = validateSwarmPath(args.directory, EVIDENCE_CACHE_FILE);
4667
3786
  let stat2;
4668
3787
  try {
4669
- stat2 = await _internals11.stat(filePath);
3788
+ stat2 = await _internals7.stat(filePath);
4670
3789
  } catch (err) {
4671
3790
  const code = err?.code;
4672
3791
  if (code === "ENOENT")
@@ -4767,21 +3886,21 @@ function isValidEvidenceType(type) {
4767
3886
  var sanitizeTaskId2 = sanitizeTaskId;
4768
3887
  function validateProjectRoot(directory) {
4769
3888
  assertProjectRoot(directory, {
4770
- realpathSync: _internals12.realpathSync,
4771
- statSync: _internals12.statSync
3889
+ realpathSync: _internals8.realpathSync,
3890
+ statSync: _internals8.statSync
4772
3891
  }, "evidence");
4773
3892
  }
4774
3893
  async function saveEvidence(directory, taskId, evidence, abortSignal) {
4775
3894
  abortSignal?.throwIfAborted();
4776
- _internals12.validateProjectRoot(directory);
3895
+ _internals8.validateProjectRoot(directory);
4777
3896
  const sanitizedTaskId = sanitizeTaskId2(taskId);
4778
- const relativePath = path10.join("evidence", sanitizedTaskId, "evidence.json");
3897
+ const relativePath = path7.join("evidence", sanitizedTaskId, "evidence.json");
4779
3898
  validateSwarmPath(directory, relativePath);
4780
- _internals12.validateEvidence(evidence);
3899
+ _internals8.validateEvidence(evidence);
4781
3900
  return withEvidenceLock(directory, relativePath, "evidence-manager", sanitizedTaskId, async () => {
4782
3901
  abortSignal?.throwIfAborted();
4783
3902
  const evidencePath = validateSwarmPath(directory, relativePath);
4784
- const evidenceDir = path10.dirname(evidencePath);
3903
+ const evidenceDir = path7.dirname(evidencePath);
4785
3904
  let bundle;
4786
3905
  const existingContent = await readSwarmFileAsync(directory, relativePath);
4787
3906
  abortSignal?.throwIfAborted();
@@ -4824,8 +3943,8 @@ async function saveEvidence(directory, taskId, evidence, abortSignal) {
4824
3943
  if (bundleJson.length > EVIDENCE_MAX_JSON_BYTES) {
4825
3944
  throw new Error(`Evidence bundle size (${bundleJson.length} bytes) exceeds maximum (${EVIDENCE_MAX_JSON_BYTES} bytes)`);
4826
3945
  }
4827
- mkdirSync5(evidenceDir, { recursive: true });
4828
- const tempPath = path10.join(evidenceDir, `evidence.json.tmp.${Date.now()}.${process.pid}`);
3946
+ mkdirSync4(evidenceDir, { recursive: true });
3947
+ const tempPath = path7.join(evidenceDir, `evidence.json.tmp.${Date.now()}.${process.pid}`);
4829
3948
  try {
4830
3949
  await bunWrite(tempPath, bundleJson);
4831
3950
  abortSignal?.throwIfAborted();
@@ -4871,7 +3990,7 @@ function wrapFlatRetrospective(flatEntry, taskId) {
4871
3990
  }
4872
3991
  async function loadEvidence(directory, taskId, options) {
4873
3992
  const sanitizedTaskId = sanitizeTaskId2(taskId);
4874
- const relativePath = path10.join("evidence", sanitizedTaskId, "evidence.json");
3993
+ const relativePath = path7.join("evidence", sanitizedTaskId, "evidence.json");
4875
3994
  if (relativePath.length > 4096) {
4876
3995
  return { status: "not_found" };
4877
3996
  }
@@ -4887,7 +4006,7 @@ async function loadEvidence(directory, taskId, options) {
4887
4006
  return { status: "invalid_schema", errors: ["Invalid JSON"] };
4888
4007
  }
4889
4008
  if (isFlatRetrospective(parsed)) {
4890
- const wrappedBundle = _internals12.wrapFlatRetrospective(parsed, sanitizedTaskId);
4009
+ const wrappedBundle = _internals8.wrapFlatRetrospective(parsed, sanitizedTaskId);
4891
4010
  try {
4892
4011
  const validated = EvidenceBundleSchema.parse(wrappedBundle);
4893
4012
  if (options?.migrate === false) {
@@ -4896,12 +4015,12 @@ async function loadEvidence(directory, taskId, options) {
4896
4015
  try {
4897
4016
  validateProjectRoot(directory);
4898
4017
  await withEvidenceLock(directory, relativePath, "evidence-loader", sanitizedTaskId, async () => {
4899
- const evidenceDir = path10.dirname(evidencePath);
4018
+ const evidenceDir = path7.dirname(evidencePath);
4900
4019
  const bundleJson = JSON.stringify(validated);
4901
- const tempPath = path10.join(evidenceDir, `evidence.json.tmp.${Date.now()}.${process.pid}`);
4020
+ const tempPath = path7.join(evidenceDir, `evidence.json.tmp.${Date.now()}.${process.pid}`);
4902
4021
  try {
4903
4022
  await bunWrite(tempPath, bundleJson);
4904
- await fs8.rename(tempPath, evidencePath);
4023
+ await fs7.rename(tempPath, evidencePath);
4905
4024
  invalidateCachedArtifact(evidencePath);
4906
4025
  } catch (writeError) {
4907
4026
  try {
@@ -4944,7 +4063,7 @@ async function listEvidenceTaskIds(directory) {
4944
4063
  }
4945
4064
  const taskIds = [];
4946
4065
  for (const entry of entries) {
4947
- const entryPath = path10.join(evidenceBasePath, entry);
4066
+ const entryPath = path7.join(evidenceBasePath, entry);
4948
4067
  try {
4949
4068
  const stats = statSync2(entryPath);
4950
4069
  if (!stats.isDirectory()) {
@@ -4967,7 +4086,7 @@ async function deleteEvidence(directory, taskId) {
4967
4086
  } catch {
4968
4087
  return false;
4969
4088
  }
4970
- const relativePath = path10.join("evidence", sanitizedTaskId);
4089
+ const relativePath = path7.join("evidence", sanitizedTaskId);
4971
4090
  const evidenceDir = validateSwarmPath(directory, relativePath);
4972
4091
  try {
4973
4092
  statSync2(evidenceDir);
@@ -4983,18 +4102,18 @@ async function deleteEvidence(directory, taskId) {
4983
4102
  }
4984
4103
  }
4985
4104
  async function checkRequirementCoverage(phase, directory) {
4986
- const relativePath = path10.join("evidence", `req-coverage-phase-${phase}.json`);
4987
- const absolutePath = path10.resolve(directory, ".swarm", relativePath);
4105
+ const relativePath = path7.join("evidence", `req-coverage-phase-${phase}.json`);
4106
+ const absolutePath = path7.resolve(directory, ".swarm", relativePath);
4988
4107
  try {
4989
- await fs8.access(absolutePath);
4108
+ await fs7.access(absolutePath);
4990
4109
  return { exists: true, path: absolutePath };
4991
4110
  } catch {
4992
4111
  return { exists: false, path: absolutePath };
4993
4112
  }
4994
4113
  }
4995
4114
  async function archiveEvidence(directory, maxAgeDays, maxBundles, options) {
4996
- const taskIds = await _internals12.listEvidenceTaskIds(directory);
4997
- const cutoffDate = options?.now ? new Date(options.now) : _internals12.now();
4115
+ const taskIds = await _internals8.listEvidenceTaskIds(directory);
4116
+ const cutoffDate = options?.now ? new Date(options.now) : _internals8.now();
4998
4117
  cutoffDate.setDate(cutoffDate.getDate() - maxAgeDays);
4999
4118
  const cutoffIso = cutoffDate.toISOString();
5000
4119
  const selected = new Set;
@@ -5006,7 +4125,7 @@ async function archiveEvidence(directory, maxAgeDays, maxBundles, options) {
5006
4125
  for (const taskId of taskIds) {
5007
4126
  let result;
5008
4127
  try {
5009
- result = await _internals12.loadEvidence(directory, taskId);
4128
+ result = await _internals8.loadEvidence(directory, taskId);
5010
4129
  } catch {
5011
4130
  warn("archive: skipping corrupt or unreadable evidence for task", taskId);
5012
4131
  continue;
@@ -5034,7 +4153,7 @@ async function archiveEvidence(directory, maxAgeDays, maxBundles, options) {
5034
4153
  }
5035
4154
  if (!options?.dryRun) {
5036
4155
  for (const taskId of [...selected].sort()) {
5037
- const deleted = await _internals12.deleteEvidence(directory, taskId);
4156
+ const deleted = await _internals8.deleteEvidence(directory, taskId);
5038
4157
  if (deleted)
5039
4158
  archived.push(taskId);
5040
4159
  else
@@ -5060,7 +4179,7 @@ async function archiveEvidence(directory, maxAgeDays, maxBundles, options) {
5060
4179
  };
5061
4180
  if (typeof options?.cacheMaxBytes === "number" && options.cacheMaxBytes > 0 || typeof options?.cacheMaxRecords === "number" && options.cacheMaxRecords > 0) {
5062
4181
  try {
5063
- documentsCache = await _internals12.pruneEvidenceDocuments({
4182
+ documentsCache = await _internals8.pruneEvidenceDocuments({
5064
4183
  directory,
5065
4184
  maxBytes: options?.cacheMaxBytes,
5066
4185
  maxRecords: options?.cacheMaxRecords,
@@ -5088,7 +4207,7 @@ async function archiveEvidence(directory, maxAgeDays, maxBundles, options) {
5088
4207
  function validateEvidence(evidence) {
5089
4208
  return EvidenceSchema.parse(evidence);
5090
4209
  }
5091
- var _internals12 = {
4210
+ var _internals8 = {
5092
4211
  wrapFlatRetrospective,
5093
4212
  loadEvidence,
5094
4213
  listEvidenceTaskIds,
@@ -5212,4 +4331,4 @@ function mergeDurableGateEntriesFromEvidence(taskId, entries, evidence) {
5212
4331
  return merged;
5213
4332
  }
5214
4333
 
5215
- export { projectDbExists, getProjectDb, closeProjectDb, normalizePath, buildTaskCompletionDescriptor, ensureTaskCheckpointReceipt, updateTaskCheckpointReceipt, isValidEnvKey, getExecutor, init_executor, MAX_TRANSIENT_RETRIES, isTransientSpawnError, transientBackoff, getGitRepositoryStatus, isGitRepo, getDefaultBaseBranch, detectDefaultRemoteBranch, resetToRemoteBranch, resetToMainAfterMerge, containsPathTraversal, containsControlChars, validateSymlinkBoundary, isStateUnreadable, loadEpicSessionState, isEpicModeActive, enableEpicMode, disableEpicMode, pathsConflict, isGlobalFile, isProtectedPath, readTaskScopes, loadPlanJsonOnly, loadPlan, savePlan, closePlanTerminalState, updateTaskStatus, derivePlanMarkdown, isValidEvidenceType, sanitizeTaskId2 as sanitizeTaskId, validateProjectRoot, saveEvidence, loadEvidence, listEvidenceTaskIds, checkRequirementCoverage, archiveEvidence, readDurableGateEvidence, getDurableGateEvidenceStatus, getDurableGateEvidenceStatusForTask, mergeDurableGateEntriesFromEvidence };
4334
+ export { projectDbExists, getProjectDb, closeProjectDb, normalizePath, buildTaskCompletionDescriptor, ensureTaskCheckpointReceipt, updateTaskCheckpointReceipt, MAX_TRANSIENT_RETRIES, isTransientSpawnError, transientBackoff, getGitRepositoryStatus, isGitRepo, getDefaultBaseBranch, detectDefaultRemoteBranch, resetToRemoteBranch, resetToMainAfterMerge, containsPathTraversal, containsControlChars, validateSymlinkBoundary, isStateUnreadable, loadEpicSessionState, isEpicModeActive, enableEpicMode, disableEpicMode, pathsConflict, isGlobalFile, isProtectedPath, readTaskScopes, loadPlanJsonOnly, loadPlan, savePlan, closePlanTerminalState, updateTaskStatus, derivePlanMarkdown, isValidEvidenceType, sanitizeTaskId2 as sanitizeTaskId, validateProjectRoot, saveEvidence, loadEvidence, listEvidenceTaskIds, checkRequirementCoverage, archiveEvidence, readDurableGateEvidence, getDurableGateEvidenceStatus, getDurableGateEvidenceStatusForTask, mergeDurableGateEntriesFromEvidence };