opencode-swarm 7.49.1 → 7.50.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -69,7 +69,7 @@ var package_default;
69
69
  var init_package = __esm(() => {
70
70
  package_default = {
71
71
  name: "opencode-swarm",
72
- version: "7.49.1",
72
+ version: "7.50.1",
73
73
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
74
74
  main: "dist/index.js",
75
75
  types: "dist/index.d.ts",
@@ -679,6 +679,10 @@ var init_tool_metadata = __esm(() => {
679
679
  lean_turbo_status: {
680
680
  description: "returns Lean Turbo configuration and active status for the current session",
681
681
  agents: ["architect"]
682
+ },
683
+ apply_patch: {
684
+ description: "Apply a unified diff patch to workspace files with exact context matching, atomic writes, and path validation",
685
+ agents: ["coder"]
682
686
  }
683
687
  };
684
688
  TOOL_NAMES = Object.keys(TOOL_METADATA);
@@ -75780,10 +75784,33 @@ function classifyAndCluster(testResults, history) {
75780
75784
  }
75781
75785
 
75782
75786
  // src/test-impact/flaky-detector.ts
75787
+ function computeCombinedFlakyScore(recent) {
75788
+ const totalRuns = recent.length;
75789
+ if (totalRuns < 2) {
75790
+ return { alternationCount: 0, flakyScore: 0 };
75791
+ }
75792
+ let alternationCount = 0;
75793
+ let passCount = 0;
75794
+ for (let i2 = 0;i2 < recent.length; i2++) {
75795
+ if (recent[i2].result === "pass") {
75796
+ passCount++;
75797
+ }
75798
+ if (i2 > 0 && recent[i2].result !== recent[i2 - 1].result) {
75799
+ alternationCount++;
75800
+ }
75801
+ }
75802
+ const alternationScore = alternationCount / totalRuns;
75803
+ const passRate = passCount / totalRuns;
75804
+ const passRateVarianceScore = 4 * passRate * (1 - passRate);
75805
+ return {
75806
+ alternationCount,
75807
+ flakyScore: (alternationScore + passRateVarianceScore) / 2
75808
+ };
75809
+ }
75783
75810
  function detectFlakyTests(allHistory) {
75784
75811
  const grouped = new Map;
75785
75812
  for (const record3 of allHistory) {
75786
- const key = `${record3.testFile.toLowerCase()}|${record3.testName.toLowerCase()}`;
75813
+ const key = `${record3.testFile.toLowerCase()}\x00${record3.testName.toLowerCase()}`;
75787
75814
  if (!grouped.has(key)) {
75788
75815
  grouped.set(key, {
75789
75816
  records: [],
@@ -75805,13 +75832,7 @@ function detectFlakyTests(allHistory) {
75805
75832
  if (totalRuns < 2) {
75806
75833
  continue;
75807
75834
  }
75808
- let alternationCount = 0;
75809
- for (let i2 = 1;i2 < recent.length; i2++) {
75810
- if (recent[i2].result !== recent[i2 - 1].result) {
75811
- alternationCount++;
75812
- }
75813
- }
75814
- const flakyScore = totalRuns >= 2 ? alternationCount / totalRuns : 0;
75835
+ const { alternationCount, flakyScore } = computeCombinedFlakyScore(recent);
75815
75836
  const isQuarantined = flakyScore > FLAKY_THRESHOLD && totalRuns >= MIN_RUNS_FOR_QUARANTINE;
75816
75837
  const recentResults = recent.map((r) => r.result);
75817
75838
  const testFile = entry.originalFile;
@@ -92314,7 +92335,7 @@ __export(exports_design_doc_drift, {
92314
92335
  _internals: () => _internals60
92315
92336
  });
92316
92337
  import * as fs98 from "node:fs";
92317
- import * as path136 from "node:path";
92338
+ import * as path137 from "node:path";
92318
92339
  function mtimeMsOrNull(absPath) {
92319
92340
  try {
92320
92341
  return fs98.statSync(absPath).mtimeMs;
@@ -92325,35 +92346,35 @@ function mtimeMsOrNull(absPath) {
92325
92346
  function resolveAnchorWithin(directory, anchor) {
92326
92347
  if (!anchor || typeof anchor !== "string")
92327
92348
  return null;
92328
- const root = path136.resolve(directory);
92329
- const resolved = path136.resolve(root, anchor);
92330
- const rel = path136.relative(root, resolved);
92331
- if (rel.startsWith("..") || path136.isAbsolute(rel))
92349
+ const root = path137.resolve(directory);
92350
+ const resolved = path137.resolve(root, anchor);
92351
+ const rel = path137.relative(root, resolved);
92352
+ if (rel.startsWith("..") || path137.isAbsolute(rel))
92332
92353
  return null;
92333
92354
  return resolved;
92334
92355
  }
92335
92356
  async function runDesignDocDriftCheck(directory, phase, outDir) {
92336
92357
  try {
92337
- const root = path136.resolve(directory);
92338
- const outAbs = path136.resolve(root, outDir);
92339
- const outRel = path136.relative(root, outAbs);
92340
- if (outRel.startsWith("..") || path136.isAbsolute(outRel)) {
92358
+ const root = path137.resolve(directory);
92359
+ const outAbs = path137.resolve(root, outDir);
92360
+ const outRel = path137.relative(root, outAbs);
92361
+ if (outRel.startsWith("..") || path137.isAbsolute(outRel)) {
92341
92362
  return null;
92342
92363
  }
92343
92364
  const docMtimes = new Map;
92344
92365
  const checkedDocs = [];
92345
92366
  const missingDocs = [];
92346
92367
  for (const [docName, relFile] of Object.entries(DESIGN_DOC_FILES)) {
92347
- const abs = path136.join(outAbs, relFile);
92368
+ const abs = path137.join(outAbs, relFile);
92348
92369
  const mtime = mtimeMsOrNull(abs);
92349
92370
  docMtimes.set(docName, mtime);
92350
92371
  if (mtime === null) {
92351
- missingDocs.push(path136.join(outDir, relFile));
92372
+ missingDocs.push(path137.join(outDir, relFile));
92352
92373
  } else {
92353
- checkedDocs.push(path136.join(outDir, relFile));
92374
+ checkedDocs.push(path137.join(outDir, relFile));
92354
92375
  }
92355
92376
  }
92356
- const traceabilityAbs = path136.join(outAbs, TRACEABILITY_REL);
92377
+ const traceabilityAbs = path137.join(outAbs, TRACEABILITY_REL);
92357
92378
  let registry3 = null;
92358
92379
  try {
92359
92380
  const stat9 = await fs98.promises.stat(traceabilityAbs);
@@ -92366,7 +92387,7 @@ async function runDesignDocDriftCheck(directory, phase, outDir) {
92366
92387
  registry3 = null;
92367
92388
  }
92368
92389
  const noDocs = checkedDocs.length === 0 || registry3 === null;
92369
- const specMtime = mtimeMsOrNull(path136.join(root, ".swarm", "spec.md"));
92390
+ const specMtime = mtimeMsOrNull(path137.join(root, ".swarm", "spec.md"));
92370
92391
  const staleSections = [];
92371
92392
  if (!noDocs && Array.isArray(registry3?.sections)) {
92372
92393
  for (const section of registry3.sections) {
@@ -92422,7 +92443,7 @@ async function runDesignDocDriftCheck(directory, phase, outDir) {
92422
92443
  };
92423
92444
  const filename = `${DOC_DRIFT_REPORT_PREFIX}${phase}.json`;
92424
92445
  const filePath = validateSwarmPath(directory, filename);
92425
- await fs98.promises.mkdir(path136.dirname(filePath), { recursive: true });
92446
+ await fs98.promises.mkdir(path137.dirname(filePath), { recursive: true });
92426
92447
  await fs98.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
92427
92448
  getGlobalEventBus().publish("curator.docdrift.completed", {
92428
92449
  phase,
@@ -92453,10 +92474,10 @@ var init_design_doc_drift = __esm(() => {
92453
92474
  domain: "domain.md",
92454
92475
  "technical-spec": "technical-spec.md",
92455
92476
  "behavior-spec": "behavior-spec.md",
92456
- "reference-impl": path136.join("reference", "reference-impl.md"),
92457
- "idiom-notes": path136.join("reference", "idiom-notes.md")
92477
+ "reference-impl": path137.join("reference", "reference-impl.md"),
92478
+ "idiom-notes": path137.join("reference", "idiom-notes.md")
92458
92479
  };
92459
- TRACEABILITY_REL = path136.join("reference", "traceability.json");
92480
+ TRACEABILITY_REL = path137.join("reference", "traceability.json");
92460
92481
  _internals60 = {
92461
92482
  mtimeMsOrNull,
92462
92483
  resolveAnchorWithin,
@@ -92472,7 +92493,7 @@ __export(exports_project_context, {
92472
92493
  LANG_BACKEND_DETECTION_TIMEOUT_MS: () => LANG_BACKEND_DETECTION_TIMEOUT_MS
92473
92494
  });
92474
92495
  import * as fs122 from "node:fs";
92475
- import * as path165 from "node:path";
92496
+ import * as path166 from "node:path";
92476
92497
  function detectFileExists2(directory, pattern) {
92477
92498
  if (pattern.includes("*") || pattern.includes("?")) {
92478
92499
  try {
@@ -92484,7 +92505,7 @@ function detectFileExists2(directory, pattern) {
92484
92505
  }
92485
92506
  }
92486
92507
  try {
92487
- fs122.accessSync(path165.join(directory, pattern));
92508
+ fs122.accessSync(path166.join(directory, pattern));
92488
92509
  return true;
92489
92510
  } catch {
92490
92511
  return false;
@@ -92493,7 +92514,7 @@ function detectFileExists2(directory, pattern) {
92493
92514
  function selectTestCommandFromScriptsTest(backend, directory) {
92494
92515
  let pkgRaw;
92495
92516
  try {
92496
- pkgRaw = fs122.readFileSync(path165.join(directory, "package.json"), "utf-8");
92517
+ pkgRaw = fs122.readFileSync(path166.join(directory, "package.json"), "utf-8");
92497
92518
  } catch {
92498
92519
  return null;
92499
92520
  }
@@ -92602,7 +92623,7 @@ var init_project_context = __esm(() => {
92602
92623
  init_package();
92603
92624
  init_agents2();
92604
92625
  init_critic();
92605
- import * as path166 from "node:path";
92626
+ import * as path167 from "node:path";
92606
92627
 
92607
92628
  // src/background/index.ts
92608
92629
  init_event_bus();
@@ -103467,29 +103488,34 @@ function createScopeGuardHook(config3, directory, injectAdvisory) {
103467
103488
  if (!declaredScope || declaredScope.length === 0)
103468
103489
  return;
103469
103490
  const argsObj = output.args;
103470
- const rawFilePath = argsObj?.path ?? argsObj?.filePath ?? argsObj?.file;
103471
- if (typeof rawFilePath !== "string" || !rawFilePath)
103472
- return;
103473
- const filePath = rawFilePath.replace(/[\r\n\t]/g, "_").split(String.fromCharCode(27)).join("_").replace(/\[[\d;]*m/g, "");
103474
- if (!isFileInScope(filePath, declaredScope, directory)) {
103475
- const taskId2 = session?.currentTaskId ?? "unknown";
103476
- const violationMessage = `SCOPE VIOLATION: ${agentName} attempted to modify '${filePath}' which is not in declared scope for task ${taskId2}. Declared scope: [${declaredScope.slice(0, 3).join(", ")}${declaredScope.length > 3 ? "..." : ""}]`;
103477
- if (session) {
103478
- session.lastScopeViolation = violationMessage;
103479
- session.scopeViolationDetected = true;
103480
- }
103481
- if (injectAdvisory) {
103482
- for (const [archSessionId, archSession] of swarmState.agentSessions) {
103483
- const archAgent = swarmState.activeAgent.get(archSessionId) ?? archSession.agentName;
103484
- if (stripKnownSwarmPrefix(archAgent) === ORCHESTRATOR_NAME) {
103485
- try {
103486
- injectAdvisory(archSessionId, `[SCOPE GUARD] ${violationMessage}`);
103487
- } catch {}
103488
- break;
103491
+ const candidatePaths = [];
103492
+ const singlePathKeys = ["path", "filePath", "file"];
103493
+ for (const key of singlePathKeys) {
103494
+ const val = argsObj?.[key];
103495
+ if (typeof val === "string" && val) {
103496
+ candidatePaths.push(val);
103497
+ }
103498
+ }
103499
+ let hasArrayKeys = false;
103500
+ const arrayPathKeys = ["files", "paths", "targetFiles"];
103501
+ for (const key of arrayPathKeys) {
103502
+ const val = argsObj?.[key];
103503
+ if (Array.isArray(val)) {
103504
+ hasArrayKeys = true;
103505
+ for (const item of val) {
103506
+ if (typeof item === "string" && item) {
103507
+ candidatePaths.push(item);
103489
103508
  }
103490
103509
  }
103491
103510
  }
103492
- throw new Error(violationMessage);
103511
+ }
103512
+ if (candidatePaths.length === 0 && !hasArrayKeys)
103513
+ return;
103514
+ for (const rawPath of candidatePaths) {
103515
+ const filePath = sanitizePath(rawPath);
103516
+ if (!isFileInScope(filePath, declaredScope, directory)) {
103517
+ reportScopeViolation(agentName, filePath, taskId, session, injectAdvisory, swarmState, declaredScope);
103518
+ }
103493
103519
  }
103494
103520
  }
103495
103521
  };
@@ -103497,7 +103523,7 @@ function createScopeGuardHook(config3, directory, injectAdvisory) {
103497
103523
  function isFileInScope(filePath, scopeEntries, directory) {
103498
103524
  const dir = directory ?? process.cwd();
103499
103525
  const resolvedFile = path102.resolve(dir, filePath);
103500
- return scopeEntries.some((scope) => {
103526
+ return scopeEntries.filter((scope) => scope.length > 0).some((scope) => {
103501
103527
  const resolvedScope = path102.resolve(dir, scope);
103502
103528
  if (resolvedFile === resolvedScope)
103503
103529
  return true;
@@ -103505,6 +103531,38 @@ function isFileInScope(filePath, scopeEntries, directory) {
103505
103531
  return rel.length > 0 && !rel.startsWith("..") && !path102.isAbsolute(rel);
103506
103532
  });
103507
103533
  }
103534
+ function sanitizePath(raw) {
103535
+ let result = "";
103536
+ for (let i2 = 0;i2 < raw.length; i2++) {
103537
+ const c = raw.charCodeAt(i2);
103538
+ if (c <= 31 || c === 127 || c >= 128 && c <= 159) {
103539
+ result += "_";
103540
+ continue;
103541
+ }
103542
+ result += raw[i2];
103543
+ }
103544
+ return result.replace(/\[[\d;]*m/g, "");
103545
+ }
103546
+ function reportScopeViolation(agentName, filePath, taskId, session, injectAdvisory, state, scopeEntries) {
103547
+ const taskLabel = taskId ?? "unknown";
103548
+ const violationMessage = `SCOPE VIOLATION: ${agentName} attempted to modify '${filePath}' which is not in declared scope for task ${taskLabel}. Declared scope: [${scopeEntries.slice(0, 3).join(", ")}${scopeEntries.length > 3 ? "..." : ""}]`;
103549
+ if (session) {
103550
+ session.lastScopeViolation = violationMessage;
103551
+ session.scopeViolationDetected = true;
103552
+ }
103553
+ if (injectAdvisory) {
103554
+ for (const [archSessionId, archSession] of state.agentSessions) {
103555
+ const archAgent = state.activeAgent.get(archSessionId) ?? archSession.agentName;
103556
+ if (stripKnownSwarmPrefix(archAgent) === ORCHESTRATOR_NAME) {
103557
+ try {
103558
+ injectAdvisory(archSessionId, `[SCOPE GUARD] ${violationMessage}`);
103559
+ } catch {}
103560
+ break;
103561
+ }
103562
+ }
103563
+ }
103564
+ throw new Error(violationMessage);
103565
+ }
103508
103566
 
103509
103567
  // src/hooks/self-review.ts
103510
103568
  init_constants();
@@ -105997,20 +106055,836 @@ init_snapshot_writer();
105997
106055
  init_state();
105998
106056
  init_telemetry();
105999
106057
 
106058
+ // src/tools/apply-patch.ts
106059
+ init_zod();
106060
+ init_path_security();
106061
+ init_create_tool();
106062
+ import {
106063
+ existsSync as existsSync58,
106064
+ mkdirSync as mkdirSync27,
106065
+ mkdtempSync as mkdtempSync2,
106066
+ readFileSync as readFileSync39,
106067
+ realpathSync as realpathSync13,
106068
+ renameSync as renameSync20,
106069
+ rmdirSync,
106070
+ unlinkSync as unlinkSync17,
106071
+ writeFileSync as writeFileSync20
106072
+ } from "node:fs";
106073
+ import * as path109 from "node:path";
106074
+ var WINDOWS_RESERVED_NAMES2 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
106075
+ var MAX_PATCH_SIZE = 500000;
106076
+ function containsWindowsAttacks2(filePath) {
106077
+ if (/:[^\\/]/.test(filePath))
106078
+ return true;
106079
+ const parts2 = filePath.split(/[/\\]/);
106080
+ for (const part of parts2) {
106081
+ if (WINDOWS_RESERVED_NAMES2.test(part))
106082
+ return true;
106083
+ }
106084
+ return false;
106085
+ }
106086
+ function isProtectedPath2(filePath) {
106087
+ const normalized = filePath.replace(/\\/g, "/");
106088
+ const segments = normalized.split("/");
106089
+ return segments.some((seg) => seg === ".git" || seg === ".swarm");
106090
+ }
106091
+ function containsStrictControlChars(str) {
106092
+ for (let i2 = 0;i2 < str.length; i2++) {
106093
+ const c = str.charCodeAt(i2);
106094
+ if (c <= 31 && c !== 9 && c !== 10 && c !== 13)
106095
+ return true;
106096
+ }
106097
+ return false;
106098
+ }
106099
+ function isCanonicalProtectedPath(targetPath, workspace) {
106100
+ try {
106101
+ const canonicalTarget = realpathSync13(targetPath);
106102
+ const canonicalWorkspace = realpathSync13(workspace);
106103
+ const relative21 = path109.relative(canonicalWorkspace, canonicalTarget).replace(/\\/g, "/");
106104
+ const segments = relative21.split("/").filter(Boolean);
106105
+ return segments.some((seg) => seg === ".git" || seg === ".swarm");
106106
+ } catch {
106107
+ const parentDir = path109.dirname(targetPath);
106108
+ if (parentDir === targetPath)
106109
+ return false;
106110
+ try {
106111
+ const canonicalParent = realpathSync13(parentDir);
106112
+ const canonicalWorkspace = realpathSync13(workspace);
106113
+ const relative21 = path109.relative(canonicalWorkspace, canonicalParent).replace(/\\/g, "/");
106114
+ const segments = relative21.split("/").filter(Boolean);
106115
+ return segments.some((seg) => seg === ".git" || seg === ".swarm");
106116
+ } catch {
106117
+ return false;
106118
+ }
106119
+ }
106120
+ }
106121
+ function isCanonicalPathWithinWorkspace(targetPath, workspaceRoot) {
106122
+ try {
106123
+ const canonicalTarget = realpathSync13(targetPath);
106124
+ const canonicalWorkspace = realpathSync13(workspaceRoot);
106125
+ const relative21 = path109.relative(canonicalWorkspace, canonicalTarget);
106126
+ if (relative21.startsWith("..") || path109.isAbsolute(relative21))
106127
+ return false;
106128
+ const segments = relative21.replace(/\\/g, "/").split("/").filter(Boolean);
106129
+ if (segments.some((seg) => seg === ".git" || seg === ".swarm"))
106130
+ return false;
106131
+ return true;
106132
+ } catch {
106133
+ const parentDir = path109.dirname(targetPath);
106134
+ if (parentDir === targetPath) {
106135
+ return false;
106136
+ }
106137
+ try {
106138
+ const canonicalParent = realpathSync13(parentDir);
106139
+ const canonicalWorkspace = realpathSync13(workspaceRoot);
106140
+ const relative21 = path109.relative(canonicalWorkspace, canonicalParent);
106141
+ if (relative21.startsWith("..") || path109.isAbsolute(relative21))
106142
+ return false;
106143
+ const segments = relative21.replace(/\\/g, "/").split("/").filter(Boolean);
106144
+ if (segments.some((seg) => seg === ".git" || seg === ".swarm"))
106145
+ return false;
106146
+ return true;
106147
+ } catch {
106148
+ return false;
106149
+ }
106150
+ }
106151
+ }
106152
+ function validatePatchTargetPath(filePath, workspace) {
106153
+ if (!filePath || filePath.trim() === "") {
106154
+ return "Empty file path";
106155
+ }
106156
+ if (path109.isAbsolute(filePath) || /^[A-Za-z]:[/\\]/.test(filePath)) {
106157
+ return `Absolute path rejected: ${filePath}`;
106158
+ }
106159
+ if (containsPathTraversal(filePath)) {
106160
+ return `Path traversal detected: ${filePath}`;
106161
+ }
106162
+ if (containsStrictControlChars(filePath)) {
106163
+ return `Control characters detected in path: ${filePath}`;
106164
+ }
106165
+ if (containsControlChars(filePath)) {
106166
+ return `Control characters detected in path: ${filePath}`;
106167
+ }
106168
+ if (containsWindowsAttacks2(filePath)) {
106169
+ return `Windows reserved name or invalid path: ${filePath}`;
106170
+ }
106171
+ if (isProtectedPath2(filePath)) {
106172
+ return `Protected directory target rejected: ${filePath}`;
106173
+ }
106174
+ const resolved = path109.resolve(workspace, filePath);
106175
+ const relative21 = path109.relative(workspace, resolved);
106176
+ if (relative21.startsWith("..") || path109.isAbsolute(relative21)) {
106177
+ return `Path escapes workspace: ${filePath}`;
106178
+ }
106179
+ if (!isCanonicalPathWithinWorkspace(resolved, workspace)) {
106180
+ return `Path escapes workspace via symlink/junction: ${filePath}`;
106181
+ }
106182
+ return null;
106183
+ }
106184
+ function extractHeaderPath(header, prefix) {
106185
+ const trimmed = header.trim();
106186
+ if (!trimmed.startsWith(prefix))
106187
+ return null;
106188
+ const rest = trimmed.slice(prefix.length).trim();
106189
+ if (rest === "/dev/null")
106190
+ return "/dev/null";
106191
+ if (rest.startsWith("a/") || rest.startsWith("b/")) {
106192
+ const stripped = rest.slice(2);
106193
+ if (stripped.length === 0)
106194
+ return null;
106195
+ return stripped;
106196
+ }
106197
+ return rest.length > 0 ? rest : null;
106198
+ }
106199
+ function parseHunkHeader(line) {
106200
+ const match = line.match(/^@@\s*-(\d+)(?:,(\d+))?\s*\+(\d+)(?:,(\d+))?\s*@@/);
106201
+ if (!match)
106202
+ return null;
106203
+ return {
106204
+ oldStart: parseInt(match[1], 10),
106205
+ oldCount: match[2] !== undefined ? parseInt(match[2], 10) : 1,
106206
+ newStart: parseInt(match[3], 10),
106207
+ newCount: match[4] !== undefined ? parseInt(match[4], 10) : 1
106208
+ };
106209
+ }
106210
+ function parseUnifiedDiff(patchText) {
106211
+ if (patchText.length > MAX_PATCH_SIZE) {
106212
+ return {
106213
+ files: [],
106214
+ error: `Patch exceeds maximum size of ${MAX_PATCH_SIZE} characters`
106215
+ };
106216
+ }
106217
+ if (patchText.includes("\x00")) {
106218
+ return {
106219
+ files: [],
106220
+ error: "Binary content detected (null byte) — binary patches are not supported (FR-013)"
106221
+ };
106222
+ }
106223
+ const normalized = patchText.replace(/\r\n/g, `
106224
+ `).replace(/\r/g, `
106225
+ `);
106226
+ let lines = normalized.split(`
106227
+ `);
106228
+ if (lines.length > 0 && lines[lines.length - 1] === "") {
106229
+ lines = lines.slice(0, -1);
106230
+ }
106231
+ for (const line of lines) {
106232
+ if (line === "GIT binary patch" || line.startsWith("Binary files ")) {
106233
+ return { files: [], error: "Binary patches are not supported (FR-013)" };
106234
+ }
106235
+ if (line.startsWith("rename from") || line.startsWith("rename to") || line.startsWith("copy from") || line.startsWith("copy to")) {
106236
+ return {
106237
+ files: [],
106238
+ error: "Rename/copy patches are not supported (FR-013)"
106239
+ };
106240
+ }
106241
+ }
106242
+ const fileDiffs = [];
106243
+ let i2 = 0;
106244
+ while (i2 < lines.length) {
106245
+ let oldHeaderPath = null;
106246
+ let newHeaderPath = null;
106247
+ if (lines[i2].startsWith("diff --git ")) {
106248
+ i2++;
106249
+ while (i2 < lines.length && (lines[i2].startsWith("index ") || lines[i2].startsWith("old mode ") || lines[i2].startsWith("new mode ") || lines[i2].startsWith("deleted file ") || lines[i2].startsWith("new file ") || lines[i2].startsWith("similarity index ") || lines[i2].startsWith("dissimilarity index "))) {
106250
+ i2++;
106251
+ }
106252
+ }
106253
+ if (i2 < lines.length && lines[i2].startsWith("--- ")) {
106254
+ oldHeaderPath = extractHeaderPath(lines[i2], "--- ");
106255
+ i2++;
106256
+ } else if (oldHeaderPath === null) {
106257
+ i2++;
106258
+ continue;
106259
+ }
106260
+ if (i2 < lines.length && lines[i2].startsWith("+++ ")) {
106261
+ newHeaderPath = extractHeaderPath(lines[i2], "+++ ");
106262
+ i2++;
106263
+ } else {
106264
+ continue;
106265
+ }
106266
+ if (oldHeaderPath === null || newHeaderPath === null) {
106267
+ continue;
106268
+ }
106269
+ const isNewFile = oldHeaderPath === "/dev/null";
106270
+ const isDelete = newHeaderPath === "/dev/null";
106271
+ const targetPath = isDelete ? oldHeaderPath : newHeaderPath;
106272
+ if (targetPath === "/dev/null") {
106273
+ continue;
106274
+ }
106275
+ const hunks = [];
106276
+ while (i2 < lines.length && lines[i2].startsWith("@@")) {
106277
+ const header = parseHunkHeader(lines[i2]);
106278
+ if (!header) {
106279
+ i2++;
106280
+ continue;
106281
+ }
106282
+ i2++;
106283
+ const hunkLines = [];
106284
+ while (i2 < lines.length) {
106285
+ const line = lines[i2];
106286
+ if (line.startsWith("@@") || line.startsWith("diff --git ") || line.startsWith("--- ") || line.startsWith("+++ ")) {
106287
+ break;
106288
+ }
106289
+ if (line.startsWith("\\")) {
106290
+ i2++;
106291
+ continue;
106292
+ }
106293
+ if (line.length === 0) {
106294
+ break;
106295
+ }
106296
+ const firstChar = line[0];
106297
+ if (firstChar !== " " && firstChar !== "+" && firstChar !== "-") {
106298
+ break;
106299
+ }
106300
+ if (firstChar === "+") {
106301
+ hunkLines.push({ type: "addition", content: line.slice(1) });
106302
+ } else if (firstChar === "-") {
106303
+ hunkLines.push({ type: "removal", content: line.slice(1) });
106304
+ } else {
106305
+ hunkLines.push({ type: "context", content: line.slice(1) });
106306
+ }
106307
+ i2++;
106308
+ }
106309
+ hunks.push({
106310
+ oldStart: header.oldStart,
106311
+ oldCount: header.oldCount,
106312
+ newStart: header.newStart,
106313
+ newCount: header.newCount,
106314
+ lines: hunkLines
106315
+ });
106316
+ }
106317
+ if (hunks.length > 0) {
106318
+ fileDiffs.push({
106319
+ oldPath: oldHeaderPath,
106320
+ newPath: newHeaderPath,
106321
+ isNewFile,
106322
+ isDelete,
106323
+ hunks
106324
+ });
106325
+ } else {
106326
+ fileDiffs.push({
106327
+ oldPath: oldHeaderPath,
106328
+ newPath: newHeaderPath,
106329
+ isNewFile,
106330
+ isDelete,
106331
+ hunks: []
106332
+ });
106333
+ }
106334
+ }
106335
+ return { files: fileDiffs, error: null };
106336
+ }
106337
+ function arraysEqual(a, b) {
106338
+ if (a.length !== b.length)
106339
+ return false;
106340
+ for (let idx = 0;idx < a.length; idx++) {
106341
+ if (a[idx] !== b[idx])
106342
+ return false;
106343
+ }
106344
+ return true;
106345
+ }
106346
+ function applyHunks(content, fileDiff) {
106347
+ const normalizedContent = content.replace(/\r\n/g, `
106348
+ `);
106349
+ const fileLines = normalizedContent.split(`
106350
+ `);
106351
+ if (fileDiff.isNewFile) {
106352
+ const newLines = [];
106353
+ for (const hunk of fileDiff.hunks) {
106354
+ for (const line of hunk.lines) {
106355
+ if (line.type === "addition" || line.type === "context") {
106356
+ newLines.push(line.content);
106357
+ }
106358
+ }
106359
+ }
106360
+ return { success: true, appliedLines: newLines };
106361
+ }
106362
+ if (fileDiff.isDelete) {
106363
+ return { success: true, appliedLines: [] };
106364
+ }
106365
+ let accumulatedDelta = 0;
106366
+ for (let hunkIdx = 0;hunkIdx < fileDiff.hunks.length; hunkIdx++) {
106367
+ const hunk = fileDiff.hunks[hunkIdx];
106368
+ const searchStart = Math.max(0, hunk.oldStart - 1 + accumulatedDelta);
106369
+ const expectedOldLines = [];
106370
+ const newLinesForHunk = [];
106371
+ for (const line of hunk.lines) {
106372
+ if (line.type === "context") {
106373
+ expectedOldLines.push(line.content);
106374
+ newLinesForHunk.push(line.content);
106375
+ } else if (line.type === "removal") {
106376
+ expectedOldLines.push(line.content);
106377
+ } else if (line.type === "addition") {
106378
+ newLinesForHunk.push(line.content);
106379
+ }
106380
+ }
106381
+ const exactOffset = searchStart;
106382
+ const matchFound = exactOffset <= fileLines.length - expectedOldLines.length && arraysEqual(fileLines.slice(exactOffset, exactOffset + expectedOldLines.length), expectedOldLines);
106383
+ if (matchFound) {
106384
+ fileLines.splice(exactOffset, expectedOldLines.length, ...newLinesForHunk);
106385
+ const delta = newLinesForHunk.length - expectedOldLines.length;
106386
+ accumulatedDelta += delta;
106387
+ }
106388
+ if (!matchFound) {
106389
+ const diagStart = Math.min(searchStart, fileLines.length);
106390
+ const diagEnd = Math.min(diagStart + expectedOldLines.length, fileLines.length);
106391
+ const actualContent = fileLines.slice(diagStart, diagEnd).join(`
106392
+ `);
106393
+ const expectedContent = expectedOldLines.join(`
106394
+ `);
106395
+ return {
106396
+ success: false,
106397
+ failedHunkIndex: hunkIdx,
106398
+ error: {
106399
+ hunkIndex: hunkIdx,
106400
+ type: "context-mismatch",
106401
+ message: `Context mismatch in hunk ${hunkIdx + 1} at line ${searchStart + 1}: expected context does not match file content`,
106402
+ expected: expectedContent.length > 200 ? `${expectedContent.slice(0, 200)}... (truncated)` : expectedContent,
106403
+ actual: actualContent.length > 200 ? `${actualContent.slice(0, 200)}... (truncated)` : actualContent,
106404
+ line: searchStart + 1
106405
+ }
106406
+ };
106407
+ }
106408
+ }
106409
+ return { success: true, appliedLines: fileLines };
106410
+ }
106411
+ function atomicWriteFileSync(targetPath, content) {
106412
+ const dir = path109.dirname(targetPath);
106413
+ mkdirSync27(dir, { recursive: true });
106414
+ const tempPrefix = `.apply-patch-${Date.now()}-${process.pid}`;
106415
+ let tempPath;
106416
+ try {
106417
+ const tempDir = realpathSync13(mkdtempSync2(path109.join(dir, tempPrefix)));
106418
+ tempPath = path109.join(tempDir, "content");
106419
+ } catch {
106420
+ tempPath = path109.join(dir, `${tempPrefix}.tmp`);
106421
+ }
106422
+ try {
106423
+ writeFileSync20(tempPath, content, "utf-8");
106424
+ renameSync20(tempPath, targetPath);
106425
+ } finally {
106426
+ if (existsSync58(tempPath)) {
106427
+ try {
106428
+ unlinkSync17(tempPath);
106429
+ } catch {}
106430
+ }
106431
+ const tempDir = path109.dirname(tempPath);
106432
+ if (tempDir !== dir && existsSync58(tempDir)) {
106433
+ try {
106434
+ rmdirSync(tempDir);
106435
+ } catch {}
106436
+ }
106437
+ }
106438
+ }
106439
+ function detectLineEnding(content) {
106440
+ return content.includes(`\r
106441
+ `) ? `\r
106442
+ ` : `
106443
+ `;
106444
+ }
106445
+ function ensureFinalNewline(content, originalEndsWithNewline) {
106446
+ if (originalEndsWithNewline && !content.endsWith(`
106447
+ `)) {
106448
+ return `${content}
106449
+ `;
106450
+ }
106451
+ if (!originalEndsWithNewline && content.endsWith(`
106452
+ `)) {
106453
+ return content.slice(0, -1);
106454
+ }
106455
+ return content;
106456
+ }
106457
+ function processFileDiff(fileDiff, targetPath, fullPath, workspace, dryRun, allowCreates, allowDeletes) {
106458
+ const hunksTotal = fileDiff.hunks.length;
106459
+ if (!isCanonicalPathWithinWorkspace(fullPath, workspace)) {
106460
+ return {
106461
+ file: targetPath,
106462
+ status: "error",
106463
+ hunks: hunksTotal,
106464
+ hunksApplied: 0,
106465
+ hunksFailed: hunksTotal,
106466
+ errors: [
106467
+ {
106468
+ hunkIndex: 0,
106469
+ type: "context-mismatch",
106470
+ message: `Path escapes workspace via symlink/junction: ${targetPath}`
106471
+ }
106472
+ ]
106473
+ };
106474
+ }
106475
+ if (isCanonicalProtectedPath(fullPath, workspace)) {
106476
+ return {
106477
+ file: targetPath,
106478
+ status: "error",
106479
+ hunks: hunksTotal,
106480
+ hunksApplied: 0,
106481
+ hunksFailed: hunksTotal,
106482
+ errors: [
106483
+ {
106484
+ hunkIndex: 0,
106485
+ type: "context-mismatch",
106486
+ message: `Protected directory target rejected via symlink: ${targetPath}`
106487
+ }
106488
+ ]
106489
+ };
106490
+ }
106491
+ if (fileDiff.isNewFile) {
106492
+ if (!allowCreates) {
106493
+ return {
106494
+ file: targetPath,
106495
+ status: "error",
106496
+ hunks: hunksTotal,
106497
+ hunksApplied: 0,
106498
+ hunksFailed: hunksTotal,
106499
+ errors: [
106500
+ {
106501
+ hunkIndex: 0,
106502
+ type: "create-not-allowed",
106503
+ message: `New file creation not allowed: ${targetPath} (set allowCreates to true)`
106504
+ }
106505
+ ]
106506
+ };
106507
+ }
106508
+ const parentDir = path109.dirname(fullPath);
106509
+ if (!existsSync58(parentDir)) {
106510
+ return {
106511
+ file: targetPath,
106512
+ status: "error",
106513
+ hunks: hunksTotal,
106514
+ hunksApplied: 0,
106515
+ hunksFailed: hunksTotal,
106516
+ errors: [
106517
+ {
106518
+ hunkIndex: 0,
106519
+ type: "file-not-found",
106520
+ message: `Parent directory does not exist: ${parentDir}`
106521
+ }
106522
+ ]
106523
+ };
106524
+ }
106525
+ if (existsSync58(fullPath)) {
106526
+ return {
106527
+ file: targetPath,
106528
+ status: "error",
106529
+ hunks: hunksTotal,
106530
+ hunksApplied: 0,
106531
+ hunksFailed: hunksTotal,
106532
+ errors: [
106533
+ {
106534
+ hunkIndex: 0,
106535
+ type: "file-not-found",
106536
+ message: `File already exists: ${targetPath} (cannot create — patch may be stale)`
106537
+ }
106538
+ ]
106539
+ };
106540
+ }
106541
+ if (hunksTotal === 0) {
106542
+ return {
106543
+ file: targetPath,
106544
+ status: "no-changes",
106545
+ hunks: 0,
106546
+ hunksApplied: 0,
106547
+ hunksFailed: 0
106548
+ };
106549
+ }
106550
+ const hunkResult2 = applyHunks("", fileDiff);
106551
+ if (!hunkResult2.success || !hunkResult2.appliedLines) {
106552
+ return {
106553
+ file: targetPath,
106554
+ status: "error",
106555
+ hunks: hunksTotal,
106556
+ hunksApplied: 0,
106557
+ hunksFailed: hunksTotal,
106558
+ errors: hunkResult2.error ? [hunkResult2.error] : []
106559
+ };
106560
+ }
106561
+ if (!dryRun) {
106562
+ const content2 = ensureFinalNewline(hunkResult2.appliedLines.join(`
106563
+ `), true);
106564
+ atomicWriteFileSync(fullPath, content2);
106565
+ }
106566
+ return {
106567
+ file: targetPath,
106568
+ status: "created",
106569
+ hunks: hunksTotal,
106570
+ hunksApplied: hunksTotal,
106571
+ hunksFailed: 0
106572
+ };
106573
+ }
106574
+ if (fileDiff.isDelete) {
106575
+ if (hunksTotal === 0) {
106576
+ return {
106577
+ file: targetPath,
106578
+ status: "no-changes",
106579
+ hunks: 0,
106580
+ hunksApplied: 0,
106581
+ hunksFailed: 0
106582
+ };
106583
+ }
106584
+ if (!allowDeletes) {
106585
+ return {
106586
+ file: targetPath,
106587
+ status: "error",
106588
+ hunks: hunksTotal,
106589
+ hunksApplied: 0,
106590
+ hunksFailed: hunksTotal,
106591
+ errors: [
106592
+ {
106593
+ hunkIndex: 0,
106594
+ type: "delete-not-allowed",
106595
+ message: `File deletion not allowed: ${targetPath} (set allowDeletes to true)`
106596
+ }
106597
+ ]
106598
+ };
106599
+ }
106600
+ if (!existsSync58(fullPath)) {
106601
+ return {
106602
+ file: targetPath,
106603
+ status: "error",
106604
+ hunks: hunksTotal,
106605
+ hunksApplied: 0,
106606
+ hunksFailed: hunksTotal,
106607
+ errors: [
106608
+ {
106609
+ hunkIndex: 0,
106610
+ type: "file-not-found",
106611
+ message: `File not found for deletion: ${targetPath}`
106612
+ }
106613
+ ]
106614
+ };
106615
+ }
106616
+ if (!dryRun) {
106617
+ try {
106618
+ unlinkSync17(fullPath);
106619
+ } catch (err2) {
106620
+ return {
106621
+ file: targetPath,
106622
+ status: "error",
106623
+ hunks: hunksTotal,
106624
+ hunksApplied: 0,
106625
+ hunksFailed: hunksTotal,
106626
+ errors: [
106627
+ {
106628
+ hunkIndex: 0,
106629
+ type: "file-not-found",
106630
+ message: `Failed to delete file: ${err2 instanceof Error ? err2.message : String(err2)}`
106631
+ }
106632
+ ]
106633
+ };
106634
+ }
106635
+ }
106636
+ return {
106637
+ file: targetPath,
106638
+ status: "applied",
106639
+ hunks: hunksTotal,
106640
+ hunksApplied: hunksTotal,
106641
+ hunksFailed: 0
106642
+ };
106643
+ }
106644
+ if (!existsSync58(fullPath)) {
106645
+ return {
106646
+ file: targetPath,
106647
+ status: "error",
106648
+ hunks: hunksTotal,
106649
+ hunksApplied: 0,
106650
+ hunksFailed: hunksTotal,
106651
+ errors: [
106652
+ {
106653
+ hunkIndex: 0,
106654
+ type: "file-not-found",
106655
+ message: `File not found: ${targetPath}`
106656
+ }
106657
+ ]
106658
+ };
106659
+ }
106660
+ let content;
106661
+ try {
106662
+ content = readFileSync39(fullPath, "utf-8");
106663
+ } catch (err2) {
106664
+ return {
106665
+ file: targetPath,
106666
+ status: "error",
106667
+ hunks: hunksTotal,
106668
+ hunksApplied: 0,
106669
+ hunksFailed: hunksTotal,
106670
+ errors: [
106671
+ {
106672
+ hunkIndex: 0,
106673
+ type: "file-not-found",
106674
+ message: `Could not read file: ${err2 instanceof Error ? err2.message : String(err2)}`
106675
+ }
106676
+ ]
106677
+ };
106678
+ }
106679
+ if (hunksTotal === 0) {
106680
+ return {
106681
+ file: targetPath,
106682
+ status: "no-changes",
106683
+ hunks: 0,
106684
+ hunksApplied: 0,
106685
+ hunksFailed: 0
106686
+ };
106687
+ }
106688
+ const originalEndsWithNewline = content.endsWith(`
106689
+ `);
106690
+ const originalLineEnding = detectLineEnding(content);
106691
+ const hunkResult = applyHunks(content, fileDiff);
106692
+ if (!hunkResult.success) {
106693
+ return {
106694
+ file: targetPath,
106695
+ status: "error",
106696
+ hunks: hunksTotal,
106697
+ hunksApplied: 0,
106698
+ hunksFailed: hunksTotal,
106699
+ errors: hunkResult.error ? [hunkResult.error] : []
106700
+ };
106701
+ }
106702
+ const resultContent = hunkResult.appliedLines.join(`
106703
+ `);
106704
+ if (resultContent === "" && !dryRun && !allowDeletes && content.length > 0) {
106705
+ return {
106706
+ file: targetPath,
106707
+ status: "error",
106708
+ hunks: hunksTotal,
106709
+ hunksApplied: hunksTotal,
106710
+ hunksFailed: 0,
106711
+ errors: [
106712
+ {
106713
+ hunkIndex: 0,
106714
+ type: "delete-not-allowed",
106715
+ message: `Patch would delete all content from ${targetPath}. Set allowDeletes to true to permit file deletion.`
106716
+ }
106717
+ ]
106718
+ };
106719
+ }
106720
+ let finalContent;
106721
+ if (resultContent === "") {
106722
+ finalContent = "";
106723
+ } else {
106724
+ const withLineEnding = originalLineEnding === `\r
106725
+ ` ? resultContent.replace(/\n/g, `\r
106726
+ `) : resultContent;
106727
+ finalContent = ensureFinalNewline(withLineEnding, originalEndsWithNewline);
106728
+ }
106729
+ if (finalContent === content) {
106730
+ return {
106731
+ file: targetPath,
106732
+ status: "no-changes",
106733
+ hunks: hunksTotal,
106734
+ hunksApplied: hunksTotal,
106735
+ hunksFailed: 0
106736
+ };
106737
+ }
106738
+ if (!dryRun) {
106739
+ atomicWriteFileSync(fullPath, finalContent);
106740
+ }
106741
+ return {
106742
+ file: targetPath,
106743
+ status: "applied",
106744
+ hunks: hunksTotal,
106745
+ hunksApplied: hunksTotal,
106746
+ hunksFailed: 0
106747
+ };
106748
+ }
106749
+ function buildErrorResult(message) {
106750
+ return {
106751
+ success: false,
106752
+ files: [
106753
+ {
106754
+ file: "",
106755
+ status: "error",
106756
+ hunks: 0,
106757
+ hunksApplied: 0,
106758
+ hunksFailed: 0,
106759
+ errors: [
106760
+ {
106761
+ hunkIndex: 0,
106762
+ type: "context-mismatch",
106763
+ message
106764
+ }
106765
+ ]
106766
+ }
106767
+ ],
106768
+ summary: {
106769
+ totalFiles: 0,
106770
+ applied: 0,
106771
+ failed: 1,
106772
+ totalHunks: 0
106773
+ }
106774
+ };
106775
+ }
106776
+ var applyPatch = createSwarmTool({
106777
+ description: "Apply a unified diff patch to workspace files. Validates paths, matches context exactly, and writes atomically. Coder-scoped write tool.",
106778
+ args: {
106779
+ patch: exports_external.string().min(1).describe("Unified diff text to parse and apply"),
106780
+ files: exports_external.array(exports_external.string()).min(1).describe("Array of target file paths the patch is expected to touch. Every parsed target must appear in this list."),
106781
+ dryRun: exports_external.boolean().optional().default(false).describe("Validate without writing files (default: false)"),
106782
+ allowCreates: exports_external.boolean().optional().default(false).describe("Allow creating new files from patches with --- /dev/null (default: false)"),
106783
+ allowDeletes: exports_external.boolean().optional().default(false).describe("Allow deleting files from patches with +++ /dev/null (default: false)")
106784
+ },
106785
+ execute: async (args2, directory) => {
106786
+ if (!args2 || typeof args2 !== "object") {
106787
+ return JSON.stringify(buildErrorResult("Could not parse apply_patch arguments"), null, 2);
106788
+ }
106789
+ const obj = args2;
106790
+ const patchText = obj.patch ?? "";
106791
+ const files = obj.files ?? [];
106792
+ const dryRun = obj.dryRun ?? false;
106793
+ const allowCreates = obj.allowCreates ?? false;
106794
+ const allowDeletes = obj.allowDeletes ?? false;
106795
+ if (!existsSync58(directory)) {
106796
+ return JSON.stringify(buildErrorResult("Workspace directory does not exist"), null, 2);
106797
+ }
106798
+ if (files.length === 0) {
106799
+ return JSON.stringify(buildErrorResult("files array cannot be empty"), null, 2);
106800
+ }
106801
+ if (!patchText || patchText.trim() === "") {
106802
+ return JSON.stringify(buildErrorResult("patch text cannot be empty"), null, 2);
106803
+ }
106804
+ for (const filePath of files) {
106805
+ const validationError = validatePatchTargetPath(filePath, directory);
106806
+ if (validationError) {
106807
+ return JSON.stringify(buildErrorResult(validationError), null, 2);
106808
+ }
106809
+ }
106810
+ const { files: parsedFiles, error: parseError } = parseUnifiedDiff(patchText);
106811
+ if (parseError) {
106812
+ return JSON.stringify(buildErrorResult(parseError), null, 2);
106813
+ }
106814
+ if (parsedFiles.length === 0) {
106815
+ return JSON.stringify({
106816
+ success: true,
106817
+ dryRun,
106818
+ files: [],
106819
+ summary: { totalFiles: 0, applied: 0, failed: 0, totalHunks: 0 }
106820
+ }, null, 2);
106821
+ }
106822
+ const declaredFileSet = new Set(files);
106823
+ const undeclaredTargets = [];
106824
+ for (const fileDiff of parsedFiles) {
106825
+ const targetPath = fileDiff.isDelete ? fileDiff.oldPath : fileDiff.newPath;
106826
+ if (targetPath && targetPath !== "/dev/null" && !declaredFileSet.has(targetPath)) {
106827
+ undeclaredTargets.push(targetPath);
106828
+ }
106829
+ }
106830
+ if (undeclaredTargets.length > 0) {
106831
+ return JSON.stringify(buildErrorResult(`Patch targets files not in the declared files array: ${undeclaredTargets.join(", ")}`), null, 2);
106832
+ }
106833
+ const parsedTargetSet = new Set(parsedFiles.map((fd) => fd.isDelete ? fd.oldPath : fd.newPath).filter(Boolean));
106834
+ const extraFiles = files.filter((f) => !parsedTargetSet.has(f));
106835
+ const fileResults = [];
106836
+ let totalApplied = 0;
106837
+ let totalFailed = 0;
106838
+ let totalHunks = 0;
106839
+ for (const fileDiff of parsedFiles) {
106840
+ const targetPath = fileDiff.isDelete ? fileDiff.oldPath : fileDiff.newPath;
106841
+ const fullPath = path109.resolve(directory, targetPath);
106842
+ totalHunks += fileDiff.hunks.length;
106843
+ const result = processFileDiff(fileDiff, targetPath, fullPath, directory, dryRun, allowCreates, allowDeletes);
106844
+ fileResults.push(result);
106845
+ if (result.status === "applied" || result.status === "created") {
106846
+ totalApplied++;
106847
+ } else if (result.status === "error") {
106848
+ totalFailed++;
106849
+ }
106850
+ }
106851
+ const output = {
106852
+ success: totalFailed === 0,
106853
+ dryRun,
106854
+ files: fileResults,
106855
+ summary: {
106856
+ totalFiles: fileResults.length,
106857
+ applied: totalApplied,
106858
+ failed: totalFailed,
106859
+ totalHunks
106860
+ }
106861
+ };
106862
+ if (extraFiles.length > 0) {
106863
+ return JSON.stringify({
106864
+ ...output,
106865
+ warnings: [
106866
+ `files[] contains entries not targeted by the patch: ${extraFiles.join(", ")}`
106867
+ ]
106868
+ }, null, 2);
106869
+ }
106870
+ return JSON.stringify(output, null, 2);
106871
+ }
106872
+ });
106873
+
106000
106874
  // src/tools/batch-symbols.ts
106001
106875
  init_dist();
106002
106876
  init_create_tool();
106003
106877
  import * as fs72 from "node:fs";
106004
- import * as path109 from "node:path";
106878
+ import * as path110 from "node:path";
106005
106879
  init_path_security();
106006
- var WINDOWS_RESERVED_NAMES2 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
106007
- function containsWindowsAttacks2(str) {
106880
+ var WINDOWS_RESERVED_NAMES3 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
106881
+ function containsWindowsAttacks3(str) {
106008
106882
  if (/:[^\\/]/.test(str)) {
106009
106883
  return true;
106010
106884
  }
106011
106885
  const parts2 = str.split(/[/\\]/);
106012
106886
  for (const part of parts2) {
106013
- if (WINDOWS_RESERVED_NAMES2.test(part)) {
106887
+ if (WINDOWS_RESERVED_NAMES3.test(part)) {
106014
106888
  return true;
106015
106889
  }
106016
106890
  }
@@ -106018,14 +106892,14 @@ function containsWindowsAttacks2(str) {
106018
106892
  }
106019
106893
  function isPathInWorkspace2(filePath, workspace) {
106020
106894
  try {
106021
- const resolvedPath = path109.resolve(workspace, filePath);
106895
+ const resolvedPath = path110.resolve(workspace, filePath);
106022
106896
  if (!fs72.existsSync(resolvedPath)) {
106023
106897
  return true;
106024
106898
  }
106025
106899
  const realWorkspace = fs72.realpathSync(workspace);
106026
106900
  const realResolvedPath = fs72.realpathSync(resolvedPath);
106027
- const relativePath = path109.relative(realWorkspace, realResolvedPath);
106028
- if (relativePath.startsWith("..") || path109.isAbsolute(relativePath)) {
106901
+ const relativePath = path110.relative(realWorkspace, realResolvedPath);
106902
+ if (relativePath.startsWith("..") || path110.isAbsolute(relativePath)) {
106029
106903
  return false;
106030
106904
  }
106031
106905
  return true;
@@ -106034,7 +106908,7 @@ function isPathInWorkspace2(filePath, workspace) {
106034
106908
  }
106035
106909
  }
106036
106910
  function processFile2(file3, cwd, exportedOnly) {
106037
- const ext = path109.extname(file3);
106911
+ const ext = path110.extname(file3);
106038
106912
  if (containsControlChars(file3)) {
106039
106913
  return {
106040
106914
  file: file3,
@@ -106051,7 +106925,7 @@ function processFile2(file3, cwd, exportedOnly) {
106051
106925
  errorType: "path-traversal"
106052
106926
  };
106053
106927
  }
106054
- if (containsWindowsAttacks2(file3)) {
106928
+ if (containsWindowsAttacks3(file3)) {
106055
106929
  return {
106056
106930
  file: file3,
106057
106931
  success: false,
@@ -106067,7 +106941,7 @@ function processFile2(file3, cwd, exportedOnly) {
106067
106941
  errorType: "path-outside-workspace"
106068
106942
  };
106069
106943
  }
106070
- const fullPath = path109.join(cwd, file3);
106944
+ const fullPath = path110.join(cwd, file3);
106071
106945
  if (!fs72.existsSync(fullPath)) {
106072
106946
  return {
106073
106947
  file: file3,
@@ -106361,15 +107235,15 @@ init_task_id();
106361
107235
  init_create_tool();
106362
107236
  init_resolve_working_directory();
106363
107237
  import * as fs73 from "node:fs";
106364
- import * as path110 from "node:path";
107238
+ import * as path111 from "node:path";
106365
107239
  var EVIDENCE_DIR = ".swarm/evidence";
106366
107240
  function isValidTaskId3(taskId) {
106367
107241
  return isStrictTaskId(taskId);
106368
107242
  }
106369
107243
  function isPathWithinSwarm(filePath, workspaceRoot) {
106370
- const normalizedWorkspace = path110.resolve(workspaceRoot);
106371
- const swarmPath = path110.join(normalizedWorkspace, ".swarm", "evidence");
106372
- const normalizedPath = path110.resolve(filePath);
107244
+ const normalizedWorkspace = path111.resolve(workspaceRoot);
107245
+ const swarmPath = path111.join(normalizedWorkspace, ".swarm", "evidence");
107246
+ const normalizedPath = path111.resolve(filePath);
106373
107247
  return normalizedPath.startsWith(swarmPath);
106374
107248
  }
106375
107249
  function readEvidenceFile(evidencePath) {
@@ -106450,7 +107324,7 @@ var check_gate_status = createSwarmTool({
106450
107324
  };
106451
107325
  return JSON.stringify(errorResult, null, 2);
106452
107326
  }
106453
- const evidencePath = path110.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
107327
+ const evidencePath = path111.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
106454
107328
  if (!isPathWithinSwarm(evidencePath, directory)) {
106455
107329
  const errorResult = {
106456
107330
  taskId: taskIdInput,
@@ -106547,7 +107421,7 @@ init_state();
106547
107421
  init_create_tool();
106548
107422
  init_resolve_working_directory();
106549
107423
  import * as fs74 from "node:fs";
106550
- import * as path111 from "node:path";
107424
+ import * as path112 from "node:path";
106551
107425
  function extractMatches(regex, text) {
106552
107426
  return Array.from(text.matchAll(regex));
106553
107427
  }
@@ -106699,10 +107573,10 @@ async function executeCompletionVerify(args2, directory) {
106699
107573
  let hasFileReadFailure = false;
106700
107574
  for (const filePath of fileTargets) {
106701
107575
  const normalizedPath = filePath.replace(/\\/g, "/");
106702
- const resolvedPath = path111.resolve(directory, normalizedPath);
106703
- const projectRoot = path111.resolve(directory);
106704
- const relative22 = path111.relative(projectRoot, resolvedPath);
106705
- const withinProject = relative22 === "" || !relative22.startsWith("..") && !path111.isAbsolute(relative22);
107576
+ const resolvedPath = path112.resolve(directory, normalizedPath);
107577
+ const projectRoot = path112.resolve(directory);
107578
+ const relative23 = path112.relative(projectRoot, resolvedPath);
107579
+ const withinProject = relative23 === "" || !relative23.startsWith("..") && !path112.isAbsolute(relative23);
106706
107580
  if (!withinProject) {
106707
107581
  blockedTasks.push({
106708
107582
  task_id: task.id,
@@ -106757,8 +107631,8 @@ async function executeCompletionVerify(args2, directory) {
106757
107631
  blockedTasks
106758
107632
  };
106759
107633
  try {
106760
- const evidenceDir = path111.join(directory, ".swarm", "evidence", `${phase}`);
106761
- const evidencePath = path111.join(evidenceDir, "completion-verify.json");
107634
+ const evidenceDir = path112.join(directory, ".swarm", "evidence", `${phase}`);
107635
+ const evidencePath = path112.join(evidenceDir, "completion-verify.json");
106762
107636
  fs74.mkdirSync(evidenceDir, { recursive: true });
106763
107637
  const evidenceBundle = {
106764
107638
  schema_version: "1.0.0",
@@ -106836,11 +107710,11 @@ var completion_verify = createSwarmTool({
106836
107710
  // src/tools/complexity-hotspots.ts
106837
107711
  init_zod();
106838
107712
  import * as fs76 from "node:fs";
106839
- import * as path113 from "node:path";
107713
+ import * as path114 from "node:path";
106840
107714
 
106841
107715
  // src/quality/metrics.ts
106842
107716
  import * as fs75 from "node:fs";
106843
- import * as path112 from "node:path";
107717
+ import * as path113 from "node:path";
106844
107718
  var MAX_FILE_SIZE_BYTES4 = 256 * 1024;
106845
107719
  var MIN_DUPLICATION_LINES = 10;
106846
107720
  function estimateCyclomaticComplexity(content) {
@@ -106892,7 +107766,7 @@ async function computeComplexityDelta(files, workingDir) {
106892
107766
  let totalComplexity = 0;
106893
107767
  const analyzedFiles = [];
106894
107768
  for (const file3 of files) {
106895
- const fullPath = path112.isAbsolute(file3) ? file3 : path112.join(workingDir, file3);
107769
+ const fullPath = path113.isAbsolute(file3) ? file3 : path113.join(workingDir, file3);
106896
107770
  if (!fs75.existsSync(fullPath)) {
106897
107771
  continue;
106898
107772
  }
@@ -107015,7 +107889,7 @@ function countGoExports(content) {
107015
107889
  function getExportCountForFile(filePath) {
107016
107890
  try {
107017
107891
  const content = fs75.readFileSync(filePath, "utf-8");
107018
- const ext = path112.extname(filePath).toLowerCase();
107892
+ const ext = path113.extname(filePath).toLowerCase();
107019
107893
  switch (ext) {
107020
107894
  case ".ts":
107021
107895
  case ".tsx":
@@ -107041,7 +107915,7 @@ async function computePublicApiDelta(files, workingDir) {
107041
107915
  let totalExports = 0;
107042
107916
  const analyzedFiles = [];
107043
107917
  for (const file3 of files) {
107044
- const fullPath = path112.isAbsolute(file3) ? file3 : path112.join(workingDir, file3);
107918
+ const fullPath = path113.isAbsolute(file3) ? file3 : path113.join(workingDir, file3);
107045
107919
  if (!fs75.existsSync(fullPath)) {
107046
107920
  continue;
107047
107921
  }
@@ -107075,7 +107949,7 @@ async function computeDuplicationRatio(files, workingDir) {
107075
107949
  let duplicateLines = 0;
107076
107950
  const analyzedFiles = [];
107077
107951
  for (const file3 of files) {
107078
- const fullPath = path112.isAbsolute(file3) ? file3 : path112.join(workingDir, file3);
107952
+ const fullPath = path113.isAbsolute(file3) ? file3 : path113.join(workingDir, file3);
107079
107953
  if (!fs75.existsSync(fullPath)) {
107080
107954
  continue;
107081
107955
  }
@@ -107108,8 +107982,8 @@ function countCodeLines(content) {
107108
107982
  return lines.length;
107109
107983
  }
107110
107984
  function isTestFile(filePath) {
107111
- const basename16 = path112.basename(filePath);
107112
- const _ext = path112.extname(filePath).toLowerCase();
107985
+ const basename16 = path113.basename(filePath);
107986
+ const _ext = path113.extname(filePath).toLowerCase();
107113
107987
  const testPatterns = [
107114
107988
  ".test.",
107115
107989
  ".spec.",
@@ -107190,8 +108064,8 @@ function matchGlobSegment(globSegments, pathSegments) {
107190
108064
  }
107191
108065
  return gIndex === globSegments.length && pIndex === pathSegments.length;
107192
108066
  }
107193
- function matchesGlobSegment(path113, glob) {
107194
- const normalizedPath = path113.replace(/\\/g, "/");
108067
+ function matchesGlobSegment(path114, glob) {
108068
+ const normalizedPath = path114.replace(/\\/g, "/");
107195
108069
  const normalizedGlob = glob.replace(/\\/g, "/");
107196
108070
  if (normalizedPath.includes("//")) {
107197
108071
  return false;
@@ -107222,8 +108096,8 @@ function simpleGlobToRegex2(glob) {
107222
108096
  function hasGlobstar(glob) {
107223
108097
  return glob.includes("**");
107224
108098
  }
107225
- function globMatches(path113, glob) {
107226
- const normalizedPath = path113.replace(/\\/g, "/");
108099
+ function globMatches(path114, glob) {
108100
+ const normalizedPath = path114.replace(/\\/g, "/");
107227
108101
  if (!glob || glob === "") {
107228
108102
  if (normalizedPath.includes("//")) {
107229
108103
  return false;
@@ -107259,7 +108133,7 @@ function shouldExcludeFile(filePath, excludeGlobs) {
107259
108133
  async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
107260
108134
  let testLines = 0;
107261
108135
  let codeLines = 0;
107262
- const srcDir = path112.join(workingDir, "src");
108136
+ const srcDir = path113.join(workingDir, "src");
107263
108137
  if (fs75.existsSync(srcDir)) {
107264
108138
  await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
107265
108139
  codeLines += lines;
@@ -107267,14 +108141,14 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
107267
108141
  }
107268
108142
  const possibleSrcDirs = ["lib", "app", "source", "core"];
107269
108143
  for (const dir of possibleSrcDirs) {
107270
- const dirPath = path112.join(workingDir, dir);
108144
+ const dirPath = path113.join(workingDir, dir);
107271
108145
  if (fs75.existsSync(dirPath)) {
107272
108146
  await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
107273
108147
  codeLines += lines;
107274
108148
  });
107275
108149
  }
107276
108150
  }
107277
- const testsDir = path112.join(workingDir, "tests");
108151
+ const testsDir = path113.join(workingDir, "tests");
107278
108152
  if (fs75.existsSync(testsDir)) {
107279
108153
  await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
107280
108154
  testLines += lines;
@@ -107282,7 +108156,7 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
107282
108156
  }
107283
108157
  const possibleTestDirs = ["test", "__tests__", "specs"];
107284
108158
  for (const dir of possibleTestDirs) {
107285
- const dirPath = path112.join(workingDir, dir);
108159
+ const dirPath = path113.join(workingDir, dir);
107286
108160
  if (fs75.existsSync(dirPath) && dirPath !== testsDir) {
107287
108161
  await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
107288
108162
  testLines += lines;
@@ -107297,7 +108171,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
107297
108171
  try {
107298
108172
  const entries = fs75.readdirSync(dirPath, { withFileTypes: true });
107299
108173
  for (const entry of entries) {
107300
- const fullPath = path112.join(dirPath, entry.name);
108174
+ const fullPath = path113.join(dirPath, entry.name);
107301
108175
  if (entry.isDirectory()) {
107302
108176
  if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
107303
108177
  continue;
@@ -107305,7 +108179,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
107305
108179
  await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
107306
108180
  } else if (entry.isFile()) {
107307
108181
  const relativePath = fullPath.replace(`${dirPath}/`, "");
107308
- const ext = path112.extname(entry.name).toLowerCase();
108182
+ const ext = path113.extname(entry.name).toLowerCase();
107309
108183
  const validExts = [
107310
108184
  ".ts",
107311
108185
  ".tsx",
@@ -107556,7 +108430,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
107556
108430
  const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
107557
108431
  const filteredChurn = new Map;
107558
108432
  for (const [file3, count] of churnMap) {
107559
- const ext = path113.extname(file3).toLowerCase();
108433
+ const ext = path114.extname(file3).toLowerCase();
107560
108434
  if (extSet.has(ext)) {
107561
108435
  filteredChurn.set(file3, count);
107562
108436
  }
@@ -107567,7 +108441,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
107567
108441
  for (const [file3, churnCount] of filteredChurn) {
107568
108442
  let fullPath = file3;
107569
108443
  if (!fs76.existsSync(fullPath)) {
107570
- fullPath = path113.join(cwd, file3);
108444
+ fullPath = path114.join(cwd, file3);
107571
108445
  }
107572
108446
  const complexity = getComplexityForFile2(fullPath);
107573
108447
  if (complexity !== null) {
@@ -107736,8 +108610,8 @@ ${body2}`);
107736
108610
 
107737
108611
  // src/council/council-evidence-writer.ts
107738
108612
  init_task_file();
107739
- import { appendFileSync as appendFileSync12, existsSync as existsSync62, mkdirSync as mkdirSync28, readFileSync as readFileSync44 } from "node:fs";
107740
- import { join as join94 } from "node:path";
108613
+ import { appendFileSync as appendFileSync12, existsSync as existsSync63, mkdirSync as mkdirSync29, readFileSync as readFileSync45 } from "node:fs";
108614
+ import { join as join95 } from "node:path";
107741
108615
  var EVIDENCE_DIR2 = ".swarm/evidence";
107742
108616
  var VALID_TASK_ID = /^\d+\.\d+(\.\d+)*$/;
107743
108617
  var COUNCIL_GATE_NAME = "council";
@@ -107774,14 +108648,14 @@ async function writeCouncilEvidence(workingDir, synthesis) {
107774
108648
  if (!VALID_TASK_ID.test(synthesis.taskId)) {
107775
108649
  throw new Error(`writeCouncilEvidence: invalid taskId "${synthesis.taskId}" — must match N.M or N.M.P format`);
107776
108650
  }
107777
- const dir = join94(workingDir, EVIDENCE_DIR2);
107778
- mkdirSync28(dir, { recursive: true });
108651
+ const dir = join95(workingDir, EVIDENCE_DIR2);
108652
+ mkdirSync29(dir, { recursive: true });
107779
108653
  const filePath = taskEvidencePath(workingDir, synthesis.taskId);
107780
108654
  await _internals53.withTaskEvidenceLock(workingDir, synthesis.taskId, COUNCIL_AGENT_ID, async () => {
107781
108655
  const existingRoot = Object.create(null);
107782
- if (existsSync62(filePath)) {
108656
+ if (existsSync63(filePath)) {
107783
108657
  try {
107784
- const parsed = JSON.parse(readFileSync44(filePath, "utf-8"));
108658
+ const parsed = JSON.parse(readFileSync45(filePath, "utf-8"));
107785
108659
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
107786
108660
  safeAssignOwnProps(existingRoot, parsed);
107787
108661
  }
@@ -107812,15 +108686,15 @@ async function writeCouncilEvidence(workingDir, synthesis) {
107812
108686
  await atomicWriteFile(filePath, JSON.stringify(updated, null, 2));
107813
108687
  });
107814
108688
  try {
107815
- const councilDir = join94(workingDir, ".swarm", "council");
107816
- mkdirSync28(councilDir, { recursive: true });
108689
+ const councilDir = join95(workingDir, ".swarm", "council");
108690
+ mkdirSync29(councilDir, { recursive: true });
107817
108691
  const auditLine = JSON.stringify({
107818
108692
  round: synthesis.roundNumber,
107819
108693
  verdict: synthesis.overallVerdict,
107820
108694
  timestamp: synthesis.timestamp,
107821
108695
  vetoedBy: synthesis.vetoedBy
107822
108696
  });
107823
- appendFileSync12(join94(councilDir, `${synthesis.taskId}.rounds.jsonl`), `${auditLine}
108697
+ appendFileSync12(join95(councilDir, `${synthesis.taskId}.rounds.jsonl`), `${auditLine}
107824
108698
  `);
107825
108699
  } catch (auditError) {
107826
108700
  console.warn(`writeCouncilEvidence: failed to append round-history audit log: ${auditError instanceof Error ? auditError.message : String(auditError)}`);
@@ -108142,25 +109016,25 @@ function buildFinalCouncilFeedback(projectSummary, verdict, vetoedBy, requiredFi
108142
109016
  }
108143
109017
 
108144
109018
  // src/council/criteria-store.ts
108145
- import { existsSync as existsSync63, mkdirSync as mkdirSync29, readFileSync as readFileSync45, writeFileSync as writeFileSync21 } from "node:fs";
108146
- import { join as join95 } from "node:path";
109019
+ import { existsSync as existsSync64, mkdirSync as mkdirSync30, readFileSync as readFileSync46, writeFileSync as writeFileSync22 } from "node:fs";
109020
+ import { join as join96 } from "node:path";
108147
109021
  var COUNCIL_DIR = ".swarm/council";
108148
109022
  function writeCriteria(workingDir, taskId, criteria) {
108149
- const dir = join95(workingDir, COUNCIL_DIR);
108150
- mkdirSync29(dir, { recursive: true });
109023
+ const dir = join96(workingDir, COUNCIL_DIR);
109024
+ mkdirSync30(dir, { recursive: true });
108151
109025
  const payload = {
108152
109026
  taskId,
108153
109027
  criteria,
108154
109028
  declaredAt: new Date().toISOString()
108155
109029
  };
108156
- writeFileSync21(join95(dir, `${safeId(taskId)}.json`), JSON.stringify(payload, null, 2));
109030
+ writeFileSync22(join96(dir, `${safeId(taskId)}.json`), JSON.stringify(payload, null, 2));
108157
109031
  }
108158
109032
  function readCriteria(workingDir, taskId) {
108159
- const filePath = join95(workingDir, COUNCIL_DIR, `${safeId(taskId)}.json`);
108160
- if (!existsSync63(filePath))
109033
+ const filePath = join96(workingDir, COUNCIL_DIR, `${safeId(taskId)}.json`);
109034
+ if (!existsSync64(filePath))
108161
109035
  return null;
108162
109036
  try {
108163
- const parsed = JSON.parse(readFileSync45(filePath, "utf-8"));
109037
+ const parsed = JSON.parse(readFileSync46(filePath, "utf-8"));
108164
109038
  if (parsed && typeof parsed === "object" && typeof parsed.taskId === "string" && Array.isArray(parsed.criteria)) {
108165
109039
  return parsed;
108166
109040
  }
@@ -108310,7 +109184,7 @@ var submit_council_verdicts = createSwarmTool({
108310
109184
  init_zod();
108311
109185
  init_loader();
108312
109186
  import * as fs77 from "node:fs";
108313
- import * as path114 from "node:path";
109187
+ import * as path115 from "node:path";
108314
109188
 
108315
109189
  // src/council/general-council-advisory.ts
108316
109190
  var ADVISORY_HEADER = "[general_council] (advisory; not blocking)";
@@ -108738,10 +109612,10 @@ var convene_general_council = createSwarmTool({
108738
109612
  const round1 = input.round1Responses;
108739
109613
  const round2 = input.round2Responses ?? [];
108740
109614
  const result = synthesizeGeneralCouncil(input.question, input.mode, round1, round2);
108741
- const evidenceDir = path114.join(workingDir, ".swarm", "council", "general");
109615
+ const evidenceDir = path115.join(workingDir, ".swarm", "council", "general");
108742
109616
  const safeTimestamp = result.timestamp.replace(/[:.]/g, "-");
108743
109617
  const evidenceFile = `${safeTimestamp}-${input.mode}.json`;
108744
- const evidencePath = path114.join(evidenceDir, evidenceFile);
109618
+ const evidencePath = path115.join(evidenceDir, evidenceFile);
108745
109619
  try {
108746
109620
  await fs77.promises.mkdir(evidenceDir, { recursive: true });
108747
109621
  await fs77.promises.writeFile(evidencePath, JSON.stringify(result, null, 2));
@@ -109012,7 +109886,7 @@ init_state();
109012
109886
  init_task_id();
109013
109887
  init_create_tool();
109014
109888
  import * as fs78 from "node:fs";
109015
- import * as path115 from "node:path";
109889
+ import * as path116 from "node:path";
109016
109890
  function validateTaskIdFormat2(taskId) {
109017
109891
  return validateTaskIdFormat(taskId);
109018
109892
  }
@@ -109086,8 +109960,8 @@ async function executeDeclareScope(args2, fallbackDir) {
109086
109960
  };
109087
109961
  }
109088
109962
  }
109089
- normalizedDir = path115.normalize(args2.working_directory);
109090
- const pathParts = normalizedDir.split(path115.sep);
109963
+ normalizedDir = path116.normalize(args2.working_directory);
109964
+ const pathParts = normalizedDir.split(path116.sep);
109091
109965
  if (pathParts.includes("..")) {
109092
109966
  return {
109093
109967
  success: false,
@@ -109097,10 +109971,10 @@ async function executeDeclareScope(args2, fallbackDir) {
109097
109971
  ]
109098
109972
  };
109099
109973
  }
109100
- const resolvedDir = path115.resolve(normalizedDir);
109974
+ const resolvedDir = path116.resolve(normalizedDir);
109101
109975
  try {
109102
109976
  const realPath = fs78.realpathSync(resolvedDir);
109103
- const planPath2 = path115.join(realPath, ".swarm", "plan.json");
109977
+ const planPath2 = path116.join(realPath, ".swarm", "plan.json");
109104
109978
  if (!fs78.existsSync(planPath2)) {
109105
109979
  return {
109106
109980
  success: false,
@@ -109121,9 +109995,9 @@ async function executeDeclareScope(args2, fallbackDir) {
109121
109995
  }
109122
109996
  if (normalizedDir && fallbackDir) {
109123
109997
  try {
109124
- const canonicalWorkingDir = fs78.realpathSync(path115.resolve(normalizedDir));
109125
- const canonicalProjectRoot = fs78.realpathSync(path115.resolve(fallbackDir));
109126
- if (canonicalWorkingDir.startsWith(canonicalProjectRoot + path115.sep)) {
109998
+ const canonicalWorkingDir = fs78.realpathSync(path116.resolve(normalizedDir));
109999
+ const canonicalProjectRoot = fs78.realpathSync(path116.resolve(fallbackDir));
110000
+ if (canonicalWorkingDir.startsWith(canonicalProjectRoot + path116.sep)) {
109127
110001
  return {
109128
110002
  success: false,
109129
110003
  message: `working_directory "${normalizedDir}" is a subdirectory of the project root. Use the project root "${fallbackDir}" instead.`,
@@ -109145,7 +110019,7 @@ async function executeDeclareScope(args2, fallbackDir) {
109145
110019
  };
109146
110020
  }
109147
110021
  const directory = normalizedDir || fallbackDir;
109148
- const planPath = path115.resolve(directory, ".swarm", "plan.json");
110022
+ const planPath = path116.resolve(directory, ".swarm", "plan.json");
109149
110023
  if (!fs78.existsSync(planPath)) {
109150
110024
  return {
109151
110025
  success: false,
@@ -109185,8 +110059,8 @@ async function executeDeclareScope(args2, fallbackDir) {
109185
110059
  const normalizeErrors = [];
109186
110060
  const dir = directory;
109187
110061
  const mergedFiles = rawMergedFiles.map((file3) => {
109188
- if (path115.isAbsolute(file3)) {
109189
- const relativePath = path115.relative(dir, file3).replace(/\\/g, "/");
110062
+ if (path116.isAbsolute(file3)) {
110063
+ const relativePath = path116.relative(dir, file3).replace(/\\/g, "/");
109190
110064
  if (relativePath.startsWith("..")) {
109191
110065
  normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
109192
110066
  return file3;
@@ -109248,7 +110122,7 @@ var declare_scope = createSwarmTool({
109248
110122
  init_zod();
109249
110123
  import * as child_process7 from "node:child_process";
109250
110124
  import * as fs79 from "node:fs";
109251
- import * as path116 from "node:path";
110125
+ import * as path117 from "node:path";
109252
110126
  init_create_tool();
109253
110127
  var MAX_DIFF_LINES = 500;
109254
110128
  var DIFF_TIMEOUT_MS = 30000;
@@ -109277,20 +110151,20 @@ function validateBase(base) {
109277
110151
  function validatePaths(paths) {
109278
110152
  if (!paths)
109279
110153
  return null;
109280
- for (const path117 of paths) {
109281
- if (!path117 || path117.length === 0) {
110154
+ for (const path118 of paths) {
110155
+ if (!path118 || path118.length === 0) {
109282
110156
  return "empty path not allowed";
109283
110157
  }
109284
- if (path117.length > MAX_PATH_LENGTH) {
110158
+ if (path118.length > MAX_PATH_LENGTH) {
109285
110159
  return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
109286
110160
  }
109287
- if (SHELL_METACHARACTERS2.test(path117)) {
110161
+ if (SHELL_METACHARACTERS2.test(path118)) {
109288
110162
  return "path contains shell metacharacters";
109289
110163
  }
109290
- if (path117.startsWith("-")) {
110164
+ if (path118.startsWith("-")) {
109291
110165
  return 'path cannot start with "-" (option-like arguments not allowed)';
109292
110166
  }
109293
- if (CONTROL_CHAR_PATTERN2.test(path117)) {
110167
+ if (CONTROL_CHAR_PATTERN2.test(path118)) {
109294
110168
  return "path contains control characters";
109295
110169
  }
109296
110170
  }
@@ -109398,8 +110272,8 @@ var diff = createSwarmTool({
109398
110272
  if (parts2.length >= 3) {
109399
110273
  const additions = parseInt(parts2[0], 10) || 0;
109400
110274
  const deletions = parseInt(parts2[1], 10) || 0;
109401
- const path117 = parts2[2];
109402
- files.push({ path: path117, additions, deletions });
110275
+ const path118 = parts2[2];
110276
+ files.push({ path: path118, additions, deletions });
109403
110277
  }
109404
110278
  }
109405
110279
  const contractChanges = [];
@@ -109438,7 +110312,7 @@ var diff = createSwarmTool({
109438
110312
  } else if (base === "unstaged") {
109439
110313
  const oldRef = `:${file3.path}`;
109440
110314
  oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
109441
- newContent = fs79.readFileSync(path116.join(directory, file3.path), "utf-8");
110315
+ newContent = fs79.readFileSync(path117.join(directory, file3.path), "utf-8");
109442
110316
  } else {
109443
110317
  const oldRef = `${base}:${file3.path}`;
109444
110318
  oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
@@ -109515,12 +110389,12 @@ var diff = createSwarmTool({
109515
110389
  init_zod();
109516
110390
  import * as child_process8 from "node:child_process";
109517
110391
  import * as fs80 from "node:fs";
109518
- import * as path117 from "node:path";
110392
+ import * as path118 from "node:path";
109519
110393
  init_create_tool();
109520
110394
  init_resolve_working_directory();
109521
110395
  async function execGit2(workingDir, args2, options) {
109522
110396
  try {
109523
- const stdout = await new Promise((resolve40, reject) => {
110397
+ const stdout = await new Promise((resolve41, reject) => {
109524
110398
  const execOpts = {
109525
110399
  encoding: "utf-8",
109526
110400
  cwd: workingDir,
@@ -109533,7 +110407,7 @@ async function execGit2(workingDir, args2, options) {
109533
110407
  reject(error93);
109534
110408
  return;
109535
110409
  }
109536
- resolve40(output ?? "");
110410
+ resolve41(output ?? "");
109537
110411
  });
109538
110412
  });
109539
110413
  return stdout;
@@ -109584,7 +110458,7 @@ var diff_summary = createSwarmTool({
109584
110458
  }
109585
110459
  try {
109586
110460
  let oldContent;
109587
- const newContent = await fs80.promises.readFile(path117.join(workingDir, filePath), "utf-8");
110461
+ const newContent = await fs80.promises.readFile(path118.join(workingDir, filePath), "utf-8");
109588
110462
  if (fileExistsInHead) {
109589
110463
  oldContent = await execGit2(workingDir, ["show", `HEAD:${filePath}`], {
109590
110464
  timeout: 5000,
@@ -109814,7 +110688,7 @@ init_zod();
109814
110688
  init_create_tool();
109815
110689
  init_path_security();
109816
110690
  import * as fs81 from "node:fs";
109817
- import * as path118 from "node:path";
110691
+ import * as path119 from "node:path";
109818
110692
  var MAX_FILE_SIZE_BYTES6 = 1024 * 1024;
109819
110693
  var MAX_EVIDENCE_FILES = 1000;
109820
110694
  var EVIDENCE_DIR3 = ".swarm/evidence";
@@ -109841,9 +110715,9 @@ function validateRequiredTypes(input) {
109841
110715
  return null;
109842
110716
  }
109843
110717
  function isPathWithinSwarm2(filePath, cwd) {
109844
- const normalizedCwd = path118.resolve(cwd);
109845
- const swarmPath = path118.join(normalizedCwd, ".swarm");
109846
- const normalizedPath = path118.resolve(filePath);
110718
+ const normalizedCwd = path119.resolve(cwd);
110719
+ const swarmPath = path119.join(normalizedCwd, ".swarm");
110720
+ const normalizedPath = path119.resolve(filePath);
109847
110721
  return normalizedPath.startsWith(swarmPath);
109848
110722
  }
109849
110723
  function parseCompletedTasks(planContent) {
@@ -109873,10 +110747,10 @@ function readEvidenceFiles(evidenceDir, _cwd) {
109873
110747
  if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
109874
110748
  continue;
109875
110749
  }
109876
- const filePath = path118.join(evidenceDir, filename);
110750
+ const filePath = path119.join(evidenceDir, filename);
109877
110751
  try {
109878
- const resolvedPath = path118.resolve(filePath);
109879
- const evidenceDirResolved = path118.resolve(evidenceDir);
110752
+ const resolvedPath = path119.resolve(filePath);
110753
+ const evidenceDirResolved = path119.resolve(evidenceDir);
109880
110754
  if (!resolvedPath.startsWith(evidenceDirResolved)) {
109881
110755
  continue;
109882
110756
  }
@@ -109994,7 +110868,7 @@ var evidence_check = createSwarmTool({
109994
110868
  return JSON.stringify(errorResult, null, 2);
109995
110869
  }
109996
110870
  const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
109997
- const planPath = path118.join(cwd, PLAN_FILE);
110871
+ const planPath = path119.join(cwd, PLAN_FILE);
109998
110872
  if (!isPathWithinSwarm2(planPath, cwd)) {
109999
110873
  const errorResult = {
110000
110874
  error: "plan file path validation failed",
@@ -110026,7 +110900,7 @@ var evidence_check = createSwarmTool({
110026
110900
  };
110027
110901
  return JSON.stringify(result2, null, 2);
110028
110902
  }
110029
- const evidenceDir = path118.join(cwd, EVIDENCE_DIR3);
110903
+ const evidenceDir = path119.join(cwd, EVIDENCE_DIR3);
110030
110904
  const evidence = readEvidenceFiles(evidenceDir, cwd);
110031
110905
  const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
110032
110906
  const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
@@ -110045,7 +110919,7 @@ var evidence_check = createSwarmTool({
110045
110919
  init_zod();
110046
110920
  init_create_tool();
110047
110921
  import * as fs82 from "node:fs";
110048
- import * as path119 from "node:path";
110922
+ import * as path120 from "node:path";
110049
110923
  var EXT_MAP = {
110050
110924
  python: ".py",
110051
110925
  py: ".py",
@@ -110126,12 +111000,12 @@ var extract_code_blocks = createSwarmTool({
110126
111000
  if (prefix) {
110127
111001
  filename = `${prefix}_${filename}`;
110128
111002
  }
110129
- let filepath = path119.join(targetDir, filename);
110130
- const base = path119.basename(filepath, path119.extname(filepath));
110131
- const ext = path119.extname(filepath);
111003
+ let filepath = path120.join(targetDir, filename);
111004
+ const base = path120.basename(filepath, path120.extname(filepath));
111005
+ const ext = path120.extname(filepath);
110132
111006
  let counter = 1;
110133
111007
  while (fs82.existsSync(filepath)) {
110134
- filepath = path119.join(targetDir, `${base}_${counter}${ext}`);
111008
+ filepath = path120.join(targetDir, `${base}_${counter}${ext}`);
110135
111009
  counter++;
110136
111010
  }
110137
111011
  try {
@@ -110473,7 +111347,7 @@ init_create_tool();
110473
111347
  var GITINGEST_TIMEOUT_MS = 1e4;
110474
111348
  var GITINGEST_MAX_RESPONSE_BYTES = 5242880;
110475
111349
  var GITINGEST_MAX_RETRIES = 2;
110476
- var delay = (ms) => new Promise((resolve41) => setTimeout(resolve41, ms));
111350
+ var delay = (ms) => new Promise((resolve42) => setTimeout(resolve42, ms));
110477
111351
  async function fetchGitingest(args2) {
110478
111352
  for (let attempt = 0;attempt <= GITINGEST_MAX_RETRIES; attempt++) {
110479
111353
  try {
@@ -110562,7 +111436,7 @@ init_zod();
110562
111436
  init_create_tool();
110563
111437
  init_path_security();
110564
111438
  import * as fs83 from "node:fs";
110565
- import * as path120 from "node:path";
111439
+ import * as path121 from "node:path";
110566
111440
  var MAX_FILE_PATH_LENGTH2 = 500;
110567
111441
  var MAX_SYMBOL_LENGTH = 256;
110568
111442
  var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
@@ -110610,7 +111484,7 @@ function validateSymbolInput(symbol3) {
110610
111484
  return null;
110611
111485
  }
110612
111486
  function isBinaryFile2(filePath, buffer) {
110613
- const ext = path120.extname(filePath).toLowerCase();
111487
+ const ext = path121.extname(filePath).toLowerCase();
110614
111488
  if (ext === ".json" || ext === ".md" || ext === ".txt") {
110615
111489
  return false;
110616
111490
  }
@@ -110634,15 +111508,15 @@ function parseImports(content, targetFile, targetSymbol) {
110634
111508
  const imports = [];
110635
111509
  let _resolvedTarget;
110636
111510
  try {
110637
- _resolvedTarget = path120.resolve(targetFile);
111511
+ _resolvedTarget = path121.resolve(targetFile);
110638
111512
  } catch {
110639
111513
  _resolvedTarget = targetFile;
110640
111514
  }
110641
- const targetBasename = path120.basename(targetFile, path120.extname(targetFile));
111515
+ const targetBasename = path121.basename(targetFile, path121.extname(targetFile));
110642
111516
  const targetWithExt = targetFile;
110643
111517
  const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
110644
- const normalizedTargetWithExt = path120.normalize(targetWithExt).replace(/\\/g, "/");
110645
- const normalizedTargetWithoutExt = path120.normalize(targetWithoutExt).replace(/\\/g, "/");
111518
+ const normalizedTargetWithExt = path121.normalize(targetWithExt).replace(/\\/g, "/");
111519
+ const normalizedTargetWithoutExt = path121.normalize(targetWithoutExt).replace(/\\/g, "/");
110646
111520
  const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
110647
111521
  for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
110648
111522
  const modulePath = match[1] || match[2] || match[3];
@@ -110665,9 +111539,9 @@ function parseImports(content, targetFile, targetSymbol) {
110665
111539
  }
110666
111540
  const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
110667
111541
  let isMatch = false;
110668
- const _targetDir = path120.dirname(targetFile);
110669
- const targetExt = path120.extname(targetFile);
110670
- const targetBasenameNoExt = path120.basename(targetFile, targetExt);
111542
+ const _targetDir = path121.dirname(targetFile);
111543
+ const targetExt = path121.extname(targetFile);
111544
+ const targetBasenameNoExt = path121.basename(targetFile, targetExt);
110671
111545
  const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
110672
111546
  const moduleName = modulePath.split(/[/\\]/).pop() || "";
110673
111547
  const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
@@ -110735,10 +111609,10 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
110735
111609
  entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
110736
111610
  for (const entry of entries) {
110737
111611
  if (SKIP_DIRECTORIES4.has(entry)) {
110738
- stats.skippedDirs.push(path120.join(dir, entry));
111612
+ stats.skippedDirs.push(path121.join(dir, entry));
110739
111613
  continue;
110740
111614
  }
110741
- const fullPath = path120.join(dir, entry);
111615
+ const fullPath = path121.join(dir, entry);
110742
111616
  let stat9;
110743
111617
  try {
110744
111618
  stat9 = fs83.statSync(fullPath);
@@ -110752,7 +111626,7 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
110752
111626
  if (stat9.isDirectory()) {
110753
111627
  findSourceFiles2(fullPath, files, stats);
110754
111628
  } else if (stat9.isFile()) {
110755
- const ext = path120.extname(fullPath).toLowerCase();
111629
+ const ext = path121.extname(fullPath).toLowerCase();
110756
111630
  if (SUPPORTED_EXTENSIONS3.includes(ext)) {
110757
111631
  files.push(fullPath);
110758
111632
  }
@@ -110809,7 +111683,7 @@ var imports = createSwarmTool({
110809
111683
  return JSON.stringify(errorResult, null, 2);
110810
111684
  }
110811
111685
  try {
110812
- const targetFile = path120.resolve(file3);
111686
+ const targetFile = path121.resolve(file3);
110813
111687
  if (!fs83.existsSync(targetFile)) {
110814
111688
  const errorResult = {
110815
111689
  error: `target file not found: ${file3}`,
@@ -110831,7 +111705,7 @@ var imports = createSwarmTool({
110831
111705
  };
110832
111706
  return JSON.stringify(errorResult, null, 2);
110833
111707
  }
110834
- const baseDir = path120.dirname(targetFile);
111708
+ const baseDir = path121.dirname(targetFile);
110835
111709
  const scanStats = {
110836
111710
  skippedDirs: [],
110837
111711
  skippedFiles: 0,
@@ -111219,7 +112093,7 @@ init_zod();
111219
112093
  init_config();
111220
112094
  init_knowledge_store();
111221
112095
  init_create_tool();
111222
- import { existsSync as existsSync68 } from "node:fs";
112096
+ import { existsSync as existsSync69 } from "node:fs";
111223
112097
  var DEFAULT_LIMIT = 10;
111224
112098
  var MAX_LESSON_LENGTH = 200;
111225
112099
  var VALID_CATEGORIES3 = [
@@ -111295,14 +112169,14 @@ function validateLimit(limit) {
111295
112169
  }
111296
112170
  async function readSwarmKnowledge(directory) {
111297
112171
  const swarmPath = resolveSwarmKnowledgePath(directory);
111298
- if (!existsSync68(swarmPath)) {
112172
+ if (!existsSync69(swarmPath)) {
111299
112173
  return [];
111300
112174
  }
111301
112175
  return readKnowledge(swarmPath);
111302
112176
  }
111303
112177
  async function readHiveKnowledge() {
111304
112178
  const hivePath = resolveHiveKnowledgePath();
111305
- if (!existsSync68(hivePath)) {
112179
+ if (!existsSync69(hivePath)) {
111306
112180
  return [];
111307
112181
  }
111308
112182
  return readKnowledge(hivePath);
@@ -111728,11 +112602,11 @@ var lean_turbo_acquire_locks = createSwarmTool({
111728
112602
  init_zod();
111729
112603
  init_constants();
111730
112604
  import * as fs85 from "node:fs";
111731
- import * as path122 from "node:path";
112605
+ import * as path123 from "node:path";
111732
112606
 
111733
112607
  // src/turbo/lean/conflicts.ts
111734
112608
  import * as fs84 from "node:fs";
111735
- import * as path121 from "node:path";
112609
+ import * as path122 from "node:path";
111736
112610
  var DEFAULT_GLOBAL_FILES = [
111737
112611
  "package.json",
111738
112612
  "package-lock.json",
@@ -111835,7 +112709,7 @@ function isGlobalFile(normalizedPath) {
111835
112709
  }
111836
112710
  return false;
111837
112711
  }
111838
- function isProtectedPath2(normalizedPath) {
112712
+ function isProtectedPath3(normalizedPath) {
111839
112713
  const lowerPath = normalizedPath.toLowerCase();
111840
112714
  for (const pattern of DEFAULT_PROTECTED_PATTERNS) {
111841
112715
  if (lowerPath.includes(pattern.toLowerCase())) {
@@ -111859,7 +112733,7 @@ function isProtectedPath2(normalizedPath) {
111859
112733
  return false;
111860
112734
  }
111861
112735
  function readTaskScopes(directory, taskId) {
111862
- const scopePath = path121.join(directory, ".swarm", "scopes", `scope-${taskId}.json`);
112736
+ const scopePath = path122.join(directory, ".swarm", "scopes", `scope-${taskId}.json`);
111863
112737
  try {
111864
112738
  if (!fs84.existsSync(scopePath)) {
111865
112739
  return null;
@@ -111885,7 +112759,7 @@ function assessTaskRisk(files, hasDeclaredScope, hasInvalidScope, config3) {
111885
112759
  files: globalFiles
111886
112760
  };
111887
112761
  }
111888
- const protectedFiles = files.filter(isProtectedPath2);
112762
+ const protectedFiles = files.filter(isProtectedPath3);
111889
112763
  if (protectedFiles.length > 0) {
111890
112764
  return {
111891
112765
  category: "protected",
@@ -112247,7 +113121,7 @@ function createEmptyPlan(phaseNumber, planId) {
112247
113121
  // src/tools/lean-turbo-plan-lanes.ts
112248
113122
  init_create_tool();
112249
113123
  function readPlanJson(directory) {
112250
- const planPath = path122.join(directory, ".swarm", "plan.json");
113124
+ const planPath = path123.join(directory, ".swarm", "plan.json");
112251
113125
  if (!fs85.existsSync(planPath)) {
112252
113126
  return null;
112253
113127
  }
@@ -112303,15 +113177,15 @@ init_config();
112303
113177
  // src/turbo/lean/reviewer.ts
112304
113178
  init_state();
112305
113179
  import * as fs87 from "node:fs/promises";
112306
- import * as path124 from "node:path";
113180
+ import * as path125 from "node:path";
112307
113181
 
112308
113182
  // src/turbo/lean/evidence.ts
112309
113183
  init_bun_compat();
112310
113184
  import { rmSync as rmSync6 } from "node:fs";
112311
113185
  import * as fs86 from "node:fs/promises";
112312
- import * as path123 from "node:path";
113186
+ import * as path124 from "node:path";
112313
113187
  function leanTurboEvidenceDir(directory, phase) {
112314
- return path123.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
113188
+ return path124.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
112315
113189
  }
112316
113190
  function validateLaneId(laneId) {
112317
113191
  if (laneId.length === 0) {
@@ -112333,16 +113207,16 @@ function validateLaneId(laneId) {
112333
113207
  function laneEvidencePath(directory, phase, laneId) {
112334
113208
  validateLaneId(laneId);
112335
113209
  const expectedDir = leanTurboEvidenceDir(directory, phase);
112336
- const resolvedPath = path123.resolve(path123.join(expectedDir, `${laneId}.json`));
112337
- const resolvedDir = path123.resolve(expectedDir);
112338
- if (!resolvedPath.startsWith(resolvedDir + path123.sep) && resolvedPath !== resolvedDir) {
113210
+ const resolvedPath = path124.resolve(path124.join(expectedDir, `${laneId}.json`));
113211
+ const resolvedDir = path124.resolve(expectedDir);
113212
+ if (!resolvedPath.startsWith(resolvedDir + path124.sep) && resolvedPath !== resolvedDir) {
112339
113213
  throw new Error(`Invalid laneId: path traversal detected (got "${laneId}")`);
112340
113214
  }
112341
113215
  return resolvedPath;
112342
113216
  }
112343
113217
  async function atomicWriteJson(filePath, data) {
112344
113218
  const content = JSON.stringify(data, null, 2);
112345
- const dir = path123.dirname(filePath);
113219
+ const dir = path124.dirname(filePath);
112346
113220
  await fs86.mkdir(dir, { recursive: true });
112347
113221
  const tempPath = `${filePath}.tmp.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}`;
112348
113222
  try {
@@ -112356,7 +113230,7 @@ async function atomicWriteJson(filePath, data) {
112356
113230
  }
112357
113231
  }
112358
113232
  function phaseEvidencePath(directory, phase) {
112359
- return path123.join(leanTurboEvidenceDir(directory, phase), "lean-turbo-phase.json");
113233
+ return path124.join(leanTurboEvidenceDir(directory, phase), "lean-turbo-phase.json");
112360
113234
  }
112361
113235
  async function writeLaneEvidence(directory, phase, evidence) {
112362
113236
  const targetPath = laneEvidencePath(directory, phase, evidence.laneId);
@@ -112400,7 +113274,7 @@ async function listLaneEvidence(directory, phase) {
112400
113274
  if (entry === "lean-turbo-phase.json") {
112401
113275
  continue;
112402
113276
  }
112403
- const filePath = path123.join(evidenceDir, entry);
113277
+ const filePath = path124.join(evidenceDir, entry);
112404
113278
  let content;
112405
113279
  try {
112406
113280
  content = await fs86.readFile(filePath, "utf-8");
@@ -112531,9 +113405,9 @@ function parseReviewerVerdict(responseText) {
112531
113405
  return { verdict, reason };
112532
113406
  }
112533
113407
  async function writeReviewerEvidence(directory, phase, verdict, reason) {
112534
- const evidenceDir = path124.join(directory, ".swarm", "evidence", String(phase));
113408
+ const evidenceDir = path125.join(directory, ".swarm", "evidence", String(phase));
112535
113409
  await fs87.mkdir(evidenceDir, { recursive: true });
112536
- const evidencePath = path124.join(evidenceDir, "lean-turbo-reviewer.json");
113410
+ const evidencePath = path125.join(evidenceDir, "lean-turbo-reviewer.json");
112537
113411
  const content = JSON.stringify({
112538
113412
  phase,
112539
113413
  verdict,
@@ -113345,7 +114219,7 @@ init_lint();
113345
114219
  init_spec_schema();
113346
114220
  init_create_tool();
113347
114221
  import * as fs88 from "node:fs";
113348
- import * as path125 from "node:path";
114222
+ import * as path126 from "node:path";
113349
114223
  var SPEC_FILE_NAME = "spec.md";
113350
114224
  var SWARM_DIR2 = ".swarm";
113351
114225
  var OBLIGATION_KEYWORDS = ["MUST", "SHALL", "SHOULD", "MAY"];
@@ -113398,7 +114272,7 @@ var lint_spec = createSwarmTool({
113398
114272
  async execute(_args, directory) {
113399
114273
  const errors5 = [];
113400
114274
  const warnings = [];
113401
- const specPath = path125.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
114275
+ const specPath = path126.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
113402
114276
  if (!fs88.existsSync(specPath)) {
113403
114277
  const result2 = {
113404
114278
  valid: false,
@@ -113470,12 +114344,12 @@ var lint_spec = createSwarmTool({
113470
114344
  // src/tools/mutation-test.ts
113471
114345
  init_zod();
113472
114346
  import * as fs89 from "node:fs";
113473
- import * as path127 from "node:path";
114347
+ import * as path128 from "node:path";
113474
114348
 
113475
114349
  // src/mutation/engine.ts
113476
114350
  import { spawnSync as spawnSync8 } from "node:child_process";
113477
- import { unlinkSync as unlinkSync17, writeFileSync as writeFileSync23 } from "node:fs";
113478
- import * as path126 from "node:path";
114351
+ import { unlinkSync as unlinkSync18, writeFileSync as writeFileSync24 } from "node:fs";
114352
+ import * as path127 from "node:path";
113479
114353
 
113480
114354
  // src/mutation/equivalence.ts
113481
114355
  function isStaticallyEquivalent(originalCode, mutatedCode) {
@@ -113621,9 +114495,9 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
113621
114495
  let patchFile;
113622
114496
  try {
113623
114497
  const safeId2 = patch.id.replace(/[^a-zA-Z0-9_-]/g, "_");
113624
- patchFile = path126.join(workingDir, `.mutation_patch_${safeId2}.diff`);
114498
+ patchFile = path127.join(workingDir, `.mutation_patch_${safeId2}.diff`);
113625
114499
  try {
113626
- writeFileSync23(patchFile, patch.patch);
114500
+ writeFileSync24(patchFile, patch.patch);
113627
114501
  } catch (writeErr) {
113628
114502
  error93 = `Failed to write patch file: ${writeErr}`;
113629
114503
  outcome = "error";
@@ -113719,7 +114593,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
113719
114593
  revertError = new Error(`Failed to revert mutation ${patch.id}: ${revertErr}. Working tree may be dirty.`);
113720
114594
  }
113721
114595
  try {
113722
- unlinkSync17(patchFile);
114596
+ unlinkSync18(patchFile);
113723
114597
  } catch (_unlinkErr) {}
113724
114598
  }
113725
114599
  }
@@ -114025,7 +114899,7 @@ var mutation_test = createSwarmTool({
114025
114899
  ];
114026
114900
  for (const filePath of uniquePaths) {
114027
114901
  try {
114028
- const resolvedPath = path127.resolve(cwd, filePath);
114902
+ const resolvedPath = path128.resolve(cwd, filePath);
114029
114903
  sourceFiles.set(filePath, fs89.readFileSync(resolvedPath, "utf-8"));
114030
114904
  } catch {}
114031
114905
  }
@@ -114047,22 +114921,22 @@ init_config();
114047
114921
  init_schema();
114048
114922
  init_manager2();
114049
114923
  import * as fs99 from "node:fs";
114050
- import * as path137 from "node:path";
114924
+ import * as path138 from "node:path";
114051
114925
 
114052
114926
  // src/full-auto/phase-approval.ts
114053
114927
  init_utils2();
114054
114928
  init_logger();
114055
114929
  init_state2();
114056
114930
  import * as fs90 from "node:fs";
114057
- import * as path128 from "node:path";
114931
+ import * as path129 from "node:path";
114058
114932
  var APPROVAL_TTL_MS = 24 * 60 * 60 * 1000;
114059
114933
  function readEvidenceDir(directory, phase) {
114060
114934
  try {
114061
- const dirPath = validateSwarmPath(directory, path128.posix.join("evidence", String(phase)));
114935
+ const dirPath = validateSwarmPath(directory, path129.posix.join("evidence", String(phase)));
114062
114936
  if (!fs90.existsSync(dirPath))
114063
114937
  return [];
114064
114938
  const entries = fs90.readdirSync(dirPath);
114065
- return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) => path128.join(dirPath, e));
114939
+ return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) => path129.join(dirPath, e));
114066
114940
  } catch {
114067
114941
  return [];
114068
114942
  }
@@ -114203,16 +115077,16 @@ init_plan_schema();
114203
115077
  init_ledger();
114204
115078
  init_manager();
114205
115079
  import * as fs91 from "node:fs";
114206
- import * as path129 from "node:path";
115080
+ import * as path130 from "node:path";
114207
115081
  async function writeCheckpoint(directory) {
114208
115082
  try {
114209
115083
  const plan = await loadPlan(directory);
114210
115084
  if (!plan)
114211
115085
  return;
114212
- const swarmDir = path129.join(directory, ".swarm");
115086
+ const swarmDir = path130.join(directory, ".swarm");
114213
115087
  fs91.mkdirSync(swarmDir, { recursive: true });
114214
- const jsonPath = path129.join(swarmDir, "SWARM_PLAN.json");
114215
- const mdPath = path129.join(swarmDir, "SWARM_PLAN.md");
115088
+ const jsonPath = path130.join(swarmDir, "SWARM_PLAN.json");
115089
+ const mdPath = path130.join(swarmDir, "SWARM_PLAN.md");
114216
115090
  fs91.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
114217
115091
  const md = derivePlanMarkdown(plan);
114218
115092
  fs91.writeFileSync(mdPath, md, "utf8");
@@ -114231,7 +115105,7 @@ init_telemetry();
114231
115105
  // src/turbo/lean/phase-ready.ts
114232
115106
  init_file_locks();
114233
115107
  import * as fs92 from "node:fs";
114234
- import * as path130 from "node:path";
115108
+ import * as path131 from "node:path";
114235
115109
  init_state3();
114236
115110
  var DEFAULT_CONFIG3 = {
114237
115111
  phase_reviewer: true,
@@ -114240,7 +115114,7 @@ var DEFAULT_CONFIG3 = {
114240
115114
  };
114241
115115
  function defaultReadPlanJson(dir) {
114242
115116
  try {
114243
- const planPath = path130.join(dir, ".swarm", "plan.json");
115117
+ const planPath = path131.join(dir, ".swarm", "plan.json");
114244
115118
  if (!fs92.existsSync(planPath))
114245
115119
  return null;
114246
115120
  const raw = fs92.readFileSync(planPath, "utf-8");
@@ -114255,7 +115129,7 @@ function defaultReadPlanJson(dir) {
114255
115129
  }
114256
115130
  function readReviewerEvidenceFromFile(directory, phase) {
114257
115131
  try {
114258
- const evidencePath = path130.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-reviewer.json");
115132
+ const evidencePath = path131.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-reviewer.json");
114259
115133
  if (!fs92.existsSync(evidencePath)) {
114260
115134
  return null;
114261
115135
  }
@@ -114275,7 +115149,7 @@ function readReviewerEvidenceFromFile(directory, phase) {
114275
115149
  }
114276
115150
  function readCriticEvidenceFromFile(directory, phase) {
114277
115151
  try {
114278
- const evidencePath = path130.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-critic.json");
115152
+ const evidencePath = path131.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-critic.json");
114279
115153
  if (!fs92.existsSync(evidencePath)) {
114280
115154
  return null;
114281
115155
  }
@@ -114294,7 +115168,7 @@ function readCriticEvidenceFromFile(directory, phase) {
114294
115168
  }
114295
115169
  }
114296
115170
  function listLaneEvidenceSync(directory, phase) {
114297
- const evidenceDir = path130.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
115171
+ const evidenceDir = path131.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
114298
115172
  let entries;
114299
115173
  try {
114300
115174
  entries = fs92.readdirSync(evidenceDir);
@@ -114364,7 +115238,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
114364
115238
  ...DEFAULT_CONFIG3,
114365
115239
  ...actualConfig
114366
115240
  };
114367
- const statePath = path130.join(directory, ".swarm", "turbo-state.json");
115241
+ const statePath = path131.join(directory, ".swarm", "turbo-state.json");
114368
115242
  if (!fs92.existsSync(statePath)) {
114369
115243
  return {
114370
115244
  ok: false,
@@ -114552,7 +115426,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
114552
115426
  }
114553
115427
  }
114554
115428
  if (mergedConfig.integrated_diff_required) {
114555
- const evidencePath = path130.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-phase.json");
115429
+ const evidencePath = path131.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-phase.json");
114556
115430
  let hasDiff = false;
114557
115431
  try {
114558
115432
  const content = fs92.readFileSync(evidencePath, "utf-8");
@@ -114704,13 +115578,13 @@ init_qa_gate_profile();
114704
115578
  init_manager();
114705
115579
  init_state();
114706
115580
  import * as fs93 from "node:fs";
114707
- import * as path131 from "node:path";
115581
+ import * as path132 from "node:path";
114708
115582
  async function runDriftGate(ctx) {
114709
115583
  const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
114710
115584
  let driftCheckEnabled = true;
114711
115585
  let driftHasSpecMd = false;
114712
115586
  try {
114713
- const specMdPath = path131.join(dir, ".swarm", "spec.md");
115587
+ const specMdPath = path132.join(dir, ".swarm", "spec.md");
114714
115588
  driftHasSpecMd = fs93.existsSync(specMdPath);
114715
115589
  const gatePlan = await loadPlan(dir);
114716
115590
  if (gatePlan) {
@@ -114738,7 +115612,7 @@ async function runDriftGate(ctx) {
114738
115612
  }
114739
115613
  let phaseType;
114740
115614
  try {
114741
- const planPath = path131.join(dir, ".swarm", "plan.json");
115615
+ const planPath = path132.join(dir, ".swarm", "plan.json");
114742
115616
  if (fs93.existsSync(planPath)) {
114743
115617
  const planRaw = fs93.readFileSync(planPath, "utf-8");
114744
115618
  const plan = JSON.parse(planRaw);
@@ -114757,7 +115631,7 @@ async function runDriftGate(ctx) {
114757
115631
  };
114758
115632
  }
114759
115633
  try {
114760
- const driftEvidencePath = path131.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
115634
+ const driftEvidencePath = path132.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
114761
115635
  let driftVerdictFound = false;
114762
115636
  let driftVerdictApproved = false;
114763
115637
  try {
@@ -114793,7 +115667,7 @@ async function runDriftGate(ctx) {
114793
115667
  let incompleteTaskCount = 0;
114794
115668
  let planParseable = false;
114795
115669
  try {
114796
- const planPath = path131.join(dir, ".swarm", "plan.json");
115670
+ const planPath = path132.join(dir, ".swarm", "plan.json");
114797
115671
  if (fs93.existsSync(planPath)) {
114798
115672
  const planRaw = fs93.readFileSync(planPath, "utf-8");
114799
115673
  const plan = JSON.parse(planRaw);
@@ -114875,7 +115749,7 @@ init_qa_gate_profile();
114875
115749
  init_manager();
114876
115750
  init_state();
114877
115751
  import * as fs94 from "node:fs";
114878
- import * as path132 from "node:path";
115752
+ import * as path133 from "node:path";
114879
115753
  async function runFinalCouncilGate(ctx) {
114880
115754
  const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
114881
115755
  let finalCouncilEnabled = false;
@@ -114892,7 +115766,7 @@ async function runFinalCouncilGate(ctx) {
114892
115766
  const effective = getEffectiveGates(profile, overrides);
114893
115767
  if (effective.final_council === true) {
114894
115768
  finalCouncilEnabled = true;
114895
- const fcPath = path132.join(dir, ".swarm", "evidence", "final-council.json");
115769
+ const fcPath = path133.join(dir, ".swarm", "evidence", "final-council.json");
114896
115770
  let fcVerdictFound = false;
114897
115771
  let _fcVerdict;
114898
115772
  try {
@@ -115022,7 +115896,7 @@ init_qa_gate_profile();
115022
115896
  init_manager();
115023
115897
  init_state();
115024
115898
  import * as fs95 from "node:fs";
115025
- import * as path133 from "node:path";
115899
+ import * as path134 from "node:path";
115026
115900
  async function runHallucinationGate(ctx) {
115027
115901
  const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
115028
115902
  try {
@@ -115035,7 +115909,7 @@ async function runHallucinationGate(ctx) {
115035
115909
  const overrides = session?.qaGateSessionOverrides ?? {};
115036
115910
  const effective = getEffectiveGates(profile, overrides);
115037
115911
  if (effective.hallucination_guard === true) {
115038
- const hgPath = path133.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
115912
+ const hgPath = path134.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
115039
115913
  let hgVerdictFound = false;
115040
115914
  let hgVerdictApproved = false;
115041
115915
  try {
@@ -115098,7 +115972,7 @@ init_qa_gate_profile();
115098
115972
  init_manager();
115099
115973
  init_state();
115100
115974
  import * as fs96 from "node:fs";
115101
- import * as path134 from "node:path";
115975
+ import * as path135 from "node:path";
115102
115976
  async function runMutationGate(ctx) {
115103
115977
  const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
115104
115978
  try {
@@ -115111,7 +115985,7 @@ async function runMutationGate(ctx) {
115111
115985
  const overrides = session?.qaGateSessionOverrides ?? {};
115112
115986
  const effective = getEffectiveGates(profile, overrides);
115113
115987
  if (effective.mutation_test === true) {
115114
- const mgPath = path134.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
115988
+ const mgPath = path135.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
115115
115989
  let mgVerdictFound = false;
115116
115990
  let mgVerdict;
115117
115991
  try {
@@ -115174,7 +116048,7 @@ init_qa_gate_profile();
115174
116048
  init_manager();
115175
116049
  init_state();
115176
116050
  import * as fs97 from "node:fs";
115177
- import * as path135 from "node:path";
116051
+ import * as path136 from "node:path";
115178
116052
  async function runPhaseCouncilGate(ctx) {
115179
116053
  const { phase, dir, sessionID, pluginConfig, agentsDispatched, safeWarn } = ctx;
115180
116054
  let councilModeEnabled = false;
@@ -115189,7 +116063,7 @@ async function runPhaseCouncilGate(ctx) {
115189
116063
  const effective = getEffectiveGates(profile, overrides);
115190
116064
  if (effective.council_mode === true) {
115191
116065
  councilModeEnabled = true;
115192
- const pcPath = path135.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
116066
+ const pcPath = path136.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
115193
116067
  let pcVerdictFound = false;
115194
116068
  let _pcVerdict;
115195
116069
  let pcQuorumSize;
@@ -115704,7 +116578,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
115704
116578
  }
115705
116579
  if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
115706
116580
  try {
115707
- const projectName = path137.basename(dir);
116581
+ const projectName = path138.basename(dir);
115708
116582
  const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
115709
116583
  if (curationResult) {
115710
116584
  const sessionState = swarmState.agentSessions.get(sessionID);
@@ -116147,7 +117021,7 @@ init_utils();
116147
117021
  init_bun_compat();
116148
117022
  init_create_tool();
116149
117023
  import * as fs100 from "node:fs";
116150
- import * as path138 from "node:path";
117024
+ import * as path139 from "node:path";
116151
117025
  var MAX_OUTPUT_BYTES6 = 52428800;
116152
117026
  var AUDIT_TIMEOUT_MS = 120000;
116153
117027
  function isValidEcosystem(value) {
@@ -116175,16 +117049,16 @@ function validateArgs3(args2) {
116175
117049
  function detectEcosystems(directory) {
116176
117050
  const ecosystems = [];
116177
117051
  const cwd = directory;
116178
- if (fs100.existsSync(path138.join(cwd, "package.json"))) {
117052
+ if (fs100.existsSync(path139.join(cwd, "package.json"))) {
116179
117053
  ecosystems.push("npm");
116180
117054
  }
116181
- if (fs100.existsSync(path138.join(cwd, "pyproject.toml")) || fs100.existsSync(path138.join(cwd, "requirements.txt"))) {
117055
+ if (fs100.existsSync(path139.join(cwd, "pyproject.toml")) || fs100.existsSync(path139.join(cwd, "requirements.txt"))) {
116182
117056
  ecosystems.push("pip");
116183
117057
  }
116184
- if (fs100.existsSync(path138.join(cwd, "Cargo.toml"))) {
117058
+ if (fs100.existsSync(path139.join(cwd, "Cargo.toml"))) {
116185
117059
  ecosystems.push("cargo");
116186
117060
  }
116187
- if (fs100.existsSync(path138.join(cwd, "go.mod"))) {
117061
+ if (fs100.existsSync(path139.join(cwd, "go.mod"))) {
116188
117062
  ecosystems.push("go");
116189
117063
  }
116190
117064
  try {
@@ -116193,13 +117067,13 @@ function detectEcosystems(directory) {
116193
117067
  ecosystems.push("dotnet");
116194
117068
  }
116195
117069
  } catch {}
116196
- if (fs100.existsSync(path138.join(cwd, "Gemfile")) || fs100.existsSync(path138.join(cwd, "Gemfile.lock"))) {
117070
+ if (fs100.existsSync(path139.join(cwd, "Gemfile")) || fs100.existsSync(path139.join(cwd, "Gemfile.lock"))) {
116197
117071
  ecosystems.push("ruby");
116198
117072
  }
116199
- if (fs100.existsSync(path138.join(cwd, "pubspec.yaml"))) {
117073
+ if (fs100.existsSync(path139.join(cwd, "pubspec.yaml"))) {
116200
117074
  ecosystems.push("dart");
116201
117075
  }
116202
- if (fs100.existsSync(path138.join(cwd, "composer.lock"))) {
117076
+ if (fs100.existsSync(path139.join(cwd, "composer.lock"))) {
116203
117077
  ecosystems.push("composer");
116204
117078
  }
116205
117079
  return ecosystems;
@@ -116212,7 +117086,7 @@ async function runNpmAudit(directory) {
116212
117086
  stderr: "pipe",
116213
117087
  cwd: directory
116214
117088
  });
116215
- const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
117089
+ const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
116216
117090
  const result = await Promise.race([
116217
117091
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr2]) => ({ stdout: stdout2, stderr: stderr2 })),
116218
117092
  timeoutPromise
@@ -116332,7 +117206,7 @@ async function runPipAudit(directory) {
116332
117206
  stderr: "pipe",
116333
117207
  cwd: directory
116334
117208
  });
116335
- const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
117209
+ const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
116336
117210
  const result = await Promise.race([
116337
117211
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr2]) => ({ stdout: stdout2, stderr: stderr2 })),
116338
117212
  timeoutPromise
@@ -116460,7 +117334,7 @@ async function runCargoAudit(directory) {
116460
117334
  stderr: "pipe",
116461
117335
  cwd: directory
116462
117336
  });
116463
- const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
117337
+ const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
116464
117338
  const result = await Promise.race([
116465
117339
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
116466
117340
  timeoutPromise
@@ -116584,7 +117458,7 @@ async function runGoAudit(directory) {
116584
117458
  stderr: "pipe",
116585
117459
  cwd: directory
116586
117460
  });
116587
- const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
117461
+ const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
116588
117462
  const result = await Promise.race([
116589
117463
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
116590
117464
  timeoutPromise
@@ -116717,7 +117591,7 @@ async function runDotnetAudit(directory) {
116717
117591
  stderr: "pipe",
116718
117592
  cwd: directory
116719
117593
  });
116720
- const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
117594
+ const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
116721
117595
  const result = await Promise.race([
116722
117596
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
116723
117597
  timeoutPromise
@@ -116833,7 +117707,7 @@ async function runBundleAudit(directory) {
116833
117707
  stderr: "pipe",
116834
117708
  cwd: directory
116835
117709
  });
116836
- const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
117710
+ const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
116837
117711
  const result = await Promise.race([
116838
117712
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
116839
117713
  timeoutPromise
@@ -116978,7 +117852,7 @@ async function runDartAudit(directory) {
116978
117852
  stderr: "pipe",
116979
117853
  cwd: directory
116980
117854
  });
116981
- const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
117855
+ const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
116982
117856
  const result = await Promise.race([
116983
117857
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
116984
117858
  timeoutPromise
@@ -117093,7 +117967,7 @@ async function runComposerAudit(directory) {
117093
117967
  stderr: "pipe",
117094
117968
  cwd: directory
117095
117969
  });
117096
- const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
117970
+ const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
117097
117971
  const result = await Promise.race([
117098
117972
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
117099
117973
  timeoutPromise
@@ -117336,7 +118210,7 @@ var pkg_audit = createSwarmTool({
117336
118210
  init_zod();
117337
118211
  init_manager2();
117338
118212
  import * as fs101 from "node:fs";
117339
- import * as path139 from "node:path";
118213
+ import * as path140 from "node:path";
117340
118214
  init_utils();
117341
118215
  init_create_tool();
117342
118216
  var MAX_FILE_SIZE = 1024 * 1024;
@@ -117459,7 +118333,7 @@ function isScaffoldFile(filePath) {
117459
118333
  if (SCAFFOLD_PATH_PATTERNS.some((pattern) => pattern.test(normalizedPath))) {
117460
118334
  return true;
117461
118335
  }
117462
- const filename = path139.basename(filePath);
118336
+ const filename = path140.basename(filePath);
117463
118337
  if (SCAFFOLD_FILENAME_PATTERNS.some((pattern) => pattern.test(filename))) {
117464
118338
  return true;
117465
118339
  }
@@ -117476,7 +118350,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
117476
118350
  if (regex.test(normalizedPath)) {
117477
118351
  return true;
117478
118352
  }
117479
- const filename = path139.basename(filePath);
118353
+ const filename = path140.basename(filePath);
117480
118354
  const filenameRegex = new RegExp(`^${regexPattern}$`, "i");
117481
118355
  if (filenameRegex.test(filename)) {
117482
118356
  return true;
@@ -117485,7 +118359,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
117485
118359
  return false;
117486
118360
  }
117487
118361
  function isParserSupported(filePath) {
117488
- const ext = path139.extname(filePath).toLowerCase();
118362
+ const ext = path140.extname(filePath).toLowerCase();
117489
118363
  return SUPPORTED_PARSER_EXTENSIONS.has(ext);
117490
118364
  }
117491
118365
  function isPlanFile(filePath) {
@@ -117732,9 +118606,9 @@ async function placeholderScan(input, directory) {
117732
118606
  let filesScanned = 0;
117733
118607
  const filesWithFindings = new Set;
117734
118608
  for (const filePath of changed_files) {
117735
- const fullPath = path139.isAbsolute(filePath) ? filePath : path139.resolve(directory, filePath);
117736
- const resolvedDirectory = path139.resolve(directory);
117737
- if (!fullPath.startsWith(resolvedDirectory + path139.sep) && fullPath !== resolvedDirectory) {
118609
+ const fullPath = path140.isAbsolute(filePath) ? filePath : path140.resolve(directory, filePath);
118610
+ const resolvedDirectory = path140.resolve(directory);
118611
+ if (!fullPath.startsWith(resolvedDirectory + path140.sep) && fullPath !== resolvedDirectory) {
117738
118612
  continue;
117739
118613
  }
117740
118614
  if (!fs101.existsSync(fullPath)) {
@@ -117743,7 +118617,7 @@ async function placeholderScan(input, directory) {
117743
118617
  if (isAllowedByGlobs(filePath, allow_globs)) {
117744
118618
  continue;
117745
118619
  }
117746
- const relativeFilePath = path139.relative(directory, fullPath).replace(/\\/g, "/");
118620
+ const relativeFilePath = path140.relative(directory, fullPath).replace(/\\/g, "/");
117747
118621
  if (FILE_ALLOWLIST.some((allowed) => relativeFilePath.endsWith(allowed))) {
117748
118622
  continue;
117749
118623
  }
@@ -117816,7 +118690,7 @@ var placeholder_scan = createSwarmTool({
117816
118690
 
117817
118691
  // src/tools/pre-check-batch.ts
117818
118692
  import * as fs105 from "node:fs";
117819
- import * as path143 from "node:path";
118693
+ import * as path144 from "node:path";
117820
118694
  init_zod();
117821
118695
  init_manager2();
117822
118696
  init_utils();
@@ -117957,7 +118831,7 @@ init_zod();
117957
118831
  init_manager2();
117958
118832
  init_detector();
117959
118833
  import * as fs104 from "node:fs";
117960
- import * as path142 from "node:path";
118834
+ import * as path143 from "node:path";
117961
118835
  import { extname as extname20 } from "node:path";
117962
118836
 
117963
118837
  // src/sast/rules/c.ts
@@ -118673,7 +119547,7 @@ function executeRulesSync(filePath, content, language) {
118673
119547
  // src/sast/semgrep.ts
118674
119548
  import * as child_process9 from "node:child_process";
118675
119549
  import * as fs102 from "node:fs";
118676
- import * as path140 from "node:path";
119550
+ import * as path141 from "node:path";
118677
119551
  var semgrepAvailableCache = null;
118678
119552
  var DEFAULT_RULES_DIR = ".swarm/semgrep-rules";
118679
119553
  var DEFAULT_TIMEOUT_MS3 = 30000;
@@ -118754,7 +119628,7 @@ function mapSemgrepSeverity(severity) {
118754
119628
  }
118755
119629
  }
118756
119630
  async function executeWithTimeout(command, args2, options) {
118757
- return new Promise((resolve47) => {
119631
+ return new Promise((resolve48) => {
118758
119632
  const child = child_process9.spawn(command, args2, {
118759
119633
  shell: false,
118760
119634
  cwd: options.cwd
@@ -118763,7 +119637,7 @@ async function executeWithTimeout(command, args2, options) {
118763
119637
  let stderr = "";
118764
119638
  const timeout = setTimeout(() => {
118765
119639
  child.kill("SIGTERM");
118766
- resolve47({
119640
+ resolve48({
118767
119641
  stdout,
118768
119642
  stderr: "Process timed out",
118769
119643
  exitCode: 124
@@ -118777,7 +119651,7 @@ async function executeWithTimeout(command, args2, options) {
118777
119651
  });
118778
119652
  child.on("close", (code) => {
118779
119653
  clearTimeout(timeout);
118780
- resolve47({
119654
+ resolve48({
118781
119655
  stdout,
118782
119656
  stderr,
118783
119657
  exitCode: code ?? 0
@@ -118785,7 +119659,7 @@ async function executeWithTimeout(command, args2, options) {
118785
119659
  });
118786
119660
  child.on("error", (err2) => {
118787
119661
  clearTimeout(timeout);
118788
- resolve47({
119662
+ resolve48({
118789
119663
  stdout,
118790
119664
  stderr: err2.message,
118791
119665
  exitCode: 1
@@ -118860,7 +119734,7 @@ async function runSemgrep(options) {
118860
119734
  }
118861
119735
  function getRulesDirectory(projectRoot) {
118862
119736
  if (projectRoot) {
118863
- return path140.resolve(projectRoot, DEFAULT_RULES_DIR);
119737
+ return path141.resolve(projectRoot, DEFAULT_RULES_DIR);
118864
119738
  }
118865
119739
  return DEFAULT_RULES_DIR;
118866
119740
  }
@@ -118881,24 +119755,24 @@ init_create_tool();
118881
119755
  init_utils2();
118882
119756
  import * as crypto11 from "node:crypto";
118883
119757
  import * as fs103 from "node:fs";
118884
- import * as path141 from "node:path";
119758
+ import * as path142 from "node:path";
118885
119759
  var BASELINE_SCHEMA_VERSION = "1.0.0";
118886
119760
  var MAX_BASELINE_FINDINGS = 2000;
118887
119761
  var MAX_BASELINE_BYTES = 2 * 1048576;
118888
119762
  var LOCK_RETRY_DELAYS_MS = [50, 100, 200, 400, 800];
118889
119763
  function normalizeFindingPath(directory, file3) {
118890
- const resolved = path141.isAbsolute(file3) ? file3 : path141.resolve(directory, file3);
118891
- const rel = path141.relative(path141.resolve(directory), resolved);
119764
+ const resolved = path142.isAbsolute(file3) ? file3 : path142.resolve(directory, file3);
119765
+ const rel = path142.relative(path142.resolve(directory), resolved);
118892
119766
  return rel.replace(/\\/g, "/");
118893
119767
  }
118894
119768
  function baselineRelPath(phase) {
118895
- return path141.join("evidence", String(phase), "sast-baseline.json");
119769
+ return path142.join("evidence", String(phase), "sast-baseline.json");
118896
119770
  }
118897
119771
  function tempRelPath(phase) {
118898
- return path141.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
119772
+ return path142.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
118899
119773
  }
118900
119774
  function lockRelPath(phase) {
118901
- return path141.join("evidence", String(phase), "sast-baseline.json.lock");
119775
+ return path142.join("evidence", String(phase), "sast-baseline.json.lock");
118902
119776
  }
118903
119777
  function getLine(lines, idx) {
118904
119778
  if (idx < 0 || idx >= lines.length)
@@ -118984,7 +119858,7 @@ async function acquireLock2(lockPath) {
118984
119858
  };
118985
119859
  } catch {
118986
119860
  if (attempt < LOCK_RETRY_DELAYS_MS.length) {
118987
- await new Promise((resolve48) => setTimeout(resolve48, LOCK_RETRY_DELAYS_MS[attempt]));
119861
+ await new Promise((resolve49) => setTimeout(resolve49, LOCK_RETRY_DELAYS_MS[attempt]));
118988
119862
  }
118989
119863
  }
118990
119864
  }
@@ -119019,8 +119893,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
119019
119893
  message: e instanceof Error ? e.message : "Path validation failed"
119020
119894
  };
119021
119895
  }
119022
- fs103.mkdirSync(path141.dirname(baselinePath), { recursive: true });
119023
- fs103.mkdirSync(path141.dirname(tempPath), { recursive: true });
119896
+ fs103.mkdirSync(path142.dirname(baselinePath), { recursive: true });
119897
+ fs103.mkdirSync(path142.dirname(tempPath), { recursive: true });
119024
119898
  const releaseLock = await acquireLock2(lockPath);
119025
119899
  try {
119026
119900
  let existing = null;
@@ -119293,9 +120167,9 @@ async function sastScan(input, directory, config3) {
119293
120167
  _filesSkipped++;
119294
120168
  continue;
119295
120169
  }
119296
- const resolvedPath = path142.isAbsolute(filePath) ? filePath : path142.resolve(directory, filePath);
119297
- const resolvedDirectory = path142.resolve(directory);
119298
- if (!resolvedPath.startsWith(resolvedDirectory + path142.sep) && resolvedPath !== resolvedDirectory) {
120170
+ const resolvedPath = path143.isAbsolute(filePath) ? filePath : path143.resolve(directory, filePath);
120171
+ const resolvedDirectory = path143.resolve(directory);
120172
+ if (!resolvedPath.startsWith(resolvedDirectory + path143.sep) && resolvedPath !== resolvedDirectory) {
119299
120173
  _filesSkipped++;
119300
120174
  continue;
119301
120175
  }
@@ -119610,20 +120484,20 @@ function validatePath(inputPath, baseDir, workspaceDir) {
119610
120484
  let resolved;
119611
120485
  const isWinAbs = isWindowsAbsolutePath(inputPath);
119612
120486
  if (isWinAbs) {
119613
- resolved = path143.win32.resolve(inputPath);
119614
- } else if (path143.isAbsolute(inputPath)) {
119615
- resolved = path143.resolve(inputPath);
120487
+ resolved = path144.win32.resolve(inputPath);
120488
+ } else if (path144.isAbsolute(inputPath)) {
120489
+ resolved = path144.resolve(inputPath);
119616
120490
  } else {
119617
- resolved = path143.resolve(baseDir, inputPath);
120491
+ resolved = path144.resolve(baseDir, inputPath);
119618
120492
  }
119619
- const workspaceResolved = path143.resolve(workspaceDir);
119620
- let relative27;
120493
+ const workspaceResolved = path144.resolve(workspaceDir);
120494
+ let relative28;
119621
120495
  if (isWinAbs) {
119622
- relative27 = path143.win32.relative(workspaceResolved, resolved);
120496
+ relative28 = path144.win32.relative(workspaceResolved, resolved);
119623
120497
  } else {
119624
- relative27 = path143.relative(workspaceResolved, resolved);
120498
+ relative28 = path144.relative(workspaceResolved, resolved);
119625
120499
  }
119626
- if (relative27.startsWith("..")) {
120500
+ if (relative28.startsWith("..")) {
119627
120501
  return "path traversal detected";
119628
120502
  }
119629
120503
  return null;
@@ -119686,7 +120560,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
119686
120560
  if (typeof file3 !== "string") {
119687
120561
  continue;
119688
120562
  }
119689
- const resolvedPath = path143.resolve(file3);
120563
+ const resolvedPath = path144.resolve(file3);
119690
120564
  const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
119691
120565
  if (validationError) {
119692
120566
  continue;
@@ -119843,7 +120717,7 @@ async function runSecretscanWithFiles(files, directory) {
119843
120717
  skippedFiles++;
119844
120718
  continue;
119845
120719
  }
119846
- const resolvedPath = path143.resolve(file3);
120720
+ const resolvedPath = path144.resolve(file3);
119847
120721
  const validationError = validatePath(resolvedPath, directory, directory);
119848
120722
  if (validationError) {
119849
120723
  skippedFiles++;
@@ -119861,7 +120735,7 @@ async function runSecretscanWithFiles(files, directory) {
119861
120735
  };
119862
120736
  }
119863
120737
  for (const file3 of validatedFiles) {
119864
- const ext = path143.extname(file3).toLowerCase();
120738
+ const ext = path144.extname(file3).toLowerCase();
119865
120739
  if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
119866
120740
  skippedFiles++;
119867
120741
  continue;
@@ -120080,7 +120954,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
120080
120954
  const preexistingFindings = [];
120081
120955
  for (const finding of findings) {
120082
120956
  const filePath = finding.location.file;
120083
- const normalised = path143.relative(directory, filePath).replace(/\\/g, "/");
120957
+ const normalised = path144.relative(directory, filePath).replace(/\\/g, "/");
120084
120958
  const changedLines = changedLineRanges.get(normalised);
120085
120959
  if (changedLines?.has(finding.location.line)) {
120086
120960
  newFindings.push(finding);
@@ -120131,7 +121005,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
120131
121005
  warn(`pre_check_batch: Invalid file path: ${file3}`);
120132
121006
  continue;
120133
121007
  }
120134
- changedFiles.push(path143.resolve(directory, file3));
121008
+ changedFiles.push(path144.resolve(directory, file3));
120135
121009
  }
120136
121010
  if (changedFiles.length === 0) {
120137
121011
  warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
@@ -120332,9 +121206,9 @@ var pre_check_batch = createSwarmTool({
120332
121206
  };
120333
121207
  return JSON.stringify(errorResult, null, 2);
120334
121208
  }
120335
- const resolvedDirectory = path143.resolve(typedArgs.directory);
120336
- const workspaceAnchor = path143.resolve(directory);
120337
- if (resolvedDirectory !== workspaceAnchor && resolvedDirectory.startsWith(workspaceAnchor + path143.sep)) {
121209
+ const resolvedDirectory = path144.resolve(typedArgs.directory);
121210
+ const workspaceAnchor = path144.resolve(directory);
121211
+ if (resolvedDirectory !== workspaceAnchor && resolvedDirectory.startsWith(workspaceAnchor + path144.sep)) {
120338
121212
  const subDirError = `directory "${typedArgs.directory}" is a subdirectory of the project root — pre_check_batch requires the project root directory "${workspaceAnchor}"`;
120339
121213
  const subDirResult = {
120340
121214
  gates_passed: false,
@@ -120386,7 +121260,7 @@ var pre_check_batch = createSwarmTool({
120386
121260
 
120387
121261
  // src/tools/repo-map.ts
120388
121262
  init_zod();
120389
- import * as path144 from "node:path";
121263
+ import * as path145 from "node:path";
120390
121264
  init_path_security();
120391
121265
  init_create_tool();
120392
121266
  var VALID_ACTIONS = [
@@ -120411,7 +121285,7 @@ function validateFile(p) {
120411
121285
  return "file contains control characters";
120412
121286
  if (containsPathTraversal(p))
120413
121287
  return "file contains path traversal";
120414
- if (path144.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
121288
+ if (path145.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
120415
121289
  return "file must be a workspace-relative path, not absolute";
120416
121290
  }
120417
121291
  return null;
@@ -120434,8 +121308,8 @@ function ok(action, payload) {
120434
121308
  }
120435
121309
  function toRelativeGraphPath(input, workspaceRoot) {
120436
121310
  const normalized = input.replace(/\\/g, "/");
120437
- if (path144.isAbsolute(normalized)) {
120438
- const rel = path144.relative(workspaceRoot, normalized).replace(/\\/g, "/");
121311
+ if (path145.isAbsolute(normalized)) {
121312
+ const rel = path145.relative(workspaceRoot, normalized).replace(/\\/g, "/");
120439
121313
  return normalizeGraphPath2(rel);
120440
121314
  }
120441
121315
  return normalizeGraphPath2(normalized);
@@ -120581,7 +121455,7 @@ var repo_map = createSwarmTool({
120581
121455
  init_zod();
120582
121456
  init_create_tool();
120583
121457
  import * as fs106 from "node:fs";
120584
- import * as path145 from "node:path";
121458
+ import * as path146 from "node:path";
120585
121459
  var SPEC_FILE = ".swarm/spec.md";
120586
121460
  var EVIDENCE_DIR4 = ".swarm/evidence";
120587
121461
  var OBLIGATION_KEYWORDS2 = ["MUST", "SHOULD", "SHALL"];
@@ -120650,7 +121524,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
120650
121524
  return [];
120651
121525
  }
120652
121526
  for (const entry of entries) {
120653
- const entryPath = path145.join(evidenceDir, entry);
121527
+ const entryPath = path146.join(evidenceDir, entry);
120654
121528
  try {
120655
121529
  const stat9 = fs106.statSync(entryPath);
120656
121530
  if (!stat9.isDirectory()) {
@@ -120666,11 +121540,11 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
120666
121540
  if (entryPhase !== String(phase)) {
120667
121541
  continue;
120668
121542
  }
120669
- const evidenceFilePath = path145.join(entryPath, "evidence.json");
121543
+ const evidenceFilePath = path146.join(entryPath, "evidence.json");
120670
121544
  try {
120671
- const resolvedPath = path145.resolve(evidenceFilePath);
120672
- const evidenceDirResolved = path145.resolve(evidenceDir);
120673
- if (!resolvedPath.startsWith(evidenceDirResolved + path145.sep)) {
121545
+ const resolvedPath = path146.resolve(evidenceFilePath);
121546
+ const evidenceDirResolved = path146.resolve(evidenceDir);
121547
+ if (!resolvedPath.startsWith(evidenceDirResolved + path146.sep)) {
120674
121548
  continue;
120675
121549
  }
120676
121550
  const stat9 = fs106.lstatSync(evidenceFilePath);
@@ -120704,7 +121578,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
120704
121578
  if (Array.isArray(diffEntry.files_changed)) {
120705
121579
  for (const file3 of diffEntry.files_changed) {
120706
121580
  if (typeof file3 === "string") {
120707
- touchedFiles.add(path145.resolve(cwd, file3));
121581
+ touchedFiles.add(path146.resolve(cwd, file3));
120708
121582
  }
120709
121583
  }
120710
121584
  }
@@ -120717,8 +121591,8 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
120717
121591
  }
120718
121592
  function searchFileForKeywords(filePath, keywords, cwd) {
120719
121593
  try {
120720
- const resolvedPath = path145.resolve(filePath);
120721
- const cwdResolved = path145.resolve(cwd);
121594
+ const resolvedPath = path146.resolve(filePath);
121595
+ const cwdResolved = path146.resolve(cwd);
120722
121596
  if (!resolvedPath.startsWith(cwdResolved)) {
120723
121597
  return false;
120724
121598
  }
@@ -120852,7 +121726,7 @@ var req_coverage = createSwarmTool({
120852
121726
  }, null, 2);
120853
121727
  }
120854
121728
  const cwd = inputDirectory || directory;
120855
- const specPath = path145.join(cwd, SPEC_FILE);
121729
+ const specPath = path146.join(cwd, SPEC_FILE);
120856
121730
  let specContent;
120857
121731
  try {
120858
121732
  specContent = fs106.readFileSync(specPath, "utf-8");
@@ -120879,7 +121753,7 @@ var req_coverage = createSwarmTool({
120879
121753
  message: "No FR requirements found in spec.md"
120880
121754
  }, null, 2);
120881
121755
  }
120882
- const evidenceDir = path145.join(cwd, EVIDENCE_DIR4);
121756
+ const evidenceDir = path146.join(cwd, EVIDENCE_DIR4);
120883
121757
  const touchedFiles = readTouchedFiles(evidenceDir, phase, cwd);
120884
121758
  const analyzedRequirements = [];
120885
121759
  let coveredCount = 0;
@@ -120905,7 +121779,7 @@ var req_coverage = createSwarmTool({
120905
121779
  requirements: analyzedRequirements
120906
121780
  };
120907
121781
  const reportFilename = `req-coverage-phase-${phase}.json`;
120908
- const reportPath = path145.join(evidenceDir, reportFilename);
121782
+ const reportPath = path146.join(evidenceDir, reportFilename);
120909
121783
  try {
120910
121784
  if (!fs106.existsSync(evidenceDir)) {
120911
121785
  fs106.mkdirSync(evidenceDir, { recursive: true });
@@ -120995,7 +121869,7 @@ init_qa_gate_profile();
120995
121869
  init_file_locks();
120996
121870
  import * as crypto12 from "node:crypto";
120997
121871
  import * as fs107 from "node:fs";
120998
- import * as path146 from "node:path";
121872
+ import * as path147 from "node:path";
120999
121873
  init_ledger();
121000
121874
  init_manager();
121001
121875
  init_state();
@@ -121076,8 +121950,8 @@ async function executeSavePlan(args2, fallbackDir) {
121076
121950
  };
121077
121951
  }
121078
121952
  if (args2.working_directory && fallbackDir) {
121079
- const resolvedTarget = path146.resolve(args2.working_directory);
121080
- const resolvedRoot = path146.resolve(fallbackDir);
121953
+ const resolvedTarget = path147.resolve(args2.working_directory);
121954
+ const resolvedRoot = path147.resolve(fallbackDir);
121081
121955
  let fallbackExists = false;
121082
121956
  try {
121083
121957
  fs107.accessSync(resolvedRoot, fs107.constants.F_OK);
@@ -121086,7 +121960,7 @@ async function executeSavePlan(args2, fallbackDir) {
121086
121960
  fallbackExists = false;
121087
121961
  }
121088
121962
  if (fallbackExists) {
121089
- const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path146.sep);
121963
+ const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path147.sep);
121090
121964
  if (isSubdirectory) {
121091
121965
  return {
121092
121966
  success: false,
@@ -121102,7 +121976,7 @@ async function executeSavePlan(args2, fallbackDir) {
121102
121976
  let specMtime;
121103
121977
  let specHash;
121104
121978
  if (process.env.SWARM_SKIP_SPEC_GATE !== "1") {
121105
- const specPath = path146.join(targetWorkspace, ".swarm", "spec.md");
121979
+ const specPath = path147.join(targetWorkspace, ".swarm", "spec.md");
121106
121980
  try {
121107
121981
  const stat9 = await fs107.promises.stat(specPath);
121108
121982
  specMtime = stat9.mtime.toISOString();
@@ -121118,7 +121992,7 @@ async function executeSavePlan(args2, fallbackDir) {
121118
121992
  }
121119
121993
  }
121120
121994
  if (process.env.SWARM_SKIP_GATE_SELECTION !== "1") {
121121
- const contextPath = path146.join(targetWorkspace, ".swarm", "context.md");
121995
+ const contextPath = path147.join(targetWorkspace, ".swarm", "context.md");
121122
121996
  let contextContent = "";
121123
121997
  try {
121124
121998
  contextContent = await fs107.promises.readFile(contextPath, "utf8");
@@ -121408,7 +122282,7 @@ async function executeSavePlan(args2, fallbackDir) {
121408
122282
  }
121409
122283
  await writeCheckpoint(dir).catch(() => {});
121410
122284
  try {
121411
- const markerPath = path146.join(dir, ".swarm", ".plan-write-marker");
122285
+ const markerPath = path147.join(dir, ".swarm", ".plan-write-marker");
121412
122286
  const marker = JSON.stringify({
121413
122287
  source: "save_plan",
121414
122288
  timestamp: new Date().toISOString(),
@@ -121431,7 +122305,7 @@ async function executeSavePlan(args2, fallbackDir) {
121431
122305
  return {
121432
122306
  success: true,
121433
122307
  message: "Plan saved successfully",
121434
- plan_path: path146.join(dir, ".swarm", "plan.json"),
122308
+ plan_path: path147.join(dir, ".swarm", "plan.json"),
121435
122309
  phases_count: plan.phases.length,
121436
122310
  tasks_count: tasksCount,
121437
122311
  ...resolvedProfile !== undefined ? { execution_profile: resolvedProfile } : {},
@@ -121498,7 +122372,7 @@ var save_plan = createSwarmTool({
121498
122372
  init_zod();
121499
122373
  init_manager2();
121500
122374
  import * as fs108 from "node:fs";
121501
- import * as path147 from "node:path";
122375
+ import * as path148 from "node:path";
121502
122376
 
121503
122377
  // src/sbom/detectors/index.ts
121504
122378
  init_utils();
@@ -122348,7 +123222,7 @@ function findManifestFiles(rootDir) {
122348
123222
  try {
122349
123223
  const entries = fs108.readdirSync(dir, { withFileTypes: true });
122350
123224
  for (const entry of entries) {
122351
- const fullPath = path147.join(dir, entry.name);
123225
+ const fullPath = path148.join(dir, entry.name);
122352
123226
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
122353
123227
  continue;
122354
123228
  }
@@ -122357,7 +123231,7 @@ function findManifestFiles(rootDir) {
122357
123231
  } else if (entry.isFile()) {
122358
123232
  for (const pattern of patterns) {
122359
123233
  if (simpleGlobToRegex(pattern).test(entry.name)) {
122360
- manifestFiles.push(path147.relative(rootDir, fullPath));
123234
+ manifestFiles.push(path148.relative(rootDir, fullPath));
122361
123235
  break;
122362
123236
  }
122363
123237
  }
@@ -122375,11 +123249,11 @@ function findManifestFilesInDirs(directories, workingDir) {
122375
123249
  try {
122376
123250
  const entries = fs108.readdirSync(dir, { withFileTypes: true });
122377
123251
  for (const entry of entries) {
122378
- const fullPath = path147.join(dir, entry.name);
123252
+ const fullPath = path148.join(dir, entry.name);
122379
123253
  if (entry.isFile()) {
122380
123254
  for (const pattern of patterns) {
122381
123255
  if (simpleGlobToRegex(pattern).test(entry.name)) {
122382
- found.push(path147.relative(workingDir, fullPath));
123256
+ found.push(path148.relative(workingDir, fullPath));
122383
123257
  break;
122384
123258
  }
122385
123259
  }
@@ -122392,11 +123266,11 @@ function findManifestFilesInDirs(directories, workingDir) {
122392
123266
  function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
122393
123267
  const dirs = new Set;
122394
123268
  for (const file3 of changedFiles) {
122395
- let currentDir = path147.dirname(file3);
123269
+ let currentDir = path148.dirname(file3);
122396
123270
  while (true) {
122397
- if (currentDir && currentDir !== "." && currentDir !== path147.sep) {
122398
- dirs.add(path147.join(workingDir, currentDir));
122399
- const parent = path147.dirname(currentDir);
123271
+ if (currentDir && currentDir !== "." && currentDir !== path148.sep) {
123272
+ dirs.add(path148.join(workingDir, currentDir));
123273
+ const parent = path148.dirname(currentDir);
122400
123274
  if (parent === currentDir)
122401
123275
  break;
122402
123276
  currentDir = parent;
@@ -122480,7 +123354,7 @@ var sbom_generate = createSwarmTool({
122480
123354
  const changedFiles = obj.changed_files;
122481
123355
  const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
122482
123356
  const workingDir = directory;
122483
- const outputDir = path147.isAbsolute(relativeOutputDir) ? relativeOutputDir : path147.join(workingDir, relativeOutputDir);
123357
+ const outputDir = path148.isAbsolute(relativeOutputDir) ? relativeOutputDir : path148.join(workingDir, relativeOutputDir);
122484
123358
  let manifestFiles = [];
122485
123359
  if (scope === "all") {
122486
123360
  manifestFiles = findManifestFiles(workingDir);
@@ -122503,7 +123377,7 @@ var sbom_generate = createSwarmTool({
122503
123377
  const processedFiles = [];
122504
123378
  for (const manifestFile of manifestFiles) {
122505
123379
  try {
122506
- const fullPath = path147.isAbsolute(manifestFile) ? manifestFile : path147.join(workingDir, manifestFile);
123380
+ const fullPath = path148.isAbsolute(manifestFile) ? manifestFile : path148.join(workingDir, manifestFile);
122507
123381
  if (!fs108.existsSync(fullPath)) {
122508
123382
  continue;
122509
123383
  }
@@ -122520,7 +123394,7 @@ var sbom_generate = createSwarmTool({
122520
123394
  const bom = generateCycloneDX(allComponents);
122521
123395
  const bomJson = serializeCycloneDX(bom);
122522
123396
  const filename = generateSbomFilename();
122523
- const outputPath = path147.join(outputDir, filename);
123397
+ const outputPath = path148.join(outputDir, filename);
122524
123398
  fs108.writeFileSync(outputPath, bomJson, "utf-8");
122525
123399
  const verdict = processedFiles.length > 0 ? "pass" : "pass";
122526
123400
  try {
@@ -122565,7 +123439,7 @@ var sbom_generate = createSwarmTool({
122565
123439
  init_zod();
122566
123440
  init_create_tool();
122567
123441
  import * as fs109 from "node:fs";
122568
- import * as path148 from "node:path";
123442
+ import * as path149 from "node:path";
122569
123443
  var SPEC_CANDIDATES = [
122570
123444
  "openapi.json",
122571
123445
  "openapi.yaml",
@@ -122597,12 +123471,12 @@ function normalizePath5(p) {
122597
123471
  }
122598
123472
  function discoverSpecFile(cwd, specFileArg) {
122599
123473
  if (specFileArg) {
122600
- const resolvedPath = path148.resolve(cwd, specFileArg);
122601
- const normalizedCwd = cwd.endsWith(path148.sep) ? cwd : cwd + path148.sep;
123474
+ const resolvedPath = path149.resolve(cwd, specFileArg);
123475
+ const normalizedCwd = cwd.endsWith(path149.sep) ? cwd : cwd + path149.sep;
122602
123476
  if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
122603
123477
  throw new Error("Invalid spec_file: path traversal detected");
122604
123478
  }
122605
- const ext = path148.extname(resolvedPath).toLowerCase();
123479
+ const ext = path149.extname(resolvedPath).toLowerCase();
122606
123480
  if (!ALLOWED_EXTENSIONS.includes(ext)) {
122607
123481
  throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
122608
123482
  }
@@ -122616,7 +123490,7 @@ function discoverSpecFile(cwd, specFileArg) {
122616
123490
  return resolvedPath;
122617
123491
  }
122618
123492
  for (const candidate of SPEC_CANDIDATES) {
122619
- const candidatePath = path148.resolve(cwd, candidate);
123493
+ const candidatePath = path149.resolve(cwd, candidate);
122620
123494
  if (fs109.existsSync(candidatePath)) {
122621
123495
  const stats = fs109.statSync(candidatePath);
122622
123496
  if (stats.size <= MAX_SPEC_SIZE) {
@@ -122628,7 +123502,7 @@ function discoverSpecFile(cwd, specFileArg) {
122628
123502
  }
122629
123503
  function parseSpec(specFile) {
122630
123504
  const content = fs109.readFileSync(specFile, "utf-8");
122631
- const ext = path148.extname(specFile).toLowerCase();
123505
+ const ext = path149.extname(specFile).toLowerCase();
122632
123506
  if (ext === ".json") {
122633
123507
  return parseJsonSpec(content);
122634
123508
  }
@@ -122704,7 +123578,7 @@ function extractRoutes(cwd) {
122704
123578
  return;
122705
123579
  }
122706
123580
  for (const entry of entries) {
122707
- const fullPath = path148.join(dir, entry.name);
123581
+ const fullPath = path149.join(dir, entry.name);
122708
123582
  if (entry.isSymbolicLink()) {
122709
123583
  continue;
122710
123584
  }
@@ -122714,7 +123588,7 @@ function extractRoutes(cwd) {
122714
123588
  }
122715
123589
  walkDir(fullPath);
122716
123590
  } else if (entry.isFile()) {
122717
- const ext = path148.extname(entry.name).toLowerCase();
123591
+ const ext = path149.extname(entry.name).toLowerCase();
122718
123592
  const baseName = entry.name.toLowerCase();
122719
123593
  if (![".ts", ".js", ".mjs"].includes(ext)) {
122720
123594
  continue;
@@ -122883,7 +123757,7 @@ init_bun_compat();
122883
123757
  init_path_security();
122884
123758
  init_create_tool();
122885
123759
  import * as fs110 from "node:fs";
122886
- import * as path149 from "node:path";
123760
+ import * as path150 from "node:path";
122887
123761
  var DEFAULT_MAX_RESULTS = 100;
122888
123762
  var DEFAULT_MAX_LINES = 200;
122889
123763
  var REGEX_TIMEOUT_MS = 5000;
@@ -122906,24 +123780,24 @@ function matchesGlobs(filePath, globs) {
122906
123780
  return true;
122907
123781
  return globs.some((glob) => globMatch(glob, filePath));
122908
123782
  }
122909
- var WINDOWS_RESERVED_NAMES3 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
122910
- function containsWindowsAttacks3(str) {
123783
+ var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
123784
+ function containsWindowsAttacks4(str) {
122911
123785
  if (/:[^\\/]/.test(str))
122912
123786
  return true;
122913
123787
  const parts2 = str.split(/[/\\]/);
122914
123788
  for (const part of parts2) {
122915
- if (WINDOWS_RESERVED_NAMES3.test(part))
123789
+ if (WINDOWS_RESERVED_NAMES4.test(part))
122916
123790
  return true;
122917
123791
  }
122918
123792
  return false;
122919
123793
  }
122920
123794
  function isPathInWorkspace3(filePath, workspace) {
122921
123795
  try {
122922
- const resolvedPath = path149.resolve(workspace, filePath);
123796
+ const resolvedPath = path150.resolve(workspace, filePath);
122923
123797
  const realWorkspace = fs110.realpathSync(workspace);
122924
123798
  const realResolvedPath = fs110.realpathSync(resolvedPath);
122925
- const relativePath = path149.relative(realWorkspace, realResolvedPath);
122926
- if (relativePath.startsWith("..") || path149.isAbsolute(relativePath)) {
123799
+ const relativePath = path150.relative(realWorkspace, realResolvedPath);
123800
+ if (relativePath.startsWith("..") || path150.isAbsolute(relativePath)) {
122927
123801
  return false;
122928
123802
  }
122929
123803
  return true;
@@ -122936,11 +123810,11 @@ function validatePathForRead2(filePath, workspace) {
122936
123810
  }
122937
123811
  function findRgInEnvPath() {
122938
123812
  const searchPath = process.env.PATH ?? "";
122939
- for (const dir of searchPath.split(path149.delimiter)) {
123813
+ for (const dir of searchPath.split(path150.delimiter)) {
122940
123814
  if (!dir)
122941
123815
  continue;
122942
123816
  const isWindows = process.platform === "win32";
122943
- const candidate = path149.join(dir, isWindows ? "rg.exe" : "rg");
123817
+ const candidate = path150.join(dir, isWindows ? "rg.exe" : "rg");
122944
123818
  if (fs110.existsSync(candidate))
122945
123819
  return candidate;
122946
123820
  }
@@ -122995,7 +123869,7 @@ async function ripgrepSearch(opts) {
122995
123869
  stderr: "pipe",
122996
123870
  cwd: opts.workspace
122997
123871
  });
122998
- const timeout = new Promise((resolve54) => setTimeout(() => resolve54("timeout"), REGEX_TIMEOUT_MS));
123872
+ const timeout = new Promise((resolve55) => setTimeout(() => resolve55("timeout"), REGEX_TIMEOUT_MS));
122999
123873
  const exitPromise = proc.exited;
123000
123874
  const result = await Promise.race([exitPromise, timeout]);
123001
123875
  if (result === "timeout") {
@@ -123070,8 +123944,8 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
123070
123944
  try {
123071
123945
  const entries = fs110.readdirSync(dir, { withFileTypes: true });
123072
123946
  for (const entry of entries) {
123073
- const fullPath = path149.join(dir, entry.name);
123074
- const relativePath = path149.relative(workspace, fullPath);
123947
+ const fullPath = path150.join(dir, entry.name);
123948
+ const relativePath = path150.relative(workspace, fullPath);
123075
123949
  if (!validatePathForRead2(fullPath, workspace)) {
123076
123950
  continue;
123077
123951
  }
@@ -123112,7 +123986,7 @@ async function fallbackSearch(opts) {
123112
123986
  const matches = [];
123113
123987
  let total = 0;
123114
123988
  for (const file3 of files) {
123115
- const fullPath = path149.join(opts.workspace, file3);
123989
+ const fullPath = path150.join(opts.workspace, file3);
123116
123990
  if (!validatePathForRead2(fullPath, opts.workspace)) {
123117
123991
  continue;
123118
123992
  }
@@ -123225,14 +124099,14 @@ var search = createSwarmTool({
123225
124099
  message: "Exclude pattern contains path traversal sequence"
123226
124100
  }, null, 2);
123227
124101
  }
123228
- if (include && containsWindowsAttacks3(include)) {
124102
+ if (include && containsWindowsAttacks4(include)) {
123229
124103
  return JSON.stringify({
123230
124104
  error: true,
123231
124105
  type: "path-escape",
123232
124106
  message: "Include pattern contains invalid Windows-specific sequence"
123233
124107
  }, null, 2);
123234
124108
  }
123235
- if (exclude && containsWindowsAttacks3(exclude)) {
124109
+ if (exclude && containsWindowsAttacks4(exclude)) {
123236
124110
  return JSON.stringify({
123237
124111
  error: true,
123238
124112
  type: "path-escape",
@@ -123525,7 +124399,7 @@ init_config();
123525
124399
  init_schema();
123526
124400
  init_create_tool();
123527
124401
  import { mkdir as mkdir24, rename as rename10, writeFile as writeFile19 } from "node:fs/promises";
123528
- import * as path150 from "node:path";
124402
+ import * as path151 from "node:path";
123529
124403
  var MAX_SPEC_BYTES = 256 * 1024;
123530
124404
  var spec_write = createSwarmTool({
123531
124405
  description: "Write the canonical project spec to .swarm/spec.md. Atomic write, size-bounded (256 KiB), heading-required. Honors spec_writer.allow_spec_write.",
@@ -123566,8 +124440,8 @@ var spec_write = createSwarmTool({
123566
124440
  reason: 'spec must contain at least one top-level "# Heading"'
123567
124441
  }, null, 2);
123568
124442
  }
123569
- const target = path150.join(directory, ".swarm", "spec.md");
123570
- await mkdir24(path150.dirname(target), { recursive: true });
124443
+ const target = path151.join(directory, ".swarm", "spec.md");
124444
+ await mkdir24(path151.dirname(target), { recursive: true });
123571
124445
  const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
123572
124446
  let finalContent = content;
123573
124447
  if (mode === "append") {
@@ -123596,14 +124470,14 @@ ${content}
123596
124470
  init_zod();
123597
124471
  init_loader();
123598
124472
  import {
123599
- existsSync as existsSync84,
123600
- mkdirSync as mkdirSync35,
123601
- readFileSync as readFileSync71,
123602
- renameSync as renameSync21,
123603
- unlinkSync as unlinkSync19,
123604
- writeFileSync as writeFileSync29
124473
+ existsSync as existsSync85,
124474
+ mkdirSync as mkdirSync36,
124475
+ readFileSync as readFileSync72,
124476
+ renameSync as renameSync22,
124477
+ unlinkSync as unlinkSync20,
124478
+ writeFileSync as writeFileSync30
123605
124479
  } from "node:fs";
123606
- import path151 from "node:path";
124480
+ import path152 from "node:path";
123607
124481
  init_create_tool();
123608
124482
  init_resolve_working_directory();
123609
124483
  var VerdictSchema2 = exports_external.object({
@@ -123733,9 +124607,9 @@ var submit_phase_council_verdicts = createSwarmTool({
123733
124607
  }
123734
124608
  });
123735
124609
  function getPhaseMutationGapFinding(phaseNumber, workingDir) {
123736
- const mutationGatePath = path151.join(workingDir, ".swarm", "evidence", String(phaseNumber), "mutation-gate.json");
124610
+ const mutationGatePath = path152.join(workingDir, ".swarm", "evidence", String(phaseNumber), "mutation-gate.json");
123737
124611
  try {
123738
- const raw = readFileSync71(mutationGatePath, "utf-8");
124612
+ const raw = readFileSync72(mutationGatePath, "utf-8");
123739
124613
  const parsed = JSON.parse(raw);
123740
124614
  const gateEntry = (parsed.entries ?? []).find((entry) => entry?.type === "mutation-gate");
123741
124615
  if (!gateEntry) {
@@ -123795,9 +124669,9 @@ function getPhaseMutationGapFinding(phaseNumber, workingDir) {
123795
124669
  }
123796
124670
  }
123797
124671
  function writePhaseCouncilEvidence(workingDir, synthesis) {
123798
- const evidenceDir = path151.join(workingDir, ".swarm", "evidence", String(synthesis.phaseNumber));
123799
- mkdirSync35(evidenceDir, { recursive: true });
123800
- const evidenceFile = path151.join(evidenceDir, "phase-council.json");
124672
+ const evidenceDir = path152.join(workingDir, ".swarm", "evidence", String(synthesis.phaseNumber));
124673
+ mkdirSync36(evidenceDir, { recursive: true });
124674
+ const evidenceFile = path152.join(evidenceDir, "phase-council.json");
123801
124675
  const evidenceBundle = {
123802
124676
  entries: [
123803
124677
  {
@@ -123830,11 +124704,11 @@ function writePhaseCouncilEvidence(workingDir, synthesis) {
123830
124704
  };
123831
124705
  const tempFile = `${evidenceFile}.tmp-${Date.now()}`;
123832
124706
  try {
123833
- writeFileSync29(tempFile, JSON.stringify(evidenceBundle, null, 2), "utf-8");
123834
- renameSync21(tempFile, evidenceFile);
124707
+ writeFileSync30(tempFile, JSON.stringify(evidenceBundle, null, 2), "utf-8");
124708
+ renameSync22(tempFile, evidenceFile);
123835
124709
  } finally {
123836
- if (existsSync84(tempFile)) {
123837
- unlinkSync19(tempFile);
124710
+ if (existsSync85(tempFile)) {
124711
+ unlinkSync20(tempFile);
123838
124712
  }
123839
124713
  }
123840
124714
  }
@@ -123859,28 +124733,28 @@ init_zod();
123859
124733
  init_path_security();
123860
124734
  init_create_tool();
123861
124735
  import * as fs111 from "node:fs";
123862
- import * as path152 from "node:path";
123863
- var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
123864
- function containsWindowsAttacks4(str) {
124736
+ import * as path153 from "node:path";
124737
+ var WINDOWS_RESERVED_NAMES5 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
124738
+ function containsWindowsAttacks5(str) {
123865
124739
  if (/:[^\\/]/.test(str))
123866
124740
  return true;
123867
124741
  const parts2 = str.split(/[/\\]/);
123868
124742
  for (const part of parts2) {
123869
- if (WINDOWS_RESERVED_NAMES4.test(part))
124743
+ if (WINDOWS_RESERVED_NAMES5.test(part))
123870
124744
  return true;
123871
124745
  }
123872
124746
  return false;
123873
124747
  }
123874
124748
  function isPathInWorkspace4(filePath, workspace) {
123875
124749
  try {
123876
- const resolvedPath = path152.resolve(workspace, filePath);
124750
+ const resolvedPath = path153.resolve(workspace, filePath);
123877
124751
  if (!fs111.existsSync(resolvedPath)) {
123878
124752
  return true;
123879
124753
  }
123880
124754
  const realWorkspace = fs111.realpathSync(workspace);
123881
124755
  const realResolvedPath = fs111.realpathSync(resolvedPath);
123882
- const relativePath = path152.relative(realWorkspace, realResolvedPath);
123883
- if (relativePath.startsWith("..") || path152.isAbsolute(relativePath)) {
124756
+ const relativePath = path153.relative(realWorkspace, realResolvedPath);
124757
+ if (relativePath.startsWith("..") || path153.isAbsolute(relativePath)) {
123884
124758
  return false;
123885
124759
  }
123886
124760
  return true;
@@ -123895,7 +124769,7 @@ function validateFilePath(filePath, workspace) {
123895
124769
  return false;
123896
124770
  if (containsControlChars(filePath))
123897
124771
  return false;
123898
- if (containsWindowsAttacks4(filePath))
124772
+ if (containsWindowsAttacks5(filePath))
123899
124773
  return false;
123900
124774
  return isPathInWorkspace4(filePath, workspace);
123901
124775
  }
@@ -123908,12 +124782,12 @@ function findContextMatch(content, contextBefore, contextAfter, oldContent) {
123908
124782
  if (contextBefore && contextBefore.length > 0) {
123909
124783
  for (let i2 = 0;i2 <= lines.length - contextBefore.length; i2++) {
123910
124784
  const slice = lines.slice(i2, i2 + contextBefore.length);
123911
- if (arraysEqual(slice, contextBefore)) {
124785
+ if (arraysEqual2(slice, contextBefore)) {
123912
124786
  const afterStart = i2 + contextBefore.length;
123913
124787
  if (contextAfter && contextAfter.length > 0) {
123914
124788
  for (let j = afterStart;j <= lines.length - contextAfter.length; j++) {
123915
124789
  const afterSlice = lines.slice(j, j + contextAfter.length);
123916
- if (arraysEqual(afterSlice, contextAfter)) {
124790
+ if (arraysEqual2(afterSlice, contextAfter)) {
123917
124791
  if (j === afterStart) {
123918
124792
  return {
123919
124793
  startLineIndex: i2,
@@ -123926,7 +124800,7 @@ function findContextMatch(content, contextBefore, contextAfter, oldContent) {
123926
124800
  const oldContentLines = oldContent.split(`
123927
124801
  `);
123928
124802
  const betweenLines = lines.slice(afterStart, j);
123929
- if (arraysEqual(betweenLines, oldContentLines)) {
124803
+ if (arraysEqual2(betweenLines, oldContentLines)) {
123930
124804
  return {
123931
124805
  startLineIndex: i2,
123932
124806
  endLineIndex: j - 1,
@@ -123952,7 +124826,7 @@ function findContextMatch(content, contextBefore, contextAfter, oldContent) {
123952
124826
  `);
123953
124827
  for (let k = afterStart;k <= lines.length - oldContentLines.length; k++) {
123954
124828
  const candidate = lines.slice(k, k + oldContentLines.length);
123955
- if (arraysEqual(candidate, oldContentLines)) {
124829
+ if (arraysEqual2(candidate, oldContentLines)) {
123956
124830
  return {
123957
124831
  startLineIndex: i2,
123958
124832
  endLineIndex: k + oldContentLines.length - 1,
@@ -123976,7 +124850,7 @@ function findContextMatch(content, contextBefore, contextAfter, oldContent) {
123976
124850
  } else if (contextAfter && contextAfter.length > 0) {
123977
124851
  for (let j = 0;j <= lines.length - contextAfter.length; j++) {
123978
124852
  const afterSlice = lines.slice(j, j + contextAfter.length);
123979
- if (arraysEqual(afterSlice, contextAfter)) {
124853
+ if (arraysEqual2(afterSlice, contextAfter)) {
123980
124854
  return {
123981
124855
  startLineIndex: 0,
123982
124856
  endLineIndex: j - 1,
@@ -123988,7 +124862,7 @@ function findContextMatch(content, contextBefore, contextAfter, oldContent) {
123988
124862
  }
123989
124863
  return null;
123990
124864
  }
123991
- function arraysEqual(a, b) {
124865
+ function arraysEqual2(a, b) {
123992
124866
  if (a.length !== b.length)
123993
124867
  return false;
123994
124868
  for (let i2 = 0;i2 < a.length; i2++) {
@@ -124088,7 +124962,7 @@ var suggestPatch = createSwarmTool({
124088
124962
  });
124089
124963
  continue;
124090
124964
  }
124091
- const fullPath = path152.resolve(directory, change.file);
124965
+ const fullPath = path153.resolve(directory, change.file);
124092
124966
  if (!fs111.existsSync(fullPath)) {
124093
124967
  errors5.push({
124094
124968
  success: false,
@@ -124492,7 +125366,7 @@ init_zod();
124492
125366
  init_manager2();
124493
125367
  init_detector();
124494
125368
  import * as fs112 from "node:fs";
124495
- import * as path153 from "node:path";
125369
+ import * as path154 from "node:path";
124496
125370
  init_create_tool();
124497
125371
  var MAX_FILE_SIZE2 = 2 * 1024 * 1024;
124498
125372
  var BINARY_CHECK_BYTES = 8192;
@@ -124558,7 +125432,7 @@ async function syntaxCheck(input, directory, config3) {
124558
125432
  if (languages?.length) {
124559
125433
  const lowerLangs = languages.map((l) => l.toLowerCase());
124560
125434
  filesToCheck = filesToCheck.filter((file3) => {
124561
- const ext = path153.extname(file3.path).toLowerCase();
125435
+ const ext = path154.extname(file3.path).toLowerCase();
124562
125436
  const langDef = getLanguageForExtension(ext);
124563
125437
  const fileProfile = getProfileForFile(file3.path);
124564
125438
  const langId = fileProfile?.id || langDef?.id;
@@ -124571,7 +125445,7 @@ async function syntaxCheck(input, directory, config3) {
124571
125445
  let skippedCount = 0;
124572
125446
  for (const fileInfo of filesToCheck) {
124573
125447
  const { path: filePath } = fileInfo;
124574
- const fullPath = path153.isAbsolute(filePath) ? filePath : path153.join(directory, filePath);
125448
+ const fullPath = path154.isAbsolute(filePath) ? filePath : path154.join(directory, filePath);
124575
125449
  const result = {
124576
125450
  path: filePath,
124577
125451
  language: "",
@@ -124620,7 +125494,7 @@ async function syntaxCheck(input, directory, config3) {
124620
125494
  results.push(result);
124621
125495
  continue;
124622
125496
  }
124623
- const ext = path153.extname(filePath).toLowerCase();
125497
+ const ext = path154.extname(filePath).toLowerCase();
124624
125498
  const langDef = getLanguageForExtension(ext);
124625
125499
  result.language = profile?.id || langDef?.id || "unknown";
124626
125500
  const errors5 = extractSyntaxErrors(parser, content);
@@ -124719,7 +125593,7 @@ init_utils();
124719
125593
  init_create_tool();
124720
125594
  init_path_security();
124721
125595
  import * as fs113 from "node:fs";
124722
- import * as path154 from "node:path";
125596
+ import * as path155 from "node:path";
124723
125597
  var MAX_TEXT_LENGTH = 200;
124724
125598
  var MAX_FILE_SIZE_BYTES11 = 1024 * 1024;
124725
125599
  var SUPPORTED_EXTENSIONS4 = new Set([
@@ -124785,9 +125659,9 @@ function validatePathsInput(paths, cwd) {
124785
125659
  return { error: "paths contains path traversal", resolvedPath: null };
124786
125660
  }
124787
125661
  try {
124788
- const resolvedPath = path154.resolve(paths);
124789
- const normalizedCwd = path154.resolve(cwd);
124790
- const normalizedResolved = path154.resolve(resolvedPath);
125662
+ const resolvedPath = path155.resolve(paths);
125663
+ const normalizedCwd = path155.resolve(cwd);
125664
+ const normalizedResolved = path155.resolve(resolvedPath);
124791
125665
  if (!normalizedResolved.startsWith(normalizedCwd)) {
124792
125666
  return {
124793
125667
  error: "paths must be within the current working directory",
@@ -124803,7 +125677,7 @@ function validatePathsInput(paths, cwd) {
124803
125677
  }
124804
125678
  }
124805
125679
  function isSupportedExtension(filePath) {
124806
- const ext = path154.extname(filePath).toLowerCase();
125680
+ const ext = path155.extname(filePath).toLowerCase();
124807
125681
  return SUPPORTED_EXTENSIONS4.has(ext);
124808
125682
  }
124809
125683
  function findSourceFiles3(dir, files = []) {
@@ -124818,7 +125692,7 @@ function findSourceFiles3(dir, files = []) {
124818
125692
  if (SKIP_DIRECTORIES5.has(entry)) {
124819
125693
  continue;
124820
125694
  }
124821
- const fullPath = path154.join(dir, entry);
125695
+ const fullPath = path155.join(dir, entry);
124822
125696
  let stat9;
124823
125697
  try {
124824
125698
  stat9 = fs113.statSync(fullPath);
@@ -124930,7 +125804,7 @@ var todo_extract = createSwarmTool({
124930
125804
  filesToScan.push(scanPath);
124931
125805
  } else {
124932
125806
  const errorResult = {
124933
- error: `unsupported file extension: ${path154.extname(scanPath)}`,
125807
+ error: `unsupported file extension: ${path155.extname(scanPath)}`,
124934
125808
  total: 0,
124935
125809
  byPriority: { high: 0, medium: 0, low: 0 },
124936
125810
  entries: []
@@ -124980,17 +125854,17 @@ init_schema();
124980
125854
  init_qa_gate_profile();
124981
125855
  init_gate_evidence();
124982
125856
  import * as fs117 from "node:fs";
124983
- import * as path158 from "node:path";
125857
+ import * as path159 from "node:path";
124984
125858
 
124985
125859
  // src/hooks/diff-scope.ts
124986
125860
  init_bun_compat();
124987
125861
  import * as fs115 from "node:fs";
124988
- import * as path156 from "node:path";
125862
+ import * as path157 from "node:path";
124989
125863
 
124990
125864
  // src/utils/gitignore-warning.ts
124991
125865
  init_bun_compat();
124992
125866
  import * as fs114 from "node:fs";
124993
- import * as path155 from "node:path";
125867
+ import * as path156 from "node:path";
124994
125868
  var _internals67 = { bunSpawn };
124995
125869
  var _swarmGitExcludedChecked = false;
124996
125870
  function fileCoversSwarm(content) {
@@ -125064,10 +125938,10 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
125064
125938
  const excludeRelPath = excludePathRaw.trim();
125065
125939
  if (!excludeRelPath)
125066
125940
  return;
125067
- const excludePath = path155.isAbsolute(excludeRelPath) ? excludeRelPath : path155.join(directory, excludeRelPath);
125941
+ const excludePath = path156.isAbsolute(excludeRelPath) ? excludeRelPath : path156.join(directory, excludeRelPath);
125068
125942
  if (checkIgnoreExitCode !== 0) {
125069
125943
  try {
125070
- fs114.mkdirSync(path155.dirname(excludePath), { recursive: true });
125944
+ fs114.mkdirSync(path156.dirname(excludePath), { recursive: true });
125071
125945
  let existing = "";
125072
125946
  try {
125073
125947
  existing = fs114.readFileSync(excludePath, "utf8");
@@ -125111,7 +125985,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
125111
125985
  var _internals68 = { bunSpawn };
125112
125986
  function getDeclaredScope(taskId, directory) {
125113
125987
  try {
125114
- const planPath = path156.join(directory, ".swarm", "plan.json");
125988
+ const planPath = path157.join(directory, ".swarm", "plan.json");
125115
125989
  if (!fs115.existsSync(planPath))
125116
125990
  return null;
125117
125991
  const raw = fs115.readFileSync(planPath, "utf-8");
@@ -125217,7 +126091,7 @@ init_telemetry();
125217
126091
  // src/turbo/lean/task-completion.ts
125218
126092
  init_file_locks();
125219
126093
  import * as fs116 from "node:fs";
125220
- import * as path157 from "node:path";
126094
+ import * as path158 from "node:path";
125221
126095
  var _internals69 = {
125222
126096
  listActiveLocks,
125223
126097
  verifyLeanTurboTaskCompletion
@@ -125236,7 +126110,7 @@ var TIER_3_PATTERNS = [
125236
126110
  ];
125237
126111
  function matchesTier3Pattern(files) {
125238
126112
  for (const file3 of files) {
125239
- const fileName = path157.basename(file3);
126113
+ const fileName = path158.basename(file3);
125240
126114
  for (const pattern of TIER_3_PATTERNS) {
125241
126115
  if (pattern.test(fileName)) {
125242
126116
  return true;
@@ -125248,7 +126122,7 @@ function matchesTier3Pattern(files) {
125248
126122
  function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
125249
126123
  let persisted = null;
125250
126124
  try {
125251
- const statePath = path157.join(directory, ".swarm", "turbo-state.json");
126125
+ const statePath = path158.join(directory, ".swarm", "turbo-state.json");
125252
126126
  if (!fs116.existsSync(statePath)) {
125253
126127
  return {
125254
126128
  ok: false,
@@ -125332,11 +126206,11 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
125332
126206
  };
125333
126207
  }
125334
126208
  const phase = runState.phase ?? 0;
125335
- const evidencePath = path157.join(directory, ".swarm", "evidence", String(phase), "lean-turbo", `${lane.laneId}.json`);
125336
- const expectedDir = path157.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
125337
- const resolvedPath = path157.resolve(evidencePath);
125338
- const resolvedDir = path157.resolve(expectedDir);
125339
- if (!resolvedPath.startsWith(resolvedDir + path157.sep) && resolvedPath !== resolvedDir) {
126209
+ const evidencePath = path158.join(directory, ".swarm", "evidence", String(phase), "lean-turbo", `${lane.laneId}.json`);
126210
+ const expectedDir = path158.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
126211
+ const resolvedPath = path158.resolve(evidencePath);
126212
+ const resolvedDir = path158.resolve(expectedDir);
126213
+ if (!resolvedPath.startsWith(resolvedDir + path158.sep) && resolvedPath !== resolvedDir) {
125340
126214
  return {
125341
126215
  ok: false,
125342
126216
  reason: `Lane ID causes path traversal: ${lane.laneId}`,
@@ -125376,7 +126250,7 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
125376
126250
  }
125377
126251
  let filesTouched = [];
125378
126252
  try {
125379
- const planPath = path157.join(directory, ".swarm", "plan.json");
126253
+ const planPath = path158.join(directory, ".swarm", "plan.json");
125380
126254
  const planRaw = fs116.readFileSync(planPath, "utf-8");
125381
126255
  const plan = JSON.parse(planRaw);
125382
126256
  for (const planPhase of plan.phases ?? []) {
@@ -125460,7 +126334,7 @@ var TIER_3_PATTERNS2 = [
125460
126334
  ];
125461
126335
  function matchesTier3Pattern2(files) {
125462
126336
  for (const file3 of files) {
125463
- const fileName = path158.basename(file3);
126337
+ const fileName = path159.basename(file3);
125464
126338
  for (const pattern of TIER_3_PATTERNS2) {
125465
126339
  if (pattern.test(fileName)) {
125466
126340
  return true;
@@ -125499,7 +126373,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
125499
126373
  if (!skipStandardTurboBypass && hasActiveTurboMode()) {
125500
126374
  const resolvedDir2 = workingDirectory;
125501
126375
  try {
125502
- const planPath = path158.join(resolvedDir2, ".swarm", "plan.json");
126376
+ const planPath = path159.join(resolvedDir2, ".swarm", "plan.json");
125503
126377
  const planRaw = fs117.readFileSync(planPath, "utf-8");
125504
126378
  const plan = JSON.parse(planRaw);
125505
126379
  for (const planPhase of plan.phases ?? []) {
@@ -125577,7 +126451,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
125577
126451
  }
125578
126452
  if (resolvedDir) {
125579
126453
  try {
125580
- const planPath = path158.join(resolvedDir, ".swarm", "plan.json");
126454
+ const planPath = path159.join(resolvedDir, ".swarm", "plan.json");
125581
126455
  const planRaw = fs117.readFileSync(planPath, "utf-8");
125582
126456
  const plan = JSON.parse(planRaw);
125583
126457
  for (const planPhase of plan.phases ?? []) {
@@ -125813,7 +126687,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
125813
126687
  };
125814
126688
  }
125815
126689
  directory = resolveResult.directory;
125816
- const planPath = path158.join(directory, ".swarm", "plan.json");
126690
+ const planPath = path159.join(directory, ".swarm", "plan.json");
125817
126691
  if (!fs117.existsSync(planPath)) {
125818
126692
  return {
125819
126693
  success: false,
@@ -125822,9 +126696,9 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
125822
126696
  };
125823
126697
  }
125824
126698
  if (fallbackDir && directory !== fallbackDir) {
125825
- const canonicalDir = fs117.realpathSync(path158.resolve(directory));
125826
- const canonicalRoot = fs117.realpathSync(path158.resolve(fallbackDir));
125827
- if (canonicalDir.startsWith(canonicalRoot + path158.sep)) {
126699
+ const canonicalDir = fs117.realpathSync(path159.resolve(directory));
126700
+ const canonicalRoot = fs117.realpathSync(path159.resolve(fallbackDir));
126701
+ if (canonicalDir.startsWith(canonicalRoot + path159.sep)) {
125828
126702
  return {
125829
126703
  success: false,
125830
126704
  message: `Invalid working_directory: "${directory}" is a subdirectory of ` + `the project root "${fallbackDir}". Pass the project root path or ` + `omit working_directory entirely.`,
@@ -125836,8 +126710,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
125836
126710
  }
125837
126711
  if (args2.status === "in_progress") {
125838
126712
  try {
125839
- const evidencePath = path158.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
125840
- fs117.mkdirSync(path158.dirname(evidencePath), { recursive: true });
126713
+ const evidencePath = path159.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
126714
+ fs117.mkdirSync(path159.dirname(evidencePath), { recursive: true });
125841
126715
  const fd = fs117.openSync(evidencePath, "wx");
125842
126716
  let writeOk = false;
125843
126717
  try {
@@ -125861,7 +126735,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
125861
126735
  recoverTaskStateFromDelegations(args2.task_id, directory);
125862
126736
  let phaseRequiresReviewer = true;
125863
126737
  try {
125864
- const planPath2 = path158.join(directory, ".swarm", "plan.json");
126738
+ const planPath2 = path159.join(directory, ".swarm", "plan.json");
125865
126739
  const planRaw = fs117.readFileSync(planPath2, "utf-8");
125866
126740
  const plan = JSON.parse(planRaw);
125867
126741
  const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
@@ -126090,7 +126964,7 @@ init_utils2();
126090
126964
  init_redaction();
126091
126965
  import { createHash as createHash12 } from "node:crypto";
126092
126966
  import { appendFile as appendFile14, mkdir as mkdir25 } from "node:fs/promises";
126093
- import * as path159 from "node:path";
126967
+ import * as path160 from "node:path";
126094
126968
  var EVIDENCE_CACHE_FILE = "evidence-cache/documents.jsonl";
126095
126969
  var MAX_EVIDENCE_TEXT_LENGTH = 4000;
126096
126970
  async function writeEvidenceDocuments(directory, inputs, now = () => new Date) {
@@ -126098,7 +126972,7 @@ async function writeEvidenceDocuments(directory, inputs, now = () => new Date) {
126098
126972
  const capturedAt = now().toISOString();
126099
126973
  const records = inputs.map((input) => createEvidenceDocumentRecord(input, capturedAt)).filter((record3) => record3 !== null);
126100
126974
  if (records.length > 0) {
126101
- await mkdir25(path159.dirname(filePath), { recursive: true });
126975
+ await mkdir25(path160.dirname(filePath), { recursive: true });
126102
126976
  await appendFile14(filePath, `${records.map((record3) => JSON.stringify(record3)).join(`
126103
126977
  `)}
126104
126978
  `, "utf-8");
@@ -126295,7 +127169,7 @@ init_schema3();
126295
127169
  init_store();
126296
127170
  init_create_tool();
126297
127171
  init_resolve_working_directory();
126298
- import * as path160 from "node:path";
127172
+ import * as path161 from "node:path";
126299
127173
  var FindingSchema2 = exports_external.object({
126300
127174
  severity: exports_external.enum(["low", "medium", "high", "critical"]),
126301
127175
  category: exports_external.string().min(1),
@@ -126359,7 +127233,7 @@ var write_architecture_supervisor_evidence = createSwarmTool({
126359
127233
  if (config3.architectural_supervision?.persist_knowledge_recommendations && args2.knowledge_recommendations.length > 0) {
126360
127234
  const knowledgeConfig = KnowledgeConfigSchema.parse(config3.knowledge ?? {});
126361
127235
  const lessons = args2.knowledge_recommendations.map((r) => r.lesson);
126362
- const result = await curateAndStoreSwarm(lessons, path160.basename(dirResult.directory), { phase_number: args2.phase }, dirResult.directory, knowledgeConfig, { skipAutoPromotion: true });
127236
+ const result = await curateAndStoreSwarm(lessons, path161.basename(dirResult.directory), { phase_number: args2.phase }, dirResult.directory, knowledgeConfig, { skipAutoPromotion: true });
126363
127237
  knowledgeProposed = result.stored;
126364
127238
  }
126365
127239
  } catch {}
@@ -126395,7 +127269,7 @@ init_ledger();
126395
127269
  init_manager();
126396
127270
  init_create_tool();
126397
127271
  import fs118 from "node:fs";
126398
- import path161 from "node:path";
127272
+ import path162 from "node:path";
126399
127273
  function normalizeVerdict(verdict) {
126400
127274
  switch (verdict) {
126401
127275
  case "APPROVED":
@@ -126443,7 +127317,7 @@ async function executeWriteDriftEvidence(args2, directory) {
126443
127317
  entries: [evidenceEntry]
126444
127318
  };
126445
127319
  const filename = "drift-verifier.json";
126446
- const relativePath = path161.join("evidence", String(phase), filename);
127320
+ const relativePath = path162.join("evidence", String(phase), filename);
126447
127321
  let validatedPath;
126448
127322
  try {
126449
127323
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -126454,10 +127328,10 @@ async function executeWriteDriftEvidence(args2, directory) {
126454
127328
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
126455
127329
  }, null, 2);
126456
127330
  }
126457
- const evidenceDir = path161.dirname(validatedPath);
127331
+ const evidenceDir = path162.dirname(validatedPath);
126458
127332
  try {
126459
127333
  await fs118.promises.mkdir(evidenceDir, { recursive: true });
126460
- const tempPath = path161.join(evidenceDir, `.${filename}.tmp`);
127334
+ const tempPath = path162.join(evidenceDir, `.${filename}.tmp`);
126461
127335
  await fs118.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
126462
127336
  await fs118.promises.rename(tempPath, validatedPath);
126463
127337
  let snapshotInfo;
@@ -126554,7 +127428,7 @@ var write_drift_evidence = createSwarmTool({
126554
127428
  init_zod();
126555
127429
  init_loader();
126556
127430
  import fs119 from "node:fs";
126557
- import path162 from "node:path";
127431
+ import path163 from "node:path";
126558
127432
  init_utils2();
126559
127433
  init_manager();
126560
127434
  init_create_tool();
@@ -126642,7 +127516,7 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
126642
127516
  timestamp: synthesis.timestamp
126643
127517
  };
126644
127518
  const filename = "final-council.json";
126645
- const relativePath = path162.join("evidence", filename);
127519
+ const relativePath = path163.join("evidence", filename);
126646
127520
  let validatedPath;
126647
127521
  try {
126648
127522
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -126656,10 +127530,10 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
126656
127530
  const evidenceContent = {
126657
127531
  entries: [evidenceEntry]
126658
127532
  };
126659
- const evidenceDir = path162.dirname(validatedPath);
127533
+ const evidenceDir = path163.dirname(validatedPath);
126660
127534
  try {
126661
127535
  await fs119.promises.mkdir(evidenceDir, { recursive: true });
126662
- const tempPath = path162.join(evidenceDir, `.${filename}.tmp`);
127536
+ const tempPath = path163.join(evidenceDir, `.${filename}.tmp`);
126663
127537
  await fs119.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
126664
127538
  await fs119.promises.rename(tempPath, validatedPath);
126665
127539
  return JSON.stringify({
@@ -126719,7 +127593,7 @@ init_zod();
126719
127593
  init_utils2();
126720
127594
  init_create_tool();
126721
127595
  import fs120 from "node:fs";
126722
- import path163 from "node:path";
127596
+ import path164 from "node:path";
126723
127597
  function normalizeVerdict2(verdict) {
126724
127598
  switch (verdict) {
126725
127599
  case "APPROVED":
@@ -126767,7 +127641,7 @@ async function executeWriteHallucinationEvidence(args2, directory) {
126767
127641
  entries: [evidenceEntry]
126768
127642
  };
126769
127643
  const filename = "hallucination-guard.json";
126770
- const relativePath = path163.join("evidence", String(phase), filename);
127644
+ const relativePath = path164.join("evidence", String(phase), filename);
126771
127645
  let validatedPath;
126772
127646
  try {
126773
127647
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -126778,10 +127652,10 @@ async function executeWriteHallucinationEvidence(args2, directory) {
126778
127652
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
126779
127653
  }, null, 2);
126780
127654
  }
126781
- const evidenceDir = path163.dirname(validatedPath);
127655
+ const evidenceDir = path164.dirname(validatedPath);
126782
127656
  try {
126783
127657
  await fs120.promises.mkdir(evidenceDir, { recursive: true });
126784
- const tempPath = path163.join(evidenceDir, `.${filename}.tmp`);
127658
+ const tempPath = path164.join(evidenceDir, `.${filename}.tmp`);
126785
127659
  await fs120.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
126786
127660
  await fs120.promises.rename(tempPath, validatedPath);
126787
127661
  return JSON.stringify({
@@ -126831,7 +127705,7 @@ init_zod();
126831
127705
  init_utils2();
126832
127706
  init_create_tool();
126833
127707
  import fs121 from "node:fs";
126834
- import path164 from "node:path";
127708
+ import path165 from "node:path";
126835
127709
  function normalizeVerdict3(verdict) {
126836
127710
  switch (verdict) {
126837
127711
  case "PASS":
@@ -126905,7 +127779,7 @@ async function executeWriteMutationEvidence(args2, directory) {
126905
127779
  entries: [evidenceEntry]
126906
127780
  };
126907
127781
  const filename = "mutation-gate.json";
126908
- const relativePath = path164.join("evidence", String(phase), filename);
127782
+ const relativePath = path165.join("evidence", String(phase), filename);
126909
127783
  let validatedPath;
126910
127784
  try {
126911
127785
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -126916,10 +127790,10 @@ async function executeWriteMutationEvidence(args2, directory) {
126916
127790
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
126917
127791
  }, null, 2);
126918
127792
  }
126919
- const evidenceDir = path164.dirname(validatedPath);
127793
+ const evidenceDir = path165.dirname(validatedPath);
126920
127794
  try {
126921
127795
  await fs121.promises.mkdir(evidenceDir, { recursive: true });
126922
- const tempPath = path164.join(evidenceDir, `.${filename}.tmp`);
127796
+ const tempPath = path165.join(evidenceDir, `.${filename}.tmp`);
126923
127797
  await fs121.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
126924
127798
  await fs121.promises.rename(tempPath, validatedPath);
126925
127799
  return JSON.stringify({
@@ -127055,7 +127929,8 @@ var TOOL_MANIFEST = defineHandlers({
127055
127929
  lean_turbo_runner_status: () => lean_turbo_runner_status,
127056
127930
  lean_turbo_review: () => lean_turbo_review,
127057
127931
  lean_turbo_run_phase: () => lean_turbo_run_phase,
127058
- lean_turbo_status: () => lean_turbo_status
127932
+ lean_turbo_status: () => lean_turbo_status,
127933
+ apply_patch: () => applyPatch
127059
127934
  });
127060
127935
 
127061
127936
  // src/tools/plugin-registration.ts
@@ -127366,7 +128241,7 @@ async function initializeOpenCodeSwarm(ctx) {
127366
128241
  const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
127367
128242
  preflightTriggerManager = new PTM(automationConfig);
127368
128243
  const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
127369
- const swarmDir = path166.resolve(ctx.directory, ".swarm");
128244
+ const swarmDir = path167.resolve(ctx.directory, ".swarm");
127370
128245
  statusArtifact = new ASA(swarmDir);
127371
128246
  statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
127372
128247
  if (automationConfig.capabilities?.evidence_auto_summaries === true) {
@@ -127880,7 +128755,7 @@ ${promptRaw}`;
127880
128755
  const meta3 = readSkillMetadata(s.skillPath, ctx.directory);
127881
128756
  let desc = meta3.description || "";
127882
128757
  if (!desc || desc === "No description provided") {
127883
- desc = path166.basename(path166.dirname(s.skillPath));
128758
+ desc = path167.basename(path167.dirname(s.skillPath));
127884
128759
  }
127885
128760
  desc = desc.replace(/,/g, ";");
127886
128761
  return `file:${s.skillPath} (-- ${desc})`;
@@ -127890,7 +128765,7 @@ ${promptRaw}`;
127890
128765
 
127891
128766
  ${promptRaw}`;
127892
128767
  argsRecord.prompt = newPrompt;
127893
- const skillNames = topSkills.map((s) => `${path166.basename(s.skillPath)} (score: ${s.score.toFixed(2)})`).join(", ");
128768
+ const skillNames = topSkills.map((s) => `${path167.basename(s.skillPath)} (score: ${s.score.toFixed(2)})`).join(", ");
127894
128769
  console.warn(`[skill-propagation-gate] Injected skills: ${skillNames}`);
127895
128770
  for (const skill of topSkills) {
127896
128771
  try {