opencode-swarm 7.4.3 → 7.5.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
@@ -33,7 +33,7 @@ var package_default;
33
33
  var init_package = __esm(() => {
34
34
  package_default = {
35
35
  name: "opencode-swarm",
36
- version: "7.4.3",
36
+ version: "7.5.0",
37
37
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
38
38
  main: "dist/index.js",
39
39
  types: "dist/index.d.ts",
@@ -62656,8 +62656,8 @@ ${JSON.stringify(symbolNames, null, 2)}`);
62656
62656
  var moduleRtn;
62657
62657
  var Module = moduleArg;
62658
62658
  var readyPromiseResolve, readyPromiseReject;
62659
- var readyPromise = new Promise((resolve21, reject) => {
62660
- readyPromiseResolve = resolve21;
62659
+ var readyPromise = new Promise((resolve22, reject) => {
62660
+ readyPromiseResolve = resolve22;
62661
62661
  readyPromiseReject = reject;
62662
62662
  });
62663
62663
  var ENVIRONMENT_IS_WEB = typeof window == "object";
@@ -62679,11 +62679,11 @@ ${JSON.stringify(symbolNames, null, 2)}`);
62679
62679
  throw toThrow;
62680
62680
  }, "quit_");
62681
62681
  var scriptDirectory = "";
62682
- function locateFile(path61) {
62682
+ function locateFile(path65) {
62683
62683
  if (Module["locateFile"]) {
62684
- return Module["locateFile"](path61, scriptDirectory);
62684
+ return Module["locateFile"](path65, scriptDirectory);
62685
62685
  }
62686
- return scriptDirectory + path61;
62686
+ return scriptDirectory + path65;
62687
62687
  }
62688
62688
  __name(locateFile, "locateFile");
62689
62689
  var readAsync, readBinary;
@@ -62737,13 +62737,13 @@ ${JSON.stringify(symbolNames, null, 2)}`);
62737
62737
  }
62738
62738
  readAsync = /* @__PURE__ */ __name(async (url3) => {
62739
62739
  if (isFileURI(url3)) {
62740
- return new Promise((resolve21, reject) => {
62740
+ return new Promise((resolve22, reject) => {
62741
62741
  var xhr = new XMLHttpRequest;
62742
62742
  xhr.open("GET", url3, true);
62743
62743
  xhr.responseType = "arraybuffer";
62744
62744
  xhr.onload = () => {
62745
62745
  if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
62746
- resolve21(xhr.response);
62746
+ resolve22(xhr.response);
62747
62747
  return;
62748
62748
  }
62749
62749
  reject(xhr.status);
@@ -62963,10 +62963,10 @@ ${JSON.stringify(symbolNames, null, 2)}`);
62963
62963
  __name(receiveInstantiationResult, "receiveInstantiationResult");
62964
62964
  var info2 = getWasmImports();
62965
62965
  if (Module["instantiateWasm"]) {
62966
- return new Promise((resolve21, reject) => {
62966
+ return new Promise((resolve22, reject) => {
62967
62967
  Module["instantiateWasm"](info2, (mod, inst) => {
62968
62968
  receiveInstance(mod, inst);
62969
- resolve21(mod.exports);
62969
+ resolve22(mod.exports);
62970
62970
  });
62971
62971
  });
62972
62972
  }
@@ -64432,13 +64432,13 @@ __export(exports_runtime, {
64432
64432
  getInitializedLanguages: () => getInitializedLanguages,
64433
64433
  clearParserCache: () => clearParserCache
64434
64434
  });
64435
- import * as path61 from "node:path";
64435
+ import * as path65 from "node:path";
64436
64436
  import { fileURLToPath as fileURLToPath2 } from "node:url";
64437
64437
  async function initTreeSitter() {
64438
64438
  if (treeSitterInitialized) {
64439
64439
  return;
64440
64440
  }
64441
- const thisDir = path61.dirname(fileURLToPath2(import.meta.url));
64441
+ const thisDir = path65.dirname(fileURLToPath2(import.meta.url));
64442
64442
  const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/lang");
64443
64443
  if (isSource) {
64444
64444
  await Parser.init();
@@ -64446,7 +64446,7 @@ async function initTreeSitter() {
64446
64446
  const grammarsDir = getGrammarsDirAbsolute();
64447
64447
  await Parser.init({
64448
64448
  locateFile(scriptName) {
64449
- return path61.join(grammarsDir, scriptName);
64449
+ return path65.join(grammarsDir, scriptName);
64450
64450
  }
64451
64451
  });
64452
64452
  }
@@ -64467,11 +64467,11 @@ function getWasmFileName(languageId) {
64467
64467
  return `tree-sitter-${sanitized}.wasm`;
64468
64468
  }
64469
64469
  function getGrammarsDirAbsolute() {
64470
- const thisDir = path61.dirname(fileURLToPath2(import.meta.url));
64470
+ const thisDir = path65.dirname(fileURLToPath2(import.meta.url));
64471
64471
  const normalized = thisDir.replace(/\\/g, "/");
64472
64472
  const isSource = normalized.endsWith("/src/lang");
64473
64473
  const isCliBundle = normalized.endsWith("/cli");
64474
- return isSource ? path61.join(thisDir, "grammars") : isCliBundle ? path61.join(thisDir, "..", "lang", "grammars") : path61.join(thisDir, "lang", "grammars");
64474
+ return isSource ? path65.join(thisDir, "grammars") : isCliBundle ? path65.join(thisDir, "..", "lang", "grammars") : path65.join(thisDir, "lang", "grammars");
64475
64475
  }
64476
64476
  async function loadGrammar(languageId) {
64477
64477
  if (typeof languageId !== "string" || languageId.length > 100) {
@@ -64487,9 +64487,9 @@ async function loadGrammar(languageId) {
64487
64487
  await initTreeSitter();
64488
64488
  const parser = new Parser;
64489
64489
  const wasmFileName = getWasmFileName(normalizedId);
64490
- const wasmPath = path61.join(getGrammarsDirAbsolute(), wasmFileName);
64491
- const { existsSync: existsSync31 } = await import("node:fs");
64492
- if (!existsSync31(wasmPath)) {
64490
+ const wasmPath = path65.join(getGrammarsDirAbsolute(), wasmFileName);
64491
+ const { existsSync: existsSync33 } = await import("node:fs");
64492
+ if (!existsSync33(wasmPath)) {
64493
64493
  throw new Error(`Grammar file not found for ${languageId}: ${wasmPath}
64494
64494
  Make sure to run 'bun run build' to copy grammar files to dist/lang/grammars/`);
64495
64495
  }
@@ -64522,7 +64522,7 @@ async function isGrammarAvailable(languageId) {
64522
64522
  }
64523
64523
  try {
64524
64524
  const wasmFileName = getWasmFileName(normalizedId);
64525
- const wasmPath = path61.join(getGrammarsDirAbsolute(), wasmFileName);
64525
+ const wasmPath = path65.join(getGrammarsDirAbsolute(), wasmFileName);
64526
64526
  const { statSync: statSync19 } = await import("node:fs");
64527
64527
  statSync19(wasmPath);
64528
64528
  return true;
@@ -64581,13 +64581,13 @@ __export(exports_doc_scan, {
64581
64581
  import * as crypto7 from "node:crypto";
64582
64582
  import * as fs45 from "node:fs";
64583
64583
  import { mkdir as mkdir10, readFile as readFile10, writeFile as writeFile9 } from "node:fs/promises";
64584
- import * as path63 from "node:path";
64584
+ import * as path67 from "node:path";
64585
64585
  function normalizeSeparators(filePath) {
64586
64586
  return filePath.replace(/\\/g, "/");
64587
64587
  }
64588
64588
  function matchesDocPattern(filePath, patterns) {
64589
64589
  const normalizedPath = normalizeSeparators(filePath);
64590
- const basename9 = path63.basename(filePath);
64590
+ const basename9 = path67.basename(filePath);
64591
64591
  for (const pattern of patterns) {
64592
64592
  if (!pattern.includes("/") && !pattern.includes("\\")) {
64593
64593
  if (basename9 === pattern) {
@@ -64643,7 +64643,7 @@ function stripMarkdown(text) {
64643
64643
  return text.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/^\s*[-*•]\s+/gm, "").replace(/^\s*\d+\.\s+/gm, "").trim();
64644
64644
  }
64645
64645
  async function scanDocIndex(directory) {
64646
- const manifestPath = path63.join(directory, ".swarm", "doc-manifest.json");
64646
+ const manifestPath = path67.join(directory, ".swarm", "doc-manifest.json");
64647
64647
  const defaultPatterns = DocsConfigSchema.parse({}).doc_patterns;
64648
64648
  const extraPatterns = [
64649
64649
  "ARCHITECTURE.md",
@@ -64660,9 +64660,9 @@ async function scanDocIndex(directory) {
64660
64660
  let cacheValid = true;
64661
64661
  for (const file3 of existingManifest.files) {
64662
64662
  try {
64663
- const fullPath = path63.join(directory, file3.path);
64664
- const stat5 = fs45.statSync(fullPath);
64665
- if (stat5.mtimeMs > file3.mtime) {
64663
+ const fullPath = path67.join(directory, file3.path);
64664
+ const stat6 = fs45.statSync(fullPath);
64665
+ if (stat6.mtimeMs > file3.mtime) {
64666
64666
  cacheValid = false;
64667
64667
  break;
64668
64668
  }
@@ -64690,14 +64690,14 @@ async function scanDocIndex(directory) {
64690
64690
  }
64691
64691
  const entries = rawEntries.filter((e) => typeof e === "string");
64692
64692
  for (const entry of entries) {
64693
- const fullPath = path63.join(directory, entry);
64694
- let stat5;
64693
+ const fullPath = path67.join(directory, entry);
64694
+ let stat6;
64695
64695
  try {
64696
- stat5 = fs45.statSync(fullPath);
64696
+ stat6 = fs45.statSync(fullPath);
64697
64697
  } catch {
64698
64698
  continue;
64699
64699
  }
64700
- if (!stat5.isFile())
64700
+ if (!stat6.isFile())
64701
64701
  continue;
64702
64702
  const pathParts = normalizeSeparators(entry).split("/");
64703
64703
  let skipThisFile = false;
@@ -64726,7 +64726,7 @@ async function scanDocIndex(directory) {
64726
64726
  } catch {
64727
64727
  continue;
64728
64728
  }
64729
- const { title, summary } = extractTitleAndSummary(content, path63.basename(entry));
64729
+ const { title, summary } = extractTitleAndSummary(content, path67.basename(entry));
64730
64730
  const lineCount = content.split(`
64731
64731
  `).length;
64732
64732
  discoveredFiles.push({
@@ -64734,7 +64734,7 @@ async function scanDocIndex(directory) {
64734
64734
  title,
64735
64735
  summary,
64736
64736
  lines: lineCount,
64737
- mtime: stat5.mtimeMs
64737
+ mtime: stat6.mtimeMs
64738
64738
  });
64739
64739
  }
64740
64740
  discoveredFiles.sort((a, b) => a.path.toLowerCase().localeCompare(b.path.toLowerCase()));
@@ -64752,7 +64752,7 @@ async function scanDocIndex(directory) {
64752
64752
  files: discoveredFiles
64753
64753
  };
64754
64754
  try {
64755
- await mkdir10(path63.dirname(manifestPath), { recursive: true });
64755
+ await mkdir10(path67.dirname(manifestPath), { recursive: true });
64756
64756
  await writeFile9(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
64757
64757
  } catch {}
64758
64758
  return { manifest, cached: false };
@@ -64791,7 +64791,7 @@ function extractConstraintsFromContent(content) {
64791
64791
  return constraints;
64792
64792
  }
64793
64793
  async function extractDocConstraints(directory, taskFiles, taskDescription) {
64794
- const manifestPath = path63.join(directory, ".swarm", "doc-manifest.json");
64794
+ const manifestPath = path67.join(directory, ".swarm", "doc-manifest.json");
64795
64795
  let manifest;
64796
64796
  try {
64797
64797
  const content = await readFile10(manifestPath, "utf-8");
@@ -64817,7 +64817,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
64817
64817
  }
64818
64818
  let fullContent;
64819
64819
  try {
64820
- fullContent = await readFile10(path63.join(directory, docFile.path), "utf-8");
64820
+ fullContent = await readFile10(path67.join(directory, docFile.path), "utf-8");
64821
64821
  } catch {
64822
64822
  skippedCount++;
64823
64823
  continue;
@@ -64840,7 +64840,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
64840
64840
  tier: "swarm",
64841
64841
  lesson: constraint,
64842
64842
  category: "architecture",
64843
- tags: ["doc-scan", path63.basename(docFile.path)],
64843
+ tags: ["doc-scan", path67.basename(docFile.path)],
64844
64844
  scope: "global",
64845
64845
  confidence: 0.5,
64846
64846
  status: "candidate",
@@ -64913,7 +64913,7 @@ var init_doc_scan = __esm(() => {
64913
64913
  }
64914
64914
  } catch {}
64915
64915
  if (force) {
64916
- const manifestPath = path63.join(directory, ".swarm", "doc-manifest.json");
64916
+ const manifestPath = path67.join(directory, ".swarm", "doc-manifest.json");
64917
64917
  try {
64918
64918
  fs45.unlinkSync(manifestPath);
64919
64919
  } catch {}
@@ -65104,9 +65104,9 @@ __export(exports_curator_drift, {
65104
65104
  buildDriftInjectionText: () => buildDriftInjectionText
65105
65105
  });
65106
65106
  import * as fs48 from "node:fs";
65107
- import * as path66 from "node:path";
65107
+ import * as path70 from "node:path";
65108
65108
  async function readPriorDriftReports(directory) {
65109
- const swarmDir = path66.join(directory, ".swarm");
65109
+ const swarmDir = path70.join(directory, ".swarm");
65110
65110
  const entries = await fs48.promises.readdir(swarmDir).catch(() => null);
65111
65111
  if (entries === null)
65112
65112
  return [];
@@ -65133,7 +65133,7 @@ async function readPriorDriftReports(directory) {
65133
65133
  async function writeDriftReport(directory, report) {
65134
65134
  const filename = `${DRIFT_REPORT_PREFIX}${report.phase}.json`;
65135
65135
  const filePath = validateSwarmPath(directory, filename);
65136
- const swarmDir = path66.dirname(filePath);
65136
+ const swarmDir = path70.dirname(filePath);
65137
65137
  await fs48.promises.mkdir(swarmDir, { recursive: true });
65138
65138
  try {
65139
65139
  await fs48.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
@@ -65267,7 +65267,7 @@ var init_curator_drift = __esm(() => {
65267
65267
  // src/index.ts
65268
65268
  init_package();
65269
65269
  init_agents2();
65270
- import * as path110 from "node:path";
65270
+ import * as path114 from "node:path";
65271
65271
 
65272
65272
  // src/background/index.ts
65273
65273
  init_event_bus();
@@ -67400,16 +67400,16 @@ ${originalText}`;
67400
67400
  }
67401
67401
  // src/hooks/repo-graph-builder.ts
67402
67402
  init_constants();
67403
- import * as path54 from "node:path";
67403
+ import { realpathSync as realpathSync8 } from "node:fs";
67404
+ import * as path58 from "node:path";
67404
67405
 
67405
- // src/tools/repo-graph.ts
67406
- init_utils2();
67406
+ // src/tools/repo-graph/builder.ts
67407
67407
  init_path_security();
67408
67408
  import * as fsSync3 from "node:fs";
67409
- import { constants as constants4, existsSync as existsSync29, realpathSync as realpathSync6 } from "node:fs";
67409
+ import { existsSync as existsSync29, realpathSync as realpathSync6 } from "node:fs";
67410
67410
  import * as fsPromises5 from "node:fs/promises";
67411
67411
  import * as os7 from "node:os";
67412
- import * as path53 from "node:path";
67412
+ import * as path54 from "node:path";
67413
67413
 
67414
67414
  // src/utils/timeout.ts
67415
67415
  async function withTimeout(promise3, ms, timeoutError) {
@@ -67769,17 +67769,38 @@ var symbols = createSwarmTool({
67769
67769
  }
67770
67770
  });
67771
67771
 
67772
- // src/tools/repo-graph.ts
67773
- var WINDOWS_RENAME_MAX_RETRIES2 = 3;
67774
- var WINDOWS_RENAME_RETRY_DELAY_MS2 = 50;
67772
+ // src/tools/repo-graph/types.ts
67773
+ import * as path53 from "node:path";
67774
+ var REPO_GRAPH_FILENAME = "repo-graph.json";
67775
+ var GRAPH_SCHEMA_VERSION = "1.0.0";
67775
67776
  function normalizeGraphPath(filePath) {
67776
67777
  return path53.normalize(filePath).replace(/\\/g, "/");
67777
67778
  }
67778
- var REPO_GRAPH_FILENAME = "repo-graph.json";
67779
- var GRAPH_SCHEMA_VERSION = "1.0.0";
67780
- var graphCache = new Map;
67781
- var dirtyFlags = new Map;
67782
- var mtimeCache = new Map;
67779
+ function createEmptyGraph(workspaceRoot) {
67780
+ return {
67781
+ schema_version: GRAPH_SCHEMA_VERSION,
67782
+ workspaceRoot: path53.normalize(workspaceRoot),
67783
+ nodes: {},
67784
+ edges: [],
67785
+ metadata: {
67786
+ generatedAt: new Date().toISOString(),
67787
+ generator: "repo-graph",
67788
+ nodeCount: 0,
67789
+ edgeCount: 0
67790
+ }
67791
+ };
67792
+ }
67793
+ function updateGraphMetadata(graph) {
67794
+ graph.metadata = {
67795
+ generatedAt: new Date().toISOString(),
67796
+ generator: "repo-graph",
67797
+ nodeCount: Object.keys(graph.nodes).length,
67798
+ edgeCount: graph.edges.length
67799
+ };
67800
+ }
67801
+
67802
+ // src/tools/repo-graph/validation.ts
67803
+ init_path_security();
67783
67804
  function validateWorkspace(workspace) {
67784
67805
  if (!workspace || typeof workspace !== "string" || workspace.trim() === "") {
67785
67806
  throw new Error("Invalid workspace: must be a non-empty string");
@@ -67867,309 +67888,8 @@ function validateGraphEdge(edge) {
67867
67888
  throw new Error("Invalid edge: control characters detected");
67868
67889
  }
67869
67890
  }
67870
- function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
67871
- if (containsControlChars(specifier)) {
67872
- return null;
67873
- }
67874
- if (specifier.startsWith("/") || specifier.startsWith("\\")) {
67875
- return null;
67876
- }
67877
- if (/^[A-Za-z]:[/\\]/.test(specifier)) {
67878
- return null;
67879
- }
67880
- if (specifier.startsWith("http://") || specifier.startsWith("https://")) {
67881
- return null;
67882
- }
67883
- try {
67884
- if (specifier.startsWith(".")) {
67885
- const sourceDir = path53.dirname(sourceFile);
67886
- let resolved = path53.resolve(sourceDir, specifier);
67887
- let realResolved;
67888
- try {
67889
- realResolved = realpathSync6(resolved);
67890
- } catch {
67891
- realResolved = resolved;
67892
- }
67893
- let realRoot;
67894
- try {
67895
- realRoot = realpathSync6(workspaceRoot);
67896
- } catch {
67897
- realRoot = path53.normalize(workspaceRoot);
67898
- }
67899
- if (!existsSync29(resolved)) {
67900
- const EXTENSIONS = [
67901
- ".ts",
67902
- ".tsx",
67903
- ".js",
67904
- ".jsx",
67905
- ".mjs",
67906
- ".cjs",
67907
- ".py",
67908
- ".json"
67909
- ];
67910
- let found = null;
67911
- for (const ext of EXTENSIONS) {
67912
- const candidate = resolved + ext;
67913
- if (existsSync29(candidate)) {
67914
- found = candidate;
67915
- break;
67916
- }
67917
- }
67918
- if (found) {
67919
- try {
67920
- realResolved = realpathSync6(found);
67921
- } catch {
67922
- realResolved = found;
67923
- }
67924
- resolved = found;
67925
- } else {
67926
- return null;
67927
- }
67928
- }
67929
- const normalizedResolved = path53.normalize(realResolved);
67930
- const normalizedRoot = path53.normalize(realRoot);
67931
- if (!normalizedResolved.startsWith(normalizedRoot + path53.sep) && normalizedResolved !== normalizedRoot) {
67932
- return null;
67933
- }
67934
- return resolved;
67935
- }
67936
- return null;
67937
- } catch {
67938
- return null;
67939
- }
67940
- }
67941
- function createEmptyGraph(workspaceRoot) {
67942
- return {
67943
- schema_version: GRAPH_SCHEMA_VERSION,
67944
- workspaceRoot: path53.normalize(workspaceRoot),
67945
- nodes: {},
67946
- edges: [],
67947
- metadata: {
67948
- generatedAt: new Date().toISOString(),
67949
- generator: "repo-graph",
67950
- nodeCount: 0,
67951
- edgeCount: 0
67952
- }
67953
- };
67954
- }
67955
- function updateGraphMetadata(graph) {
67956
- graph.metadata = {
67957
- generatedAt: new Date().toISOString(),
67958
- generator: "repo-graph",
67959
- nodeCount: Object.keys(graph.nodes).length,
67960
- edgeCount: graph.edges.length
67961
- };
67962
- }
67963
- function upsertNode(graph, node) {
67964
- validateGraphNode(node);
67965
- const key = normalizeGraphPath(node.filePath);
67966
- graph.nodes[key] = node;
67967
- updateGraphMetadata(graph);
67968
- }
67969
- function addEdge(graph, edge) {
67970
- validateGraphEdge(edge);
67971
- const exists = graph.edges.some((e) => e.source === edge.source && e.target === edge.target && e.importSpecifier === edge.importSpecifier);
67972
- if (!exists) {
67973
- graph.edges.push(edge);
67974
- updateGraphMetadata(graph);
67975
- }
67976
- }
67977
- function getCachedGraph(workspace) {
67978
- return graphCache.get(path53.normalize(workspace));
67979
- }
67980
- function setCachedGraph(workspace, graph, mtime) {
67981
- const normalized = path53.normalize(workspace);
67982
- graphCache.set(normalized, graph);
67983
- dirtyFlags.set(normalized, false);
67984
- if (mtime !== undefined) {
67985
- mtimeCache.set(normalized, mtime);
67986
- }
67987
- }
67988
- function isDirty(workspace) {
67989
- return dirtyFlags.get(path53.normalize(workspace)) ?? false;
67990
- }
67991
- function clearCache(workspace) {
67992
- const normalized = path53.normalize(workspace);
67993
- graphCache.delete(normalized);
67994
- dirtyFlags.delete(normalized);
67995
- mtimeCache.delete(normalized);
67996
- }
67997
- function getGraphPath(workspace) {
67998
- validateWorkspace(workspace);
67999
- const basePath = validateSwarmPath(workspace, REPO_GRAPH_FILENAME);
68000
- validateSymlinkBoundary(basePath, workspace);
68001
- return basePath;
68002
- }
68003
- async function loadGraph(workspace) {
68004
- validateWorkspace(workspace);
68005
- const normalized = path53.normalize(workspace);
68006
- const cached3 = getCachedGraph(normalized);
68007
- if (cached3 && !isDirty(normalized)) {
68008
- try {
68009
- const graphPath = getGraphPath(workspace);
68010
- if (existsSync29(graphPath)) {
68011
- const stats = await fsPromises5.stat(graphPath);
68012
- const cachedMtime = mtimeCache.get(normalized);
68013
- if (cachedMtime !== undefined && stats.mtimeMs !== cachedMtime) {
68014
- clearCache(normalized);
68015
- } else {
68016
- return cached3;
68017
- }
68018
- } else {
68019
- clearCache(normalized);
68020
- }
68021
- } catch {
68022
- clearCache(normalized);
68023
- }
68024
- }
68025
- try {
68026
- const graphPath = getGraphPath(workspace);
68027
- if (!existsSync29(graphPath)) {
68028
- return null;
68029
- }
68030
- const stats = await fsPromises5.stat(graphPath);
68031
- const content = await fsPromises5.readFile(graphPath, "utf-8");
68032
- if (content.includes("\x00") || content.includes("�")) {
68033
- throw Object.assign(new Error("repo-graph.json contains null bytes or invalid encoding"), { code: "CORRUPTION" });
68034
- }
68035
- let parsed;
68036
- try {
68037
- parsed = JSON.parse(content);
68038
- } catch {
68039
- throw Object.assign(new Error("repo-graph.json contains invalid JSON"), {
68040
- code: "CORRUPTION"
68041
- });
68042
- }
68043
- if (!parsed.schema_version) {
68044
- throw Object.assign(new Error("repo-graph.json missing schema_version"), {
68045
- code: "CORRUPTION"
68046
- });
68047
- }
68048
- if (!parsed.nodes || typeof parsed.nodes !== "object") {
68049
- throw Object.assign(new Error("repo-graph.json missing or invalid nodes"), { code: "CORRUPTION" });
68050
- }
68051
- if (!Array.isArray(parsed.edges)) {
68052
- throw Object.assign(new Error("repo-graph.json missing or invalid edges"), { code: "CORRUPTION" });
68053
- }
68054
- for (const [key, node] of Object.entries(parsed.nodes)) {
68055
- if (!key || typeof key !== "string") {
68056
- throw Object.assign(new Error("repo-graph.json contains invalid node key"), { code: "CORRUPTION" });
68057
- }
68058
- try {
68059
- validateGraphNode(node);
68060
- } catch (err2) {
68061
- const msg = err2 instanceof Error ? err2.message : "Invalid node structure";
68062
- throw Object.assign(new Error(`repo-graph.json node validation failed: ${msg}`), { code: "CORRUPTION" });
68063
- }
68064
- }
68065
- for (const edge of parsed.edges) {
68066
- try {
68067
- validateGraphEdge(edge);
68068
- } catch (err2) {
68069
- const msg = err2 instanceof Error ? err2.message : "Invalid edge structure";
68070
- throw Object.assign(new Error(`repo-graph.json edge validation failed: ${msg}`), { code: "CORRUPTION" });
68071
- }
68072
- }
68073
- if (!parsed.metadata || typeof parsed.metadata !== "object" || typeof parsed.metadata.generatedAt !== "string" || typeof parsed.metadata.generator !== "string" || typeof parsed.metadata.nodeCount !== "number" || typeof parsed.metadata.edgeCount !== "number") {
68074
- throw Object.assign(new Error("repo-graph.json missing or invalid metadata"), { code: "CORRUPTION" });
68075
- }
68076
- setCachedGraph(normalized, parsed, stats.mtimeMs);
68077
- return parsed;
68078
- } catch (error93) {
68079
- if (error93 instanceof Error && "code" in error93 && error93.code === "CORRUPTION") {
68080
- throw error93;
68081
- }
68082
- if (error93 instanceof Error && "code" in error93 && error93.code === "ENOENT") {
68083
- return null;
68084
- }
68085
- throw error93;
68086
- }
68087
- }
68088
- async function saveGraph(workspace, graph, options) {
68089
- validateWorkspace(workspace);
68090
- if (!graph.schema_version) {
68091
- throw new Error("Graph must have schema_version");
68092
- }
68093
- if (!graph.nodes || typeof graph.nodes !== "object") {
68094
- throw new Error("Graph must have nodes object");
68095
- }
68096
- if (!Array.isArray(graph.edges)) {
68097
- throw new Error("Graph must have edges array");
68098
- }
68099
- const normalizedWorkspace = path53.normalize(workspace);
68100
- let realWorkspace;
68101
- try {
68102
- realWorkspace = realpathSync6(workspace);
68103
- } catch {
68104
- realWorkspace = normalizedWorkspace;
68105
- }
68106
- const normalizedGraphRoot = path53.normalize(graph.workspaceRoot);
68107
- let realGraphRoot;
68108
- try {
68109
- realGraphRoot = realpathSync6(graph.workspaceRoot);
68110
- } catch {
68111
- realGraphRoot = normalizedGraphRoot;
68112
- }
68113
- if (path53.normalize(realWorkspace) !== path53.normalize(realGraphRoot)) {
68114
- throw new Error(`Graph workspaceRoot mismatch: graph was built for "${graph.workspaceRoot}" but save was called for "${workspace}"`);
68115
- }
68116
- const normalized = normalizedWorkspace;
68117
- const graphPath = getGraphPath(workspace);
68118
- updateGraphMetadata(graph);
68119
- const tempPath = `${graphPath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
68120
- await fsPromises5.mkdir(path53.dirname(tempPath), { recursive: true });
68121
- let lastError = null;
68122
- try {
68123
- if (options?.createAtomic) {
68124
- try {
68125
- const handle2 = await fsPromises5.open(tempPath, "wx", 420);
68126
- await handle2.writeFile(JSON.stringify(graph, null, 2), "utf-8");
68127
- await handle2.close();
68128
- } catch (error93) {
68129
- if (error93 instanceof Error && "code" in error93 && error93.code === "EEXIST") {
68130
- throw new Error("file already exists");
68131
- }
68132
- throw error93;
68133
- }
68134
- } else {
68135
- await fsPromises5.writeFile(tempPath, JSON.stringify(graph, null, 2), "utf-8");
68136
- }
68137
- if (options?.createAtomic) {
68138
- try {
68139
- await fsPromises5.copyFile(tempPath, graphPath, constants4.COPYFILE_EXCL);
68140
- } catch (error93) {
68141
- lastError = error93 instanceof Error ? error93 : new Error(String(error93));
68142
- throw lastError;
68143
- }
68144
- } else {
68145
- let retries = 0;
68146
- while (retries < WINDOWS_RENAME_MAX_RETRIES2) {
68147
- try {
68148
- await fsPromises5.rename(tempPath, graphPath);
68149
- break;
68150
- } catch (error93) {
68151
- lastError = error93 instanceof Error ? error93 : new Error(String(error93));
68152
- if (lastError instanceof Error && "code" in lastError && lastError.code === "EEXIST" && retries < WINDOWS_RENAME_MAX_RETRIES2 - 1) {
68153
- retries++;
68154
- await new Promise((resolve18) => setTimeout(resolve18, WINDOWS_RENAME_RETRY_DELAY_MS2));
68155
- continue;
68156
- }
68157
- throw lastError;
68158
- }
68159
- }
68160
- }
68161
- } finally {
68162
- try {
68163
- await fsPromises5.unlink(tempPath);
68164
- } catch (error93) {
68165
- if (error93 instanceof Error && "code" in error93 && error93.code !== "ENOENT") {
68166
- error48(`Failed to clean up temp file ${tempPath}:`, error93);
68167
- }
68168
- }
68169
- }
68170
- const stats = await fsPromises5.stat(graphPath);
68171
- setCachedGraph(normalized, graph, stats.mtimeMs);
68172
- }
67891
+
67892
+ // src/tools/repo-graph/builder.ts
68173
67893
  var SKIP_DIRECTORIES2 = new Set([
68174
67894
  "node_modules",
68175
67895
  ".git",
@@ -68196,17 +67916,111 @@ var SUPPORTED_EXTENSIONS = [
68196
67916
  var DEFAULT_WALK_FILE_CAP = 1e4;
68197
67917
  var DEFAULT_WALK_BUDGET_MS = 5000;
68198
67918
  var ASYNC_WALK_YIELD_INTERVAL = 200;
67919
+ var EXTENSION_TO_LANGUAGE = {
67920
+ ".ts": "typescript",
67921
+ ".tsx": "typescript",
67922
+ ".js": "javascript",
67923
+ ".jsx": "javascript",
67924
+ ".mjs": "javascript",
67925
+ ".cjs": "javascript",
67926
+ ".py": "python"
67927
+ };
67928
+ function upsertNode(graph, node) {
67929
+ validateGraphNode(node);
67930
+ const key = normalizeGraphPath(node.filePath);
67931
+ graph.nodes[key] = node;
67932
+ updateGraphMetadata(graph);
67933
+ }
67934
+ function addEdge(graph, edge) {
67935
+ validateGraphEdge(edge);
67936
+ const exists = graph.edges.some((e) => e.source === edge.source && e.target === edge.target && e.importSpecifier === edge.importSpecifier);
67937
+ if (!exists) {
67938
+ graph.edges.push(edge);
67939
+ updateGraphMetadata(graph);
67940
+ }
67941
+ }
67942
+ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
67943
+ if (containsControlChars(specifier)) {
67944
+ return null;
67945
+ }
67946
+ if (specifier.startsWith("/") || specifier.startsWith("\\")) {
67947
+ return null;
67948
+ }
67949
+ if (/^[A-Za-z]:[/\\]/.test(specifier)) {
67950
+ return null;
67951
+ }
67952
+ if (specifier.startsWith("http://") || specifier.startsWith("https://")) {
67953
+ return null;
67954
+ }
67955
+ try {
67956
+ if (specifier.startsWith(".")) {
67957
+ const sourceDir = path54.dirname(sourceFile);
67958
+ let resolved = path54.resolve(sourceDir, specifier);
67959
+ let realResolved;
67960
+ try {
67961
+ realResolved = realpathSync6(resolved);
67962
+ } catch {
67963
+ realResolved = resolved;
67964
+ }
67965
+ let realRoot;
67966
+ try {
67967
+ realRoot = realpathSync6(workspaceRoot);
67968
+ } catch {
67969
+ realRoot = path54.normalize(workspaceRoot);
67970
+ }
67971
+ if (!existsSync29(resolved)) {
67972
+ const EXTENSIONS = [
67973
+ ".ts",
67974
+ ".tsx",
67975
+ ".js",
67976
+ ".jsx",
67977
+ ".mjs",
67978
+ ".cjs",
67979
+ ".py",
67980
+ ".json"
67981
+ ];
67982
+ let found = null;
67983
+ for (const ext of EXTENSIONS) {
67984
+ const candidate = resolved + ext;
67985
+ if (existsSync29(candidate)) {
67986
+ found = candidate;
67987
+ break;
67988
+ }
67989
+ }
67990
+ if (found) {
67991
+ try {
67992
+ realResolved = realpathSync6(found);
67993
+ } catch {
67994
+ realResolved = found;
67995
+ }
67996
+ resolved = found;
67997
+ } else {
67998
+ return null;
67999
+ }
68000
+ }
68001
+ const normalizedResolved = path54.normalize(realResolved);
68002
+ const normalizedRoot = path54.normalize(realRoot);
68003
+ if (!normalizedResolved.startsWith(normalizedRoot + path54.sep) && normalizedResolved !== normalizedRoot) {
68004
+ return null;
68005
+ }
68006
+ return resolved;
68007
+ }
68008
+ return null;
68009
+ } catch {
68010
+ return null;
68011
+ }
68012
+ }
68199
68013
  function isRefusedWorkspaceRoot(target) {
68200
68014
  let resolved;
68201
68015
  try {
68202
68016
  resolved = realpathSync6(target);
68203
68017
  } catch {
68204
- resolved = path53.resolve(target);
68018
+ resolved = path54.resolve(target);
68205
68019
  }
68206
68020
  const refused = new Set;
68207
68021
  const add = (p) => {
68208
68022
  if (typeof p === "string" && p.length > 0) {
68209
- refused.add(path53.resolve(p));
68023
+ refused.add(path54.resolve(p));
68210
68024
  }
68211
68025
  };
68212
68026
  add(os7.homedir());
@@ -68221,15 +68035,6 @@ function isRefusedWorkspaceRoot(target) {
68221
68035
  }
68222
68036
  return refused.has(resolved);
68223
68037
  }
68224
- var EXTENSION_TO_LANGUAGE = {
68225
- ".ts": "typescript",
68226
- ".tsx": "typescript",
68227
- ".js": "javascript",
68228
- ".jsx": "javascript",
68229
- ".mjs": "javascript",
68230
- ".cjs": "javascript",
68231
- ".py": "python"
68232
- };
68233
68038
  function parseFileImports(content) {
68234
68039
  const imports = [];
68235
68040
  const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`\0\t\r\n]+)['"`]|import\s+['"`]([^'"`\0\t\r\n]+)['"`]|require\s*\(\s*['"`]([^'"`\0\t\r\n]+)['"`]\s*\)|export\s*\{[^}]*\}\s*from\s+['"`]([^'"`\0\t\r\n]+)['"`]|export\s+\*(?:\s+as\s+\w+)?\s+from\s+['"`]([^'"`\0\t\r\n]+)['"`]|import\s*\(\s*['"`]([^'"`\0\t\r\n]+)['"`]\s*\)/g;
@@ -68325,7 +68130,7 @@ async function findSourceFilesAsync(dir, stats, options) {
68325
68130
  ctx.stats.skippedDirs++;
68326
68131
  continue;
68327
68132
  }
68328
- const fullPath = path53.join(current, entry.name);
68133
+ const fullPath = path54.join(current, entry.name);
68329
68134
  if (entry.isSymbolicLink() && !ctx.followSymlinks) {
68330
68135
  ctx.stats.skippedDirs++;
68331
68136
  continue;
@@ -68333,7 +68138,7 @@ async function findSourceFilesAsync(dir, stats, options) {
68333
68138
  if (entry.isDirectory()) {
68334
68139
  queue.push(fullPath);
68335
68140
  } else if (entry.isFile()) {
68336
- const ext = path53.extname(fullPath).toLowerCase();
68141
+ const ext = path54.extname(fullPath).toLowerCase();
68337
68142
  if (SUPPORTED_EXTENSIONS.includes(ext)) {
68338
68143
  files.push(fullPath);
68339
68144
  }
@@ -68350,11 +68155,11 @@ async function findSourceFilesAsync(dir, stats, options) {
68350
68155
  return files;
68351
68156
  }
68352
68157
  function toModuleName(filePath, workspaceRoot) {
68353
- const relative9 = path53.relative(workspaceRoot, filePath);
68354
- return relative9.split(path53.sep).join("/");
68158
+ const relative9 = path54.relative(workspaceRoot, filePath);
68159
+ return relative9.split(path54.sep).join("/");
68355
68160
  }
68356
68161
  function getLanguage(filePath) {
68357
- const ext = path53.extname(filePath).toLowerCase();
68162
+ const ext = path54.extname(filePath).toLowerCase();
68358
68163
  return EXTENSION_TO_LANGUAGE[ext] ?? "unknown";
68359
68164
  }
68360
68165
  function isBinaryContent(content) {
@@ -68363,13 +68168,67 @@ function isBinaryContent(content) {
68363
68168
  }
68364
68169
  return false;
68365
68170
  }
68171
+ function scanFile(filePath, absoluteRoot, maxFileSize) {
68172
+ let content;
68173
+ let fileStats;
68174
+ try {
68175
+ fileStats = fsSync3.statSync(filePath);
68176
+ if (fileStats.size > maxFileSize) {
68177
+ return { node: null, edges: [] };
68178
+ }
68179
+ content = fsSync3.readFileSync(filePath, "utf-8");
68180
+ } catch {
68181
+ return { node: null, edges: [] };
68182
+ }
68183
+ if (isBinaryContent(content)) {
68184
+ return { node: null, edges: [] };
68185
+ }
68186
+ const ext = path54.extname(filePath).toLowerCase();
68187
+ let exports = [];
68188
+ try {
68189
+ if ([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext)) {
68190
+ const relativePath = path54.relative(absoluteRoot, filePath);
68191
+ const symbols2 = extractTSSymbols(relativePath, absoluteRoot);
68192
+ exports = symbols2.filter((s) => s.exported).map((s) => s.name);
68193
+ } else if (ext === ".py") {
68194
+ const relativePath = path54.relative(absoluteRoot, filePath);
68195
+ const symbols2 = extractPythonSymbols(relativePath, absoluteRoot);
68196
+ exports = symbols2.filter((s) => s.exported).map((s) => s.name);
68197
+ }
68198
+ const parsedImports = parseFileImports(content);
68199
+ const node = {
68200
+ filePath,
68201
+ moduleName: toModuleName(filePath, absoluteRoot),
68202
+ exports,
68203
+ imports: parsedImports.map((p) => p.specifier),
68204
+ language: getLanguage(filePath),
68205
+ mtime: fileStats.mtime.toISOString()
68206
+ };
68207
+ const edges = [];
68208
+ const sortedImports = [...parsedImports].sort((a, b) => a.specifier.localeCompare(b.specifier));
68209
+ for (const parsed of sortedImports) {
68210
+ const resolvedTarget = resolveModuleSpecifier(absoluteRoot, filePath, parsed.specifier);
68211
+ if (resolvedTarget !== null) {
68212
+ edges.push({
68213
+ source: filePath,
68214
+ target: resolvedTarget,
68215
+ importSpecifier: parsed.specifier,
68216
+ importType: parsed.importType
68217
+ });
68218
+ }
68219
+ }
68220
+ return { node, edges };
68221
+ } catch {
68222
+ return { node: null, edges: [] };
68223
+ }
68224
+ }
68366
68225
  async function buildWorkspaceGraphAsync(workspaceRoot, options) {
68367
68226
  validateWorkspace(workspaceRoot);
68368
68227
  const maxFileSize = options?.maxFileSizeBytes ?? 1024 * 1024;
68369
68228
  const maxFiles = options?.maxFiles ?? DEFAULT_WALK_FILE_CAP;
68370
68229
  const walkBudgetMs = options?.walkBudgetMs ?? DEFAULT_WALK_BUDGET_MS;
68371
68230
  const followSymlinks = options?.followSymlinks ?? false;
68372
- const absoluteRoot = path53.resolve(workspaceRoot);
68231
+ const absoluteRoot = path54.resolve(workspaceRoot);
68373
68232
  if (!existsSync29(absoluteRoot)) {
68374
68233
  throw new Error(`Workspace directory does not exist: ${workspaceRoot}`);
68375
68234
  }
@@ -68424,60 +68283,225 @@ async function buildWorkspaceGraphAsync(workspaceRoot, options) {
68424
68283
  }
68425
68284
  return graph;
68426
68285
  }
68427
- function scanFile(filePath, absoluteRoot, maxFileSize) {
68428
- let content;
68429
- let fileStats;
68286
+ // src/tools/repo-graph/cache.ts
68287
+ import * as path55 from "node:path";
68288
+ var graphCache = new Map;
68289
+ var dirtyFlags = new Map;
68290
+ var mtimeCache = new Map;
68291
+ function getCachedGraph(workspace) {
68292
+ return graphCache.get(path55.normalize(workspace));
68293
+ }
68294
+ function setCachedGraph(workspace, graph, mtime) {
68295
+ const normalized = path55.normalize(workspace);
68296
+ graphCache.set(normalized, graph);
68297
+ dirtyFlags.set(normalized, false);
68298
+ if (mtime !== undefined) {
68299
+ mtimeCache.set(normalized, mtime);
68300
+ }
68301
+ }
68302
+ function isDirty(workspace) {
68303
+ return dirtyFlags.get(path55.normalize(workspace)) ?? false;
68304
+ }
68305
+ function clearCache(workspace) {
68306
+ const normalized = path55.normalize(workspace);
68307
+ graphCache.delete(normalized);
68308
+ dirtyFlags.delete(normalized);
68309
+ mtimeCache.delete(normalized);
68310
+ }
68311
+ function getCachedMtime(workspace) {
68312
+ return mtimeCache.get(path55.normalize(workspace));
68313
+ }
68314
+ // src/tools/repo-graph/incremental.ts
68315
+ import { existsSync as existsSync31 } from "node:fs";
68316
+ import * as fsPromises7 from "node:fs/promises";
68317
+ import * as path57 from "node:path";
68318
+
68319
+ // src/tools/repo-graph/storage.ts
68320
+ init_utils2();
68321
+ init_path_security();
68322
+ import { constants as constants4, existsSync as existsSync30, realpathSync as realpathSync7 } from "node:fs";
68323
+ import * as fsPromises6 from "node:fs/promises";
68324
+ import * as path56 from "node:path";
68325
+ var WINDOWS_RENAME_MAX_RETRIES2 = 3;
68326
+ var WINDOWS_RENAME_RETRY_DELAY_MS2 = 50;
68327
+ function getGraphPath(workspace) {
68328
+ validateWorkspace(workspace);
68329
+ const basePath = validateSwarmPath(workspace, REPO_GRAPH_FILENAME);
68330
+ validateSymlinkBoundary(basePath, workspace);
68331
+ return basePath;
68332
+ }
68333
+ async function loadGraph(workspace) {
68334
+ validateWorkspace(workspace);
68335
+ const normalized = path56.normalize(workspace);
68336
+ const cached3 = getCachedGraph(normalized);
68337
+ if (cached3 && !isDirty(normalized)) {
68338
+ try {
68339
+ const graphPath = getGraphPath(workspace);
68340
+ if (existsSync30(graphPath)) {
68341
+ const stats = await fsPromises6.stat(graphPath);
68342
+ const cachedMtime = getCachedMtime(normalized);
68343
+ if (cachedMtime !== undefined && stats.mtimeMs !== cachedMtime) {
68344
+ clearCache(normalized);
68345
+ } else {
68346
+ return cached3;
68347
+ }
68348
+ } else {
68349
+ clearCache(normalized);
68350
+ }
68351
+ } catch {
68352
+ clearCache(normalized);
68353
+ }
68354
+ }
68430
68355
  try {
68431
- fileStats = fsSync3.statSync(filePath);
68432
- if (fileStats.size > maxFileSize) {
68433
- return { node: null, edges: [] };
68356
+ const graphPath = getGraphPath(workspace);
68357
+ if (!existsSync30(graphPath)) {
68358
+ return null;
68434
68359
  }
68435
- content = fsSync3.readFileSync(filePath, "utf-8");
68360
+ const stats = await fsPromises6.stat(graphPath);
68361
+ const content = await fsPromises6.readFile(graphPath, "utf-8");
68362
+ if (content.includes("\x00") || content.includes("�")) {
68363
+ throw Object.assign(new Error("repo-graph.json contains null bytes or invalid encoding"), { code: "CORRUPTION" });
68364
+ }
68365
+ let parsed;
68366
+ try {
68367
+ parsed = JSON.parse(content);
68368
+ } catch {
68369
+ throw Object.assign(new Error("repo-graph.json contains invalid JSON"), {
68370
+ code: "CORRUPTION"
68371
+ });
68372
+ }
68373
+ if (!parsed.schema_version) {
68374
+ throw Object.assign(new Error("repo-graph.json missing schema_version"), {
68375
+ code: "CORRUPTION"
68376
+ });
68377
+ }
68378
+ if (!parsed.nodes || typeof parsed.nodes !== "object") {
68379
+ throw Object.assign(new Error("repo-graph.json missing or invalid nodes"), { code: "CORRUPTION" });
68380
+ }
68381
+ if (!Array.isArray(parsed.edges)) {
68382
+ throw Object.assign(new Error("repo-graph.json missing or invalid edges"), { code: "CORRUPTION" });
68383
+ }
68384
+ for (const [key, node] of Object.entries(parsed.nodes)) {
68385
+ if (!key || typeof key !== "string") {
68386
+ throw Object.assign(new Error("repo-graph.json contains invalid node key"), { code: "CORRUPTION" });
68387
+ }
68388
+ try {
68389
+ validateGraphNode(node);
68390
+ } catch (err2) {
68391
+ const msg = err2 instanceof Error ? err2.message : "Invalid node structure";
68392
+ throw Object.assign(new Error(`repo-graph.json node validation failed: ${msg}`), { code: "CORRUPTION" });
68393
+ }
68394
+ }
68395
+ for (const edge of parsed.edges) {
68396
+ try {
68397
+ validateGraphEdge(edge);
68398
+ } catch (err2) {
68399
+ const msg = err2 instanceof Error ? err2.message : "Invalid edge structure";
68400
+ throw Object.assign(new Error(`repo-graph.json edge validation failed: ${msg}`), { code: "CORRUPTION" });
68401
+ }
68402
+ }
68403
+ if (!parsed.metadata || typeof parsed.metadata !== "object" || typeof parsed.metadata.generatedAt !== "string" || typeof parsed.metadata.generator !== "string" || typeof parsed.metadata.nodeCount !== "number" || typeof parsed.metadata.edgeCount !== "number") {
68404
+ throw Object.assign(new Error("repo-graph.json missing or invalid metadata"), { code: "CORRUPTION" });
68405
+ }
68406
+ setCachedGraph(normalized, parsed, stats.mtimeMs);
68407
+ return parsed;
68408
+ } catch (error93) {
68409
+ if (error93 instanceof Error && "code" in error93 && error93.code === "CORRUPTION") {
68410
+ throw error93;
68411
+ }
68412
+ if (error93 instanceof Error && "code" in error93 && error93.code === "ENOENT") {
68413
+ return null;
68414
+ }
68415
+ throw error93;
68416
+ }
68417
+ }
68418
+ async function saveGraph(workspace, graph, options) {
68419
+ validateWorkspace(workspace);
68420
+ if (!graph.schema_version) {
68421
+ throw new Error("Graph must have schema_version");
68422
+ }
68423
+ if (!graph.nodes || typeof graph.nodes !== "object") {
68424
+ throw new Error("Graph must have nodes object");
68425
+ }
68426
+ if (!Array.isArray(graph.edges)) {
68427
+ throw new Error("Graph must have edges array");
68428
+ }
68429
+ const normalizedWorkspace = path56.normalize(workspace);
68430
+ let realWorkspace;
68431
+ try {
68432
+ realWorkspace = realpathSync7(workspace);
68436
68433
  } catch {
68437
- return { node: null, edges: [] };
68434
+ realWorkspace = normalizedWorkspace;
68438
68435
  }
68439
- if (isBinaryContent(content)) {
68440
- return { node: null, edges: [] };
68436
+ const normalizedGraphRoot = path56.normalize(graph.workspaceRoot);
68437
+ let realGraphRoot;
68438
+ try {
68439
+ realGraphRoot = realpathSync7(graph.workspaceRoot);
68440
+ } catch {
68441
+ realGraphRoot = normalizedGraphRoot;
68441
68442
  }
68442
- const ext = path53.extname(filePath).toLowerCase();
68443
- let exports = [];
68443
+ if (path56.normalize(realWorkspace) !== path56.normalize(realGraphRoot)) {
68444
+ throw new Error(`Graph workspaceRoot mismatch: graph was built for "${graph.workspaceRoot}" but save was called for "${workspace}"`);
68445
+ }
68446
+ const normalized = normalizedWorkspace;
68447
+ const graphPath = getGraphPath(workspace);
68448
+ updateGraphMetadata(graph);
68449
+ const tempPath = `${graphPath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
68450
+ await fsPromises6.mkdir(path56.dirname(tempPath), { recursive: true });
68451
+ let lastError = null;
68444
68452
  try {
68445
- if ([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext)) {
68446
- const relativePath = path53.relative(absoluteRoot, filePath);
68447
- const symbols2 = extractTSSymbols(relativePath, absoluteRoot);
68448
- exports = symbols2.filter((s) => s.exported).map((s) => s.name);
68449
- } else if (ext === ".py") {
68450
- const relativePath = path53.relative(absoluteRoot, filePath);
68451
- const symbols2 = extractPythonSymbols(relativePath, absoluteRoot);
68452
- exports = symbols2.filter((s) => s.exported).map((s) => s.name);
68453
+ if (options?.createAtomic) {
68454
+ try {
68455
+ const handle2 = await fsPromises6.open(tempPath, "wx", 420);
68456
+ await handle2.writeFile(JSON.stringify(graph, null, 2), "utf-8");
68457
+ await handle2.close();
68458
+ } catch (error93) {
68459
+ if (error93 instanceof Error && "code" in error93 && error93.code === "EEXIST") {
68460
+ throw new Error("file already exists");
68461
+ }
68462
+ throw error93;
68463
+ }
68464
+ } else {
68465
+ await fsPromises6.writeFile(tempPath, JSON.stringify(graph, null, 2), "utf-8");
68453
68466
  }
68454
- const parsedImports = parseFileImports(content);
68455
- const node = {
68456
- filePath,
68457
- moduleName: toModuleName(filePath, absoluteRoot),
68458
- exports,
68459
- imports: parsedImports.map((p) => p.specifier),
68460
- language: getLanguage(filePath),
68461
- mtime: fileStats.mtime.toISOString()
68462
- };
68463
- const edges = [];
68464
- const sortedImports = [...parsedImports].sort((a, b) => a.specifier.localeCompare(b.specifier));
68465
- for (const parsed of sortedImports) {
68466
- const resolvedTarget = resolveModuleSpecifier(absoluteRoot, filePath, parsed.specifier);
68467
- if (resolvedTarget !== null) {
68468
- edges.push({
68469
- source: filePath,
68470
- target: resolvedTarget,
68471
- importSpecifier: parsed.specifier,
68472
- importType: parsed.importType
68473
- });
68467
+ if (options?.createAtomic) {
68468
+ try {
68469
+ await fsPromises6.copyFile(tempPath, graphPath, constants4.COPYFILE_EXCL);
68470
+ } catch (error93) {
68471
+ lastError = error93 instanceof Error ? error93 : new Error(String(error93));
68472
+ throw lastError;
68473
+ }
68474
+ } else {
68475
+ let retries = 0;
68476
+ while (retries < WINDOWS_RENAME_MAX_RETRIES2) {
68477
+ try {
68478
+ await fsPromises6.rename(tempPath, graphPath);
68479
+ break;
68480
+ } catch (error93) {
68481
+ lastError = error93 instanceof Error ? error93 : new Error(String(error93));
68482
+ if (lastError instanceof Error && "code" in lastError && lastError.code === "EEXIST" && retries < WINDOWS_RENAME_MAX_RETRIES2 - 1) {
68483
+ retries++;
68484
+ await new Promise((resolve18) => setTimeout(resolve18, WINDOWS_RENAME_RETRY_DELAY_MS2));
68485
+ continue;
68486
+ }
68487
+ throw lastError;
68488
+ }
68489
+ }
68490
+ }
68491
+ } finally {
68492
+ try {
68493
+ await fsPromises6.unlink(tempPath);
68494
+ } catch (error93) {
68495
+ if (error93 instanceof Error && "code" in error93 && error93.code !== "ENOENT") {
68496
+ error48(`Failed to clean up temp file ${tempPath}:`, error93);
68474
68497
  }
68475
68498
  }
68476
- return { node, edges };
68477
- } catch {
68478
- return { node: null, edges: [] };
68479
68499
  }
68500
+ const stats = await fsPromises6.stat(graphPath);
68501
+ setCachedGraph(normalized, graph, stats.mtimeMs);
68480
68502
  }
68503
+
68504
+ // src/tools/repo-graph/incremental.ts
68481
68505
  async function updateGraphForFiles(workspaceRoot, filePaths, options) {
68482
68506
  if (options?.forceRebuild) {
68483
68507
  const graph2 = await buildWorkspaceGraphAsync(workspaceRoot);
@@ -68491,12 +68515,12 @@ async function updateGraphForFiles(workspaceRoot, filePaths, options) {
68491
68515
  return graph2;
68492
68516
  }
68493
68517
  const graph = existingGraph;
68494
- const absoluteRoot = path53.resolve(workspaceRoot);
68518
+ const absoluteRoot = path57.resolve(workspaceRoot);
68495
68519
  const maxFileSize = 1024 * 1024;
68496
68520
  const updatedPaths = new Set;
68497
68521
  for (const rawFilePath of filePaths) {
68498
68522
  const normalizedPath = normalizeGraphPath(rawFilePath);
68499
- const fileExists = existsSync29(rawFilePath);
68523
+ const fileExists = existsSync31(rawFilePath);
68500
68524
  if (fileExists) {
68501
68525
  graph.edges = graph.edges.filter((e) => normalizeGraphPath(e.source) !== normalizedPath);
68502
68526
  const result = scanFile(rawFilePath, absoluteRoot, maxFileSize);
@@ -68531,6 +68555,22 @@ async function updateGraphForFiles(workspaceRoot, filePaths, options) {
68531
68555
  await saveGraph(workspaceRoot, rebuiltGraph);
68532
68556
  return rebuiltGraph;
68533
68557
  }
68558
+ const normalizedWorkspace = path57.normalize(workspaceRoot);
68559
+ const loadedMtime = getCachedMtime(normalizedWorkspace);
68560
+ if (loadedMtime !== undefined) {
68561
+ try {
68562
+ const graphPath = getGraphPath(workspaceRoot);
68563
+ if (existsSync31(graphPath)) {
68564
+ const currentStats = await fsPromises7.stat(graphPath);
68565
+ if (currentStats.mtimeMs !== loadedMtime) {
68566
+ warn(`[repo-graph] Concurrent modification detected — falling back to full rebuild`);
68567
+ const rebuiltGraph = await buildWorkspaceGraphAsync(workspaceRoot);
68568
+ await saveGraph(workspaceRoot, rebuiltGraph);
68569
+ return rebuiltGraph;
68570
+ }
68571
+ }
68572
+ } catch {}
68573
+ }
68534
68574
  updateGraphMetadata(graph);
68535
68575
  await saveGraph(workspaceRoot, graph);
68536
68576
  return graph;
@@ -68549,9 +68589,20 @@ function extractFilePath(args2) {
68549
68589
  if (!args2 || typeof args2 !== "object")
68550
68590
  return null;
68551
68591
  const a = args2;
68552
- const filePath = a.file_path ?? a.path ?? a.filePath;
68592
+ let filePath = a.file_path ?? a.path ?? a.filePath;
68553
68593
  if (!filePath || typeof filePath !== "string")
68554
68594
  return null;
68595
+ for (let i2 = 0;i2 < 3; i2++) {
68596
+ try {
68597
+ const decoded = decodeURIComponent(filePath);
68598
+ if (decoded === filePath)
68599
+ break;
68600
+ filePath = decoded;
68601
+ } catch {
68602
+ break;
68603
+ }
68604
+ }
68605
+ filePath = filePath.replace(/./g, ".").replace(///g, "/").replace(/․/g, ".");
68555
68606
  return filePath;
68556
68607
  }
68557
68608
  function isSupportedSourceFile(filePath) {
@@ -68564,6 +68615,8 @@ function createRepoGraphBuilderHook(workspaceRoot, deps) {
68564
68615
  const _updateGraphForFiles = deps?.updateGraphForFiles ?? updateGraphForFiles;
68565
68616
  let initStarted = false;
68566
68617
  let initPromise = Promise.resolve();
68618
+ let consecutiveFailures = 0;
68619
+ const FAILURE_ADVISORY_THRESHOLD = 3;
68567
68620
  async function doInit() {
68568
68621
  await yieldToEventLoop();
68569
68622
  try {
@@ -68592,37 +68645,48 @@ function createRepoGraphBuilderHook(workspaceRoot, deps) {
68592
68645
  if (!WRITE_TOOL_NAMES.includes(input.tool)) {
68593
68646
  return;
68594
68647
  }
68595
- const rawFilePath = extractFilePath(input.args);
68596
- if (!rawFilePath)
68648
+ const filePath = extractFilePath(input.args);
68649
+ if (!filePath)
68597
68650
  return;
68598
- if (rawFilePath.includes("\x00"))
68651
+ if (filePath.includes("\x00"))
68599
68652
  return;
68600
- let filePath = rawFilePath;
68601
- for (let i2 = 0;i2 < 3; i2++) {
68602
- try {
68603
- const decoded = decodeURIComponent(filePath);
68604
- if (decoded === filePath)
68605
- break;
68606
- filePath = decoded;
68607
- } catch {
68608
- break;
68609
- }
68610
- }
68611
- filePath = filePath.replace(/./g, ".").replace(///g, "/").replace(/․/g, ".");
68612
68653
  if (!isSupportedSourceFile(filePath))
68613
68654
  return;
68614
- const absoluteFilePath = path54.isAbsolute(filePath) ? filePath : path54.resolve(workspaceRoot, filePath);
68615
- const normalizedAbsolute = absoluteFilePath.replace(/\\/g, "/");
68616
- const normalizedWorkspace = workspaceRoot.replace(/\\/g, "/");
68655
+ const absoluteFilePath = path58.isAbsolute(filePath) ? filePath : path58.resolve(workspaceRoot, filePath);
68656
+ let realFilePath;
68657
+ try {
68658
+ realFilePath = realpathSync8(absoluteFilePath);
68659
+ } catch (error93) {
68660
+ if (!(error93 instanceof Error) || error93.code !== "ENOENT") {
68661
+ return;
68662
+ }
68663
+ realFilePath = absoluteFilePath;
68664
+ }
68665
+ let realWorkspace;
68666
+ try {
68667
+ realWorkspace = realpathSync8(workspaceRoot);
68668
+ } catch (error93) {
68669
+ if (!(error93 instanceof Error) || error93.code !== "ENOENT") {
68670
+ return;
68671
+ }
68672
+ realWorkspace = workspaceRoot;
68673
+ }
68674
+ const normalizedAbsolute = realFilePath.replace(/\\/g, "/");
68675
+ const normalizedWorkspace = realWorkspace.replace(/\\/g, "/");
68617
68676
  if (!normalizedAbsolute.startsWith(`${normalizedWorkspace}/`) && normalizedAbsolute !== normalizedWorkspace) {
68618
68677
  return;
68619
68678
  }
68620
68679
  try {
68621
68680
  await _updateGraphForFiles(workspaceRoot, [absoluteFilePath]);
68622
- log(`[repo-graph] Incremental update for ${path54.basename(filePath)}`);
68681
+ consecutiveFailures = 0;
68682
+ log(`[repo-graph] Incremental update for ${path58.basename(filePath)}`);
68623
68683
  } catch (error93) {
68624
68684
  const message = error93 instanceof Error ? error93.message : String(error93);
68685
+ consecutiveFailures++;
68625
68686
  error48(`[repo-graph] Incremental update failed: ${message}`);
68687
+ if (consecutiveFailures >= FAILURE_ADVISORY_THRESHOLD) {
68688
+ warn(`[repo-graph] ${consecutiveFailures} consecutive incremental update failures. ` + `The dependency graph may be stale. Consider reloading the workspace.`);
68689
+ }
68626
68690
  }
68627
68691
  }
68628
68692
  };
@@ -68638,14 +68702,14 @@ init_manager2();
68638
68702
  init_detector();
68639
68703
  init_manager();
68640
68704
  import * as fs46 from "node:fs";
68641
- import * as path64 from "node:path";
68705
+ import * as path68 from "node:path";
68642
68706
 
68643
68707
  // src/services/decision-drift-analyzer.ts
68644
68708
  init_utils2();
68645
68709
  init_manager();
68646
68710
  init_utils();
68647
68711
  import * as fs38 from "node:fs";
68648
- import * as path55 from "node:path";
68712
+ import * as path59 from "node:path";
68649
68713
  var DEFAULT_DRIFT_CONFIG = {
68650
68714
  staleThresholdPhases: 1,
68651
68715
  detectContradictions: true,
@@ -68799,7 +68863,7 @@ async function analyzeDecisionDrift(directory, config3 = {}) {
68799
68863
  currentPhase = legacyPhase;
68800
68864
  }
68801
68865
  }
68802
- const contextPath = path55.join(directory, ".swarm", "context.md");
68866
+ const contextPath = path59.join(directory, ".swarm", "context.md");
68803
68867
  let contextContent = "";
68804
68868
  try {
68805
68869
  if (fs38.existsSync(contextPath)) {
@@ -68938,7 +69002,7 @@ init_utils();
68938
69002
  init_constants();
68939
69003
  init_schema();
68940
69004
  import * as fs39 from "node:fs/promises";
68941
- import * as path56 from "node:path";
69005
+ import * as path60 from "node:path";
68942
69006
  function safeGet(obj, key) {
68943
69007
  if (!obj || !Object.hasOwn(obj, key))
68944
69008
  return;
@@ -69170,9 +69234,9 @@ async function handleDebuggingSpiral(match, taskId, directory) {
69170
69234
  let eventLogged = false;
69171
69235
  let checkpointCreated = false;
69172
69236
  try {
69173
- const swarmDir = path56.join(directory, ".swarm");
69237
+ const swarmDir = path60.join(directory, ".swarm");
69174
69238
  await fs39.mkdir(swarmDir, { recursive: true });
69175
- const eventsPath = path56.join(swarmDir, "events.jsonl");
69239
+ const eventsPath = path60.join(swarmDir, "events.jsonl");
69176
69240
  await fs39.appendFile(eventsPath, `${formatDebuggingSpiralEvent(match, taskId)}
69177
69241
  `);
69178
69242
  eventLogged = true;
@@ -69307,7 +69371,7 @@ import * as fs43 from "node:fs";
69307
69371
 
69308
69372
  // src/graph/graph-builder.ts
69309
69373
  import * as fs41 from "node:fs";
69310
- import * as path59 from "node:path";
69374
+ import * as path63 from "node:path";
69311
69375
 
69312
69376
  // node_modules/yocto-queue/index.js
69313
69377
  class Node {
@@ -69398,26 +69462,26 @@ function pLimit(concurrency) {
69398
69462
  activeCount--;
69399
69463
  resumeNext();
69400
69464
  };
69401
- const run2 = async (function_, resolve19, arguments_2) => {
69465
+ const run2 = async (function_, resolve20, arguments_2) => {
69402
69466
  const result = (async () => function_(...arguments_2))();
69403
- resolve19(result);
69467
+ resolve20(result);
69404
69468
  try {
69405
69469
  await result;
69406
69470
  } catch {}
69407
69471
  next();
69408
69472
  };
69409
- const enqueue = (function_, resolve19, reject, arguments_2) => {
69473
+ const enqueue = (function_, resolve20, reject, arguments_2) => {
69410
69474
  const queueItem = { reject };
69411
69475
  new Promise((internalResolve) => {
69412
69476
  queueItem.run = internalResolve;
69413
69477
  queue.enqueue(queueItem);
69414
- }).then(run2.bind(undefined, function_, resolve19, arguments_2));
69478
+ }).then(run2.bind(undefined, function_, resolve20, arguments_2));
69415
69479
  if (activeCount < concurrency) {
69416
69480
  resumeNext();
69417
69481
  }
69418
69482
  };
69419
- const generator = (function_, ...arguments_2) => new Promise((resolve19, reject) => {
69420
- enqueue(function_, resolve19, reject, arguments_2);
69483
+ const generator = (function_, ...arguments_2) => new Promise((resolve20, reject) => {
69484
+ enqueue(function_, resolve20, reject, arguments_2);
69421
69485
  });
69422
69486
  Object.defineProperties(generator, {
69423
69487
  activeCount: {
@@ -69468,7 +69532,7 @@ function validateConcurrency(concurrency) {
69468
69532
  // src/graph/import-extractor.ts
69469
69533
  init_path_security();
69470
69534
  import * as fs40 from "node:fs";
69471
- import * as path57 from "node:path";
69535
+ import * as path61 from "node:path";
69472
69536
  var SOURCE_EXTENSIONS2 = [
69473
69537
  ".ts",
69474
69538
  ".tsx",
@@ -69513,28 +69577,28 @@ function getLanguageFromExtension(ext) {
69513
69577
  return null;
69514
69578
  }
69515
69579
  function toRelForwardSlash(absPath, root) {
69516
- return path57.relative(root, absPath).replace(/\\/g, "/");
69580
+ return path61.relative(root, absPath).replace(/\\/g, "/");
69517
69581
  }
69518
69582
  function tryResolveTSJS(rawModule, sourceFileAbs) {
69519
69583
  if (!rawModule.startsWith(".") && !rawModule.startsWith("/")) {
69520
69584
  return null;
69521
69585
  }
69522
- const sourceDir = path57.dirname(sourceFileAbs);
69523
- const baseAbs = path57.resolve(sourceDir, rawModule);
69586
+ const sourceDir = path61.dirname(sourceFileAbs);
69587
+ const baseAbs = path61.resolve(sourceDir, rawModule);
69524
69588
  const probe = (basePath) => {
69525
69589
  for (const ext of RESOLVE_EXTENSION_CANDIDATES) {
69526
69590
  const test = basePath + ext;
69527
69591
  try {
69528
- const stat5 = fs40.statSync(test);
69529
- if (stat5.isFile())
69592
+ const stat6 = fs40.statSync(test);
69593
+ if (stat6.isFile())
69530
69594
  return test;
69531
69595
  } catch {}
69532
69596
  }
69533
69597
  for (const indexFile of RESOLVE_INDEX_CANDIDATES) {
69534
- const test = path57.join(basePath, indexFile);
69598
+ const test = path61.join(basePath, indexFile);
69535
69599
  try {
69536
- const stat5 = fs40.statSync(test);
69537
- if (stat5.isFile())
69600
+ const stat6 = fs40.statSync(test);
69601
+ if (stat6.isFile())
69538
69602
  return test;
69539
69603
  } catch {}
69540
69604
  }
@@ -69561,13 +69625,13 @@ function tryResolvePython(rawModule, sourceFileAbs, workspaceRoot) {
69561
69625
  }
69562
69626
  const remainder = rawModule.slice(leadingDots).replace(/\./g, "/");
69563
69627
  const upDirs = "../".repeat(Math.max(0, leadingDots - 1));
69564
- const sourceDir = path57.dirname(sourceFileAbs);
69565
- const baseAbs = path57.resolve(sourceDir, upDirs + remainder);
69628
+ const sourceDir = path61.dirname(sourceFileAbs);
69629
+ const baseAbs = path61.resolve(sourceDir, upDirs + remainder);
69566
69630
  const accept = (test) => {
69567
69631
  try {
69568
- const stat5 = fs40.statSync(test);
69569
- if (stat5.isFile()) {
69570
- const rel = path57.relative(workspaceRoot, test).replace(/\\/g, "/");
69632
+ const stat6 = fs40.statSync(test);
69633
+ if (stat6.isFile()) {
69634
+ const rel = path61.relative(workspaceRoot, test).replace(/\\/g, "/");
69571
69635
  if (rel.startsWith(".."))
69572
69636
  return null;
69573
69637
  return test;
@@ -69581,7 +69645,7 @@ function tryResolvePython(rawModule, sourceFileAbs, workspaceRoot) {
69581
69645
  return hit;
69582
69646
  }
69583
69647
  for (const indexFile of PY_INDEX_CANDIDATES) {
69584
- const hit = accept(path57.join(baseAbs, indexFile));
69648
+ const hit = accept(path61.join(baseAbs, indexFile));
69585
69649
  if (hit)
69586
69650
  return hit;
69587
69651
  }
@@ -69952,7 +70016,7 @@ function parseRustUses(content) {
69952
70016
  }
69953
70017
  function extractImports2(opts) {
69954
70018
  const { absoluteFilePath, workspaceRoot } = opts;
69955
- const ext = path57.extname(absoluteFilePath).toLowerCase();
70019
+ const ext = path61.extname(absoluteFilePath).toLowerCase();
69956
70020
  const language = getLanguageFromExtension(ext);
69957
70021
  if (!language)
69958
70022
  return [];
@@ -70003,9 +70067,9 @@ function extractImports2(opts) {
70003
70067
  }
70004
70068
 
70005
70069
  // src/graph/symbol-extractor.ts
70006
- import * as path58 from "node:path";
70070
+ import * as path62 from "node:path";
70007
70071
  function extractExportedSymbols(relativeFilePath, workspaceRoot) {
70008
- const ext = path58.extname(relativeFilePath).toLowerCase();
70072
+ const ext = path62.extname(relativeFilePath).toLowerCase();
70009
70073
  const language = getLanguageFromExtension(ext);
70010
70074
  if (!language)
70011
70075
  return [];
@@ -70094,15 +70158,15 @@ function findSourceFiles(workspaceRoot, skipDirs = DEFAULT_SKIP_DIRS) {
70094
70158
  if (entry.isDirectory()) {
70095
70159
  if (skipDirs.has(entry.name))
70096
70160
  continue;
70097
- stack.push(path59.join(dir, entry.name));
70161
+ stack.push(path63.join(dir, entry.name));
70098
70162
  continue;
70099
70163
  }
70100
70164
  if (!entry.isFile())
70101
70165
  continue;
70102
- const ext = path59.extname(entry.name).toLowerCase();
70166
+ const ext = path63.extname(entry.name).toLowerCase();
70103
70167
  if (!SOURCE_EXT_SET.has(ext))
70104
70168
  continue;
70105
- out2.push(path59.join(dir, entry.name));
70169
+ out2.push(path63.join(dir, entry.name));
70106
70170
  }
70107
70171
  }
70108
70172
  return out2;
@@ -70130,7 +70194,7 @@ async function buildRepoGraph(workspaceRoot, options = {}) {
70130
70194
  };
70131
70195
  }
70132
70196
  async function processFile(absoluteFilePath, workspaceRoot) {
70133
- const ext = path59.extname(absoluteFilePath).toLowerCase();
70197
+ const ext = path63.extname(absoluteFilePath).toLowerCase();
70134
70198
  const language = getLanguageFromExtension(ext);
70135
70199
  if (!language)
70136
70200
  return null;
@@ -70150,7 +70214,7 @@ async function processFile(absoluteFilePath, workspaceRoot) {
70150
70214
  } catch {
70151
70215
  return null;
70152
70216
  }
70153
- const relPath = path59.relative(workspaceRoot, absoluteFilePath).replace(/\\/g, "/");
70217
+ const relPath = path63.relative(workspaceRoot, absoluteFilePath).replace(/\\/g, "/");
70154
70218
  const imports = extractImports2({
70155
70219
  absoluteFilePath,
70156
70220
  workspaceRoot,
@@ -70392,10 +70456,10 @@ function formatSummary(opts) {
70392
70456
  // src/graph/graph-store.ts
70393
70457
  import * as crypto6 from "node:crypto";
70394
70458
  import * as fs42 from "node:fs";
70395
- import * as path60 from "node:path";
70459
+ import * as path64 from "node:path";
70396
70460
  var SWARM_DIR = ".swarm";
70397
70461
  function getGraphPath2(workspaceRoot) {
70398
- return path60.join(workspaceRoot, SWARM_DIR, REPO_GRAPH_FILENAME2);
70462
+ return path64.join(workspaceRoot, SWARM_DIR, REPO_GRAPH_FILENAME2);
70399
70463
  }
70400
70464
  function loadGraph2(workspaceRoot) {
70401
70465
  const file3 = getGraphPath2(workspaceRoot);
@@ -70417,10 +70481,10 @@ function loadGraph2(workspaceRoot) {
70417
70481
  }
70418
70482
  function saveGraph2(workspaceRoot, graph) {
70419
70483
  const file3 = getGraphPath2(workspaceRoot);
70420
- const dir = path60.dirname(file3);
70484
+ const dir = path64.dirname(file3);
70421
70485
  try {
70422
- const stat5 = fs42.lstatSync(dir);
70423
- if (stat5.isSymbolicLink()) {
70486
+ const stat6 = fs42.lstatSync(dir);
70487
+ if (stat6.isSymbolicLink()) {
70424
70488
  throw new Error(`refusing to write graph: ${SWARM_DIR}/ is a symbolic link`);
70425
70489
  }
70426
70490
  } catch (err2) {
@@ -70456,15 +70520,15 @@ function isGraphFresh(graph, maxAgeMs = 5 * 60 * 1000) {
70456
70520
  var cache = new Map;
70457
70521
  function getCachedGraph2(directory) {
70458
70522
  const file3 = getGraphPath2(directory);
70459
- let stat5;
70523
+ let stat6;
70460
70524
  try {
70461
- stat5 = fs43.statSync(file3);
70525
+ stat6 = fs43.statSync(file3);
70462
70526
  } catch {
70463
70527
  cache.delete(directory);
70464
70528
  return null;
70465
70529
  }
70466
70530
  const cached3 = cache.get(directory);
70467
- if (cached3 && cached3.mtimeMs === stat5.mtimeMs && cached3.size === stat5.size) {
70531
+ if (cached3 && cached3.mtimeMs === stat6.mtimeMs && cached3.size === stat6.size) {
70468
70532
  return cached3.graph;
70469
70533
  }
70470
70534
  const graph = loadGraph2(directory);
@@ -70472,7 +70536,7 @@ function getCachedGraph2(directory) {
70472
70536
  cache.delete(directory);
70473
70537
  return null;
70474
70538
  }
70475
- cache.set(directory, { graph, mtimeMs: stat5.mtimeMs, size: stat5.size });
70539
+ cache.set(directory, { graph, mtimeMs: stat6.mtimeMs, size: stat6.size });
70476
70540
  return graph;
70477
70541
  }
70478
70542
  function buildCoderLocalizationBlock(directory, targetFile) {
@@ -70523,7 +70587,7 @@ function buildReviewerBlastRadiusBlock(directory, changedFiles) {
70523
70587
  // src/hooks/semantic-diff-injection.ts
70524
70588
  import * as child_process5 from "node:child_process";
70525
70589
  import * as fs44 from "node:fs";
70526
- import * as path62 from "node:path";
70590
+ import * as path66 from "node:path";
70527
70591
 
70528
70592
  // src/diff/ast-diff.ts
70529
70593
  init_tree_sitter();
@@ -71270,17 +71334,17 @@ async function buildSemanticDiffBlock(directory, changedFiles, maxFiles = 10) {
71270
71334
  const fileConsumers = {};
71271
71335
  if (graph) {
71272
71336
  for (const f of filesToProcess) {
71273
- const relativePath = path62.isAbsolute(f) ? path62.relative(directory, f) : f;
71337
+ const relativePath = path66.isAbsolute(f) ? path66.relative(directory, f) : f;
71274
71338
  const normalized = normalizeGraphPath2(relativePath);
71275
71339
  fileConsumers[normalized] = getImporters(graph, normalized).length;
71276
71340
  fileConsumers[f] = fileConsumers[normalized];
71277
71341
  }
71278
71342
  }
71279
71343
  for (const filePath of filesToProcess) {
71280
- const normalizedPath = path62.normalize(filePath);
71281
- const resolvedPath = path62.resolve(directory, normalizedPath);
71282
- const relativeToDir = path62.relative(directory, resolvedPath);
71283
- if (relativeToDir.startsWith("..") || path62.isAbsolute(relativeToDir)) {
71344
+ const normalizedPath = path66.normalize(filePath);
71345
+ const resolvedPath = path66.resolve(directory, normalizedPath);
71346
+ const relativeToDir = path66.relative(directory, resolvedPath);
71347
+ if (relativeToDir.startsWith("..") || path66.isAbsolute(relativeToDir)) {
71284
71348
  continue;
71285
71349
  }
71286
71350
  try {
@@ -71307,7 +71371,7 @@ async function buildSemanticDiffBlock(directory, changedFiles, maxFiles = 10) {
71307
71371
  stdio: "pipe",
71308
71372
  maxBuffer: 5 * 1024 * 1024
71309
71373
  }) : "";
71310
- const newContent = fs44.readFileSync(path62.join(directory, filePath), "utf-8");
71374
+ const newContent = fs44.readFileSync(path66.join(directory, filePath), "utf-8");
71311
71375
  const astResult = await computeASTDiff(filePath, oldContent, newContent);
71312
71376
  if (astResult && (astResult.changes.length > 0 || astResult.error !== undefined)) {
71313
71377
  astDiffs.push(astResult);
@@ -71649,7 +71713,7 @@ function createSystemEnhancerHook(config3, directory) {
71649
71713
  await fs46.promises.writeFile(darkMatterPath, darkMatterReport, "utf-8");
71650
71714
  warn(`[system-enhancer] Dark matter scan complete: ${darkMatter.length} co-change patterns found`);
71651
71715
  try {
71652
- const projectName = path64.basename(path64.resolve(directory));
71716
+ const projectName = path68.basename(path68.resolve(directory));
71653
71717
  const knowledgeEntries = darkMatterToKnowledgeEntries2(darkMatter, projectName);
71654
71718
  const knowledgePath = resolveSwarmKnowledgePath(directory);
71655
71719
  const existingEntries = await readKnowledge(knowledgePath);
@@ -71848,7 +71912,7 @@ ${lines.join(`
71848
71912
  try {
71849
71913
  const taskId_ccp = ccpSession?.currentTaskId;
71850
71914
  if (taskId_ccp && !taskId_ccp.includes("..") && !taskId_ccp.includes("/") && !taskId_ccp.includes("\\") && !taskId_ccp.includes("\x00")) {
71851
- const evidencePath = path64.join(directory, ".swarm", "evidence", `${taskId_ccp}.json`);
71915
+ const evidencePath = path68.join(directory, ".swarm", "evidence", `${taskId_ccp}.json`);
71852
71916
  if (fs46.existsSync(evidencePath)) {
71853
71917
  const evidenceContent = fs46.readFileSync(evidencePath, "utf-8");
71854
71918
  const evidenceData = JSON.parse(evidenceContent);
@@ -72996,13 +73060,13 @@ init_hive_promoter();
72996
73060
 
72997
73061
  // src/hooks/incremental-verify.ts
72998
73062
  import * as fs47 from "node:fs";
72999
- import * as path65 from "node:path";
73063
+ import * as path69 from "node:path";
73000
73064
 
73001
73065
  // src/hooks/spawn-helper.ts
73002
73066
  import * as child_process6 from "node:child_process";
73003
73067
  var WIN32_CMD_BINARIES = new Set(["npm", "npx", "pnpm", "yarn"]);
73004
73068
  function spawnAsync(command, cwd, timeoutMs) {
73005
- return new Promise((resolve23) => {
73069
+ return new Promise((resolve24) => {
73006
73070
  try {
73007
73071
  const [rawCmd, ...args2] = command;
73008
73072
  const cmd = process.platform === "win32" && WIN32_CMD_BINARIES.has(rawCmd) && !rawCmd.includes(".") ? `${rawCmd}.cmd` : rawCmd;
@@ -73049,24 +73113,24 @@ function spawnAsync(command, cwd, timeoutMs) {
73049
73113
  try {
73050
73114
  proc.kill();
73051
73115
  } catch {}
73052
- resolve23(null);
73116
+ resolve24(null);
73053
73117
  }, timeoutMs);
73054
73118
  proc.on("close", (code) => {
73055
73119
  if (done)
73056
73120
  return;
73057
73121
  done = true;
73058
73122
  clearTimeout(timer);
73059
- resolve23({ exitCode: code ?? 1, stdout, stderr });
73123
+ resolve24({ exitCode: code ?? 1, stdout, stderr });
73060
73124
  });
73061
73125
  proc.on("error", () => {
73062
73126
  if (done)
73063
73127
  return;
73064
73128
  done = true;
73065
73129
  clearTimeout(timer);
73066
- resolve23(null);
73130
+ resolve24(null);
73067
73131
  });
73068
73132
  } catch {
73069
- resolve23(null);
73133
+ resolve24(null);
73070
73134
  }
73071
73135
  });
73072
73136
  }
@@ -73074,18 +73138,18 @@ function spawnAsync(command, cwd, timeoutMs) {
73074
73138
  // src/hooks/incremental-verify.ts
73075
73139
  var emittedSkipAdvisories = new Set;
73076
73140
  function detectPackageManager(projectDir) {
73077
- if (fs47.existsSync(path65.join(projectDir, "bun.lockb")))
73141
+ if (fs47.existsSync(path69.join(projectDir, "bun.lockb")))
73078
73142
  return "bun";
73079
- if (fs47.existsSync(path65.join(projectDir, "pnpm-lock.yaml")))
73143
+ if (fs47.existsSync(path69.join(projectDir, "pnpm-lock.yaml")))
73080
73144
  return "pnpm";
73081
- if (fs47.existsSync(path65.join(projectDir, "yarn.lock")))
73145
+ if (fs47.existsSync(path69.join(projectDir, "yarn.lock")))
73082
73146
  return "yarn";
73083
- if (fs47.existsSync(path65.join(projectDir, "package-lock.json")))
73147
+ if (fs47.existsSync(path69.join(projectDir, "package-lock.json")))
73084
73148
  return "npm";
73085
73149
  return "bun";
73086
73150
  }
73087
73151
  function detectTypecheckCommand(projectDir) {
73088
- const pkgPath = path65.join(projectDir, "package.json");
73152
+ const pkgPath = path69.join(projectDir, "package.json");
73089
73153
  if (fs47.existsSync(pkgPath)) {
73090
73154
  try {
73091
73155
  const pkg = JSON.parse(fs47.readFileSync(pkgPath, "utf8"));
@@ -73102,8 +73166,8 @@ function detectTypecheckCommand(projectDir) {
73102
73166
  ...pkg.dependencies,
73103
73167
  ...pkg.devDependencies
73104
73168
  };
73105
- if (!deps?.typescript && !fs47.existsSync(path65.join(projectDir, "tsconfig.json"))) {}
73106
- const hasTSMarkers = deps?.typescript || fs47.existsSync(path65.join(projectDir, "tsconfig.json"));
73169
+ if (!deps?.typescript && !fs47.existsSync(path69.join(projectDir, "tsconfig.json"))) {}
73170
+ const hasTSMarkers = deps?.typescript || fs47.existsSync(path69.join(projectDir, "tsconfig.json"));
73107
73171
  if (hasTSMarkers) {
73108
73172
  return { command: ["npx", "tsc", "--noEmit"], language: "typescript" };
73109
73173
  }
@@ -73111,13 +73175,13 @@ function detectTypecheckCommand(projectDir) {
73111
73175
  return null;
73112
73176
  }
73113
73177
  }
73114
- if (fs47.existsSync(path65.join(projectDir, "go.mod"))) {
73178
+ if (fs47.existsSync(path69.join(projectDir, "go.mod"))) {
73115
73179
  return { command: ["go", "vet", "./..."], language: "go" };
73116
73180
  }
73117
- if (fs47.existsSync(path65.join(projectDir, "Cargo.toml"))) {
73181
+ if (fs47.existsSync(path69.join(projectDir, "Cargo.toml"))) {
73118
73182
  return { command: ["cargo", "check"], language: "rust" };
73119
73183
  }
73120
- if (fs47.existsSync(path65.join(projectDir, "pyproject.toml")) || fs47.existsSync(path65.join(projectDir, "requirements.txt")) || fs47.existsSync(path65.join(projectDir, "setup.py"))) {
73184
+ if (fs47.existsSync(path69.join(projectDir, "pyproject.toml")) || fs47.existsSync(path69.join(projectDir, "requirements.txt")) || fs47.existsSync(path69.join(projectDir, "setup.py"))) {
73121
73185
  return { command: null, language: "python" };
73122
73186
  }
73123
73187
  try {
@@ -73467,7 +73531,7 @@ init_scope_persistence();
73467
73531
  init_state();
73468
73532
  init_delegation_gate();
73469
73533
  init_normalize_tool_name();
73470
- import * as path67 from "node:path";
73534
+ import * as path71 from "node:path";
73471
73535
  var WRITE_TOOLS = new Set(WRITE_TOOL_NAMES);
73472
73536
  function createScopeGuardHook(config3, directory, injectAdvisory) {
73473
73537
  const enabled = config3.enabled ?? true;
@@ -73525,13 +73589,13 @@ function createScopeGuardHook(config3, directory, injectAdvisory) {
73525
73589
  }
73526
73590
  function isFileInScope(filePath, scopeEntries, directory) {
73527
73591
  const dir = directory ?? process.cwd();
73528
- const resolvedFile = path67.resolve(dir, filePath);
73592
+ const resolvedFile = path71.resolve(dir, filePath);
73529
73593
  return scopeEntries.some((scope) => {
73530
- const resolvedScope = path67.resolve(dir, scope);
73594
+ const resolvedScope = path71.resolve(dir, scope);
73531
73595
  if (resolvedFile === resolvedScope)
73532
73596
  return true;
73533
- const rel = path67.relative(resolvedScope, resolvedFile);
73534
- return rel.length > 0 && !rel.startsWith("..") && !path67.isAbsolute(rel);
73597
+ const rel = path71.relative(resolvedScope, resolvedFile);
73598
+ return rel.length > 0 && !rel.startsWith("..") && !path71.isAbsolute(rel);
73535
73599
  });
73536
73600
  }
73537
73601
 
@@ -73583,7 +73647,7 @@ function createSelfReviewHook(config3, injectAdvisory) {
73583
73647
 
73584
73648
  // src/hooks/slop-detector.ts
73585
73649
  import * as fs49 from "node:fs";
73586
- import * as path68 from "node:path";
73650
+ import * as path72 from "node:path";
73587
73651
  var WRITE_EDIT_TOOLS = new Set([
73588
73652
  "write",
73589
73653
  "edit",
@@ -73633,7 +73697,7 @@ function walkFiles(dir, exts, deadline) {
73633
73697
  break;
73634
73698
  if (entry.isSymbolicLink())
73635
73699
  continue;
73636
- const full = path68.join(dir, entry.name);
73700
+ const full = path72.join(dir, entry.name);
73637
73701
  if (entry.isDirectory()) {
73638
73702
  if (entry.name === "node_modules" || entry.name === ".git")
73639
73703
  continue;
@@ -73648,7 +73712,7 @@ function walkFiles(dir, exts, deadline) {
73648
73712
  return results;
73649
73713
  }
73650
73714
  function checkDeadExports(content, projectDir, startTime) {
73651
- const hasPackageJson = fs49.existsSync(path68.join(projectDir, "package.json"));
73715
+ const hasPackageJson = fs49.existsSync(path72.join(projectDir, "package.json"));
73652
73716
  if (!hasPackageJson)
73653
73717
  return null;
73654
73718
  const exportMatches = content.matchAll(/^\+(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm);
@@ -73762,14 +73826,14 @@ function checkDuplicateUtility(content, projectDir, startTime, targetFile) {
73762
73826
  for (const utilDir of utilityDirs) {
73763
73827
  if (Date.now() > deadline)
73764
73828
  break;
73765
- const utilPath = path68.join(projectDir, utilDir);
73829
+ const utilPath = path72.join(projectDir, utilDir);
73766
73830
  if (!fs49.existsSync(utilPath))
73767
73831
  continue;
73768
73832
  const files = walkFiles(utilPath, [".ts", ".tsx", ".js", ".jsx"], deadline);
73769
73833
  for (const file3 of files) {
73770
73834
  if (Date.now() > deadline)
73771
73835
  break;
73772
- if (targetFile && path68.resolve(file3) === path68.resolve(targetFile))
73836
+ if (targetFile && path72.resolve(file3) === path72.resolve(targetFile))
73773
73837
  continue;
73774
73838
  try {
73775
73839
  const text = fs49.readFileSync(file3, "utf-8");
@@ -73907,14 +73971,14 @@ function createSteeringConsumedHook(directory) {
73907
73971
  // src/hooks/trajectory-logger.ts
73908
73972
  init_manager2();
73909
73973
  import * as fs52 from "node:fs/promises";
73910
- import * as path70 from "node:path";
73974
+ import * as path74 from "node:path";
73911
73975
 
73912
73976
  // src/prm/trajectory-store.ts
73913
73977
  init_utils2();
73914
73978
  import * as fs51 from "node:fs/promises";
73915
- import * as path69 from "node:path";
73979
+ import * as path73 from "node:path";
73916
73980
  function getTrajectoryPath(sessionId, directory) {
73917
- const relativePath = path69.join("trajectories", `${sessionId}.jsonl`);
73981
+ const relativePath = path73.join("trajectories", `${sessionId}.jsonl`);
73918
73982
  return validateSwarmPath(directory, relativePath);
73919
73983
  }
73920
73984
  var _inMemoryTrajectoryCache = new Map;
@@ -73933,7 +73997,7 @@ async function appendTrajectoryEntry(sessionId, entry, directory, maxLines = 100
73933
73997
  _inMemoryTrajectoryCache.set(sessionId, cached3);
73934
73998
  }
73935
73999
  const trajectoryPath = getTrajectoryPath(sessionId, directory);
73936
- await fs51.mkdir(path69.dirname(trajectoryPath), { recursive: true });
74000
+ await fs51.mkdir(path73.dirname(trajectoryPath), { recursive: true });
73937
74001
  const line = `${JSON.stringify(entry)}
73938
74002
  `;
73939
74003
  await fs51.appendFile(trajectoryPath, line, "utf-8");
@@ -73972,10 +74036,10 @@ async function cleanupOldTrajectoryFiles(directory, maxAgeDays = 7) {
73972
74036
  for (const entry of entries) {
73973
74037
  if (!entry.isFile())
73974
74038
  continue;
73975
- const filePath = path69.join(dirPath, entry.name);
74039
+ const filePath = path73.join(dirPath, entry.name);
73976
74040
  try {
73977
- const stat6 = await fs51.stat(filePath);
73978
- if (now - stat6.mtimeMs > cutoffMs) {
74041
+ const stat7 = await fs51.stat(filePath);
74042
+ if (now - stat7.mtimeMs > cutoffMs) {
73979
74043
  await fs51.unlink(filePath);
73980
74044
  }
73981
74045
  } catch {}
@@ -74164,10 +74228,10 @@ function createTrajectoryLoggerHook(config3, _directory) {
74164
74228
  elapsed_ms
74165
74229
  };
74166
74230
  const sanitized = sanitizeTaskId2(taskId);
74167
- const relativePath = path70.join("evidence", sanitized, "trajectory.jsonl");
74231
+ const relativePath = path74.join("evidence", sanitized, "trajectory.jsonl");
74168
74232
  const trajectoryPath = validateSwarmPath(_directory, relativePath);
74169
74233
  try {
74170
- await fs52.mkdir(path70.dirname(trajectoryPath), { recursive: true });
74234
+ await fs52.mkdir(path74.dirname(trajectoryPath), { recursive: true });
74171
74235
  const line = `${JSON.stringify(entry)}
74172
74236
  `;
74173
74237
  await fs52.appendFile(trajectoryPath, line, "utf-8");
@@ -74718,16 +74782,16 @@ init_telemetry();
74718
74782
 
74719
74783
  // src/prm/replay.ts
74720
74784
  import { promises as fs53 } from "node:fs";
74721
- import path71 from "node:path";
74785
+ import path75 from "node:path";
74722
74786
  function isPathSafe2(targetPath, basePath) {
74723
- const resolvedTarget = path71.resolve(targetPath);
74724
- const resolvedBase = path71.resolve(basePath);
74725
- const rel = path71.relative(resolvedBase, resolvedTarget);
74726
- return !rel.startsWith("..") && !path71.isAbsolute(rel);
74787
+ const resolvedTarget = path75.resolve(targetPath);
74788
+ const resolvedBase = path75.resolve(basePath);
74789
+ const rel = path75.relative(resolvedBase, resolvedTarget);
74790
+ return !rel.startsWith("..") && !path75.isAbsolute(rel);
74727
74791
  }
74728
74792
  function isWithinReplaysDir(targetPath) {
74729
- const resolved = path71.resolve(targetPath);
74730
- const parts2 = resolved.split(path71.sep);
74793
+ const resolved = path75.resolve(targetPath);
74794
+ const parts2 = resolved.split(path75.sep);
74731
74795
  for (let i2 = 0;i2 < parts2.length - 1; i2++) {
74732
74796
  if (parts2[i2] === ".swarm" && parts2[i2 + 1] === "replays") {
74733
74797
  return true;
@@ -74740,10 +74804,10 @@ function sanitizeFilename(input) {
74740
74804
  }
74741
74805
  async function startReplayRecording(sessionID, directory) {
74742
74806
  try {
74743
- const replayDir = path71.join(directory, ".swarm", "replays");
74807
+ const replayDir = path75.join(directory, ".swarm", "replays");
74744
74808
  const safeSessionID = sanitizeFilename(sessionID);
74745
74809
  const filename = `${safeSessionID}-${Date.now()}.jsonl`;
74746
- const filepath = path71.join(replayDir, filename);
74810
+ const filepath = path75.join(replayDir, filename);
74747
74811
  if (!isPathSafe2(filepath, replayDir)) {
74748
74812
  console.warn(`[replay] Invalid path detected - path traversal attempt blocked for session ${sessionID}`);
74749
74813
  return null;
@@ -75117,7 +75181,7 @@ init_telemetry();
75117
75181
  init_dist();
75118
75182
  init_create_tool();
75119
75183
  import * as fs54 from "node:fs";
75120
- import * as path72 from "node:path";
75184
+ import * as path76 from "node:path";
75121
75185
  init_path_security();
75122
75186
  var WINDOWS_RESERVED_NAMES2 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
75123
75187
  function containsWindowsAttacks2(str) {
@@ -75134,14 +75198,14 @@ function containsWindowsAttacks2(str) {
75134
75198
  }
75135
75199
  function isPathInWorkspace2(filePath, workspace) {
75136
75200
  try {
75137
- const resolvedPath = path72.resolve(workspace, filePath);
75201
+ const resolvedPath = path76.resolve(workspace, filePath);
75138
75202
  if (!fs54.existsSync(resolvedPath)) {
75139
75203
  return true;
75140
75204
  }
75141
75205
  const realWorkspace = fs54.realpathSync(workspace);
75142
75206
  const realResolvedPath = fs54.realpathSync(resolvedPath);
75143
- const relativePath = path72.relative(realWorkspace, realResolvedPath);
75144
- if (relativePath.startsWith("..") || path72.isAbsolute(relativePath)) {
75207
+ const relativePath = path76.relative(realWorkspace, realResolvedPath);
75208
+ if (relativePath.startsWith("..") || path76.isAbsolute(relativePath)) {
75145
75209
  return false;
75146
75210
  }
75147
75211
  return true;
@@ -75150,7 +75214,7 @@ function isPathInWorkspace2(filePath, workspace) {
75150
75214
  }
75151
75215
  }
75152
75216
  function processFile2(file3, cwd, exportedOnly) {
75153
- const ext = path72.extname(file3);
75217
+ const ext = path76.extname(file3);
75154
75218
  if (containsControlChars(file3)) {
75155
75219
  return {
75156
75220
  file: file3,
@@ -75183,7 +75247,7 @@ function processFile2(file3, cwd, exportedOnly) {
75183
75247
  errorType: "path-outside-workspace"
75184
75248
  };
75185
75249
  }
75186
- const fullPath = path72.join(cwd, file3);
75250
+ const fullPath = path76.join(cwd, file3);
75187
75251
  if (!fs54.existsSync(fullPath)) {
75188
75252
  return {
75189
75253
  file: file3,
@@ -75475,15 +75539,15 @@ init_task_id();
75475
75539
  init_create_tool();
75476
75540
  init_resolve_working_directory();
75477
75541
  import * as fs55 from "node:fs";
75478
- import * as path73 from "node:path";
75542
+ import * as path77 from "node:path";
75479
75543
  var EVIDENCE_DIR = ".swarm/evidence";
75480
75544
  function isValidTaskId3(taskId) {
75481
75545
  return isStrictTaskId(taskId);
75482
75546
  }
75483
75547
  function isPathWithinSwarm(filePath, workspaceRoot) {
75484
- const normalizedWorkspace = path73.resolve(workspaceRoot);
75485
- const swarmPath = path73.join(normalizedWorkspace, ".swarm", "evidence");
75486
- const normalizedPath = path73.resolve(filePath);
75548
+ const normalizedWorkspace = path77.resolve(workspaceRoot);
75549
+ const swarmPath = path77.join(normalizedWorkspace, ".swarm", "evidence");
75550
+ const normalizedPath = path77.resolve(filePath);
75487
75551
  return normalizedPath.startsWith(swarmPath);
75488
75552
  }
75489
75553
  function readEvidenceFile(evidencePath) {
@@ -75564,7 +75628,7 @@ var check_gate_status = createSwarmTool({
75564
75628
  };
75565
75629
  return JSON.stringify(errorResult, null, 2);
75566
75630
  }
75567
- const evidencePath = path73.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
75631
+ const evidencePath = path77.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
75568
75632
  if (!isPathWithinSwarm(evidencePath, directory)) {
75569
75633
  const errorResult = {
75570
75634
  taskId: taskIdInput,
@@ -75661,7 +75725,7 @@ init_state();
75661
75725
  init_create_tool();
75662
75726
  init_resolve_working_directory();
75663
75727
  import * as fs56 from "node:fs";
75664
- import * as path74 from "node:path";
75728
+ import * as path78 from "node:path";
75665
75729
  function extractMatches(regex, text) {
75666
75730
  return Array.from(text.matchAll(regex));
75667
75731
  }
@@ -75813,10 +75877,10 @@ async function executeCompletionVerify(args2, directory) {
75813
75877
  let hasFileReadFailure = false;
75814
75878
  for (const filePath of fileTargets) {
75815
75879
  const normalizedPath = filePath.replace(/\\/g, "/");
75816
- const resolvedPath = path74.resolve(directory, normalizedPath);
75817
- const projectRoot = path74.resolve(directory);
75818
- const relative16 = path74.relative(projectRoot, resolvedPath);
75819
- const withinProject = relative16 === "" || !relative16.startsWith("..") && !path74.isAbsolute(relative16);
75880
+ const resolvedPath = path78.resolve(directory, normalizedPath);
75881
+ const projectRoot = path78.resolve(directory);
75882
+ const relative16 = path78.relative(projectRoot, resolvedPath);
75883
+ const withinProject = relative16 === "" || !relative16.startsWith("..") && !path78.isAbsolute(relative16);
75820
75884
  if (!withinProject) {
75821
75885
  blockedTasks.push({
75822
75886
  task_id: task.id,
@@ -75871,8 +75935,8 @@ async function executeCompletionVerify(args2, directory) {
75871
75935
  blockedTasks
75872
75936
  };
75873
75937
  try {
75874
- const evidenceDir = path74.join(directory, ".swarm", "evidence", `${phase}`);
75875
- const evidencePath = path74.join(evidenceDir, "completion-verify.json");
75938
+ const evidenceDir = path78.join(directory, ".swarm", "evidence", `${phase}`);
75939
+ const evidencePath = path78.join(evidenceDir, "completion-verify.json");
75876
75940
  fs56.mkdirSync(evidenceDir, { recursive: true });
75877
75941
  const evidenceBundle = {
75878
75942
  schema_version: "1.0.0",
@@ -75949,11 +76013,11 @@ var completion_verify = createSwarmTool({
75949
76013
  // src/tools/complexity-hotspots.ts
75950
76014
  init_zod();
75951
76015
  import * as fs58 from "node:fs";
75952
- import * as path76 from "node:path";
76016
+ import * as path80 from "node:path";
75953
76017
 
75954
76018
  // src/quality/metrics.ts
75955
76019
  import * as fs57 from "node:fs";
75956
- import * as path75 from "node:path";
76020
+ import * as path79 from "node:path";
75957
76021
  var MAX_FILE_SIZE_BYTES4 = 256 * 1024;
75958
76022
  var MIN_DUPLICATION_LINES = 10;
75959
76023
  function estimateCyclomaticComplexity(content) {
@@ -75991,8 +76055,8 @@ function estimateCyclomaticComplexity(content) {
75991
76055
  }
75992
76056
  function getComplexityForFile(filePath) {
75993
76057
  try {
75994
- const stat6 = fs57.statSync(filePath);
75995
- if (stat6.size > MAX_FILE_SIZE_BYTES4) {
76058
+ const stat7 = fs57.statSync(filePath);
76059
+ if (stat7.size > MAX_FILE_SIZE_BYTES4) {
75996
76060
  return null;
75997
76061
  }
75998
76062
  const content = fs57.readFileSync(filePath, "utf-8");
@@ -76005,7 +76069,7 @@ async function computeComplexityDelta(files, workingDir) {
76005
76069
  let totalComplexity = 0;
76006
76070
  const analyzedFiles = [];
76007
76071
  for (const file3 of files) {
76008
- const fullPath = path75.isAbsolute(file3) ? file3 : path75.join(workingDir, file3);
76072
+ const fullPath = path79.isAbsolute(file3) ? file3 : path79.join(workingDir, file3);
76009
76073
  if (!fs57.existsSync(fullPath)) {
76010
76074
  continue;
76011
76075
  }
@@ -76128,7 +76192,7 @@ function countGoExports(content) {
76128
76192
  function getExportCountForFile(filePath) {
76129
76193
  try {
76130
76194
  const content = fs57.readFileSync(filePath, "utf-8");
76131
- const ext = path75.extname(filePath).toLowerCase();
76195
+ const ext = path79.extname(filePath).toLowerCase();
76132
76196
  switch (ext) {
76133
76197
  case ".ts":
76134
76198
  case ".tsx":
@@ -76154,7 +76218,7 @@ async function computePublicApiDelta(files, workingDir) {
76154
76218
  let totalExports = 0;
76155
76219
  const analyzedFiles = [];
76156
76220
  for (const file3 of files) {
76157
- const fullPath = path75.isAbsolute(file3) ? file3 : path75.join(workingDir, file3);
76221
+ const fullPath = path79.isAbsolute(file3) ? file3 : path79.join(workingDir, file3);
76158
76222
  if (!fs57.existsSync(fullPath)) {
76159
76223
  continue;
76160
76224
  }
@@ -76188,13 +76252,13 @@ async function computeDuplicationRatio(files, workingDir) {
76188
76252
  let duplicateLines = 0;
76189
76253
  const analyzedFiles = [];
76190
76254
  for (const file3 of files) {
76191
- const fullPath = path75.isAbsolute(file3) ? file3 : path75.join(workingDir, file3);
76255
+ const fullPath = path79.isAbsolute(file3) ? file3 : path79.join(workingDir, file3);
76192
76256
  if (!fs57.existsSync(fullPath)) {
76193
76257
  continue;
76194
76258
  }
76195
76259
  try {
76196
- const stat6 = fs57.statSync(fullPath);
76197
- if (stat6.size > MAX_FILE_SIZE_BYTES4) {
76260
+ const stat7 = fs57.statSync(fullPath);
76261
+ if (stat7.size > MAX_FILE_SIZE_BYTES4) {
76198
76262
  continue;
76199
76263
  }
76200
76264
  const content = fs57.readFileSync(fullPath, "utf-8");
@@ -76221,8 +76285,8 @@ function countCodeLines(content) {
76221
76285
  return lines.length;
76222
76286
  }
76223
76287
  function isTestFile(filePath) {
76224
- const basename11 = path75.basename(filePath);
76225
- const _ext = path75.extname(filePath).toLowerCase();
76288
+ const basename11 = path79.basename(filePath);
76289
+ const _ext = path79.extname(filePath).toLowerCase();
76226
76290
  const testPatterns = [
76227
76291
  ".test.",
76228
76292
  ".spec.",
@@ -76303,8 +76367,8 @@ function matchGlobSegment(globSegments, pathSegments) {
76303
76367
  }
76304
76368
  return gIndex === globSegments.length && pIndex === pathSegments.length;
76305
76369
  }
76306
- function matchesGlobSegment(path76, glob) {
76307
- const normalizedPath = path76.replace(/\\/g, "/");
76370
+ function matchesGlobSegment(path80, glob) {
76371
+ const normalizedPath = path80.replace(/\\/g, "/");
76308
76372
  const normalizedGlob = glob.replace(/\\/g, "/");
76309
76373
  if (normalizedPath.includes("//")) {
76310
76374
  return false;
@@ -76335,8 +76399,8 @@ function simpleGlobToRegex2(glob) {
76335
76399
  function hasGlobstar(glob) {
76336
76400
  return glob.includes("**");
76337
76401
  }
76338
- function globMatches(path76, glob) {
76339
- const normalizedPath = path76.replace(/\\/g, "/");
76402
+ function globMatches(path80, glob) {
76403
+ const normalizedPath = path80.replace(/\\/g, "/");
76340
76404
  if (!glob || glob === "") {
76341
76405
  if (normalizedPath.includes("//")) {
76342
76406
  return false;
@@ -76372,7 +76436,7 @@ function shouldExcludeFile(filePath, excludeGlobs) {
76372
76436
  async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
76373
76437
  let testLines = 0;
76374
76438
  let codeLines = 0;
76375
- const srcDir = path75.join(workingDir, "src");
76439
+ const srcDir = path79.join(workingDir, "src");
76376
76440
  if (fs57.existsSync(srcDir)) {
76377
76441
  await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
76378
76442
  codeLines += lines;
@@ -76380,14 +76444,14 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
76380
76444
  }
76381
76445
  const possibleSrcDirs = ["lib", "app", "source", "core"];
76382
76446
  for (const dir of possibleSrcDirs) {
76383
- const dirPath = path75.join(workingDir, dir);
76447
+ const dirPath = path79.join(workingDir, dir);
76384
76448
  if (fs57.existsSync(dirPath)) {
76385
76449
  await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
76386
76450
  codeLines += lines;
76387
76451
  });
76388
76452
  }
76389
76453
  }
76390
- const testsDir = path75.join(workingDir, "tests");
76454
+ const testsDir = path79.join(workingDir, "tests");
76391
76455
  if (fs57.existsSync(testsDir)) {
76392
76456
  await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
76393
76457
  testLines += lines;
@@ -76395,7 +76459,7 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
76395
76459
  }
76396
76460
  const possibleTestDirs = ["test", "__tests__", "specs"];
76397
76461
  for (const dir of possibleTestDirs) {
76398
- const dirPath = path75.join(workingDir, dir);
76462
+ const dirPath = path79.join(workingDir, dir);
76399
76463
  if (fs57.existsSync(dirPath) && dirPath !== testsDir) {
76400
76464
  await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
76401
76465
  testLines += lines;
@@ -76410,7 +76474,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
76410
76474
  try {
76411
76475
  const entries = fs57.readdirSync(dirPath, { withFileTypes: true });
76412
76476
  for (const entry of entries) {
76413
- const fullPath = path75.join(dirPath, entry.name);
76477
+ const fullPath = path79.join(dirPath, entry.name);
76414
76478
  if (entry.isDirectory()) {
76415
76479
  if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
76416
76480
  continue;
@@ -76418,7 +76482,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
76418
76482
  await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
76419
76483
  } else if (entry.isFile()) {
76420
76484
  const relativePath = fullPath.replace(`${dirPath}/`, "");
76421
- const ext = path75.extname(entry.name).toLowerCase();
76485
+ const ext = path79.extname(entry.name).toLowerCase();
76422
76486
  const validExts = [
76423
76487
  ".ts",
76424
76488
  ".tsx",
@@ -76654,8 +76718,8 @@ async function getGitChurn(days, directory) {
76654
76718
  }
76655
76719
  function getComplexityForFile2(filePath) {
76656
76720
  try {
76657
- const stat6 = fs58.statSync(filePath);
76658
- if (stat6.size > MAX_FILE_SIZE_BYTES5) {
76721
+ const stat7 = fs58.statSync(filePath);
76722
+ if (stat7.size > MAX_FILE_SIZE_BYTES5) {
76659
76723
  return null;
76660
76724
  }
76661
76725
  const content = fs58.readFileSync(filePath, "utf-8");
@@ -76669,7 +76733,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
76669
76733
  const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
76670
76734
  const filteredChurn = new Map;
76671
76735
  for (const [file3, count] of churnMap) {
76672
- const ext = path76.extname(file3).toLowerCase();
76736
+ const ext = path80.extname(file3).toLowerCase();
76673
76737
  if (extSet.has(ext)) {
76674
76738
  filteredChurn.set(file3, count);
76675
76739
  }
@@ -76680,7 +76744,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
76680
76744
  for (const [file3, churnCount] of filteredChurn) {
76681
76745
  let fullPath = file3;
76682
76746
  if (!fs58.existsSync(fullPath)) {
76683
- fullPath = path76.join(cwd, file3);
76747
+ fullPath = path80.join(cwd, file3);
76684
76748
  }
76685
76749
  const complexity = getComplexityForFile2(fullPath);
76686
76750
  if (complexity !== null) {
@@ -76849,7 +76913,7 @@ ${body2}`);
76849
76913
  // src/council/council-evidence-writer.ts
76850
76914
  import {
76851
76915
  appendFileSync as appendFileSync6,
76852
- existsSync as existsSync38,
76916
+ existsSync as existsSync40,
76853
76917
  mkdirSync as mkdirSync19,
76854
76918
  readFileSync as readFileSync36,
76855
76919
  writeFileSync as writeFileSync12
@@ -76892,7 +76956,7 @@ function writeCouncilEvidence(workingDir, synthesis) {
76892
76956
  mkdirSync19(dir, { recursive: true });
76893
76957
  const filePath = join69(dir, `${synthesis.taskId}.json`);
76894
76958
  const existingRoot = Object.create(null);
76895
- if (existsSync38(filePath)) {
76959
+ if (existsSync40(filePath)) {
76896
76960
  try {
76897
76961
  const parsed = JSON.parse(readFileSync36(filePath, "utf-8"));
76898
76962
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
@@ -76941,7 +77005,7 @@ function writeCouncilEvidence(workingDir, synthesis) {
76941
77005
 
76942
77006
  // src/council/council-service.ts
76943
77007
  import fs59 from "node:fs";
76944
- import path77 from "node:path";
77008
+ import path81 from "node:path";
76945
77009
 
76946
77010
  // src/council/types.ts
76947
77011
  var COUNCIL_DEFAULTS = {
@@ -77101,9 +77165,9 @@ function synthesizePhaseCouncilAdvisory(phaseNumber, phaseSummary, verdicts, rou
77101
77165
  const unifiedFeedbackMd = buildPhaseCouncilFeedback(phaseNumber, phaseSummary, overallVerdict, rejectingMembers, requiredFixes, advisoryFindings, unresolvedConflicts, roundNumber, cfg.maxRounds);
77102
77166
  const evidencePath = `.swarm/evidence/${phaseNumber}/phase-council.json`;
77103
77167
  const baseDir = workingDir ?? process.cwd();
77104
- const evidenceDir = path77.join(baseDir, ".swarm", "evidence", String(phaseNumber));
77168
+ const evidenceDir = path81.join(baseDir, ".swarm", "evidence", String(phaseNumber));
77105
77169
  fs59.mkdirSync(evidenceDir, { recursive: true });
77106
- const evidenceFile = path77.join(evidenceDir, "phase-council.json");
77170
+ const evidenceFile = path81.join(evidenceDir, "phase-council.json");
77107
77171
  const evidenceBundle = {
77108
77172
  entries: [
77109
77173
  {
@@ -77206,7 +77270,7 @@ function buildPhaseCouncilFeedback(phaseNumber, phaseSummary, verdict, vetoedBy,
77206
77270
  }
77207
77271
 
77208
77272
  // src/council/criteria-store.ts
77209
- import { existsSync as existsSync39, mkdirSync as mkdirSync20, readFileSync as readFileSync37, writeFileSync as writeFileSync13 } from "node:fs";
77273
+ import { existsSync as existsSync41, mkdirSync as mkdirSync20, readFileSync as readFileSync37, writeFileSync as writeFileSync13 } from "node:fs";
77210
77274
  import { join as join70 } from "node:path";
77211
77275
  var COUNCIL_DIR = ".swarm/council";
77212
77276
  function writeCriteria(workingDir, taskId, criteria) {
@@ -77221,7 +77285,7 @@ function writeCriteria(workingDir, taskId, criteria) {
77221
77285
  }
77222
77286
  function readCriteria(workingDir, taskId) {
77223
77287
  const filePath = join70(workingDir, COUNCIL_DIR, `${safeId(taskId)}.json`);
77224
- if (!existsSync39(filePath))
77288
+ if (!existsSync41(filePath))
77225
77289
  return null;
77226
77290
  try {
77227
77291
  const parsed = JSON.parse(readFileSync37(filePath, "utf-8"));
@@ -77373,7 +77437,7 @@ var submit_council_verdicts = createSwarmTool({
77373
77437
  init_zod();
77374
77438
  init_loader();
77375
77439
  import * as fs60 from "node:fs";
77376
- import * as path78 from "node:path";
77440
+ import * as path82 from "node:path";
77377
77441
 
77378
77442
  // src/council/general-council-advisory.ts
77379
77443
  var ADVISORY_HEADER = "[general_council] (advisory; not blocking)";
@@ -77801,10 +77865,10 @@ var convene_general_council = createSwarmTool({
77801
77865
  const round1 = input.round1Responses;
77802
77866
  const round2 = input.round2Responses ?? [];
77803
77867
  const result = synthesizeGeneralCouncil(input.question, input.mode, round1, round2);
77804
- const evidenceDir = path78.join(workingDir, ".swarm", "council", "general");
77868
+ const evidenceDir = path82.join(workingDir, ".swarm", "council", "general");
77805
77869
  const safeTimestamp = result.timestamp.replace(/[:.]/g, "-");
77806
77870
  const evidenceFile = `${safeTimestamp}-${input.mode}.json`;
77807
- const evidencePath = path78.join(evidenceDir, evidenceFile);
77871
+ const evidencePath = path82.join(evidenceDir, evidenceFile);
77808
77872
  try {
77809
77873
  await fs60.promises.mkdir(evidenceDir, { recursive: true });
77810
77874
  await fs60.promises.writeFile(evidencePath, JSON.stringify(result, null, 2));
@@ -78039,7 +78103,7 @@ init_state();
78039
78103
  init_task_id();
78040
78104
  init_create_tool();
78041
78105
  import * as fs61 from "node:fs";
78042
- import * as path79 from "node:path";
78106
+ import * as path83 from "node:path";
78043
78107
  function validateTaskIdFormat2(taskId) {
78044
78108
  return validateTaskIdFormat(taskId);
78045
78109
  }
@@ -78113,8 +78177,8 @@ async function executeDeclareScope(args2, fallbackDir) {
78113
78177
  };
78114
78178
  }
78115
78179
  }
78116
- normalizedDir = path79.normalize(args2.working_directory);
78117
- const pathParts = normalizedDir.split(path79.sep);
78180
+ normalizedDir = path83.normalize(args2.working_directory);
78181
+ const pathParts = normalizedDir.split(path83.sep);
78118
78182
  if (pathParts.includes("..")) {
78119
78183
  return {
78120
78184
  success: false,
@@ -78124,10 +78188,10 @@ async function executeDeclareScope(args2, fallbackDir) {
78124
78188
  ]
78125
78189
  };
78126
78190
  }
78127
- const resolvedDir = path79.resolve(normalizedDir);
78191
+ const resolvedDir = path83.resolve(normalizedDir);
78128
78192
  try {
78129
78193
  const realPath = fs61.realpathSync(resolvedDir);
78130
- const planPath2 = path79.join(realPath, ".swarm", "plan.json");
78194
+ const planPath2 = path83.join(realPath, ".swarm", "plan.json");
78131
78195
  if (!fs61.existsSync(planPath2)) {
78132
78196
  return {
78133
78197
  success: false,
@@ -78151,7 +78215,7 @@ async function executeDeclareScope(args2, fallbackDir) {
78151
78215
  console.warn("[declare-scope] fallbackDir is undefined, falling back to process.cwd()");
78152
78216
  }
78153
78217
  const directory = normalizedDir || fallbackDir;
78154
- const planPath = path79.resolve(directory, ".swarm", "plan.json");
78218
+ const planPath = path83.resolve(directory, ".swarm", "plan.json");
78155
78219
  if (!fs61.existsSync(planPath)) {
78156
78220
  return {
78157
78221
  success: false,
@@ -78191,8 +78255,8 @@ async function executeDeclareScope(args2, fallbackDir) {
78191
78255
  const normalizeErrors = [];
78192
78256
  const dir = normalizedDir || fallbackDir || process.cwd();
78193
78257
  const mergedFiles = rawMergedFiles.map((file3) => {
78194
- if (path79.isAbsolute(file3)) {
78195
- const relativePath = path79.relative(dir, file3).replace(/\\/g, "/");
78258
+ if (path83.isAbsolute(file3)) {
78259
+ const relativePath = path83.relative(dir, file3).replace(/\\/g, "/");
78196
78260
  if (relativePath.startsWith("..")) {
78197
78261
  normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
78198
78262
  return file3;
@@ -78253,7 +78317,7 @@ var declare_scope = createSwarmTool({
78253
78317
  init_zod();
78254
78318
  import * as child_process7 from "node:child_process";
78255
78319
  import * as fs62 from "node:fs";
78256
- import * as path80 from "node:path";
78320
+ import * as path84 from "node:path";
78257
78321
  init_create_tool();
78258
78322
  var MAX_DIFF_LINES = 500;
78259
78323
  var DIFF_TIMEOUT_MS = 30000;
@@ -78282,20 +78346,20 @@ function validateBase(base) {
78282
78346
  function validatePaths(paths) {
78283
78347
  if (!paths)
78284
78348
  return null;
78285
- for (const path81 of paths) {
78286
- if (!path81 || path81.length === 0) {
78349
+ for (const path85 of paths) {
78350
+ if (!path85 || path85.length === 0) {
78287
78351
  return "empty path not allowed";
78288
78352
  }
78289
- if (path81.length > MAX_PATH_LENGTH) {
78353
+ if (path85.length > MAX_PATH_LENGTH) {
78290
78354
  return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
78291
78355
  }
78292
- if (SHELL_METACHARACTERS2.test(path81)) {
78356
+ if (SHELL_METACHARACTERS2.test(path85)) {
78293
78357
  return "path contains shell metacharacters";
78294
78358
  }
78295
- if (path81.startsWith("-")) {
78359
+ if (path85.startsWith("-")) {
78296
78360
  return 'path cannot start with "-" (option-like arguments not allowed)';
78297
78361
  }
78298
- if (CONTROL_CHAR_PATTERN2.test(path81)) {
78362
+ if (CONTROL_CHAR_PATTERN2.test(path85)) {
78299
78363
  return "path contains control characters";
78300
78364
  }
78301
78365
  }
@@ -78401,8 +78465,8 @@ var diff = createSwarmTool({
78401
78465
  if (parts2.length >= 3) {
78402
78466
  const additions = parseInt(parts2[0], 10) || 0;
78403
78467
  const deletions = parseInt(parts2[1], 10) || 0;
78404
- const path81 = parts2[2];
78405
- files.push({ path: path81, additions, deletions });
78468
+ const path85 = parts2[2];
78469
+ files.push({ path: path85, additions, deletions });
78406
78470
  }
78407
78471
  }
78408
78472
  const contractChanges = [];
@@ -78442,7 +78506,7 @@ var diff = createSwarmTool({
78442
78506
  } else if (base === "unstaged") {
78443
78507
  const oldRef = `:${file3.path}`;
78444
78508
  oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
78445
- newContent = fs62.readFileSync(path80.join(directory, file3.path), "utf-8");
78509
+ newContent = fs62.readFileSync(path84.join(directory, file3.path), "utf-8");
78446
78510
  } else {
78447
78511
  const oldRef = `${base}:${file3.path}`;
78448
78512
  oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
@@ -78517,7 +78581,7 @@ var diff = createSwarmTool({
78517
78581
  init_zod();
78518
78582
  import * as child_process8 from "node:child_process";
78519
78583
  import * as fs63 from "node:fs";
78520
- import * as path81 from "node:path";
78584
+ import * as path85 from "node:path";
78521
78585
  init_create_tool();
78522
78586
  var diff_summary = createSwarmTool({
78523
78587
  description: "Generate a filtered semantic diff summary from AST analysis. Returns SemanticDiffSummary with optional filtering by classification or riskLevel.",
@@ -78565,7 +78629,7 @@ var diff_summary = createSwarmTool({
78565
78629
  }
78566
78630
  try {
78567
78631
  let oldContent;
78568
- const newContent = fs63.readFileSync(path81.join(workingDir, filePath), "utf-8");
78632
+ const newContent = fs63.readFileSync(path85.join(workingDir, filePath), "utf-8");
78569
78633
  if (fileExistsInHead) {
78570
78634
  oldContent = child_process8.execFileSync("git", ["show", `HEAD:${filePath}`], {
78571
78635
  encoding: "utf-8",
@@ -78794,7 +78858,7 @@ init_zod();
78794
78858
  init_create_tool();
78795
78859
  init_path_security();
78796
78860
  import * as fs64 from "node:fs";
78797
- import * as path82 from "node:path";
78861
+ import * as path86 from "node:path";
78798
78862
  var MAX_FILE_SIZE_BYTES6 = 1024 * 1024;
78799
78863
  var MAX_EVIDENCE_FILES = 1000;
78800
78864
  var EVIDENCE_DIR3 = ".swarm/evidence";
@@ -78821,9 +78885,9 @@ function validateRequiredTypes(input) {
78821
78885
  return null;
78822
78886
  }
78823
78887
  function isPathWithinSwarm2(filePath, cwd) {
78824
- const normalizedCwd = path82.resolve(cwd);
78825
- const swarmPath = path82.join(normalizedCwd, ".swarm");
78826
- const normalizedPath = path82.resolve(filePath);
78888
+ const normalizedCwd = path86.resolve(cwd);
78889
+ const swarmPath = path86.join(normalizedCwd, ".swarm");
78890
+ const normalizedPath = path86.resolve(filePath);
78827
78891
  return normalizedPath.startsWith(swarmPath);
78828
78892
  }
78829
78893
  function parseCompletedTasks(planContent) {
@@ -78853,15 +78917,15 @@ function readEvidenceFiles(evidenceDir, _cwd) {
78853
78917
  if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
78854
78918
  continue;
78855
78919
  }
78856
- const filePath = path82.join(evidenceDir, filename);
78920
+ const filePath = path86.join(evidenceDir, filename);
78857
78921
  try {
78858
- const resolvedPath = path82.resolve(filePath);
78859
- const evidenceDirResolved = path82.resolve(evidenceDir);
78922
+ const resolvedPath = path86.resolve(filePath);
78923
+ const evidenceDirResolved = path86.resolve(evidenceDir);
78860
78924
  if (!resolvedPath.startsWith(evidenceDirResolved)) {
78861
78925
  continue;
78862
78926
  }
78863
- const stat6 = fs64.lstatSync(filePath);
78864
- if (!stat6.isFile()) {
78927
+ const stat7 = fs64.lstatSync(filePath);
78928
+ if (!stat7.isFile()) {
78865
78929
  continue;
78866
78930
  }
78867
78931
  } catch {
@@ -78974,7 +79038,7 @@ var evidence_check = createSwarmTool({
78974
79038
  return JSON.stringify(errorResult, null, 2);
78975
79039
  }
78976
79040
  const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
78977
- const planPath = path82.join(cwd, PLAN_FILE);
79041
+ const planPath = path86.join(cwd, PLAN_FILE);
78978
79042
  if (!isPathWithinSwarm2(planPath, cwd)) {
78979
79043
  const errorResult = {
78980
79044
  error: "plan file path validation failed",
@@ -79006,7 +79070,7 @@ var evidence_check = createSwarmTool({
79006
79070
  };
79007
79071
  return JSON.stringify(result2, null, 2);
79008
79072
  }
79009
- const evidenceDir = path82.join(cwd, EVIDENCE_DIR3);
79073
+ const evidenceDir = path86.join(cwd, EVIDENCE_DIR3);
79010
79074
  const evidence = readEvidenceFiles(evidenceDir, cwd);
79011
79075
  const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
79012
79076
  const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
@@ -79024,7 +79088,7 @@ var evidence_check = createSwarmTool({
79024
79088
  init_zod();
79025
79089
  init_create_tool();
79026
79090
  import * as fs65 from "node:fs";
79027
- import * as path83 from "node:path";
79091
+ import * as path87 from "node:path";
79028
79092
  var EXT_MAP = {
79029
79093
  python: ".py",
79030
79094
  py: ".py",
@@ -79105,12 +79169,12 @@ var extract_code_blocks = createSwarmTool({
79105
79169
  if (prefix) {
79106
79170
  filename = `${prefix}_${filename}`;
79107
79171
  }
79108
- let filepath = path83.join(targetDir, filename);
79109
- const base = path83.basename(filepath, path83.extname(filepath));
79110
- const ext = path83.extname(filepath);
79172
+ let filepath = path87.join(targetDir, filename);
79173
+ const base = path87.basename(filepath, path87.extname(filepath));
79174
+ const ext = path87.extname(filepath);
79111
79175
  let counter = 1;
79112
79176
  while (fs65.existsSync(filepath)) {
79113
- filepath = path83.join(targetDir, `${base}_${counter}${ext}`);
79177
+ filepath = path87.join(targetDir, `${base}_${counter}${ext}`);
79114
79178
  counter++;
79115
79179
  }
79116
79180
  try {
@@ -79286,7 +79350,7 @@ init_create_tool();
79286
79350
  var GITINGEST_TIMEOUT_MS = 1e4;
79287
79351
  var GITINGEST_MAX_RESPONSE_BYTES = 5242880;
79288
79352
  var GITINGEST_MAX_RETRIES = 2;
79289
- var delay = (ms) => new Promise((resolve30) => setTimeout(resolve30, ms));
79353
+ var delay = (ms) => new Promise((resolve31) => setTimeout(resolve31, ms));
79290
79354
  async function fetchGitingest(args2) {
79291
79355
  for (let attempt = 0;attempt <= GITINGEST_MAX_RETRIES; attempt++) {
79292
79356
  try {
@@ -79374,7 +79438,7 @@ init_zod();
79374
79438
  init_create_tool();
79375
79439
  init_path_security();
79376
79440
  import * as fs66 from "node:fs";
79377
- import * as path84 from "node:path";
79441
+ import * as path88 from "node:path";
79378
79442
  var MAX_FILE_PATH_LENGTH2 = 500;
79379
79443
  var MAX_SYMBOL_LENGTH = 256;
79380
79444
  var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
@@ -79422,7 +79486,7 @@ function validateSymbolInput(symbol3) {
79422
79486
  return null;
79423
79487
  }
79424
79488
  function isBinaryFile2(filePath, buffer) {
79425
- const ext = path84.extname(filePath).toLowerCase();
79489
+ const ext = path88.extname(filePath).toLowerCase();
79426
79490
  if (ext === ".json" || ext === ".md" || ext === ".txt") {
79427
79491
  return false;
79428
79492
  }
@@ -79446,15 +79510,15 @@ function parseImports(content, targetFile, targetSymbol) {
79446
79510
  const imports = [];
79447
79511
  let _resolvedTarget;
79448
79512
  try {
79449
- _resolvedTarget = path84.resolve(targetFile);
79513
+ _resolvedTarget = path88.resolve(targetFile);
79450
79514
  } catch {
79451
79515
  _resolvedTarget = targetFile;
79452
79516
  }
79453
- const targetBasename = path84.basename(targetFile, path84.extname(targetFile));
79517
+ const targetBasename = path88.basename(targetFile, path88.extname(targetFile));
79454
79518
  const targetWithExt = targetFile;
79455
79519
  const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
79456
- const normalizedTargetWithExt = path84.normalize(targetWithExt).replace(/\\/g, "/");
79457
- const normalizedTargetWithoutExt = path84.normalize(targetWithoutExt).replace(/\\/g, "/");
79520
+ const normalizedTargetWithExt = path88.normalize(targetWithExt).replace(/\\/g, "/");
79521
+ const normalizedTargetWithoutExt = path88.normalize(targetWithoutExt).replace(/\\/g, "/");
79458
79522
  const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
79459
79523
  for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
79460
79524
  const modulePath = match[1] || match[2] || match[3];
@@ -79477,9 +79541,9 @@ function parseImports(content, targetFile, targetSymbol) {
79477
79541
  }
79478
79542
  const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
79479
79543
  let isMatch = false;
79480
- const _targetDir = path84.dirname(targetFile);
79481
- const targetExt = path84.extname(targetFile);
79482
- const targetBasenameNoExt = path84.basename(targetFile, targetExt);
79544
+ const _targetDir = path88.dirname(targetFile);
79545
+ const targetExt = path88.extname(targetFile);
79546
+ const targetBasenameNoExt = path88.basename(targetFile, targetExt);
79483
79547
  const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
79484
79548
  const moduleName = modulePath.split(/[/\\]/).pop() || "";
79485
79549
  const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
@@ -79547,13 +79611,13 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
79547
79611
  entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
79548
79612
  for (const entry of entries) {
79549
79613
  if (SKIP_DIRECTORIES4.has(entry)) {
79550
- stats.skippedDirs.push(path84.join(dir, entry));
79614
+ stats.skippedDirs.push(path88.join(dir, entry));
79551
79615
  continue;
79552
79616
  }
79553
- const fullPath = path84.join(dir, entry);
79554
- let stat6;
79617
+ const fullPath = path88.join(dir, entry);
79618
+ let stat7;
79555
79619
  try {
79556
- stat6 = fs66.statSync(fullPath);
79620
+ stat7 = fs66.statSync(fullPath);
79557
79621
  } catch (e) {
79558
79622
  stats.fileErrors.push({
79559
79623
  path: fullPath,
@@ -79561,10 +79625,10 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
79561
79625
  });
79562
79626
  continue;
79563
79627
  }
79564
- if (stat6.isDirectory()) {
79628
+ if (stat7.isDirectory()) {
79565
79629
  findSourceFiles2(fullPath, files, stats);
79566
- } else if (stat6.isFile()) {
79567
- const ext = path84.extname(fullPath).toLowerCase();
79630
+ } else if (stat7.isFile()) {
79631
+ const ext = path88.extname(fullPath).toLowerCase();
79568
79632
  if (SUPPORTED_EXTENSIONS3.includes(ext)) {
79569
79633
  files.push(fullPath);
79570
79634
  }
@@ -79621,7 +79685,7 @@ var imports = createSwarmTool({
79621
79685
  return JSON.stringify(errorResult, null, 2);
79622
79686
  }
79623
79687
  try {
79624
- const targetFile = path84.resolve(file3);
79688
+ const targetFile = path88.resolve(file3);
79625
79689
  if (!fs66.existsSync(targetFile)) {
79626
79690
  const errorResult = {
79627
79691
  error: `target file not found: ${file3}`,
@@ -79643,7 +79707,7 @@ var imports = createSwarmTool({
79643
79707
  };
79644
79708
  return JSON.stringify(errorResult, null, 2);
79645
79709
  }
79646
- const baseDir = path84.dirname(targetFile);
79710
+ const baseDir = path88.dirname(targetFile);
79647
79711
  const scanStats = {
79648
79712
  skippedDirs: [],
79649
79713
  skippedFiles: 0,
@@ -79658,8 +79722,8 @@ var imports = createSwarmTool({
79658
79722
  if (consumers.length >= MAX_CONSUMERS)
79659
79723
  break;
79660
79724
  try {
79661
- const stat6 = fs66.statSync(filePath);
79662
- if (stat6.size > MAX_FILE_SIZE_BYTES7) {
79725
+ const stat7 = fs66.statSync(filePath);
79726
+ if (stat7.size > MAX_FILE_SIZE_BYTES7) {
79663
79727
  skippedFileCount++;
79664
79728
  continue;
79665
79729
  }
@@ -79876,7 +79940,7 @@ init_zod();
79876
79940
  init_config();
79877
79941
  init_knowledge_store();
79878
79942
  init_create_tool();
79879
- import { existsSync as existsSync44 } from "node:fs";
79943
+ import { existsSync as existsSync46 } from "node:fs";
79880
79944
  var DEFAULT_LIMIT = 10;
79881
79945
  var MAX_LESSON_LENGTH = 200;
79882
79946
  var VALID_CATEGORIES3 = [
@@ -79946,14 +80010,14 @@ function validateLimit(limit) {
79946
80010
  }
79947
80011
  async function readSwarmKnowledge(directory) {
79948
80012
  const swarmPath = resolveSwarmKnowledgePath(directory);
79949
- if (!existsSync44(swarmPath)) {
80013
+ if (!existsSync46(swarmPath)) {
79950
80014
  return [];
79951
80015
  }
79952
80016
  return readKnowledge(swarmPath);
79953
80017
  }
79954
80018
  async function readHiveKnowledge() {
79955
80019
  const hivePath = resolveHiveKnowledgePath();
79956
- if (!existsSync44(hivePath)) {
80020
+ if (!existsSync46(hivePath)) {
79957
80021
  return [];
79958
80022
  }
79959
80023
  return readKnowledge(hivePath);
@@ -80189,7 +80253,7 @@ init_qa_gate_profile();
80189
80253
  init_manager2();
80190
80254
  init_curator();
80191
80255
  import * as fs68 from "node:fs";
80192
- import * as path86 from "node:path";
80256
+ import * as path90 from "node:path";
80193
80257
  init_knowledge_curator();
80194
80258
  init_knowledge_reader();
80195
80259
  init_knowledge_store();
@@ -80202,16 +80266,16 @@ init_plan_schema();
80202
80266
  init_ledger();
80203
80267
  init_manager();
80204
80268
  import * as fs67 from "node:fs";
80205
- import * as path85 from "node:path";
80269
+ import * as path89 from "node:path";
80206
80270
  async function writeCheckpoint(directory) {
80207
80271
  try {
80208
80272
  const plan = await loadPlan(directory);
80209
80273
  if (!plan)
80210
80274
  return;
80211
- const swarmDir = path85.join(directory, ".swarm");
80275
+ const swarmDir = path89.join(directory, ".swarm");
80212
80276
  fs67.mkdirSync(swarmDir, { recursive: true });
80213
- const jsonPath = path85.join(swarmDir, "SWARM_PLAN.json");
80214
- const mdPath = path85.join(swarmDir, "SWARM_PLAN.md");
80277
+ const jsonPath = path89.join(swarmDir, "SWARM_PLAN.json");
80278
+ const mdPath = path89.join(swarmDir, "SWARM_PLAN.md");
80215
80279
  fs67.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
80216
80280
  const md = derivePlanMarkdown(plan);
80217
80281
  fs67.writeFileSync(mdPath, md, "utf8");
@@ -80446,7 +80510,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
80446
80510
  let driftCheckEnabled = true;
80447
80511
  let driftHasSpecMd = false;
80448
80512
  try {
80449
- const specMdPath = path86.join(dir, ".swarm", "spec.md");
80513
+ const specMdPath = path90.join(dir, ".swarm", "spec.md");
80450
80514
  driftHasSpecMd = fs68.existsSync(specMdPath);
80451
80515
  const gatePlan = await loadPlan(dir);
80452
80516
  if (gatePlan) {
@@ -80468,7 +80532,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
80468
80532
  } else {
80469
80533
  let phaseType;
80470
80534
  try {
80471
- const planPath = path86.join(dir, ".swarm", "plan.json");
80535
+ const planPath = path90.join(dir, ".swarm", "plan.json");
80472
80536
  if (fs68.existsSync(planPath)) {
80473
80537
  const planRaw = fs68.readFileSync(planPath, "utf-8");
80474
80538
  const plan = JSON.parse(planRaw);
@@ -80481,7 +80545,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
80481
80545
  warnings.push(`Phase ${phase} is annotated as 'non-code'. Drift verification was skipped per phase type annotation.`);
80482
80546
  } else {
80483
80547
  try {
80484
- const driftEvidencePath = path86.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
80548
+ const driftEvidencePath = path90.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
80485
80549
  let driftVerdictFound = false;
80486
80550
  let driftVerdictApproved = false;
80487
80551
  try {
@@ -80519,7 +80583,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
80519
80583
  let incompleteTaskCount = 0;
80520
80584
  let planParseable = false;
80521
80585
  try {
80522
- const planPath = path86.join(dir, ".swarm", "plan.json");
80586
+ const planPath = path90.join(dir, ".swarm", "plan.json");
80523
80587
  if (fs68.existsSync(planPath)) {
80524
80588
  const planRaw = fs68.readFileSync(planPath, "utf-8");
80525
80589
  const plan = JSON.parse(planRaw);
@@ -80586,7 +80650,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
80586
80650
  const overrides = session2?.qaGateSessionOverrides ?? {};
80587
80651
  const effective = getEffectiveGates(profile, overrides);
80588
80652
  if (effective.hallucination_guard === true) {
80589
- const hgPath = path86.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
80653
+ const hgPath = path90.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
80590
80654
  let hgVerdictFound = false;
80591
80655
  let hgVerdictApproved = false;
80592
80656
  try {
@@ -80658,7 +80722,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
80658
80722
  const overrides = session2?.qaGateSessionOverrides ?? {};
80659
80723
  const effective = getEffectiveGates(profile, overrides);
80660
80724
  if (effective.mutation_test === true) {
80661
- const mgPath = path86.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
80725
+ const mgPath = path90.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
80662
80726
  let mgVerdictFound = false;
80663
80727
  let mgVerdict;
80664
80728
  try {
@@ -80732,7 +80796,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
80732
80796
  const effective = getEffectiveGates(profile, overrides);
80733
80797
  if (effective.council_mode === true) {
80734
80798
  councilModeEnabled = true;
80735
- const pcPath = path86.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
80799
+ const pcPath = path90.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
80736
80800
  let pcVerdictFound = false;
80737
80801
  let _pcVerdict;
80738
80802
  let pcQuorumSize;
@@ -80934,7 +80998,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
80934
80998
  }
80935
80999
  if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
80936
81000
  try {
80937
- const projectName = path86.basename(dir);
81001
+ const projectName = path90.basename(dir);
80938
81002
  const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
80939
81003
  if (curationResult) {
80940
81004
  const sessionState = swarmState.agentSessions.get(sessionID);
@@ -81304,7 +81368,7 @@ init_utils();
81304
81368
  init_bun_compat();
81305
81369
  init_create_tool();
81306
81370
  import * as fs69 from "node:fs";
81307
- import * as path87 from "node:path";
81371
+ import * as path91 from "node:path";
81308
81372
  var MAX_OUTPUT_BYTES5 = 52428800;
81309
81373
  var AUDIT_TIMEOUT_MS = 120000;
81310
81374
  function isValidEcosystem(value) {
@@ -81332,16 +81396,16 @@ function validateArgs3(args2) {
81332
81396
  function detectEcosystems(directory) {
81333
81397
  const ecosystems = [];
81334
81398
  const cwd = directory;
81335
- if (fs69.existsSync(path87.join(cwd, "package.json"))) {
81399
+ if (fs69.existsSync(path91.join(cwd, "package.json"))) {
81336
81400
  ecosystems.push("npm");
81337
81401
  }
81338
- if (fs69.existsSync(path87.join(cwd, "pyproject.toml")) || fs69.existsSync(path87.join(cwd, "requirements.txt"))) {
81402
+ if (fs69.existsSync(path91.join(cwd, "pyproject.toml")) || fs69.existsSync(path91.join(cwd, "requirements.txt"))) {
81339
81403
  ecosystems.push("pip");
81340
81404
  }
81341
- if (fs69.existsSync(path87.join(cwd, "Cargo.toml"))) {
81405
+ if (fs69.existsSync(path91.join(cwd, "Cargo.toml"))) {
81342
81406
  ecosystems.push("cargo");
81343
81407
  }
81344
- if (fs69.existsSync(path87.join(cwd, "go.mod"))) {
81408
+ if (fs69.existsSync(path91.join(cwd, "go.mod"))) {
81345
81409
  ecosystems.push("go");
81346
81410
  }
81347
81411
  try {
@@ -81350,13 +81414,13 @@ function detectEcosystems(directory) {
81350
81414
  ecosystems.push("dotnet");
81351
81415
  }
81352
81416
  } catch {}
81353
- if (fs69.existsSync(path87.join(cwd, "Gemfile")) || fs69.existsSync(path87.join(cwd, "Gemfile.lock"))) {
81417
+ if (fs69.existsSync(path91.join(cwd, "Gemfile")) || fs69.existsSync(path91.join(cwd, "Gemfile.lock"))) {
81354
81418
  ecosystems.push("ruby");
81355
81419
  }
81356
- if (fs69.existsSync(path87.join(cwd, "pubspec.yaml"))) {
81420
+ if (fs69.existsSync(path91.join(cwd, "pubspec.yaml"))) {
81357
81421
  ecosystems.push("dart");
81358
81422
  }
81359
- if (fs69.existsSync(path87.join(cwd, "composer.lock"))) {
81423
+ if (fs69.existsSync(path91.join(cwd, "composer.lock"))) {
81360
81424
  ecosystems.push("composer");
81361
81425
  }
81362
81426
  return ecosystems;
@@ -81369,7 +81433,7 @@ async function runNpmAudit(directory) {
81369
81433
  stderr: "pipe",
81370
81434
  cwd: directory
81371
81435
  });
81372
- const timeoutPromise = new Promise((resolve31) => setTimeout(() => resolve31("timeout"), AUDIT_TIMEOUT_MS));
81436
+ const timeoutPromise = new Promise((resolve32) => setTimeout(() => resolve32("timeout"), AUDIT_TIMEOUT_MS));
81373
81437
  const result = await Promise.race([
81374
81438
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr2]) => ({ stdout: stdout2, stderr: stderr2 })),
81375
81439
  timeoutPromise
@@ -81489,7 +81553,7 @@ async function runPipAudit(directory) {
81489
81553
  stderr: "pipe",
81490
81554
  cwd: directory
81491
81555
  });
81492
- const timeoutPromise = new Promise((resolve31) => setTimeout(() => resolve31("timeout"), AUDIT_TIMEOUT_MS));
81556
+ const timeoutPromise = new Promise((resolve32) => setTimeout(() => resolve32("timeout"), AUDIT_TIMEOUT_MS));
81493
81557
  const result = await Promise.race([
81494
81558
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr2]) => ({ stdout: stdout2, stderr: stderr2 })),
81495
81559
  timeoutPromise
@@ -81617,7 +81681,7 @@ async function runCargoAudit(directory) {
81617
81681
  stderr: "pipe",
81618
81682
  cwd: directory
81619
81683
  });
81620
- const timeoutPromise = new Promise((resolve31) => setTimeout(() => resolve31("timeout"), AUDIT_TIMEOUT_MS));
81684
+ const timeoutPromise = new Promise((resolve32) => setTimeout(() => resolve32("timeout"), AUDIT_TIMEOUT_MS));
81621
81685
  const result = await Promise.race([
81622
81686
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
81623
81687
  timeoutPromise
@@ -81741,7 +81805,7 @@ async function runGoAudit(directory) {
81741
81805
  stderr: "pipe",
81742
81806
  cwd: directory
81743
81807
  });
81744
- const timeoutPromise = new Promise((resolve31) => setTimeout(() => resolve31("timeout"), AUDIT_TIMEOUT_MS));
81808
+ const timeoutPromise = new Promise((resolve32) => setTimeout(() => resolve32("timeout"), AUDIT_TIMEOUT_MS));
81745
81809
  const result = await Promise.race([
81746
81810
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
81747
81811
  timeoutPromise
@@ -81874,7 +81938,7 @@ async function runDotnetAudit(directory) {
81874
81938
  stderr: "pipe",
81875
81939
  cwd: directory
81876
81940
  });
81877
- const timeoutPromise = new Promise((resolve31) => setTimeout(() => resolve31("timeout"), AUDIT_TIMEOUT_MS));
81941
+ const timeoutPromise = new Promise((resolve32) => setTimeout(() => resolve32("timeout"), AUDIT_TIMEOUT_MS));
81878
81942
  const result = await Promise.race([
81879
81943
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
81880
81944
  timeoutPromise
@@ -81990,7 +82054,7 @@ async function runBundleAudit(directory) {
81990
82054
  stderr: "pipe",
81991
82055
  cwd: directory
81992
82056
  });
81993
- const timeoutPromise = new Promise((resolve31) => setTimeout(() => resolve31("timeout"), AUDIT_TIMEOUT_MS));
82057
+ const timeoutPromise = new Promise((resolve32) => setTimeout(() => resolve32("timeout"), AUDIT_TIMEOUT_MS));
81994
82058
  const result = await Promise.race([
81995
82059
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
81996
82060
  timeoutPromise
@@ -82135,7 +82199,7 @@ async function runDartAudit(directory) {
82135
82199
  stderr: "pipe",
82136
82200
  cwd: directory
82137
82201
  });
82138
- const timeoutPromise = new Promise((resolve31) => setTimeout(() => resolve31("timeout"), AUDIT_TIMEOUT_MS));
82202
+ const timeoutPromise = new Promise((resolve32) => setTimeout(() => resolve32("timeout"), AUDIT_TIMEOUT_MS));
82139
82203
  const result = await Promise.race([
82140
82204
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
82141
82205
  timeoutPromise
@@ -82250,7 +82314,7 @@ async function runComposerAudit(directory) {
82250
82314
  stderr: "pipe",
82251
82315
  cwd: directory
82252
82316
  });
82253
- const timeoutPromise = new Promise((resolve31) => setTimeout(() => resolve31("timeout"), AUDIT_TIMEOUT_MS));
82317
+ const timeoutPromise = new Promise((resolve32) => setTimeout(() => resolve32("timeout"), AUDIT_TIMEOUT_MS));
82254
82318
  const result = await Promise.race([
82255
82319
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
82256
82320
  timeoutPromise
@@ -82492,7 +82556,7 @@ var pkg_audit = createSwarmTool({
82492
82556
  init_zod();
82493
82557
  init_manager2();
82494
82558
  import * as fs70 from "node:fs";
82495
- import * as path88 from "node:path";
82559
+ import * as path92 from "node:path";
82496
82560
  init_utils();
82497
82561
  init_create_tool();
82498
82562
  var MAX_FILE_SIZE = 1024 * 1024;
@@ -82615,7 +82679,7 @@ function isScaffoldFile(filePath) {
82615
82679
  if (SCAFFOLD_PATH_PATTERNS.some((pattern) => pattern.test(normalizedPath))) {
82616
82680
  return true;
82617
82681
  }
82618
- const filename = path88.basename(filePath);
82682
+ const filename = path92.basename(filePath);
82619
82683
  if (SCAFFOLD_FILENAME_PATTERNS.some((pattern) => pattern.test(filename))) {
82620
82684
  return true;
82621
82685
  }
@@ -82632,7 +82696,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
82632
82696
  if (regex.test(normalizedPath)) {
82633
82697
  return true;
82634
82698
  }
82635
- const filename = path88.basename(filePath);
82699
+ const filename = path92.basename(filePath);
82636
82700
  const filenameRegex = new RegExp(`^${regexPattern}$`, "i");
82637
82701
  if (filenameRegex.test(filename)) {
82638
82702
  return true;
@@ -82641,7 +82705,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
82641
82705
  return false;
82642
82706
  }
82643
82707
  function isParserSupported(filePath) {
82644
- const ext = path88.extname(filePath).toLowerCase();
82708
+ const ext = path92.extname(filePath).toLowerCase();
82645
82709
  return SUPPORTED_PARSER_EXTENSIONS.has(ext);
82646
82710
  }
82647
82711
  function isPlanFile(filePath) {
@@ -82888,9 +82952,9 @@ async function placeholderScan(input, directory) {
82888
82952
  let filesScanned = 0;
82889
82953
  const filesWithFindings = new Set;
82890
82954
  for (const filePath of changed_files) {
82891
- const fullPath = path88.isAbsolute(filePath) ? filePath : path88.resolve(directory, filePath);
82892
- const resolvedDirectory = path88.resolve(directory);
82893
- if (!fullPath.startsWith(resolvedDirectory + path88.sep) && fullPath !== resolvedDirectory) {
82955
+ const fullPath = path92.isAbsolute(filePath) ? filePath : path92.resolve(directory, filePath);
82956
+ const resolvedDirectory = path92.resolve(directory);
82957
+ if (!fullPath.startsWith(resolvedDirectory + path92.sep) && fullPath !== resolvedDirectory) {
82894
82958
  continue;
82895
82959
  }
82896
82960
  if (!fs70.existsSync(fullPath)) {
@@ -82899,14 +82963,14 @@ async function placeholderScan(input, directory) {
82899
82963
  if (isAllowedByGlobs(filePath, allow_globs)) {
82900
82964
  continue;
82901
82965
  }
82902
- const relativeFilePath = path88.relative(directory, fullPath).replace(/\\/g, "/");
82966
+ const relativeFilePath = path92.relative(directory, fullPath).replace(/\\/g, "/");
82903
82967
  if (FILE_ALLOWLIST.some((allowed) => relativeFilePath.endsWith(allowed))) {
82904
82968
  continue;
82905
82969
  }
82906
82970
  let content;
82907
82971
  try {
82908
- const stat6 = fs70.statSync(fullPath);
82909
- if (stat6.size > MAX_FILE_SIZE) {
82972
+ const stat7 = fs70.statSync(fullPath);
82973
+ if (stat7.size > MAX_FILE_SIZE) {
82910
82974
  continue;
82911
82975
  }
82912
82976
  content = fs70.readFileSync(fullPath, "utf-8");
@@ -82971,7 +83035,7 @@ var placeholder_scan = createSwarmTool({
82971
83035
  });
82972
83036
  // src/tools/pre-check-batch.ts
82973
83037
  import * as fs73 from "node:fs";
82974
- import * as path91 from "node:path";
83038
+ import * as path95 from "node:path";
82975
83039
  init_zod();
82976
83040
  init_manager2();
82977
83041
  init_utils();
@@ -83109,7 +83173,7 @@ init_zod();
83109
83173
  init_manager2();
83110
83174
  init_detector();
83111
83175
  import * as fs72 from "node:fs";
83112
- import * as path90 from "node:path";
83176
+ import * as path94 from "node:path";
83113
83177
  import { extname as extname18 } from "node:path";
83114
83178
 
83115
83179
  // src/sast/rules/c.ts
@@ -83890,7 +83954,7 @@ function mapSemgrepSeverity(severity) {
83890
83954
  }
83891
83955
  }
83892
83956
  async function executeWithTimeout(command, args2, options) {
83893
- return new Promise((resolve32) => {
83957
+ return new Promise((resolve33) => {
83894
83958
  const child = child_process9.spawn(command, args2, {
83895
83959
  shell: false,
83896
83960
  cwd: options.cwd
@@ -83899,7 +83963,7 @@ async function executeWithTimeout(command, args2, options) {
83899
83963
  let stderr = "";
83900
83964
  const timeout = setTimeout(() => {
83901
83965
  child.kill("SIGTERM");
83902
- resolve32({
83966
+ resolve33({
83903
83967
  stdout,
83904
83968
  stderr: "Process timed out",
83905
83969
  exitCode: 124
@@ -83913,7 +83977,7 @@ async function executeWithTimeout(command, args2, options) {
83913
83977
  });
83914
83978
  child.on("close", (code) => {
83915
83979
  clearTimeout(timeout);
83916
- resolve32({
83980
+ resolve33({
83917
83981
  stdout,
83918
83982
  stderr,
83919
83983
  exitCode: code ?? 0
@@ -83921,7 +83985,7 @@ async function executeWithTimeout(command, args2, options) {
83921
83985
  });
83922
83986
  child.on("error", (err2) => {
83923
83987
  clearTimeout(timeout);
83924
- resolve32({
83988
+ resolve33({
83925
83989
  stdout,
83926
83990
  stderr: err2.message,
83927
83991
  exitCode: 1
@@ -84003,24 +84067,24 @@ init_create_tool();
84003
84067
  init_utils2();
84004
84068
  import * as crypto8 from "node:crypto";
84005
84069
  import * as fs71 from "node:fs";
84006
- import * as path89 from "node:path";
84070
+ import * as path93 from "node:path";
84007
84071
  var BASELINE_SCHEMA_VERSION = "1.0.0";
84008
84072
  var MAX_BASELINE_FINDINGS = 2000;
84009
84073
  var MAX_BASELINE_BYTES = 2 * 1048576;
84010
84074
  var LOCK_RETRY_DELAYS_MS = [50, 100, 200, 400, 800];
84011
84075
  function normalizeFindingPath(directory, file3) {
84012
- const resolved = path89.isAbsolute(file3) ? file3 : path89.resolve(directory, file3);
84013
- const rel = path89.relative(path89.resolve(directory), resolved);
84076
+ const resolved = path93.isAbsolute(file3) ? file3 : path93.resolve(directory, file3);
84077
+ const rel = path93.relative(path93.resolve(directory), resolved);
84014
84078
  return rel.replace(/\\/g, "/");
84015
84079
  }
84016
84080
  function baselineRelPath(phase) {
84017
- return path89.join("evidence", String(phase), "sast-baseline.json");
84081
+ return path93.join("evidence", String(phase), "sast-baseline.json");
84018
84082
  }
84019
84083
  function tempRelPath(phase) {
84020
- return path89.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
84084
+ return path93.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
84021
84085
  }
84022
84086
  function lockRelPath(phase) {
84023
- return path89.join("evidence", String(phase), "sast-baseline.json.lock");
84087
+ return path93.join("evidence", String(phase), "sast-baseline.json.lock");
84024
84088
  }
84025
84089
  function getLine(lines, idx) {
84026
84090
  if (idx < 0 || idx >= lines.length)
@@ -84106,7 +84170,7 @@ async function acquireLock(lockPath) {
84106
84170
  };
84107
84171
  } catch {
84108
84172
  if (attempt < LOCK_RETRY_DELAYS_MS.length) {
84109
- await new Promise((resolve33) => setTimeout(resolve33, LOCK_RETRY_DELAYS_MS[attempt]));
84173
+ await new Promise((resolve34) => setTimeout(resolve34, LOCK_RETRY_DELAYS_MS[attempt]));
84110
84174
  }
84111
84175
  }
84112
84176
  }
@@ -84141,8 +84205,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
84141
84205
  message: e instanceof Error ? e.message : "Path validation failed"
84142
84206
  };
84143
84207
  }
84144
- fs71.mkdirSync(path89.dirname(baselinePath), { recursive: true });
84145
- fs71.mkdirSync(path89.dirname(tempPath), { recursive: true });
84208
+ fs71.mkdirSync(path93.dirname(baselinePath), { recursive: true });
84209
+ fs71.mkdirSync(path93.dirname(tempPath), { recursive: true });
84146
84210
  const releaseLock = await acquireLock(lockPath);
84147
84211
  try {
84148
84212
  let existing = null;
@@ -84409,9 +84473,9 @@ async function sastScan(input, directory, config3) {
84409
84473
  _filesSkipped++;
84410
84474
  continue;
84411
84475
  }
84412
- const resolvedPath = path90.isAbsolute(filePath) ? filePath : path90.resolve(directory, filePath);
84413
- const resolvedDirectory = path90.resolve(directory);
84414
- if (!resolvedPath.startsWith(resolvedDirectory + path90.sep) && resolvedPath !== resolvedDirectory) {
84476
+ const resolvedPath = path94.isAbsolute(filePath) ? filePath : path94.resolve(directory, filePath);
84477
+ const resolvedDirectory = path94.resolve(directory);
84478
+ if (!resolvedPath.startsWith(resolvedDirectory + path94.sep) && resolvedPath !== resolvedDirectory) {
84415
84479
  _filesSkipped++;
84416
84480
  continue;
84417
84481
  }
@@ -84722,18 +84786,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
84722
84786
  let resolved;
84723
84787
  const isWinAbs = isWindowsAbsolutePath(inputPath);
84724
84788
  if (isWinAbs) {
84725
- resolved = path91.win32.resolve(inputPath);
84726
- } else if (path91.isAbsolute(inputPath)) {
84727
- resolved = path91.resolve(inputPath);
84789
+ resolved = path95.win32.resolve(inputPath);
84790
+ } else if (path95.isAbsolute(inputPath)) {
84791
+ resolved = path95.resolve(inputPath);
84728
84792
  } else {
84729
- resolved = path91.resolve(baseDir, inputPath);
84793
+ resolved = path95.resolve(baseDir, inputPath);
84730
84794
  }
84731
- const workspaceResolved = path91.resolve(workspaceDir);
84795
+ const workspaceResolved = path95.resolve(workspaceDir);
84732
84796
  let relative20;
84733
84797
  if (isWinAbs) {
84734
- relative20 = path91.win32.relative(workspaceResolved, resolved);
84798
+ relative20 = path95.win32.relative(workspaceResolved, resolved);
84735
84799
  } else {
84736
- relative20 = path91.relative(workspaceResolved, resolved);
84800
+ relative20 = path95.relative(workspaceResolved, resolved);
84737
84801
  }
84738
84802
  if (relative20.startsWith("..")) {
84739
84803
  return "path traversal detected";
@@ -84798,7 +84862,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
84798
84862
  if (typeof file3 !== "string") {
84799
84863
  continue;
84800
84864
  }
84801
- const resolvedPath = path91.resolve(file3);
84865
+ const resolvedPath = path95.resolve(file3);
84802
84866
  const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
84803
84867
  if (validationError) {
84804
84868
  continue;
@@ -84955,7 +85019,7 @@ async function runSecretscanWithFiles(files, directory) {
84955
85019
  skippedFiles++;
84956
85020
  continue;
84957
85021
  }
84958
- const resolvedPath = path91.resolve(file3);
85022
+ const resolvedPath = path95.resolve(file3);
84959
85023
  const validationError = validatePath(resolvedPath, directory, directory);
84960
85024
  if (validationError) {
84961
85025
  skippedFiles++;
@@ -84973,19 +85037,19 @@ async function runSecretscanWithFiles(files, directory) {
84973
85037
  };
84974
85038
  }
84975
85039
  for (const file3 of validatedFiles) {
84976
- const ext = path91.extname(file3).toLowerCase();
85040
+ const ext = path95.extname(file3).toLowerCase();
84977
85041
  if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
84978
85042
  skippedFiles++;
84979
85043
  continue;
84980
85044
  }
84981
- let stat6;
85045
+ let stat7;
84982
85046
  try {
84983
- stat6 = fs73.statSync(file3);
85047
+ stat7 = fs73.statSync(file3);
84984
85048
  } catch {
84985
85049
  skippedFiles++;
84986
85050
  continue;
84987
85051
  }
84988
- if (stat6.size > MAX_FILE_SIZE_BYTES9) {
85052
+ if (stat7.size > MAX_FILE_SIZE_BYTES9) {
84989
85053
  skippedFiles++;
84990
85054
  continue;
84991
85055
  }
@@ -85192,7 +85256,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
85192
85256
  const preexistingFindings = [];
85193
85257
  for (const finding of findings) {
85194
85258
  const filePath = finding.location.file;
85195
- const normalised = path91.relative(directory, filePath).replace(/\\/g, "/");
85259
+ const normalised = path95.relative(directory, filePath).replace(/\\/g, "/");
85196
85260
  const changedLines = changedLineRanges.get(normalised);
85197
85261
  if (changedLines?.has(finding.location.line)) {
85198
85262
  newFindings.push(finding);
@@ -85243,7 +85307,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
85243
85307
  warn(`pre_check_batch: Invalid file path: ${file3}`);
85244
85308
  continue;
85245
85309
  }
85246
- changedFiles.push(path91.resolve(directory, file3));
85310
+ changedFiles.push(path95.resolve(directory, file3));
85247
85311
  }
85248
85312
  if (changedFiles.length === 0) {
85249
85313
  warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
@@ -85444,7 +85508,7 @@ var pre_check_batch = createSwarmTool({
85444
85508
  };
85445
85509
  return JSON.stringify(errorResult, null, 2);
85446
85510
  }
85447
- const resolvedDirectory = path91.resolve(typedArgs.directory);
85511
+ const resolvedDirectory = path95.resolve(typedArgs.directory);
85448
85512
  const workspaceAnchor = resolvedDirectory;
85449
85513
  const dirError = validateDirectory2(resolvedDirectory, workspaceAnchor);
85450
85514
  if (dirError) {
@@ -85485,7 +85549,7 @@ var pre_check_batch = createSwarmTool({
85485
85549
  });
85486
85550
  // src/tools/repo-map.ts
85487
85551
  init_zod();
85488
- import * as path92 from "node:path";
85552
+ import * as path96 from "node:path";
85489
85553
  init_path_security();
85490
85554
  init_create_tool();
85491
85555
  var VALID_ACTIONS = [
@@ -85510,7 +85574,7 @@ function validateFile(p) {
85510
85574
  return "file contains control characters";
85511
85575
  if (containsPathTraversal(p))
85512
85576
  return "file contains path traversal";
85513
- if (path92.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
85577
+ if (path96.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
85514
85578
  return "file must be a workspace-relative path, not absolute";
85515
85579
  }
85516
85580
  return null;
@@ -85533,8 +85597,8 @@ function ok(action, payload) {
85533
85597
  }
85534
85598
  function toRelativeGraphPath(input, workspaceRoot) {
85535
85599
  const normalized = input.replace(/\\/g, "/");
85536
- if (path92.isAbsolute(normalized)) {
85537
- const rel = path92.relative(workspaceRoot, normalized).replace(/\\/g, "/");
85600
+ if (path96.isAbsolute(normalized)) {
85601
+ const rel = path96.relative(workspaceRoot, normalized).replace(/\\/g, "/");
85538
85602
  return normalizeGraphPath2(rel);
85539
85603
  }
85540
85604
  return normalizeGraphPath2(normalized);
@@ -85679,7 +85743,7 @@ var repo_map = createSwarmTool({
85679
85743
  init_zod();
85680
85744
  init_create_tool();
85681
85745
  import * as fs74 from "node:fs";
85682
- import * as path93 from "node:path";
85746
+ import * as path97 from "node:path";
85683
85747
  var SPEC_FILE = ".swarm/spec.md";
85684
85748
  var EVIDENCE_DIR4 = ".swarm/evidence";
85685
85749
  var OBLIGATION_KEYWORDS = ["MUST", "SHOULD", "SHALL"];
@@ -85748,10 +85812,10 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
85748
85812
  return [];
85749
85813
  }
85750
85814
  for (const entry of entries) {
85751
- const entryPath = path93.join(evidenceDir, entry);
85815
+ const entryPath = path97.join(evidenceDir, entry);
85752
85816
  try {
85753
- const stat6 = fs74.statSync(entryPath);
85754
- if (!stat6.isDirectory()) {
85817
+ const stat7 = fs74.statSync(entryPath);
85818
+ if (!stat7.isDirectory()) {
85755
85819
  continue;
85756
85820
  }
85757
85821
  } catch {
@@ -85764,18 +85828,18 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
85764
85828
  if (entryPhase !== String(phase)) {
85765
85829
  continue;
85766
85830
  }
85767
- const evidenceFilePath = path93.join(entryPath, "evidence.json");
85831
+ const evidenceFilePath = path97.join(entryPath, "evidence.json");
85768
85832
  try {
85769
- const resolvedPath = path93.resolve(evidenceFilePath);
85770
- const evidenceDirResolved = path93.resolve(evidenceDir);
85771
- if (!resolvedPath.startsWith(evidenceDirResolved + path93.sep)) {
85833
+ const resolvedPath = path97.resolve(evidenceFilePath);
85834
+ const evidenceDirResolved = path97.resolve(evidenceDir);
85835
+ if (!resolvedPath.startsWith(evidenceDirResolved + path97.sep)) {
85772
85836
  continue;
85773
85837
  }
85774
- const stat6 = fs74.lstatSync(evidenceFilePath);
85775
- if (!stat6.isFile()) {
85838
+ const stat7 = fs74.lstatSync(evidenceFilePath);
85839
+ if (!stat7.isFile()) {
85776
85840
  continue;
85777
85841
  }
85778
- if (stat6.size > MAX_FILE_SIZE_BYTES9) {
85842
+ if (stat7.size > MAX_FILE_SIZE_BYTES9) {
85779
85843
  continue;
85780
85844
  }
85781
85845
  } catch {
@@ -85802,7 +85866,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
85802
85866
  if (Array.isArray(diffEntry.files_changed)) {
85803
85867
  for (const file3 of diffEntry.files_changed) {
85804
85868
  if (typeof file3 === "string") {
85805
- touchedFiles.add(path93.resolve(cwd, file3));
85869
+ touchedFiles.add(path97.resolve(cwd, file3));
85806
85870
  }
85807
85871
  }
85808
85872
  }
@@ -85815,8 +85879,8 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
85815
85879
  }
85816
85880
  function searchFileForKeywords(filePath, keywords, cwd) {
85817
85881
  try {
85818
- const resolvedPath = path93.resolve(filePath);
85819
- const cwdResolved = path93.resolve(cwd);
85882
+ const resolvedPath = path97.resolve(filePath);
85883
+ const cwdResolved = path97.resolve(cwd);
85820
85884
  if (!resolvedPath.startsWith(cwdResolved)) {
85821
85885
  return false;
85822
85886
  }
@@ -85950,7 +86014,7 @@ var req_coverage = createSwarmTool({
85950
86014
  }, null, 2);
85951
86015
  }
85952
86016
  const cwd = inputDirectory || directory;
85953
- const specPath = path93.join(cwd, SPEC_FILE);
86017
+ const specPath = path97.join(cwd, SPEC_FILE);
85954
86018
  let specContent;
85955
86019
  try {
85956
86020
  specContent = fs74.readFileSync(specPath, "utf-8");
@@ -85977,7 +86041,7 @@ var req_coverage = createSwarmTool({
85977
86041
  message: "No FR requirements found in spec.md"
85978
86042
  }, null, 2);
85979
86043
  }
85980
- const evidenceDir = path93.join(cwd, EVIDENCE_DIR4);
86044
+ const evidenceDir = path97.join(cwd, EVIDENCE_DIR4);
85981
86045
  const touchedFiles = readTouchedFiles(evidenceDir, phase, cwd);
85982
86046
  const analyzedRequirements = [];
85983
86047
  let coveredCount = 0;
@@ -86003,7 +86067,7 @@ var req_coverage = createSwarmTool({
86003
86067
  requirements: analyzedRequirements
86004
86068
  };
86005
86069
  const reportFilename = `req-coverage-phase-${phase}.json`;
86006
- const reportPath = path93.join(evidenceDir, reportFilename);
86070
+ const reportPath = path97.join(evidenceDir, reportFilename);
86007
86071
  try {
86008
86072
  if (!fs74.existsSync(evidenceDir)) {
86009
86073
  fs74.mkdirSync(evidenceDir, { recursive: true });
@@ -86091,7 +86155,7 @@ init_qa_gate_profile();
86091
86155
  init_file_locks();
86092
86156
  import * as crypto9 from "node:crypto";
86093
86157
  import * as fs75 from "node:fs";
86094
- import * as path94 from "node:path";
86158
+ import * as path98 from "node:path";
86095
86159
  init_ledger();
86096
86160
  init_manager();
86097
86161
  init_state();
@@ -86169,8 +86233,8 @@ async function executeSavePlan(args2, fallbackDir) {
86169
86233
  };
86170
86234
  }
86171
86235
  if (args2.working_directory && fallbackDir) {
86172
- const resolvedTarget = path94.resolve(args2.working_directory);
86173
- const resolvedRoot = path94.resolve(fallbackDir);
86236
+ const resolvedTarget = path98.resolve(args2.working_directory);
86237
+ const resolvedRoot = path98.resolve(fallbackDir);
86174
86238
  let fallbackExists = false;
86175
86239
  try {
86176
86240
  fs75.accessSync(resolvedRoot, fs75.constants.F_OK);
@@ -86179,7 +86243,7 @@ async function executeSavePlan(args2, fallbackDir) {
86179
86243
  fallbackExists = false;
86180
86244
  }
86181
86245
  if (fallbackExists) {
86182
- const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path94.sep);
86246
+ const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path98.sep);
86183
86247
  if (isSubdirectory) {
86184
86248
  return {
86185
86249
  success: false,
@@ -86195,10 +86259,10 @@ async function executeSavePlan(args2, fallbackDir) {
86195
86259
  let specMtime;
86196
86260
  let specHash;
86197
86261
  if (process.env.SWARM_SKIP_SPEC_GATE !== "1") {
86198
- const specPath = path94.join(targetWorkspace, ".swarm", "spec.md");
86262
+ const specPath = path98.join(targetWorkspace, ".swarm", "spec.md");
86199
86263
  try {
86200
- const stat6 = await fs75.promises.stat(specPath);
86201
- specMtime = stat6.mtime.toISOString();
86264
+ const stat7 = await fs75.promises.stat(specPath);
86265
+ specMtime = stat7.mtime.toISOString();
86202
86266
  const content = await fs75.promises.readFile(specPath, "utf8");
86203
86267
  specHash = crypto9.createHash("sha256").update(content).digest("hex");
86204
86268
  } catch {
@@ -86211,7 +86275,7 @@ async function executeSavePlan(args2, fallbackDir) {
86211
86275
  }
86212
86276
  }
86213
86277
  if (process.env.SWARM_SKIP_GATE_SELECTION !== "1") {
86214
- const contextPath = path94.join(targetWorkspace, ".swarm", "context.md");
86278
+ const contextPath = path98.join(targetWorkspace, ".swarm", "context.md");
86215
86279
  let contextContent = "";
86216
86280
  try {
86217
86281
  contextContent = await fs75.promises.readFile(contextPath, "utf8");
@@ -86361,7 +86425,7 @@ async function executeSavePlan(args2, fallbackDir) {
86361
86425
  }
86362
86426
  await writeCheckpoint(dir).catch(() => {});
86363
86427
  try {
86364
- const markerPath = path94.join(dir, ".swarm", ".plan-write-marker");
86428
+ const markerPath = path98.join(dir, ".swarm", ".plan-write-marker");
86365
86429
  const marker = JSON.stringify({
86366
86430
  source: "save_plan",
86367
86431
  timestamp: new Date().toISOString(),
@@ -86384,7 +86448,7 @@ async function executeSavePlan(args2, fallbackDir) {
86384
86448
  return {
86385
86449
  success: true,
86386
86450
  message: "Plan saved successfully",
86387
- plan_path: path94.join(dir, ".swarm", "plan.json"),
86451
+ plan_path: path98.join(dir, ".swarm", "plan.json"),
86388
86452
  phases_count: plan.phases.length,
86389
86453
  tasks_count: tasksCount,
86390
86454
  ...resolvedProfile !== undefined ? { execution_profile: resolvedProfile } : {},
@@ -86437,7 +86501,7 @@ var save_plan = createSwarmTool({
86437
86501
  init_zod();
86438
86502
  init_manager2();
86439
86503
  import * as fs76 from "node:fs";
86440
- import * as path95 from "node:path";
86504
+ import * as path99 from "node:path";
86441
86505
 
86442
86506
  // src/sbom/detectors/index.ts
86443
86507
  init_utils();
@@ -87287,7 +87351,7 @@ function findManifestFiles(rootDir) {
87287
87351
  try {
87288
87352
  const entries = fs76.readdirSync(dir, { withFileTypes: true });
87289
87353
  for (const entry of entries) {
87290
- const fullPath = path95.join(dir, entry.name);
87354
+ const fullPath = path99.join(dir, entry.name);
87291
87355
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
87292
87356
  continue;
87293
87357
  }
@@ -87296,7 +87360,7 @@ function findManifestFiles(rootDir) {
87296
87360
  } else if (entry.isFile()) {
87297
87361
  for (const pattern of patterns) {
87298
87362
  if (simpleGlobToRegex(pattern).test(entry.name)) {
87299
- manifestFiles.push(path95.relative(rootDir, fullPath));
87363
+ manifestFiles.push(path99.relative(rootDir, fullPath));
87300
87364
  break;
87301
87365
  }
87302
87366
  }
@@ -87314,11 +87378,11 @@ function findManifestFilesInDirs(directories, workingDir) {
87314
87378
  try {
87315
87379
  const entries = fs76.readdirSync(dir, { withFileTypes: true });
87316
87380
  for (const entry of entries) {
87317
- const fullPath = path95.join(dir, entry.name);
87381
+ const fullPath = path99.join(dir, entry.name);
87318
87382
  if (entry.isFile()) {
87319
87383
  for (const pattern of patterns) {
87320
87384
  if (simpleGlobToRegex(pattern).test(entry.name)) {
87321
- found.push(path95.relative(workingDir, fullPath));
87385
+ found.push(path99.relative(workingDir, fullPath));
87322
87386
  break;
87323
87387
  }
87324
87388
  }
@@ -87331,11 +87395,11 @@ function findManifestFilesInDirs(directories, workingDir) {
87331
87395
  function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
87332
87396
  const dirs = new Set;
87333
87397
  for (const file3 of changedFiles) {
87334
- let currentDir = path95.dirname(file3);
87398
+ let currentDir = path99.dirname(file3);
87335
87399
  while (true) {
87336
- if (currentDir && currentDir !== "." && currentDir !== path95.sep) {
87337
- dirs.add(path95.join(workingDir, currentDir));
87338
- const parent = path95.dirname(currentDir);
87400
+ if (currentDir && currentDir !== "." && currentDir !== path99.sep) {
87401
+ dirs.add(path99.join(workingDir, currentDir));
87402
+ const parent = path99.dirname(currentDir);
87339
87403
  if (parent === currentDir)
87340
87404
  break;
87341
87405
  currentDir = parent;
@@ -87419,7 +87483,7 @@ var sbom_generate = createSwarmTool({
87419
87483
  const changedFiles = obj.changed_files;
87420
87484
  const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
87421
87485
  const workingDir = directory;
87422
- const outputDir = path95.isAbsolute(relativeOutputDir) ? relativeOutputDir : path95.join(workingDir, relativeOutputDir);
87486
+ const outputDir = path99.isAbsolute(relativeOutputDir) ? relativeOutputDir : path99.join(workingDir, relativeOutputDir);
87423
87487
  let manifestFiles = [];
87424
87488
  if (scope === "all") {
87425
87489
  manifestFiles = findManifestFiles(workingDir);
@@ -87442,7 +87506,7 @@ var sbom_generate = createSwarmTool({
87442
87506
  const processedFiles = [];
87443
87507
  for (const manifestFile of manifestFiles) {
87444
87508
  try {
87445
- const fullPath = path95.isAbsolute(manifestFile) ? manifestFile : path95.join(workingDir, manifestFile);
87509
+ const fullPath = path99.isAbsolute(manifestFile) ? manifestFile : path99.join(workingDir, manifestFile);
87446
87510
  if (!fs76.existsSync(fullPath)) {
87447
87511
  continue;
87448
87512
  }
@@ -87459,7 +87523,7 @@ var sbom_generate = createSwarmTool({
87459
87523
  const bom = generateCycloneDX(allComponents);
87460
87524
  const bomJson = serializeCycloneDX(bom);
87461
87525
  const filename = generateSbomFilename();
87462
- const outputPath = path95.join(outputDir, filename);
87526
+ const outputPath = path99.join(outputDir, filename);
87463
87527
  fs76.writeFileSync(outputPath, bomJson, "utf-8");
87464
87528
  const verdict = processedFiles.length > 0 ? "pass" : "pass";
87465
87529
  try {
@@ -87503,7 +87567,7 @@ var sbom_generate = createSwarmTool({
87503
87567
  init_zod();
87504
87568
  init_create_tool();
87505
87569
  import * as fs77 from "node:fs";
87506
- import * as path96 from "node:path";
87570
+ import * as path100 from "node:path";
87507
87571
  var SPEC_CANDIDATES = [
87508
87572
  "openapi.json",
87509
87573
  "openapi.yaml",
@@ -87535,12 +87599,12 @@ function normalizePath3(p) {
87535
87599
  }
87536
87600
  function discoverSpecFile(cwd, specFileArg) {
87537
87601
  if (specFileArg) {
87538
- const resolvedPath = path96.resolve(cwd, specFileArg);
87539
- const normalizedCwd = cwd.endsWith(path96.sep) ? cwd : cwd + path96.sep;
87602
+ const resolvedPath = path100.resolve(cwd, specFileArg);
87603
+ const normalizedCwd = cwd.endsWith(path100.sep) ? cwd : cwd + path100.sep;
87540
87604
  if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
87541
87605
  throw new Error("Invalid spec_file: path traversal detected");
87542
87606
  }
87543
- const ext = path96.extname(resolvedPath).toLowerCase();
87607
+ const ext = path100.extname(resolvedPath).toLowerCase();
87544
87608
  if (!ALLOWED_EXTENSIONS.includes(ext)) {
87545
87609
  throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
87546
87610
  }
@@ -87554,7 +87618,7 @@ function discoverSpecFile(cwd, specFileArg) {
87554
87618
  return resolvedPath;
87555
87619
  }
87556
87620
  for (const candidate of SPEC_CANDIDATES) {
87557
- const candidatePath = path96.resolve(cwd, candidate);
87621
+ const candidatePath = path100.resolve(cwd, candidate);
87558
87622
  if (fs77.existsSync(candidatePath)) {
87559
87623
  const stats = fs77.statSync(candidatePath);
87560
87624
  if (stats.size <= MAX_SPEC_SIZE) {
@@ -87566,7 +87630,7 @@ function discoverSpecFile(cwd, specFileArg) {
87566
87630
  }
87567
87631
  function parseSpec(specFile) {
87568
87632
  const content = fs77.readFileSync(specFile, "utf-8");
87569
- const ext = path96.extname(specFile).toLowerCase();
87633
+ const ext = path100.extname(specFile).toLowerCase();
87570
87634
  if (ext === ".json") {
87571
87635
  return parseJsonSpec(content);
87572
87636
  }
@@ -87642,7 +87706,7 @@ function extractRoutes(cwd) {
87642
87706
  return;
87643
87707
  }
87644
87708
  for (const entry of entries) {
87645
- const fullPath = path96.join(dir, entry.name);
87709
+ const fullPath = path100.join(dir, entry.name);
87646
87710
  if (entry.isSymbolicLink()) {
87647
87711
  continue;
87648
87712
  }
@@ -87652,7 +87716,7 @@ function extractRoutes(cwd) {
87652
87716
  }
87653
87717
  walkDir(fullPath);
87654
87718
  } else if (entry.isFile()) {
87655
- const ext = path96.extname(entry.name).toLowerCase();
87719
+ const ext = path100.extname(entry.name).toLowerCase();
87656
87720
  const baseName = entry.name.toLowerCase();
87657
87721
  if (![".ts", ".js", ".mjs"].includes(ext)) {
87658
87722
  continue;
@@ -87820,7 +87884,7 @@ init_bun_compat();
87820
87884
  init_path_security();
87821
87885
  init_create_tool();
87822
87886
  import * as fs78 from "node:fs";
87823
- import * as path97 from "node:path";
87887
+ import * as path101 from "node:path";
87824
87888
  var DEFAULT_MAX_RESULTS = 100;
87825
87889
  var DEFAULT_MAX_LINES = 200;
87826
87890
  var REGEX_TIMEOUT_MS = 5000;
@@ -87856,11 +87920,11 @@ function containsWindowsAttacks3(str) {
87856
87920
  }
87857
87921
  function isPathInWorkspace3(filePath, workspace) {
87858
87922
  try {
87859
- const resolvedPath = path97.resolve(workspace, filePath);
87923
+ const resolvedPath = path101.resolve(workspace, filePath);
87860
87924
  const realWorkspace = fs78.realpathSync(workspace);
87861
87925
  const realResolvedPath = fs78.realpathSync(resolvedPath);
87862
- const relativePath = path97.relative(realWorkspace, realResolvedPath);
87863
- if (relativePath.startsWith("..") || path97.isAbsolute(relativePath)) {
87926
+ const relativePath = path101.relative(realWorkspace, realResolvedPath);
87927
+ if (relativePath.startsWith("..") || path101.isAbsolute(relativePath)) {
87864
87928
  return false;
87865
87929
  }
87866
87930
  return true;
@@ -87873,11 +87937,11 @@ function validatePathForRead2(filePath, workspace) {
87873
87937
  }
87874
87938
  function findRgInEnvPath() {
87875
87939
  const searchPath = process.env.PATH ?? "";
87876
- for (const dir of searchPath.split(path97.delimiter)) {
87940
+ for (const dir of searchPath.split(path101.delimiter)) {
87877
87941
  if (!dir)
87878
87942
  continue;
87879
87943
  const isWindows = process.platform === "win32";
87880
- const candidate = path97.join(dir, isWindows ? "rg.exe" : "rg");
87944
+ const candidate = path101.join(dir, isWindows ? "rg.exe" : "rg");
87881
87945
  if (fs78.existsSync(candidate))
87882
87946
  return candidate;
87883
87947
  }
@@ -87932,7 +87996,7 @@ async function ripgrepSearch(opts) {
87932
87996
  stderr: "pipe",
87933
87997
  cwd: opts.workspace
87934
87998
  });
87935
- const timeout = new Promise((resolve39) => setTimeout(() => resolve39("timeout"), REGEX_TIMEOUT_MS));
87999
+ const timeout = new Promise((resolve40) => setTimeout(() => resolve40("timeout"), REGEX_TIMEOUT_MS));
87936
88000
  const exitPromise = proc.exited;
87937
88001
  const result = await Promise.race([exitPromise, timeout]);
87938
88002
  if (result === "timeout") {
@@ -88007,8 +88071,8 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
88007
88071
  try {
88008
88072
  const entries = fs78.readdirSync(dir, { withFileTypes: true });
88009
88073
  for (const entry of entries) {
88010
- const fullPath = path97.join(dir, entry.name);
88011
- const relativePath = path97.relative(workspace, fullPath);
88074
+ const fullPath = path101.join(dir, entry.name);
88075
+ const relativePath = path101.relative(workspace, fullPath);
88012
88076
  if (!validatePathForRead2(fullPath, workspace)) {
88013
88077
  continue;
88014
88078
  }
@@ -88049,7 +88113,7 @@ async function fallbackSearch(opts) {
88049
88113
  const matches = [];
88050
88114
  let total = 0;
88051
88115
  for (const file3 of files) {
88052
- const fullPath = path97.join(opts.workspace, file3);
88116
+ const fullPath = path101.join(opts.workspace, file3);
88053
88117
  if (!validatePathForRead2(fullPath, opts.workspace)) {
88054
88118
  continue;
88055
88119
  }
@@ -88430,7 +88494,7 @@ init_zod();
88430
88494
  init_path_security();
88431
88495
  init_create_tool();
88432
88496
  import * as fs79 from "node:fs";
88433
- import * as path98 from "node:path";
88497
+ import * as path102 from "node:path";
88434
88498
  var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
88435
88499
  function containsWindowsAttacks4(str) {
88436
88500
  if (/:[^\\/]/.test(str))
@@ -88444,14 +88508,14 @@ function containsWindowsAttacks4(str) {
88444
88508
  }
88445
88509
  function isPathInWorkspace4(filePath, workspace) {
88446
88510
  try {
88447
- const resolvedPath = path98.resolve(workspace, filePath);
88511
+ const resolvedPath = path102.resolve(workspace, filePath);
88448
88512
  if (!fs79.existsSync(resolvedPath)) {
88449
88513
  return true;
88450
88514
  }
88451
88515
  const realWorkspace = fs79.realpathSync(workspace);
88452
88516
  const realResolvedPath = fs79.realpathSync(resolvedPath);
88453
- const relativePath = path98.relative(realWorkspace, realResolvedPath);
88454
- if (relativePath.startsWith("..") || path98.isAbsolute(relativePath)) {
88517
+ const relativePath = path102.relative(realWorkspace, realResolvedPath);
88518
+ if (relativePath.startsWith("..") || path102.isAbsolute(relativePath)) {
88455
88519
  return false;
88456
88520
  }
88457
88521
  return true;
@@ -88659,7 +88723,7 @@ var suggestPatch = createSwarmTool({
88659
88723
  });
88660
88724
  continue;
88661
88725
  }
88662
- const fullPath = path98.resolve(directory, change.file);
88726
+ const fullPath = path102.resolve(directory, change.file);
88663
88727
  if (!fs79.existsSync(fullPath)) {
88664
88728
  errors5.push({
88665
88729
  success: false,
@@ -88922,7 +88986,7 @@ var generate_mutants = createSwarmTool({
88922
88986
  init_spec_schema();
88923
88987
  init_create_tool();
88924
88988
  import * as fs80 from "node:fs";
88925
- import * as path99 from "node:path";
88989
+ import * as path103 from "node:path";
88926
88990
  var SPEC_FILE_NAME = "spec.md";
88927
88991
  var SWARM_DIR2 = ".swarm";
88928
88992
  var OBLIGATION_KEYWORDS2 = ["MUST", "SHALL", "SHOULD", "MAY"];
@@ -88975,7 +89039,7 @@ var lint_spec = createSwarmTool({
88975
89039
  async execute(_args, directory) {
88976
89040
  const errors5 = [];
88977
89041
  const warnings = [];
88978
- const specPath = path99.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
89042
+ const specPath = path103.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
88979
89043
  if (!fs80.existsSync(specPath)) {
88980
89044
  const result2 = {
88981
89045
  valid: false,
@@ -89046,12 +89110,12 @@ var lint_spec = createSwarmTool({
89046
89110
  // src/tools/mutation-test.ts
89047
89111
  init_zod();
89048
89112
  import * as fs81 from "node:fs";
89049
- import * as path101 from "node:path";
89113
+ import * as path105 from "node:path";
89050
89114
 
89051
89115
  // src/mutation/engine.ts
89052
89116
  import { spawnSync as spawnSync3 } from "node:child_process";
89053
89117
  import { unlinkSync as unlinkSync13, writeFileSync as writeFileSync20 } from "node:fs";
89054
- import * as path100 from "node:path";
89118
+ import * as path104 from "node:path";
89055
89119
 
89056
89120
  // src/mutation/equivalence.ts
89057
89121
  function isStaticallyEquivalent(originalCode, mutatedCode) {
@@ -89186,7 +89250,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
89186
89250
  let patchFile;
89187
89251
  try {
89188
89252
  const safeId2 = patch.id.replace(/[^a-zA-Z0-9_-]/g, "_");
89189
- patchFile = path100.join(workingDir, `.mutation_patch_${safeId2}.diff`);
89253
+ patchFile = path104.join(workingDir, `.mutation_patch_${safeId2}.diff`);
89190
89254
  try {
89191
89255
  writeFileSync20(patchFile, patch.patch);
89192
89256
  } catch (writeErr) {
@@ -89580,7 +89644,7 @@ var mutation_test = createSwarmTool({
89580
89644
  ];
89581
89645
  for (const filePath of uniquePaths) {
89582
89646
  try {
89583
- const resolvedPath = path101.resolve(cwd, filePath);
89647
+ const resolvedPath = path105.resolve(cwd, filePath);
89584
89648
  sourceFiles.set(filePath, fs81.readFileSync(resolvedPath, "utf-8"));
89585
89649
  } catch {}
89586
89650
  }
@@ -89600,7 +89664,7 @@ init_zod();
89600
89664
  init_manager2();
89601
89665
  init_detector();
89602
89666
  import * as fs82 from "node:fs";
89603
- import * as path102 from "node:path";
89667
+ import * as path106 from "node:path";
89604
89668
  init_create_tool();
89605
89669
  var MAX_FILE_SIZE2 = 2 * 1024 * 1024;
89606
89670
  var BINARY_CHECK_BYTES = 8192;
@@ -89666,7 +89730,7 @@ async function syntaxCheck(input, directory, config3) {
89666
89730
  if (languages?.length) {
89667
89731
  const lowerLangs = languages.map((l) => l.toLowerCase());
89668
89732
  filesToCheck = filesToCheck.filter((file3) => {
89669
- const ext = path102.extname(file3.path).toLowerCase();
89733
+ const ext = path106.extname(file3.path).toLowerCase();
89670
89734
  const langDef = getLanguageForExtension(ext);
89671
89735
  const fileProfile = getProfileForFile(file3.path);
89672
89736
  const langId = fileProfile?.id || langDef?.id;
@@ -89679,7 +89743,7 @@ async function syntaxCheck(input, directory, config3) {
89679
89743
  let skippedCount = 0;
89680
89744
  for (const fileInfo of filesToCheck) {
89681
89745
  const { path: filePath } = fileInfo;
89682
- const fullPath = path102.isAbsolute(filePath) ? filePath : path102.join(directory, filePath);
89746
+ const fullPath = path106.isAbsolute(filePath) ? filePath : path106.join(directory, filePath);
89683
89747
  const result = {
89684
89748
  path: filePath,
89685
89749
  language: "",
@@ -89728,7 +89792,7 @@ async function syntaxCheck(input, directory, config3) {
89728
89792
  results.push(result);
89729
89793
  continue;
89730
89794
  }
89731
- const ext = path102.extname(filePath).toLowerCase();
89795
+ const ext = path106.extname(filePath).toLowerCase();
89732
89796
  const langDef = getLanguageForExtension(ext);
89733
89797
  result.language = profile?.id || langDef?.id || "unknown";
89734
89798
  const errors5 = extractSyntaxErrors(parser, content);
@@ -89821,7 +89885,7 @@ init_utils();
89821
89885
  init_create_tool();
89822
89886
  init_path_security();
89823
89887
  import * as fs83 from "node:fs";
89824
- import * as path103 from "node:path";
89888
+ import * as path107 from "node:path";
89825
89889
  var MAX_TEXT_LENGTH = 200;
89826
89890
  var MAX_FILE_SIZE_BYTES11 = 1024 * 1024;
89827
89891
  var SUPPORTED_EXTENSIONS4 = new Set([
@@ -89887,9 +89951,9 @@ function validatePathsInput(paths, cwd) {
89887
89951
  return { error: "paths contains path traversal", resolvedPath: null };
89888
89952
  }
89889
89953
  try {
89890
- const resolvedPath = path103.resolve(paths);
89891
- const normalizedCwd = path103.resolve(cwd);
89892
- const normalizedResolved = path103.resolve(resolvedPath);
89954
+ const resolvedPath = path107.resolve(paths);
89955
+ const normalizedCwd = path107.resolve(cwd);
89956
+ const normalizedResolved = path107.resolve(resolvedPath);
89893
89957
  if (!normalizedResolved.startsWith(normalizedCwd)) {
89894
89958
  return {
89895
89959
  error: "paths must be within the current working directory",
@@ -89905,7 +89969,7 @@ function validatePathsInput(paths, cwd) {
89905
89969
  }
89906
89970
  }
89907
89971
  function isSupportedExtension(filePath) {
89908
- const ext = path103.extname(filePath).toLowerCase();
89972
+ const ext = path107.extname(filePath).toLowerCase();
89909
89973
  return SUPPORTED_EXTENSIONS4.has(ext);
89910
89974
  }
89911
89975
  function findSourceFiles3(dir, files = []) {
@@ -89920,16 +89984,16 @@ function findSourceFiles3(dir, files = []) {
89920
89984
  if (SKIP_DIRECTORIES5.has(entry)) {
89921
89985
  continue;
89922
89986
  }
89923
- const fullPath = path103.join(dir, entry);
89924
- let stat6;
89987
+ const fullPath = path107.join(dir, entry);
89988
+ let stat7;
89925
89989
  try {
89926
- stat6 = fs83.statSync(fullPath);
89990
+ stat7 = fs83.statSync(fullPath);
89927
89991
  } catch {
89928
89992
  continue;
89929
89993
  }
89930
- if (stat6.isDirectory()) {
89994
+ if (stat7.isDirectory()) {
89931
89995
  findSourceFiles3(fullPath, files);
89932
- } else if (stat6.isFile()) {
89996
+ } else if (stat7.isFile()) {
89933
89997
  if (isSupportedExtension(fullPath)) {
89934
89998
  files.push(fullPath);
89935
89999
  }
@@ -90026,13 +90090,13 @@ var todo_extract = createSwarmTool({
90026
90090
  return JSON.stringify(errorResult, null, 2);
90027
90091
  }
90028
90092
  const filesToScan = [];
90029
- const stat6 = fs83.statSync(scanPath);
90030
- if (stat6.isFile()) {
90093
+ const stat7 = fs83.statSync(scanPath);
90094
+ if (stat7.isFile()) {
90031
90095
  if (isSupportedExtension(scanPath)) {
90032
90096
  filesToScan.push(scanPath);
90033
90097
  } else {
90034
90098
  const errorResult = {
90035
- error: `unsupported file extension: ${path103.extname(scanPath)}`,
90099
+ error: `unsupported file extension: ${path107.extname(scanPath)}`,
90036
90100
  total: 0,
90037
90101
  byPriority: { high: 0, medium: 0, low: 0 },
90038
90102
  entries: []
@@ -90081,17 +90145,17 @@ init_schema();
90081
90145
  init_qa_gate_profile();
90082
90146
  init_gate_evidence();
90083
90147
  import * as fs86 from "node:fs";
90084
- import * as path106 from "node:path";
90148
+ import * as path110 from "node:path";
90085
90149
 
90086
90150
  // src/hooks/diff-scope.ts
90087
90151
  init_bun_compat();
90088
90152
  import * as fs85 from "node:fs";
90089
- import * as path105 from "node:path";
90153
+ import * as path109 from "node:path";
90090
90154
 
90091
90155
  // src/utils/gitignore-warning.ts
90092
90156
  init_bun_compat();
90093
90157
  import * as fs84 from "node:fs";
90094
- import * as path104 from "node:path";
90158
+ import * as path108 from "node:path";
90095
90159
  var _internals = { bunSpawn };
90096
90160
  var _swarmGitExcludedChecked = false;
90097
90161
  function fileCoversSwarm(content) {
@@ -90165,10 +90229,10 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
90165
90229
  const excludeRelPath = excludePathRaw.trim();
90166
90230
  if (!excludeRelPath)
90167
90231
  return;
90168
- const excludePath = path104.isAbsolute(excludeRelPath) ? excludeRelPath : path104.join(directory, excludeRelPath);
90232
+ const excludePath = path108.isAbsolute(excludeRelPath) ? excludeRelPath : path108.join(directory, excludeRelPath);
90169
90233
  if (checkIgnoreExitCode !== 0) {
90170
90234
  try {
90171
- fs84.mkdirSync(path104.dirname(excludePath), { recursive: true });
90235
+ fs84.mkdirSync(path108.dirname(excludePath), { recursive: true });
90172
90236
  let existing = "";
90173
90237
  try {
90174
90238
  existing = fs84.readFileSync(excludePath, "utf8");
@@ -90212,7 +90276,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
90212
90276
  var _internals2 = { bunSpawn };
90213
90277
  function getDeclaredScope(taskId, directory) {
90214
90278
  try {
90215
- const planPath = path105.join(directory, ".swarm", "plan.json");
90279
+ const planPath = path109.join(directory, ".swarm", "plan.json");
90216
90280
  if (!fs85.existsSync(planPath))
90217
90281
  return null;
90218
90282
  const raw = fs85.readFileSync(planPath, "utf-8");
@@ -90349,7 +90413,7 @@ var TIER_3_PATTERNS = [
90349
90413
  ];
90350
90414
  function matchesTier3Pattern(files) {
90351
90415
  for (const file3 of files) {
90352
- const fileName = path106.basename(file3);
90416
+ const fileName = path110.basename(file3);
90353
90417
  for (const pattern of TIER_3_PATTERNS) {
90354
90418
  if (pattern.test(fileName)) {
90355
90419
  return true;
@@ -90363,7 +90427,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
90363
90427
  if (hasActiveTurboMode()) {
90364
90428
  const resolvedDir2 = workingDirectory;
90365
90429
  try {
90366
- const planPath = path106.join(resolvedDir2, ".swarm", "plan.json");
90430
+ const planPath = path110.join(resolvedDir2, ".swarm", "plan.json");
90367
90431
  const planRaw = fs86.readFileSync(planPath, "utf-8");
90368
90432
  const plan = JSON.parse(planRaw);
90369
90433
  for (const planPhase of plan.phases ?? []) {
@@ -90433,7 +90497,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
90433
90497
  }
90434
90498
  try {
90435
90499
  const resolvedDir2 = workingDirectory;
90436
- const planPath = path106.join(resolvedDir2, ".swarm", "plan.json");
90500
+ const planPath = path110.join(resolvedDir2, ".swarm", "plan.json");
90437
90501
  const planRaw = fs86.readFileSync(planPath, "utf-8");
90438
90502
  const plan = JSON.parse(planRaw);
90439
90503
  for (const planPhase of plan.phases ?? []) {
@@ -90623,8 +90687,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
90623
90687
  };
90624
90688
  }
90625
90689
  }
90626
- normalizedDir = path106.normalize(args2.working_directory);
90627
- const pathParts = normalizedDir.split(path106.sep);
90690
+ normalizedDir = path110.normalize(args2.working_directory);
90691
+ const pathParts = normalizedDir.split(path110.sep);
90628
90692
  if (pathParts.includes("..")) {
90629
90693
  return {
90630
90694
  success: false,
@@ -90634,10 +90698,10 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
90634
90698
  ]
90635
90699
  };
90636
90700
  }
90637
- const resolvedDir = path106.resolve(normalizedDir);
90701
+ const resolvedDir = path110.resolve(normalizedDir);
90638
90702
  try {
90639
90703
  const realPath = fs86.realpathSync(resolvedDir);
90640
- const planPath = path106.join(realPath, ".swarm", "plan.json");
90704
+ const planPath = path110.join(realPath, ".swarm", "plan.json");
90641
90705
  if (!fs86.existsSync(planPath)) {
90642
90706
  return {
90643
90707
  success: false,
@@ -90669,8 +90733,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
90669
90733
  }
90670
90734
  if (args2.status === "in_progress") {
90671
90735
  try {
90672
- const evidencePath = path106.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
90673
- fs86.mkdirSync(path106.dirname(evidencePath), { recursive: true });
90736
+ const evidencePath = path110.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
90737
+ fs86.mkdirSync(path110.dirname(evidencePath), { recursive: true });
90674
90738
  const fd = fs86.openSync(evidencePath, "wx");
90675
90739
  let writeOk = false;
90676
90740
  try {
@@ -90694,7 +90758,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
90694
90758
  recoverTaskStateFromDelegations(args2.task_id);
90695
90759
  let phaseRequiresReviewer = true;
90696
90760
  try {
90697
- const planPath = path106.join(directory, ".swarm", "plan.json");
90761
+ const planPath = path110.join(directory, ".swarm", "plan.json");
90698
90762
  const planRaw = fs86.readFileSync(planPath, "utf-8");
90699
90763
  const plan = JSON.parse(planRaw);
90700
90764
  const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
@@ -91006,7 +91070,7 @@ init_ledger();
91006
91070
  init_manager();
91007
91071
  init_create_tool();
91008
91072
  import fs87 from "node:fs";
91009
- import path107 from "node:path";
91073
+ import path111 from "node:path";
91010
91074
  function derivePlanId5(plan) {
91011
91075
  return `${plan.swarm}-${plan.title}`.replace(/[^a-zA-Z0-9-_]/g, "_");
91012
91076
  }
@@ -91057,7 +91121,7 @@ async function executeWriteDriftEvidence(args2, directory) {
91057
91121
  entries: [evidenceEntry]
91058
91122
  };
91059
91123
  const filename = "drift-verifier.json";
91060
- const relativePath = path107.join("evidence", String(phase), filename);
91124
+ const relativePath = path111.join("evidence", String(phase), filename);
91061
91125
  let validatedPath;
91062
91126
  try {
91063
91127
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -91068,10 +91132,10 @@ async function executeWriteDriftEvidence(args2, directory) {
91068
91132
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
91069
91133
  }, null, 2);
91070
91134
  }
91071
- const evidenceDir = path107.dirname(validatedPath);
91135
+ const evidenceDir = path111.dirname(validatedPath);
91072
91136
  try {
91073
91137
  await fs87.promises.mkdir(evidenceDir, { recursive: true });
91074
- const tempPath = path107.join(evidenceDir, `.${filename}.tmp`);
91138
+ const tempPath = path111.join(evidenceDir, `.${filename}.tmp`);
91075
91139
  await fs87.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
91076
91140
  await fs87.promises.rename(tempPath, validatedPath);
91077
91141
  let snapshotInfo;
@@ -91168,7 +91232,7 @@ init_zod();
91168
91232
  init_utils2();
91169
91233
  init_create_tool();
91170
91234
  import fs88 from "node:fs";
91171
- import path108 from "node:path";
91235
+ import path112 from "node:path";
91172
91236
  function normalizeVerdict2(verdict) {
91173
91237
  switch (verdict) {
91174
91238
  case "APPROVED":
@@ -91216,7 +91280,7 @@ async function executeWriteHallucinationEvidence(args2, directory) {
91216
91280
  entries: [evidenceEntry]
91217
91281
  };
91218
91282
  const filename = "hallucination-guard.json";
91219
- const relativePath = path108.join("evidence", String(phase), filename);
91283
+ const relativePath = path112.join("evidence", String(phase), filename);
91220
91284
  let validatedPath;
91221
91285
  try {
91222
91286
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -91227,10 +91291,10 @@ async function executeWriteHallucinationEvidence(args2, directory) {
91227
91291
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
91228
91292
  }, null, 2);
91229
91293
  }
91230
- const evidenceDir = path108.dirname(validatedPath);
91294
+ const evidenceDir = path112.dirname(validatedPath);
91231
91295
  try {
91232
91296
  await fs88.promises.mkdir(evidenceDir, { recursive: true });
91233
- const tempPath = path108.join(evidenceDir, `.${filename}.tmp`);
91297
+ const tempPath = path112.join(evidenceDir, `.${filename}.tmp`);
91234
91298
  await fs88.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
91235
91299
  await fs88.promises.rename(tempPath, validatedPath);
91236
91300
  return JSON.stringify({
@@ -91279,7 +91343,7 @@ init_zod();
91279
91343
  init_utils2();
91280
91344
  init_create_tool();
91281
91345
  import fs89 from "node:fs";
91282
- import path109 from "node:path";
91346
+ import path113 from "node:path";
91283
91347
  function normalizeVerdict3(verdict) {
91284
91348
  switch (verdict) {
91285
91349
  case "PASS":
@@ -91353,7 +91417,7 @@ async function executeWriteMutationEvidence(args2, directory) {
91353
91417
  entries: [evidenceEntry]
91354
91418
  };
91355
91419
  const filename = "mutation-gate.json";
91356
- const relativePath = path109.join("evidence", String(phase), filename);
91420
+ const relativePath = path113.join("evidence", String(phase), filename);
91357
91421
  let validatedPath;
91358
91422
  try {
91359
91423
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -91364,10 +91428,10 @@ async function executeWriteMutationEvidence(args2, directory) {
91364
91428
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
91365
91429
  }, null, 2);
91366
91430
  }
91367
- const evidenceDir = path109.dirname(validatedPath);
91431
+ const evidenceDir = path113.dirname(validatedPath);
91368
91432
  try {
91369
91433
  await fs89.promises.mkdir(evidenceDir, { recursive: true });
91370
- const tempPath = path109.join(evidenceDir, `.${filename}.tmp`);
91434
+ const tempPath = path113.join(evidenceDir, `.${filename}.tmp`);
91371
91435
  await fs89.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
91372
91436
  await fs89.promises.rename(tempPath, validatedPath);
91373
91437
  return JSON.stringify({
@@ -91661,7 +91725,7 @@ async function initializeOpenCodeSwarm(ctx) {
91661
91725
  const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
91662
91726
  preflightTriggerManager = new PTM(automationConfig);
91663
91727
  const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
91664
- const swarmDir = path110.resolve(ctx.directory, ".swarm");
91728
+ const swarmDir = path114.resolve(ctx.directory, ".swarm");
91665
91729
  statusArtifact = new ASA(swarmDir);
91666
91730
  statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
91667
91731
  if (automationConfig.capabilities?.evidence_auto_summaries === true) {