opencode-swarm 7.4.2 → 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.2",
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",
@@ -23146,7 +23146,8 @@ function extractIncompleteTasksFromPlan(plan, maxChars = 500) {
23146
23146
  return null;
23147
23147
  const lines = incomplete.map((t) => {
23148
23148
  const deps = t.depends.length > 0 ? ` (depends: ${t.depends.join(", ")})` : "";
23149
- return `- [ ] ${t.id}: ${t.description} [${t.size.toUpperCase()}]${deps}`;
23149
+ const marker = t.status === "in_progress" ? " ← CURRENT" : "";
23150
+ return `- [ ] ${t.id}: ${t.description} [${t.size.toUpperCase()}]${deps}${marker}`;
23150
23151
  });
23151
23152
  const text = lines.join(`
23152
23153
  `);
@@ -62655,8 +62656,8 @@ ${JSON.stringify(symbolNames, null, 2)}`);
62655
62656
  var moduleRtn;
62656
62657
  var Module = moduleArg;
62657
62658
  var readyPromiseResolve, readyPromiseReject;
62658
- var readyPromise = new Promise((resolve21, reject) => {
62659
- readyPromiseResolve = resolve21;
62659
+ var readyPromise = new Promise((resolve22, reject) => {
62660
+ readyPromiseResolve = resolve22;
62660
62661
  readyPromiseReject = reject;
62661
62662
  });
62662
62663
  var ENVIRONMENT_IS_WEB = typeof window == "object";
@@ -62678,11 +62679,11 @@ ${JSON.stringify(symbolNames, null, 2)}`);
62678
62679
  throw toThrow;
62679
62680
  }, "quit_");
62680
62681
  var scriptDirectory = "";
62681
- function locateFile(path61) {
62682
+ function locateFile(path65) {
62682
62683
  if (Module["locateFile"]) {
62683
- return Module["locateFile"](path61, scriptDirectory);
62684
+ return Module["locateFile"](path65, scriptDirectory);
62684
62685
  }
62685
- return scriptDirectory + path61;
62686
+ return scriptDirectory + path65;
62686
62687
  }
62687
62688
  __name(locateFile, "locateFile");
62688
62689
  var readAsync, readBinary;
@@ -62736,13 +62737,13 @@ ${JSON.stringify(symbolNames, null, 2)}`);
62736
62737
  }
62737
62738
  readAsync = /* @__PURE__ */ __name(async (url3) => {
62738
62739
  if (isFileURI(url3)) {
62739
- return new Promise((resolve21, reject) => {
62740
+ return new Promise((resolve22, reject) => {
62740
62741
  var xhr = new XMLHttpRequest;
62741
62742
  xhr.open("GET", url3, true);
62742
62743
  xhr.responseType = "arraybuffer";
62743
62744
  xhr.onload = () => {
62744
62745
  if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
62745
- resolve21(xhr.response);
62746
+ resolve22(xhr.response);
62746
62747
  return;
62747
62748
  }
62748
62749
  reject(xhr.status);
@@ -62962,10 +62963,10 @@ ${JSON.stringify(symbolNames, null, 2)}`);
62962
62963
  __name(receiveInstantiationResult, "receiveInstantiationResult");
62963
62964
  var info2 = getWasmImports();
62964
62965
  if (Module["instantiateWasm"]) {
62965
- return new Promise((resolve21, reject) => {
62966
+ return new Promise((resolve22, reject) => {
62966
62967
  Module["instantiateWasm"](info2, (mod, inst) => {
62967
62968
  receiveInstance(mod, inst);
62968
- resolve21(mod.exports);
62969
+ resolve22(mod.exports);
62969
62970
  });
62970
62971
  });
62971
62972
  }
@@ -64431,13 +64432,13 @@ __export(exports_runtime, {
64431
64432
  getInitializedLanguages: () => getInitializedLanguages,
64432
64433
  clearParserCache: () => clearParserCache
64433
64434
  });
64434
- import * as path61 from "node:path";
64435
+ import * as path65 from "node:path";
64435
64436
  import { fileURLToPath as fileURLToPath2 } from "node:url";
64436
64437
  async function initTreeSitter() {
64437
64438
  if (treeSitterInitialized) {
64438
64439
  return;
64439
64440
  }
64440
- const thisDir = path61.dirname(fileURLToPath2(import.meta.url));
64441
+ const thisDir = path65.dirname(fileURLToPath2(import.meta.url));
64441
64442
  const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/lang");
64442
64443
  if (isSource) {
64443
64444
  await Parser.init();
@@ -64445,7 +64446,7 @@ async function initTreeSitter() {
64445
64446
  const grammarsDir = getGrammarsDirAbsolute();
64446
64447
  await Parser.init({
64447
64448
  locateFile(scriptName) {
64448
- return path61.join(grammarsDir, scriptName);
64449
+ return path65.join(grammarsDir, scriptName);
64449
64450
  }
64450
64451
  });
64451
64452
  }
@@ -64466,11 +64467,11 @@ function getWasmFileName(languageId) {
64466
64467
  return `tree-sitter-${sanitized}.wasm`;
64467
64468
  }
64468
64469
  function getGrammarsDirAbsolute() {
64469
- const thisDir = path61.dirname(fileURLToPath2(import.meta.url));
64470
+ const thisDir = path65.dirname(fileURLToPath2(import.meta.url));
64470
64471
  const normalized = thisDir.replace(/\\/g, "/");
64471
64472
  const isSource = normalized.endsWith("/src/lang");
64472
64473
  const isCliBundle = normalized.endsWith("/cli");
64473
- 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");
64474
64475
  }
64475
64476
  async function loadGrammar(languageId) {
64476
64477
  if (typeof languageId !== "string" || languageId.length > 100) {
@@ -64486,9 +64487,9 @@ async function loadGrammar(languageId) {
64486
64487
  await initTreeSitter();
64487
64488
  const parser = new Parser;
64488
64489
  const wasmFileName = getWasmFileName(normalizedId);
64489
- const wasmPath = path61.join(getGrammarsDirAbsolute(), wasmFileName);
64490
- const { existsSync: existsSync31 } = await import("node:fs");
64491
- if (!existsSync31(wasmPath)) {
64490
+ const wasmPath = path65.join(getGrammarsDirAbsolute(), wasmFileName);
64491
+ const { existsSync: existsSync33 } = await import("node:fs");
64492
+ if (!existsSync33(wasmPath)) {
64492
64493
  throw new Error(`Grammar file not found for ${languageId}: ${wasmPath}
64493
64494
  Make sure to run 'bun run build' to copy grammar files to dist/lang/grammars/`);
64494
64495
  }
@@ -64521,7 +64522,7 @@ async function isGrammarAvailable(languageId) {
64521
64522
  }
64522
64523
  try {
64523
64524
  const wasmFileName = getWasmFileName(normalizedId);
64524
- const wasmPath = path61.join(getGrammarsDirAbsolute(), wasmFileName);
64525
+ const wasmPath = path65.join(getGrammarsDirAbsolute(), wasmFileName);
64525
64526
  const { statSync: statSync19 } = await import("node:fs");
64526
64527
  statSync19(wasmPath);
64527
64528
  return true;
@@ -64580,13 +64581,13 @@ __export(exports_doc_scan, {
64580
64581
  import * as crypto7 from "node:crypto";
64581
64582
  import * as fs45 from "node:fs";
64582
64583
  import { mkdir as mkdir10, readFile as readFile10, writeFile as writeFile9 } from "node:fs/promises";
64583
- import * as path63 from "node:path";
64584
+ import * as path67 from "node:path";
64584
64585
  function normalizeSeparators(filePath) {
64585
64586
  return filePath.replace(/\\/g, "/");
64586
64587
  }
64587
64588
  function matchesDocPattern(filePath, patterns) {
64588
64589
  const normalizedPath = normalizeSeparators(filePath);
64589
- const basename9 = path63.basename(filePath);
64590
+ const basename9 = path67.basename(filePath);
64590
64591
  for (const pattern of patterns) {
64591
64592
  if (!pattern.includes("/") && !pattern.includes("\\")) {
64592
64593
  if (basename9 === pattern) {
@@ -64642,7 +64643,7 @@ function stripMarkdown(text) {
64642
64643
  return text.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/^\s*[-*•]\s+/gm, "").replace(/^\s*\d+\.\s+/gm, "").trim();
64643
64644
  }
64644
64645
  async function scanDocIndex(directory) {
64645
- const manifestPath = path63.join(directory, ".swarm", "doc-manifest.json");
64646
+ const manifestPath = path67.join(directory, ".swarm", "doc-manifest.json");
64646
64647
  const defaultPatterns = DocsConfigSchema.parse({}).doc_patterns;
64647
64648
  const extraPatterns = [
64648
64649
  "ARCHITECTURE.md",
@@ -64659,9 +64660,9 @@ async function scanDocIndex(directory) {
64659
64660
  let cacheValid = true;
64660
64661
  for (const file3 of existingManifest.files) {
64661
64662
  try {
64662
- const fullPath = path63.join(directory, file3.path);
64663
- const stat5 = fs45.statSync(fullPath);
64664
- 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) {
64665
64666
  cacheValid = false;
64666
64667
  break;
64667
64668
  }
@@ -64689,14 +64690,14 @@ async function scanDocIndex(directory) {
64689
64690
  }
64690
64691
  const entries = rawEntries.filter((e) => typeof e === "string");
64691
64692
  for (const entry of entries) {
64692
- const fullPath = path63.join(directory, entry);
64693
- let stat5;
64693
+ const fullPath = path67.join(directory, entry);
64694
+ let stat6;
64694
64695
  try {
64695
- stat5 = fs45.statSync(fullPath);
64696
+ stat6 = fs45.statSync(fullPath);
64696
64697
  } catch {
64697
64698
  continue;
64698
64699
  }
64699
- if (!stat5.isFile())
64700
+ if (!stat6.isFile())
64700
64701
  continue;
64701
64702
  const pathParts = normalizeSeparators(entry).split("/");
64702
64703
  let skipThisFile = false;
@@ -64725,7 +64726,7 @@ async function scanDocIndex(directory) {
64725
64726
  } catch {
64726
64727
  continue;
64727
64728
  }
64728
- const { title, summary } = extractTitleAndSummary(content, path63.basename(entry));
64729
+ const { title, summary } = extractTitleAndSummary(content, path67.basename(entry));
64729
64730
  const lineCount = content.split(`
64730
64731
  `).length;
64731
64732
  discoveredFiles.push({
@@ -64733,7 +64734,7 @@ async function scanDocIndex(directory) {
64733
64734
  title,
64734
64735
  summary,
64735
64736
  lines: lineCount,
64736
- mtime: stat5.mtimeMs
64737
+ mtime: stat6.mtimeMs
64737
64738
  });
64738
64739
  }
64739
64740
  discoveredFiles.sort((a, b) => a.path.toLowerCase().localeCompare(b.path.toLowerCase()));
@@ -64751,7 +64752,7 @@ async function scanDocIndex(directory) {
64751
64752
  files: discoveredFiles
64752
64753
  };
64753
64754
  try {
64754
- await mkdir10(path63.dirname(manifestPath), { recursive: true });
64755
+ await mkdir10(path67.dirname(manifestPath), { recursive: true });
64755
64756
  await writeFile9(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
64756
64757
  } catch {}
64757
64758
  return { manifest, cached: false };
@@ -64790,7 +64791,7 @@ function extractConstraintsFromContent(content) {
64790
64791
  return constraints;
64791
64792
  }
64792
64793
  async function extractDocConstraints(directory, taskFiles, taskDescription) {
64793
- const manifestPath = path63.join(directory, ".swarm", "doc-manifest.json");
64794
+ const manifestPath = path67.join(directory, ".swarm", "doc-manifest.json");
64794
64795
  let manifest;
64795
64796
  try {
64796
64797
  const content = await readFile10(manifestPath, "utf-8");
@@ -64816,7 +64817,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
64816
64817
  }
64817
64818
  let fullContent;
64818
64819
  try {
64819
- fullContent = await readFile10(path63.join(directory, docFile.path), "utf-8");
64820
+ fullContent = await readFile10(path67.join(directory, docFile.path), "utf-8");
64820
64821
  } catch {
64821
64822
  skippedCount++;
64822
64823
  continue;
@@ -64839,7 +64840,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
64839
64840
  tier: "swarm",
64840
64841
  lesson: constraint,
64841
64842
  category: "architecture",
64842
- tags: ["doc-scan", path63.basename(docFile.path)],
64843
+ tags: ["doc-scan", path67.basename(docFile.path)],
64843
64844
  scope: "global",
64844
64845
  confidence: 0.5,
64845
64846
  status: "candidate",
@@ -64912,7 +64913,7 @@ var init_doc_scan = __esm(() => {
64912
64913
  }
64913
64914
  } catch {}
64914
64915
  if (force) {
64915
- const manifestPath = path63.join(directory, ".swarm", "doc-manifest.json");
64916
+ const manifestPath = path67.join(directory, ".swarm", "doc-manifest.json");
64916
64917
  try {
64917
64918
  fs45.unlinkSync(manifestPath);
64918
64919
  } catch {}
@@ -65103,9 +65104,9 @@ __export(exports_curator_drift, {
65103
65104
  buildDriftInjectionText: () => buildDriftInjectionText
65104
65105
  });
65105
65106
  import * as fs48 from "node:fs";
65106
- import * as path66 from "node:path";
65107
+ import * as path70 from "node:path";
65107
65108
  async function readPriorDriftReports(directory) {
65108
- const swarmDir = path66.join(directory, ".swarm");
65109
+ const swarmDir = path70.join(directory, ".swarm");
65109
65110
  const entries = await fs48.promises.readdir(swarmDir).catch(() => null);
65110
65111
  if (entries === null)
65111
65112
  return [];
@@ -65132,7 +65133,7 @@ async function readPriorDriftReports(directory) {
65132
65133
  async function writeDriftReport(directory, report) {
65133
65134
  const filename = `${DRIFT_REPORT_PREFIX}${report.phase}.json`;
65134
65135
  const filePath = validateSwarmPath(directory, filename);
65135
- const swarmDir = path66.dirname(filePath);
65136
+ const swarmDir = path70.dirname(filePath);
65136
65137
  await fs48.promises.mkdir(swarmDir, { recursive: true });
65137
65138
  try {
65138
65139
  await fs48.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
@@ -65266,7 +65267,7 @@ var init_curator_drift = __esm(() => {
65266
65267
  // src/index.ts
65267
65268
  init_package();
65268
65269
  init_agents2();
65269
- import * as path110 from "node:path";
65270
+ import * as path114 from "node:path";
65270
65271
 
65271
65272
  // src/background/index.ts
65272
65273
  init_event_bus();
@@ -65939,6 +65940,7 @@ function createCcCommandInterceptHook(config3 = {}) {
65939
65940
  }
65940
65941
  // src/hooks/compaction-customizer.ts
65941
65942
  init_manager();
65943
+ init_state();
65942
65944
  init_utils2();
65943
65945
  import * as fs33 from "node:fs";
65944
65946
  import { join as join45 } from "node:path";
@@ -65995,6 +65997,7 @@ function createCompactionCustomizerHook(config3, directory) {
65995
65997
  }
65996
65998
  } catch {}
65997
65999
  output.context.push("[KNOWLEDGE TOOLS] You have persistent knowledge tools: knowledge_recall (search for relevant past decisions), knowledge_add (store a new lesson), knowledge_remove (delete outdated entries). Use knowledge_recall when past context would help.");
66000
+ await buildRehydrationCache(directory);
65998
66001
  })
65999
66002
  };
66000
66003
  }
@@ -67397,16 +67400,16 @@ ${originalText}`;
67397
67400
  }
67398
67401
  // src/hooks/repo-graph-builder.ts
67399
67402
  init_constants();
67400
- import * as path54 from "node:path";
67403
+ import { realpathSync as realpathSync8 } from "node:fs";
67404
+ import * as path58 from "node:path";
67401
67405
 
67402
- // src/tools/repo-graph.ts
67403
- init_utils2();
67406
+ // src/tools/repo-graph/builder.ts
67404
67407
  init_path_security();
67405
67408
  import * as fsSync3 from "node:fs";
67406
- import { constants as constants4, existsSync as existsSync29, realpathSync as realpathSync6 } from "node:fs";
67409
+ import { existsSync as existsSync29, realpathSync as realpathSync6 } from "node:fs";
67407
67410
  import * as fsPromises5 from "node:fs/promises";
67408
67411
  import * as os7 from "node:os";
67409
- import * as path53 from "node:path";
67412
+ import * as path54 from "node:path";
67410
67413
 
67411
67414
  // src/utils/timeout.ts
67412
67415
  async function withTimeout(promise3, ms, timeoutError) {
@@ -67766,17 +67769,38 @@ var symbols = createSwarmTool({
67766
67769
  }
67767
67770
  });
67768
67771
 
67769
- // src/tools/repo-graph.ts
67770
- var WINDOWS_RENAME_MAX_RETRIES2 = 3;
67771
- 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";
67772
67776
  function normalizeGraphPath(filePath) {
67773
67777
  return path53.normalize(filePath).replace(/\\/g, "/");
67774
67778
  }
67775
- var REPO_GRAPH_FILENAME = "repo-graph.json";
67776
- var GRAPH_SCHEMA_VERSION = "1.0.0";
67777
- var graphCache = new Map;
67778
- var dirtyFlags = new Map;
67779
- 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();
67780
67804
  function validateWorkspace(workspace) {
67781
67805
  if (!workspace || typeof workspace !== "string" || workspace.trim() === "") {
67782
67806
  throw new Error("Invalid workspace: must be a non-empty string");
@@ -67864,309 +67888,8 @@ function validateGraphEdge(edge) {
67864
67888
  throw new Error("Invalid edge: control characters detected");
67865
67889
  }
67866
67890
  }
67867
- function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
67868
- if (containsControlChars(specifier)) {
67869
- return null;
67870
- }
67871
- if (specifier.startsWith("/") || specifier.startsWith("\\")) {
67872
- return null;
67873
- }
67874
- if (/^[A-Za-z]:[/\\]/.test(specifier)) {
67875
- return null;
67876
- }
67877
- if (specifier.startsWith("http://") || specifier.startsWith("https://")) {
67878
- return null;
67879
- }
67880
- try {
67881
- if (specifier.startsWith(".")) {
67882
- const sourceDir = path53.dirname(sourceFile);
67883
- let resolved = path53.resolve(sourceDir, specifier);
67884
- let realResolved;
67885
- try {
67886
- realResolved = realpathSync6(resolved);
67887
- } catch {
67888
- realResolved = resolved;
67889
- }
67890
- let realRoot;
67891
- try {
67892
- realRoot = realpathSync6(workspaceRoot);
67893
- } catch {
67894
- realRoot = path53.normalize(workspaceRoot);
67895
- }
67896
- if (!existsSync29(resolved)) {
67897
- const EXTENSIONS = [
67898
- ".ts",
67899
- ".tsx",
67900
- ".js",
67901
- ".jsx",
67902
- ".mjs",
67903
- ".cjs",
67904
- ".py",
67905
- ".json"
67906
- ];
67907
- let found = null;
67908
- for (const ext of EXTENSIONS) {
67909
- const candidate = resolved + ext;
67910
- if (existsSync29(candidate)) {
67911
- found = candidate;
67912
- break;
67913
- }
67914
- }
67915
- if (found) {
67916
- try {
67917
- realResolved = realpathSync6(found);
67918
- } catch {
67919
- realResolved = found;
67920
- }
67921
- resolved = found;
67922
- } else {
67923
- return null;
67924
- }
67925
- }
67926
- const normalizedResolved = path53.normalize(realResolved);
67927
- const normalizedRoot = path53.normalize(realRoot);
67928
- if (!normalizedResolved.startsWith(normalizedRoot + path53.sep) && normalizedResolved !== normalizedRoot) {
67929
- return null;
67930
- }
67931
- return resolved;
67932
- }
67933
- return null;
67934
- } catch {
67935
- return null;
67936
- }
67937
- }
67938
- function createEmptyGraph(workspaceRoot) {
67939
- return {
67940
- schema_version: GRAPH_SCHEMA_VERSION,
67941
- workspaceRoot: path53.normalize(workspaceRoot),
67942
- nodes: {},
67943
- edges: [],
67944
- metadata: {
67945
- generatedAt: new Date().toISOString(),
67946
- generator: "repo-graph",
67947
- nodeCount: 0,
67948
- edgeCount: 0
67949
- }
67950
- };
67951
- }
67952
- function updateGraphMetadata(graph) {
67953
- graph.metadata = {
67954
- generatedAt: new Date().toISOString(),
67955
- generator: "repo-graph",
67956
- nodeCount: Object.keys(graph.nodes).length,
67957
- edgeCount: graph.edges.length
67958
- };
67959
- }
67960
- function upsertNode(graph, node) {
67961
- validateGraphNode(node);
67962
- const key = normalizeGraphPath(node.filePath);
67963
- graph.nodes[key] = node;
67964
- updateGraphMetadata(graph);
67965
- }
67966
- function addEdge(graph, edge) {
67967
- validateGraphEdge(edge);
67968
- const exists = graph.edges.some((e) => e.source === edge.source && e.target === edge.target && e.importSpecifier === edge.importSpecifier);
67969
- if (!exists) {
67970
- graph.edges.push(edge);
67971
- updateGraphMetadata(graph);
67972
- }
67973
- }
67974
- function getCachedGraph(workspace) {
67975
- return graphCache.get(path53.normalize(workspace));
67976
- }
67977
- function setCachedGraph(workspace, graph, mtime) {
67978
- const normalized = path53.normalize(workspace);
67979
- graphCache.set(normalized, graph);
67980
- dirtyFlags.set(normalized, false);
67981
- if (mtime !== undefined) {
67982
- mtimeCache.set(normalized, mtime);
67983
- }
67984
- }
67985
- function isDirty(workspace) {
67986
- return dirtyFlags.get(path53.normalize(workspace)) ?? false;
67987
- }
67988
- function clearCache(workspace) {
67989
- const normalized = path53.normalize(workspace);
67990
- graphCache.delete(normalized);
67991
- dirtyFlags.delete(normalized);
67992
- mtimeCache.delete(normalized);
67993
- }
67994
- function getGraphPath(workspace) {
67995
- validateWorkspace(workspace);
67996
- const basePath = validateSwarmPath(workspace, REPO_GRAPH_FILENAME);
67997
- validateSymlinkBoundary(basePath, workspace);
67998
- return basePath;
67999
- }
68000
- async function loadGraph(workspace) {
68001
- validateWorkspace(workspace);
68002
- const normalized = path53.normalize(workspace);
68003
- const cached3 = getCachedGraph(normalized);
68004
- if (cached3 && !isDirty(normalized)) {
68005
- try {
68006
- const graphPath = getGraphPath(workspace);
68007
- if (existsSync29(graphPath)) {
68008
- const stats = await fsPromises5.stat(graphPath);
68009
- const cachedMtime = mtimeCache.get(normalized);
68010
- if (cachedMtime !== undefined && stats.mtimeMs !== cachedMtime) {
68011
- clearCache(normalized);
68012
- } else {
68013
- return cached3;
68014
- }
68015
- } else {
68016
- clearCache(normalized);
68017
- }
68018
- } catch {
68019
- clearCache(normalized);
68020
- }
68021
- }
68022
- try {
68023
- const graphPath = getGraphPath(workspace);
68024
- if (!existsSync29(graphPath)) {
68025
- return null;
68026
- }
68027
- const stats = await fsPromises5.stat(graphPath);
68028
- const content = await fsPromises5.readFile(graphPath, "utf-8");
68029
- if (content.includes("\x00") || content.includes("�")) {
68030
- throw Object.assign(new Error("repo-graph.json contains null bytes or invalid encoding"), { code: "CORRUPTION" });
68031
- }
68032
- let parsed;
68033
- try {
68034
- parsed = JSON.parse(content);
68035
- } catch {
68036
- throw Object.assign(new Error("repo-graph.json contains invalid JSON"), {
68037
- code: "CORRUPTION"
68038
- });
68039
- }
68040
- if (!parsed.schema_version) {
68041
- throw Object.assign(new Error("repo-graph.json missing schema_version"), {
68042
- code: "CORRUPTION"
68043
- });
68044
- }
68045
- if (!parsed.nodes || typeof parsed.nodes !== "object") {
68046
- throw Object.assign(new Error("repo-graph.json missing or invalid nodes"), { code: "CORRUPTION" });
68047
- }
68048
- if (!Array.isArray(parsed.edges)) {
68049
- throw Object.assign(new Error("repo-graph.json missing or invalid edges"), { code: "CORRUPTION" });
68050
- }
68051
- for (const [key, node] of Object.entries(parsed.nodes)) {
68052
- if (!key || typeof key !== "string") {
68053
- throw Object.assign(new Error("repo-graph.json contains invalid node key"), { code: "CORRUPTION" });
68054
- }
68055
- try {
68056
- validateGraphNode(node);
68057
- } catch (err2) {
68058
- const msg = err2 instanceof Error ? err2.message : "Invalid node structure";
68059
- throw Object.assign(new Error(`repo-graph.json node validation failed: ${msg}`), { code: "CORRUPTION" });
68060
- }
68061
- }
68062
- for (const edge of parsed.edges) {
68063
- try {
68064
- validateGraphEdge(edge);
68065
- } catch (err2) {
68066
- const msg = err2 instanceof Error ? err2.message : "Invalid edge structure";
68067
- throw Object.assign(new Error(`repo-graph.json edge validation failed: ${msg}`), { code: "CORRUPTION" });
68068
- }
68069
- }
68070
- 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") {
68071
- throw Object.assign(new Error("repo-graph.json missing or invalid metadata"), { code: "CORRUPTION" });
68072
- }
68073
- setCachedGraph(normalized, parsed, stats.mtimeMs);
68074
- return parsed;
68075
- } catch (error93) {
68076
- if (error93 instanceof Error && "code" in error93 && error93.code === "CORRUPTION") {
68077
- throw error93;
68078
- }
68079
- if (error93 instanceof Error && "code" in error93 && error93.code === "ENOENT") {
68080
- return null;
68081
- }
68082
- throw error93;
68083
- }
68084
- }
68085
- async function saveGraph(workspace, graph, options) {
68086
- validateWorkspace(workspace);
68087
- if (!graph.schema_version) {
68088
- throw new Error("Graph must have schema_version");
68089
- }
68090
- if (!graph.nodes || typeof graph.nodes !== "object") {
68091
- throw new Error("Graph must have nodes object");
68092
- }
68093
- if (!Array.isArray(graph.edges)) {
68094
- throw new Error("Graph must have edges array");
68095
- }
68096
- const normalizedWorkspace = path53.normalize(workspace);
68097
- let realWorkspace;
68098
- try {
68099
- realWorkspace = realpathSync6(workspace);
68100
- } catch {
68101
- realWorkspace = normalizedWorkspace;
68102
- }
68103
- const normalizedGraphRoot = path53.normalize(graph.workspaceRoot);
68104
- let realGraphRoot;
68105
- try {
68106
- realGraphRoot = realpathSync6(graph.workspaceRoot);
68107
- } catch {
68108
- realGraphRoot = normalizedGraphRoot;
68109
- }
68110
- if (path53.normalize(realWorkspace) !== path53.normalize(realGraphRoot)) {
68111
- throw new Error(`Graph workspaceRoot mismatch: graph was built for "${graph.workspaceRoot}" but save was called for "${workspace}"`);
68112
- }
68113
- const normalized = normalizedWorkspace;
68114
- const graphPath = getGraphPath(workspace);
68115
- updateGraphMetadata(graph);
68116
- const tempPath = `${graphPath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
68117
- await fsPromises5.mkdir(path53.dirname(tempPath), { recursive: true });
68118
- let lastError = null;
68119
- try {
68120
- if (options?.createAtomic) {
68121
- try {
68122
- const handle2 = await fsPromises5.open(tempPath, "wx", 420);
68123
- await handle2.writeFile(JSON.stringify(graph, null, 2), "utf-8");
68124
- await handle2.close();
68125
- } catch (error93) {
68126
- if (error93 instanceof Error && "code" in error93 && error93.code === "EEXIST") {
68127
- throw new Error("file already exists");
68128
- }
68129
- throw error93;
68130
- }
68131
- } else {
68132
- await fsPromises5.writeFile(tempPath, JSON.stringify(graph, null, 2), "utf-8");
68133
- }
68134
- if (options?.createAtomic) {
68135
- try {
68136
- await fsPromises5.copyFile(tempPath, graphPath, constants4.COPYFILE_EXCL);
68137
- } catch (error93) {
68138
- lastError = error93 instanceof Error ? error93 : new Error(String(error93));
68139
- throw lastError;
68140
- }
68141
- } else {
68142
- let retries = 0;
68143
- while (retries < WINDOWS_RENAME_MAX_RETRIES2) {
68144
- try {
68145
- await fsPromises5.rename(tempPath, graphPath);
68146
- break;
68147
- } catch (error93) {
68148
- lastError = error93 instanceof Error ? error93 : new Error(String(error93));
68149
- if (lastError instanceof Error && "code" in lastError && lastError.code === "EEXIST" && retries < WINDOWS_RENAME_MAX_RETRIES2 - 1) {
68150
- retries++;
68151
- await new Promise((resolve18) => setTimeout(resolve18, WINDOWS_RENAME_RETRY_DELAY_MS2));
68152
- continue;
68153
- }
68154
- throw lastError;
68155
- }
68156
- }
68157
- }
68158
- } finally {
68159
- try {
68160
- await fsPromises5.unlink(tempPath);
68161
- } catch (error93) {
68162
- if (error93 instanceof Error && "code" in error93 && error93.code !== "ENOENT") {
68163
- error48(`Failed to clean up temp file ${tempPath}:`, error93);
68164
- }
68165
- }
68166
- }
68167
- const stats = await fsPromises5.stat(graphPath);
68168
- setCachedGraph(normalized, graph, stats.mtimeMs);
68169
- }
67891
+
67892
+ // src/tools/repo-graph/builder.ts
68170
67893
  var SKIP_DIRECTORIES2 = new Set([
68171
67894
  "node_modules",
68172
67895
  ".git",
@@ -68193,17 +67916,111 @@ var SUPPORTED_EXTENSIONS = [
68193
67916
  var DEFAULT_WALK_FILE_CAP = 1e4;
68194
67917
  var DEFAULT_WALK_BUDGET_MS = 5000;
68195
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
+ }
68196
68013
  function isRefusedWorkspaceRoot(target) {
68197
68014
  let resolved;
68198
68015
  try {
68199
68016
  resolved = realpathSync6(target);
68200
68017
  } catch {
68201
- resolved = path53.resolve(target);
68018
+ resolved = path54.resolve(target);
68202
68019
  }
68203
68020
  const refused = new Set;
68204
68021
  const add = (p) => {
68205
68022
  if (typeof p === "string" && p.length > 0) {
68206
- refused.add(path53.resolve(p));
68023
+ refused.add(path54.resolve(p));
68207
68024
  }
68208
68025
  };
68209
68026
  add(os7.homedir());
@@ -68218,15 +68035,6 @@ function isRefusedWorkspaceRoot(target) {
68218
68035
  }
68219
68036
  return refused.has(resolved);
68220
68037
  }
68221
- var EXTENSION_TO_LANGUAGE = {
68222
- ".ts": "typescript",
68223
- ".tsx": "typescript",
68224
- ".js": "javascript",
68225
- ".jsx": "javascript",
68226
- ".mjs": "javascript",
68227
- ".cjs": "javascript",
68228
- ".py": "python"
68229
- };
68230
68038
  function parseFileImports(content) {
68231
68039
  const imports = [];
68232
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;
@@ -68322,7 +68130,7 @@ async function findSourceFilesAsync(dir, stats, options) {
68322
68130
  ctx.stats.skippedDirs++;
68323
68131
  continue;
68324
68132
  }
68325
- const fullPath = path53.join(current, entry.name);
68133
+ const fullPath = path54.join(current, entry.name);
68326
68134
  if (entry.isSymbolicLink() && !ctx.followSymlinks) {
68327
68135
  ctx.stats.skippedDirs++;
68328
68136
  continue;
@@ -68330,7 +68138,7 @@ async function findSourceFilesAsync(dir, stats, options) {
68330
68138
  if (entry.isDirectory()) {
68331
68139
  queue.push(fullPath);
68332
68140
  } else if (entry.isFile()) {
68333
- const ext = path53.extname(fullPath).toLowerCase();
68141
+ const ext = path54.extname(fullPath).toLowerCase();
68334
68142
  if (SUPPORTED_EXTENSIONS.includes(ext)) {
68335
68143
  files.push(fullPath);
68336
68144
  }
@@ -68347,11 +68155,11 @@ async function findSourceFilesAsync(dir, stats, options) {
68347
68155
  return files;
68348
68156
  }
68349
68157
  function toModuleName(filePath, workspaceRoot) {
68350
- const relative9 = path53.relative(workspaceRoot, filePath);
68351
- return relative9.split(path53.sep).join("/");
68158
+ const relative9 = path54.relative(workspaceRoot, filePath);
68159
+ return relative9.split(path54.sep).join("/");
68352
68160
  }
68353
68161
  function getLanguage(filePath) {
68354
- const ext = path53.extname(filePath).toLowerCase();
68162
+ const ext = path54.extname(filePath).toLowerCase();
68355
68163
  return EXTENSION_TO_LANGUAGE[ext] ?? "unknown";
68356
68164
  }
68357
68165
  function isBinaryContent(content) {
@@ -68360,13 +68168,67 @@ function isBinaryContent(content) {
68360
68168
  }
68361
68169
  return false;
68362
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
+ }
68363
68225
  async function buildWorkspaceGraphAsync(workspaceRoot, options) {
68364
68226
  validateWorkspace(workspaceRoot);
68365
68227
  const maxFileSize = options?.maxFileSizeBytes ?? 1024 * 1024;
68366
68228
  const maxFiles = options?.maxFiles ?? DEFAULT_WALK_FILE_CAP;
68367
68229
  const walkBudgetMs = options?.walkBudgetMs ?? DEFAULT_WALK_BUDGET_MS;
68368
68230
  const followSymlinks = options?.followSymlinks ?? false;
68369
- const absoluteRoot = path53.resolve(workspaceRoot);
68231
+ const absoluteRoot = path54.resolve(workspaceRoot);
68370
68232
  if (!existsSync29(absoluteRoot)) {
68371
68233
  throw new Error(`Workspace directory does not exist: ${workspaceRoot}`);
68372
68234
  }
@@ -68421,60 +68283,225 @@ async function buildWorkspaceGraphAsync(workspaceRoot, options) {
68421
68283
  }
68422
68284
  return graph;
68423
68285
  }
68424
- function scanFile(filePath, absoluteRoot, maxFileSize) {
68425
- let content;
68426
- 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
+ }
68427
68355
  try {
68428
- fileStats = fsSync3.statSync(filePath);
68429
- if (fileStats.size > maxFileSize) {
68430
- return { node: null, edges: [] };
68356
+ const graphPath = getGraphPath(workspace);
68357
+ if (!existsSync30(graphPath)) {
68358
+ return null;
68431
68359
  }
68432
- 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);
68433
68433
  } catch {
68434
- return { node: null, edges: [] };
68434
+ realWorkspace = normalizedWorkspace;
68435
68435
  }
68436
- if (isBinaryContent(content)) {
68437
- 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;
68438
68442
  }
68439
- const ext = path53.extname(filePath).toLowerCase();
68440
- 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;
68441
68452
  try {
68442
- if ([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext)) {
68443
- const relativePath = path53.relative(absoluteRoot, filePath);
68444
- const symbols2 = extractTSSymbols(relativePath, absoluteRoot);
68445
- exports = symbols2.filter((s) => s.exported).map((s) => s.name);
68446
- } else if (ext === ".py") {
68447
- const relativePath = path53.relative(absoluteRoot, filePath);
68448
- const symbols2 = extractPythonSymbols(relativePath, absoluteRoot);
68449
- 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");
68450
68466
  }
68451
- const parsedImports = parseFileImports(content);
68452
- const node = {
68453
- filePath,
68454
- moduleName: toModuleName(filePath, absoluteRoot),
68455
- exports,
68456
- imports: parsedImports.map((p) => p.specifier),
68457
- language: getLanguage(filePath),
68458
- mtime: fileStats.mtime.toISOString()
68459
- };
68460
- const edges = [];
68461
- const sortedImports = [...parsedImports].sort((a, b) => a.specifier.localeCompare(b.specifier));
68462
- for (const parsed of sortedImports) {
68463
- const resolvedTarget = resolveModuleSpecifier(absoluteRoot, filePath, parsed.specifier);
68464
- if (resolvedTarget !== null) {
68465
- edges.push({
68466
- source: filePath,
68467
- target: resolvedTarget,
68468
- importSpecifier: parsed.specifier,
68469
- importType: parsed.importType
68470
- });
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);
68471
68497
  }
68472
68498
  }
68473
- return { node, edges };
68474
- } catch {
68475
- return { node: null, edges: [] };
68476
68499
  }
68500
+ const stats = await fsPromises6.stat(graphPath);
68501
+ setCachedGraph(normalized, graph, stats.mtimeMs);
68477
68502
  }
68503
+
68504
+ // src/tools/repo-graph/incremental.ts
68478
68505
  async function updateGraphForFiles(workspaceRoot, filePaths, options) {
68479
68506
  if (options?.forceRebuild) {
68480
68507
  const graph2 = await buildWorkspaceGraphAsync(workspaceRoot);
@@ -68488,12 +68515,12 @@ async function updateGraphForFiles(workspaceRoot, filePaths, options) {
68488
68515
  return graph2;
68489
68516
  }
68490
68517
  const graph = existingGraph;
68491
- const absoluteRoot = path53.resolve(workspaceRoot);
68518
+ const absoluteRoot = path57.resolve(workspaceRoot);
68492
68519
  const maxFileSize = 1024 * 1024;
68493
68520
  const updatedPaths = new Set;
68494
68521
  for (const rawFilePath of filePaths) {
68495
68522
  const normalizedPath = normalizeGraphPath(rawFilePath);
68496
- const fileExists = existsSync29(rawFilePath);
68523
+ const fileExists = existsSync31(rawFilePath);
68497
68524
  if (fileExists) {
68498
68525
  graph.edges = graph.edges.filter((e) => normalizeGraphPath(e.source) !== normalizedPath);
68499
68526
  const result = scanFile(rawFilePath, absoluteRoot, maxFileSize);
@@ -68528,6 +68555,22 @@ async function updateGraphForFiles(workspaceRoot, filePaths, options) {
68528
68555
  await saveGraph(workspaceRoot, rebuiltGraph);
68529
68556
  return rebuiltGraph;
68530
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
+ }
68531
68574
  updateGraphMetadata(graph);
68532
68575
  await saveGraph(workspaceRoot, graph);
68533
68576
  return graph;
@@ -68546,9 +68589,20 @@ function extractFilePath(args2) {
68546
68589
  if (!args2 || typeof args2 !== "object")
68547
68590
  return null;
68548
68591
  const a = args2;
68549
- const filePath = a.file_path ?? a.path ?? a.filePath;
68592
+ let filePath = a.file_path ?? a.path ?? a.filePath;
68550
68593
  if (!filePath || typeof filePath !== "string")
68551
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, ".");
68552
68606
  return filePath;
68553
68607
  }
68554
68608
  function isSupportedSourceFile(filePath) {
@@ -68561,6 +68615,8 @@ function createRepoGraphBuilderHook(workspaceRoot, deps) {
68561
68615
  const _updateGraphForFiles = deps?.updateGraphForFiles ?? updateGraphForFiles;
68562
68616
  let initStarted = false;
68563
68617
  let initPromise = Promise.resolve();
68618
+ let consecutiveFailures = 0;
68619
+ const FAILURE_ADVISORY_THRESHOLD = 3;
68564
68620
  async function doInit() {
68565
68621
  await yieldToEventLoop();
68566
68622
  try {
@@ -68589,37 +68645,48 @@ function createRepoGraphBuilderHook(workspaceRoot, deps) {
68589
68645
  if (!WRITE_TOOL_NAMES.includes(input.tool)) {
68590
68646
  return;
68591
68647
  }
68592
- const rawFilePath = extractFilePath(input.args);
68593
- if (!rawFilePath)
68648
+ const filePath = extractFilePath(input.args);
68649
+ if (!filePath)
68594
68650
  return;
68595
- if (rawFilePath.includes("\x00"))
68651
+ if (filePath.includes("\x00"))
68596
68652
  return;
68597
- let filePath = rawFilePath;
68598
- for (let i2 = 0;i2 < 3; i2++) {
68599
- try {
68600
- const decoded = decodeURIComponent(filePath);
68601
- if (decoded === filePath)
68602
- break;
68603
- filePath = decoded;
68604
- } catch {
68605
- break;
68606
- }
68607
- }
68608
- filePath = filePath.replace(/./g, ".").replace(///g, "/").replace(/․/g, ".");
68609
68653
  if (!isSupportedSourceFile(filePath))
68610
68654
  return;
68611
- const absoluteFilePath = path54.isAbsolute(filePath) ? filePath : path54.resolve(workspaceRoot, filePath);
68612
- const normalizedAbsolute = absoluteFilePath.replace(/\\/g, "/");
68613
- 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, "/");
68614
68676
  if (!normalizedAbsolute.startsWith(`${normalizedWorkspace}/`) && normalizedAbsolute !== normalizedWorkspace) {
68615
68677
  return;
68616
68678
  }
68617
68679
  try {
68618
68680
  await _updateGraphForFiles(workspaceRoot, [absoluteFilePath]);
68619
- log(`[repo-graph] Incremental update for ${path54.basename(filePath)}`);
68681
+ consecutiveFailures = 0;
68682
+ log(`[repo-graph] Incremental update for ${path58.basename(filePath)}`);
68620
68683
  } catch (error93) {
68621
68684
  const message = error93 instanceof Error ? error93.message : String(error93);
68685
+ consecutiveFailures++;
68622
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
+ }
68623
68690
  }
68624
68691
  }
68625
68692
  };
@@ -68635,14 +68702,14 @@ init_manager2();
68635
68702
  init_detector();
68636
68703
  init_manager();
68637
68704
  import * as fs46 from "node:fs";
68638
- import * as path64 from "node:path";
68705
+ import * as path68 from "node:path";
68639
68706
 
68640
68707
  // src/services/decision-drift-analyzer.ts
68641
68708
  init_utils2();
68642
68709
  init_manager();
68643
68710
  init_utils();
68644
68711
  import * as fs38 from "node:fs";
68645
- import * as path55 from "node:path";
68712
+ import * as path59 from "node:path";
68646
68713
  var DEFAULT_DRIFT_CONFIG = {
68647
68714
  staleThresholdPhases: 1,
68648
68715
  detectContradictions: true,
@@ -68796,7 +68863,7 @@ async function analyzeDecisionDrift(directory, config3 = {}) {
68796
68863
  currentPhase = legacyPhase;
68797
68864
  }
68798
68865
  }
68799
- const contextPath = path55.join(directory, ".swarm", "context.md");
68866
+ const contextPath = path59.join(directory, ".swarm", "context.md");
68800
68867
  let contextContent = "";
68801
68868
  try {
68802
68869
  if (fs38.existsSync(contextPath)) {
@@ -68935,7 +69002,7 @@ init_utils();
68935
69002
  init_constants();
68936
69003
  init_schema();
68937
69004
  import * as fs39 from "node:fs/promises";
68938
- import * as path56 from "node:path";
69005
+ import * as path60 from "node:path";
68939
69006
  function safeGet(obj, key) {
68940
69007
  if (!obj || !Object.hasOwn(obj, key))
68941
69008
  return;
@@ -69167,9 +69234,9 @@ async function handleDebuggingSpiral(match, taskId, directory) {
69167
69234
  let eventLogged = false;
69168
69235
  let checkpointCreated = false;
69169
69236
  try {
69170
- const swarmDir = path56.join(directory, ".swarm");
69237
+ const swarmDir = path60.join(directory, ".swarm");
69171
69238
  await fs39.mkdir(swarmDir, { recursive: true });
69172
- const eventsPath = path56.join(swarmDir, "events.jsonl");
69239
+ const eventsPath = path60.join(swarmDir, "events.jsonl");
69173
69240
  await fs39.appendFile(eventsPath, `${formatDebuggingSpiralEvent(match, taskId)}
69174
69241
  `);
69175
69242
  eventLogged = true;
@@ -69304,7 +69371,7 @@ import * as fs43 from "node:fs";
69304
69371
 
69305
69372
  // src/graph/graph-builder.ts
69306
69373
  import * as fs41 from "node:fs";
69307
- import * as path59 from "node:path";
69374
+ import * as path63 from "node:path";
69308
69375
 
69309
69376
  // node_modules/yocto-queue/index.js
69310
69377
  class Node {
@@ -69395,26 +69462,26 @@ function pLimit(concurrency) {
69395
69462
  activeCount--;
69396
69463
  resumeNext();
69397
69464
  };
69398
- const run2 = async (function_, resolve19, arguments_2) => {
69465
+ const run2 = async (function_, resolve20, arguments_2) => {
69399
69466
  const result = (async () => function_(...arguments_2))();
69400
- resolve19(result);
69467
+ resolve20(result);
69401
69468
  try {
69402
69469
  await result;
69403
69470
  } catch {}
69404
69471
  next();
69405
69472
  };
69406
- const enqueue = (function_, resolve19, reject, arguments_2) => {
69473
+ const enqueue = (function_, resolve20, reject, arguments_2) => {
69407
69474
  const queueItem = { reject };
69408
69475
  new Promise((internalResolve) => {
69409
69476
  queueItem.run = internalResolve;
69410
69477
  queue.enqueue(queueItem);
69411
- }).then(run2.bind(undefined, function_, resolve19, arguments_2));
69478
+ }).then(run2.bind(undefined, function_, resolve20, arguments_2));
69412
69479
  if (activeCount < concurrency) {
69413
69480
  resumeNext();
69414
69481
  }
69415
69482
  };
69416
- const generator = (function_, ...arguments_2) => new Promise((resolve19, reject) => {
69417
- enqueue(function_, resolve19, reject, arguments_2);
69483
+ const generator = (function_, ...arguments_2) => new Promise((resolve20, reject) => {
69484
+ enqueue(function_, resolve20, reject, arguments_2);
69418
69485
  });
69419
69486
  Object.defineProperties(generator, {
69420
69487
  activeCount: {
@@ -69465,7 +69532,7 @@ function validateConcurrency(concurrency) {
69465
69532
  // src/graph/import-extractor.ts
69466
69533
  init_path_security();
69467
69534
  import * as fs40 from "node:fs";
69468
- import * as path57 from "node:path";
69535
+ import * as path61 from "node:path";
69469
69536
  var SOURCE_EXTENSIONS2 = [
69470
69537
  ".ts",
69471
69538
  ".tsx",
@@ -69510,28 +69577,28 @@ function getLanguageFromExtension(ext) {
69510
69577
  return null;
69511
69578
  }
69512
69579
  function toRelForwardSlash(absPath, root) {
69513
- return path57.relative(root, absPath).replace(/\\/g, "/");
69580
+ return path61.relative(root, absPath).replace(/\\/g, "/");
69514
69581
  }
69515
69582
  function tryResolveTSJS(rawModule, sourceFileAbs) {
69516
69583
  if (!rawModule.startsWith(".") && !rawModule.startsWith("/")) {
69517
69584
  return null;
69518
69585
  }
69519
- const sourceDir = path57.dirname(sourceFileAbs);
69520
- const baseAbs = path57.resolve(sourceDir, rawModule);
69586
+ const sourceDir = path61.dirname(sourceFileAbs);
69587
+ const baseAbs = path61.resolve(sourceDir, rawModule);
69521
69588
  const probe = (basePath) => {
69522
69589
  for (const ext of RESOLVE_EXTENSION_CANDIDATES) {
69523
69590
  const test = basePath + ext;
69524
69591
  try {
69525
- const stat5 = fs40.statSync(test);
69526
- if (stat5.isFile())
69592
+ const stat6 = fs40.statSync(test);
69593
+ if (stat6.isFile())
69527
69594
  return test;
69528
69595
  } catch {}
69529
69596
  }
69530
69597
  for (const indexFile of RESOLVE_INDEX_CANDIDATES) {
69531
- const test = path57.join(basePath, indexFile);
69598
+ const test = path61.join(basePath, indexFile);
69532
69599
  try {
69533
- const stat5 = fs40.statSync(test);
69534
- if (stat5.isFile())
69600
+ const stat6 = fs40.statSync(test);
69601
+ if (stat6.isFile())
69535
69602
  return test;
69536
69603
  } catch {}
69537
69604
  }
@@ -69558,13 +69625,13 @@ function tryResolvePython(rawModule, sourceFileAbs, workspaceRoot) {
69558
69625
  }
69559
69626
  const remainder = rawModule.slice(leadingDots).replace(/\./g, "/");
69560
69627
  const upDirs = "../".repeat(Math.max(0, leadingDots - 1));
69561
- const sourceDir = path57.dirname(sourceFileAbs);
69562
- const baseAbs = path57.resolve(sourceDir, upDirs + remainder);
69628
+ const sourceDir = path61.dirname(sourceFileAbs);
69629
+ const baseAbs = path61.resolve(sourceDir, upDirs + remainder);
69563
69630
  const accept = (test) => {
69564
69631
  try {
69565
- const stat5 = fs40.statSync(test);
69566
- if (stat5.isFile()) {
69567
- 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, "/");
69568
69635
  if (rel.startsWith(".."))
69569
69636
  return null;
69570
69637
  return test;
@@ -69578,7 +69645,7 @@ function tryResolvePython(rawModule, sourceFileAbs, workspaceRoot) {
69578
69645
  return hit;
69579
69646
  }
69580
69647
  for (const indexFile of PY_INDEX_CANDIDATES) {
69581
- const hit = accept(path57.join(baseAbs, indexFile));
69648
+ const hit = accept(path61.join(baseAbs, indexFile));
69582
69649
  if (hit)
69583
69650
  return hit;
69584
69651
  }
@@ -69949,7 +70016,7 @@ function parseRustUses(content) {
69949
70016
  }
69950
70017
  function extractImports2(opts) {
69951
70018
  const { absoluteFilePath, workspaceRoot } = opts;
69952
- const ext = path57.extname(absoluteFilePath).toLowerCase();
70019
+ const ext = path61.extname(absoluteFilePath).toLowerCase();
69953
70020
  const language = getLanguageFromExtension(ext);
69954
70021
  if (!language)
69955
70022
  return [];
@@ -70000,9 +70067,9 @@ function extractImports2(opts) {
70000
70067
  }
70001
70068
 
70002
70069
  // src/graph/symbol-extractor.ts
70003
- import * as path58 from "node:path";
70070
+ import * as path62 from "node:path";
70004
70071
  function extractExportedSymbols(relativeFilePath, workspaceRoot) {
70005
- const ext = path58.extname(relativeFilePath).toLowerCase();
70072
+ const ext = path62.extname(relativeFilePath).toLowerCase();
70006
70073
  const language = getLanguageFromExtension(ext);
70007
70074
  if (!language)
70008
70075
  return [];
@@ -70091,15 +70158,15 @@ function findSourceFiles(workspaceRoot, skipDirs = DEFAULT_SKIP_DIRS) {
70091
70158
  if (entry.isDirectory()) {
70092
70159
  if (skipDirs.has(entry.name))
70093
70160
  continue;
70094
- stack.push(path59.join(dir, entry.name));
70161
+ stack.push(path63.join(dir, entry.name));
70095
70162
  continue;
70096
70163
  }
70097
70164
  if (!entry.isFile())
70098
70165
  continue;
70099
- const ext = path59.extname(entry.name).toLowerCase();
70166
+ const ext = path63.extname(entry.name).toLowerCase();
70100
70167
  if (!SOURCE_EXT_SET.has(ext))
70101
70168
  continue;
70102
- out2.push(path59.join(dir, entry.name));
70169
+ out2.push(path63.join(dir, entry.name));
70103
70170
  }
70104
70171
  }
70105
70172
  return out2;
@@ -70127,7 +70194,7 @@ async function buildRepoGraph(workspaceRoot, options = {}) {
70127
70194
  };
70128
70195
  }
70129
70196
  async function processFile(absoluteFilePath, workspaceRoot) {
70130
- const ext = path59.extname(absoluteFilePath).toLowerCase();
70197
+ const ext = path63.extname(absoluteFilePath).toLowerCase();
70131
70198
  const language = getLanguageFromExtension(ext);
70132
70199
  if (!language)
70133
70200
  return null;
@@ -70147,7 +70214,7 @@ async function processFile(absoluteFilePath, workspaceRoot) {
70147
70214
  } catch {
70148
70215
  return null;
70149
70216
  }
70150
- const relPath = path59.relative(workspaceRoot, absoluteFilePath).replace(/\\/g, "/");
70217
+ const relPath = path63.relative(workspaceRoot, absoluteFilePath).replace(/\\/g, "/");
70151
70218
  const imports = extractImports2({
70152
70219
  absoluteFilePath,
70153
70220
  workspaceRoot,
@@ -70389,10 +70456,10 @@ function formatSummary(opts) {
70389
70456
  // src/graph/graph-store.ts
70390
70457
  import * as crypto6 from "node:crypto";
70391
70458
  import * as fs42 from "node:fs";
70392
- import * as path60 from "node:path";
70459
+ import * as path64 from "node:path";
70393
70460
  var SWARM_DIR = ".swarm";
70394
70461
  function getGraphPath2(workspaceRoot) {
70395
- return path60.join(workspaceRoot, SWARM_DIR, REPO_GRAPH_FILENAME2);
70462
+ return path64.join(workspaceRoot, SWARM_DIR, REPO_GRAPH_FILENAME2);
70396
70463
  }
70397
70464
  function loadGraph2(workspaceRoot) {
70398
70465
  const file3 = getGraphPath2(workspaceRoot);
@@ -70414,10 +70481,10 @@ function loadGraph2(workspaceRoot) {
70414
70481
  }
70415
70482
  function saveGraph2(workspaceRoot, graph) {
70416
70483
  const file3 = getGraphPath2(workspaceRoot);
70417
- const dir = path60.dirname(file3);
70484
+ const dir = path64.dirname(file3);
70418
70485
  try {
70419
- const stat5 = fs42.lstatSync(dir);
70420
- if (stat5.isSymbolicLink()) {
70486
+ const stat6 = fs42.lstatSync(dir);
70487
+ if (stat6.isSymbolicLink()) {
70421
70488
  throw new Error(`refusing to write graph: ${SWARM_DIR}/ is a symbolic link`);
70422
70489
  }
70423
70490
  } catch (err2) {
@@ -70453,15 +70520,15 @@ function isGraphFresh(graph, maxAgeMs = 5 * 60 * 1000) {
70453
70520
  var cache = new Map;
70454
70521
  function getCachedGraph2(directory) {
70455
70522
  const file3 = getGraphPath2(directory);
70456
- let stat5;
70523
+ let stat6;
70457
70524
  try {
70458
- stat5 = fs43.statSync(file3);
70525
+ stat6 = fs43.statSync(file3);
70459
70526
  } catch {
70460
70527
  cache.delete(directory);
70461
70528
  return null;
70462
70529
  }
70463
70530
  const cached3 = cache.get(directory);
70464
- if (cached3 && cached3.mtimeMs === stat5.mtimeMs && cached3.size === stat5.size) {
70531
+ if (cached3 && cached3.mtimeMs === stat6.mtimeMs && cached3.size === stat6.size) {
70465
70532
  return cached3.graph;
70466
70533
  }
70467
70534
  const graph = loadGraph2(directory);
@@ -70469,7 +70536,7 @@ function getCachedGraph2(directory) {
70469
70536
  cache.delete(directory);
70470
70537
  return null;
70471
70538
  }
70472
- cache.set(directory, { graph, mtimeMs: stat5.mtimeMs, size: stat5.size });
70539
+ cache.set(directory, { graph, mtimeMs: stat6.mtimeMs, size: stat6.size });
70473
70540
  return graph;
70474
70541
  }
70475
70542
  function buildCoderLocalizationBlock(directory, targetFile) {
@@ -70520,7 +70587,7 @@ function buildReviewerBlastRadiusBlock(directory, changedFiles) {
70520
70587
  // src/hooks/semantic-diff-injection.ts
70521
70588
  import * as child_process5 from "node:child_process";
70522
70589
  import * as fs44 from "node:fs";
70523
- import * as path62 from "node:path";
70590
+ import * as path66 from "node:path";
70524
70591
 
70525
70592
  // src/diff/ast-diff.ts
70526
70593
  init_tree_sitter();
@@ -71267,17 +71334,17 @@ async function buildSemanticDiffBlock(directory, changedFiles, maxFiles = 10) {
71267
71334
  const fileConsumers = {};
71268
71335
  if (graph) {
71269
71336
  for (const f of filesToProcess) {
71270
- const relativePath = path62.isAbsolute(f) ? path62.relative(directory, f) : f;
71337
+ const relativePath = path66.isAbsolute(f) ? path66.relative(directory, f) : f;
71271
71338
  const normalized = normalizeGraphPath2(relativePath);
71272
71339
  fileConsumers[normalized] = getImporters(graph, normalized).length;
71273
71340
  fileConsumers[f] = fileConsumers[normalized];
71274
71341
  }
71275
71342
  }
71276
71343
  for (const filePath of filesToProcess) {
71277
- const normalizedPath = path62.normalize(filePath);
71278
- const resolvedPath = path62.resolve(directory, normalizedPath);
71279
- const relativeToDir = path62.relative(directory, resolvedPath);
71280
- 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)) {
71281
71348
  continue;
71282
71349
  }
71283
71350
  try {
@@ -71304,7 +71371,7 @@ async function buildSemanticDiffBlock(directory, changedFiles, maxFiles = 10) {
71304
71371
  stdio: "pipe",
71305
71372
  maxBuffer: 5 * 1024 * 1024
71306
71373
  }) : "";
71307
- const newContent = fs44.readFileSync(path62.join(directory, filePath), "utf-8");
71374
+ const newContent = fs44.readFileSync(path66.join(directory, filePath), "utf-8");
71308
71375
  const astResult = await computeASTDiff(filePath, oldContent, newContent);
71309
71376
  if (astResult && (astResult.changes.length > 0 || astResult.error !== undefined)) {
71310
71377
  astDiffs.push(astResult);
@@ -71646,7 +71713,7 @@ function createSystemEnhancerHook(config3, directory) {
71646
71713
  await fs46.promises.writeFile(darkMatterPath, darkMatterReport, "utf-8");
71647
71714
  warn(`[system-enhancer] Dark matter scan complete: ${darkMatter.length} co-change patterns found`);
71648
71715
  try {
71649
- const projectName = path64.basename(path64.resolve(directory));
71716
+ const projectName = path68.basename(path68.resolve(directory));
71650
71717
  const knowledgeEntries = darkMatterToKnowledgeEntries2(darkMatter, projectName);
71651
71718
  const knowledgePath = resolveSwarmKnowledgePath(directory);
71652
71719
  const existingEntries = await readKnowledge(knowledgePath);
@@ -71845,7 +71912,7 @@ ${lines.join(`
71845
71912
  try {
71846
71913
  const taskId_ccp = ccpSession?.currentTaskId;
71847
71914
  if (taskId_ccp && !taskId_ccp.includes("..") && !taskId_ccp.includes("/") && !taskId_ccp.includes("\\") && !taskId_ccp.includes("\x00")) {
71848
- const evidencePath = path64.join(directory, ".swarm", "evidence", `${taskId_ccp}.json`);
71915
+ const evidencePath = path68.join(directory, ".swarm", "evidence", `${taskId_ccp}.json`);
71849
71916
  if (fs46.existsSync(evidencePath)) {
71850
71917
  const evidenceContent = fs46.readFileSync(evidencePath, "utf-8");
71851
71918
  const evidenceData = JSON.parse(evidenceContent);
@@ -72993,13 +73060,13 @@ init_hive_promoter();
72993
73060
 
72994
73061
  // src/hooks/incremental-verify.ts
72995
73062
  import * as fs47 from "node:fs";
72996
- import * as path65 from "node:path";
73063
+ import * as path69 from "node:path";
72997
73064
 
72998
73065
  // src/hooks/spawn-helper.ts
72999
73066
  import * as child_process6 from "node:child_process";
73000
73067
  var WIN32_CMD_BINARIES = new Set(["npm", "npx", "pnpm", "yarn"]);
73001
73068
  function spawnAsync(command, cwd, timeoutMs) {
73002
- return new Promise((resolve23) => {
73069
+ return new Promise((resolve24) => {
73003
73070
  try {
73004
73071
  const [rawCmd, ...args2] = command;
73005
73072
  const cmd = process.platform === "win32" && WIN32_CMD_BINARIES.has(rawCmd) && !rawCmd.includes(".") ? `${rawCmd}.cmd` : rawCmd;
@@ -73046,24 +73113,24 @@ function spawnAsync(command, cwd, timeoutMs) {
73046
73113
  try {
73047
73114
  proc.kill();
73048
73115
  } catch {}
73049
- resolve23(null);
73116
+ resolve24(null);
73050
73117
  }, timeoutMs);
73051
73118
  proc.on("close", (code) => {
73052
73119
  if (done)
73053
73120
  return;
73054
73121
  done = true;
73055
73122
  clearTimeout(timer);
73056
- resolve23({ exitCode: code ?? 1, stdout, stderr });
73123
+ resolve24({ exitCode: code ?? 1, stdout, stderr });
73057
73124
  });
73058
73125
  proc.on("error", () => {
73059
73126
  if (done)
73060
73127
  return;
73061
73128
  done = true;
73062
73129
  clearTimeout(timer);
73063
- resolve23(null);
73130
+ resolve24(null);
73064
73131
  });
73065
73132
  } catch {
73066
- resolve23(null);
73133
+ resolve24(null);
73067
73134
  }
73068
73135
  });
73069
73136
  }
@@ -73071,18 +73138,18 @@ function spawnAsync(command, cwd, timeoutMs) {
73071
73138
  // src/hooks/incremental-verify.ts
73072
73139
  var emittedSkipAdvisories = new Set;
73073
73140
  function detectPackageManager(projectDir) {
73074
- if (fs47.existsSync(path65.join(projectDir, "bun.lockb")))
73141
+ if (fs47.existsSync(path69.join(projectDir, "bun.lockb")))
73075
73142
  return "bun";
73076
- if (fs47.existsSync(path65.join(projectDir, "pnpm-lock.yaml")))
73143
+ if (fs47.existsSync(path69.join(projectDir, "pnpm-lock.yaml")))
73077
73144
  return "pnpm";
73078
- if (fs47.existsSync(path65.join(projectDir, "yarn.lock")))
73145
+ if (fs47.existsSync(path69.join(projectDir, "yarn.lock")))
73079
73146
  return "yarn";
73080
- if (fs47.existsSync(path65.join(projectDir, "package-lock.json")))
73147
+ if (fs47.existsSync(path69.join(projectDir, "package-lock.json")))
73081
73148
  return "npm";
73082
73149
  return "bun";
73083
73150
  }
73084
73151
  function detectTypecheckCommand(projectDir) {
73085
- const pkgPath = path65.join(projectDir, "package.json");
73152
+ const pkgPath = path69.join(projectDir, "package.json");
73086
73153
  if (fs47.existsSync(pkgPath)) {
73087
73154
  try {
73088
73155
  const pkg = JSON.parse(fs47.readFileSync(pkgPath, "utf8"));
@@ -73099,8 +73166,8 @@ function detectTypecheckCommand(projectDir) {
73099
73166
  ...pkg.dependencies,
73100
73167
  ...pkg.devDependencies
73101
73168
  };
73102
- if (!deps?.typescript && !fs47.existsSync(path65.join(projectDir, "tsconfig.json"))) {}
73103
- 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"));
73104
73171
  if (hasTSMarkers) {
73105
73172
  return { command: ["npx", "tsc", "--noEmit"], language: "typescript" };
73106
73173
  }
@@ -73108,13 +73175,13 @@ function detectTypecheckCommand(projectDir) {
73108
73175
  return null;
73109
73176
  }
73110
73177
  }
73111
- if (fs47.existsSync(path65.join(projectDir, "go.mod"))) {
73178
+ if (fs47.existsSync(path69.join(projectDir, "go.mod"))) {
73112
73179
  return { command: ["go", "vet", "./..."], language: "go" };
73113
73180
  }
73114
- if (fs47.existsSync(path65.join(projectDir, "Cargo.toml"))) {
73181
+ if (fs47.existsSync(path69.join(projectDir, "Cargo.toml"))) {
73115
73182
  return { command: ["cargo", "check"], language: "rust" };
73116
73183
  }
73117
- 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"))) {
73118
73185
  return { command: null, language: "python" };
73119
73186
  }
73120
73187
  try {
@@ -73464,7 +73531,7 @@ init_scope_persistence();
73464
73531
  init_state();
73465
73532
  init_delegation_gate();
73466
73533
  init_normalize_tool_name();
73467
- import * as path67 from "node:path";
73534
+ import * as path71 from "node:path";
73468
73535
  var WRITE_TOOLS = new Set(WRITE_TOOL_NAMES);
73469
73536
  function createScopeGuardHook(config3, directory, injectAdvisory) {
73470
73537
  const enabled = config3.enabled ?? true;
@@ -73522,13 +73589,13 @@ function createScopeGuardHook(config3, directory, injectAdvisory) {
73522
73589
  }
73523
73590
  function isFileInScope(filePath, scopeEntries, directory) {
73524
73591
  const dir = directory ?? process.cwd();
73525
- const resolvedFile = path67.resolve(dir, filePath);
73592
+ const resolvedFile = path71.resolve(dir, filePath);
73526
73593
  return scopeEntries.some((scope) => {
73527
- const resolvedScope = path67.resolve(dir, scope);
73594
+ const resolvedScope = path71.resolve(dir, scope);
73528
73595
  if (resolvedFile === resolvedScope)
73529
73596
  return true;
73530
- const rel = path67.relative(resolvedScope, resolvedFile);
73531
- 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);
73532
73599
  });
73533
73600
  }
73534
73601
 
@@ -73580,7 +73647,7 @@ function createSelfReviewHook(config3, injectAdvisory) {
73580
73647
 
73581
73648
  // src/hooks/slop-detector.ts
73582
73649
  import * as fs49 from "node:fs";
73583
- import * as path68 from "node:path";
73650
+ import * as path72 from "node:path";
73584
73651
  var WRITE_EDIT_TOOLS = new Set([
73585
73652
  "write",
73586
73653
  "edit",
@@ -73630,7 +73697,7 @@ function walkFiles(dir, exts, deadline) {
73630
73697
  break;
73631
73698
  if (entry.isSymbolicLink())
73632
73699
  continue;
73633
- const full = path68.join(dir, entry.name);
73700
+ const full = path72.join(dir, entry.name);
73634
73701
  if (entry.isDirectory()) {
73635
73702
  if (entry.name === "node_modules" || entry.name === ".git")
73636
73703
  continue;
@@ -73645,7 +73712,7 @@ function walkFiles(dir, exts, deadline) {
73645
73712
  return results;
73646
73713
  }
73647
73714
  function checkDeadExports(content, projectDir, startTime) {
73648
- const hasPackageJson = fs49.existsSync(path68.join(projectDir, "package.json"));
73715
+ const hasPackageJson = fs49.existsSync(path72.join(projectDir, "package.json"));
73649
73716
  if (!hasPackageJson)
73650
73717
  return null;
73651
73718
  const exportMatches = content.matchAll(/^\+(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm);
@@ -73759,14 +73826,14 @@ function checkDuplicateUtility(content, projectDir, startTime, targetFile) {
73759
73826
  for (const utilDir of utilityDirs) {
73760
73827
  if (Date.now() > deadline)
73761
73828
  break;
73762
- const utilPath = path68.join(projectDir, utilDir);
73829
+ const utilPath = path72.join(projectDir, utilDir);
73763
73830
  if (!fs49.existsSync(utilPath))
73764
73831
  continue;
73765
73832
  const files = walkFiles(utilPath, [".ts", ".tsx", ".js", ".jsx"], deadline);
73766
73833
  for (const file3 of files) {
73767
73834
  if (Date.now() > deadline)
73768
73835
  break;
73769
- if (targetFile && path68.resolve(file3) === path68.resolve(targetFile))
73836
+ if (targetFile && path72.resolve(file3) === path72.resolve(targetFile))
73770
73837
  continue;
73771
73838
  try {
73772
73839
  const text = fs49.readFileSync(file3, "utf-8");
@@ -73904,14 +73971,14 @@ function createSteeringConsumedHook(directory) {
73904
73971
  // src/hooks/trajectory-logger.ts
73905
73972
  init_manager2();
73906
73973
  import * as fs52 from "node:fs/promises";
73907
- import * as path70 from "node:path";
73974
+ import * as path74 from "node:path";
73908
73975
 
73909
73976
  // src/prm/trajectory-store.ts
73910
73977
  init_utils2();
73911
73978
  import * as fs51 from "node:fs/promises";
73912
- import * as path69 from "node:path";
73979
+ import * as path73 from "node:path";
73913
73980
  function getTrajectoryPath(sessionId, directory) {
73914
- const relativePath = path69.join("trajectories", `${sessionId}.jsonl`);
73981
+ const relativePath = path73.join("trajectories", `${sessionId}.jsonl`);
73915
73982
  return validateSwarmPath(directory, relativePath);
73916
73983
  }
73917
73984
  var _inMemoryTrajectoryCache = new Map;
@@ -73930,7 +73997,7 @@ async function appendTrajectoryEntry(sessionId, entry, directory, maxLines = 100
73930
73997
  _inMemoryTrajectoryCache.set(sessionId, cached3);
73931
73998
  }
73932
73999
  const trajectoryPath = getTrajectoryPath(sessionId, directory);
73933
- await fs51.mkdir(path69.dirname(trajectoryPath), { recursive: true });
74000
+ await fs51.mkdir(path73.dirname(trajectoryPath), { recursive: true });
73934
74001
  const line = `${JSON.stringify(entry)}
73935
74002
  `;
73936
74003
  await fs51.appendFile(trajectoryPath, line, "utf-8");
@@ -73969,10 +74036,10 @@ async function cleanupOldTrajectoryFiles(directory, maxAgeDays = 7) {
73969
74036
  for (const entry of entries) {
73970
74037
  if (!entry.isFile())
73971
74038
  continue;
73972
- const filePath = path69.join(dirPath, entry.name);
74039
+ const filePath = path73.join(dirPath, entry.name);
73973
74040
  try {
73974
- const stat6 = await fs51.stat(filePath);
73975
- if (now - stat6.mtimeMs > cutoffMs) {
74041
+ const stat7 = await fs51.stat(filePath);
74042
+ if (now - stat7.mtimeMs > cutoffMs) {
73976
74043
  await fs51.unlink(filePath);
73977
74044
  }
73978
74045
  } catch {}
@@ -74161,10 +74228,10 @@ function createTrajectoryLoggerHook(config3, _directory) {
74161
74228
  elapsed_ms
74162
74229
  };
74163
74230
  const sanitized = sanitizeTaskId2(taskId);
74164
- const relativePath = path70.join("evidence", sanitized, "trajectory.jsonl");
74231
+ const relativePath = path74.join("evidence", sanitized, "trajectory.jsonl");
74165
74232
  const trajectoryPath = validateSwarmPath(_directory, relativePath);
74166
74233
  try {
74167
- await fs52.mkdir(path70.dirname(trajectoryPath), { recursive: true });
74234
+ await fs52.mkdir(path74.dirname(trajectoryPath), { recursive: true });
74168
74235
  const line = `${JSON.stringify(entry)}
74169
74236
  `;
74170
74237
  await fs52.appendFile(trajectoryPath, line, "utf-8");
@@ -74715,16 +74782,16 @@ init_telemetry();
74715
74782
 
74716
74783
  // src/prm/replay.ts
74717
74784
  import { promises as fs53 } from "node:fs";
74718
- import path71 from "node:path";
74785
+ import path75 from "node:path";
74719
74786
  function isPathSafe2(targetPath, basePath) {
74720
- const resolvedTarget = path71.resolve(targetPath);
74721
- const resolvedBase = path71.resolve(basePath);
74722
- const rel = path71.relative(resolvedBase, resolvedTarget);
74723
- 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);
74724
74791
  }
74725
74792
  function isWithinReplaysDir(targetPath) {
74726
- const resolved = path71.resolve(targetPath);
74727
- const parts2 = resolved.split(path71.sep);
74793
+ const resolved = path75.resolve(targetPath);
74794
+ const parts2 = resolved.split(path75.sep);
74728
74795
  for (let i2 = 0;i2 < parts2.length - 1; i2++) {
74729
74796
  if (parts2[i2] === ".swarm" && parts2[i2 + 1] === "replays") {
74730
74797
  return true;
@@ -74737,10 +74804,10 @@ function sanitizeFilename(input) {
74737
74804
  }
74738
74805
  async function startReplayRecording(sessionID, directory) {
74739
74806
  try {
74740
- const replayDir = path71.join(directory, ".swarm", "replays");
74807
+ const replayDir = path75.join(directory, ".swarm", "replays");
74741
74808
  const safeSessionID = sanitizeFilename(sessionID);
74742
74809
  const filename = `${safeSessionID}-${Date.now()}.jsonl`;
74743
- const filepath = path71.join(replayDir, filename);
74810
+ const filepath = path75.join(replayDir, filename);
74744
74811
  if (!isPathSafe2(filepath, replayDir)) {
74745
74812
  console.warn(`[replay] Invalid path detected - path traversal attempt blocked for session ${sessionID}`);
74746
74813
  return null;
@@ -75114,7 +75181,7 @@ init_telemetry();
75114
75181
  init_dist();
75115
75182
  init_create_tool();
75116
75183
  import * as fs54 from "node:fs";
75117
- import * as path72 from "node:path";
75184
+ import * as path76 from "node:path";
75118
75185
  init_path_security();
75119
75186
  var WINDOWS_RESERVED_NAMES2 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
75120
75187
  function containsWindowsAttacks2(str) {
@@ -75131,14 +75198,14 @@ function containsWindowsAttacks2(str) {
75131
75198
  }
75132
75199
  function isPathInWorkspace2(filePath, workspace) {
75133
75200
  try {
75134
- const resolvedPath = path72.resolve(workspace, filePath);
75201
+ const resolvedPath = path76.resolve(workspace, filePath);
75135
75202
  if (!fs54.existsSync(resolvedPath)) {
75136
75203
  return true;
75137
75204
  }
75138
75205
  const realWorkspace = fs54.realpathSync(workspace);
75139
75206
  const realResolvedPath = fs54.realpathSync(resolvedPath);
75140
- const relativePath = path72.relative(realWorkspace, realResolvedPath);
75141
- if (relativePath.startsWith("..") || path72.isAbsolute(relativePath)) {
75207
+ const relativePath = path76.relative(realWorkspace, realResolvedPath);
75208
+ if (relativePath.startsWith("..") || path76.isAbsolute(relativePath)) {
75142
75209
  return false;
75143
75210
  }
75144
75211
  return true;
@@ -75147,7 +75214,7 @@ function isPathInWorkspace2(filePath, workspace) {
75147
75214
  }
75148
75215
  }
75149
75216
  function processFile2(file3, cwd, exportedOnly) {
75150
- const ext = path72.extname(file3);
75217
+ const ext = path76.extname(file3);
75151
75218
  if (containsControlChars(file3)) {
75152
75219
  return {
75153
75220
  file: file3,
@@ -75180,7 +75247,7 @@ function processFile2(file3, cwd, exportedOnly) {
75180
75247
  errorType: "path-outside-workspace"
75181
75248
  };
75182
75249
  }
75183
- const fullPath = path72.join(cwd, file3);
75250
+ const fullPath = path76.join(cwd, file3);
75184
75251
  if (!fs54.existsSync(fullPath)) {
75185
75252
  return {
75186
75253
  file: file3,
@@ -75472,15 +75539,15 @@ init_task_id();
75472
75539
  init_create_tool();
75473
75540
  init_resolve_working_directory();
75474
75541
  import * as fs55 from "node:fs";
75475
- import * as path73 from "node:path";
75542
+ import * as path77 from "node:path";
75476
75543
  var EVIDENCE_DIR = ".swarm/evidence";
75477
75544
  function isValidTaskId3(taskId) {
75478
75545
  return isStrictTaskId(taskId);
75479
75546
  }
75480
75547
  function isPathWithinSwarm(filePath, workspaceRoot) {
75481
- const normalizedWorkspace = path73.resolve(workspaceRoot);
75482
- const swarmPath = path73.join(normalizedWorkspace, ".swarm", "evidence");
75483
- 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);
75484
75551
  return normalizedPath.startsWith(swarmPath);
75485
75552
  }
75486
75553
  function readEvidenceFile(evidencePath) {
@@ -75561,7 +75628,7 @@ var check_gate_status = createSwarmTool({
75561
75628
  };
75562
75629
  return JSON.stringify(errorResult, null, 2);
75563
75630
  }
75564
- const evidencePath = path73.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
75631
+ const evidencePath = path77.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
75565
75632
  if (!isPathWithinSwarm(evidencePath, directory)) {
75566
75633
  const errorResult = {
75567
75634
  taskId: taskIdInput,
@@ -75658,7 +75725,7 @@ init_state();
75658
75725
  init_create_tool();
75659
75726
  init_resolve_working_directory();
75660
75727
  import * as fs56 from "node:fs";
75661
- import * as path74 from "node:path";
75728
+ import * as path78 from "node:path";
75662
75729
  function extractMatches(regex, text) {
75663
75730
  return Array.from(text.matchAll(regex));
75664
75731
  }
@@ -75810,10 +75877,10 @@ async function executeCompletionVerify(args2, directory) {
75810
75877
  let hasFileReadFailure = false;
75811
75878
  for (const filePath of fileTargets) {
75812
75879
  const normalizedPath = filePath.replace(/\\/g, "/");
75813
- const resolvedPath = path74.resolve(directory, normalizedPath);
75814
- const projectRoot = path74.resolve(directory);
75815
- const relative16 = path74.relative(projectRoot, resolvedPath);
75816
- 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);
75817
75884
  if (!withinProject) {
75818
75885
  blockedTasks.push({
75819
75886
  task_id: task.id,
@@ -75868,8 +75935,8 @@ async function executeCompletionVerify(args2, directory) {
75868
75935
  blockedTasks
75869
75936
  };
75870
75937
  try {
75871
- const evidenceDir = path74.join(directory, ".swarm", "evidence", `${phase}`);
75872
- 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");
75873
75940
  fs56.mkdirSync(evidenceDir, { recursive: true });
75874
75941
  const evidenceBundle = {
75875
75942
  schema_version: "1.0.0",
@@ -75946,11 +76013,11 @@ var completion_verify = createSwarmTool({
75946
76013
  // src/tools/complexity-hotspots.ts
75947
76014
  init_zod();
75948
76015
  import * as fs58 from "node:fs";
75949
- import * as path76 from "node:path";
76016
+ import * as path80 from "node:path";
75950
76017
 
75951
76018
  // src/quality/metrics.ts
75952
76019
  import * as fs57 from "node:fs";
75953
- import * as path75 from "node:path";
76020
+ import * as path79 from "node:path";
75954
76021
  var MAX_FILE_SIZE_BYTES4 = 256 * 1024;
75955
76022
  var MIN_DUPLICATION_LINES = 10;
75956
76023
  function estimateCyclomaticComplexity(content) {
@@ -75988,8 +76055,8 @@ function estimateCyclomaticComplexity(content) {
75988
76055
  }
75989
76056
  function getComplexityForFile(filePath) {
75990
76057
  try {
75991
- const stat6 = fs57.statSync(filePath);
75992
- if (stat6.size > MAX_FILE_SIZE_BYTES4) {
76058
+ const stat7 = fs57.statSync(filePath);
76059
+ if (stat7.size > MAX_FILE_SIZE_BYTES4) {
75993
76060
  return null;
75994
76061
  }
75995
76062
  const content = fs57.readFileSync(filePath, "utf-8");
@@ -76002,7 +76069,7 @@ async function computeComplexityDelta(files, workingDir) {
76002
76069
  let totalComplexity = 0;
76003
76070
  const analyzedFiles = [];
76004
76071
  for (const file3 of files) {
76005
- const fullPath = path75.isAbsolute(file3) ? file3 : path75.join(workingDir, file3);
76072
+ const fullPath = path79.isAbsolute(file3) ? file3 : path79.join(workingDir, file3);
76006
76073
  if (!fs57.existsSync(fullPath)) {
76007
76074
  continue;
76008
76075
  }
@@ -76125,7 +76192,7 @@ function countGoExports(content) {
76125
76192
  function getExportCountForFile(filePath) {
76126
76193
  try {
76127
76194
  const content = fs57.readFileSync(filePath, "utf-8");
76128
- const ext = path75.extname(filePath).toLowerCase();
76195
+ const ext = path79.extname(filePath).toLowerCase();
76129
76196
  switch (ext) {
76130
76197
  case ".ts":
76131
76198
  case ".tsx":
@@ -76151,7 +76218,7 @@ async function computePublicApiDelta(files, workingDir) {
76151
76218
  let totalExports = 0;
76152
76219
  const analyzedFiles = [];
76153
76220
  for (const file3 of files) {
76154
- const fullPath = path75.isAbsolute(file3) ? file3 : path75.join(workingDir, file3);
76221
+ const fullPath = path79.isAbsolute(file3) ? file3 : path79.join(workingDir, file3);
76155
76222
  if (!fs57.existsSync(fullPath)) {
76156
76223
  continue;
76157
76224
  }
@@ -76185,13 +76252,13 @@ async function computeDuplicationRatio(files, workingDir) {
76185
76252
  let duplicateLines = 0;
76186
76253
  const analyzedFiles = [];
76187
76254
  for (const file3 of files) {
76188
- const fullPath = path75.isAbsolute(file3) ? file3 : path75.join(workingDir, file3);
76255
+ const fullPath = path79.isAbsolute(file3) ? file3 : path79.join(workingDir, file3);
76189
76256
  if (!fs57.existsSync(fullPath)) {
76190
76257
  continue;
76191
76258
  }
76192
76259
  try {
76193
- const stat6 = fs57.statSync(fullPath);
76194
- if (stat6.size > MAX_FILE_SIZE_BYTES4) {
76260
+ const stat7 = fs57.statSync(fullPath);
76261
+ if (stat7.size > MAX_FILE_SIZE_BYTES4) {
76195
76262
  continue;
76196
76263
  }
76197
76264
  const content = fs57.readFileSync(fullPath, "utf-8");
@@ -76218,8 +76285,8 @@ function countCodeLines(content) {
76218
76285
  return lines.length;
76219
76286
  }
76220
76287
  function isTestFile(filePath) {
76221
- const basename11 = path75.basename(filePath);
76222
- const _ext = path75.extname(filePath).toLowerCase();
76288
+ const basename11 = path79.basename(filePath);
76289
+ const _ext = path79.extname(filePath).toLowerCase();
76223
76290
  const testPatterns = [
76224
76291
  ".test.",
76225
76292
  ".spec.",
@@ -76300,8 +76367,8 @@ function matchGlobSegment(globSegments, pathSegments) {
76300
76367
  }
76301
76368
  return gIndex === globSegments.length && pIndex === pathSegments.length;
76302
76369
  }
76303
- function matchesGlobSegment(path76, glob) {
76304
- const normalizedPath = path76.replace(/\\/g, "/");
76370
+ function matchesGlobSegment(path80, glob) {
76371
+ const normalizedPath = path80.replace(/\\/g, "/");
76305
76372
  const normalizedGlob = glob.replace(/\\/g, "/");
76306
76373
  if (normalizedPath.includes("//")) {
76307
76374
  return false;
@@ -76332,8 +76399,8 @@ function simpleGlobToRegex2(glob) {
76332
76399
  function hasGlobstar(glob) {
76333
76400
  return glob.includes("**");
76334
76401
  }
76335
- function globMatches(path76, glob) {
76336
- const normalizedPath = path76.replace(/\\/g, "/");
76402
+ function globMatches(path80, glob) {
76403
+ const normalizedPath = path80.replace(/\\/g, "/");
76337
76404
  if (!glob || glob === "") {
76338
76405
  if (normalizedPath.includes("//")) {
76339
76406
  return false;
@@ -76369,7 +76436,7 @@ function shouldExcludeFile(filePath, excludeGlobs) {
76369
76436
  async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
76370
76437
  let testLines = 0;
76371
76438
  let codeLines = 0;
76372
- const srcDir = path75.join(workingDir, "src");
76439
+ const srcDir = path79.join(workingDir, "src");
76373
76440
  if (fs57.existsSync(srcDir)) {
76374
76441
  await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
76375
76442
  codeLines += lines;
@@ -76377,14 +76444,14 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
76377
76444
  }
76378
76445
  const possibleSrcDirs = ["lib", "app", "source", "core"];
76379
76446
  for (const dir of possibleSrcDirs) {
76380
- const dirPath = path75.join(workingDir, dir);
76447
+ const dirPath = path79.join(workingDir, dir);
76381
76448
  if (fs57.existsSync(dirPath)) {
76382
76449
  await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
76383
76450
  codeLines += lines;
76384
76451
  });
76385
76452
  }
76386
76453
  }
76387
- const testsDir = path75.join(workingDir, "tests");
76454
+ const testsDir = path79.join(workingDir, "tests");
76388
76455
  if (fs57.existsSync(testsDir)) {
76389
76456
  await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
76390
76457
  testLines += lines;
@@ -76392,7 +76459,7 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
76392
76459
  }
76393
76460
  const possibleTestDirs = ["test", "__tests__", "specs"];
76394
76461
  for (const dir of possibleTestDirs) {
76395
- const dirPath = path75.join(workingDir, dir);
76462
+ const dirPath = path79.join(workingDir, dir);
76396
76463
  if (fs57.existsSync(dirPath) && dirPath !== testsDir) {
76397
76464
  await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
76398
76465
  testLines += lines;
@@ -76407,7 +76474,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
76407
76474
  try {
76408
76475
  const entries = fs57.readdirSync(dirPath, { withFileTypes: true });
76409
76476
  for (const entry of entries) {
76410
- const fullPath = path75.join(dirPath, entry.name);
76477
+ const fullPath = path79.join(dirPath, entry.name);
76411
76478
  if (entry.isDirectory()) {
76412
76479
  if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
76413
76480
  continue;
@@ -76415,7 +76482,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
76415
76482
  await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
76416
76483
  } else if (entry.isFile()) {
76417
76484
  const relativePath = fullPath.replace(`${dirPath}/`, "");
76418
- const ext = path75.extname(entry.name).toLowerCase();
76485
+ const ext = path79.extname(entry.name).toLowerCase();
76419
76486
  const validExts = [
76420
76487
  ".ts",
76421
76488
  ".tsx",
@@ -76651,8 +76718,8 @@ async function getGitChurn(days, directory) {
76651
76718
  }
76652
76719
  function getComplexityForFile2(filePath) {
76653
76720
  try {
76654
- const stat6 = fs58.statSync(filePath);
76655
- if (stat6.size > MAX_FILE_SIZE_BYTES5) {
76721
+ const stat7 = fs58.statSync(filePath);
76722
+ if (stat7.size > MAX_FILE_SIZE_BYTES5) {
76656
76723
  return null;
76657
76724
  }
76658
76725
  const content = fs58.readFileSync(filePath, "utf-8");
@@ -76666,7 +76733,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
76666
76733
  const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
76667
76734
  const filteredChurn = new Map;
76668
76735
  for (const [file3, count] of churnMap) {
76669
- const ext = path76.extname(file3).toLowerCase();
76736
+ const ext = path80.extname(file3).toLowerCase();
76670
76737
  if (extSet.has(ext)) {
76671
76738
  filteredChurn.set(file3, count);
76672
76739
  }
@@ -76677,7 +76744,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
76677
76744
  for (const [file3, churnCount] of filteredChurn) {
76678
76745
  let fullPath = file3;
76679
76746
  if (!fs58.existsSync(fullPath)) {
76680
- fullPath = path76.join(cwd, file3);
76747
+ fullPath = path80.join(cwd, file3);
76681
76748
  }
76682
76749
  const complexity = getComplexityForFile2(fullPath);
76683
76750
  if (complexity !== null) {
@@ -76846,7 +76913,7 @@ ${body2}`);
76846
76913
  // src/council/council-evidence-writer.ts
76847
76914
  import {
76848
76915
  appendFileSync as appendFileSync6,
76849
- existsSync as existsSync38,
76916
+ existsSync as existsSync40,
76850
76917
  mkdirSync as mkdirSync19,
76851
76918
  readFileSync as readFileSync36,
76852
76919
  writeFileSync as writeFileSync12
@@ -76889,7 +76956,7 @@ function writeCouncilEvidence(workingDir, synthesis) {
76889
76956
  mkdirSync19(dir, { recursive: true });
76890
76957
  const filePath = join69(dir, `${synthesis.taskId}.json`);
76891
76958
  const existingRoot = Object.create(null);
76892
- if (existsSync38(filePath)) {
76959
+ if (existsSync40(filePath)) {
76893
76960
  try {
76894
76961
  const parsed = JSON.parse(readFileSync36(filePath, "utf-8"));
76895
76962
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
@@ -76938,7 +77005,7 @@ function writeCouncilEvidence(workingDir, synthesis) {
76938
77005
 
76939
77006
  // src/council/council-service.ts
76940
77007
  import fs59 from "node:fs";
76941
- import path77 from "node:path";
77008
+ import path81 from "node:path";
76942
77009
 
76943
77010
  // src/council/types.ts
76944
77011
  var COUNCIL_DEFAULTS = {
@@ -77098,9 +77165,9 @@ function synthesizePhaseCouncilAdvisory(phaseNumber, phaseSummary, verdicts, rou
77098
77165
  const unifiedFeedbackMd = buildPhaseCouncilFeedback(phaseNumber, phaseSummary, overallVerdict, rejectingMembers, requiredFixes, advisoryFindings, unresolvedConflicts, roundNumber, cfg.maxRounds);
77099
77166
  const evidencePath = `.swarm/evidence/${phaseNumber}/phase-council.json`;
77100
77167
  const baseDir = workingDir ?? process.cwd();
77101
- const evidenceDir = path77.join(baseDir, ".swarm", "evidence", String(phaseNumber));
77168
+ const evidenceDir = path81.join(baseDir, ".swarm", "evidence", String(phaseNumber));
77102
77169
  fs59.mkdirSync(evidenceDir, { recursive: true });
77103
- const evidenceFile = path77.join(evidenceDir, "phase-council.json");
77170
+ const evidenceFile = path81.join(evidenceDir, "phase-council.json");
77104
77171
  const evidenceBundle = {
77105
77172
  entries: [
77106
77173
  {
@@ -77203,7 +77270,7 @@ function buildPhaseCouncilFeedback(phaseNumber, phaseSummary, verdict, vetoedBy,
77203
77270
  }
77204
77271
 
77205
77272
  // src/council/criteria-store.ts
77206
- 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";
77207
77274
  import { join as join70 } from "node:path";
77208
77275
  var COUNCIL_DIR = ".swarm/council";
77209
77276
  function writeCriteria(workingDir, taskId, criteria) {
@@ -77218,7 +77285,7 @@ function writeCriteria(workingDir, taskId, criteria) {
77218
77285
  }
77219
77286
  function readCriteria(workingDir, taskId) {
77220
77287
  const filePath = join70(workingDir, COUNCIL_DIR, `${safeId(taskId)}.json`);
77221
- if (!existsSync39(filePath))
77288
+ if (!existsSync41(filePath))
77222
77289
  return null;
77223
77290
  try {
77224
77291
  const parsed = JSON.parse(readFileSync37(filePath, "utf-8"));
@@ -77370,7 +77437,7 @@ var submit_council_verdicts = createSwarmTool({
77370
77437
  init_zod();
77371
77438
  init_loader();
77372
77439
  import * as fs60 from "node:fs";
77373
- import * as path78 from "node:path";
77440
+ import * as path82 from "node:path";
77374
77441
 
77375
77442
  // src/council/general-council-advisory.ts
77376
77443
  var ADVISORY_HEADER = "[general_council] (advisory; not blocking)";
@@ -77798,10 +77865,10 @@ var convene_general_council = createSwarmTool({
77798
77865
  const round1 = input.round1Responses;
77799
77866
  const round2 = input.round2Responses ?? [];
77800
77867
  const result = synthesizeGeneralCouncil(input.question, input.mode, round1, round2);
77801
- const evidenceDir = path78.join(workingDir, ".swarm", "council", "general");
77868
+ const evidenceDir = path82.join(workingDir, ".swarm", "council", "general");
77802
77869
  const safeTimestamp = result.timestamp.replace(/[:.]/g, "-");
77803
77870
  const evidenceFile = `${safeTimestamp}-${input.mode}.json`;
77804
- const evidencePath = path78.join(evidenceDir, evidenceFile);
77871
+ const evidencePath = path82.join(evidenceDir, evidenceFile);
77805
77872
  try {
77806
77873
  await fs60.promises.mkdir(evidenceDir, { recursive: true });
77807
77874
  await fs60.promises.writeFile(evidencePath, JSON.stringify(result, null, 2));
@@ -78036,7 +78103,7 @@ init_state();
78036
78103
  init_task_id();
78037
78104
  init_create_tool();
78038
78105
  import * as fs61 from "node:fs";
78039
- import * as path79 from "node:path";
78106
+ import * as path83 from "node:path";
78040
78107
  function validateTaskIdFormat2(taskId) {
78041
78108
  return validateTaskIdFormat(taskId);
78042
78109
  }
@@ -78110,8 +78177,8 @@ async function executeDeclareScope(args2, fallbackDir) {
78110
78177
  };
78111
78178
  }
78112
78179
  }
78113
- normalizedDir = path79.normalize(args2.working_directory);
78114
- const pathParts = normalizedDir.split(path79.sep);
78180
+ normalizedDir = path83.normalize(args2.working_directory);
78181
+ const pathParts = normalizedDir.split(path83.sep);
78115
78182
  if (pathParts.includes("..")) {
78116
78183
  return {
78117
78184
  success: false,
@@ -78121,10 +78188,10 @@ async function executeDeclareScope(args2, fallbackDir) {
78121
78188
  ]
78122
78189
  };
78123
78190
  }
78124
- const resolvedDir = path79.resolve(normalizedDir);
78191
+ const resolvedDir = path83.resolve(normalizedDir);
78125
78192
  try {
78126
78193
  const realPath = fs61.realpathSync(resolvedDir);
78127
- const planPath2 = path79.join(realPath, ".swarm", "plan.json");
78194
+ const planPath2 = path83.join(realPath, ".swarm", "plan.json");
78128
78195
  if (!fs61.existsSync(planPath2)) {
78129
78196
  return {
78130
78197
  success: false,
@@ -78148,7 +78215,7 @@ async function executeDeclareScope(args2, fallbackDir) {
78148
78215
  console.warn("[declare-scope] fallbackDir is undefined, falling back to process.cwd()");
78149
78216
  }
78150
78217
  const directory = normalizedDir || fallbackDir;
78151
- const planPath = path79.resolve(directory, ".swarm", "plan.json");
78218
+ const planPath = path83.resolve(directory, ".swarm", "plan.json");
78152
78219
  if (!fs61.existsSync(planPath)) {
78153
78220
  return {
78154
78221
  success: false,
@@ -78188,8 +78255,8 @@ async function executeDeclareScope(args2, fallbackDir) {
78188
78255
  const normalizeErrors = [];
78189
78256
  const dir = normalizedDir || fallbackDir || process.cwd();
78190
78257
  const mergedFiles = rawMergedFiles.map((file3) => {
78191
- if (path79.isAbsolute(file3)) {
78192
- const relativePath = path79.relative(dir, file3).replace(/\\/g, "/");
78258
+ if (path83.isAbsolute(file3)) {
78259
+ const relativePath = path83.relative(dir, file3).replace(/\\/g, "/");
78193
78260
  if (relativePath.startsWith("..")) {
78194
78261
  normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
78195
78262
  return file3;
@@ -78250,7 +78317,7 @@ var declare_scope = createSwarmTool({
78250
78317
  init_zod();
78251
78318
  import * as child_process7 from "node:child_process";
78252
78319
  import * as fs62 from "node:fs";
78253
- import * as path80 from "node:path";
78320
+ import * as path84 from "node:path";
78254
78321
  init_create_tool();
78255
78322
  var MAX_DIFF_LINES = 500;
78256
78323
  var DIFF_TIMEOUT_MS = 30000;
@@ -78279,20 +78346,20 @@ function validateBase(base) {
78279
78346
  function validatePaths(paths) {
78280
78347
  if (!paths)
78281
78348
  return null;
78282
- for (const path81 of paths) {
78283
- if (!path81 || path81.length === 0) {
78349
+ for (const path85 of paths) {
78350
+ if (!path85 || path85.length === 0) {
78284
78351
  return "empty path not allowed";
78285
78352
  }
78286
- if (path81.length > MAX_PATH_LENGTH) {
78353
+ if (path85.length > MAX_PATH_LENGTH) {
78287
78354
  return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
78288
78355
  }
78289
- if (SHELL_METACHARACTERS2.test(path81)) {
78356
+ if (SHELL_METACHARACTERS2.test(path85)) {
78290
78357
  return "path contains shell metacharacters";
78291
78358
  }
78292
- if (path81.startsWith("-")) {
78359
+ if (path85.startsWith("-")) {
78293
78360
  return 'path cannot start with "-" (option-like arguments not allowed)';
78294
78361
  }
78295
- if (CONTROL_CHAR_PATTERN2.test(path81)) {
78362
+ if (CONTROL_CHAR_PATTERN2.test(path85)) {
78296
78363
  return "path contains control characters";
78297
78364
  }
78298
78365
  }
@@ -78398,8 +78465,8 @@ var diff = createSwarmTool({
78398
78465
  if (parts2.length >= 3) {
78399
78466
  const additions = parseInt(parts2[0], 10) || 0;
78400
78467
  const deletions = parseInt(parts2[1], 10) || 0;
78401
- const path81 = parts2[2];
78402
- files.push({ path: path81, additions, deletions });
78468
+ const path85 = parts2[2];
78469
+ files.push({ path: path85, additions, deletions });
78403
78470
  }
78404
78471
  }
78405
78472
  const contractChanges = [];
@@ -78439,7 +78506,7 @@ var diff = createSwarmTool({
78439
78506
  } else if (base === "unstaged") {
78440
78507
  const oldRef = `:${file3.path}`;
78441
78508
  oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
78442
- newContent = fs62.readFileSync(path80.join(directory, file3.path), "utf-8");
78509
+ newContent = fs62.readFileSync(path84.join(directory, file3.path), "utf-8");
78443
78510
  } else {
78444
78511
  const oldRef = `${base}:${file3.path}`;
78445
78512
  oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
@@ -78514,7 +78581,7 @@ var diff = createSwarmTool({
78514
78581
  init_zod();
78515
78582
  import * as child_process8 from "node:child_process";
78516
78583
  import * as fs63 from "node:fs";
78517
- import * as path81 from "node:path";
78584
+ import * as path85 from "node:path";
78518
78585
  init_create_tool();
78519
78586
  var diff_summary = createSwarmTool({
78520
78587
  description: "Generate a filtered semantic diff summary from AST analysis. Returns SemanticDiffSummary with optional filtering by classification or riskLevel.",
@@ -78562,7 +78629,7 @@ var diff_summary = createSwarmTool({
78562
78629
  }
78563
78630
  try {
78564
78631
  let oldContent;
78565
- const newContent = fs63.readFileSync(path81.join(workingDir, filePath), "utf-8");
78632
+ const newContent = fs63.readFileSync(path85.join(workingDir, filePath), "utf-8");
78566
78633
  if (fileExistsInHead) {
78567
78634
  oldContent = child_process8.execFileSync("git", ["show", `HEAD:${filePath}`], {
78568
78635
  encoding: "utf-8",
@@ -78791,7 +78858,7 @@ init_zod();
78791
78858
  init_create_tool();
78792
78859
  init_path_security();
78793
78860
  import * as fs64 from "node:fs";
78794
- import * as path82 from "node:path";
78861
+ import * as path86 from "node:path";
78795
78862
  var MAX_FILE_SIZE_BYTES6 = 1024 * 1024;
78796
78863
  var MAX_EVIDENCE_FILES = 1000;
78797
78864
  var EVIDENCE_DIR3 = ".swarm/evidence";
@@ -78818,9 +78885,9 @@ function validateRequiredTypes(input) {
78818
78885
  return null;
78819
78886
  }
78820
78887
  function isPathWithinSwarm2(filePath, cwd) {
78821
- const normalizedCwd = path82.resolve(cwd);
78822
- const swarmPath = path82.join(normalizedCwd, ".swarm");
78823
- const normalizedPath = path82.resolve(filePath);
78888
+ const normalizedCwd = path86.resolve(cwd);
78889
+ const swarmPath = path86.join(normalizedCwd, ".swarm");
78890
+ const normalizedPath = path86.resolve(filePath);
78824
78891
  return normalizedPath.startsWith(swarmPath);
78825
78892
  }
78826
78893
  function parseCompletedTasks(planContent) {
@@ -78850,15 +78917,15 @@ function readEvidenceFiles(evidenceDir, _cwd) {
78850
78917
  if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
78851
78918
  continue;
78852
78919
  }
78853
- const filePath = path82.join(evidenceDir, filename);
78920
+ const filePath = path86.join(evidenceDir, filename);
78854
78921
  try {
78855
- const resolvedPath = path82.resolve(filePath);
78856
- const evidenceDirResolved = path82.resolve(evidenceDir);
78922
+ const resolvedPath = path86.resolve(filePath);
78923
+ const evidenceDirResolved = path86.resolve(evidenceDir);
78857
78924
  if (!resolvedPath.startsWith(evidenceDirResolved)) {
78858
78925
  continue;
78859
78926
  }
78860
- const stat6 = fs64.lstatSync(filePath);
78861
- if (!stat6.isFile()) {
78927
+ const stat7 = fs64.lstatSync(filePath);
78928
+ if (!stat7.isFile()) {
78862
78929
  continue;
78863
78930
  }
78864
78931
  } catch {
@@ -78971,7 +79038,7 @@ var evidence_check = createSwarmTool({
78971
79038
  return JSON.stringify(errorResult, null, 2);
78972
79039
  }
78973
79040
  const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
78974
- const planPath = path82.join(cwd, PLAN_FILE);
79041
+ const planPath = path86.join(cwd, PLAN_FILE);
78975
79042
  if (!isPathWithinSwarm2(planPath, cwd)) {
78976
79043
  const errorResult = {
78977
79044
  error: "plan file path validation failed",
@@ -79003,7 +79070,7 @@ var evidence_check = createSwarmTool({
79003
79070
  };
79004
79071
  return JSON.stringify(result2, null, 2);
79005
79072
  }
79006
- const evidenceDir = path82.join(cwd, EVIDENCE_DIR3);
79073
+ const evidenceDir = path86.join(cwd, EVIDENCE_DIR3);
79007
79074
  const evidence = readEvidenceFiles(evidenceDir, cwd);
79008
79075
  const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
79009
79076
  const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
@@ -79021,7 +79088,7 @@ var evidence_check = createSwarmTool({
79021
79088
  init_zod();
79022
79089
  init_create_tool();
79023
79090
  import * as fs65 from "node:fs";
79024
- import * as path83 from "node:path";
79091
+ import * as path87 from "node:path";
79025
79092
  var EXT_MAP = {
79026
79093
  python: ".py",
79027
79094
  py: ".py",
@@ -79102,12 +79169,12 @@ var extract_code_blocks = createSwarmTool({
79102
79169
  if (prefix) {
79103
79170
  filename = `${prefix}_${filename}`;
79104
79171
  }
79105
- let filepath = path83.join(targetDir, filename);
79106
- const base = path83.basename(filepath, path83.extname(filepath));
79107
- 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);
79108
79175
  let counter = 1;
79109
79176
  while (fs65.existsSync(filepath)) {
79110
- filepath = path83.join(targetDir, `${base}_${counter}${ext}`);
79177
+ filepath = path87.join(targetDir, `${base}_${counter}${ext}`);
79111
79178
  counter++;
79112
79179
  }
79113
79180
  try {
@@ -79283,7 +79350,7 @@ init_create_tool();
79283
79350
  var GITINGEST_TIMEOUT_MS = 1e4;
79284
79351
  var GITINGEST_MAX_RESPONSE_BYTES = 5242880;
79285
79352
  var GITINGEST_MAX_RETRIES = 2;
79286
- var delay = (ms) => new Promise((resolve30) => setTimeout(resolve30, ms));
79353
+ var delay = (ms) => new Promise((resolve31) => setTimeout(resolve31, ms));
79287
79354
  async function fetchGitingest(args2) {
79288
79355
  for (let attempt = 0;attempt <= GITINGEST_MAX_RETRIES; attempt++) {
79289
79356
  try {
@@ -79371,7 +79438,7 @@ init_zod();
79371
79438
  init_create_tool();
79372
79439
  init_path_security();
79373
79440
  import * as fs66 from "node:fs";
79374
- import * as path84 from "node:path";
79441
+ import * as path88 from "node:path";
79375
79442
  var MAX_FILE_PATH_LENGTH2 = 500;
79376
79443
  var MAX_SYMBOL_LENGTH = 256;
79377
79444
  var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
@@ -79419,7 +79486,7 @@ function validateSymbolInput(symbol3) {
79419
79486
  return null;
79420
79487
  }
79421
79488
  function isBinaryFile2(filePath, buffer) {
79422
- const ext = path84.extname(filePath).toLowerCase();
79489
+ const ext = path88.extname(filePath).toLowerCase();
79423
79490
  if (ext === ".json" || ext === ".md" || ext === ".txt") {
79424
79491
  return false;
79425
79492
  }
@@ -79443,15 +79510,15 @@ function parseImports(content, targetFile, targetSymbol) {
79443
79510
  const imports = [];
79444
79511
  let _resolvedTarget;
79445
79512
  try {
79446
- _resolvedTarget = path84.resolve(targetFile);
79513
+ _resolvedTarget = path88.resolve(targetFile);
79447
79514
  } catch {
79448
79515
  _resolvedTarget = targetFile;
79449
79516
  }
79450
- const targetBasename = path84.basename(targetFile, path84.extname(targetFile));
79517
+ const targetBasename = path88.basename(targetFile, path88.extname(targetFile));
79451
79518
  const targetWithExt = targetFile;
79452
79519
  const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
79453
- const normalizedTargetWithExt = path84.normalize(targetWithExt).replace(/\\/g, "/");
79454
- const normalizedTargetWithoutExt = path84.normalize(targetWithoutExt).replace(/\\/g, "/");
79520
+ const normalizedTargetWithExt = path88.normalize(targetWithExt).replace(/\\/g, "/");
79521
+ const normalizedTargetWithoutExt = path88.normalize(targetWithoutExt).replace(/\\/g, "/");
79455
79522
  const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
79456
79523
  for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
79457
79524
  const modulePath = match[1] || match[2] || match[3];
@@ -79474,9 +79541,9 @@ function parseImports(content, targetFile, targetSymbol) {
79474
79541
  }
79475
79542
  const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
79476
79543
  let isMatch = false;
79477
- const _targetDir = path84.dirname(targetFile);
79478
- const targetExt = path84.extname(targetFile);
79479
- 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);
79480
79547
  const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
79481
79548
  const moduleName = modulePath.split(/[/\\]/).pop() || "";
79482
79549
  const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
@@ -79544,13 +79611,13 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
79544
79611
  entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
79545
79612
  for (const entry of entries) {
79546
79613
  if (SKIP_DIRECTORIES4.has(entry)) {
79547
- stats.skippedDirs.push(path84.join(dir, entry));
79614
+ stats.skippedDirs.push(path88.join(dir, entry));
79548
79615
  continue;
79549
79616
  }
79550
- const fullPath = path84.join(dir, entry);
79551
- let stat6;
79617
+ const fullPath = path88.join(dir, entry);
79618
+ let stat7;
79552
79619
  try {
79553
- stat6 = fs66.statSync(fullPath);
79620
+ stat7 = fs66.statSync(fullPath);
79554
79621
  } catch (e) {
79555
79622
  stats.fileErrors.push({
79556
79623
  path: fullPath,
@@ -79558,10 +79625,10 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
79558
79625
  });
79559
79626
  continue;
79560
79627
  }
79561
- if (stat6.isDirectory()) {
79628
+ if (stat7.isDirectory()) {
79562
79629
  findSourceFiles2(fullPath, files, stats);
79563
- } else if (stat6.isFile()) {
79564
- const ext = path84.extname(fullPath).toLowerCase();
79630
+ } else if (stat7.isFile()) {
79631
+ const ext = path88.extname(fullPath).toLowerCase();
79565
79632
  if (SUPPORTED_EXTENSIONS3.includes(ext)) {
79566
79633
  files.push(fullPath);
79567
79634
  }
@@ -79618,7 +79685,7 @@ var imports = createSwarmTool({
79618
79685
  return JSON.stringify(errorResult, null, 2);
79619
79686
  }
79620
79687
  try {
79621
- const targetFile = path84.resolve(file3);
79688
+ const targetFile = path88.resolve(file3);
79622
79689
  if (!fs66.existsSync(targetFile)) {
79623
79690
  const errorResult = {
79624
79691
  error: `target file not found: ${file3}`,
@@ -79640,7 +79707,7 @@ var imports = createSwarmTool({
79640
79707
  };
79641
79708
  return JSON.stringify(errorResult, null, 2);
79642
79709
  }
79643
- const baseDir = path84.dirname(targetFile);
79710
+ const baseDir = path88.dirname(targetFile);
79644
79711
  const scanStats = {
79645
79712
  skippedDirs: [],
79646
79713
  skippedFiles: 0,
@@ -79655,8 +79722,8 @@ var imports = createSwarmTool({
79655
79722
  if (consumers.length >= MAX_CONSUMERS)
79656
79723
  break;
79657
79724
  try {
79658
- const stat6 = fs66.statSync(filePath);
79659
- if (stat6.size > MAX_FILE_SIZE_BYTES7) {
79725
+ const stat7 = fs66.statSync(filePath);
79726
+ if (stat7.size > MAX_FILE_SIZE_BYTES7) {
79660
79727
  skippedFileCount++;
79661
79728
  continue;
79662
79729
  }
@@ -79873,7 +79940,7 @@ init_zod();
79873
79940
  init_config();
79874
79941
  init_knowledge_store();
79875
79942
  init_create_tool();
79876
- import { existsSync as existsSync44 } from "node:fs";
79943
+ import { existsSync as existsSync46 } from "node:fs";
79877
79944
  var DEFAULT_LIMIT = 10;
79878
79945
  var MAX_LESSON_LENGTH = 200;
79879
79946
  var VALID_CATEGORIES3 = [
@@ -79943,14 +80010,14 @@ function validateLimit(limit) {
79943
80010
  }
79944
80011
  async function readSwarmKnowledge(directory) {
79945
80012
  const swarmPath = resolveSwarmKnowledgePath(directory);
79946
- if (!existsSync44(swarmPath)) {
80013
+ if (!existsSync46(swarmPath)) {
79947
80014
  return [];
79948
80015
  }
79949
80016
  return readKnowledge(swarmPath);
79950
80017
  }
79951
80018
  async function readHiveKnowledge() {
79952
80019
  const hivePath = resolveHiveKnowledgePath();
79953
- if (!existsSync44(hivePath)) {
80020
+ if (!existsSync46(hivePath)) {
79954
80021
  return [];
79955
80022
  }
79956
80023
  return readKnowledge(hivePath);
@@ -80186,7 +80253,7 @@ init_qa_gate_profile();
80186
80253
  init_manager2();
80187
80254
  init_curator();
80188
80255
  import * as fs68 from "node:fs";
80189
- import * as path86 from "node:path";
80256
+ import * as path90 from "node:path";
80190
80257
  init_knowledge_curator();
80191
80258
  init_knowledge_reader();
80192
80259
  init_knowledge_store();
@@ -80199,16 +80266,16 @@ init_plan_schema();
80199
80266
  init_ledger();
80200
80267
  init_manager();
80201
80268
  import * as fs67 from "node:fs";
80202
- import * as path85 from "node:path";
80269
+ import * as path89 from "node:path";
80203
80270
  async function writeCheckpoint(directory) {
80204
80271
  try {
80205
80272
  const plan = await loadPlan(directory);
80206
80273
  if (!plan)
80207
80274
  return;
80208
- const swarmDir = path85.join(directory, ".swarm");
80275
+ const swarmDir = path89.join(directory, ".swarm");
80209
80276
  fs67.mkdirSync(swarmDir, { recursive: true });
80210
- const jsonPath = path85.join(swarmDir, "SWARM_PLAN.json");
80211
- 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");
80212
80279
  fs67.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
80213
80280
  const md = derivePlanMarkdown(plan);
80214
80281
  fs67.writeFileSync(mdPath, md, "utf8");
@@ -80443,7 +80510,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
80443
80510
  let driftCheckEnabled = true;
80444
80511
  let driftHasSpecMd = false;
80445
80512
  try {
80446
- const specMdPath = path86.join(dir, ".swarm", "spec.md");
80513
+ const specMdPath = path90.join(dir, ".swarm", "spec.md");
80447
80514
  driftHasSpecMd = fs68.existsSync(specMdPath);
80448
80515
  const gatePlan = await loadPlan(dir);
80449
80516
  if (gatePlan) {
@@ -80465,7 +80532,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
80465
80532
  } else {
80466
80533
  let phaseType;
80467
80534
  try {
80468
- const planPath = path86.join(dir, ".swarm", "plan.json");
80535
+ const planPath = path90.join(dir, ".swarm", "plan.json");
80469
80536
  if (fs68.existsSync(planPath)) {
80470
80537
  const planRaw = fs68.readFileSync(planPath, "utf-8");
80471
80538
  const plan = JSON.parse(planRaw);
@@ -80478,7 +80545,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
80478
80545
  warnings.push(`Phase ${phase} is annotated as 'non-code'. Drift verification was skipped per phase type annotation.`);
80479
80546
  } else {
80480
80547
  try {
80481
- 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");
80482
80549
  let driftVerdictFound = false;
80483
80550
  let driftVerdictApproved = false;
80484
80551
  try {
@@ -80516,7 +80583,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
80516
80583
  let incompleteTaskCount = 0;
80517
80584
  let planParseable = false;
80518
80585
  try {
80519
- const planPath = path86.join(dir, ".swarm", "plan.json");
80586
+ const planPath = path90.join(dir, ".swarm", "plan.json");
80520
80587
  if (fs68.existsSync(planPath)) {
80521
80588
  const planRaw = fs68.readFileSync(planPath, "utf-8");
80522
80589
  const plan = JSON.parse(planRaw);
@@ -80583,7 +80650,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
80583
80650
  const overrides = session2?.qaGateSessionOverrides ?? {};
80584
80651
  const effective = getEffectiveGates(profile, overrides);
80585
80652
  if (effective.hallucination_guard === true) {
80586
- 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");
80587
80654
  let hgVerdictFound = false;
80588
80655
  let hgVerdictApproved = false;
80589
80656
  try {
@@ -80655,7 +80722,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
80655
80722
  const overrides = session2?.qaGateSessionOverrides ?? {};
80656
80723
  const effective = getEffectiveGates(profile, overrides);
80657
80724
  if (effective.mutation_test === true) {
80658
- 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");
80659
80726
  let mgVerdictFound = false;
80660
80727
  let mgVerdict;
80661
80728
  try {
@@ -80729,7 +80796,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
80729
80796
  const effective = getEffectiveGates(profile, overrides);
80730
80797
  if (effective.council_mode === true) {
80731
80798
  councilModeEnabled = true;
80732
- 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");
80733
80800
  let pcVerdictFound = false;
80734
80801
  let _pcVerdict;
80735
80802
  let pcQuorumSize;
@@ -80931,7 +80998,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
80931
80998
  }
80932
80999
  if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
80933
81000
  try {
80934
- const projectName = path86.basename(dir);
81001
+ const projectName = path90.basename(dir);
80935
81002
  const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
80936
81003
  if (curationResult) {
80937
81004
  const sessionState = swarmState.agentSessions.get(sessionID);
@@ -81301,7 +81368,7 @@ init_utils();
81301
81368
  init_bun_compat();
81302
81369
  init_create_tool();
81303
81370
  import * as fs69 from "node:fs";
81304
- import * as path87 from "node:path";
81371
+ import * as path91 from "node:path";
81305
81372
  var MAX_OUTPUT_BYTES5 = 52428800;
81306
81373
  var AUDIT_TIMEOUT_MS = 120000;
81307
81374
  function isValidEcosystem(value) {
@@ -81329,16 +81396,16 @@ function validateArgs3(args2) {
81329
81396
  function detectEcosystems(directory) {
81330
81397
  const ecosystems = [];
81331
81398
  const cwd = directory;
81332
- if (fs69.existsSync(path87.join(cwd, "package.json"))) {
81399
+ if (fs69.existsSync(path91.join(cwd, "package.json"))) {
81333
81400
  ecosystems.push("npm");
81334
81401
  }
81335
- 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"))) {
81336
81403
  ecosystems.push("pip");
81337
81404
  }
81338
- if (fs69.existsSync(path87.join(cwd, "Cargo.toml"))) {
81405
+ if (fs69.existsSync(path91.join(cwd, "Cargo.toml"))) {
81339
81406
  ecosystems.push("cargo");
81340
81407
  }
81341
- if (fs69.existsSync(path87.join(cwd, "go.mod"))) {
81408
+ if (fs69.existsSync(path91.join(cwd, "go.mod"))) {
81342
81409
  ecosystems.push("go");
81343
81410
  }
81344
81411
  try {
@@ -81347,13 +81414,13 @@ function detectEcosystems(directory) {
81347
81414
  ecosystems.push("dotnet");
81348
81415
  }
81349
81416
  } catch {}
81350
- 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"))) {
81351
81418
  ecosystems.push("ruby");
81352
81419
  }
81353
- if (fs69.existsSync(path87.join(cwd, "pubspec.yaml"))) {
81420
+ if (fs69.existsSync(path91.join(cwd, "pubspec.yaml"))) {
81354
81421
  ecosystems.push("dart");
81355
81422
  }
81356
- if (fs69.existsSync(path87.join(cwd, "composer.lock"))) {
81423
+ if (fs69.existsSync(path91.join(cwd, "composer.lock"))) {
81357
81424
  ecosystems.push("composer");
81358
81425
  }
81359
81426
  return ecosystems;
@@ -81366,7 +81433,7 @@ async function runNpmAudit(directory) {
81366
81433
  stderr: "pipe",
81367
81434
  cwd: directory
81368
81435
  });
81369
- const timeoutPromise = new Promise((resolve31) => setTimeout(() => resolve31("timeout"), AUDIT_TIMEOUT_MS));
81436
+ const timeoutPromise = new Promise((resolve32) => setTimeout(() => resolve32("timeout"), AUDIT_TIMEOUT_MS));
81370
81437
  const result = await Promise.race([
81371
81438
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr2]) => ({ stdout: stdout2, stderr: stderr2 })),
81372
81439
  timeoutPromise
@@ -81486,7 +81553,7 @@ async function runPipAudit(directory) {
81486
81553
  stderr: "pipe",
81487
81554
  cwd: directory
81488
81555
  });
81489
- const timeoutPromise = new Promise((resolve31) => setTimeout(() => resolve31("timeout"), AUDIT_TIMEOUT_MS));
81556
+ const timeoutPromise = new Promise((resolve32) => setTimeout(() => resolve32("timeout"), AUDIT_TIMEOUT_MS));
81490
81557
  const result = await Promise.race([
81491
81558
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr2]) => ({ stdout: stdout2, stderr: stderr2 })),
81492
81559
  timeoutPromise
@@ -81614,7 +81681,7 @@ async function runCargoAudit(directory) {
81614
81681
  stderr: "pipe",
81615
81682
  cwd: directory
81616
81683
  });
81617
- const timeoutPromise = new Promise((resolve31) => setTimeout(() => resolve31("timeout"), AUDIT_TIMEOUT_MS));
81684
+ const timeoutPromise = new Promise((resolve32) => setTimeout(() => resolve32("timeout"), AUDIT_TIMEOUT_MS));
81618
81685
  const result = await Promise.race([
81619
81686
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
81620
81687
  timeoutPromise
@@ -81738,7 +81805,7 @@ async function runGoAudit(directory) {
81738
81805
  stderr: "pipe",
81739
81806
  cwd: directory
81740
81807
  });
81741
- const timeoutPromise = new Promise((resolve31) => setTimeout(() => resolve31("timeout"), AUDIT_TIMEOUT_MS));
81808
+ const timeoutPromise = new Promise((resolve32) => setTimeout(() => resolve32("timeout"), AUDIT_TIMEOUT_MS));
81742
81809
  const result = await Promise.race([
81743
81810
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
81744
81811
  timeoutPromise
@@ -81871,7 +81938,7 @@ async function runDotnetAudit(directory) {
81871
81938
  stderr: "pipe",
81872
81939
  cwd: directory
81873
81940
  });
81874
- const timeoutPromise = new Promise((resolve31) => setTimeout(() => resolve31("timeout"), AUDIT_TIMEOUT_MS));
81941
+ const timeoutPromise = new Promise((resolve32) => setTimeout(() => resolve32("timeout"), AUDIT_TIMEOUT_MS));
81875
81942
  const result = await Promise.race([
81876
81943
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
81877
81944
  timeoutPromise
@@ -81987,7 +82054,7 @@ async function runBundleAudit(directory) {
81987
82054
  stderr: "pipe",
81988
82055
  cwd: directory
81989
82056
  });
81990
- const timeoutPromise = new Promise((resolve31) => setTimeout(() => resolve31("timeout"), AUDIT_TIMEOUT_MS));
82057
+ const timeoutPromise = new Promise((resolve32) => setTimeout(() => resolve32("timeout"), AUDIT_TIMEOUT_MS));
81991
82058
  const result = await Promise.race([
81992
82059
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
81993
82060
  timeoutPromise
@@ -82132,7 +82199,7 @@ async function runDartAudit(directory) {
82132
82199
  stderr: "pipe",
82133
82200
  cwd: directory
82134
82201
  });
82135
- const timeoutPromise = new Promise((resolve31) => setTimeout(() => resolve31("timeout"), AUDIT_TIMEOUT_MS));
82202
+ const timeoutPromise = new Promise((resolve32) => setTimeout(() => resolve32("timeout"), AUDIT_TIMEOUT_MS));
82136
82203
  const result = await Promise.race([
82137
82204
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
82138
82205
  timeoutPromise
@@ -82247,7 +82314,7 @@ async function runComposerAudit(directory) {
82247
82314
  stderr: "pipe",
82248
82315
  cwd: directory
82249
82316
  });
82250
- const timeoutPromise = new Promise((resolve31) => setTimeout(() => resolve31("timeout"), AUDIT_TIMEOUT_MS));
82317
+ const timeoutPromise = new Promise((resolve32) => setTimeout(() => resolve32("timeout"), AUDIT_TIMEOUT_MS));
82251
82318
  const result = await Promise.race([
82252
82319
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
82253
82320
  timeoutPromise
@@ -82489,7 +82556,7 @@ var pkg_audit = createSwarmTool({
82489
82556
  init_zod();
82490
82557
  init_manager2();
82491
82558
  import * as fs70 from "node:fs";
82492
- import * as path88 from "node:path";
82559
+ import * as path92 from "node:path";
82493
82560
  init_utils();
82494
82561
  init_create_tool();
82495
82562
  var MAX_FILE_SIZE = 1024 * 1024;
@@ -82612,7 +82679,7 @@ function isScaffoldFile(filePath) {
82612
82679
  if (SCAFFOLD_PATH_PATTERNS.some((pattern) => pattern.test(normalizedPath))) {
82613
82680
  return true;
82614
82681
  }
82615
- const filename = path88.basename(filePath);
82682
+ const filename = path92.basename(filePath);
82616
82683
  if (SCAFFOLD_FILENAME_PATTERNS.some((pattern) => pattern.test(filename))) {
82617
82684
  return true;
82618
82685
  }
@@ -82629,7 +82696,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
82629
82696
  if (regex.test(normalizedPath)) {
82630
82697
  return true;
82631
82698
  }
82632
- const filename = path88.basename(filePath);
82699
+ const filename = path92.basename(filePath);
82633
82700
  const filenameRegex = new RegExp(`^${regexPattern}$`, "i");
82634
82701
  if (filenameRegex.test(filename)) {
82635
82702
  return true;
@@ -82638,7 +82705,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
82638
82705
  return false;
82639
82706
  }
82640
82707
  function isParserSupported(filePath) {
82641
- const ext = path88.extname(filePath).toLowerCase();
82708
+ const ext = path92.extname(filePath).toLowerCase();
82642
82709
  return SUPPORTED_PARSER_EXTENSIONS.has(ext);
82643
82710
  }
82644
82711
  function isPlanFile(filePath) {
@@ -82885,9 +82952,9 @@ async function placeholderScan(input, directory) {
82885
82952
  let filesScanned = 0;
82886
82953
  const filesWithFindings = new Set;
82887
82954
  for (const filePath of changed_files) {
82888
- const fullPath = path88.isAbsolute(filePath) ? filePath : path88.resolve(directory, filePath);
82889
- const resolvedDirectory = path88.resolve(directory);
82890
- 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) {
82891
82958
  continue;
82892
82959
  }
82893
82960
  if (!fs70.existsSync(fullPath)) {
@@ -82896,14 +82963,14 @@ async function placeholderScan(input, directory) {
82896
82963
  if (isAllowedByGlobs(filePath, allow_globs)) {
82897
82964
  continue;
82898
82965
  }
82899
- const relativeFilePath = path88.relative(directory, fullPath).replace(/\\/g, "/");
82966
+ const relativeFilePath = path92.relative(directory, fullPath).replace(/\\/g, "/");
82900
82967
  if (FILE_ALLOWLIST.some((allowed) => relativeFilePath.endsWith(allowed))) {
82901
82968
  continue;
82902
82969
  }
82903
82970
  let content;
82904
82971
  try {
82905
- const stat6 = fs70.statSync(fullPath);
82906
- if (stat6.size > MAX_FILE_SIZE) {
82972
+ const stat7 = fs70.statSync(fullPath);
82973
+ if (stat7.size > MAX_FILE_SIZE) {
82907
82974
  continue;
82908
82975
  }
82909
82976
  content = fs70.readFileSync(fullPath, "utf-8");
@@ -82968,7 +83035,7 @@ var placeholder_scan = createSwarmTool({
82968
83035
  });
82969
83036
  // src/tools/pre-check-batch.ts
82970
83037
  import * as fs73 from "node:fs";
82971
- import * as path91 from "node:path";
83038
+ import * as path95 from "node:path";
82972
83039
  init_zod();
82973
83040
  init_manager2();
82974
83041
  init_utils();
@@ -83106,7 +83173,7 @@ init_zod();
83106
83173
  init_manager2();
83107
83174
  init_detector();
83108
83175
  import * as fs72 from "node:fs";
83109
- import * as path90 from "node:path";
83176
+ import * as path94 from "node:path";
83110
83177
  import { extname as extname18 } from "node:path";
83111
83178
 
83112
83179
  // src/sast/rules/c.ts
@@ -83887,7 +83954,7 @@ function mapSemgrepSeverity(severity) {
83887
83954
  }
83888
83955
  }
83889
83956
  async function executeWithTimeout(command, args2, options) {
83890
- return new Promise((resolve32) => {
83957
+ return new Promise((resolve33) => {
83891
83958
  const child = child_process9.spawn(command, args2, {
83892
83959
  shell: false,
83893
83960
  cwd: options.cwd
@@ -83896,7 +83963,7 @@ async function executeWithTimeout(command, args2, options) {
83896
83963
  let stderr = "";
83897
83964
  const timeout = setTimeout(() => {
83898
83965
  child.kill("SIGTERM");
83899
- resolve32({
83966
+ resolve33({
83900
83967
  stdout,
83901
83968
  stderr: "Process timed out",
83902
83969
  exitCode: 124
@@ -83910,7 +83977,7 @@ async function executeWithTimeout(command, args2, options) {
83910
83977
  });
83911
83978
  child.on("close", (code) => {
83912
83979
  clearTimeout(timeout);
83913
- resolve32({
83980
+ resolve33({
83914
83981
  stdout,
83915
83982
  stderr,
83916
83983
  exitCode: code ?? 0
@@ -83918,7 +83985,7 @@ async function executeWithTimeout(command, args2, options) {
83918
83985
  });
83919
83986
  child.on("error", (err2) => {
83920
83987
  clearTimeout(timeout);
83921
- resolve32({
83988
+ resolve33({
83922
83989
  stdout,
83923
83990
  stderr: err2.message,
83924
83991
  exitCode: 1
@@ -84000,24 +84067,24 @@ init_create_tool();
84000
84067
  init_utils2();
84001
84068
  import * as crypto8 from "node:crypto";
84002
84069
  import * as fs71 from "node:fs";
84003
- import * as path89 from "node:path";
84070
+ import * as path93 from "node:path";
84004
84071
  var BASELINE_SCHEMA_VERSION = "1.0.0";
84005
84072
  var MAX_BASELINE_FINDINGS = 2000;
84006
84073
  var MAX_BASELINE_BYTES = 2 * 1048576;
84007
84074
  var LOCK_RETRY_DELAYS_MS = [50, 100, 200, 400, 800];
84008
84075
  function normalizeFindingPath(directory, file3) {
84009
- const resolved = path89.isAbsolute(file3) ? file3 : path89.resolve(directory, file3);
84010
- 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);
84011
84078
  return rel.replace(/\\/g, "/");
84012
84079
  }
84013
84080
  function baselineRelPath(phase) {
84014
- return path89.join("evidence", String(phase), "sast-baseline.json");
84081
+ return path93.join("evidence", String(phase), "sast-baseline.json");
84015
84082
  }
84016
84083
  function tempRelPath(phase) {
84017
- 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}`);
84018
84085
  }
84019
84086
  function lockRelPath(phase) {
84020
- return path89.join("evidence", String(phase), "sast-baseline.json.lock");
84087
+ return path93.join("evidence", String(phase), "sast-baseline.json.lock");
84021
84088
  }
84022
84089
  function getLine(lines, idx) {
84023
84090
  if (idx < 0 || idx >= lines.length)
@@ -84103,7 +84170,7 @@ async function acquireLock(lockPath) {
84103
84170
  };
84104
84171
  } catch {
84105
84172
  if (attempt < LOCK_RETRY_DELAYS_MS.length) {
84106
- await new Promise((resolve33) => setTimeout(resolve33, LOCK_RETRY_DELAYS_MS[attempt]));
84173
+ await new Promise((resolve34) => setTimeout(resolve34, LOCK_RETRY_DELAYS_MS[attempt]));
84107
84174
  }
84108
84175
  }
84109
84176
  }
@@ -84138,8 +84205,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
84138
84205
  message: e instanceof Error ? e.message : "Path validation failed"
84139
84206
  };
84140
84207
  }
84141
- fs71.mkdirSync(path89.dirname(baselinePath), { recursive: true });
84142
- fs71.mkdirSync(path89.dirname(tempPath), { recursive: true });
84208
+ fs71.mkdirSync(path93.dirname(baselinePath), { recursive: true });
84209
+ fs71.mkdirSync(path93.dirname(tempPath), { recursive: true });
84143
84210
  const releaseLock = await acquireLock(lockPath);
84144
84211
  try {
84145
84212
  let existing = null;
@@ -84406,9 +84473,9 @@ async function sastScan(input, directory, config3) {
84406
84473
  _filesSkipped++;
84407
84474
  continue;
84408
84475
  }
84409
- const resolvedPath = path90.isAbsolute(filePath) ? filePath : path90.resolve(directory, filePath);
84410
- const resolvedDirectory = path90.resolve(directory);
84411
- 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) {
84412
84479
  _filesSkipped++;
84413
84480
  continue;
84414
84481
  }
@@ -84719,18 +84786,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
84719
84786
  let resolved;
84720
84787
  const isWinAbs = isWindowsAbsolutePath(inputPath);
84721
84788
  if (isWinAbs) {
84722
- resolved = path91.win32.resolve(inputPath);
84723
- } else if (path91.isAbsolute(inputPath)) {
84724
- resolved = path91.resolve(inputPath);
84789
+ resolved = path95.win32.resolve(inputPath);
84790
+ } else if (path95.isAbsolute(inputPath)) {
84791
+ resolved = path95.resolve(inputPath);
84725
84792
  } else {
84726
- resolved = path91.resolve(baseDir, inputPath);
84793
+ resolved = path95.resolve(baseDir, inputPath);
84727
84794
  }
84728
- const workspaceResolved = path91.resolve(workspaceDir);
84795
+ const workspaceResolved = path95.resolve(workspaceDir);
84729
84796
  let relative20;
84730
84797
  if (isWinAbs) {
84731
- relative20 = path91.win32.relative(workspaceResolved, resolved);
84798
+ relative20 = path95.win32.relative(workspaceResolved, resolved);
84732
84799
  } else {
84733
- relative20 = path91.relative(workspaceResolved, resolved);
84800
+ relative20 = path95.relative(workspaceResolved, resolved);
84734
84801
  }
84735
84802
  if (relative20.startsWith("..")) {
84736
84803
  return "path traversal detected";
@@ -84795,7 +84862,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
84795
84862
  if (typeof file3 !== "string") {
84796
84863
  continue;
84797
84864
  }
84798
- const resolvedPath = path91.resolve(file3);
84865
+ const resolvedPath = path95.resolve(file3);
84799
84866
  const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
84800
84867
  if (validationError) {
84801
84868
  continue;
@@ -84952,7 +85019,7 @@ async function runSecretscanWithFiles(files, directory) {
84952
85019
  skippedFiles++;
84953
85020
  continue;
84954
85021
  }
84955
- const resolvedPath = path91.resolve(file3);
85022
+ const resolvedPath = path95.resolve(file3);
84956
85023
  const validationError = validatePath(resolvedPath, directory, directory);
84957
85024
  if (validationError) {
84958
85025
  skippedFiles++;
@@ -84970,19 +85037,19 @@ async function runSecretscanWithFiles(files, directory) {
84970
85037
  };
84971
85038
  }
84972
85039
  for (const file3 of validatedFiles) {
84973
- const ext = path91.extname(file3).toLowerCase();
85040
+ const ext = path95.extname(file3).toLowerCase();
84974
85041
  if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
84975
85042
  skippedFiles++;
84976
85043
  continue;
84977
85044
  }
84978
- let stat6;
85045
+ let stat7;
84979
85046
  try {
84980
- stat6 = fs73.statSync(file3);
85047
+ stat7 = fs73.statSync(file3);
84981
85048
  } catch {
84982
85049
  skippedFiles++;
84983
85050
  continue;
84984
85051
  }
84985
- if (stat6.size > MAX_FILE_SIZE_BYTES9) {
85052
+ if (stat7.size > MAX_FILE_SIZE_BYTES9) {
84986
85053
  skippedFiles++;
84987
85054
  continue;
84988
85055
  }
@@ -85189,7 +85256,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
85189
85256
  const preexistingFindings = [];
85190
85257
  for (const finding of findings) {
85191
85258
  const filePath = finding.location.file;
85192
- const normalised = path91.relative(directory, filePath).replace(/\\/g, "/");
85259
+ const normalised = path95.relative(directory, filePath).replace(/\\/g, "/");
85193
85260
  const changedLines = changedLineRanges.get(normalised);
85194
85261
  if (changedLines?.has(finding.location.line)) {
85195
85262
  newFindings.push(finding);
@@ -85240,7 +85307,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
85240
85307
  warn(`pre_check_batch: Invalid file path: ${file3}`);
85241
85308
  continue;
85242
85309
  }
85243
- changedFiles.push(path91.resolve(directory, file3));
85310
+ changedFiles.push(path95.resolve(directory, file3));
85244
85311
  }
85245
85312
  if (changedFiles.length === 0) {
85246
85313
  warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
@@ -85441,7 +85508,7 @@ var pre_check_batch = createSwarmTool({
85441
85508
  };
85442
85509
  return JSON.stringify(errorResult, null, 2);
85443
85510
  }
85444
- const resolvedDirectory = path91.resolve(typedArgs.directory);
85511
+ const resolvedDirectory = path95.resolve(typedArgs.directory);
85445
85512
  const workspaceAnchor = resolvedDirectory;
85446
85513
  const dirError = validateDirectory2(resolvedDirectory, workspaceAnchor);
85447
85514
  if (dirError) {
@@ -85482,7 +85549,7 @@ var pre_check_batch = createSwarmTool({
85482
85549
  });
85483
85550
  // src/tools/repo-map.ts
85484
85551
  init_zod();
85485
- import * as path92 from "node:path";
85552
+ import * as path96 from "node:path";
85486
85553
  init_path_security();
85487
85554
  init_create_tool();
85488
85555
  var VALID_ACTIONS = [
@@ -85507,7 +85574,7 @@ function validateFile(p) {
85507
85574
  return "file contains control characters";
85508
85575
  if (containsPathTraversal(p))
85509
85576
  return "file contains path traversal";
85510
- if (path92.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
85577
+ if (path96.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
85511
85578
  return "file must be a workspace-relative path, not absolute";
85512
85579
  }
85513
85580
  return null;
@@ -85530,8 +85597,8 @@ function ok(action, payload) {
85530
85597
  }
85531
85598
  function toRelativeGraphPath(input, workspaceRoot) {
85532
85599
  const normalized = input.replace(/\\/g, "/");
85533
- if (path92.isAbsolute(normalized)) {
85534
- const rel = path92.relative(workspaceRoot, normalized).replace(/\\/g, "/");
85600
+ if (path96.isAbsolute(normalized)) {
85601
+ const rel = path96.relative(workspaceRoot, normalized).replace(/\\/g, "/");
85535
85602
  return normalizeGraphPath2(rel);
85536
85603
  }
85537
85604
  return normalizeGraphPath2(normalized);
@@ -85676,7 +85743,7 @@ var repo_map = createSwarmTool({
85676
85743
  init_zod();
85677
85744
  init_create_tool();
85678
85745
  import * as fs74 from "node:fs";
85679
- import * as path93 from "node:path";
85746
+ import * as path97 from "node:path";
85680
85747
  var SPEC_FILE = ".swarm/spec.md";
85681
85748
  var EVIDENCE_DIR4 = ".swarm/evidence";
85682
85749
  var OBLIGATION_KEYWORDS = ["MUST", "SHOULD", "SHALL"];
@@ -85745,10 +85812,10 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
85745
85812
  return [];
85746
85813
  }
85747
85814
  for (const entry of entries) {
85748
- const entryPath = path93.join(evidenceDir, entry);
85815
+ const entryPath = path97.join(evidenceDir, entry);
85749
85816
  try {
85750
- const stat6 = fs74.statSync(entryPath);
85751
- if (!stat6.isDirectory()) {
85817
+ const stat7 = fs74.statSync(entryPath);
85818
+ if (!stat7.isDirectory()) {
85752
85819
  continue;
85753
85820
  }
85754
85821
  } catch {
@@ -85761,18 +85828,18 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
85761
85828
  if (entryPhase !== String(phase)) {
85762
85829
  continue;
85763
85830
  }
85764
- const evidenceFilePath = path93.join(entryPath, "evidence.json");
85831
+ const evidenceFilePath = path97.join(entryPath, "evidence.json");
85765
85832
  try {
85766
- const resolvedPath = path93.resolve(evidenceFilePath);
85767
- const evidenceDirResolved = path93.resolve(evidenceDir);
85768
- 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)) {
85769
85836
  continue;
85770
85837
  }
85771
- const stat6 = fs74.lstatSync(evidenceFilePath);
85772
- if (!stat6.isFile()) {
85838
+ const stat7 = fs74.lstatSync(evidenceFilePath);
85839
+ if (!stat7.isFile()) {
85773
85840
  continue;
85774
85841
  }
85775
- if (stat6.size > MAX_FILE_SIZE_BYTES9) {
85842
+ if (stat7.size > MAX_FILE_SIZE_BYTES9) {
85776
85843
  continue;
85777
85844
  }
85778
85845
  } catch {
@@ -85799,7 +85866,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
85799
85866
  if (Array.isArray(diffEntry.files_changed)) {
85800
85867
  for (const file3 of diffEntry.files_changed) {
85801
85868
  if (typeof file3 === "string") {
85802
- touchedFiles.add(path93.resolve(cwd, file3));
85869
+ touchedFiles.add(path97.resolve(cwd, file3));
85803
85870
  }
85804
85871
  }
85805
85872
  }
@@ -85812,8 +85879,8 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
85812
85879
  }
85813
85880
  function searchFileForKeywords(filePath, keywords, cwd) {
85814
85881
  try {
85815
- const resolvedPath = path93.resolve(filePath);
85816
- const cwdResolved = path93.resolve(cwd);
85882
+ const resolvedPath = path97.resolve(filePath);
85883
+ const cwdResolved = path97.resolve(cwd);
85817
85884
  if (!resolvedPath.startsWith(cwdResolved)) {
85818
85885
  return false;
85819
85886
  }
@@ -85947,7 +86014,7 @@ var req_coverage = createSwarmTool({
85947
86014
  }, null, 2);
85948
86015
  }
85949
86016
  const cwd = inputDirectory || directory;
85950
- const specPath = path93.join(cwd, SPEC_FILE);
86017
+ const specPath = path97.join(cwd, SPEC_FILE);
85951
86018
  let specContent;
85952
86019
  try {
85953
86020
  specContent = fs74.readFileSync(specPath, "utf-8");
@@ -85974,7 +86041,7 @@ var req_coverage = createSwarmTool({
85974
86041
  message: "No FR requirements found in spec.md"
85975
86042
  }, null, 2);
85976
86043
  }
85977
- const evidenceDir = path93.join(cwd, EVIDENCE_DIR4);
86044
+ const evidenceDir = path97.join(cwd, EVIDENCE_DIR4);
85978
86045
  const touchedFiles = readTouchedFiles(evidenceDir, phase, cwd);
85979
86046
  const analyzedRequirements = [];
85980
86047
  let coveredCount = 0;
@@ -86000,7 +86067,7 @@ var req_coverage = createSwarmTool({
86000
86067
  requirements: analyzedRequirements
86001
86068
  };
86002
86069
  const reportFilename = `req-coverage-phase-${phase}.json`;
86003
- const reportPath = path93.join(evidenceDir, reportFilename);
86070
+ const reportPath = path97.join(evidenceDir, reportFilename);
86004
86071
  try {
86005
86072
  if (!fs74.existsSync(evidenceDir)) {
86006
86073
  fs74.mkdirSync(evidenceDir, { recursive: true });
@@ -86088,7 +86155,7 @@ init_qa_gate_profile();
86088
86155
  init_file_locks();
86089
86156
  import * as crypto9 from "node:crypto";
86090
86157
  import * as fs75 from "node:fs";
86091
- import * as path94 from "node:path";
86158
+ import * as path98 from "node:path";
86092
86159
  init_ledger();
86093
86160
  init_manager();
86094
86161
  init_state();
@@ -86166,8 +86233,8 @@ async function executeSavePlan(args2, fallbackDir) {
86166
86233
  };
86167
86234
  }
86168
86235
  if (args2.working_directory && fallbackDir) {
86169
- const resolvedTarget = path94.resolve(args2.working_directory);
86170
- const resolvedRoot = path94.resolve(fallbackDir);
86236
+ const resolvedTarget = path98.resolve(args2.working_directory);
86237
+ const resolvedRoot = path98.resolve(fallbackDir);
86171
86238
  let fallbackExists = false;
86172
86239
  try {
86173
86240
  fs75.accessSync(resolvedRoot, fs75.constants.F_OK);
@@ -86176,7 +86243,7 @@ async function executeSavePlan(args2, fallbackDir) {
86176
86243
  fallbackExists = false;
86177
86244
  }
86178
86245
  if (fallbackExists) {
86179
- const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path94.sep);
86246
+ const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path98.sep);
86180
86247
  if (isSubdirectory) {
86181
86248
  return {
86182
86249
  success: false,
@@ -86192,10 +86259,10 @@ async function executeSavePlan(args2, fallbackDir) {
86192
86259
  let specMtime;
86193
86260
  let specHash;
86194
86261
  if (process.env.SWARM_SKIP_SPEC_GATE !== "1") {
86195
- const specPath = path94.join(targetWorkspace, ".swarm", "spec.md");
86262
+ const specPath = path98.join(targetWorkspace, ".swarm", "spec.md");
86196
86263
  try {
86197
- const stat6 = await fs75.promises.stat(specPath);
86198
- specMtime = stat6.mtime.toISOString();
86264
+ const stat7 = await fs75.promises.stat(specPath);
86265
+ specMtime = stat7.mtime.toISOString();
86199
86266
  const content = await fs75.promises.readFile(specPath, "utf8");
86200
86267
  specHash = crypto9.createHash("sha256").update(content).digest("hex");
86201
86268
  } catch {
@@ -86208,7 +86275,7 @@ async function executeSavePlan(args2, fallbackDir) {
86208
86275
  }
86209
86276
  }
86210
86277
  if (process.env.SWARM_SKIP_GATE_SELECTION !== "1") {
86211
- const contextPath = path94.join(targetWorkspace, ".swarm", "context.md");
86278
+ const contextPath = path98.join(targetWorkspace, ".swarm", "context.md");
86212
86279
  let contextContent = "";
86213
86280
  try {
86214
86281
  contextContent = await fs75.promises.readFile(contextPath, "utf8");
@@ -86358,7 +86425,7 @@ async function executeSavePlan(args2, fallbackDir) {
86358
86425
  }
86359
86426
  await writeCheckpoint(dir).catch(() => {});
86360
86427
  try {
86361
- const markerPath = path94.join(dir, ".swarm", ".plan-write-marker");
86428
+ const markerPath = path98.join(dir, ".swarm", ".plan-write-marker");
86362
86429
  const marker = JSON.stringify({
86363
86430
  source: "save_plan",
86364
86431
  timestamp: new Date().toISOString(),
@@ -86381,7 +86448,7 @@ async function executeSavePlan(args2, fallbackDir) {
86381
86448
  return {
86382
86449
  success: true,
86383
86450
  message: "Plan saved successfully",
86384
- plan_path: path94.join(dir, ".swarm", "plan.json"),
86451
+ plan_path: path98.join(dir, ".swarm", "plan.json"),
86385
86452
  phases_count: plan.phases.length,
86386
86453
  tasks_count: tasksCount,
86387
86454
  ...resolvedProfile !== undefined ? { execution_profile: resolvedProfile } : {},
@@ -86434,7 +86501,7 @@ var save_plan = createSwarmTool({
86434
86501
  init_zod();
86435
86502
  init_manager2();
86436
86503
  import * as fs76 from "node:fs";
86437
- import * as path95 from "node:path";
86504
+ import * as path99 from "node:path";
86438
86505
 
86439
86506
  // src/sbom/detectors/index.ts
86440
86507
  init_utils();
@@ -87284,7 +87351,7 @@ function findManifestFiles(rootDir) {
87284
87351
  try {
87285
87352
  const entries = fs76.readdirSync(dir, { withFileTypes: true });
87286
87353
  for (const entry of entries) {
87287
- const fullPath = path95.join(dir, entry.name);
87354
+ const fullPath = path99.join(dir, entry.name);
87288
87355
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
87289
87356
  continue;
87290
87357
  }
@@ -87293,7 +87360,7 @@ function findManifestFiles(rootDir) {
87293
87360
  } else if (entry.isFile()) {
87294
87361
  for (const pattern of patterns) {
87295
87362
  if (simpleGlobToRegex(pattern).test(entry.name)) {
87296
- manifestFiles.push(path95.relative(rootDir, fullPath));
87363
+ manifestFiles.push(path99.relative(rootDir, fullPath));
87297
87364
  break;
87298
87365
  }
87299
87366
  }
@@ -87311,11 +87378,11 @@ function findManifestFilesInDirs(directories, workingDir) {
87311
87378
  try {
87312
87379
  const entries = fs76.readdirSync(dir, { withFileTypes: true });
87313
87380
  for (const entry of entries) {
87314
- const fullPath = path95.join(dir, entry.name);
87381
+ const fullPath = path99.join(dir, entry.name);
87315
87382
  if (entry.isFile()) {
87316
87383
  for (const pattern of patterns) {
87317
87384
  if (simpleGlobToRegex(pattern).test(entry.name)) {
87318
- found.push(path95.relative(workingDir, fullPath));
87385
+ found.push(path99.relative(workingDir, fullPath));
87319
87386
  break;
87320
87387
  }
87321
87388
  }
@@ -87328,11 +87395,11 @@ function findManifestFilesInDirs(directories, workingDir) {
87328
87395
  function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
87329
87396
  const dirs = new Set;
87330
87397
  for (const file3 of changedFiles) {
87331
- let currentDir = path95.dirname(file3);
87398
+ let currentDir = path99.dirname(file3);
87332
87399
  while (true) {
87333
- if (currentDir && currentDir !== "." && currentDir !== path95.sep) {
87334
- dirs.add(path95.join(workingDir, currentDir));
87335
- 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);
87336
87403
  if (parent === currentDir)
87337
87404
  break;
87338
87405
  currentDir = parent;
@@ -87416,7 +87483,7 @@ var sbom_generate = createSwarmTool({
87416
87483
  const changedFiles = obj.changed_files;
87417
87484
  const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
87418
87485
  const workingDir = directory;
87419
- const outputDir = path95.isAbsolute(relativeOutputDir) ? relativeOutputDir : path95.join(workingDir, relativeOutputDir);
87486
+ const outputDir = path99.isAbsolute(relativeOutputDir) ? relativeOutputDir : path99.join(workingDir, relativeOutputDir);
87420
87487
  let manifestFiles = [];
87421
87488
  if (scope === "all") {
87422
87489
  manifestFiles = findManifestFiles(workingDir);
@@ -87439,7 +87506,7 @@ var sbom_generate = createSwarmTool({
87439
87506
  const processedFiles = [];
87440
87507
  for (const manifestFile of manifestFiles) {
87441
87508
  try {
87442
- const fullPath = path95.isAbsolute(manifestFile) ? manifestFile : path95.join(workingDir, manifestFile);
87509
+ const fullPath = path99.isAbsolute(manifestFile) ? manifestFile : path99.join(workingDir, manifestFile);
87443
87510
  if (!fs76.existsSync(fullPath)) {
87444
87511
  continue;
87445
87512
  }
@@ -87456,7 +87523,7 @@ var sbom_generate = createSwarmTool({
87456
87523
  const bom = generateCycloneDX(allComponents);
87457
87524
  const bomJson = serializeCycloneDX(bom);
87458
87525
  const filename = generateSbomFilename();
87459
- const outputPath = path95.join(outputDir, filename);
87526
+ const outputPath = path99.join(outputDir, filename);
87460
87527
  fs76.writeFileSync(outputPath, bomJson, "utf-8");
87461
87528
  const verdict = processedFiles.length > 0 ? "pass" : "pass";
87462
87529
  try {
@@ -87500,7 +87567,7 @@ var sbom_generate = createSwarmTool({
87500
87567
  init_zod();
87501
87568
  init_create_tool();
87502
87569
  import * as fs77 from "node:fs";
87503
- import * as path96 from "node:path";
87570
+ import * as path100 from "node:path";
87504
87571
  var SPEC_CANDIDATES = [
87505
87572
  "openapi.json",
87506
87573
  "openapi.yaml",
@@ -87532,12 +87599,12 @@ function normalizePath3(p) {
87532
87599
  }
87533
87600
  function discoverSpecFile(cwd, specFileArg) {
87534
87601
  if (specFileArg) {
87535
- const resolvedPath = path96.resolve(cwd, specFileArg);
87536
- 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;
87537
87604
  if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
87538
87605
  throw new Error("Invalid spec_file: path traversal detected");
87539
87606
  }
87540
- const ext = path96.extname(resolvedPath).toLowerCase();
87607
+ const ext = path100.extname(resolvedPath).toLowerCase();
87541
87608
  if (!ALLOWED_EXTENSIONS.includes(ext)) {
87542
87609
  throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
87543
87610
  }
@@ -87551,7 +87618,7 @@ function discoverSpecFile(cwd, specFileArg) {
87551
87618
  return resolvedPath;
87552
87619
  }
87553
87620
  for (const candidate of SPEC_CANDIDATES) {
87554
- const candidatePath = path96.resolve(cwd, candidate);
87621
+ const candidatePath = path100.resolve(cwd, candidate);
87555
87622
  if (fs77.existsSync(candidatePath)) {
87556
87623
  const stats = fs77.statSync(candidatePath);
87557
87624
  if (stats.size <= MAX_SPEC_SIZE) {
@@ -87563,7 +87630,7 @@ function discoverSpecFile(cwd, specFileArg) {
87563
87630
  }
87564
87631
  function parseSpec(specFile) {
87565
87632
  const content = fs77.readFileSync(specFile, "utf-8");
87566
- const ext = path96.extname(specFile).toLowerCase();
87633
+ const ext = path100.extname(specFile).toLowerCase();
87567
87634
  if (ext === ".json") {
87568
87635
  return parseJsonSpec(content);
87569
87636
  }
@@ -87639,7 +87706,7 @@ function extractRoutes(cwd) {
87639
87706
  return;
87640
87707
  }
87641
87708
  for (const entry of entries) {
87642
- const fullPath = path96.join(dir, entry.name);
87709
+ const fullPath = path100.join(dir, entry.name);
87643
87710
  if (entry.isSymbolicLink()) {
87644
87711
  continue;
87645
87712
  }
@@ -87649,7 +87716,7 @@ function extractRoutes(cwd) {
87649
87716
  }
87650
87717
  walkDir(fullPath);
87651
87718
  } else if (entry.isFile()) {
87652
- const ext = path96.extname(entry.name).toLowerCase();
87719
+ const ext = path100.extname(entry.name).toLowerCase();
87653
87720
  const baseName = entry.name.toLowerCase();
87654
87721
  if (![".ts", ".js", ".mjs"].includes(ext)) {
87655
87722
  continue;
@@ -87817,7 +87884,7 @@ init_bun_compat();
87817
87884
  init_path_security();
87818
87885
  init_create_tool();
87819
87886
  import * as fs78 from "node:fs";
87820
- import * as path97 from "node:path";
87887
+ import * as path101 from "node:path";
87821
87888
  var DEFAULT_MAX_RESULTS = 100;
87822
87889
  var DEFAULT_MAX_LINES = 200;
87823
87890
  var REGEX_TIMEOUT_MS = 5000;
@@ -87853,11 +87920,11 @@ function containsWindowsAttacks3(str) {
87853
87920
  }
87854
87921
  function isPathInWorkspace3(filePath, workspace) {
87855
87922
  try {
87856
- const resolvedPath = path97.resolve(workspace, filePath);
87923
+ const resolvedPath = path101.resolve(workspace, filePath);
87857
87924
  const realWorkspace = fs78.realpathSync(workspace);
87858
87925
  const realResolvedPath = fs78.realpathSync(resolvedPath);
87859
- const relativePath = path97.relative(realWorkspace, realResolvedPath);
87860
- if (relativePath.startsWith("..") || path97.isAbsolute(relativePath)) {
87926
+ const relativePath = path101.relative(realWorkspace, realResolvedPath);
87927
+ if (relativePath.startsWith("..") || path101.isAbsolute(relativePath)) {
87861
87928
  return false;
87862
87929
  }
87863
87930
  return true;
@@ -87870,11 +87937,11 @@ function validatePathForRead2(filePath, workspace) {
87870
87937
  }
87871
87938
  function findRgInEnvPath() {
87872
87939
  const searchPath = process.env.PATH ?? "";
87873
- for (const dir of searchPath.split(path97.delimiter)) {
87940
+ for (const dir of searchPath.split(path101.delimiter)) {
87874
87941
  if (!dir)
87875
87942
  continue;
87876
87943
  const isWindows = process.platform === "win32";
87877
- const candidate = path97.join(dir, isWindows ? "rg.exe" : "rg");
87944
+ const candidate = path101.join(dir, isWindows ? "rg.exe" : "rg");
87878
87945
  if (fs78.existsSync(candidate))
87879
87946
  return candidate;
87880
87947
  }
@@ -87929,7 +87996,7 @@ async function ripgrepSearch(opts) {
87929
87996
  stderr: "pipe",
87930
87997
  cwd: opts.workspace
87931
87998
  });
87932
- const timeout = new Promise((resolve39) => setTimeout(() => resolve39("timeout"), REGEX_TIMEOUT_MS));
87999
+ const timeout = new Promise((resolve40) => setTimeout(() => resolve40("timeout"), REGEX_TIMEOUT_MS));
87933
88000
  const exitPromise = proc.exited;
87934
88001
  const result = await Promise.race([exitPromise, timeout]);
87935
88002
  if (result === "timeout") {
@@ -88004,8 +88071,8 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
88004
88071
  try {
88005
88072
  const entries = fs78.readdirSync(dir, { withFileTypes: true });
88006
88073
  for (const entry of entries) {
88007
- const fullPath = path97.join(dir, entry.name);
88008
- const relativePath = path97.relative(workspace, fullPath);
88074
+ const fullPath = path101.join(dir, entry.name);
88075
+ const relativePath = path101.relative(workspace, fullPath);
88009
88076
  if (!validatePathForRead2(fullPath, workspace)) {
88010
88077
  continue;
88011
88078
  }
@@ -88046,7 +88113,7 @@ async function fallbackSearch(opts) {
88046
88113
  const matches = [];
88047
88114
  let total = 0;
88048
88115
  for (const file3 of files) {
88049
- const fullPath = path97.join(opts.workspace, file3);
88116
+ const fullPath = path101.join(opts.workspace, file3);
88050
88117
  if (!validatePathForRead2(fullPath, opts.workspace)) {
88051
88118
  continue;
88052
88119
  }
@@ -88427,7 +88494,7 @@ init_zod();
88427
88494
  init_path_security();
88428
88495
  init_create_tool();
88429
88496
  import * as fs79 from "node:fs";
88430
- import * as path98 from "node:path";
88497
+ import * as path102 from "node:path";
88431
88498
  var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
88432
88499
  function containsWindowsAttacks4(str) {
88433
88500
  if (/:[^\\/]/.test(str))
@@ -88441,14 +88508,14 @@ function containsWindowsAttacks4(str) {
88441
88508
  }
88442
88509
  function isPathInWorkspace4(filePath, workspace) {
88443
88510
  try {
88444
- const resolvedPath = path98.resolve(workspace, filePath);
88511
+ const resolvedPath = path102.resolve(workspace, filePath);
88445
88512
  if (!fs79.existsSync(resolvedPath)) {
88446
88513
  return true;
88447
88514
  }
88448
88515
  const realWorkspace = fs79.realpathSync(workspace);
88449
88516
  const realResolvedPath = fs79.realpathSync(resolvedPath);
88450
- const relativePath = path98.relative(realWorkspace, realResolvedPath);
88451
- if (relativePath.startsWith("..") || path98.isAbsolute(relativePath)) {
88517
+ const relativePath = path102.relative(realWorkspace, realResolvedPath);
88518
+ if (relativePath.startsWith("..") || path102.isAbsolute(relativePath)) {
88452
88519
  return false;
88453
88520
  }
88454
88521
  return true;
@@ -88656,7 +88723,7 @@ var suggestPatch = createSwarmTool({
88656
88723
  });
88657
88724
  continue;
88658
88725
  }
88659
- const fullPath = path98.resolve(directory, change.file);
88726
+ const fullPath = path102.resolve(directory, change.file);
88660
88727
  if (!fs79.existsSync(fullPath)) {
88661
88728
  errors5.push({
88662
88729
  success: false,
@@ -88919,7 +88986,7 @@ var generate_mutants = createSwarmTool({
88919
88986
  init_spec_schema();
88920
88987
  init_create_tool();
88921
88988
  import * as fs80 from "node:fs";
88922
- import * as path99 from "node:path";
88989
+ import * as path103 from "node:path";
88923
88990
  var SPEC_FILE_NAME = "spec.md";
88924
88991
  var SWARM_DIR2 = ".swarm";
88925
88992
  var OBLIGATION_KEYWORDS2 = ["MUST", "SHALL", "SHOULD", "MAY"];
@@ -88972,7 +89039,7 @@ var lint_spec = createSwarmTool({
88972
89039
  async execute(_args, directory) {
88973
89040
  const errors5 = [];
88974
89041
  const warnings = [];
88975
- const specPath = path99.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
89042
+ const specPath = path103.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
88976
89043
  if (!fs80.existsSync(specPath)) {
88977
89044
  const result2 = {
88978
89045
  valid: false,
@@ -89043,12 +89110,12 @@ var lint_spec = createSwarmTool({
89043
89110
  // src/tools/mutation-test.ts
89044
89111
  init_zod();
89045
89112
  import * as fs81 from "node:fs";
89046
- import * as path101 from "node:path";
89113
+ import * as path105 from "node:path";
89047
89114
 
89048
89115
  // src/mutation/engine.ts
89049
89116
  import { spawnSync as spawnSync3 } from "node:child_process";
89050
89117
  import { unlinkSync as unlinkSync13, writeFileSync as writeFileSync20 } from "node:fs";
89051
- import * as path100 from "node:path";
89118
+ import * as path104 from "node:path";
89052
89119
 
89053
89120
  // src/mutation/equivalence.ts
89054
89121
  function isStaticallyEquivalent(originalCode, mutatedCode) {
@@ -89183,7 +89250,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
89183
89250
  let patchFile;
89184
89251
  try {
89185
89252
  const safeId2 = patch.id.replace(/[^a-zA-Z0-9_-]/g, "_");
89186
- patchFile = path100.join(workingDir, `.mutation_patch_${safeId2}.diff`);
89253
+ patchFile = path104.join(workingDir, `.mutation_patch_${safeId2}.diff`);
89187
89254
  try {
89188
89255
  writeFileSync20(patchFile, patch.patch);
89189
89256
  } catch (writeErr) {
@@ -89577,7 +89644,7 @@ var mutation_test = createSwarmTool({
89577
89644
  ];
89578
89645
  for (const filePath of uniquePaths) {
89579
89646
  try {
89580
- const resolvedPath = path101.resolve(cwd, filePath);
89647
+ const resolvedPath = path105.resolve(cwd, filePath);
89581
89648
  sourceFiles.set(filePath, fs81.readFileSync(resolvedPath, "utf-8"));
89582
89649
  } catch {}
89583
89650
  }
@@ -89597,7 +89664,7 @@ init_zod();
89597
89664
  init_manager2();
89598
89665
  init_detector();
89599
89666
  import * as fs82 from "node:fs";
89600
- import * as path102 from "node:path";
89667
+ import * as path106 from "node:path";
89601
89668
  init_create_tool();
89602
89669
  var MAX_FILE_SIZE2 = 2 * 1024 * 1024;
89603
89670
  var BINARY_CHECK_BYTES = 8192;
@@ -89663,7 +89730,7 @@ async function syntaxCheck(input, directory, config3) {
89663
89730
  if (languages?.length) {
89664
89731
  const lowerLangs = languages.map((l) => l.toLowerCase());
89665
89732
  filesToCheck = filesToCheck.filter((file3) => {
89666
- const ext = path102.extname(file3.path).toLowerCase();
89733
+ const ext = path106.extname(file3.path).toLowerCase();
89667
89734
  const langDef = getLanguageForExtension(ext);
89668
89735
  const fileProfile = getProfileForFile(file3.path);
89669
89736
  const langId = fileProfile?.id || langDef?.id;
@@ -89676,7 +89743,7 @@ async function syntaxCheck(input, directory, config3) {
89676
89743
  let skippedCount = 0;
89677
89744
  for (const fileInfo of filesToCheck) {
89678
89745
  const { path: filePath } = fileInfo;
89679
- const fullPath = path102.isAbsolute(filePath) ? filePath : path102.join(directory, filePath);
89746
+ const fullPath = path106.isAbsolute(filePath) ? filePath : path106.join(directory, filePath);
89680
89747
  const result = {
89681
89748
  path: filePath,
89682
89749
  language: "",
@@ -89725,7 +89792,7 @@ async function syntaxCheck(input, directory, config3) {
89725
89792
  results.push(result);
89726
89793
  continue;
89727
89794
  }
89728
- const ext = path102.extname(filePath).toLowerCase();
89795
+ const ext = path106.extname(filePath).toLowerCase();
89729
89796
  const langDef = getLanguageForExtension(ext);
89730
89797
  result.language = profile?.id || langDef?.id || "unknown";
89731
89798
  const errors5 = extractSyntaxErrors(parser, content);
@@ -89818,7 +89885,7 @@ init_utils();
89818
89885
  init_create_tool();
89819
89886
  init_path_security();
89820
89887
  import * as fs83 from "node:fs";
89821
- import * as path103 from "node:path";
89888
+ import * as path107 from "node:path";
89822
89889
  var MAX_TEXT_LENGTH = 200;
89823
89890
  var MAX_FILE_SIZE_BYTES11 = 1024 * 1024;
89824
89891
  var SUPPORTED_EXTENSIONS4 = new Set([
@@ -89884,9 +89951,9 @@ function validatePathsInput(paths, cwd) {
89884
89951
  return { error: "paths contains path traversal", resolvedPath: null };
89885
89952
  }
89886
89953
  try {
89887
- const resolvedPath = path103.resolve(paths);
89888
- const normalizedCwd = path103.resolve(cwd);
89889
- const normalizedResolved = path103.resolve(resolvedPath);
89954
+ const resolvedPath = path107.resolve(paths);
89955
+ const normalizedCwd = path107.resolve(cwd);
89956
+ const normalizedResolved = path107.resolve(resolvedPath);
89890
89957
  if (!normalizedResolved.startsWith(normalizedCwd)) {
89891
89958
  return {
89892
89959
  error: "paths must be within the current working directory",
@@ -89902,7 +89969,7 @@ function validatePathsInput(paths, cwd) {
89902
89969
  }
89903
89970
  }
89904
89971
  function isSupportedExtension(filePath) {
89905
- const ext = path103.extname(filePath).toLowerCase();
89972
+ const ext = path107.extname(filePath).toLowerCase();
89906
89973
  return SUPPORTED_EXTENSIONS4.has(ext);
89907
89974
  }
89908
89975
  function findSourceFiles3(dir, files = []) {
@@ -89917,16 +89984,16 @@ function findSourceFiles3(dir, files = []) {
89917
89984
  if (SKIP_DIRECTORIES5.has(entry)) {
89918
89985
  continue;
89919
89986
  }
89920
- const fullPath = path103.join(dir, entry);
89921
- let stat6;
89987
+ const fullPath = path107.join(dir, entry);
89988
+ let stat7;
89922
89989
  try {
89923
- stat6 = fs83.statSync(fullPath);
89990
+ stat7 = fs83.statSync(fullPath);
89924
89991
  } catch {
89925
89992
  continue;
89926
89993
  }
89927
- if (stat6.isDirectory()) {
89994
+ if (stat7.isDirectory()) {
89928
89995
  findSourceFiles3(fullPath, files);
89929
- } else if (stat6.isFile()) {
89996
+ } else if (stat7.isFile()) {
89930
89997
  if (isSupportedExtension(fullPath)) {
89931
89998
  files.push(fullPath);
89932
89999
  }
@@ -90023,13 +90090,13 @@ var todo_extract = createSwarmTool({
90023
90090
  return JSON.stringify(errorResult, null, 2);
90024
90091
  }
90025
90092
  const filesToScan = [];
90026
- const stat6 = fs83.statSync(scanPath);
90027
- if (stat6.isFile()) {
90093
+ const stat7 = fs83.statSync(scanPath);
90094
+ if (stat7.isFile()) {
90028
90095
  if (isSupportedExtension(scanPath)) {
90029
90096
  filesToScan.push(scanPath);
90030
90097
  } else {
90031
90098
  const errorResult = {
90032
- error: `unsupported file extension: ${path103.extname(scanPath)}`,
90099
+ error: `unsupported file extension: ${path107.extname(scanPath)}`,
90033
90100
  total: 0,
90034
90101
  byPriority: { high: 0, medium: 0, low: 0 },
90035
90102
  entries: []
@@ -90078,17 +90145,17 @@ init_schema();
90078
90145
  init_qa_gate_profile();
90079
90146
  init_gate_evidence();
90080
90147
  import * as fs86 from "node:fs";
90081
- import * as path106 from "node:path";
90148
+ import * as path110 from "node:path";
90082
90149
 
90083
90150
  // src/hooks/diff-scope.ts
90084
90151
  init_bun_compat();
90085
90152
  import * as fs85 from "node:fs";
90086
- import * as path105 from "node:path";
90153
+ import * as path109 from "node:path";
90087
90154
 
90088
90155
  // src/utils/gitignore-warning.ts
90089
90156
  init_bun_compat();
90090
90157
  import * as fs84 from "node:fs";
90091
- import * as path104 from "node:path";
90158
+ import * as path108 from "node:path";
90092
90159
  var _internals = { bunSpawn };
90093
90160
  var _swarmGitExcludedChecked = false;
90094
90161
  function fileCoversSwarm(content) {
@@ -90162,10 +90229,10 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
90162
90229
  const excludeRelPath = excludePathRaw.trim();
90163
90230
  if (!excludeRelPath)
90164
90231
  return;
90165
- const excludePath = path104.isAbsolute(excludeRelPath) ? excludeRelPath : path104.join(directory, excludeRelPath);
90232
+ const excludePath = path108.isAbsolute(excludeRelPath) ? excludeRelPath : path108.join(directory, excludeRelPath);
90166
90233
  if (checkIgnoreExitCode !== 0) {
90167
90234
  try {
90168
- fs84.mkdirSync(path104.dirname(excludePath), { recursive: true });
90235
+ fs84.mkdirSync(path108.dirname(excludePath), { recursive: true });
90169
90236
  let existing = "";
90170
90237
  try {
90171
90238
  existing = fs84.readFileSync(excludePath, "utf8");
@@ -90209,7 +90276,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
90209
90276
  var _internals2 = { bunSpawn };
90210
90277
  function getDeclaredScope(taskId, directory) {
90211
90278
  try {
90212
- const planPath = path105.join(directory, ".swarm", "plan.json");
90279
+ const planPath = path109.join(directory, ".swarm", "plan.json");
90213
90280
  if (!fs85.existsSync(planPath))
90214
90281
  return null;
90215
90282
  const raw = fs85.readFileSync(planPath, "utf-8");
@@ -90346,7 +90413,7 @@ var TIER_3_PATTERNS = [
90346
90413
  ];
90347
90414
  function matchesTier3Pattern(files) {
90348
90415
  for (const file3 of files) {
90349
- const fileName = path106.basename(file3);
90416
+ const fileName = path110.basename(file3);
90350
90417
  for (const pattern of TIER_3_PATTERNS) {
90351
90418
  if (pattern.test(fileName)) {
90352
90419
  return true;
@@ -90360,7 +90427,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
90360
90427
  if (hasActiveTurboMode()) {
90361
90428
  const resolvedDir2 = workingDirectory;
90362
90429
  try {
90363
- const planPath = path106.join(resolvedDir2, ".swarm", "plan.json");
90430
+ const planPath = path110.join(resolvedDir2, ".swarm", "plan.json");
90364
90431
  const planRaw = fs86.readFileSync(planPath, "utf-8");
90365
90432
  const plan = JSON.parse(planRaw);
90366
90433
  for (const planPhase of plan.phases ?? []) {
@@ -90430,7 +90497,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
90430
90497
  }
90431
90498
  try {
90432
90499
  const resolvedDir2 = workingDirectory;
90433
- const planPath = path106.join(resolvedDir2, ".swarm", "plan.json");
90500
+ const planPath = path110.join(resolvedDir2, ".swarm", "plan.json");
90434
90501
  const planRaw = fs86.readFileSync(planPath, "utf-8");
90435
90502
  const plan = JSON.parse(planRaw);
90436
90503
  for (const planPhase of plan.phases ?? []) {
@@ -90620,8 +90687,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
90620
90687
  };
90621
90688
  }
90622
90689
  }
90623
- normalizedDir = path106.normalize(args2.working_directory);
90624
- const pathParts = normalizedDir.split(path106.sep);
90690
+ normalizedDir = path110.normalize(args2.working_directory);
90691
+ const pathParts = normalizedDir.split(path110.sep);
90625
90692
  if (pathParts.includes("..")) {
90626
90693
  return {
90627
90694
  success: false,
@@ -90631,10 +90698,10 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
90631
90698
  ]
90632
90699
  };
90633
90700
  }
90634
- const resolvedDir = path106.resolve(normalizedDir);
90701
+ const resolvedDir = path110.resolve(normalizedDir);
90635
90702
  try {
90636
90703
  const realPath = fs86.realpathSync(resolvedDir);
90637
- const planPath = path106.join(realPath, ".swarm", "plan.json");
90704
+ const planPath = path110.join(realPath, ".swarm", "plan.json");
90638
90705
  if (!fs86.existsSync(planPath)) {
90639
90706
  return {
90640
90707
  success: false,
@@ -90666,8 +90733,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
90666
90733
  }
90667
90734
  if (args2.status === "in_progress") {
90668
90735
  try {
90669
- const evidencePath = path106.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
90670
- 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 });
90671
90738
  const fd = fs86.openSync(evidencePath, "wx");
90672
90739
  let writeOk = false;
90673
90740
  try {
@@ -90691,7 +90758,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
90691
90758
  recoverTaskStateFromDelegations(args2.task_id);
90692
90759
  let phaseRequiresReviewer = true;
90693
90760
  try {
90694
- const planPath = path106.join(directory, ".swarm", "plan.json");
90761
+ const planPath = path110.join(directory, ".swarm", "plan.json");
90695
90762
  const planRaw = fs86.readFileSync(planPath, "utf-8");
90696
90763
  const plan = JSON.parse(planRaw);
90697
90764
  const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
@@ -91003,7 +91070,7 @@ init_ledger();
91003
91070
  init_manager();
91004
91071
  init_create_tool();
91005
91072
  import fs87 from "node:fs";
91006
- import path107 from "node:path";
91073
+ import path111 from "node:path";
91007
91074
  function derivePlanId5(plan) {
91008
91075
  return `${plan.swarm}-${plan.title}`.replace(/[^a-zA-Z0-9-_]/g, "_");
91009
91076
  }
@@ -91054,7 +91121,7 @@ async function executeWriteDriftEvidence(args2, directory) {
91054
91121
  entries: [evidenceEntry]
91055
91122
  };
91056
91123
  const filename = "drift-verifier.json";
91057
- const relativePath = path107.join("evidence", String(phase), filename);
91124
+ const relativePath = path111.join("evidence", String(phase), filename);
91058
91125
  let validatedPath;
91059
91126
  try {
91060
91127
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -91065,10 +91132,10 @@ async function executeWriteDriftEvidence(args2, directory) {
91065
91132
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
91066
91133
  }, null, 2);
91067
91134
  }
91068
- const evidenceDir = path107.dirname(validatedPath);
91135
+ const evidenceDir = path111.dirname(validatedPath);
91069
91136
  try {
91070
91137
  await fs87.promises.mkdir(evidenceDir, { recursive: true });
91071
- const tempPath = path107.join(evidenceDir, `.${filename}.tmp`);
91138
+ const tempPath = path111.join(evidenceDir, `.${filename}.tmp`);
91072
91139
  await fs87.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
91073
91140
  await fs87.promises.rename(tempPath, validatedPath);
91074
91141
  let snapshotInfo;
@@ -91165,7 +91232,7 @@ init_zod();
91165
91232
  init_utils2();
91166
91233
  init_create_tool();
91167
91234
  import fs88 from "node:fs";
91168
- import path108 from "node:path";
91235
+ import path112 from "node:path";
91169
91236
  function normalizeVerdict2(verdict) {
91170
91237
  switch (verdict) {
91171
91238
  case "APPROVED":
@@ -91213,7 +91280,7 @@ async function executeWriteHallucinationEvidence(args2, directory) {
91213
91280
  entries: [evidenceEntry]
91214
91281
  };
91215
91282
  const filename = "hallucination-guard.json";
91216
- const relativePath = path108.join("evidence", String(phase), filename);
91283
+ const relativePath = path112.join("evidence", String(phase), filename);
91217
91284
  let validatedPath;
91218
91285
  try {
91219
91286
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -91224,10 +91291,10 @@ async function executeWriteHallucinationEvidence(args2, directory) {
91224
91291
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
91225
91292
  }, null, 2);
91226
91293
  }
91227
- const evidenceDir = path108.dirname(validatedPath);
91294
+ const evidenceDir = path112.dirname(validatedPath);
91228
91295
  try {
91229
91296
  await fs88.promises.mkdir(evidenceDir, { recursive: true });
91230
- const tempPath = path108.join(evidenceDir, `.${filename}.tmp`);
91297
+ const tempPath = path112.join(evidenceDir, `.${filename}.tmp`);
91231
91298
  await fs88.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
91232
91299
  await fs88.promises.rename(tempPath, validatedPath);
91233
91300
  return JSON.stringify({
@@ -91276,7 +91343,7 @@ init_zod();
91276
91343
  init_utils2();
91277
91344
  init_create_tool();
91278
91345
  import fs89 from "node:fs";
91279
- import path109 from "node:path";
91346
+ import path113 from "node:path";
91280
91347
  function normalizeVerdict3(verdict) {
91281
91348
  switch (verdict) {
91282
91349
  case "PASS":
@@ -91350,7 +91417,7 @@ async function executeWriteMutationEvidence(args2, directory) {
91350
91417
  entries: [evidenceEntry]
91351
91418
  };
91352
91419
  const filename = "mutation-gate.json";
91353
- const relativePath = path109.join("evidence", String(phase), filename);
91420
+ const relativePath = path113.join("evidence", String(phase), filename);
91354
91421
  let validatedPath;
91355
91422
  try {
91356
91423
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -91361,10 +91428,10 @@ async function executeWriteMutationEvidence(args2, directory) {
91361
91428
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
91362
91429
  }, null, 2);
91363
91430
  }
91364
- const evidenceDir = path109.dirname(validatedPath);
91431
+ const evidenceDir = path113.dirname(validatedPath);
91365
91432
  try {
91366
91433
  await fs89.promises.mkdir(evidenceDir, { recursive: true });
91367
- const tempPath = path109.join(evidenceDir, `.${filename}.tmp`);
91434
+ const tempPath = path113.join(evidenceDir, `.${filename}.tmp`);
91368
91435
  await fs89.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
91369
91436
  await fs89.promises.rename(tempPath, validatedPath);
91370
91437
  return JSON.stringify({
@@ -91658,7 +91725,7 @@ async function initializeOpenCodeSwarm(ctx) {
91658
91725
  const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
91659
91726
  preflightTriggerManager = new PTM(automationConfig);
91660
91727
  const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
91661
- const swarmDir = path110.resolve(ctx.directory, ".swarm");
91728
+ const swarmDir = path114.resolve(ctx.directory, ".swarm");
91662
91729
  statusArtifact = new ASA(swarmDir);
91663
91730
  statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
91664
91731
  if (automationConfig.capabilities?.evidence_auto_summaries === true) {