opencode-swarm 7.49.0 → 7.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/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.0",
72
+ version: "7.50.0",
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);
@@ -84420,7 +84424,8 @@ Before reviewing the plan, check whether it was silently mutated since last crit
84420
84424
  2. Examine the response:
84421
84425
  - If \`success: false\` with \`reason: "no_approved_snapshot"\`: this is the first plan or no prior approval exists. Note this and proceed with plan review.
84422
84426
  - If \`drift_detected: false\`: baseline integrity confirmed — the plan has not been mutated since the last critic approval. Proceed with plan review.
84423
- - If \`drift_detected: true\`: CRITICAL finding — plan mutated after approval. Compare \`approved_plan\` vs \`current_plan\` to identify what changed (phases added/removed, tasks modified, scope changes). Report findings in a \`## BASELINE DRIFT\` section before the rubric assessment.
84427
+ - If \`drift_detected: true\` AND \`approved_plan\` is defined: CRITICAL finding — plan mutated after approval. Compare \`approved_plan\` vs \`current_plan\` to identify what changed (phases added/removed, tasks modified, scope changes). Report findings in a \`## BASELINE DRIFT\` section before the rubric assessment.
84428
+ - If \`drift_detected: true\` AND \`approved_plan\` is undefined but \`current_plan_error\` is present: CRITICAL finding — plan identity was mutated (tampering detected). Report \`current_plan_error\` as primary evidence; state that direct comparison is unavailable due to identity mutation. Report findings in a \`## BASELINE DRIFT\` section before the rubric assessment.
84424
84429
  - If \`drift_detected: "unknown"\`: flag as warning and proceed with caution.
84425
84430
  3. Report spec-intent divergence: compare the approved baseline intent against what the current plan actually does, not just structural diff. Identify if the plan's purpose or scope has drifted from the original approved intent.
84426
84431
 
@@ -84606,7 +84611,8 @@ Before reviewing individual tasks, check whether the plan itself was silently mu
84606
84611
  2. Examine the response:
84607
84612
  - If \`success: false\` with \`reason: "no_approved_snapshot"\`: this is likely the first phase or no prior approval exists. Note this and proceed to per-task review.
84608
84613
  - If \`drift_detected: false\`: baseline integrity confirmed — the plan has not been mutated since the last critic approval. Proceed to per-task review.
84609
- - If \`drift_detected: true\`: the plan was mutated after critic approval. Compare \`approved_plan\` vs \`current_plan\` to identify what changed (phases added/removed, tasks modified, scope changes). Report findings in a \`## BASELINE DRIFT\` section before the per-task rubric.
84614
+ - If \`drift_detected: true\` AND \`approved_plan\` is defined: CRITICAL finding — plan mutated after approval. Compare \`approved_plan\` vs \`current_plan\` to identify what changed (phases added/removed, tasks modified, scope changes). Report findings in a \`## BASELINE DRIFT\` section before the per-task rubric.
84615
+ - If \`drift_detected: true\` AND \`approved_plan\` is undefined but \`current_plan_error\` is present: CRITICAL finding — plan identity was mutated (tampering detected). Report \`current_plan_error\` as primary evidence; state that direct comparison is unavailable due to identity mutation. Report findings in a \`## BASELINE DRIFT\` section before the per-task rubric.
84610
84616
  - If \`drift_detected: "unknown"\`: current plan.json is unavailable. Flag this as a warning and proceed.
84611
84617
  3. If baseline drift is detected, this is a CRITICAL finding — plan mutations after approval bypass the quality gate.
84612
84618
  4. EXECUTION PROFILE DRIFT: If the \`get_approved_plan\` response includes \`execution_profile\` (on \`approved_plan\`) and the current plan also has \`execution_profile\`, compare them. If they differ and the approved profile was locked, flag as CRITICAL (locked profiles are immutable — a change indicates tampering or plan reset without re-approval). If the current plan has lost its execution_profile entirely when the approved plan had a locked one, flag as CRITICAL.
@@ -92312,7 +92318,7 @@ __export(exports_design_doc_drift, {
92312
92318
  _internals: () => _internals60
92313
92319
  });
92314
92320
  import * as fs98 from "node:fs";
92315
- import * as path136 from "node:path";
92321
+ import * as path137 from "node:path";
92316
92322
  function mtimeMsOrNull(absPath) {
92317
92323
  try {
92318
92324
  return fs98.statSync(absPath).mtimeMs;
@@ -92323,35 +92329,35 @@ function mtimeMsOrNull(absPath) {
92323
92329
  function resolveAnchorWithin(directory, anchor) {
92324
92330
  if (!anchor || typeof anchor !== "string")
92325
92331
  return null;
92326
- const root = path136.resolve(directory);
92327
- const resolved = path136.resolve(root, anchor);
92328
- const rel = path136.relative(root, resolved);
92329
- if (rel.startsWith("..") || path136.isAbsolute(rel))
92332
+ const root = path137.resolve(directory);
92333
+ const resolved = path137.resolve(root, anchor);
92334
+ const rel = path137.relative(root, resolved);
92335
+ if (rel.startsWith("..") || path137.isAbsolute(rel))
92330
92336
  return null;
92331
92337
  return resolved;
92332
92338
  }
92333
92339
  async function runDesignDocDriftCheck(directory, phase, outDir) {
92334
92340
  try {
92335
- const root = path136.resolve(directory);
92336
- const outAbs = path136.resolve(root, outDir);
92337
- const outRel = path136.relative(root, outAbs);
92338
- if (outRel.startsWith("..") || path136.isAbsolute(outRel)) {
92341
+ const root = path137.resolve(directory);
92342
+ const outAbs = path137.resolve(root, outDir);
92343
+ const outRel = path137.relative(root, outAbs);
92344
+ if (outRel.startsWith("..") || path137.isAbsolute(outRel)) {
92339
92345
  return null;
92340
92346
  }
92341
92347
  const docMtimes = new Map;
92342
92348
  const checkedDocs = [];
92343
92349
  const missingDocs = [];
92344
92350
  for (const [docName, relFile] of Object.entries(DESIGN_DOC_FILES)) {
92345
- const abs = path136.join(outAbs, relFile);
92351
+ const abs = path137.join(outAbs, relFile);
92346
92352
  const mtime = mtimeMsOrNull(abs);
92347
92353
  docMtimes.set(docName, mtime);
92348
92354
  if (mtime === null) {
92349
- missingDocs.push(path136.join(outDir, relFile));
92355
+ missingDocs.push(path137.join(outDir, relFile));
92350
92356
  } else {
92351
- checkedDocs.push(path136.join(outDir, relFile));
92357
+ checkedDocs.push(path137.join(outDir, relFile));
92352
92358
  }
92353
92359
  }
92354
- const traceabilityAbs = path136.join(outAbs, TRACEABILITY_REL);
92360
+ const traceabilityAbs = path137.join(outAbs, TRACEABILITY_REL);
92355
92361
  let registry3 = null;
92356
92362
  try {
92357
92363
  const stat9 = await fs98.promises.stat(traceabilityAbs);
@@ -92364,7 +92370,7 @@ async function runDesignDocDriftCheck(directory, phase, outDir) {
92364
92370
  registry3 = null;
92365
92371
  }
92366
92372
  const noDocs = checkedDocs.length === 0 || registry3 === null;
92367
- const specMtime = mtimeMsOrNull(path136.join(root, ".swarm", "spec.md"));
92373
+ const specMtime = mtimeMsOrNull(path137.join(root, ".swarm", "spec.md"));
92368
92374
  const staleSections = [];
92369
92375
  if (!noDocs && Array.isArray(registry3?.sections)) {
92370
92376
  for (const section of registry3.sections) {
@@ -92420,7 +92426,7 @@ async function runDesignDocDriftCheck(directory, phase, outDir) {
92420
92426
  };
92421
92427
  const filename = `${DOC_DRIFT_REPORT_PREFIX}${phase}.json`;
92422
92428
  const filePath = validateSwarmPath(directory, filename);
92423
- await fs98.promises.mkdir(path136.dirname(filePath), { recursive: true });
92429
+ await fs98.promises.mkdir(path137.dirname(filePath), { recursive: true });
92424
92430
  await fs98.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
92425
92431
  getGlobalEventBus().publish("curator.docdrift.completed", {
92426
92432
  phase,
@@ -92451,10 +92457,10 @@ var init_design_doc_drift = __esm(() => {
92451
92457
  domain: "domain.md",
92452
92458
  "technical-spec": "technical-spec.md",
92453
92459
  "behavior-spec": "behavior-spec.md",
92454
- "reference-impl": path136.join("reference", "reference-impl.md"),
92455
- "idiom-notes": path136.join("reference", "idiom-notes.md")
92460
+ "reference-impl": path137.join("reference", "reference-impl.md"),
92461
+ "idiom-notes": path137.join("reference", "idiom-notes.md")
92456
92462
  };
92457
- TRACEABILITY_REL = path136.join("reference", "traceability.json");
92463
+ TRACEABILITY_REL = path137.join("reference", "traceability.json");
92458
92464
  _internals60 = {
92459
92465
  mtimeMsOrNull,
92460
92466
  resolveAnchorWithin,
@@ -92470,7 +92476,7 @@ __export(exports_project_context, {
92470
92476
  LANG_BACKEND_DETECTION_TIMEOUT_MS: () => LANG_BACKEND_DETECTION_TIMEOUT_MS
92471
92477
  });
92472
92478
  import * as fs122 from "node:fs";
92473
- import * as path165 from "node:path";
92479
+ import * as path166 from "node:path";
92474
92480
  function detectFileExists2(directory, pattern) {
92475
92481
  if (pattern.includes("*") || pattern.includes("?")) {
92476
92482
  try {
@@ -92482,7 +92488,7 @@ function detectFileExists2(directory, pattern) {
92482
92488
  }
92483
92489
  }
92484
92490
  try {
92485
- fs122.accessSync(path165.join(directory, pattern));
92491
+ fs122.accessSync(path166.join(directory, pattern));
92486
92492
  return true;
92487
92493
  } catch {
92488
92494
  return false;
@@ -92491,7 +92497,7 @@ function detectFileExists2(directory, pattern) {
92491
92497
  function selectTestCommandFromScriptsTest(backend, directory) {
92492
92498
  let pkgRaw;
92493
92499
  try {
92494
- pkgRaw = fs122.readFileSync(path165.join(directory, "package.json"), "utf-8");
92500
+ pkgRaw = fs122.readFileSync(path166.join(directory, "package.json"), "utf-8");
92495
92501
  } catch {
92496
92502
  return null;
92497
92503
  }
@@ -92600,7 +92606,7 @@ var init_project_context = __esm(() => {
92600
92606
  init_package();
92601
92607
  init_agents2();
92602
92608
  init_critic();
92603
- import * as path166 from "node:path";
92609
+ import * as path167 from "node:path";
92604
92610
 
92605
92611
  // src/background/index.ts
92606
92612
  init_event_bus();
@@ -95825,7 +95831,10 @@ function validateGraphEdge(edge) {
95825
95831
 
95826
95832
  // src/tools/repo-graph/builder.ts
95827
95833
  var _internals43 = {
95828
- safeRealpathSync
95834
+ safeRealpathSync,
95835
+ extractTSSymbols,
95836
+ extractPythonSymbols,
95837
+ parseFileImports
95829
95838
  };
95830
95839
  var SKIP_DIRECTORIES2 = new Set([
95831
95840
  "node_modules",
@@ -96122,14 +96131,14 @@ function scanFile(filePath, absoluteRoot, maxFileSize) {
96122
96131
  try {
96123
96132
  if ([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext)) {
96124
96133
  const relativePath = path81.relative(absoluteRoot, filePath);
96125
- const symbols2 = extractTSSymbols(relativePath, absoluteRoot);
96134
+ const symbols2 = _internals43.extractTSSymbols(relativePath, absoluteRoot);
96126
96135
  exports = symbols2.filter((s) => s.exported).map((s) => s.name);
96127
96136
  } else if (ext === ".py") {
96128
96137
  const relativePath = path81.relative(absoluteRoot, filePath);
96129
- const symbols2 = extractPythonSymbols(relativePath, absoluteRoot);
96138
+ const symbols2 = _internals43.extractPythonSymbols(relativePath, absoluteRoot);
96130
96139
  exports = symbols2.filter((s) => s.exported).map((s) => s.name);
96131
96140
  }
96132
- const parsedImports = parseFileImports(content);
96141
+ const parsedImports = _internals43.parseFileImports(content);
96133
96142
  const node = {
96134
96143
  filePath,
96135
96144
  moduleName: toModuleName(filePath, absoluteRoot),
@@ -103462,29 +103471,34 @@ function createScopeGuardHook(config3, directory, injectAdvisory) {
103462
103471
  if (!declaredScope || declaredScope.length === 0)
103463
103472
  return;
103464
103473
  const argsObj = output.args;
103465
- const rawFilePath = argsObj?.path ?? argsObj?.filePath ?? argsObj?.file;
103466
- if (typeof rawFilePath !== "string" || !rawFilePath)
103467
- return;
103468
- const filePath = rawFilePath.replace(/[\r\n\t]/g, "_").split(String.fromCharCode(27)).join("_").replace(/\[[\d;]*m/g, "");
103469
- if (!isFileInScope(filePath, declaredScope, directory)) {
103470
- const taskId2 = session?.currentTaskId ?? "unknown";
103471
- 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 ? "..." : ""}]`;
103472
- if (session) {
103473
- session.lastScopeViolation = violationMessage;
103474
- session.scopeViolationDetected = true;
103475
- }
103476
- if (injectAdvisory) {
103477
- for (const [archSessionId, archSession] of swarmState.agentSessions) {
103478
- const archAgent = swarmState.activeAgent.get(archSessionId) ?? archSession.agentName;
103479
- if (stripKnownSwarmPrefix(archAgent) === ORCHESTRATOR_NAME) {
103480
- try {
103481
- injectAdvisory(archSessionId, `[SCOPE GUARD] ${violationMessage}`);
103482
- } catch {}
103483
- break;
103474
+ const candidatePaths = [];
103475
+ const singlePathKeys = ["path", "filePath", "file"];
103476
+ for (const key of singlePathKeys) {
103477
+ const val = argsObj?.[key];
103478
+ if (typeof val === "string" && val) {
103479
+ candidatePaths.push(val);
103480
+ }
103481
+ }
103482
+ let hasArrayKeys = false;
103483
+ const arrayPathKeys = ["files", "paths", "targetFiles"];
103484
+ for (const key of arrayPathKeys) {
103485
+ const val = argsObj?.[key];
103486
+ if (Array.isArray(val)) {
103487
+ hasArrayKeys = true;
103488
+ for (const item of val) {
103489
+ if (typeof item === "string" && item) {
103490
+ candidatePaths.push(item);
103484
103491
  }
103485
103492
  }
103486
103493
  }
103487
- throw new Error(violationMessage);
103494
+ }
103495
+ if (candidatePaths.length === 0 && !hasArrayKeys)
103496
+ return;
103497
+ for (const rawPath of candidatePaths) {
103498
+ const filePath = sanitizePath(rawPath);
103499
+ if (!isFileInScope(filePath, declaredScope, directory)) {
103500
+ reportScopeViolation(agentName, filePath, taskId, session, injectAdvisory, swarmState, declaredScope);
103501
+ }
103488
103502
  }
103489
103503
  }
103490
103504
  };
@@ -103492,7 +103506,7 @@ function createScopeGuardHook(config3, directory, injectAdvisory) {
103492
103506
  function isFileInScope(filePath, scopeEntries, directory) {
103493
103507
  const dir = directory ?? process.cwd();
103494
103508
  const resolvedFile = path102.resolve(dir, filePath);
103495
- return scopeEntries.some((scope) => {
103509
+ return scopeEntries.filter((scope) => scope.length > 0).some((scope) => {
103496
103510
  const resolvedScope = path102.resolve(dir, scope);
103497
103511
  if (resolvedFile === resolvedScope)
103498
103512
  return true;
@@ -103500,6 +103514,38 @@ function isFileInScope(filePath, scopeEntries, directory) {
103500
103514
  return rel.length > 0 && !rel.startsWith("..") && !path102.isAbsolute(rel);
103501
103515
  });
103502
103516
  }
103517
+ function sanitizePath(raw) {
103518
+ let result = "";
103519
+ for (let i2 = 0;i2 < raw.length; i2++) {
103520
+ const c = raw.charCodeAt(i2);
103521
+ if (c <= 31 || c === 127 || c >= 128 && c <= 159) {
103522
+ result += "_";
103523
+ continue;
103524
+ }
103525
+ result += raw[i2];
103526
+ }
103527
+ return result.replace(/\[[\d;]*m/g, "");
103528
+ }
103529
+ function reportScopeViolation(agentName, filePath, taskId, session, injectAdvisory, state, scopeEntries) {
103530
+ const taskLabel = taskId ?? "unknown";
103531
+ 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 ? "..." : ""}]`;
103532
+ if (session) {
103533
+ session.lastScopeViolation = violationMessage;
103534
+ session.scopeViolationDetected = true;
103535
+ }
103536
+ if (injectAdvisory) {
103537
+ for (const [archSessionId, archSession] of state.agentSessions) {
103538
+ const archAgent = state.activeAgent.get(archSessionId) ?? archSession.agentName;
103539
+ if (stripKnownSwarmPrefix(archAgent) === ORCHESTRATOR_NAME) {
103540
+ try {
103541
+ injectAdvisory(archSessionId, `[SCOPE GUARD] ${violationMessage}`);
103542
+ } catch {}
103543
+ break;
103544
+ }
103545
+ }
103546
+ }
103547
+ throw new Error(violationMessage);
103548
+ }
103503
103549
 
103504
103550
  // src/hooks/self-review.ts
103505
103551
  init_constants();
@@ -105992,20 +106038,836 @@ init_snapshot_writer();
105992
106038
  init_state();
105993
106039
  init_telemetry();
105994
106040
 
106041
+ // src/tools/apply-patch.ts
106042
+ init_zod();
106043
+ init_path_security();
106044
+ init_create_tool();
106045
+ import {
106046
+ existsSync as existsSync58,
106047
+ mkdirSync as mkdirSync27,
106048
+ mkdtempSync as mkdtempSync2,
106049
+ readFileSync as readFileSync39,
106050
+ realpathSync as realpathSync13,
106051
+ renameSync as renameSync20,
106052
+ rmdirSync,
106053
+ unlinkSync as unlinkSync17,
106054
+ writeFileSync as writeFileSync20
106055
+ } from "node:fs";
106056
+ import * as path109 from "node:path";
106057
+ var WINDOWS_RESERVED_NAMES2 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
106058
+ var MAX_PATCH_SIZE = 500000;
106059
+ function containsWindowsAttacks2(filePath) {
106060
+ if (/:[^\\/]/.test(filePath))
106061
+ return true;
106062
+ const parts2 = filePath.split(/[/\\]/);
106063
+ for (const part of parts2) {
106064
+ if (WINDOWS_RESERVED_NAMES2.test(part))
106065
+ return true;
106066
+ }
106067
+ return false;
106068
+ }
106069
+ function isProtectedPath2(filePath) {
106070
+ const normalized = filePath.replace(/\\/g, "/");
106071
+ const segments = normalized.split("/");
106072
+ return segments.some((seg) => seg === ".git" || seg === ".swarm");
106073
+ }
106074
+ function containsStrictControlChars(str) {
106075
+ for (let i2 = 0;i2 < str.length; i2++) {
106076
+ const c = str.charCodeAt(i2);
106077
+ if (c <= 31 && c !== 9 && c !== 10 && c !== 13)
106078
+ return true;
106079
+ }
106080
+ return false;
106081
+ }
106082
+ function isCanonicalProtectedPath(targetPath, workspace) {
106083
+ try {
106084
+ const canonicalTarget = realpathSync13(targetPath);
106085
+ const canonicalWorkspace = realpathSync13(workspace);
106086
+ const relative21 = path109.relative(canonicalWorkspace, canonicalTarget).replace(/\\/g, "/");
106087
+ const segments = relative21.split("/").filter(Boolean);
106088
+ return segments.some((seg) => seg === ".git" || seg === ".swarm");
106089
+ } catch {
106090
+ const parentDir = path109.dirname(targetPath);
106091
+ if (parentDir === targetPath)
106092
+ return false;
106093
+ try {
106094
+ const canonicalParent = realpathSync13(parentDir);
106095
+ const canonicalWorkspace = realpathSync13(workspace);
106096
+ const relative21 = path109.relative(canonicalWorkspace, canonicalParent).replace(/\\/g, "/");
106097
+ const segments = relative21.split("/").filter(Boolean);
106098
+ return segments.some((seg) => seg === ".git" || seg === ".swarm");
106099
+ } catch {
106100
+ return false;
106101
+ }
106102
+ }
106103
+ }
106104
+ function isCanonicalPathWithinWorkspace(targetPath, workspaceRoot) {
106105
+ try {
106106
+ const canonicalTarget = realpathSync13(targetPath);
106107
+ const canonicalWorkspace = realpathSync13(workspaceRoot);
106108
+ const relative21 = path109.relative(canonicalWorkspace, canonicalTarget);
106109
+ if (relative21.startsWith("..") || path109.isAbsolute(relative21))
106110
+ return false;
106111
+ const segments = relative21.replace(/\\/g, "/").split("/").filter(Boolean);
106112
+ if (segments.some((seg) => seg === ".git" || seg === ".swarm"))
106113
+ return false;
106114
+ return true;
106115
+ } catch {
106116
+ const parentDir = path109.dirname(targetPath);
106117
+ if (parentDir === targetPath) {
106118
+ return false;
106119
+ }
106120
+ try {
106121
+ const canonicalParent = realpathSync13(parentDir);
106122
+ const canonicalWorkspace = realpathSync13(workspaceRoot);
106123
+ const relative21 = path109.relative(canonicalWorkspace, canonicalParent);
106124
+ if (relative21.startsWith("..") || path109.isAbsolute(relative21))
106125
+ return false;
106126
+ const segments = relative21.replace(/\\/g, "/").split("/").filter(Boolean);
106127
+ if (segments.some((seg) => seg === ".git" || seg === ".swarm"))
106128
+ return false;
106129
+ return true;
106130
+ } catch {
106131
+ return false;
106132
+ }
106133
+ }
106134
+ }
106135
+ function validatePatchTargetPath(filePath, workspace) {
106136
+ if (!filePath || filePath.trim() === "") {
106137
+ return "Empty file path";
106138
+ }
106139
+ if (path109.isAbsolute(filePath) || /^[A-Za-z]:[/\\]/.test(filePath)) {
106140
+ return `Absolute path rejected: ${filePath}`;
106141
+ }
106142
+ if (containsPathTraversal(filePath)) {
106143
+ return `Path traversal detected: ${filePath}`;
106144
+ }
106145
+ if (containsStrictControlChars(filePath)) {
106146
+ return `Control characters detected in path: ${filePath}`;
106147
+ }
106148
+ if (containsControlChars(filePath)) {
106149
+ return `Control characters detected in path: ${filePath}`;
106150
+ }
106151
+ if (containsWindowsAttacks2(filePath)) {
106152
+ return `Windows reserved name or invalid path: ${filePath}`;
106153
+ }
106154
+ if (isProtectedPath2(filePath)) {
106155
+ return `Protected directory target rejected: ${filePath}`;
106156
+ }
106157
+ const resolved = path109.resolve(workspace, filePath);
106158
+ const relative21 = path109.relative(workspace, resolved);
106159
+ if (relative21.startsWith("..") || path109.isAbsolute(relative21)) {
106160
+ return `Path escapes workspace: ${filePath}`;
106161
+ }
106162
+ if (!isCanonicalPathWithinWorkspace(resolved, workspace)) {
106163
+ return `Path escapes workspace via symlink/junction: ${filePath}`;
106164
+ }
106165
+ return null;
106166
+ }
106167
+ function extractHeaderPath(header, prefix) {
106168
+ const trimmed = header.trim();
106169
+ if (!trimmed.startsWith(prefix))
106170
+ return null;
106171
+ const rest = trimmed.slice(prefix.length).trim();
106172
+ if (rest === "/dev/null")
106173
+ return "/dev/null";
106174
+ if (rest.startsWith("a/") || rest.startsWith("b/")) {
106175
+ const stripped = rest.slice(2);
106176
+ if (stripped.length === 0)
106177
+ return null;
106178
+ return stripped;
106179
+ }
106180
+ return rest.length > 0 ? rest : null;
106181
+ }
106182
+ function parseHunkHeader(line) {
106183
+ const match = line.match(/^@@\s*-(\d+)(?:,(\d+))?\s*\+(\d+)(?:,(\d+))?\s*@@/);
106184
+ if (!match)
106185
+ return null;
106186
+ return {
106187
+ oldStart: parseInt(match[1], 10),
106188
+ oldCount: match[2] !== undefined ? parseInt(match[2], 10) : 1,
106189
+ newStart: parseInt(match[3], 10),
106190
+ newCount: match[4] !== undefined ? parseInt(match[4], 10) : 1
106191
+ };
106192
+ }
106193
+ function parseUnifiedDiff(patchText) {
106194
+ if (patchText.length > MAX_PATCH_SIZE) {
106195
+ return {
106196
+ files: [],
106197
+ error: `Patch exceeds maximum size of ${MAX_PATCH_SIZE} characters`
106198
+ };
106199
+ }
106200
+ if (patchText.includes("\x00")) {
106201
+ return {
106202
+ files: [],
106203
+ error: "Binary content detected (null byte) — binary patches are not supported (FR-013)"
106204
+ };
106205
+ }
106206
+ const normalized = patchText.replace(/\r\n/g, `
106207
+ `).replace(/\r/g, `
106208
+ `);
106209
+ let lines = normalized.split(`
106210
+ `);
106211
+ if (lines.length > 0 && lines[lines.length - 1] === "") {
106212
+ lines = lines.slice(0, -1);
106213
+ }
106214
+ for (const line of lines) {
106215
+ if (line === "GIT binary patch" || line.startsWith("Binary files ")) {
106216
+ return { files: [], error: "Binary patches are not supported (FR-013)" };
106217
+ }
106218
+ if (line.startsWith("rename from") || line.startsWith("rename to") || line.startsWith("copy from") || line.startsWith("copy to")) {
106219
+ return {
106220
+ files: [],
106221
+ error: "Rename/copy patches are not supported (FR-013)"
106222
+ };
106223
+ }
106224
+ }
106225
+ const fileDiffs = [];
106226
+ let i2 = 0;
106227
+ while (i2 < lines.length) {
106228
+ let oldHeaderPath = null;
106229
+ let newHeaderPath = null;
106230
+ if (lines[i2].startsWith("diff --git ")) {
106231
+ i2++;
106232
+ 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 "))) {
106233
+ i2++;
106234
+ }
106235
+ }
106236
+ if (i2 < lines.length && lines[i2].startsWith("--- ")) {
106237
+ oldHeaderPath = extractHeaderPath(lines[i2], "--- ");
106238
+ i2++;
106239
+ } else if (oldHeaderPath === null) {
106240
+ i2++;
106241
+ continue;
106242
+ }
106243
+ if (i2 < lines.length && lines[i2].startsWith("+++ ")) {
106244
+ newHeaderPath = extractHeaderPath(lines[i2], "+++ ");
106245
+ i2++;
106246
+ } else {
106247
+ continue;
106248
+ }
106249
+ if (oldHeaderPath === null || newHeaderPath === null) {
106250
+ continue;
106251
+ }
106252
+ const isNewFile = oldHeaderPath === "/dev/null";
106253
+ const isDelete = newHeaderPath === "/dev/null";
106254
+ const targetPath = isDelete ? oldHeaderPath : newHeaderPath;
106255
+ if (targetPath === "/dev/null") {
106256
+ continue;
106257
+ }
106258
+ const hunks = [];
106259
+ while (i2 < lines.length && lines[i2].startsWith("@@")) {
106260
+ const header = parseHunkHeader(lines[i2]);
106261
+ if (!header) {
106262
+ i2++;
106263
+ continue;
106264
+ }
106265
+ i2++;
106266
+ const hunkLines = [];
106267
+ while (i2 < lines.length) {
106268
+ const line = lines[i2];
106269
+ if (line.startsWith("@@") || line.startsWith("diff --git ") || line.startsWith("--- ") || line.startsWith("+++ ")) {
106270
+ break;
106271
+ }
106272
+ if (line.startsWith("\\")) {
106273
+ i2++;
106274
+ continue;
106275
+ }
106276
+ if (line.length === 0) {
106277
+ break;
106278
+ }
106279
+ const firstChar = line[0];
106280
+ if (firstChar !== " " && firstChar !== "+" && firstChar !== "-") {
106281
+ break;
106282
+ }
106283
+ if (firstChar === "+") {
106284
+ hunkLines.push({ type: "addition", content: line.slice(1) });
106285
+ } else if (firstChar === "-") {
106286
+ hunkLines.push({ type: "removal", content: line.slice(1) });
106287
+ } else {
106288
+ hunkLines.push({ type: "context", content: line.slice(1) });
106289
+ }
106290
+ i2++;
106291
+ }
106292
+ hunks.push({
106293
+ oldStart: header.oldStart,
106294
+ oldCount: header.oldCount,
106295
+ newStart: header.newStart,
106296
+ newCount: header.newCount,
106297
+ lines: hunkLines
106298
+ });
106299
+ }
106300
+ if (hunks.length > 0) {
106301
+ fileDiffs.push({
106302
+ oldPath: oldHeaderPath,
106303
+ newPath: newHeaderPath,
106304
+ isNewFile,
106305
+ isDelete,
106306
+ hunks
106307
+ });
106308
+ } else {
106309
+ fileDiffs.push({
106310
+ oldPath: oldHeaderPath,
106311
+ newPath: newHeaderPath,
106312
+ isNewFile,
106313
+ isDelete,
106314
+ hunks: []
106315
+ });
106316
+ }
106317
+ }
106318
+ return { files: fileDiffs, error: null };
106319
+ }
106320
+ function arraysEqual(a, b) {
106321
+ if (a.length !== b.length)
106322
+ return false;
106323
+ for (let idx = 0;idx < a.length; idx++) {
106324
+ if (a[idx] !== b[idx])
106325
+ return false;
106326
+ }
106327
+ return true;
106328
+ }
106329
+ function applyHunks(content, fileDiff) {
106330
+ const normalizedContent = content.replace(/\r\n/g, `
106331
+ `);
106332
+ const fileLines = normalizedContent.split(`
106333
+ `);
106334
+ if (fileDiff.isNewFile) {
106335
+ const newLines = [];
106336
+ for (const hunk of fileDiff.hunks) {
106337
+ for (const line of hunk.lines) {
106338
+ if (line.type === "addition" || line.type === "context") {
106339
+ newLines.push(line.content);
106340
+ }
106341
+ }
106342
+ }
106343
+ return { success: true, appliedLines: newLines };
106344
+ }
106345
+ if (fileDiff.isDelete) {
106346
+ return { success: true, appliedLines: [] };
106347
+ }
106348
+ let accumulatedDelta = 0;
106349
+ for (let hunkIdx = 0;hunkIdx < fileDiff.hunks.length; hunkIdx++) {
106350
+ const hunk = fileDiff.hunks[hunkIdx];
106351
+ const searchStart = Math.max(0, hunk.oldStart - 1 + accumulatedDelta);
106352
+ const expectedOldLines = [];
106353
+ const newLinesForHunk = [];
106354
+ for (const line of hunk.lines) {
106355
+ if (line.type === "context") {
106356
+ expectedOldLines.push(line.content);
106357
+ newLinesForHunk.push(line.content);
106358
+ } else if (line.type === "removal") {
106359
+ expectedOldLines.push(line.content);
106360
+ } else if (line.type === "addition") {
106361
+ newLinesForHunk.push(line.content);
106362
+ }
106363
+ }
106364
+ const exactOffset = searchStart;
106365
+ const matchFound = exactOffset <= fileLines.length - expectedOldLines.length && arraysEqual(fileLines.slice(exactOffset, exactOffset + expectedOldLines.length), expectedOldLines);
106366
+ if (matchFound) {
106367
+ fileLines.splice(exactOffset, expectedOldLines.length, ...newLinesForHunk);
106368
+ const delta = newLinesForHunk.length - expectedOldLines.length;
106369
+ accumulatedDelta += delta;
106370
+ }
106371
+ if (!matchFound) {
106372
+ const diagStart = Math.min(searchStart, fileLines.length);
106373
+ const diagEnd = Math.min(diagStart + expectedOldLines.length, fileLines.length);
106374
+ const actualContent = fileLines.slice(diagStart, diagEnd).join(`
106375
+ `);
106376
+ const expectedContent = expectedOldLines.join(`
106377
+ `);
106378
+ return {
106379
+ success: false,
106380
+ failedHunkIndex: hunkIdx,
106381
+ error: {
106382
+ hunkIndex: hunkIdx,
106383
+ type: "context-mismatch",
106384
+ message: `Context mismatch in hunk ${hunkIdx + 1} at line ${searchStart + 1}: expected context does not match file content`,
106385
+ expected: expectedContent.length > 200 ? `${expectedContent.slice(0, 200)}... (truncated)` : expectedContent,
106386
+ actual: actualContent.length > 200 ? `${actualContent.slice(0, 200)}... (truncated)` : actualContent,
106387
+ line: searchStart + 1
106388
+ }
106389
+ };
106390
+ }
106391
+ }
106392
+ return { success: true, appliedLines: fileLines };
106393
+ }
106394
+ function atomicWriteFileSync(targetPath, content) {
106395
+ const dir = path109.dirname(targetPath);
106396
+ mkdirSync27(dir, { recursive: true });
106397
+ const tempPrefix = `.apply-patch-${Date.now()}-${process.pid}`;
106398
+ let tempPath;
106399
+ try {
106400
+ const tempDir = realpathSync13(mkdtempSync2(path109.join(dir, tempPrefix)));
106401
+ tempPath = path109.join(tempDir, "content");
106402
+ } catch {
106403
+ tempPath = path109.join(dir, `${tempPrefix}.tmp`);
106404
+ }
106405
+ try {
106406
+ writeFileSync20(tempPath, content, "utf-8");
106407
+ renameSync20(tempPath, targetPath);
106408
+ } finally {
106409
+ if (existsSync58(tempPath)) {
106410
+ try {
106411
+ unlinkSync17(tempPath);
106412
+ } catch {}
106413
+ }
106414
+ const tempDir = path109.dirname(tempPath);
106415
+ if (tempDir !== dir && existsSync58(tempDir)) {
106416
+ try {
106417
+ rmdirSync(tempDir);
106418
+ } catch {}
106419
+ }
106420
+ }
106421
+ }
106422
+ function detectLineEnding(content) {
106423
+ return content.includes(`\r
106424
+ `) ? `\r
106425
+ ` : `
106426
+ `;
106427
+ }
106428
+ function ensureFinalNewline(content, originalEndsWithNewline) {
106429
+ if (originalEndsWithNewline && !content.endsWith(`
106430
+ `)) {
106431
+ return `${content}
106432
+ `;
106433
+ }
106434
+ if (!originalEndsWithNewline && content.endsWith(`
106435
+ `)) {
106436
+ return content.slice(0, -1);
106437
+ }
106438
+ return content;
106439
+ }
106440
+ function processFileDiff(fileDiff, targetPath, fullPath, workspace, dryRun, allowCreates, allowDeletes) {
106441
+ const hunksTotal = fileDiff.hunks.length;
106442
+ if (!isCanonicalPathWithinWorkspace(fullPath, workspace)) {
106443
+ return {
106444
+ file: targetPath,
106445
+ status: "error",
106446
+ hunks: hunksTotal,
106447
+ hunksApplied: 0,
106448
+ hunksFailed: hunksTotal,
106449
+ errors: [
106450
+ {
106451
+ hunkIndex: 0,
106452
+ type: "context-mismatch",
106453
+ message: `Path escapes workspace via symlink/junction: ${targetPath}`
106454
+ }
106455
+ ]
106456
+ };
106457
+ }
106458
+ if (isCanonicalProtectedPath(fullPath, workspace)) {
106459
+ return {
106460
+ file: targetPath,
106461
+ status: "error",
106462
+ hunks: hunksTotal,
106463
+ hunksApplied: 0,
106464
+ hunksFailed: hunksTotal,
106465
+ errors: [
106466
+ {
106467
+ hunkIndex: 0,
106468
+ type: "context-mismatch",
106469
+ message: `Protected directory target rejected via symlink: ${targetPath}`
106470
+ }
106471
+ ]
106472
+ };
106473
+ }
106474
+ if (fileDiff.isNewFile) {
106475
+ if (!allowCreates) {
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: "create-not-allowed",
106486
+ message: `New file creation not allowed: ${targetPath} (set allowCreates to true)`
106487
+ }
106488
+ ]
106489
+ };
106490
+ }
106491
+ const parentDir = path109.dirname(fullPath);
106492
+ if (!existsSync58(parentDir)) {
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: "file-not-found",
106503
+ message: `Parent directory does not exist: ${parentDir}`
106504
+ }
106505
+ ]
106506
+ };
106507
+ }
106508
+ if (existsSync58(fullPath)) {
106509
+ return {
106510
+ file: targetPath,
106511
+ status: "error",
106512
+ hunks: hunksTotal,
106513
+ hunksApplied: 0,
106514
+ hunksFailed: hunksTotal,
106515
+ errors: [
106516
+ {
106517
+ hunkIndex: 0,
106518
+ type: "file-not-found",
106519
+ message: `File already exists: ${targetPath} (cannot create — patch may be stale)`
106520
+ }
106521
+ ]
106522
+ };
106523
+ }
106524
+ if (hunksTotal === 0) {
106525
+ return {
106526
+ file: targetPath,
106527
+ status: "no-changes",
106528
+ hunks: 0,
106529
+ hunksApplied: 0,
106530
+ hunksFailed: 0
106531
+ };
106532
+ }
106533
+ const hunkResult2 = applyHunks("", fileDiff);
106534
+ if (!hunkResult2.success || !hunkResult2.appliedLines) {
106535
+ return {
106536
+ file: targetPath,
106537
+ status: "error",
106538
+ hunks: hunksTotal,
106539
+ hunksApplied: 0,
106540
+ hunksFailed: hunksTotal,
106541
+ errors: hunkResult2.error ? [hunkResult2.error] : []
106542
+ };
106543
+ }
106544
+ if (!dryRun) {
106545
+ const content2 = ensureFinalNewline(hunkResult2.appliedLines.join(`
106546
+ `), true);
106547
+ atomicWriteFileSync(fullPath, content2);
106548
+ }
106549
+ return {
106550
+ file: targetPath,
106551
+ status: "created",
106552
+ hunks: hunksTotal,
106553
+ hunksApplied: hunksTotal,
106554
+ hunksFailed: 0
106555
+ };
106556
+ }
106557
+ if (fileDiff.isDelete) {
106558
+ if (hunksTotal === 0) {
106559
+ return {
106560
+ file: targetPath,
106561
+ status: "no-changes",
106562
+ hunks: 0,
106563
+ hunksApplied: 0,
106564
+ hunksFailed: 0
106565
+ };
106566
+ }
106567
+ if (!allowDeletes) {
106568
+ return {
106569
+ file: targetPath,
106570
+ status: "error",
106571
+ hunks: hunksTotal,
106572
+ hunksApplied: 0,
106573
+ hunksFailed: hunksTotal,
106574
+ errors: [
106575
+ {
106576
+ hunkIndex: 0,
106577
+ type: "delete-not-allowed",
106578
+ message: `File deletion not allowed: ${targetPath} (set allowDeletes to true)`
106579
+ }
106580
+ ]
106581
+ };
106582
+ }
106583
+ if (!existsSync58(fullPath)) {
106584
+ return {
106585
+ file: targetPath,
106586
+ status: "error",
106587
+ hunks: hunksTotal,
106588
+ hunksApplied: 0,
106589
+ hunksFailed: hunksTotal,
106590
+ errors: [
106591
+ {
106592
+ hunkIndex: 0,
106593
+ type: "file-not-found",
106594
+ message: `File not found for deletion: ${targetPath}`
106595
+ }
106596
+ ]
106597
+ };
106598
+ }
106599
+ if (!dryRun) {
106600
+ try {
106601
+ unlinkSync17(fullPath);
106602
+ } catch (err2) {
106603
+ return {
106604
+ file: targetPath,
106605
+ status: "error",
106606
+ hunks: hunksTotal,
106607
+ hunksApplied: 0,
106608
+ hunksFailed: hunksTotal,
106609
+ errors: [
106610
+ {
106611
+ hunkIndex: 0,
106612
+ type: "file-not-found",
106613
+ message: `Failed to delete file: ${err2 instanceof Error ? err2.message : String(err2)}`
106614
+ }
106615
+ ]
106616
+ };
106617
+ }
106618
+ }
106619
+ return {
106620
+ file: targetPath,
106621
+ status: "applied",
106622
+ hunks: hunksTotal,
106623
+ hunksApplied: hunksTotal,
106624
+ hunksFailed: 0
106625
+ };
106626
+ }
106627
+ if (!existsSync58(fullPath)) {
106628
+ return {
106629
+ file: targetPath,
106630
+ status: "error",
106631
+ hunks: hunksTotal,
106632
+ hunksApplied: 0,
106633
+ hunksFailed: hunksTotal,
106634
+ errors: [
106635
+ {
106636
+ hunkIndex: 0,
106637
+ type: "file-not-found",
106638
+ message: `File not found: ${targetPath}`
106639
+ }
106640
+ ]
106641
+ };
106642
+ }
106643
+ let content;
106644
+ try {
106645
+ content = readFileSync39(fullPath, "utf-8");
106646
+ } catch (err2) {
106647
+ return {
106648
+ file: targetPath,
106649
+ status: "error",
106650
+ hunks: hunksTotal,
106651
+ hunksApplied: 0,
106652
+ hunksFailed: hunksTotal,
106653
+ errors: [
106654
+ {
106655
+ hunkIndex: 0,
106656
+ type: "file-not-found",
106657
+ message: `Could not read file: ${err2 instanceof Error ? err2.message : String(err2)}`
106658
+ }
106659
+ ]
106660
+ };
106661
+ }
106662
+ if (hunksTotal === 0) {
106663
+ return {
106664
+ file: targetPath,
106665
+ status: "no-changes",
106666
+ hunks: 0,
106667
+ hunksApplied: 0,
106668
+ hunksFailed: 0
106669
+ };
106670
+ }
106671
+ const originalEndsWithNewline = content.endsWith(`
106672
+ `);
106673
+ const originalLineEnding = detectLineEnding(content);
106674
+ const hunkResult = applyHunks(content, fileDiff);
106675
+ if (!hunkResult.success) {
106676
+ return {
106677
+ file: targetPath,
106678
+ status: "error",
106679
+ hunks: hunksTotal,
106680
+ hunksApplied: 0,
106681
+ hunksFailed: hunksTotal,
106682
+ errors: hunkResult.error ? [hunkResult.error] : []
106683
+ };
106684
+ }
106685
+ const resultContent = hunkResult.appliedLines.join(`
106686
+ `);
106687
+ if (resultContent === "" && !dryRun && !allowDeletes && content.length > 0) {
106688
+ return {
106689
+ file: targetPath,
106690
+ status: "error",
106691
+ hunks: hunksTotal,
106692
+ hunksApplied: hunksTotal,
106693
+ hunksFailed: 0,
106694
+ errors: [
106695
+ {
106696
+ hunkIndex: 0,
106697
+ type: "delete-not-allowed",
106698
+ message: `Patch would delete all content from ${targetPath}. Set allowDeletes to true to permit file deletion.`
106699
+ }
106700
+ ]
106701
+ };
106702
+ }
106703
+ let finalContent;
106704
+ if (resultContent === "") {
106705
+ finalContent = "";
106706
+ } else {
106707
+ const withLineEnding = originalLineEnding === `\r
106708
+ ` ? resultContent.replace(/\n/g, `\r
106709
+ `) : resultContent;
106710
+ finalContent = ensureFinalNewline(withLineEnding, originalEndsWithNewline);
106711
+ }
106712
+ if (finalContent === content) {
106713
+ return {
106714
+ file: targetPath,
106715
+ status: "no-changes",
106716
+ hunks: hunksTotal,
106717
+ hunksApplied: hunksTotal,
106718
+ hunksFailed: 0
106719
+ };
106720
+ }
106721
+ if (!dryRun) {
106722
+ atomicWriteFileSync(fullPath, finalContent);
106723
+ }
106724
+ return {
106725
+ file: targetPath,
106726
+ status: "applied",
106727
+ hunks: hunksTotal,
106728
+ hunksApplied: hunksTotal,
106729
+ hunksFailed: 0
106730
+ };
106731
+ }
106732
+ function buildErrorResult(message) {
106733
+ return {
106734
+ success: false,
106735
+ files: [
106736
+ {
106737
+ file: "",
106738
+ status: "error",
106739
+ hunks: 0,
106740
+ hunksApplied: 0,
106741
+ hunksFailed: 0,
106742
+ errors: [
106743
+ {
106744
+ hunkIndex: 0,
106745
+ type: "context-mismatch",
106746
+ message
106747
+ }
106748
+ ]
106749
+ }
106750
+ ],
106751
+ summary: {
106752
+ totalFiles: 0,
106753
+ applied: 0,
106754
+ failed: 1,
106755
+ totalHunks: 0
106756
+ }
106757
+ };
106758
+ }
106759
+ var applyPatch = createSwarmTool({
106760
+ description: "Apply a unified diff patch to workspace files. Validates paths, matches context exactly, and writes atomically. Coder-scoped write tool.",
106761
+ args: {
106762
+ patch: exports_external.string().min(1).describe("Unified diff text to parse and apply"),
106763
+ 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."),
106764
+ dryRun: exports_external.boolean().optional().default(false).describe("Validate without writing files (default: false)"),
106765
+ allowCreates: exports_external.boolean().optional().default(false).describe("Allow creating new files from patches with --- /dev/null (default: false)"),
106766
+ allowDeletes: exports_external.boolean().optional().default(false).describe("Allow deleting files from patches with +++ /dev/null (default: false)")
106767
+ },
106768
+ execute: async (args2, directory) => {
106769
+ if (!args2 || typeof args2 !== "object") {
106770
+ return JSON.stringify(buildErrorResult("Could not parse apply_patch arguments"), null, 2);
106771
+ }
106772
+ const obj = args2;
106773
+ const patchText = obj.patch ?? "";
106774
+ const files = obj.files ?? [];
106775
+ const dryRun = obj.dryRun ?? false;
106776
+ const allowCreates = obj.allowCreates ?? false;
106777
+ const allowDeletes = obj.allowDeletes ?? false;
106778
+ if (!existsSync58(directory)) {
106779
+ return JSON.stringify(buildErrorResult("Workspace directory does not exist"), null, 2);
106780
+ }
106781
+ if (files.length === 0) {
106782
+ return JSON.stringify(buildErrorResult("files array cannot be empty"), null, 2);
106783
+ }
106784
+ if (!patchText || patchText.trim() === "") {
106785
+ return JSON.stringify(buildErrorResult("patch text cannot be empty"), null, 2);
106786
+ }
106787
+ for (const filePath of files) {
106788
+ const validationError = validatePatchTargetPath(filePath, directory);
106789
+ if (validationError) {
106790
+ return JSON.stringify(buildErrorResult(validationError), null, 2);
106791
+ }
106792
+ }
106793
+ const { files: parsedFiles, error: parseError } = parseUnifiedDiff(patchText);
106794
+ if (parseError) {
106795
+ return JSON.stringify(buildErrorResult(parseError), null, 2);
106796
+ }
106797
+ if (parsedFiles.length === 0) {
106798
+ return JSON.stringify({
106799
+ success: true,
106800
+ dryRun,
106801
+ files: [],
106802
+ summary: { totalFiles: 0, applied: 0, failed: 0, totalHunks: 0 }
106803
+ }, null, 2);
106804
+ }
106805
+ const declaredFileSet = new Set(files);
106806
+ const undeclaredTargets = [];
106807
+ for (const fileDiff of parsedFiles) {
106808
+ const targetPath = fileDiff.isDelete ? fileDiff.oldPath : fileDiff.newPath;
106809
+ if (targetPath && targetPath !== "/dev/null" && !declaredFileSet.has(targetPath)) {
106810
+ undeclaredTargets.push(targetPath);
106811
+ }
106812
+ }
106813
+ if (undeclaredTargets.length > 0) {
106814
+ return JSON.stringify(buildErrorResult(`Patch targets files not in the declared files array: ${undeclaredTargets.join(", ")}`), null, 2);
106815
+ }
106816
+ const parsedTargetSet = new Set(parsedFiles.map((fd) => fd.isDelete ? fd.oldPath : fd.newPath).filter(Boolean));
106817
+ const extraFiles = files.filter((f) => !parsedTargetSet.has(f));
106818
+ const fileResults = [];
106819
+ let totalApplied = 0;
106820
+ let totalFailed = 0;
106821
+ let totalHunks = 0;
106822
+ for (const fileDiff of parsedFiles) {
106823
+ const targetPath = fileDiff.isDelete ? fileDiff.oldPath : fileDiff.newPath;
106824
+ const fullPath = path109.resolve(directory, targetPath);
106825
+ totalHunks += fileDiff.hunks.length;
106826
+ const result = processFileDiff(fileDiff, targetPath, fullPath, directory, dryRun, allowCreates, allowDeletes);
106827
+ fileResults.push(result);
106828
+ if (result.status === "applied" || result.status === "created") {
106829
+ totalApplied++;
106830
+ } else if (result.status === "error") {
106831
+ totalFailed++;
106832
+ }
106833
+ }
106834
+ const output = {
106835
+ success: totalFailed === 0,
106836
+ dryRun,
106837
+ files: fileResults,
106838
+ summary: {
106839
+ totalFiles: fileResults.length,
106840
+ applied: totalApplied,
106841
+ failed: totalFailed,
106842
+ totalHunks
106843
+ }
106844
+ };
106845
+ if (extraFiles.length > 0) {
106846
+ return JSON.stringify({
106847
+ ...output,
106848
+ warnings: [
106849
+ `files[] contains entries not targeted by the patch: ${extraFiles.join(", ")}`
106850
+ ]
106851
+ }, null, 2);
106852
+ }
106853
+ return JSON.stringify(output, null, 2);
106854
+ }
106855
+ });
106856
+
105995
106857
  // src/tools/batch-symbols.ts
105996
106858
  init_dist();
105997
106859
  init_create_tool();
105998
106860
  import * as fs72 from "node:fs";
105999
- import * as path109 from "node:path";
106861
+ import * as path110 from "node:path";
106000
106862
  init_path_security();
106001
- var WINDOWS_RESERVED_NAMES2 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
106002
- function containsWindowsAttacks2(str) {
106863
+ var WINDOWS_RESERVED_NAMES3 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
106864
+ function containsWindowsAttacks3(str) {
106003
106865
  if (/:[^\\/]/.test(str)) {
106004
106866
  return true;
106005
106867
  }
106006
106868
  const parts2 = str.split(/[/\\]/);
106007
106869
  for (const part of parts2) {
106008
- if (WINDOWS_RESERVED_NAMES2.test(part)) {
106870
+ if (WINDOWS_RESERVED_NAMES3.test(part)) {
106009
106871
  return true;
106010
106872
  }
106011
106873
  }
@@ -106013,14 +106875,14 @@ function containsWindowsAttacks2(str) {
106013
106875
  }
106014
106876
  function isPathInWorkspace2(filePath, workspace) {
106015
106877
  try {
106016
- const resolvedPath = path109.resolve(workspace, filePath);
106878
+ const resolvedPath = path110.resolve(workspace, filePath);
106017
106879
  if (!fs72.existsSync(resolvedPath)) {
106018
106880
  return true;
106019
106881
  }
106020
106882
  const realWorkspace = fs72.realpathSync(workspace);
106021
106883
  const realResolvedPath = fs72.realpathSync(resolvedPath);
106022
- const relativePath = path109.relative(realWorkspace, realResolvedPath);
106023
- if (relativePath.startsWith("..") || path109.isAbsolute(relativePath)) {
106884
+ const relativePath = path110.relative(realWorkspace, realResolvedPath);
106885
+ if (relativePath.startsWith("..") || path110.isAbsolute(relativePath)) {
106024
106886
  return false;
106025
106887
  }
106026
106888
  return true;
@@ -106029,7 +106891,7 @@ function isPathInWorkspace2(filePath, workspace) {
106029
106891
  }
106030
106892
  }
106031
106893
  function processFile2(file3, cwd, exportedOnly) {
106032
- const ext = path109.extname(file3);
106894
+ const ext = path110.extname(file3);
106033
106895
  if (containsControlChars(file3)) {
106034
106896
  return {
106035
106897
  file: file3,
@@ -106046,7 +106908,7 @@ function processFile2(file3, cwd, exportedOnly) {
106046
106908
  errorType: "path-traversal"
106047
106909
  };
106048
106910
  }
106049
- if (containsWindowsAttacks2(file3)) {
106911
+ if (containsWindowsAttacks3(file3)) {
106050
106912
  return {
106051
106913
  file: file3,
106052
106914
  success: false,
@@ -106062,7 +106924,7 @@ function processFile2(file3, cwd, exportedOnly) {
106062
106924
  errorType: "path-outside-workspace"
106063
106925
  };
106064
106926
  }
106065
- const fullPath = path109.join(cwd, file3);
106927
+ const fullPath = path110.join(cwd, file3);
106066
106928
  if (!fs72.existsSync(fullPath)) {
106067
106929
  return {
106068
106930
  file: file3,
@@ -106356,15 +107218,15 @@ init_task_id();
106356
107218
  init_create_tool();
106357
107219
  init_resolve_working_directory();
106358
107220
  import * as fs73 from "node:fs";
106359
- import * as path110 from "node:path";
107221
+ import * as path111 from "node:path";
106360
107222
  var EVIDENCE_DIR = ".swarm/evidence";
106361
107223
  function isValidTaskId3(taskId) {
106362
107224
  return isStrictTaskId(taskId);
106363
107225
  }
106364
107226
  function isPathWithinSwarm(filePath, workspaceRoot) {
106365
- const normalizedWorkspace = path110.resolve(workspaceRoot);
106366
- const swarmPath = path110.join(normalizedWorkspace, ".swarm", "evidence");
106367
- const normalizedPath = path110.resolve(filePath);
107227
+ const normalizedWorkspace = path111.resolve(workspaceRoot);
107228
+ const swarmPath = path111.join(normalizedWorkspace, ".swarm", "evidence");
107229
+ const normalizedPath = path111.resolve(filePath);
106368
107230
  return normalizedPath.startsWith(swarmPath);
106369
107231
  }
106370
107232
  function readEvidenceFile(evidencePath) {
@@ -106445,7 +107307,7 @@ var check_gate_status = createSwarmTool({
106445
107307
  };
106446
107308
  return JSON.stringify(errorResult, null, 2);
106447
107309
  }
106448
- const evidencePath = path110.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
107310
+ const evidencePath = path111.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
106449
107311
  if (!isPathWithinSwarm(evidencePath, directory)) {
106450
107312
  const errorResult = {
106451
107313
  taskId: taskIdInput,
@@ -106542,7 +107404,7 @@ init_state();
106542
107404
  init_create_tool();
106543
107405
  init_resolve_working_directory();
106544
107406
  import * as fs74 from "node:fs";
106545
- import * as path111 from "node:path";
107407
+ import * as path112 from "node:path";
106546
107408
  function extractMatches(regex, text) {
106547
107409
  return Array.from(text.matchAll(regex));
106548
107410
  }
@@ -106694,10 +107556,10 @@ async function executeCompletionVerify(args2, directory) {
106694
107556
  let hasFileReadFailure = false;
106695
107557
  for (const filePath of fileTargets) {
106696
107558
  const normalizedPath = filePath.replace(/\\/g, "/");
106697
- const resolvedPath = path111.resolve(directory, normalizedPath);
106698
- const projectRoot = path111.resolve(directory);
106699
- const relative22 = path111.relative(projectRoot, resolvedPath);
106700
- const withinProject = relative22 === "" || !relative22.startsWith("..") && !path111.isAbsolute(relative22);
107559
+ const resolvedPath = path112.resolve(directory, normalizedPath);
107560
+ const projectRoot = path112.resolve(directory);
107561
+ const relative23 = path112.relative(projectRoot, resolvedPath);
107562
+ const withinProject = relative23 === "" || !relative23.startsWith("..") && !path112.isAbsolute(relative23);
106701
107563
  if (!withinProject) {
106702
107564
  blockedTasks.push({
106703
107565
  task_id: task.id,
@@ -106752,8 +107614,8 @@ async function executeCompletionVerify(args2, directory) {
106752
107614
  blockedTasks
106753
107615
  };
106754
107616
  try {
106755
- const evidenceDir = path111.join(directory, ".swarm", "evidence", `${phase}`);
106756
- const evidencePath = path111.join(evidenceDir, "completion-verify.json");
107617
+ const evidenceDir = path112.join(directory, ".swarm", "evidence", `${phase}`);
107618
+ const evidencePath = path112.join(evidenceDir, "completion-verify.json");
106757
107619
  fs74.mkdirSync(evidenceDir, { recursive: true });
106758
107620
  const evidenceBundle = {
106759
107621
  schema_version: "1.0.0",
@@ -106831,11 +107693,11 @@ var completion_verify = createSwarmTool({
106831
107693
  // src/tools/complexity-hotspots.ts
106832
107694
  init_zod();
106833
107695
  import * as fs76 from "node:fs";
106834
- import * as path113 from "node:path";
107696
+ import * as path114 from "node:path";
106835
107697
 
106836
107698
  // src/quality/metrics.ts
106837
107699
  import * as fs75 from "node:fs";
106838
- import * as path112 from "node:path";
107700
+ import * as path113 from "node:path";
106839
107701
  var MAX_FILE_SIZE_BYTES4 = 256 * 1024;
106840
107702
  var MIN_DUPLICATION_LINES = 10;
106841
107703
  function estimateCyclomaticComplexity(content) {
@@ -106887,7 +107749,7 @@ async function computeComplexityDelta(files, workingDir) {
106887
107749
  let totalComplexity = 0;
106888
107750
  const analyzedFiles = [];
106889
107751
  for (const file3 of files) {
106890
- const fullPath = path112.isAbsolute(file3) ? file3 : path112.join(workingDir, file3);
107752
+ const fullPath = path113.isAbsolute(file3) ? file3 : path113.join(workingDir, file3);
106891
107753
  if (!fs75.existsSync(fullPath)) {
106892
107754
  continue;
106893
107755
  }
@@ -107010,7 +107872,7 @@ function countGoExports(content) {
107010
107872
  function getExportCountForFile(filePath) {
107011
107873
  try {
107012
107874
  const content = fs75.readFileSync(filePath, "utf-8");
107013
- const ext = path112.extname(filePath).toLowerCase();
107875
+ const ext = path113.extname(filePath).toLowerCase();
107014
107876
  switch (ext) {
107015
107877
  case ".ts":
107016
107878
  case ".tsx":
@@ -107036,7 +107898,7 @@ async function computePublicApiDelta(files, workingDir) {
107036
107898
  let totalExports = 0;
107037
107899
  const analyzedFiles = [];
107038
107900
  for (const file3 of files) {
107039
- const fullPath = path112.isAbsolute(file3) ? file3 : path112.join(workingDir, file3);
107901
+ const fullPath = path113.isAbsolute(file3) ? file3 : path113.join(workingDir, file3);
107040
107902
  if (!fs75.existsSync(fullPath)) {
107041
107903
  continue;
107042
107904
  }
@@ -107070,7 +107932,7 @@ async function computeDuplicationRatio(files, workingDir) {
107070
107932
  let duplicateLines = 0;
107071
107933
  const analyzedFiles = [];
107072
107934
  for (const file3 of files) {
107073
- const fullPath = path112.isAbsolute(file3) ? file3 : path112.join(workingDir, file3);
107935
+ const fullPath = path113.isAbsolute(file3) ? file3 : path113.join(workingDir, file3);
107074
107936
  if (!fs75.existsSync(fullPath)) {
107075
107937
  continue;
107076
107938
  }
@@ -107103,8 +107965,8 @@ function countCodeLines(content) {
107103
107965
  return lines.length;
107104
107966
  }
107105
107967
  function isTestFile(filePath) {
107106
- const basename16 = path112.basename(filePath);
107107
- const _ext = path112.extname(filePath).toLowerCase();
107968
+ const basename16 = path113.basename(filePath);
107969
+ const _ext = path113.extname(filePath).toLowerCase();
107108
107970
  const testPatterns = [
107109
107971
  ".test.",
107110
107972
  ".spec.",
@@ -107185,8 +108047,8 @@ function matchGlobSegment(globSegments, pathSegments) {
107185
108047
  }
107186
108048
  return gIndex === globSegments.length && pIndex === pathSegments.length;
107187
108049
  }
107188
- function matchesGlobSegment(path113, glob) {
107189
- const normalizedPath = path113.replace(/\\/g, "/");
108050
+ function matchesGlobSegment(path114, glob) {
108051
+ const normalizedPath = path114.replace(/\\/g, "/");
107190
108052
  const normalizedGlob = glob.replace(/\\/g, "/");
107191
108053
  if (normalizedPath.includes("//")) {
107192
108054
  return false;
@@ -107217,8 +108079,8 @@ function simpleGlobToRegex2(glob) {
107217
108079
  function hasGlobstar(glob) {
107218
108080
  return glob.includes("**");
107219
108081
  }
107220
- function globMatches(path113, glob) {
107221
- const normalizedPath = path113.replace(/\\/g, "/");
108082
+ function globMatches(path114, glob) {
108083
+ const normalizedPath = path114.replace(/\\/g, "/");
107222
108084
  if (!glob || glob === "") {
107223
108085
  if (normalizedPath.includes("//")) {
107224
108086
  return false;
@@ -107254,7 +108116,7 @@ function shouldExcludeFile(filePath, excludeGlobs) {
107254
108116
  async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
107255
108117
  let testLines = 0;
107256
108118
  let codeLines = 0;
107257
- const srcDir = path112.join(workingDir, "src");
108119
+ const srcDir = path113.join(workingDir, "src");
107258
108120
  if (fs75.existsSync(srcDir)) {
107259
108121
  await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
107260
108122
  codeLines += lines;
@@ -107262,14 +108124,14 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
107262
108124
  }
107263
108125
  const possibleSrcDirs = ["lib", "app", "source", "core"];
107264
108126
  for (const dir of possibleSrcDirs) {
107265
- const dirPath = path112.join(workingDir, dir);
108127
+ const dirPath = path113.join(workingDir, dir);
107266
108128
  if (fs75.existsSync(dirPath)) {
107267
108129
  await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
107268
108130
  codeLines += lines;
107269
108131
  });
107270
108132
  }
107271
108133
  }
107272
- const testsDir = path112.join(workingDir, "tests");
108134
+ const testsDir = path113.join(workingDir, "tests");
107273
108135
  if (fs75.existsSync(testsDir)) {
107274
108136
  await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
107275
108137
  testLines += lines;
@@ -107277,7 +108139,7 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
107277
108139
  }
107278
108140
  const possibleTestDirs = ["test", "__tests__", "specs"];
107279
108141
  for (const dir of possibleTestDirs) {
107280
- const dirPath = path112.join(workingDir, dir);
108142
+ const dirPath = path113.join(workingDir, dir);
107281
108143
  if (fs75.existsSync(dirPath) && dirPath !== testsDir) {
107282
108144
  await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
107283
108145
  testLines += lines;
@@ -107292,7 +108154,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
107292
108154
  try {
107293
108155
  const entries = fs75.readdirSync(dirPath, { withFileTypes: true });
107294
108156
  for (const entry of entries) {
107295
- const fullPath = path112.join(dirPath, entry.name);
108157
+ const fullPath = path113.join(dirPath, entry.name);
107296
108158
  if (entry.isDirectory()) {
107297
108159
  if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
107298
108160
  continue;
@@ -107300,7 +108162,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
107300
108162
  await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
107301
108163
  } else if (entry.isFile()) {
107302
108164
  const relativePath = fullPath.replace(`${dirPath}/`, "");
107303
- const ext = path112.extname(entry.name).toLowerCase();
108165
+ const ext = path113.extname(entry.name).toLowerCase();
107304
108166
  const validExts = [
107305
108167
  ".ts",
107306
108168
  ".tsx",
@@ -107551,7 +108413,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
107551
108413
  const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
107552
108414
  const filteredChurn = new Map;
107553
108415
  for (const [file3, count] of churnMap) {
107554
- const ext = path113.extname(file3).toLowerCase();
108416
+ const ext = path114.extname(file3).toLowerCase();
107555
108417
  if (extSet.has(ext)) {
107556
108418
  filteredChurn.set(file3, count);
107557
108419
  }
@@ -107562,7 +108424,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
107562
108424
  for (const [file3, churnCount] of filteredChurn) {
107563
108425
  let fullPath = file3;
107564
108426
  if (!fs76.existsSync(fullPath)) {
107565
- fullPath = path113.join(cwd, file3);
108427
+ fullPath = path114.join(cwd, file3);
107566
108428
  }
107567
108429
  const complexity = getComplexityForFile2(fullPath);
107568
108430
  if (complexity !== null) {
@@ -107731,8 +108593,8 @@ ${body2}`);
107731
108593
 
107732
108594
  // src/council/council-evidence-writer.ts
107733
108595
  init_task_file();
107734
- import { appendFileSync as appendFileSync12, existsSync as existsSync62, mkdirSync as mkdirSync28, readFileSync as readFileSync44 } from "node:fs";
107735
- import { join as join94 } from "node:path";
108596
+ import { appendFileSync as appendFileSync12, existsSync as existsSync63, mkdirSync as mkdirSync29, readFileSync as readFileSync45 } from "node:fs";
108597
+ import { join as join95 } from "node:path";
107736
108598
  var EVIDENCE_DIR2 = ".swarm/evidence";
107737
108599
  var VALID_TASK_ID = /^\d+\.\d+(\.\d+)*$/;
107738
108600
  var COUNCIL_GATE_NAME = "council";
@@ -107769,14 +108631,14 @@ async function writeCouncilEvidence(workingDir, synthesis) {
107769
108631
  if (!VALID_TASK_ID.test(synthesis.taskId)) {
107770
108632
  throw new Error(`writeCouncilEvidence: invalid taskId "${synthesis.taskId}" — must match N.M or N.M.P format`);
107771
108633
  }
107772
- const dir = join94(workingDir, EVIDENCE_DIR2);
107773
- mkdirSync28(dir, { recursive: true });
108634
+ const dir = join95(workingDir, EVIDENCE_DIR2);
108635
+ mkdirSync29(dir, { recursive: true });
107774
108636
  const filePath = taskEvidencePath(workingDir, synthesis.taskId);
107775
108637
  await _internals53.withTaskEvidenceLock(workingDir, synthesis.taskId, COUNCIL_AGENT_ID, async () => {
107776
108638
  const existingRoot = Object.create(null);
107777
- if (existsSync62(filePath)) {
108639
+ if (existsSync63(filePath)) {
107778
108640
  try {
107779
- const parsed = JSON.parse(readFileSync44(filePath, "utf-8"));
108641
+ const parsed = JSON.parse(readFileSync45(filePath, "utf-8"));
107780
108642
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
107781
108643
  safeAssignOwnProps(existingRoot, parsed);
107782
108644
  }
@@ -107807,15 +108669,15 @@ async function writeCouncilEvidence(workingDir, synthesis) {
107807
108669
  await atomicWriteFile(filePath, JSON.stringify(updated, null, 2));
107808
108670
  });
107809
108671
  try {
107810
- const councilDir = join94(workingDir, ".swarm", "council");
107811
- mkdirSync28(councilDir, { recursive: true });
108672
+ const councilDir = join95(workingDir, ".swarm", "council");
108673
+ mkdirSync29(councilDir, { recursive: true });
107812
108674
  const auditLine = JSON.stringify({
107813
108675
  round: synthesis.roundNumber,
107814
108676
  verdict: synthesis.overallVerdict,
107815
108677
  timestamp: synthesis.timestamp,
107816
108678
  vetoedBy: synthesis.vetoedBy
107817
108679
  });
107818
- appendFileSync12(join94(councilDir, `${synthesis.taskId}.rounds.jsonl`), `${auditLine}
108680
+ appendFileSync12(join95(councilDir, `${synthesis.taskId}.rounds.jsonl`), `${auditLine}
107819
108681
  `);
107820
108682
  } catch (auditError) {
107821
108683
  console.warn(`writeCouncilEvidence: failed to append round-history audit log: ${auditError instanceof Error ? auditError.message : String(auditError)}`);
@@ -108137,25 +108999,25 @@ function buildFinalCouncilFeedback(projectSummary, verdict, vetoedBy, requiredFi
108137
108999
  }
108138
109000
 
108139
109001
  // src/council/criteria-store.ts
108140
- import { existsSync as existsSync63, mkdirSync as mkdirSync29, readFileSync as readFileSync45, writeFileSync as writeFileSync21 } from "node:fs";
108141
- import { join as join95 } from "node:path";
109002
+ import { existsSync as existsSync64, mkdirSync as mkdirSync30, readFileSync as readFileSync46, writeFileSync as writeFileSync22 } from "node:fs";
109003
+ import { join as join96 } from "node:path";
108142
109004
  var COUNCIL_DIR = ".swarm/council";
108143
109005
  function writeCriteria(workingDir, taskId, criteria) {
108144
- const dir = join95(workingDir, COUNCIL_DIR);
108145
- mkdirSync29(dir, { recursive: true });
109006
+ const dir = join96(workingDir, COUNCIL_DIR);
109007
+ mkdirSync30(dir, { recursive: true });
108146
109008
  const payload = {
108147
109009
  taskId,
108148
109010
  criteria,
108149
109011
  declaredAt: new Date().toISOString()
108150
109012
  };
108151
- writeFileSync21(join95(dir, `${safeId(taskId)}.json`), JSON.stringify(payload, null, 2));
109013
+ writeFileSync22(join96(dir, `${safeId(taskId)}.json`), JSON.stringify(payload, null, 2));
108152
109014
  }
108153
109015
  function readCriteria(workingDir, taskId) {
108154
- const filePath = join95(workingDir, COUNCIL_DIR, `${safeId(taskId)}.json`);
108155
- if (!existsSync63(filePath))
109016
+ const filePath = join96(workingDir, COUNCIL_DIR, `${safeId(taskId)}.json`);
109017
+ if (!existsSync64(filePath))
108156
109018
  return null;
108157
109019
  try {
108158
- const parsed = JSON.parse(readFileSync45(filePath, "utf-8"));
109020
+ const parsed = JSON.parse(readFileSync46(filePath, "utf-8"));
108159
109021
  if (parsed && typeof parsed === "object" && typeof parsed.taskId === "string" && Array.isArray(parsed.criteria)) {
108160
109022
  return parsed;
108161
109023
  }
@@ -108305,7 +109167,7 @@ var submit_council_verdicts = createSwarmTool({
108305
109167
  init_zod();
108306
109168
  init_loader();
108307
109169
  import * as fs77 from "node:fs";
108308
- import * as path114 from "node:path";
109170
+ import * as path115 from "node:path";
108309
109171
 
108310
109172
  // src/council/general-council-advisory.ts
108311
109173
  var ADVISORY_HEADER = "[general_council] (advisory; not blocking)";
@@ -108733,10 +109595,10 @@ var convene_general_council = createSwarmTool({
108733
109595
  const round1 = input.round1Responses;
108734
109596
  const round2 = input.round2Responses ?? [];
108735
109597
  const result = synthesizeGeneralCouncil(input.question, input.mode, round1, round2);
108736
- const evidenceDir = path114.join(workingDir, ".swarm", "council", "general");
109598
+ const evidenceDir = path115.join(workingDir, ".swarm", "council", "general");
108737
109599
  const safeTimestamp = result.timestamp.replace(/[:.]/g, "-");
108738
109600
  const evidenceFile = `${safeTimestamp}-${input.mode}.json`;
108739
- const evidencePath = path114.join(evidenceDir, evidenceFile);
109601
+ const evidencePath = path115.join(evidenceDir, evidenceFile);
108740
109602
  try {
108741
109603
  await fs77.promises.mkdir(evidenceDir, { recursive: true });
108742
109604
  await fs77.promises.writeFile(evidencePath, JSON.stringify(result, null, 2));
@@ -109007,7 +109869,7 @@ init_state();
109007
109869
  init_task_id();
109008
109870
  init_create_tool();
109009
109871
  import * as fs78 from "node:fs";
109010
- import * as path115 from "node:path";
109872
+ import * as path116 from "node:path";
109011
109873
  function validateTaskIdFormat2(taskId) {
109012
109874
  return validateTaskIdFormat(taskId);
109013
109875
  }
@@ -109081,8 +109943,8 @@ async function executeDeclareScope(args2, fallbackDir) {
109081
109943
  };
109082
109944
  }
109083
109945
  }
109084
- normalizedDir = path115.normalize(args2.working_directory);
109085
- const pathParts = normalizedDir.split(path115.sep);
109946
+ normalizedDir = path116.normalize(args2.working_directory);
109947
+ const pathParts = normalizedDir.split(path116.sep);
109086
109948
  if (pathParts.includes("..")) {
109087
109949
  return {
109088
109950
  success: false,
@@ -109092,10 +109954,10 @@ async function executeDeclareScope(args2, fallbackDir) {
109092
109954
  ]
109093
109955
  };
109094
109956
  }
109095
- const resolvedDir = path115.resolve(normalizedDir);
109957
+ const resolvedDir = path116.resolve(normalizedDir);
109096
109958
  try {
109097
109959
  const realPath = fs78.realpathSync(resolvedDir);
109098
- const planPath2 = path115.join(realPath, ".swarm", "plan.json");
109960
+ const planPath2 = path116.join(realPath, ".swarm", "plan.json");
109099
109961
  if (!fs78.existsSync(planPath2)) {
109100
109962
  return {
109101
109963
  success: false,
@@ -109116,9 +109978,9 @@ async function executeDeclareScope(args2, fallbackDir) {
109116
109978
  }
109117
109979
  if (normalizedDir && fallbackDir) {
109118
109980
  try {
109119
- const canonicalWorkingDir = fs78.realpathSync(path115.resolve(normalizedDir));
109120
- const canonicalProjectRoot = fs78.realpathSync(path115.resolve(fallbackDir));
109121
- if (canonicalWorkingDir.startsWith(canonicalProjectRoot + path115.sep)) {
109981
+ const canonicalWorkingDir = fs78.realpathSync(path116.resolve(normalizedDir));
109982
+ const canonicalProjectRoot = fs78.realpathSync(path116.resolve(fallbackDir));
109983
+ if (canonicalWorkingDir.startsWith(canonicalProjectRoot + path116.sep)) {
109122
109984
  return {
109123
109985
  success: false,
109124
109986
  message: `working_directory "${normalizedDir}" is a subdirectory of the project root. Use the project root "${fallbackDir}" instead.`,
@@ -109140,7 +110002,7 @@ async function executeDeclareScope(args2, fallbackDir) {
109140
110002
  };
109141
110003
  }
109142
110004
  const directory = normalizedDir || fallbackDir;
109143
- const planPath = path115.resolve(directory, ".swarm", "plan.json");
110005
+ const planPath = path116.resolve(directory, ".swarm", "plan.json");
109144
110006
  if (!fs78.existsSync(planPath)) {
109145
110007
  return {
109146
110008
  success: false,
@@ -109180,8 +110042,8 @@ async function executeDeclareScope(args2, fallbackDir) {
109180
110042
  const normalizeErrors = [];
109181
110043
  const dir = directory;
109182
110044
  const mergedFiles = rawMergedFiles.map((file3) => {
109183
- if (path115.isAbsolute(file3)) {
109184
- const relativePath = path115.relative(dir, file3).replace(/\\/g, "/");
110045
+ if (path116.isAbsolute(file3)) {
110046
+ const relativePath = path116.relative(dir, file3).replace(/\\/g, "/");
109185
110047
  if (relativePath.startsWith("..")) {
109186
110048
  normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
109187
110049
  return file3;
@@ -109243,7 +110105,7 @@ var declare_scope = createSwarmTool({
109243
110105
  init_zod();
109244
110106
  import * as child_process7 from "node:child_process";
109245
110107
  import * as fs79 from "node:fs";
109246
- import * as path116 from "node:path";
110108
+ import * as path117 from "node:path";
109247
110109
  init_create_tool();
109248
110110
  var MAX_DIFF_LINES = 500;
109249
110111
  var DIFF_TIMEOUT_MS = 30000;
@@ -109272,20 +110134,20 @@ function validateBase(base) {
109272
110134
  function validatePaths(paths) {
109273
110135
  if (!paths)
109274
110136
  return null;
109275
- for (const path117 of paths) {
109276
- if (!path117 || path117.length === 0) {
110137
+ for (const path118 of paths) {
110138
+ if (!path118 || path118.length === 0) {
109277
110139
  return "empty path not allowed";
109278
110140
  }
109279
- if (path117.length > MAX_PATH_LENGTH) {
110141
+ if (path118.length > MAX_PATH_LENGTH) {
109280
110142
  return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
109281
110143
  }
109282
- if (SHELL_METACHARACTERS2.test(path117)) {
110144
+ if (SHELL_METACHARACTERS2.test(path118)) {
109283
110145
  return "path contains shell metacharacters";
109284
110146
  }
109285
- if (path117.startsWith("-")) {
110147
+ if (path118.startsWith("-")) {
109286
110148
  return 'path cannot start with "-" (option-like arguments not allowed)';
109287
110149
  }
109288
- if (CONTROL_CHAR_PATTERN2.test(path117)) {
110150
+ if (CONTROL_CHAR_PATTERN2.test(path118)) {
109289
110151
  return "path contains control characters";
109290
110152
  }
109291
110153
  }
@@ -109393,8 +110255,8 @@ var diff = createSwarmTool({
109393
110255
  if (parts2.length >= 3) {
109394
110256
  const additions = parseInt(parts2[0], 10) || 0;
109395
110257
  const deletions = parseInt(parts2[1], 10) || 0;
109396
- const path117 = parts2[2];
109397
- files.push({ path: path117, additions, deletions });
110258
+ const path118 = parts2[2];
110259
+ files.push({ path: path118, additions, deletions });
109398
110260
  }
109399
110261
  }
109400
110262
  const contractChanges = [];
@@ -109433,7 +110295,7 @@ var diff = createSwarmTool({
109433
110295
  } else if (base === "unstaged") {
109434
110296
  const oldRef = `:${file3.path}`;
109435
110297
  oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
109436
- newContent = fs79.readFileSync(path116.join(directory, file3.path), "utf-8");
110298
+ newContent = fs79.readFileSync(path117.join(directory, file3.path), "utf-8");
109437
110299
  } else {
109438
110300
  const oldRef = `${base}:${file3.path}`;
109439
110301
  oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
@@ -109510,12 +110372,12 @@ var diff = createSwarmTool({
109510
110372
  init_zod();
109511
110373
  import * as child_process8 from "node:child_process";
109512
110374
  import * as fs80 from "node:fs";
109513
- import * as path117 from "node:path";
110375
+ import * as path118 from "node:path";
109514
110376
  init_create_tool();
109515
110377
  init_resolve_working_directory();
109516
110378
  async function execGit2(workingDir, args2, options) {
109517
110379
  try {
109518
- const stdout = await new Promise((resolve40, reject) => {
110380
+ const stdout = await new Promise((resolve41, reject) => {
109519
110381
  const execOpts = {
109520
110382
  encoding: "utf-8",
109521
110383
  cwd: workingDir,
@@ -109528,7 +110390,7 @@ async function execGit2(workingDir, args2, options) {
109528
110390
  reject(error93);
109529
110391
  return;
109530
110392
  }
109531
- resolve40(output ?? "");
110393
+ resolve41(output ?? "");
109532
110394
  });
109533
110395
  });
109534
110396
  return stdout;
@@ -109579,7 +110441,7 @@ var diff_summary = createSwarmTool({
109579
110441
  }
109580
110442
  try {
109581
110443
  let oldContent;
109582
- const newContent = await fs80.promises.readFile(path117.join(workingDir, filePath), "utf-8");
110444
+ const newContent = await fs80.promises.readFile(path118.join(workingDir, filePath), "utf-8");
109583
110445
  if (fileExistsInHead) {
109584
110446
  oldContent = await execGit2(workingDir, ["show", `HEAD:${filePath}`], {
109585
110447
  timeout: 5000,
@@ -109809,7 +110671,7 @@ init_zod();
109809
110671
  init_create_tool();
109810
110672
  init_path_security();
109811
110673
  import * as fs81 from "node:fs";
109812
- import * as path118 from "node:path";
110674
+ import * as path119 from "node:path";
109813
110675
  var MAX_FILE_SIZE_BYTES6 = 1024 * 1024;
109814
110676
  var MAX_EVIDENCE_FILES = 1000;
109815
110677
  var EVIDENCE_DIR3 = ".swarm/evidence";
@@ -109836,9 +110698,9 @@ function validateRequiredTypes(input) {
109836
110698
  return null;
109837
110699
  }
109838
110700
  function isPathWithinSwarm2(filePath, cwd) {
109839
- const normalizedCwd = path118.resolve(cwd);
109840
- const swarmPath = path118.join(normalizedCwd, ".swarm");
109841
- const normalizedPath = path118.resolve(filePath);
110701
+ const normalizedCwd = path119.resolve(cwd);
110702
+ const swarmPath = path119.join(normalizedCwd, ".swarm");
110703
+ const normalizedPath = path119.resolve(filePath);
109842
110704
  return normalizedPath.startsWith(swarmPath);
109843
110705
  }
109844
110706
  function parseCompletedTasks(planContent) {
@@ -109868,10 +110730,10 @@ function readEvidenceFiles(evidenceDir, _cwd) {
109868
110730
  if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
109869
110731
  continue;
109870
110732
  }
109871
- const filePath = path118.join(evidenceDir, filename);
110733
+ const filePath = path119.join(evidenceDir, filename);
109872
110734
  try {
109873
- const resolvedPath = path118.resolve(filePath);
109874
- const evidenceDirResolved = path118.resolve(evidenceDir);
110735
+ const resolvedPath = path119.resolve(filePath);
110736
+ const evidenceDirResolved = path119.resolve(evidenceDir);
109875
110737
  if (!resolvedPath.startsWith(evidenceDirResolved)) {
109876
110738
  continue;
109877
110739
  }
@@ -109989,7 +110851,7 @@ var evidence_check = createSwarmTool({
109989
110851
  return JSON.stringify(errorResult, null, 2);
109990
110852
  }
109991
110853
  const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
109992
- const planPath = path118.join(cwd, PLAN_FILE);
110854
+ const planPath = path119.join(cwd, PLAN_FILE);
109993
110855
  if (!isPathWithinSwarm2(planPath, cwd)) {
109994
110856
  const errorResult = {
109995
110857
  error: "plan file path validation failed",
@@ -110021,7 +110883,7 @@ var evidence_check = createSwarmTool({
110021
110883
  };
110022
110884
  return JSON.stringify(result2, null, 2);
110023
110885
  }
110024
- const evidenceDir = path118.join(cwd, EVIDENCE_DIR3);
110886
+ const evidenceDir = path119.join(cwd, EVIDENCE_DIR3);
110025
110887
  const evidence = readEvidenceFiles(evidenceDir, cwd);
110026
110888
  const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
110027
110889
  const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
@@ -110040,7 +110902,7 @@ var evidence_check = createSwarmTool({
110040
110902
  init_zod();
110041
110903
  init_create_tool();
110042
110904
  import * as fs82 from "node:fs";
110043
- import * as path119 from "node:path";
110905
+ import * as path120 from "node:path";
110044
110906
  var EXT_MAP = {
110045
110907
  python: ".py",
110046
110908
  py: ".py",
@@ -110121,12 +110983,12 @@ var extract_code_blocks = createSwarmTool({
110121
110983
  if (prefix) {
110122
110984
  filename = `${prefix}_${filename}`;
110123
110985
  }
110124
- let filepath = path119.join(targetDir, filename);
110125
- const base = path119.basename(filepath, path119.extname(filepath));
110126
- const ext = path119.extname(filepath);
110986
+ let filepath = path120.join(targetDir, filename);
110987
+ const base = path120.basename(filepath, path120.extname(filepath));
110988
+ const ext = path120.extname(filepath);
110127
110989
  let counter = 1;
110128
110990
  while (fs82.existsSync(filepath)) {
110129
- filepath = path119.join(targetDir, `${base}_${counter}${ext}`);
110991
+ filepath = path120.join(targetDir, `${base}_${counter}${ext}`);
110130
110992
  counter++;
110131
110993
  }
110132
110994
  try {
@@ -110468,7 +111330,7 @@ init_create_tool();
110468
111330
  var GITINGEST_TIMEOUT_MS = 1e4;
110469
111331
  var GITINGEST_MAX_RESPONSE_BYTES = 5242880;
110470
111332
  var GITINGEST_MAX_RETRIES = 2;
110471
- var delay = (ms) => new Promise((resolve41) => setTimeout(resolve41, ms));
111333
+ var delay = (ms) => new Promise((resolve42) => setTimeout(resolve42, ms));
110472
111334
  async function fetchGitingest(args2) {
110473
111335
  for (let attempt = 0;attempt <= GITINGEST_MAX_RETRIES; attempt++) {
110474
111336
  try {
@@ -110557,7 +111419,7 @@ init_zod();
110557
111419
  init_create_tool();
110558
111420
  init_path_security();
110559
111421
  import * as fs83 from "node:fs";
110560
- import * as path120 from "node:path";
111422
+ import * as path121 from "node:path";
110561
111423
  var MAX_FILE_PATH_LENGTH2 = 500;
110562
111424
  var MAX_SYMBOL_LENGTH = 256;
110563
111425
  var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
@@ -110605,7 +111467,7 @@ function validateSymbolInput(symbol3) {
110605
111467
  return null;
110606
111468
  }
110607
111469
  function isBinaryFile2(filePath, buffer) {
110608
- const ext = path120.extname(filePath).toLowerCase();
111470
+ const ext = path121.extname(filePath).toLowerCase();
110609
111471
  if (ext === ".json" || ext === ".md" || ext === ".txt") {
110610
111472
  return false;
110611
111473
  }
@@ -110629,15 +111491,15 @@ function parseImports(content, targetFile, targetSymbol) {
110629
111491
  const imports = [];
110630
111492
  let _resolvedTarget;
110631
111493
  try {
110632
- _resolvedTarget = path120.resolve(targetFile);
111494
+ _resolvedTarget = path121.resolve(targetFile);
110633
111495
  } catch {
110634
111496
  _resolvedTarget = targetFile;
110635
111497
  }
110636
- const targetBasename = path120.basename(targetFile, path120.extname(targetFile));
111498
+ const targetBasename = path121.basename(targetFile, path121.extname(targetFile));
110637
111499
  const targetWithExt = targetFile;
110638
111500
  const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
110639
- const normalizedTargetWithExt = path120.normalize(targetWithExt).replace(/\\/g, "/");
110640
- const normalizedTargetWithoutExt = path120.normalize(targetWithoutExt).replace(/\\/g, "/");
111501
+ const normalizedTargetWithExt = path121.normalize(targetWithExt).replace(/\\/g, "/");
111502
+ const normalizedTargetWithoutExt = path121.normalize(targetWithoutExt).replace(/\\/g, "/");
110641
111503
  const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
110642
111504
  for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
110643
111505
  const modulePath = match[1] || match[2] || match[3];
@@ -110660,9 +111522,9 @@ function parseImports(content, targetFile, targetSymbol) {
110660
111522
  }
110661
111523
  const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
110662
111524
  let isMatch = false;
110663
- const _targetDir = path120.dirname(targetFile);
110664
- const targetExt = path120.extname(targetFile);
110665
- const targetBasenameNoExt = path120.basename(targetFile, targetExt);
111525
+ const _targetDir = path121.dirname(targetFile);
111526
+ const targetExt = path121.extname(targetFile);
111527
+ const targetBasenameNoExt = path121.basename(targetFile, targetExt);
110666
111528
  const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
110667
111529
  const moduleName = modulePath.split(/[/\\]/).pop() || "";
110668
111530
  const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
@@ -110730,10 +111592,10 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
110730
111592
  entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
110731
111593
  for (const entry of entries) {
110732
111594
  if (SKIP_DIRECTORIES4.has(entry)) {
110733
- stats.skippedDirs.push(path120.join(dir, entry));
111595
+ stats.skippedDirs.push(path121.join(dir, entry));
110734
111596
  continue;
110735
111597
  }
110736
- const fullPath = path120.join(dir, entry);
111598
+ const fullPath = path121.join(dir, entry);
110737
111599
  let stat9;
110738
111600
  try {
110739
111601
  stat9 = fs83.statSync(fullPath);
@@ -110747,7 +111609,7 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
110747
111609
  if (stat9.isDirectory()) {
110748
111610
  findSourceFiles2(fullPath, files, stats);
110749
111611
  } else if (stat9.isFile()) {
110750
- const ext = path120.extname(fullPath).toLowerCase();
111612
+ const ext = path121.extname(fullPath).toLowerCase();
110751
111613
  if (SUPPORTED_EXTENSIONS3.includes(ext)) {
110752
111614
  files.push(fullPath);
110753
111615
  }
@@ -110804,7 +111666,7 @@ var imports = createSwarmTool({
110804
111666
  return JSON.stringify(errorResult, null, 2);
110805
111667
  }
110806
111668
  try {
110807
- const targetFile = path120.resolve(file3);
111669
+ const targetFile = path121.resolve(file3);
110808
111670
  if (!fs83.existsSync(targetFile)) {
110809
111671
  const errorResult = {
110810
111672
  error: `target file not found: ${file3}`,
@@ -110826,7 +111688,7 @@ var imports = createSwarmTool({
110826
111688
  };
110827
111689
  return JSON.stringify(errorResult, null, 2);
110828
111690
  }
110829
- const baseDir = path120.dirname(targetFile);
111691
+ const baseDir = path121.dirname(targetFile);
110830
111692
  const scanStats = {
110831
111693
  skippedDirs: [],
110832
111694
  skippedFiles: 0,
@@ -111214,7 +112076,7 @@ init_zod();
111214
112076
  init_config();
111215
112077
  init_knowledge_store();
111216
112078
  init_create_tool();
111217
- import { existsSync as existsSync68 } from "node:fs";
112079
+ import { existsSync as existsSync69 } from "node:fs";
111218
112080
  var DEFAULT_LIMIT = 10;
111219
112081
  var MAX_LESSON_LENGTH = 200;
111220
112082
  var VALID_CATEGORIES3 = [
@@ -111290,14 +112152,14 @@ function validateLimit(limit) {
111290
112152
  }
111291
112153
  async function readSwarmKnowledge(directory) {
111292
112154
  const swarmPath = resolveSwarmKnowledgePath(directory);
111293
- if (!existsSync68(swarmPath)) {
112155
+ if (!existsSync69(swarmPath)) {
111294
112156
  return [];
111295
112157
  }
111296
112158
  return readKnowledge(swarmPath);
111297
112159
  }
111298
112160
  async function readHiveKnowledge() {
111299
112161
  const hivePath = resolveHiveKnowledgePath();
111300
- if (!existsSync68(hivePath)) {
112162
+ if (!existsSync69(hivePath)) {
111301
112163
  return [];
111302
112164
  }
111303
112165
  return readKnowledge(hivePath);
@@ -111723,11 +112585,11 @@ var lean_turbo_acquire_locks = createSwarmTool({
111723
112585
  init_zod();
111724
112586
  init_constants();
111725
112587
  import * as fs85 from "node:fs";
111726
- import * as path122 from "node:path";
112588
+ import * as path123 from "node:path";
111727
112589
 
111728
112590
  // src/turbo/lean/conflicts.ts
111729
112591
  import * as fs84 from "node:fs";
111730
- import * as path121 from "node:path";
112592
+ import * as path122 from "node:path";
111731
112593
  var DEFAULT_GLOBAL_FILES = [
111732
112594
  "package.json",
111733
112595
  "package-lock.json",
@@ -111830,7 +112692,7 @@ function isGlobalFile(normalizedPath) {
111830
112692
  }
111831
112693
  return false;
111832
112694
  }
111833
- function isProtectedPath2(normalizedPath) {
112695
+ function isProtectedPath3(normalizedPath) {
111834
112696
  const lowerPath = normalizedPath.toLowerCase();
111835
112697
  for (const pattern of DEFAULT_PROTECTED_PATTERNS) {
111836
112698
  if (lowerPath.includes(pattern.toLowerCase())) {
@@ -111854,7 +112716,7 @@ function isProtectedPath2(normalizedPath) {
111854
112716
  return false;
111855
112717
  }
111856
112718
  function readTaskScopes(directory, taskId) {
111857
- const scopePath = path121.join(directory, ".swarm", "scopes", `scope-${taskId}.json`);
112719
+ const scopePath = path122.join(directory, ".swarm", "scopes", `scope-${taskId}.json`);
111858
112720
  try {
111859
112721
  if (!fs84.existsSync(scopePath)) {
111860
112722
  return null;
@@ -111880,7 +112742,7 @@ function assessTaskRisk(files, hasDeclaredScope, hasInvalidScope, config3) {
111880
112742
  files: globalFiles
111881
112743
  };
111882
112744
  }
111883
- const protectedFiles = files.filter(isProtectedPath2);
112745
+ const protectedFiles = files.filter(isProtectedPath3);
111884
112746
  if (protectedFiles.length > 0) {
111885
112747
  return {
111886
112748
  category: "protected",
@@ -112242,7 +113104,7 @@ function createEmptyPlan(phaseNumber, planId) {
112242
113104
  // src/tools/lean-turbo-plan-lanes.ts
112243
113105
  init_create_tool();
112244
113106
  function readPlanJson(directory) {
112245
- const planPath = path122.join(directory, ".swarm", "plan.json");
113107
+ const planPath = path123.join(directory, ".swarm", "plan.json");
112246
113108
  if (!fs85.existsSync(planPath)) {
112247
113109
  return null;
112248
113110
  }
@@ -112298,15 +113160,15 @@ init_config();
112298
113160
  // src/turbo/lean/reviewer.ts
112299
113161
  init_state();
112300
113162
  import * as fs87 from "node:fs/promises";
112301
- import * as path124 from "node:path";
113163
+ import * as path125 from "node:path";
112302
113164
 
112303
113165
  // src/turbo/lean/evidence.ts
112304
113166
  init_bun_compat();
112305
113167
  import { rmSync as rmSync6 } from "node:fs";
112306
113168
  import * as fs86 from "node:fs/promises";
112307
- import * as path123 from "node:path";
113169
+ import * as path124 from "node:path";
112308
113170
  function leanTurboEvidenceDir(directory, phase) {
112309
- return path123.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
113171
+ return path124.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
112310
113172
  }
112311
113173
  function validateLaneId(laneId) {
112312
113174
  if (laneId.length === 0) {
@@ -112328,16 +113190,16 @@ function validateLaneId(laneId) {
112328
113190
  function laneEvidencePath(directory, phase, laneId) {
112329
113191
  validateLaneId(laneId);
112330
113192
  const expectedDir = leanTurboEvidenceDir(directory, phase);
112331
- const resolvedPath = path123.resolve(path123.join(expectedDir, `${laneId}.json`));
112332
- const resolvedDir = path123.resolve(expectedDir);
112333
- if (!resolvedPath.startsWith(resolvedDir + path123.sep) && resolvedPath !== resolvedDir) {
113193
+ const resolvedPath = path124.resolve(path124.join(expectedDir, `${laneId}.json`));
113194
+ const resolvedDir = path124.resolve(expectedDir);
113195
+ if (!resolvedPath.startsWith(resolvedDir + path124.sep) && resolvedPath !== resolvedDir) {
112334
113196
  throw new Error(`Invalid laneId: path traversal detected (got "${laneId}")`);
112335
113197
  }
112336
113198
  return resolvedPath;
112337
113199
  }
112338
113200
  async function atomicWriteJson(filePath, data) {
112339
113201
  const content = JSON.stringify(data, null, 2);
112340
- const dir = path123.dirname(filePath);
113202
+ const dir = path124.dirname(filePath);
112341
113203
  await fs86.mkdir(dir, { recursive: true });
112342
113204
  const tempPath = `${filePath}.tmp.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}`;
112343
113205
  try {
@@ -112351,7 +113213,7 @@ async function atomicWriteJson(filePath, data) {
112351
113213
  }
112352
113214
  }
112353
113215
  function phaseEvidencePath(directory, phase) {
112354
- return path123.join(leanTurboEvidenceDir(directory, phase), "lean-turbo-phase.json");
113216
+ return path124.join(leanTurboEvidenceDir(directory, phase), "lean-turbo-phase.json");
112355
113217
  }
112356
113218
  async function writeLaneEvidence(directory, phase, evidence) {
112357
113219
  const targetPath = laneEvidencePath(directory, phase, evidence.laneId);
@@ -112395,7 +113257,7 @@ async function listLaneEvidence(directory, phase) {
112395
113257
  if (entry === "lean-turbo-phase.json") {
112396
113258
  continue;
112397
113259
  }
112398
- const filePath = path123.join(evidenceDir, entry);
113260
+ const filePath = path124.join(evidenceDir, entry);
112399
113261
  let content;
112400
113262
  try {
112401
113263
  content = await fs86.readFile(filePath, "utf-8");
@@ -112526,9 +113388,9 @@ function parseReviewerVerdict(responseText) {
112526
113388
  return { verdict, reason };
112527
113389
  }
112528
113390
  async function writeReviewerEvidence(directory, phase, verdict, reason) {
112529
- const evidenceDir = path124.join(directory, ".swarm", "evidence", String(phase));
113391
+ const evidenceDir = path125.join(directory, ".swarm", "evidence", String(phase));
112530
113392
  await fs87.mkdir(evidenceDir, { recursive: true });
112531
- const evidencePath = path124.join(evidenceDir, "lean-turbo-reviewer.json");
113393
+ const evidencePath = path125.join(evidenceDir, "lean-turbo-reviewer.json");
112532
113394
  const content = JSON.stringify({
112533
113395
  phase,
112534
113396
  verdict,
@@ -113340,7 +114202,7 @@ init_lint();
113340
114202
  init_spec_schema();
113341
114203
  init_create_tool();
113342
114204
  import * as fs88 from "node:fs";
113343
- import * as path125 from "node:path";
114205
+ import * as path126 from "node:path";
113344
114206
  var SPEC_FILE_NAME = "spec.md";
113345
114207
  var SWARM_DIR2 = ".swarm";
113346
114208
  var OBLIGATION_KEYWORDS = ["MUST", "SHALL", "SHOULD", "MAY"];
@@ -113393,7 +114255,7 @@ var lint_spec = createSwarmTool({
113393
114255
  async execute(_args, directory) {
113394
114256
  const errors5 = [];
113395
114257
  const warnings = [];
113396
- const specPath = path125.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
114258
+ const specPath = path126.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
113397
114259
  if (!fs88.existsSync(specPath)) {
113398
114260
  const result2 = {
113399
114261
  valid: false,
@@ -113465,12 +114327,12 @@ var lint_spec = createSwarmTool({
113465
114327
  // src/tools/mutation-test.ts
113466
114328
  init_zod();
113467
114329
  import * as fs89 from "node:fs";
113468
- import * as path127 from "node:path";
114330
+ import * as path128 from "node:path";
113469
114331
 
113470
114332
  // src/mutation/engine.ts
113471
114333
  import { spawnSync as spawnSync8 } from "node:child_process";
113472
- import { unlinkSync as unlinkSync17, writeFileSync as writeFileSync23 } from "node:fs";
113473
- import * as path126 from "node:path";
114334
+ import { unlinkSync as unlinkSync18, writeFileSync as writeFileSync24 } from "node:fs";
114335
+ import * as path127 from "node:path";
113474
114336
 
113475
114337
  // src/mutation/equivalence.ts
113476
114338
  function isStaticallyEquivalent(originalCode, mutatedCode) {
@@ -113616,9 +114478,9 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
113616
114478
  let patchFile;
113617
114479
  try {
113618
114480
  const safeId2 = patch.id.replace(/[^a-zA-Z0-9_-]/g, "_");
113619
- patchFile = path126.join(workingDir, `.mutation_patch_${safeId2}.diff`);
114481
+ patchFile = path127.join(workingDir, `.mutation_patch_${safeId2}.diff`);
113620
114482
  try {
113621
- writeFileSync23(patchFile, patch.patch);
114483
+ writeFileSync24(patchFile, patch.patch);
113622
114484
  } catch (writeErr) {
113623
114485
  error93 = `Failed to write patch file: ${writeErr}`;
113624
114486
  outcome = "error";
@@ -113714,7 +114576,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
113714
114576
  revertError = new Error(`Failed to revert mutation ${patch.id}: ${revertErr}. Working tree may be dirty.`);
113715
114577
  }
113716
114578
  try {
113717
- unlinkSync17(patchFile);
114579
+ unlinkSync18(patchFile);
113718
114580
  } catch (_unlinkErr) {}
113719
114581
  }
113720
114582
  }
@@ -114020,7 +114882,7 @@ var mutation_test = createSwarmTool({
114020
114882
  ];
114021
114883
  for (const filePath of uniquePaths) {
114022
114884
  try {
114023
- const resolvedPath = path127.resolve(cwd, filePath);
114885
+ const resolvedPath = path128.resolve(cwd, filePath);
114024
114886
  sourceFiles.set(filePath, fs89.readFileSync(resolvedPath, "utf-8"));
114025
114887
  } catch {}
114026
114888
  }
@@ -114042,22 +114904,22 @@ init_config();
114042
114904
  init_schema();
114043
114905
  init_manager2();
114044
114906
  import * as fs99 from "node:fs";
114045
- import * as path137 from "node:path";
114907
+ import * as path138 from "node:path";
114046
114908
 
114047
114909
  // src/full-auto/phase-approval.ts
114048
114910
  init_utils2();
114049
114911
  init_logger();
114050
114912
  init_state2();
114051
114913
  import * as fs90 from "node:fs";
114052
- import * as path128 from "node:path";
114914
+ import * as path129 from "node:path";
114053
114915
  var APPROVAL_TTL_MS = 24 * 60 * 60 * 1000;
114054
114916
  function readEvidenceDir(directory, phase) {
114055
114917
  try {
114056
- const dirPath = validateSwarmPath(directory, path128.posix.join("evidence", String(phase)));
114918
+ const dirPath = validateSwarmPath(directory, path129.posix.join("evidence", String(phase)));
114057
114919
  if (!fs90.existsSync(dirPath))
114058
114920
  return [];
114059
114921
  const entries = fs90.readdirSync(dirPath);
114060
- return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) => path128.join(dirPath, e));
114922
+ return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) => path129.join(dirPath, e));
114061
114923
  } catch {
114062
114924
  return [];
114063
114925
  }
@@ -114198,16 +115060,16 @@ init_plan_schema();
114198
115060
  init_ledger();
114199
115061
  init_manager();
114200
115062
  import * as fs91 from "node:fs";
114201
- import * as path129 from "node:path";
115063
+ import * as path130 from "node:path";
114202
115064
  async function writeCheckpoint(directory) {
114203
115065
  try {
114204
115066
  const plan = await loadPlan(directory);
114205
115067
  if (!plan)
114206
115068
  return;
114207
- const swarmDir = path129.join(directory, ".swarm");
115069
+ const swarmDir = path130.join(directory, ".swarm");
114208
115070
  fs91.mkdirSync(swarmDir, { recursive: true });
114209
- const jsonPath = path129.join(swarmDir, "SWARM_PLAN.json");
114210
- const mdPath = path129.join(swarmDir, "SWARM_PLAN.md");
115071
+ const jsonPath = path130.join(swarmDir, "SWARM_PLAN.json");
115072
+ const mdPath = path130.join(swarmDir, "SWARM_PLAN.md");
114211
115073
  fs91.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
114212
115074
  const md = derivePlanMarkdown(plan);
114213
115075
  fs91.writeFileSync(mdPath, md, "utf8");
@@ -114226,7 +115088,7 @@ init_telemetry();
114226
115088
  // src/turbo/lean/phase-ready.ts
114227
115089
  init_file_locks();
114228
115090
  import * as fs92 from "node:fs";
114229
- import * as path130 from "node:path";
115091
+ import * as path131 from "node:path";
114230
115092
  init_state3();
114231
115093
  var DEFAULT_CONFIG3 = {
114232
115094
  phase_reviewer: true,
@@ -114235,7 +115097,7 @@ var DEFAULT_CONFIG3 = {
114235
115097
  };
114236
115098
  function defaultReadPlanJson(dir) {
114237
115099
  try {
114238
- const planPath = path130.join(dir, ".swarm", "plan.json");
115100
+ const planPath = path131.join(dir, ".swarm", "plan.json");
114239
115101
  if (!fs92.existsSync(planPath))
114240
115102
  return null;
114241
115103
  const raw = fs92.readFileSync(planPath, "utf-8");
@@ -114250,7 +115112,7 @@ function defaultReadPlanJson(dir) {
114250
115112
  }
114251
115113
  function readReviewerEvidenceFromFile(directory, phase) {
114252
115114
  try {
114253
- const evidencePath = path130.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-reviewer.json");
115115
+ const evidencePath = path131.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-reviewer.json");
114254
115116
  if (!fs92.existsSync(evidencePath)) {
114255
115117
  return null;
114256
115118
  }
@@ -114270,7 +115132,7 @@ function readReviewerEvidenceFromFile(directory, phase) {
114270
115132
  }
114271
115133
  function readCriticEvidenceFromFile(directory, phase) {
114272
115134
  try {
114273
- const evidencePath = path130.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-critic.json");
115135
+ const evidencePath = path131.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-critic.json");
114274
115136
  if (!fs92.existsSync(evidencePath)) {
114275
115137
  return null;
114276
115138
  }
@@ -114289,7 +115151,7 @@ function readCriticEvidenceFromFile(directory, phase) {
114289
115151
  }
114290
115152
  }
114291
115153
  function listLaneEvidenceSync(directory, phase) {
114292
- const evidenceDir = path130.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
115154
+ const evidenceDir = path131.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
114293
115155
  let entries;
114294
115156
  try {
114295
115157
  entries = fs92.readdirSync(evidenceDir);
@@ -114359,7 +115221,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
114359
115221
  ...DEFAULT_CONFIG3,
114360
115222
  ...actualConfig
114361
115223
  };
114362
- const statePath = path130.join(directory, ".swarm", "turbo-state.json");
115224
+ const statePath = path131.join(directory, ".swarm", "turbo-state.json");
114363
115225
  if (!fs92.existsSync(statePath)) {
114364
115226
  return {
114365
115227
  ok: false,
@@ -114547,7 +115409,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
114547
115409
  }
114548
115410
  }
114549
115411
  if (mergedConfig.integrated_diff_required) {
114550
- const evidencePath = path130.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-phase.json");
115412
+ const evidencePath = path131.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-phase.json");
114551
115413
  let hasDiff = false;
114552
115414
  try {
114553
115415
  const content = fs92.readFileSync(evidencePath, "utf-8");
@@ -114699,13 +115561,13 @@ init_qa_gate_profile();
114699
115561
  init_manager();
114700
115562
  init_state();
114701
115563
  import * as fs93 from "node:fs";
114702
- import * as path131 from "node:path";
115564
+ import * as path132 from "node:path";
114703
115565
  async function runDriftGate(ctx) {
114704
115566
  const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
114705
115567
  let driftCheckEnabled = true;
114706
115568
  let driftHasSpecMd = false;
114707
115569
  try {
114708
- const specMdPath = path131.join(dir, ".swarm", "spec.md");
115570
+ const specMdPath = path132.join(dir, ".swarm", "spec.md");
114709
115571
  driftHasSpecMd = fs93.existsSync(specMdPath);
114710
115572
  const gatePlan = await loadPlan(dir);
114711
115573
  if (gatePlan) {
@@ -114733,7 +115595,7 @@ async function runDriftGate(ctx) {
114733
115595
  }
114734
115596
  let phaseType;
114735
115597
  try {
114736
- const planPath = path131.join(dir, ".swarm", "plan.json");
115598
+ const planPath = path132.join(dir, ".swarm", "plan.json");
114737
115599
  if (fs93.existsSync(planPath)) {
114738
115600
  const planRaw = fs93.readFileSync(planPath, "utf-8");
114739
115601
  const plan = JSON.parse(planRaw);
@@ -114752,7 +115614,7 @@ async function runDriftGate(ctx) {
114752
115614
  };
114753
115615
  }
114754
115616
  try {
114755
- const driftEvidencePath = path131.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
115617
+ const driftEvidencePath = path132.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
114756
115618
  let driftVerdictFound = false;
114757
115619
  let driftVerdictApproved = false;
114758
115620
  try {
@@ -114788,7 +115650,7 @@ async function runDriftGate(ctx) {
114788
115650
  let incompleteTaskCount = 0;
114789
115651
  let planParseable = false;
114790
115652
  try {
114791
- const planPath = path131.join(dir, ".swarm", "plan.json");
115653
+ const planPath = path132.join(dir, ".swarm", "plan.json");
114792
115654
  if (fs93.existsSync(planPath)) {
114793
115655
  const planRaw = fs93.readFileSync(planPath, "utf-8");
114794
115656
  const plan = JSON.parse(planRaw);
@@ -114870,7 +115732,7 @@ init_qa_gate_profile();
114870
115732
  init_manager();
114871
115733
  init_state();
114872
115734
  import * as fs94 from "node:fs";
114873
- import * as path132 from "node:path";
115735
+ import * as path133 from "node:path";
114874
115736
  async function runFinalCouncilGate(ctx) {
114875
115737
  const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
114876
115738
  let finalCouncilEnabled = false;
@@ -114887,7 +115749,7 @@ async function runFinalCouncilGate(ctx) {
114887
115749
  const effective = getEffectiveGates(profile, overrides);
114888
115750
  if (effective.final_council === true) {
114889
115751
  finalCouncilEnabled = true;
114890
- const fcPath = path132.join(dir, ".swarm", "evidence", "final-council.json");
115752
+ const fcPath = path133.join(dir, ".swarm", "evidence", "final-council.json");
114891
115753
  let fcVerdictFound = false;
114892
115754
  let _fcVerdict;
114893
115755
  try {
@@ -115017,7 +115879,7 @@ init_qa_gate_profile();
115017
115879
  init_manager();
115018
115880
  init_state();
115019
115881
  import * as fs95 from "node:fs";
115020
- import * as path133 from "node:path";
115882
+ import * as path134 from "node:path";
115021
115883
  async function runHallucinationGate(ctx) {
115022
115884
  const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
115023
115885
  try {
@@ -115030,7 +115892,7 @@ async function runHallucinationGate(ctx) {
115030
115892
  const overrides = session?.qaGateSessionOverrides ?? {};
115031
115893
  const effective = getEffectiveGates(profile, overrides);
115032
115894
  if (effective.hallucination_guard === true) {
115033
- const hgPath = path133.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
115895
+ const hgPath = path134.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
115034
115896
  let hgVerdictFound = false;
115035
115897
  let hgVerdictApproved = false;
115036
115898
  try {
@@ -115093,7 +115955,7 @@ init_qa_gate_profile();
115093
115955
  init_manager();
115094
115956
  init_state();
115095
115957
  import * as fs96 from "node:fs";
115096
- import * as path134 from "node:path";
115958
+ import * as path135 from "node:path";
115097
115959
  async function runMutationGate(ctx) {
115098
115960
  const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
115099
115961
  try {
@@ -115106,7 +115968,7 @@ async function runMutationGate(ctx) {
115106
115968
  const overrides = session?.qaGateSessionOverrides ?? {};
115107
115969
  const effective = getEffectiveGates(profile, overrides);
115108
115970
  if (effective.mutation_test === true) {
115109
- const mgPath = path134.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
115971
+ const mgPath = path135.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
115110
115972
  let mgVerdictFound = false;
115111
115973
  let mgVerdict;
115112
115974
  try {
@@ -115169,7 +116031,7 @@ init_qa_gate_profile();
115169
116031
  init_manager();
115170
116032
  init_state();
115171
116033
  import * as fs97 from "node:fs";
115172
- import * as path135 from "node:path";
116034
+ import * as path136 from "node:path";
115173
116035
  async function runPhaseCouncilGate(ctx) {
115174
116036
  const { phase, dir, sessionID, pluginConfig, agentsDispatched, safeWarn } = ctx;
115175
116037
  let councilModeEnabled = false;
@@ -115184,7 +116046,7 @@ async function runPhaseCouncilGate(ctx) {
115184
116046
  const effective = getEffectiveGates(profile, overrides);
115185
116047
  if (effective.council_mode === true) {
115186
116048
  councilModeEnabled = true;
115187
- const pcPath = path135.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
116049
+ const pcPath = path136.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
115188
116050
  let pcVerdictFound = false;
115189
116051
  let _pcVerdict;
115190
116052
  let pcQuorumSize;
@@ -115699,7 +116561,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
115699
116561
  }
115700
116562
  if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
115701
116563
  try {
115702
- const projectName = path137.basename(dir);
116564
+ const projectName = path138.basename(dir);
115703
116565
  const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
115704
116566
  if (curationResult) {
115705
116567
  const sessionState = swarmState.agentSessions.get(sessionID);
@@ -116142,7 +117004,7 @@ init_utils();
116142
117004
  init_bun_compat();
116143
117005
  init_create_tool();
116144
117006
  import * as fs100 from "node:fs";
116145
- import * as path138 from "node:path";
117007
+ import * as path139 from "node:path";
116146
117008
  var MAX_OUTPUT_BYTES6 = 52428800;
116147
117009
  var AUDIT_TIMEOUT_MS = 120000;
116148
117010
  function isValidEcosystem(value) {
@@ -116170,16 +117032,16 @@ function validateArgs3(args2) {
116170
117032
  function detectEcosystems(directory) {
116171
117033
  const ecosystems = [];
116172
117034
  const cwd = directory;
116173
- if (fs100.existsSync(path138.join(cwd, "package.json"))) {
117035
+ if (fs100.existsSync(path139.join(cwd, "package.json"))) {
116174
117036
  ecosystems.push("npm");
116175
117037
  }
116176
- if (fs100.existsSync(path138.join(cwd, "pyproject.toml")) || fs100.existsSync(path138.join(cwd, "requirements.txt"))) {
117038
+ if (fs100.existsSync(path139.join(cwd, "pyproject.toml")) || fs100.existsSync(path139.join(cwd, "requirements.txt"))) {
116177
117039
  ecosystems.push("pip");
116178
117040
  }
116179
- if (fs100.existsSync(path138.join(cwd, "Cargo.toml"))) {
117041
+ if (fs100.existsSync(path139.join(cwd, "Cargo.toml"))) {
116180
117042
  ecosystems.push("cargo");
116181
117043
  }
116182
- if (fs100.existsSync(path138.join(cwd, "go.mod"))) {
117044
+ if (fs100.existsSync(path139.join(cwd, "go.mod"))) {
116183
117045
  ecosystems.push("go");
116184
117046
  }
116185
117047
  try {
@@ -116188,13 +117050,13 @@ function detectEcosystems(directory) {
116188
117050
  ecosystems.push("dotnet");
116189
117051
  }
116190
117052
  } catch {}
116191
- if (fs100.existsSync(path138.join(cwd, "Gemfile")) || fs100.existsSync(path138.join(cwd, "Gemfile.lock"))) {
117053
+ if (fs100.existsSync(path139.join(cwd, "Gemfile")) || fs100.existsSync(path139.join(cwd, "Gemfile.lock"))) {
116192
117054
  ecosystems.push("ruby");
116193
117055
  }
116194
- if (fs100.existsSync(path138.join(cwd, "pubspec.yaml"))) {
117056
+ if (fs100.existsSync(path139.join(cwd, "pubspec.yaml"))) {
116195
117057
  ecosystems.push("dart");
116196
117058
  }
116197
- if (fs100.existsSync(path138.join(cwd, "composer.lock"))) {
117059
+ if (fs100.existsSync(path139.join(cwd, "composer.lock"))) {
116198
117060
  ecosystems.push("composer");
116199
117061
  }
116200
117062
  return ecosystems;
@@ -116207,7 +117069,7 @@ async function runNpmAudit(directory) {
116207
117069
  stderr: "pipe",
116208
117070
  cwd: directory
116209
117071
  });
116210
- const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
117072
+ const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
116211
117073
  const result = await Promise.race([
116212
117074
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr2]) => ({ stdout: stdout2, stderr: stderr2 })),
116213
117075
  timeoutPromise
@@ -116327,7 +117189,7 @@ async function runPipAudit(directory) {
116327
117189
  stderr: "pipe",
116328
117190
  cwd: directory
116329
117191
  });
116330
- const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
117192
+ const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
116331
117193
  const result = await Promise.race([
116332
117194
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr2]) => ({ stdout: stdout2, stderr: stderr2 })),
116333
117195
  timeoutPromise
@@ -116455,7 +117317,7 @@ async function runCargoAudit(directory) {
116455
117317
  stderr: "pipe",
116456
117318
  cwd: directory
116457
117319
  });
116458
- const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
117320
+ const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
116459
117321
  const result = await Promise.race([
116460
117322
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
116461
117323
  timeoutPromise
@@ -116579,7 +117441,7 @@ async function runGoAudit(directory) {
116579
117441
  stderr: "pipe",
116580
117442
  cwd: directory
116581
117443
  });
116582
- const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
117444
+ const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
116583
117445
  const result = await Promise.race([
116584
117446
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
116585
117447
  timeoutPromise
@@ -116712,7 +117574,7 @@ async function runDotnetAudit(directory) {
116712
117574
  stderr: "pipe",
116713
117575
  cwd: directory
116714
117576
  });
116715
- const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
117577
+ const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
116716
117578
  const result = await Promise.race([
116717
117579
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
116718
117580
  timeoutPromise
@@ -116828,7 +117690,7 @@ async function runBundleAudit(directory) {
116828
117690
  stderr: "pipe",
116829
117691
  cwd: directory
116830
117692
  });
116831
- const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
117693
+ const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
116832
117694
  const result = await Promise.race([
116833
117695
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
116834
117696
  timeoutPromise
@@ -116973,7 +117835,7 @@ async function runDartAudit(directory) {
116973
117835
  stderr: "pipe",
116974
117836
  cwd: directory
116975
117837
  });
116976
- const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
117838
+ const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
116977
117839
  const result = await Promise.race([
116978
117840
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
116979
117841
  timeoutPromise
@@ -117088,7 +117950,7 @@ async function runComposerAudit(directory) {
117088
117950
  stderr: "pipe",
117089
117951
  cwd: directory
117090
117952
  });
117091
- const timeoutPromise = new Promise((resolve45) => setTimeout(() => resolve45("timeout"), AUDIT_TIMEOUT_MS));
117953
+ const timeoutPromise = new Promise((resolve46) => setTimeout(() => resolve46("timeout"), AUDIT_TIMEOUT_MS));
117092
117954
  const result = await Promise.race([
117093
117955
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
117094
117956
  timeoutPromise
@@ -117331,7 +118193,7 @@ var pkg_audit = createSwarmTool({
117331
118193
  init_zod();
117332
118194
  init_manager2();
117333
118195
  import * as fs101 from "node:fs";
117334
- import * as path139 from "node:path";
118196
+ import * as path140 from "node:path";
117335
118197
  init_utils();
117336
118198
  init_create_tool();
117337
118199
  var MAX_FILE_SIZE = 1024 * 1024;
@@ -117454,7 +118316,7 @@ function isScaffoldFile(filePath) {
117454
118316
  if (SCAFFOLD_PATH_PATTERNS.some((pattern) => pattern.test(normalizedPath))) {
117455
118317
  return true;
117456
118318
  }
117457
- const filename = path139.basename(filePath);
118319
+ const filename = path140.basename(filePath);
117458
118320
  if (SCAFFOLD_FILENAME_PATTERNS.some((pattern) => pattern.test(filename))) {
117459
118321
  return true;
117460
118322
  }
@@ -117471,7 +118333,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
117471
118333
  if (regex.test(normalizedPath)) {
117472
118334
  return true;
117473
118335
  }
117474
- const filename = path139.basename(filePath);
118336
+ const filename = path140.basename(filePath);
117475
118337
  const filenameRegex = new RegExp(`^${regexPattern}$`, "i");
117476
118338
  if (filenameRegex.test(filename)) {
117477
118339
  return true;
@@ -117480,7 +118342,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
117480
118342
  return false;
117481
118343
  }
117482
118344
  function isParserSupported(filePath) {
117483
- const ext = path139.extname(filePath).toLowerCase();
118345
+ const ext = path140.extname(filePath).toLowerCase();
117484
118346
  return SUPPORTED_PARSER_EXTENSIONS.has(ext);
117485
118347
  }
117486
118348
  function isPlanFile(filePath) {
@@ -117727,9 +118589,9 @@ async function placeholderScan(input, directory) {
117727
118589
  let filesScanned = 0;
117728
118590
  const filesWithFindings = new Set;
117729
118591
  for (const filePath of changed_files) {
117730
- const fullPath = path139.isAbsolute(filePath) ? filePath : path139.resolve(directory, filePath);
117731
- const resolvedDirectory = path139.resolve(directory);
117732
- if (!fullPath.startsWith(resolvedDirectory + path139.sep) && fullPath !== resolvedDirectory) {
118592
+ const fullPath = path140.isAbsolute(filePath) ? filePath : path140.resolve(directory, filePath);
118593
+ const resolvedDirectory = path140.resolve(directory);
118594
+ if (!fullPath.startsWith(resolvedDirectory + path140.sep) && fullPath !== resolvedDirectory) {
117733
118595
  continue;
117734
118596
  }
117735
118597
  if (!fs101.existsSync(fullPath)) {
@@ -117738,7 +118600,7 @@ async function placeholderScan(input, directory) {
117738
118600
  if (isAllowedByGlobs(filePath, allow_globs)) {
117739
118601
  continue;
117740
118602
  }
117741
- const relativeFilePath = path139.relative(directory, fullPath).replace(/\\/g, "/");
118603
+ const relativeFilePath = path140.relative(directory, fullPath).replace(/\\/g, "/");
117742
118604
  if (FILE_ALLOWLIST.some((allowed) => relativeFilePath.endsWith(allowed))) {
117743
118605
  continue;
117744
118606
  }
@@ -117811,7 +118673,7 @@ var placeholder_scan = createSwarmTool({
117811
118673
 
117812
118674
  // src/tools/pre-check-batch.ts
117813
118675
  import * as fs105 from "node:fs";
117814
- import * as path143 from "node:path";
118676
+ import * as path144 from "node:path";
117815
118677
  init_zod();
117816
118678
  init_manager2();
117817
118679
  init_utils();
@@ -117952,7 +118814,7 @@ init_zod();
117952
118814
  init_manager2();
117953
118815
  init_detector();
117954
118816
  import * as fs104 from "node:fs";
117955
- import * as path142 from "node:path";
118817
+ import * as path143 from "node:path";
117956
118818
  import { extname as extname20 } from "node:path";
117957
118819
 
117958
118820
  // src/sast/rules/c.ts
@@ -118668,7 +119530,7 @@ function executeRulesSync(filePath, content, language) {
118668
119530
  // src/sast/semgrep.ts
118669
119531
  import * as child_process9 from "node:child_process";
118670
119532
  import * as fs102 from "node:fs";
118671
- import * as path140 from "node:path";
119533
+ import * as path141 from "node:path";
118672
119534
  var semgrepAvailableCache = null;
118673
119535
  var DEFAULT_RULES_DIR = ".swarm/semgrep-rules";
118674
119536
  var DEFAULT_TIMEOUT_MS3 = 30000;
@@ -118749,7 +119611,7 @@ function mapSemgrepSeverity(severity) {
118749
119611
  }
118750
119612
  }
118751
119613
  async function executeWithTimeout(command, args2, options) {
118752
- return new Promise((resolve47) => {
119614
+ return new Promise((resolve48) => {
118753
119615
  const child = child_process9.spawn(command, args2, {
118754
119616
  shell: false,
118755
119617
  cwd: options.cwd
@@ -118758,7 +119620,7 @@ async function executeWithTimeout(command, args2, options) {
118758
119620
  let stderr = "";
118759
119621
  const timeout = setTimeout(() => {
118760
119622
  child.kill("SIGTERM");
118761
- resolve47({
119623
+ resolve48({
118762
119624
  stdout,
118763
119625
  stderr: "Process timed out",
118764
119626
  exitCode: 124
@@ -118772,7 +119634,7 @@ async function executeWithTimeout(command, args2, options) {
118772
119634
  });
118773
119635
  child.on("close", (code) => {
118774
119636
  clearTimeout(timeout);
118775
- resolve47({
119637
+ resolve48({
118776
119638
  stdout,
118777
119639
  stderr,
118778
119640
  exitCode: code ?? 0
@@ -118780,7 +119642,7 @@ async function executeWithTimeout(command, args2, options) {
118780
119642
  });
118781
119643
  child.on("error", (err2) => {
118782
119644
  clearTimeout(timeout);
118783
- resolve47({
119645
+ resolve48({
118784
119646
  stdout,
118785
119647
  stderr: err2.message,
118786
119648
  exitCode: 1
@@ -118855,7 +119717,7 @@ async function runSemgrep(options) {
118855
119717
  }
118856
119718
  function getRulesDirectory(projectRoot) {
118857
119719
  if (projectRoot) {
118858
- return path140.resolve(projectRoot, DEFAULT_RULES_DIR);
119720
+ return path141.resolve(projectRoot, DEFAULT_RULES_DIR);
118859
119721
  }
118860
119722
  return DEFAULT_RULES_DIR;
118861
119723
  }
@@ -118876,24 +119738,24 @@ init_create_tool();
118876
119738
  init_utils2();
118877
119739
  import * as crypto11 from "node:crypto";
118878
119740
  import * as fs103 from "node:fs";
118879
- import * as path141 from "node:path";
119741
+ import * as path142 from "node:path";
118880
119742
  var BASELINE_SCHEMA_VERSION = "1.0.0";
118881
119743
  var MAX_BASELINE_FINDINGS = 2000;
118882
119744
  var MAX_BASELINE_BYTES = 2 * 1048576;
118883
119745
  var LOCK_RETRY_DELAYS_MS = [50, 100, 200, 400, 800];
118884
119746
  function normalizeFindingPath(directory, file3) {
118885
- const resolved = path141.isAbsolute(file3) ? file3 : path141.resolve(directory, file3);
118886
- const rel = path141.relative(path141.resolve(directory), resolved);
119747
+ const resolved = path142.isAbsolute(file3) ? file3 : path142.resolve(directory, file3);
119748
+ const rel = path142.relative(path142.resolve(directory), resolved);
118887
119749
  return rel.replace(/\\/g, "/");
118888
119750
  }
118889
119751
  function baselineRelPath(phase) {
118890
- return path141.join("evidence", String(phase), "sast-baseline.json");
119752
+ return path142.join("evidence", String(phase), "sast-baseline.json");
118891
119753
  }
118892
119754
  function tempRelPath(phase) {
118893
- return path141.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
119755
+ return path142.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
118894
119756
  }
118895
119757
  function lockRelPath(phase) {
118896
- return path141.join("evidence", String(phase), "sast-baseline.json.lock");
119758
+ return path142.join("evidence", String(phase), "sast-baseline.json.lock");
118897
119759
  }
118898
119760
  function getLine(lines, idx) {
118899
119761
  if (idx < 0 || idx >= lines.length)
@@ -118979,7 +119841,7 @@ async function acquireLock2(lockPath) {
118979
119841
  };
118980
119842
  } catch {
118981
119843
  if (attempt < LOCK_RETRY_DELAYS_MS.length) {
118982
- await new Promise((resolve48) => setTimeout(resolve48, LOCK_RETRY_DELAYS_MS[attempt]));
119844
+ await new Promise((resolve49) => setTimeout(resolve49, LOCK_RETRY_DELAYS_MS[attempt]));
118983
119845
  }
118984
119846
  }
118985
119847
  }
@@ -119014,8 +119876,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
119014
119876
  message: e instanceof Error ? e.message : "Path validation failed"
119015
119877
  };
119016
119878
  }
119017
- fs103.mkdirSync(path141.dirname(baselinePath), { recursive: true });
119018
- fs103.mkdirSync(path141.dirname(tempPath), { recursive: true });
119879
+ fs103.mkdirSync(path142.dirname(baselinePath), { recursive: true });
119880
+ fs103.mkdirSync(path142.dirname(tempPath), { recursive: true });
119019
119881
  const releaseLock = await acquireLock2(lockPath);
119020
119882
  try {
119021
119883
  let existing = null;
@@ -119288,9 +120150,9 @@ async function sastScan(input, directory, config3) {
119288
120150
  _filesSkipped++;
119289
120151
  continue;
119290
120152
  }
119291
- const resolvedPath = path142.isAbsolute(filePath) ? filePath : path142.resolve(directory, filePath);
119292
- const resolvedDirectory = path142.resolve(directory);
119293
- if (!resolvedPath.startsWith(resolvedDirectory + path142.sep) && resolvedPath !== resolvedDirectory) {
120153
+ const resolvedPath = path143.isAbsolute(filePath) ? filePath : path143.resolve(directory, filePath);
120154
+ const resolvedDirectory = path143.resolve(directory);
120155
+ if (!resolvedPath.startsWith(resolvedDirectory + path143.sep) && resolvedPath !== resolvedDirectory) {
119294
120156
  _filesSkipped++;
119295
120157
  continue;
119296
120158
  }
@@ -119605,20 +120467,20 @@ function validatePath(inputPath, baseDir, workspaceDir) {
119605
120467
  let resolved;
119606
120468
  const isWinAbs = isWindowsAbsolutePath(inputPath);
119607
120469
  if (isWinAbs) {
119608
- resolved = path143.win32.resolve(inputPath);
119609
- } else if (path143.isAbsolute(inputPath)) {
119610
- resolved = path143.resolve(inputPath);
120470
+ resolved = path144.win32.resolve(inputPath);
120471
+ } else if (path144.isAbsolute(inputPath)) {
120472
+ resolved = path144.resolve(inputPath);
119611
120473
  } else {
119612
- resolved = path143.resolve(baseDir, inputPath);
120474
+ resolved = path144.resolve(baseDir, inputPath);
119613
120475
  }
119614
- const workspaceResolved = path143.resolve(workspaceDir);
119615
- let relative27;
120476
+ const workspaceResolved = path144.resolve(workspaceDir);
120477
+ let relative28;
119616
120478
  if (isWinAbs) {
119617
- relative27 = path143.win32.relative(workspaceResolved, resolved);
120479
+ relative28 = path144.win32.relative(workspaceResolved, resolved);
119618
120480
  } else {
119619
- relative27 = path143.relative(workspaceResolved, resolved);
120481
+ relative28 = path144.relative(workspaceResolved, resolved);
119620
120482
  }
119621
- if (relative27.startsWith("..")) {
120483
+ if (relative28.startsWith("..")) {
119622
120484
  return "path traversal detected";
119623
120485
  }
119624
120486
  return null;
@@ -119681,7 +120543,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
119681
120543
  if (typeof file3 !== "string") {
119682
120544
  continue;
119683
120545
  }
119684
- const resolvedPath = path143.resolve(file3);
120546
+ const resolvedPath = path144.resolve(file3);
119685
120547
  const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
119686
120548
  if (validationError) {
119687
120549
  continue;
@@ -119838,7 +120700,7 @@ async function runSecretscanWithFiles(files, directory) {
119838
120700
  skippedFiles++;
119839
120701
  continue;
119840
120702
  }
119841
- const resolvedPath = path143.resolve(file3);
120703
+ const resolvedPath = path144.resolve(file3);
119842
120704
  const validationError = validatePath(resolvedPath, directory, directory);
119843
120705
  if (validationError) {
119844
120706
  skippedFiles++;
@@ -119856,7 +120718,7 @@ async function runSecretscanWithFiles(files, directory) {
119856
120718
  };
119857
120719
  }
119858
120720
  for (const file3 of validatedFiles) {
119859
- const ext = path143.extname(file3).toLowerCase();
120721
+ const ext = path144.extname(file3).toLowerCase();
119860
120722
  if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
119861
120723
  skippedFiles++;
119862
120724
  continue;
@@ -120075,7 +120937,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
120075
120937
  const preexistingFindings = [];
120076
120938
  for (const finding of findings) {
120077
120939
  const filePath = finding.location.file;
120078
- const normalised = path143.relative(directory, filePath).replace(/\\/g, "/");
120940
+ const normalised = path144.relative(directory, filePath).replace(/\\/g, "/");
120079
120941
  const changedLines = changedLineRanges.get(normalised);
120080
120942
  if (changedLines?.has(finding.location.line)) {
120081
120943
  newFindings.push(finding);
@@ -120126,7 +120988,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
120126
120988
  warn(`pre_check_batch: Invalid file path: ${file3}`);
120127
120989
  continue;
120128
120990
  }
120129
- changedFiles.push(path143.resolve(directory, file3));
120991
+ changedFiles.push(path144.resolve(directory, file3));
120130
120992
  }
120131
120993
  if (changedFiles.length === 0) {
120132
120994
  warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
@@ -120327,9 +121189,9 @@ var pre_check_batch = createSwarmTool({
120327
121189
  };
120328
121190
  return JSON.stringify(errorResult, null, 2);
120329
121191
  }
120330
- const resolvedDirectory = path143.resolve(typedArgs.directory);
120331
- const workspaceAnchor = path143.resolve(directory);
120332
- if (resolvedDirectory !== workspaceAnchor && resolvedDirectory.startsWith(workspaceAnchor + path143.sep)) {
121192
+ const resolvedDirectory = path144.resolve(typedArgs.directory);
121193
+ const workspaceAnchor = path144.resolve(directory);
121194
+ if (resolvedDirectory !== workspaceAnchor && resolvedDirectory.startsWith(workspaceAnchor + path144.sep)) {
120333
121195
  const subDirError = `directory "${typedArgs.directory}" is a subdirectory of the project root — pre_check_batch requires the project root directory "${workspaceAnchor}"`;
120334
121196
  const subDirResult = {
120335
121197
  gates_passed: false,
@@ -120381,7 +121243,7 @@ var pre_check_batch = createSwarmTool({
120381
121243
 
120382
121244
  // src/tools/repo-map.ts
120383
121245
  init_zod();
120384
- import * as path144 from "node:path";
121246
+ import * as path145 from "node:path";
120385
121247
  init_path_security();
120386
121248
  init_create_tool();
120387
121249
  var VALID_ACTIONS = [
@@ -120406,7 +121268,7 @@ function validateFile(p) {
120406
121268
  return "file contains control characters";
120407
121269
  if (containsPathTraversal(p))
120408
121270
  return "file contains path traversal";
120409
- if (path144.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
121271
+ if (path145.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
120410
121272
  return "file must be a workspace-relative path, not absolute";
120411
121273
  }
120412
121274
  return null;
@@ -120429,8 +121291,8 @@ function ok(action, payload) {
120429
121291
  }
120430
121292
  function toRelativeGraphPath(input, workspaceRoot) {
120431
121293
  const normalized = input.replace(/\\/g, "/");
120432
- if (path144.isAbsolute(normalized)) {
120433
- const rel = path144.relative(workspaceRoot, normalized).replace(/\\/g, "/");
121294
+ if (path145.isAbsolute(normalized)) {
121295
+ const rel = path145.relative(workspaceRoot, normalized).replace(/\\/g, "/");
120434
121296
  return normalizeGraphPath2(rel);
120435
121297
  }
120436
121298
  return normalizeGraphPath2(normalized);
@@ -120576,7 +121438,7 @@ var repo_map = createSwarmTool({
120576
121438
  init_zod();
120577
121439
  init_create_tool();
120578
121440
  import * as fs106 from "node:fs";
120579
- import * as path145 from "node:path";
121441
+ import * as path146 from "node:path";
120580
121442
  var SPEC_FILE = ".swarm/spec.md";
120581
121443
  var EVIDENCE_DIR4 = ".swarm/evidence";
120582
121444
  var OBLIGATION_KEYWORDS2 = ["MUST", "SHOULD", "SHALL"];
@@ -120645,7 +121507,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
120645
121507
  return [];
120646
121508
  }
120647
121509
  for (const entry of entries) {
120648
- const entryPath = path145.join(evidenceDir, entry);
121510
+ const entryPath = path146.join(evidenceDir, entry);
120649
121511
  try {
120650
121512
  const stat9 = fs106.statSync(entryPath);
120651
121513
  if (!stat9.isDirectory()) {
@@ -120661,11 +121523,11 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
120661
121523
  if (entryPhase !== String(phase)) {
120662
121524
  continue;
120663
121525
  }
120664
- const evidenceFilePath = path145.join(entryPath, "evidence.json");
121526
+ const evidenceFilePath = path146.join(entryPath, "evidence.json");
120665
121527
  try {
120666
- const resolvedPath = path145.resolve(evidenceFilePath);
120667
- const evidenceDirResolved = path145.resolve(evidenceDir);
120668
- if (!resolvedPath.startsWith(evidenceDirResolved + path145.sep)) {
121528
+ const resolvedPath = path146.resolve(evidenceFilePath);
121529
+ const evidenceDirResolved = path146.resolve(evidenceDir);
121530
+ if (!resolvedPath.startsWith(evidenceDirResolved + path146.sep)) {
120669
121531
  continue;
120670
121532
  }
120671
121533
  const stat9 = fs106.lstatSync(evidenceFilePath);
@@ -120699,7 +121561,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
120699
121561
  if (Array.isArray(diffEntry.files_changed)) {
120700
121562
  for (const file3 of diffEntry.files_changed) {
120701
121563
  if (typeof file3 === "string") {
120702
- touchedFiles.add(path145.resolve(cwd, file3));
121564
+ touchedFiles.add(path146.resolve(cwd, file3));
120703
121565
  }
120704
121566
  }
120705
121567
  }
@@ -120712,8 +121574,8 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
120712
121574
  }
120713
121575
  function searchFileForKeywords(filePath, keywords, cwd) {
120714
121576
  try {
120715
- const resolvedPath = path145.resolve(filePath);
120716
- const cwdResolved = path145.resolve(cwd);
121577
+ const resolvedPath = path146.resolve(filePath);
121578
+ const cwdResolved = path146.resolve(cwd);
120717
121579
  if (!resolvedPath.startsWith(cwdResolved)) {
120718
121580
  return false;
120719
121581
  }
@@ -120847,7 +121709,7 @@ var req_coverage = createSwarmTool({
120847
121709
  }, null, 2);
120848
121710
  }
120849
121711
  const cwd = inputDirectory || directory;
120850
- const specPath = path145.join(cwd, SPEC_FILE);
121712
+ const specPath = path146.join(cwd, SPEC_FILE);
120851
121713
  let specContent;
120852
121714
  try {
120853
121715
  specContent = fs106.readFileSync(specPath, "utf-8");
@@ -120874,7 +121736,7 @@ var req_coverage = createSwarmTool({
120874
121736
  message: "No FR requirements found in spec.md"
120875
121737
  }, null, 2);
120876
121738
  }
120877
- const evidenceDir = path145.join(cwd, EVIDENCE_DIR4);
121739
+ const evidenceDir = path146.join(cwd, EVIDENCE_DIR4);
120878
121740
  const touchedFiles = readTouchedFiles(evidenceDir, phase, cwd);
120879
121741
  const analyzedRequirements = [];
120880
121742
  let coveredCount = 0;
@@ -120900,7 +121762,7 @@ var req_coverage = createSwarmTool({
120900
121762
  requirements: analyzedRequirements
120901
121763
  };
120902
121764
  const reportFilename = `req-coverage-phase-${phase}.json`;
120903
- const reportPath = path145.join(evidenceDir, reportFilename);
121765
+ const reportPath = path146.join(evidenceDir, reportFilename);
120904
121766
  try {
120905
121767
  if (!fs106.existsSync(evidenceDir)) {
120906
121768
  fs106.mkdirSync(evidenceDir, { recursive: true });
@@ -120990,7 +121852,7 @@ init_qa_gate_profile();
120990
121852
  init_file_locks();
120991
121853
  import * as crypto12 from "node:crypto";
120992
121854
  import * as fs107 from "node:fs";
120993
- import * as path146 from "node:path";
121855
+ import * as path147 from "node:path";
120994
121856
  init_ledger();
120995
121857
  init_manager();
120996
121858
  init_state();
@@ -121071,8 +121933,8 @@ async function executeSavePlan(args2, fallbackDir) {
121071
121933
  };
121072
121934
  }
121073
121935
  if (args2.working_directory && fallbackDir) {
121074
- const resolvedTarget = path146.resolve(args2.working_directory);
121075
- const resolvedRoot = path146.resolve(fallbackDir);
121936
+ const resolvedTarget = path147.resolve(args2.working_directory);
121937
+ const resolvedRoot = path147.resolve(fallbackDir);
121076
121938
  let fallbackExists = false;
121077
121939
  try {
121078
121940
  fs107.accessSync(resolvedRoot, fs107.constants.F_OK);
@@ -121081,7 +121943,7 @@ async function executeSavePlan(args2, fallbackDir) {
121081
121943
  fallbackExists = false;
121082
121944
  }
121083
121945
  if (fallbackExists) {
121084
- const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path146.sep);
121946
+ const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path147.sep);
121085
121947
  if (isSubdirectory) {
121086
121948
  return {
121087
121949
  success: false,
@@ -121097,7 +121959,7 @@ async function executeSavePlan(args2, fallbackDir) {
121097
121959
  let specMtime;
121098
121960
  let specHash;
121099
121961
  if (process.env.SWARM_SKIP_SPEC_GATE !== "1") {
121100
- const specPath = path146.join(targetWorkspace, ".swarm", "spec.md");
121962
+ const specPath = path147.join(targetWorkspace, ".swarm", "spec.md");
121101
121963
  try {
121102
121964
  const stat9 = await fs107.promises.stat(specPath);
121103
121965
  specMtime = stat9.mtime.toISOString();
@@ -121113,7 +121975,7 @@ async function executeSavePlan(args2, fallbackDir) {
121113
121975
  }
121114
121976
  }
121115
121977
  if (process.env.SWARM_SKIP_GATE_SELECTION !== "1") {
121116
- const contextPath = path146.join(targetWorkspace, ".swarm", "context.md");
121978
+ const contextPath = path147.join(targetWorkspace, ".swarm", "context.md");
121117
121979
  let contextContent = "";
121118
121980
  try {
121119
121981
  contextContent = await fs107.promises.readFile(contextPath, "utf8");
@@ -121403,7 +122265,7 @@ async function executeSavePlan(args2, fallbackDir) {
121403
122265
  }
121404
122266
  await writeCheckpoint(dir).catch(() => {});
121405
122267
  try {
121406
- const markerPath = path146.join(dir, ".swarm", ".plan-write-marker");
122268
+ const markerPath = path147.join(dir, ".swarm", ".plan-write-marker");
121407
122269
  const marker = JSON.stringify({
121408
122270
  source: "save_plan",
121409
122271
  timestamp: new Date().toISOString(),
@@ -121426,7 +122288,7 @@ async function executeSavePlan(args2, fallbackDir) {
121426
122288
  return {
121427
122289
  success: true,
121428
122290
  message: "Plan saved successfully",
121429
- plan_path: path146.join(dir, ".swarm", "plan.json"),
122291
+ plan_path: path147.join(dir, ".swarm", "plan.json"),
121430
122292
  phases_count: plan.phases.length,
121431
122293
  tasks_count: tasksCount,
121432
122294
  ...resolvedProfile !== undefined ? { execution_profile: resolvedProfile } : {},
@@ -121493,7 +122355,7 @@ var save_plan = createSwarmTool({
121493
122355
  init_zod();
121494
122356
  init_manager2();
121495
122357
  import * as fs108 from "node:fs";
121496
- import * as path147 from "node:path";
122358
+ import * as path148 from "node:path";
121497
122359
 
121498
122360
  // src/sbom/detectors/index.ts
121499
122361
  init_utils();
@@ -122343,7 +123205,7 @@ function findManifestFiles(rootDir) {
122343
123205
  try {
122344
123206
  const entries = fs108.readdirSync(dir, { withFileTypes: true });
122345
123207
  for (const entry of entries) {
122346
- const fullPath = path147.join(dir, entry.name);
123208
+ const fullPath = path148.join(dir, entry.name);
122347
123209
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
122348
123210
  continue;
122349
123211
  }
@@ -122352,7 +123214,7 @@ function findManifestFiles(rootDir) {
122352
123214
  } else if (entry.isFile()) {
122353
123215
  for (const pattern of patterns) {
122354
123216
  if (simpleGlobToRegex(pattern).test(entry.name)) {
122355
- manifestFiles.push(path147.relative(rootDir, fullPath));
123217
+ manifestFiles.push(path148.relative(rootDir, fullPath));
122356
123218
  break;
122357
123219
  }
122358
123220
  }
@@ -122370,11 +123232,11 @@ function findManifestFilesInDirs(directories, workingDir) {
122370
123232
  try {
122371
123233
  const entries = fs108.readdirSync(dir, { withFileTypes: true });
122372
123234
  for (const entry of entries) {
122373
- const fullPath = path147.join(dir, entry.name);
123235
+ const fullPath = path148.join(dir, entry.name);
122374
123236
  if (entry.isFile()) {
122375
123237
  for (const pattern of patterns) {
122376
123238
  if (simpleGlobToRegex(pattern).test(entry.name)) {
122377
- found.push(path147.relative(workingDir, fullPath));
123239
+ found.push(path148.relative(workingDir, fullPath));
122378
123240
  break;
122379
123241
  }
122380
123242
  }
@@ -122387,11 +123249,11 @@ function findManifestFilesInDirs(directories, workingDir) {
122387
123249
  function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
122388
123250
  const dirs = new Set;
122389
123251
  for (const file3 of changedFiles) {
122390
- let currentDir = path147.dirname(file3);
123252
+ let currentDir = path148.dirname(file3);
122391
123253
  while (true) {
122392
- if (currentDir && currentDir !== "." && currentDir !== path147.sep) {
122393
- dirs.add(path147.join(workingDir, currentDir));
122394
- const parent = path147.dirname(currentDir);
123254
+ if (currentDir && currentDir !== "." && currentDir !== path148.sep) {
123255
+ dirs.add(path148.join(workingDir, currentDir));
123256
+ const parent = path148.dirname(currentDir);
122395
123257
  if (parent === currentDir)
122396
123258
  break;
122397
123259
  currentDir = parent;
@@ -122475,7 +123337,7 @@ var sbom_generate = createSwarmTool({
122475
123337
  const changedFiles = obj.changed_files;
122476
123338
  const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
122477
123339
  const workingDir = directory;
122478
- const outputDir = path147.isAbsolute(relativeOutputDir) ? relativeOutputDir : path147.join(workingDir, relativeOutputDir);
123340
+ const outputDir = path148.isAbsolute(relativeOutputDir) ? relativeOutputDir : path148.join(workingDir, relativeOutputDir);
122479
123341
  let manifestFiles = [];
122480
123342
  if (scope === "all") {
122481
123343
  manifestFiles = findManifestFiles(workingDir);
@@ -122498,7 +123360,7 @@ var sbom_generate = createSwarmTool({
122498
123360
  const processedFiles = [];
122499
123361
  for (const manifestFile of manifestFiles) {
122500
123362
  try {
122501
- const fullPath = path147.isAbsolute(manifestFile) ? manifestFile : path147.join(workingDir, manifestFile);
123363
+ const fullPath = path148.isAbsolute(manifestFile) ? manifestFile : path148.join(workingDir, manifestFile);
122502
123364
  if (!fs108.existsSync(fullPath)) {
122503
123365
  continue;
122504
123366
  }
@@ -122515,7 +123377,7 @@ var sbom_generate = createSwarmTool({
122515
123377
  const bom = generateCycloneDX(allComponents);
122516
123378
  const bomJson = serializeCycloneDX(bom);
122517
123379
  const filename = generateSbomFilename();
122518
- const outputPath = path147.join(outputDir, filename);
123380
+ const outputPath = path148.join(outputDir, filename);
122519
123381
  fs108.writeFileSync(outputPath, bomJson, "utf-8");
122520
123382
  const verdict = processedFiles.length > 0 ? "pass" : "pass";
122521
123383
  try {
@@ -122560,7 +123422,7 @@ var sbom_generate = createSwarmTool({
122560
123422
  init_zod();
122561
123423
  init_create_tool();
122562
123424
  import * as fs109 from "node:fs";
122563
- import * as path148 from "node:path";
123425
+ import * as path149 from "node:path";
122564
123426
  var SPEC_CANDIDATES = [
122565
123427
  "openapi.json",
122566
123428
  "openapi.yaml",
@@ -122592,12 +123454,12 @@ function normalizePath5(p) {
122592
123454
  }
122593
123455
  function discoverSpecFile(cwd, specFileArg) {
122594
123456
  if (specFileArg) {
122595
- const resolvedPath = path148.resolve(cwd, specFileArg);
122596
- const normalizedCwd = cwd.endsWith(path148.sep) ? cwd : cwd + path148.sep;
123457
+ const resolvedPath = path149.resolve(cwd, specFileArg);
123458
+ const normalizedCwd = cwd.endsWith(path149.sep) ? cwd : cwd + path149.sep;
122597
123459
  if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
122598
123460
  throw new Error("Invalid spec_file: path traversal detected");
122599
123461
  }
122600
- const ext = path148.extname(resolvedPath).toLowerCase();
123462
+ const ext = path149.extname(resolvedPath).toLowerCase();
122601
123463
  if (!ALLOWED_EXTENSIONS.includes(ext)) {
122602
123464
  throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
122603
123465
  }
@@ -122611,7 +123473,7 @@ function discoverSpecFile(cwd, specFileArg) {
122611
123473
  return resolvedPath;
122612
123474
  }
122613
123475
  for (const candidate of SPEC_CANDIDATES) {
122614
- const candidatePath = path148.resolve(cwd, candidate);
123476
+ const candidatePath = path149.resolve(cwd, candidate);
122615
123477
  if (fs109.existsSync(candidatePath)) {
122616
123478
  const stats = fs109.statSync(candidatePath);
122617
123479
  if (stats.size <= MAX_SPEC_SIZE) {
@@ -122623,7 +123485,7 @@ function discoverSpecFile(cwd, specFileArg) {
122623
123485
  }
122624
123486
  function parseSpec(specFile) {
122625
123487
  const content = fs109.readFileSync(specFile, "utf-8");
122626
- const ext = path148.extname(specFile).toLowerCase();
123488
+ const ext = path149.extname(specFile).toLowerCase();
122627
123489
  if (ext === ".json") {
122628
123490
  return parseJsonSpec(content);
122629
123491
  }
@@ -122699,7 +123561,7 @@ function extractRoutes(cwd) {
122699
123561
  return;
122700
123562
  }
122701
123563
  for (const entry of entries) {
122702
- const fullPath = path148.join(dir, entry.name);
123564
+ const fullPath = path149.join(dir, entry.name);
122703
123565
  if (entry.isSymbolicLink()) {
122704
123566
  continue;
122705
123567
  }
@@ -122709,7 +123571,7 @@ function extractRoutes(cwd) {
122709
123571
  }
122710
123572
  walkDir(fullPath);
122711
123573
  } else if (entry.isFile()) {
122712
- const ext = path148.extname(entry.name).toLowerCase();
123574
+ const ext = path149.extname(entry.name).toLowerCase();
122713
123575
  const baseName = entry.name.toLowerCase();
122714
123576
  if (![".ts", ".js", ".mjs"].includes(ext)) {
122715
123577
  continue;
@@ -122878,7 +123740,7 @@ init_bun_compat();
122878
123740
  init_path_security();
122879
123741
  init_create_tool();
122880
123742
  import * as fs110 from "node:fs";
122881
- import * as path149 from "node:path";
123743
+ import * as path150 from "node:path";
122882
123744
  var DEFAULT_MAX_RESULTS = 100;
122883
123745
  var DEFAULT_MAX_LINES = 200;
122884
123746
  var REGEX_TIMEOUT_MS = 5000;
@@ -122901,24 +123763,24 @@ function matchesGlobs(filePath, globs) {
122901
123763
  return true;
122902
123764
  return globs.some((glob) => globMatch(glob, filePath));
122903
123765
  }
122904
- var WINDOWS_RESERVED_NAMES3 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
122905
- function containsWindowsAttacks3(str) {
123766
+ var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
123767
+ function containsWindowsAttacks4(str) {
122906
123768
  if (/:[^\\/]/.test(str))
122907
123769
  return true;
122908
123770
  const parts2 = str.split(/[/\\]/);
122909
123771
  for (const part of parts2) {
122910
- if (WINDOWS_RESERVED_NAMES3.test(part))
123772
+ if (WINDOWS_RESERVED_NAMES4.test(part))
122911
123773
  return true;
122912
123774
  }
122913
123775
  return false;
122914
123776
  }
122915
123777
  function isPathInWorkspace3(filePath, workspace) {
122916
123778
  try {
122917
- const resolvedPath = path149.resolve(workspace, filePath);
123779
+ const resolvedPath = path150.resolve(workspace, filePath);
122918
123780
  const realWorkspace = fs110.realpathSync(workspace);
122919
123781
  const realResolvedPath = fs110.realpathSync(resolvedPath);
122920
- const relativePath = path149.relative(realWorkspace, realResolvedPath);
122921
- if (relativePath.startsWith("..") || path149.isAbsolute(relativePath)) {
123782
+ const relativePath = path150.relative(realWorkspace, realResolvedPath);
123783
+ if (relativePath.startsWith("..") || path150.isAbsolute(relativePath)) {
122922
123784
  return false;
122923
123785
  }
122924
123786
  return true;
@@ -122931,11 +123793,11 @@ function validatePathForRead2(filePath, workspace) {
122931
123793
  }
122932
123794
  function findRgInEnvPath() {
122933
123795
  const searchPath = process.env.PATH ?? "";
122934
- for (const dir of searchPath.split(path149.delimiter)) {
123796
+ for (const dir of searchPath.split(path150.delimiter)) {
122935
123797
  if (!dir)
122936
123798
  continue;
122937
123799
  const isWindows = process.platform === "win32";
122938
- const candidate = path149.join(dir, isWindows ? "rg.exe" : "rg");
123800
+ const candidate = path150.join(dir, isWindows ? "rg.exe" : "rg");
122939
123801
  if (fs110.existsSync(candidate))
122940
123802
  return candidate;
122941
123803
  }
@@ -122990,7 +123852,7 @@ async function ripgrepSearch(opts) {
122990
123852
  stderr: "pipe",
122991
123853
  cwd: opts.workspace
122992
123854
  });
122993
- const timeout = new Promise((resolve54) => setTimeout(() => resolve54("timeout"), REGEX_TIMEOUT_MS));
123855
+ const timeout = new Promise((resolve55) => setTimeout(() => resolve55("timeout"), REGEX_TIMEOUT_MS));
122994
123856
  const exitPromise = proc.exited;
122995
123857
  const result = await Promise.race([exitPromise, timeout]);
122996
123858
  if (result === "timeout") {
@@ -123065,8 +123927,8 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
123065
123927
  try {
123066
123928
  const entries = fs110.readdirSync(dir, { withFileTypes: true });
123067
123929
  for (const entry of entries) {
123068
- const fullPath = path149.join(dir, entry.name);
123069
- const relativePath = path149.relative(workspace, fullPath);
123930
+ const fullPath = path150.join(dir, entry.name);
123931
+ const relativePath = path150.relative(workspace, fullPath);
123070
123932
  if (!validatePathForRead2(fullPath, workspace)) {
123071
123933
  continue;
123072
123934
  }
@@ -123107,7 +123969,7 @@ async function fallbackSearch(opts) {
123107
123969
  const matches = [];
123108
123970
  let total = 0;
123109
123971
  for (const file3 of files) {
123110
- const fullPath = path149.join(opts.workspace, file3);
123972
+ const fullPath = path150.join(opts.workspace, file3);
123111
123973
  if (!validatePathForRead2(fullPath, opts.workspace)) {
123112
123974
  continue;
123113
123975
  }
@@ -123220,14 +124082,14 @@ var search = createSwarmTool({
123220
124082
  message: "Exclude pattern contains path traversal sequence"
123221
124083
  }, null, 2);
123222
124084
  }
123223
- if (include && containsWindowsAttacks3(include)) {
124085
+ if (include && containsWindowsAttacks4(include)) {
123224
124086
  return JSON.stringify({
123225
124087
  error: true,
123226
124088
  type: "path-escape",
123227
124089
  message: "Include pattern contains invalid Windows-specific sequence"
123228
124090
  }, null, 2);
123229
124091
  }
123230
- if (exclude && containsWindowsAttacks3(exclude)) {
124092
+ if (exclude && containsWindowsAttacks4(exclude)) {
123231
124093
  return JSON.stringify({
123232
124094
  error: true,
123233
124095
  type: "path-escape",
@@ -123520,7 +124382,7 @@ init_config();
123520
124382
  init_schema();
123521
124383
  init_create_tool();
123522
124384
  import { mkdir as mkdir24, rename as rename10, writeFile as writeFile19 } from "node:fs/promises";
123523
- import * as path150 from "node:path";
124385
+ import * as path151 from "node:path";
123524
124386
  var MAX_SPEC_BYTES = 256 * 1024;
123525
124387
  var spec_write = createSwarmTool({
123526
124388
  description: "Write the canonical project spec to .swarm/spec.md. Atomic write, size-bounded (256 KiB), heading-required. Honors spec_writer.allow_spec_write.",
@@ -123561,8 +124423,8 @@ var spec_write = createSwarmTool({
123561
124423
  reason: 'spec must contain at least one top-level "# Heading"'
123562
124424
  }, null, 2);
123563
124425
  }
123564
- const target = path150.join(directory, ".swarm", "spec.md");
123565
- await mkdir24(path150.dirname(target), { recursive: true });
124426
+ const target = path151.join(directory, ".swarm", "spec.md");
124427
+ await mkdir24(path151.dirname(target), { recursive: true });
123566
124428
  const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
123567
124429
  let finalContent = content;
123568
124430
  if (mode === "append") {
@@ -123591,14 +124453,14 @@ ${content}
123591
124453
  init_zod();
123592
124454
  init_loader();
123593
124455
  import {
123594
- existsSync as existsSync84,
123595
- mkdirSync as mkdirSync35,
123596
- readFileSync as readFileSync71,
123597
- renameSync as renameSync21,
123598
- unlinkSync as unlinkSync19,
123599
- writeFileSync as writeFileSync29
124456
+ existsSync as existsSync85,
124457
+ mkdirSync as mkdirSync36,
124458
+ readFileSync as readFileSync72,
124459
+ renameSync as renameSync22,
124460
+ unlinkSync as unlinkSync20,
124461
+ writeFileSync as writeFileSync30
123600
124462
  } from "node:fs";
123601
- import path151 from "node:path";
124463
+ import path152 from "node:path";
123602
124464
  init_create_tool();
123603
124465
  init_resolve_working_directory();
123604
124466
  var VerdictSchema2 = exports_external.object({
@@ -123728,9 +124590,9 @@ var submit_phase_council_verdicts = createSwarmTool({
123728
124590
  }
123729
124591
  });
123730
124592
  function getPhaseMutationGapFinding(phaseNumber, workingDir) {
123731
- const mutationGatePath = path151.join(workingDir, ".swarm", "evidence", String(phaseNumber), "mutation-gate.json");
124593
+ const mutationGatePath = path152.join(workingDir, ".swarm", "evidence", String(phaseNumber), "mutation-gate.json");
123732
124594
  try {
123733
- const raw = readFileSync71(mutationGatePath, "utf-8");
124595
+ const raw = readFileSync72(mutationGatePath, "utf-8");
123734
124596
  const parsed = JSON.parse(raw);
123735
124597
  const gateEntry = (parsed.entries ?? []).find((entry) => entry?.type === "mutation-gate");
123736
124598
  if (!gateEntry) {
@@ -123790,9 +124652,9 @@ function getPhaseMutationGapFinding(phaseNumber, workingDir) {
123790
124652
  }
123791
124653
  }
123792
124654
  function writePhaseCouncilEvidence(workingDir, synthesis) {
123793
- const evidenceDir = path151.join(workingDir, ".swarm", "evidence", String(synthesis.phaseNumber));
123794
- mkdirSync35(evidenceDir, { recursive: true });
123795
- const evidenceFile = path151.join(evidenceDir, "phase-council.json");
124655
+ const evidenceDir = path152.join(workingDir, ".swarm", "evidence", String(synthesis.phaseNumber));
124656
+ mkdirSync36(evidenceDir, { recursive: true });
124657
+ const evidenceFile = path152.join(evidenceDir, "phase-council.json");
123796
124658
  const evidenceBundle = {
123797
124659
  entries: [
123798
124660
  {
@@ -123825,11 +124687,11 @@ function writePhaseCouncilEvidence(workingDir, synthesis) {
123825
124687
  };
123826
124688
  const tempFile = `${evidenceFile}.tmp-${Date.now()}`;
123827
124689
  try {
123828
- writeFileSync29(tempFile, JSON.stringify(evidenceBundle, null, 2), "utf-8");
123829
- renameSync21(tempFile, evidenceFile);
124690
+ writeFileSync30(tempFile, JSON.stringify(evidenceBundle, null, 2), "utf-8");
124691
+ renameSync22(tempFile, evidenceFile);
123830
124692
  } finally {
123831
- if (existsSync84(tempFile)) {
123832
- unlinkSync19(tempFile);
124693
+ if (existsSync85(tempFile)) {
124694
+ unlinkSync20(tempFile);
123833
124695
  }
123834
124696
  }
123835
124697
  }
@@ -123854,28 +124716,28 @@ init_zod();
123854
124716
  init_path_security();
123855
124717
  init_create_tool();
123856
124718
  import * as fs111 from "node:fs";
123857
- import * as path152 from "node:path";
123858
- var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
123859
- function containsWindowsAttacks4(str) {
124719
+ import * as path153 from "node:path";
124720
+ var WINDOWS_RESERVED_NAMES5 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
124721
+ function containsWindowsAttacks5(str) {
123860
124722
  if (/:[^\\/]/.test(str))
123861
124723
  return true;
123862
124724
  const parts2 = str.split(/[/\\]/);
123863
124725
  for (const part of parts2) {
123864
- if (WINDOWS_RESERVED_NAMES4.test(part))
124726
+ if (WINDOWS_RESERVED_NAMES5.test(part))
123865
124727
  return true;
123866
124728
  }
123867
124729
  return false;
123868
124730
  }
123869
124731
  function isPathInWorkspace4(filePath, workspace) {
123870
124732
  try {
123871
- const resolvedPath = path152.resolve(workspace, filePath);
124733
+ const resolvedPath = path153.resolve(workspace, filePath);
123872
124734
  if (!fs111.existsSync(resolvedPath)) {
123873
124735
  return true;
123874
124736
  }
123875
124737
  const realWorkspace = fs111.realpathSync(workspace);
123876
124738
  const realResolvedPath = fs111.realpathSync(resolvedPath);
123877
- const relativePath = path152.relative(realWorkspace, realResolvedPath);
123878
- if (relativePath.startsWith("..") || path152.isAbsolute(relativePath)) {
124739
+ const relativePath = path153.relative(realWorkspace, realResolvedPath);
124740
+ if (relativePath.startsWith("..") || path153.isAbsolute(relativePath)) {
123879
124741
  return false;
123880
124742
  }
123881
124743
  return true;
@@ -123890,7 +124752,7 @@ function validateFilePath(filePath, workspace) {
123890
124752
  return false;
123891
124753
  if (containsControlChars(filePath))
123892
124754
  return false;
123893
- if (containsWindowsAttacks4(filePath))
124755
+ if (containsWindowsAttacks5(filePath))
123894
124756
  return false;
123895
124757
  return isPathInWorkspace4(filePath, workspace);
123896
124758
  }
@@ -123903,12 +124765,12 @@ function findContextMatch(content, contextBefore, contextAfter, oldContent) {
123903
124765
  if (contextBefore && contextBefore.length > 0) {
123904
124766
  for (let i2 = 0;i2 <= lines.length - contextBefore.length; i2++) {
123905
124767
  const slice = lines.slice(i2, i2 + contextBefore.length);
123906
- if (arraysEqual(slice, contextBefore)) {
124768
+ if (arraysEqual2(slice, contextBefore)) {
123907
124769
  const afterStart = i2 + contextBefore.length;
123908
124770
  if (contextAfter && contextAfter.length > 0) {
123909
124771
  for (let j = afterStart;j <= lines.length - contextAfter.length; j++) {
123910
124772
  const afterSlice = lines.slice(j, j + contextAfter.length);
123911
- if (arraysEqual(afterSlice, contextAfter)) {
124773
+ if (arraysEqual2(afterSlice, contextAfter)) {
123912
124774
  if (j === afterStart) {
123913
124775
  return {
123914
124776
  startLineIndex: i2,
@@ -123921,7 +124783,7 @@ function findContextMatch(content, contextBefore, contextAfter, oldContent) {
123921
124783
  const oldContentLines = oldContent.split(`
123922
124784
  `);
123923
124785
  const betweenLines = lines.slice(afterStart, j);
123924
- if (arraysEqual(betweenLines, oldContentLines)) {
124786
+ if (arraysEqual2(betweenLines, oldContentLines)) {
123925
124787
  return {
123926
124788
  startLineIndex: i2,
123927
124789
  endLineIndex: j - 1,
@@ -123947,7 +124809,7 @@ function findContextMatch(content, contextBefore, contextAfter, oldContent) {
123947
124809
  `);
123948
124810
  for (let k = afterStart;k <= lines.length - oldContentLines.length; k++) {
123949
124811
  const candidate = lines.slice(k, k + oldContentLines.length);
123950
- if (arraysEqual(candidate, oldContentLines)) {
124812
+ if (arraysEqual2(candidate, oldContentLines)) {
123951
124813
  return {
123952
124814
  startLineIndex: i2,
123953
124815
  endLineIndex: k + oldContentLines.length - 1,
@@ -123971,7 +124833,7 @@ function findContextMatch(content, contextBefore, contextAfter, oldContent) {
123971
124833
  } else if (contextAfter && contextAfter.length > 0) {
123972
124834
  for (let j = 0;j <= lines.length - contextAfter.length; j++) {
123973
124835
  const afterSlice = lines.slice(j, j + contextAfter.length);
123974
- if (arraysEqual(afterSlice, contextAfter)) {
124836
+ if (arraysEqual2(afterSlice, contextAfter)) {
123975
124837
  return {
123976
124838
  startLineIndex: 0,
123977
124839
  endLineIndex: j - 1,
@@ -123983,7 +124845,7 @@ function findContextMatch(content, contextBefore, contextAfter, oldContent) {
123983
124845
  }
123984
124846
  return null;
123985
124847
  }
123986
- function arraysEqual(a, b) {
124848
+ function arraysEqual2(a, b) {
123987
124849
  if (a.length !== b.length)
123988
124850
  return false;
123989
124851
  for (let i2 = 0;i2 < a.length; i2++) {
@@ -124083,7 +124945,7 @@ var suggestPatch = createSwarmTool({
124083
124945
  });
124084
124946
  continue;
124085
124947
  }
124086
- const fullPath = path152.resolve(directory, change.file);
124948
+ const fullPath = path153.resolve(directory, change.file);
124087
124949
  if (!fs111.existsSync(fullPath)) {
124088
124950
  errors5.push({
124089
124951
  success: false,
@@ -124487,7 +125349,7 @@ init_zod();
124487
125349
  init_manager2();
124488
125350
  init_detector();
124489
125351
  import * as fs112 from "node:fs";
124490
- import * as path153 from "node:path";
125352
+ import * as path154 from "node:path";
124491
125353
  init_create_tool();
124492
125354
  var MAX_FILE_SIZE2 = 2 * 1024 * 1024;
124493
125355
  var BINARY_CHECK_BYTES = 8192;
@@ -124553,7 +125415,7 @@ async function syntaxCheck(input, directory, config3) {
124553
125415
  if (languages?.length) {
124554
125416
  const lowerLangs = languages.map((l) => l.toLowerCase());
124555
125417
  filesToCheck = filesToCheck.filter((file3) => {
124556
- const ext = path153.extname(file3.path).toLowerCase();
125418
+ const ext = path154.extname(file3.path).toLowerCase();
124557
125419
  const langDef = getLanguageForExtension(ext);
124558
125420
  const fileProfile = getProfileForFile(file3.path);
124559
125421
  const langId = fileProfile?.id || langDef?.id;
@@ -124566,7 +125428,7 @@ async function syntaxCheck(input, directory, config3) {
124566
125428
  let skippedCount = 0;
124567
125429
  for (const fileInfo of filesToCheck) {
124568
125430
  const { path: filePath } = fileInfo;
124569
- const fullPath = path153.isAbsolute(filePath) ? filePath : path153.join(directory, filePath);
125431
+ const fullPath = path154.isAbsolute(filePath) ? filePath : path154.join(directory, filePath);
124570
125432
  const result = {
124571
125433
  path: filePath,
124572
125434
  language: "",
@@ -124615,7 +125477,7 @@ async function syntaxCheck(input, directory, config3) {
124615
125477
  results.push(result);
124616
125478
  continue;
124617
125479
  }
124618
- const ext = path153.extname(filePath).toLowerCase();
125480
+ const ext = path154.extname(filePath).toLowerCase();
124619
125481
  const langDef = getLanguageForExtension(ext);
124620
125482
  result.language = profile?.id || langDef?.id || "unknown";
124621
125483
  const errors5 = extractSyntaxErrors(parser, content);
@@ -124714,7 +125576,7 @@ init_utils();
124714
125576
  init_create_tool();
124715
125577
  init_path_security();
124716
125578
  import * as fs113 from "node:fs";
124717
- import * as path154 from "node:path";
125579
+ import * as path155 from "node:path";
124718
125580
  var MAX_TEXT_LENGTH = 200;
124719
125581
  var MAX_FILE_SIZE_BYTES11 = 1024 * 1024;
124720
125582
  var SUPPORTED_EXTENSIONS4 = new Set([
@@ -124780,9 +125642,9 @@ function validatePathsInput(paths, cwd) {
124780
125642
  return { error: "paths contains path traversal", resolvedPath: null };
124781
125643
  }
124782
125644
  try {
124783
- const resolvedPath = path154.resolve(paths);
124784
- const normalizedCwd = path154.resolve(cwd);
124785
- const normalizedResolved = path154.resolve(resolvedPath);
125645
+ const resolvedPath = path155.resolve(paths);
125646
+ const normalizedCwd = path155.resolve(cwd);
125647
+ const normalizedResolved = path155.resolve(resolvedPath);
124786
125648
  if (!normalizedResolved.startsWith(normalizedCwd)) {
124787
125649
  return {
124788
125650
  error: "paths must be within the current working directory",
@@ -124798,7 +125660,7 @@ function validatePathsInput(paths, cwd) {
124798
125660
  }
124799
125661
  }
124800
125662
  function isSupportedExtension(filePath) {
124801
- const ext = path154.extname(filePath).toLowerCase();
125663
+ const ext = path155.extname(filePath).toLowerCase();
124802
125664
  return SUPPORTED_EXTENSIONS4.has(ext);
124803
125665
  }
124804
125666
  function findSourceFiles3(dir, files = []) {
@@ -124813,7 +125675,7 @@ function findSourceFiles3(dir, files = []) {
124813
125675
  if (SKIP_DIRECTORIES5.has(entry)) {
124814
125676
  continue;
124815
125677
  }
124816
- const fullPath = path154.join(dir, entry);
125678
+ const fullPath = path155.join(dir, entry);
124817
125679
  let stat9;
124818
125680
  try {
124819
125681
  stat9 = fs113.statSync(fullPath);
@@ -124925,7 +125787,7 @@ var todo_extract = createSwarmTool({
124925
125787
  filesToScan.push(scanPath);
124926
125788
  } else {
124927
125789
  const errorResult = {
124928
- error: `unsupported file extension: ${path154.extname(scanPath)}`,
125790
+ error: `unsupported file extension: ${path155.extname(scanPath)}`,
124929
125791
  total: 0,
124930
125792
  byPriority: { high: 0, medium: 0, low: 0 },
124931
125793
  entries: []
@@ -124975,17 +125837,17 @@ init_schema();
124975
125837
  init_qa_gate_profile();
124976
125838
  init_gate_evidence();
124977
125839
  import * as fs117 from "node:fs";
124978
- import * as path158 from "node:path";
125840
+ import * as path159 from "node:path";
124979
125841
 
124980
125842
  // src/hooks/diff-scope.ts
124981
125843
  init_bun_compat();
124982
125844
  import * as fs115 from "node:fs";
124983
- import * as path156 from "node:path";
125845
+ import * as path157 from "node:path";
124984
125846
 
124985
125847
  // src/utils/gitignore-warning.ts
124986
125848
  init_bun_compat();
124987
125849
  import * as fs114 from "node:fs";
124988
- import * as path155 from "node:path";
125850
+ import * as path156 from "node:path";
124989
125851
  var _internals67 = { bunSpawn };
124990
125852
  var _swarmGitExcludedChecked = false;
124991
125853
  function fileCoversSwarm(content) {
@@ -125059,10 +125921,10 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
125059
125921
  const excludeRelPath = excludePathRaw.trim();
125060
125922
  if (!excludeRelPath)
125061
125923
  return;
125062
- const excludePath = path155.isAbsolute(excludeRelPath) ? excludeRelPath : path155.join(directory, excludeRelPath);
125924
+ const excludePath = path156.isAbsolute(excludeRelPath) ? excludeRelPath : path156.join(directory, excludeRelPath);
125063
125925
  if (checkIgnoreExitCode !== 0) {
125064
125926
  try {
125065
- fs114.mkdirSync(path155.dirname(excludePath), { recursive: true });
125927
+ fs114.mkdirSync(path156.dirname(excludePath), { recursive: true });
125066
125928
  let existing = "";
125067
125929
  try {
125068
125930
  existing = fs114.readFileSync(excludePath, "utf8");
@@ -125106,7 +125968,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
125106
125968
  var _internals68 = { bunSpawn };
125107
125969
  function getDeclaredScope(taskId, directory) {
125108
125970
  try {
125109
- const planPath = path156.join(directory, ".swarm", "plan.json");
125971
+ const planPath = path157.join(directory, ".swarm", "plan.json");
125110
125972
  if (!fs115.existsSync(planPath))
125111
125973
  return null;
125112
125974
  const raw = fs115.readFileSync(planPath, "utf-8");
@@ -125212,7 +126074,7 @@ init_telemetry();
125212
126074
  // src/turbo/lean/task-completion.ts
125213
126075
  init_file_locks();
125214
126076
  import * as fs116 from "node:fs";
125215
- import * as path157 from "node:path";
126077
+ import * as path158 from "node:path";
125216
126078
  var _internals69 = {
125217
126079
  listActiveLocks,
125218
126080
  verifyLeanTurboTaskCompletion
@@ -125231,7 +126093,7 @@ var TIER_3_PATTERNS = [
125231
126093
  ];
125232
126094
  function matchesTier3Pattern(files) {
125233
126095
  for (const file3 of files) {
125234
- const fileName = path157.basename(file3);
126096
+ const fileName = path158.basename(file3);
125235
126097
  for (const pattern of TIER_3_PATTERNS) {
125236
126098
  if (pattern.test(fileName)) {
125237
126099
  return true;
@@ -125243,7 +126105,7 @@ function matchesTier3Pattern(files) {
125243
126105
  function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
125244
126106
  let persisted = null;
125245
126107
  try {
125246
- const statePath = path157.join(directory, ".swarm", "turbo-state.json");
126108
+ const statePath = path158.join(directory, ".swarm", "turbo-state.json");
125247
126109
  if (!fs116.existsSync(statePath)) {
125248
126110
  return {
125249
126111
  ok: false,
@@ -125327,11 +126189,11 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
125327
126189
  };
125328
126190
  }
125329
126191
  const phase = runState.phase ?? 0;
125330
- const evidencePath = path157.join(directory, ".swarm", "evidence", String(phase), "lean-turbo", `${lane.laneId}.json`);
125331
- const expectedDir = path157.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
125332
- const resolvedPath = path157.resolve(evidencePath);
125333
- const resolvedDir = path157.resolve(expectedDir);
125334
- if (!resolvedPath.startsWith(resolvedDir + path157.sep) && resolvedPath !== resolvedDir) {
126192
+ const evidencePath = path158.join(directory, ".swarm", "evidence", String(phase), "lean-turbo", `${lane.laneId}.json`);
126193
+ const expectedDir = path158.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
126194
+ const resolvedPath = path158.resolve(evidencePath);
126195
+ const resolvedDir = path158.resolve(expectedDir);
126196
+ if (!resolvedPath.startsWith(resolvedDir + path158.sep) && resolvedPath !== resolvedDir) {
125335
126197
  return {
125336
126198
  ok: false,
125337
126199
  reason: `Lane ID causes path traversal: ${lane.laneId}`,
@@ -125371,7 +126233,7 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
125371
126233
  }
125372
126234
  let filesTouched = [];
125373
126235
  try {
125374
- const planPath = path157.join(directory, ".swarm", "plan.json");
126236
+ const planPath = path158.join(directory, ".swarm", "plan.json");
125375
126237
  const planRaw = fs116.readFileSync(planPath, "utf-8");
125376
126238
  const plan = JSON.parse(planRaw);
125377
126239
  for (const planPhase of plan.phases ?? []) {
@@ -125455,7 +126317,7 @@ var TIER_3_PATTERNS2 = [
125455
126317
  ];
125456
126318
  function matchesTier3Pattern2(files) {
125457
126319
  for (const file3 of files) {
125458
- const fileName = path158.basename(file3);
126320
+ const fileName = path159.basename(file3);
125459
126321
  for (const pattern of TIER_3_PATTERNS2) {
125460
126322
  if (pattern.test(fileName)) {
125461
126323
  return true;
@@ -125494,7 +126356,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
125494
126356
  if (!skipStandardTurboBypass && hasActiveTurboMode()) {
125495
126357
  const resolvedDir2 = workingDirectory;
125496
126358
  try {
125497
- const planPath = path158.join(resolvedDir2, ".swarm", "plan.json");
126359
+ const planPath = path159.join(resolvedDir2, ".swarm", "plan.json");
125498
126360
  const planRaw = fs117.readFileSync(planPath, "utf-8");
125499
126361
  const plan = JSON.parse(planRaw);
125500
126362
  for (const planPhase of plan.phases ?? []) {
@@ -125572,7 +126434,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
125572
126434
  }
125573
126435
  if (resolvedDir) {
125574
126436
  try {
125575
- const planPath = path158.join(resolvedDir, ".swarm", "plan.json");
126437
+ const planPath = path159.join(resolvedDir, ".swarm", "plan.json");
125576
126438
  const planRaw = fs117.readFileSync(planPath, "utf-8");
125577
126439
  const plan = JSON.parse(planRaw);
125578
126440
  for (const planPhase of plan.phases ?? []) {
@@ -125808,7 +126670,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
125808
126670
  };
125809
126671
  }
125810
126672
  directory = resolveResult.directory;
125811
- const planPath = path158.join(directory, ".swarm", "plan.json");
126673
+ const planPath = path159.join(directory, ".swarm", "plan.json");
125812
126674
  if (!fs117.existsSync(planPath)) {
125813
126675
  return {
125814
126676
  success: false,
@@ -125817,9 +126679,9 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
125817
126679
  };
125818
126680
  }
125819
126681
  if (fallbackDir && directory !== fallbackDir) {
125820
- const canonicalDir = fs117.realpathSync(path158.resolve(directory));
125821
- const canonicalRoot = fs117.realpathSync(path158.resolve(fallbackDir));
125822
- if (canonicalDir.startsWith(canonicalRoot + path158.sep)) {
126682
+ const canonicalDir = fs117.realpathSync(path159.resolve(directory));
126683
+ const canonicalRoot = fs117.realpathSync(path159.resolve(fallbackDir));
126684
+ if (canonicalDir.startsWith(canonicalRoot + path159.sep)) {
125823
126685
  return {
125824
126686
  success: false,
125825
126687
  message: `Invalid working_directory: "${directory}" is a subdirectory of ` + `the project root "${fallbackDir}". Pass the project root path or ` + `omit working_directory entirely.`,
@@ -125831,8 +126693,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
125831
126693
  }
125832
126694
  if (args2.status === "in_progress") {
125833
126695
  try {
125834
- const evidencePath = path158.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
125835
- fs117.mkdirSync(path158.dirname(evidencePath), { recursive: true });
126696
+ const evidencePath = path159.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
126697
+ fs117.mkdirSync(path159.dirname(evidencePath), { recursive: true });
125836
126698
  const fd = fs117.openSync(evidencePath, "wx");
125837
126699
  let writeOk = false;
125838
126700
  try {
@@ -125856,7 +126718,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
125856
126718
  recoverTaskStateFromDelegations(args2.task_id, directory);
125857
126719
  let phaseRequiresReviewer = true;
125858
126720
  try {
125859
- const planPath2 = path158.join(directory, ".swarm", "plan.json");
126721
+ const planPath2 = path159.join(directory, ".swarm", "plan.json");
125860
126722
  const planRaw = fs117.readFileSync(planPath2, "utf-8");
125861
126723
  const plan = JSON.parse(planRaw);
125862
126724
  const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
@@ -126085,7 +126947,7 @@ init_utils2();
126085
126947
  init_redaction();
126086
126948
  import { createHash as createHash12 } from "node:crypto";
126087
126949
  import { appendFile as appendFile14, mkdir as mkdir25 } from "node:fs/promises";
126088
- import * as path159 from "node:path";
126950
+ import * as path160 from "node:path";
126089
126951
  var EVIDENCE_CACHE_FILE = "evidence-cache/documents.jsonl";
126090
126952
  var MAX_EVIDENCE_TEXT_LENGTH = 4000;
126091
126953
  async function writeEvidenceDocuments(directory, inputs, now = () => new Date) {
@@ -126093,7 +126955,7 @@ async function writeEvidenceDocuments(directory, inputs, now = () => new Date) {
126093
126955
  const capturedAt = now().toISOString();
126094
126956
  const records = inputs.map((input) => createEvidenceDocumentRecord(input, capturedAt)).filter((record3) => record3 !== null);
126095
126957
  if (records.length > 0) {
126096
- await mkdir25(path159.dirname(filePath), { recursive: true });
126958
+ await mkdir25(path160.dirname(filePath), { recursive: true });
126097
126959
  await appendFile14(filePath, `${records.map((record3) => JSON.stringify(record3)).join(`
126098
126960
  `)}
126099
126961
  `, "utf-8");
@@ -126290,7 +127152,7 @@ init_schema3();
126290
127152
  init_store();
126291
127153
  init_create_tool();
126292
127154
  init_resolve_working_directory();
126293
- import * as path160 from "node:path";
127155
+ import * as path161 from "node:path";
126294
127156
  var FindingSchema2 = exports_external.object({
126295
127157
  severity: exports_external.enum(["low", "medium", "high", "critical"]),
126296
127158
  category: exports_external.string().min(1),
@@ -126354,7 +127216,7 @@ var write_architecture_supervisor_evidence = createSwarmTool({
126354
127216
  if (config3.architectural_supervision?.persist_knowledge_recommendations && args2.knowledge_recommendations.length > 0) {
126355
127217
  const knowledgeConfig = KnowledgeConfigSchema.parse(config3.knowledge ?? {});
126356
127218
  const lessons = args2.knowledge_recommendations.map((r) => r.lesson);
126357
- const result = await curateAndStoreSwarm(lessons, path160.basename(dirResult.directory), { phase_number: args2.phase }, dirResult.directory, knowledgeConfig, { skipAutoPromotion: true });
127219
+ const result = await curateAndStoreSwarm(lessons, path161.basename(dirResult.directory), { phase_number: args2.phase }, dirResult.directory, knowledgeConfig, { skipAutoPromotion: true });
126358
127220
  knowledgeProposed = result.stored;
126359
127221
  }
126360
127222
  } catch {}
@@ -126390,7 +127252,7 @@ init_ledger();
126390
127252
  init_manager();
126391
127253
  init_create_tool();
126392
127254
  import fs118 from "node:fs";
126393
- import path161 from "node:path";
127255
+ import path162 from "node:path";
126394
127256
  function normalizeVerdict(verdict) {
126395
127257
  switch (verdict) {
126396
127258
  case "APPROVED":
@@ -126438,7 +127300,7 @@ async function executeWriteDriftEvidence(args2, directory) {
126438
127300
  entries: [evidenceEntry]
126439
127301
  };
126440
127302
  const filename = "drift-verifier.json";
126441
- const relativePath = path161.join("evidence", String(phase), filename);
127303
+ const relativePath = path162.join("evidence", String(phase), filename);
126442
127304
  let validatedPath;
126443
127305
  try {
126444
127306
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -126449,10 +127311,10 @@ async function executeWriteDriftEvidence(args2, directory) {
126449
127311
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
126450
127312
  }, null, 2);
126451
127313
  }
126452
- const evidenceDir = path161.dirname(validatedPath);
127314
+ const evidenceDir = path162.dirname(validatedPath);
126453
127315
  try {
126454
127316
  await fs118.promises.mkdir(evidenceDir, { recursive: true });
126455
- const tempPath = path161.join(evidenceDir, `.${filename}.tmp`);
127317
+ const tempPath = path162.join(evidenceDir, `.${filename}.tmp`);
126456
127318
  await fs118.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
126457
127319
  await fs118.promises.rename(tempPath, validatedPath);
126458
127320
  let snapshotInfo;
@@ -126549,7 +127411,7 @@ var write_drift_evidence = createSwarmTool({
126549
127411
  init_zod();
126550
127412
  init_loader();
126551
127413
  import fs119 from "node:fs";
126552
- import path162 from "node:path";
127414
+ import path163 from "node:path";
126553
127415
  init_utils2();
126554
127416
  init_manager();
126555
127417
  init_create_tool();
@@ -126637,7 +127499,7 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
126637
127499
  timestamp: synthesis.timestamp
126638
127500
  };
126639
127501
  const filename = "final-council.json";
126640
- const relativePath = path162.join("evidence", filename);
127502
+ const relativePath = path163.join("evidence", filename);
126641
127503
  let validatedPath;
126642
127504
  try {
126643
127505
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -126651,10 +127513,10 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
126651
127513
  const evidenceContent = {
126652
127514
  entries: [evidenceEntry]
126653
127515
  };
126654
- const evidenceDir = path162.dirname(validatedPath);
127516
+ const evidenceDir = path163.dirname(validatedPath);
126655
127517
  try {
126656
127518
  await fs119.promises.mkdir(evidenceDir, { recursive: true });
126657
- const tempPath = path162.join(evidenceDir, `.${filename}.tmp`);
127519
+ const tempPath = path163.join(evidenceDir, `.${filename}.tmp`);
126658
127520
  await fs119.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
126659
127521
  await fs119.promises.rename(tempPath, validatedPath);
126660
127522
  return JSON.stringify({
@@ -126714,7 +127576,7 @@ init_zod();
126714
127576
  init_utils2();
126715
127577
  init_create_tool();
126716
127578
  import fs120 from "node:fs";
126717
- import path163 from "node:path";
127579
+ import path164 from "node:path";
126718
127580
  function normalizeVerdict2(verdict) {
126719
127581
  switch (verdict) {
126720
127582
  case "APPROVED":
@@ -126762,7 +127624,7 @@ async function executeWriteHallucinationEvidence(args2, directory) {
126762
127624
  entries: [evidenceEntry]
126763
127625
  };
126764
127626
  const filename = "hallucination-guard.json";
126765
- const relativePath = path163.join("evidence", String(phase), filename);
127627
+ const relativePath = path164.join("evidence", String(phase), filename);
126766
127628
  let validatedPath;
126767
127629
  try {
126768
127630
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -126773,10 +127635,10 @@ async function executeWriteHallucinationEvidence(args2, directory) {
126773
127635
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
126774
127636
  }, null, 2);
126775
127637
  }
126776
- const evidenceDir = path163.dirname(validatedPath);
127638
+ const evidenceDir = path164.dirname(validatedPath);
126777
127639
  try {
126778
127640
  await fs120.promises.mkdir(evidenceDir, { recursive: true });
126779
- const tempPath = path163.join(evidenceDir, `.${filename}.tmp`);
127641
+ const tempPath = path164.join(evidenceDir, `.${filename}.tmp`);
126780
127642
  await fs120.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
126781
127643
  await fs120.promises.rename(tempPath, validatedPath);
126782
127644
  return JSON.stringify({
@@ -126826,7 +127688,7 @@ init_zod();
126826
127688
  init_utils2();
126827
127689
  init_create_tool();
126828
127690
  import fs121 from "node:fs";
126829
- import path164 from "node:path";
127691
+ import path165 from "node:path";
126830
127692
  function normalizeVerdict3(verdict) {
126831
127693
  switch (verdict) {
126832
127694
  case "PASS":
@@ -126900,7 +127762,7 @@ async function executeWriteMutationEvidence(args2, directory) {
126900
127762
  entries: [evidenceEntry]
126901
127763
  };
126902
127764
  const filename = "mutation-gate.json";
126903
- const relativePath = path164.join("evidence", String(phase), filename);
127765
+ const relativePath = path165.join("evidence", String(phase), filename);
126904
127766
  let validatedPath;
126905
127767
  try {
126906
127768
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -126911,10 +127773,10 @@ async function executeWriteMutationEvidence(args2, directory) {
126911
127773
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
126912
127774
  }, null, 2);
126913
127775
  }
126914
- const evidenceDir = path164.dirname(validatedPath);
127776
+ const evidenceDir = path165.dirname(validatedPath);
126915
127777
  try {
126916
127778
  await fs121.promises.mkdir(evidenceDir, { recursive: true });
126917
- const tempPath = path164.join(evidenceDir, `.${filename}.tmp`);
127779
+ const tempPath = path165.join(evidenceDir, `.${filename}.tmp`);
126918
127780
  await fs121.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
126919
127781
  await fs121.promises.rename(tempPath, validatedPath);
126920
127782
  return JSON.stringify({
@@ -127050,7 +127912,8 @@ var TOOL_MANIFEST = defineHandlers({
127050
127912
  lean_turbo_runner_status: () => lean_turbo_runner_status,
127051
127913
  lean_turbo_review: () => lean_turbo_review,
127052
127914
  lean_turbo_run_phase: () => lean_turbo_run_phase,
127053
- lean_turbo_status: () => lean_turbo_status
127915
+ lean_turbo_status: () => lean_turbo_status,
127916
+ apply_patch: () => applyPatch
127054
127917
  });
127055
127918
 
127056
127919
  // src/tools/plugin-registration.ts
@@ -127180,6 +128043,7 @@ async function initializeOpenCodeSwarm(ctx) {
127180
128043
  const msg = err3 instanceof Error ? err3.message : String(err3);
127181
128044
  log("loadSnapshot timed out or failed (non-fatal)", { error: msg });
127182
128045
  });
128046
+ initTelemetry(ctx.directory);
127183
128047
  const repoGraphHook = createRepoGraphBuilderHook(ctx.directory);
127184
128048
  queueMicrotask(() => {
127185
128049
  const watchdog = setTimeout(() => {
@@ -127196,7 +128060,6 @@ async function initializeOpenCodeSwarm(ctx) {
127196
128060
  error: msg
127197
128061
  });
127198
128062
  });
127199
- initTelemetry(ctx.directory);
127200
128063
  writeSwarmConfigExampleIfNew(ctx.directory);
127201
128064
  writeProjectConfigIfNew(ctx.directory, config3.quiet);
127202
128065
  if (config3.version_check !== false) {
@@ -127361,7 +128224,7 @@ async function initializeOpenCodeSwarm(ctx) {
127361
128224
  const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
127362
128225
  preflightTriggerManager = new PTM(automationConfig);
127363
128226
  const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
127364
- const swarmDir = path166.resolve(ctx.directory, ".swarm");
128227
+ const swarmDir = path167.resolve(ctx.directory, ".swarm");
127365
128228
  statusArtifact = new ASA(swarmDir);
127366
128229
  statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
127367
128230
  if (automationConfig.capabilities?.evidence_auto_summaries === true) {
@@ -127875,7 +128738,7 @@ ${promptRaw}`;
127875
128738
  const meta3 = readSkillMetadata(s.skillPath, ctx.directory);
127876
128739
  let desc = meta3.description || "";
127877
128740
  if (!desc || desc === "No description provided") {
127878
- desc = path166.basename(path166.dirname(s.skillPath));
128741
+ desc = path167.basename(path167.dirname(s.skillPath));
127879
128742
  }
127880
128743
  desc = desc.replace(/,/g, ";");
127881
128744
  return `file:${s.skillPath} (-- ${desc})`;
@@ -127885,7 +128748,7 @@ ${promptRaw}`;
127885
128748
 
127886
128749
  ${promptRaw}`;
127887
128750
  argsRecord.prompt = newPrompt;
127888
- const skillNames = topSkills.map((s) => `${path166.basename(s.skillPath)} (score: ${s.score.toFixed(2)})`).join(", ");
128751
+ const skillNames = topSkills.map((s) => `${path167.basename(s.skillPath)} (score: ${s.score.toFixed(2)})`).join(", ");
127889
128752
  console.warn(`[skill-propagation-gate] Injected skills: ${skillNames}`);
127890
128753
  for (const skill of topSkills) {
127891
128754
  try {