opencode-swarm 7.4.3 → 7.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -33,7 +33,7 @@ var package_default;
33
33
  var init_package = __esm(() => {
34
34
  package_default = {
35
35
  name: "opencode-swarm",
36
- version: "7.4.3",
36
+ version: "7.5.1",
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",
@@ -22637,7 +22637,7 @@ var init_quick_lru = __esm(() => {
22637
22637
  // src/context/zone-classifier.ts
22638
22638
  function classifyFile(filePath) {
22639
22639
  const normalized = filePath.toLowerCase().replace(/\\/g, "/");
22640
- if (normalized.endsWith(".wasm") || normalized.includes("/dist/") || normalized.includes("/build/") || normalized.includes(".swarm/checkpoints/")) {
22640
+ if (normalized.endsWith(".wasm") || normalized.startsWith("dist/") || normalized.includes("/dist/") || normalized.startsWith("build/") || normalized.includes("/build/") || normalized.includes(".swarm/checkpoints/")) {
22641
22641
  return {
22642
22642
  filePath,
22643
22643
  zone: "generated",
@@ -25225,6 +25225,16 @@ function checkFileAuthorityWithRules(agentName, filePath, cwd, effectiveRules, o
25225
25225
  return { allowed: true };
25226
25226
  }
25227
25227
  }
25228
+ if (rules.blockedZones && rules.blockedZones.length > 0) {
25229
+ const { zone } = classifyFile(normalizedPath);
25230
+ if (rules.blockedZones.includes(zone)) {
25231
+ return {
25232
+ allowed: false,
25233
+ reason: `Path blocked: ${normalizedPath} is in ${zone} zone`,
25234
+ zone
25235
+ };
25236
+ }
25237
+ }
25228
25238
  if (rules.allowedGlobs && rules.allowedGlobs.length > 0) {
25229
25239
  const isGlobAllowed = rules.allowedGlobs.some((glob) => {
25230
25240
  const matcher = getGlobMatcher(glob);
@@ -25262,16 +25272,6 @@ function checkFileAuthorityWithRules(agentName, filePath, cwd, effectiveRules, o
25262
25272
  };
25263
25273
  }
25264
25274
  }
25265
- if (rules.blockedZones && rules.blockedZones.length > 0) {
25266
- const { zone } = classifyFile(normalizedPath);
25267
- if (rules.blockedZones.includes(zone)) {
25268
- return {
25269
- allowed: false,
25270
- reason: `Path blocked: ${normalizedPath} is in ${zone} zone`,
25271
- zone
25272
- };
25273
- }
25274
- }
25275
25275
  return { allowed: true };
25276
25276
  }
25277
25277
  var import_picomatch, storedInputArgs, TRANSIENT_MODEL_ERROR_PATTERN, toolCallsSinceLastWrite, noOpWarningIssued, consecutiveNoToolTurns, DC_MAX_UNWRAP_DEPTH = 5, DC_SAFE_TARGETS, DC_BLOCKED_ABSOLUTE_PREFIXES, DC_FS_ROOTS, DC_REMOTE_PREFIXES, pathNormalizationCache, globMatcherCache, DEFAULT_AGENT_AUTHORITY_RULES;
@@ -25390,15 +25390,24 @@ var init_guardrails = __esm(() => {
25390
25390
  test_engineer: {
25391
25391
  blockedExact: [".swarm/plan.md", ".swarm/plan.json"],
25392
25392
  blockedPrefix: ["src/"],
25393
- allowedPrefix: ["tests/", ".swarm/evidence/"],
25393
+ allowedPrefix: ["tests/", "test/", ".swarm/evidence/"],
25394
+ allowedGlobs: [
25395
+ "**/tests/**",
25396
+ "**/test/**",
25397
+ "**/__tests__/**",
25398
+ "**/*.test.*",
25399
+ "**/*.spec.*"
25400
+ ],
25394
25401
  blockedZones: ["generated"]
25395
25402
  },
25396
25403
  docs: {
25397
25404
  allowedPrefix: ["docs/", ".swarm/outputs/"],
25405
+ allowedGlobs: ["**/docs/**", "**/*.md", "**/*.mdx", "**/*.rst"],
25398
25406
  blockedZones: ["generated"]
25399
25407
  },
25400
25408
  designer: {
25401
25409
  allowedPrefix: ["docs/", ".swarm/outputs/"],
25410
+ allowedGlobs: ["**/docs/**", "**/*.md", "**/*.mdx", "**/*.rst"],
25402
25411
  blockedZones: ["generated"]
25403
25412
  },
25404
25413
  critic: {
@@ -62656,8 +62665,8 @@ ${JSON.stringify(symbolNames, null, 2)}`);
62656
62665
  var moduleRtn;
62657
62666
  var Module = moduleArg;
62658
62667
  var readyPromiseResolve, readyPromiseReject;
62659
- var readyPromise = new Promise((resolve21, reject) => {
62660
- readyPromiseResolve = resolve21;
62668
+ var readyPromise = new Promise((resolve22, reject) => {
62669
+ readyPromiseResolve = resolve22;
62661
62670
  readyPromiseReject = reject;
62662
62671
  });
62663
62672
  var ENVIRONMENT_IS_WEB = typeof window == "object";
@@ -62679,11 +62688,11 @@ ${JSON.stringify(symbolNames, null, 2)}`);
62679
62688
  throw toThrow;
62680
62689
  }, "quit_");
62681
62690
  var scriptDirectory = "";
62682
- function locateFile(path61) {
62691
+ function locateFile(path65) {
62683
62692
  if (Module["locateFile"]) {
62684
- return Module["locateFile"](path61, scriptDirectory);
62693
+ return Module["locateFile"](path65, scriptDirectory);
62685
62694
  }
62686
- return scriptDirectory + path61;
62695
+ return scriptDirectory + path65;
62687
62696
  }
62688
62697
  __name(locateFile, "locateFile");
62689
62698
  var readAsync, readBinary;
@@ -62737,13 +62746,13 @@ ${JSON.stringify(symbolNames, null, 2)}`);
62737
62746
  }
62738
62747
  readAsync = /* @__PURE__ */ __name(async (url3) => {
62739
62748
  if (isFileURI(url3)) {
62740
- return new Promise((resolve21, reject) => {
62749
+ return new Promise((resolve22, reject) => {
62741
62750
  var xhr = new XMLHttpRequest;
62742
62751
  xhr.open("GET", url3, true);
62743
62752
  xhr.responseType = "arraybuffer";
62744
62753
  xhr.onload = () => {
62745
62754
  if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
62746
- resolve21(xhr.response);
62755
+ resolve22(xhr.response);
62747
62756
  return;
62748
62757
  }
62749
62758
  reject(xhr.status);
@@ -62963,10 +62972,10 @@ ${JSON.stringify(symbolNames, null, 2)}`);
62963
62972
  __name(receiveInstantiationResult, "receiveInstantiationResult");
62964
62973
  var info2 = getWasmImports();
62965
62974
  if (Module["instantiateWasm"]) {
62966
- return new Promise((resolve21, reject) => {
62975
+ return new Promise((resolve22, reject) => {
62967
62976
  Module["instantiateWasm"](info2, (mod, inst) => {
62968
62977
  receiveInstance(mod, inst);
62969
- resolve21(mod.exports);
62978
+ resolve22(mod.exports);
62970
62979
  });
62971
62980
  });
62972
62981
  }
@@ -64432,13 +64441,13 @@ __export(exports_runtime, {
64432
64441
  getInitializedLanguages: () => getInitializedLanguages,
64433
64442
  clearParserCache: () => clearParserCache
64434
64443
  });
64435
- import * as path61 from "node:path";
64444
+ import * as path65 from "node:path";
64436
64445
  import { fileURLToPath as fileURLToPath2 } from "node:url";
64437
64446
  async function initTreeSitter() {
64438
64447
  if (treeSitterInitialized) {
64439
64448
  return;
64440
64449
  }
64441
- const thisDir = path61.dirname(fileURLToPath2(import.meta.url));
64450
+ const thisDir = path65.dirname(fileURLToPath2(import.meta.url));
64442
64451
  const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/lang");
64443
64452
  if (isSource) {
64444
64453
  await Parser.init();
@@ -64446,7 +64455,7 @@ async function initTreeSitter() {
64446
64455
  const grammarsDir = getGrammarsDirAbsolute();
64447
64456
  await Parser.init({
64448
64457
  locateFile(scriptName) {
64449
- return path61.join(grammarsDir, scriptName);
64458
+ return path65.join(grammarsDir, scriptName);
64450
64459
  }
64451
64460
  });
64452
64461
  }
@@ -64467,11 +64476,11 @@ function getWasmFileName(languageId) {
64467
64476
  return `tree-sitter-${sanitized}.wasm`;
64468
64477
  }
64469
64478
  function getGrammarsDirAbsolute() {
64470
- const thisDir = path61.dirname(fileURLToPath2(import.meta.url));
64479
+ const thisDir = path65.dirname(fileURLToPath2(import.meta.url));
64471
64480
  const normalized = thisDir.replace(/\\/g, "/");
64472
64481
  const isSource = normalized.endsWith("/src/lang");
64473
64482
  const isCliBundle = normalized.endsWith("/cli");
64474
- return isSource ? path61.join(thisDir, "grammars") : isCliBundle ? path61.join(thisDir, "..", "lang", "grammars") : path61.join(thisDir, "lang", "grammars");
64483
+ return isSource ? path65.join(thisDir, "grammars") : isCliBundle ? path65.join(thisDir, "..", "lang", "grammars") : path65.join(thisDir, "lang", "grammars");
64475
64484
  }
64476
64485
  async function loadGrammar(languageId) {
64477
64486
  if (typeof languageId !== "string" || languageId.length > 100) {
@@ -64487,9 +64496,9 @@ async function loadGrammar(languageId) {
64487
64496
  await initTreeSitter();
64488
64497
  const parser = new Parser;
64489
64498
  const wasmFileName = getWasmFileName(normalizedId);
64490
- const wasmPath = path61.join(getGrammarsDirAbsolute(), wasmFileName);
64491
- const { existsSync: existsSync31 } = await import("node:fs");
64492
- if (!existsSync31(wasmPath)) {
64499
+ const wasmPath = path65.join(getGrammarsDirAbsolute(), wasmFileName);
64500
+ const { existsSync: existsSync33 } = await import("node:fs");
64501
+ if (!existsSync33(wasmPath)) {
64493
64502
  throw new Error(`Grammar file not found for ${languageId}: ${wasmPath}
64494
64503
  Make sure to run 'bun run build' to copy grammar files to dist/lang/grammars/`);
64495
64504
  }
@@ -64522,7 +64531,7 @@ async function isGrammarAvailable(languageId) {
64522
64531
  }
64523
64532
  try {
64524
64533
  const wasmFileName = getWasmFileName(normalizedId);
64525
- const wasmPath = path61.join(getGrammarsDirAbsolute(), wasmFileName);
64534
+ const wasmPath = path65.join(getGrammarsDirAbsolute(), wasmFileName);
64526
64535
  const { statSync: statSync19 } = await import("node:fs");
64527
64536
  statSync19(wasmPath);
64528
64537
  return true;
@@ -64581,13 +64590,13 @@ __export(exports_doc_scan, {
64581
64590
  import * as crypto7 from "node:crypto";
64582
64591
  import * as fs45 from "node:fs";
64583
64592
  import { mkdir as mkdir10, readFile as readFile10, writeFile as writeFile9 } from "node:fs/promises";
64584
- import * as path63 from "node:path";
64593
+ import * as path67 from "node:path";
64585
64594
  function normalizeSeparators(filePath) {
64586
64595
  return filePath.replace(/\\/g, "/");
64587
64596
  }
64588
64597
  function matchesDocPattern(filePath, patterns) {
64589
64598
  const normalizedPath = normalizeSeparators(filePath);
64590
- const basename9 = path63.basename(filePath);
64599
+ const basename9 = path67.basename(filePath);
64591
64600
  for (const pattern of patterns) {
64592
64601
  if (!pattern.includes("/") && !pattern.includes("\\")) {
64593
64602
  if (basename9 === pattern) {
@@ -64643,7 +64652,7 @@ function stripMarkdown(text) {
64643
64652
  return text.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/^\s*[-*•]\s+/gm, "").replace(/^\s*\d+\.\s+/gm, "").trim();
64644
64653
  }
64645
64654
  async function scanDocIndex(directory) {
64646
- const manifestPath = path63.join(directory, ".swarm", "doc-manifest.json");
64655
+ const manifestPath = path67.join(directory, ".swarm", "doc-manifest.json");
64647
64656
  const defaultPatterns = DocsConfigSchema.parse({}).doc_patterns;
64648
64657
  const extraPatterns = [
64649
64658
  "ARCHITECTURE.md",
@@ -64660,9 +64669,9 @@ async function scanDocIndex(directory) {
64660
64669
  let cacheValid = true;
64661
64670
  for (const file3 of existingManifest.files) {
64662
64671
  try {
64663
- const fullPath = path63.join(directory, file3.path);
64664
- const stat5 = fs45.statSync(fullPath);
64665
- if (stat5.mtimeMs > file3.mtime) {
64672
+ const fullPath = path67.join(directory, file3.path);
64673
+ const stat6 = fs45.statSync(fullPath);
64674
+ if (stat6.mtimeMs > file3.mtime) {
64666
64675
  cacheValid = false;
64667
64676
  break;
64668
64677
  }
@@ -64690,14 +64699,14 @@ async function scanDocIndex(directory) {
64690
64699
  }
64691
64700
  const entries = rawEntries.filter((e) => typeof e === "string");
64692
64701
  for (const entry of entries) {
64693
- const fullPath = path63.join(directory, entry);
64694
- let stat5;
64702
+ const fullPath = path67.join(directory, entry);
64703
+ let stat6;
64695
64704
  try {
64696
- stat5 = fs45.statSync(fullPath);
64705
+ stat6 = fs45.statSync(fullPath);
64697
64706
  } catch {
64698
64707
  continue;
64699
64708
  }
64700
- if (!stat5.isFile())
64709
+ if (!stat6.isFile())
64701
64710
  continue;
64702
64711
  const pathParts = normalizeSeparators(entry).split("/");
64703
64712
  let skipThisFile = false;
@@ -64726,7 +64735,7 @@ async function scanDocIndex(directory) {
64726
64735
  } catch {
64727
64736
  continue;
64728
64737
  }
64729
- const { title, summary } = extractTitleAndSummary(content, path63.basename(entry));
64738
+ const { title, summary } = extractTitleAndSummary(content, path67.basename(entry));
64730
64739
  const lineCount = content.split(`
64731
64740
  `).length;
64732
64741
  discoveredFiles.push({
@@ -64734,7 +64743,7 @@ async function scanDocIndex(directory) {
64734
64743
  title,
64735
64744
  summary,
64736
64745
  lines: lineCount,
64737
- mtime: stat5.mtimeMs
64746
+ mtime: stat6.mtimeMs
64738
64747
  });
64739
64748
  }
64740
64749
  discoveredFiles.sort((a, b) => a.path.toLowerCase().localeCompare(b.path.toLowerCase()));
@@ -64752,7 +64761,7 @@ async function scanDocIndex(directory) {
64752
64761
  files: discoveredFiles
64753
64762
  };
64754
64763
  try {
64755
- await mkdir10(path63.dirname(manifestPath), { recursive: true });
64764
+ await mkdir10(path67.dirname(manifestPath), { recursive: true });
64756
64765
  await writeFile9(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
64757
64766
  } catch {}
64758
64767
  return { manifest, cached: false };
@@ -64791,7 +64800,7 @@ function extractConstraintsFromContent(content) {
64791
64800
  return constraints;
64792
64801
  }
64793
64802
  async function extractDocConstraints(directory, taskFiles, taskDescription) {
64794
- const manifestPath = path63.join(directory, ".swarm", "doc-manifest.json");
64803
+ const manifestPath = path67.join(directory, ".swarm", "doc-manifest.json");
64795
64804
  let manifest;
64796
64805
  try {
64797
64806
  const content = await readFile10(manifestPath, "utf-8");
@@ -64817,7 +64826,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
64817
64826
  }
64818
64827
  let fullContent;
64819
64828
  try {
64820
- fullContent = await readFile10(path63.join(directory, docFile.path), "utf-8");
64829
+ fullContent = await readFile10(path67.join(directory, docFile.path), "utf-8");
64821
64830
  } catch {
64822
64831
  skippedCount++;
64823
64832
  continue;
@@ -64840,7 +64849,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
64840
64849
  tier: "swarm",
64841
64850
  lesson: constraint,
64842
64851
  category: "architecture",
64843
- tags: ["doc-scan", path63.basename(docFile.path)],
64852
+ tags: ["doc-scan", path67.basename(docFile.path)],
64844
64853
  scope: "global",
64845
64854
  confidence: 0.5,
64846
64855
  status: "candidate",
@@ -64913,7 +64922,7 @@ var init_doc_scan = __esm(() => {
64913
64922
  }
64914
64923
  } catch {}
64915
64924
  if (force) {
64916
- const manifestPath = path63.join(directory, ".swarm", "doc-manifest.json");
64925
+ const manifestPath = path67.join(directory, ".swarm", "doc-manifest.json");
64917
64926
  try {
64918
64927
  fs45.unlinkSync(manifestPath);
64919
64928
  } catch {}
@@ -65104,9 +65113,9 @@ __export(exports_curator_drift, {
65104
65113
  buildDriftInjectionText: () => buildDriftInjectionText
65105
65114
  });
65106
65115
  import * as fs48 from "node:fs";
65107
- import * as path66 from "node:path";
65116
+ import * as path70 from "node:path";
65108
65117
  async function readPriorDriftReports(directory) {
65109
- const swarmDir = path66.join(directory, ".swarm");
65118
+ const swarmDir = path70.join(directory, ".swarm");
65110
65119
  const entries = await fs48.promises.readdir(swarmDir).catch(() => null);
65111
65120
  if (entries === null)
65112
65121
  return [];
@@ -65133,7 +65142,7 @@ async function readPriorDriftReports(directory) {
65133
65142
  async function writeDriftReport(directory, report) {
65134
65143
  const filename = `${DRIFT_REPORT_PREFIX}${report.phase}.json`;
65135
65144
  const filePath = validateSwarmPath(directory, filename);
65136
- const swarmDir = path66.dirname(filePath);
65145
+ const swarmDir = path70.dirname(filePath);
65137
65146
  await fs48.promises.mkdir(swarmDir, { recursive: true });
65138
65147
  try {
65139
65148
  await fs48.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
@@ -65267,7 +65276,7 @@ var init_curator_drift = __esm(() => {
65267
65276
  // src/index.ts
65268
65277
  init_package();
65269
65278
  init_agents2();
65270
- import * as path110 from "node:path";
65279
+ import * as path114 from "node:path";
65271
65280
 
65272
65281
  // src/background/index.ts
65273
65282
  init_event_bus();
@@ -67400,16 +67409,16 @@ ${originalText}`;
67400
67409
  }
67401
67410
  // src/hooks/repo-graph-builder.ts
67402
67411
  init_constants();
67403
- import * as path54 from "node:path";
67412
+ import { realpathSync as realpathSync8 } from "node:fs";
67413
+ import * as path58 from "node:path";
67404
67414
 
67405
- // src/tools/repo-graph.ts
67406
- init_utils2();
67415
+ // src/tools/repo-graph/builder.ts
67407
67416
  init_path_security();
67408
67417
  import * as fsSync3 from "node:fs";
67409
- import { constants as constants4, existsSync as existsSync29, realpathSync as realpathSync6 } from "node:fs";
67418
+ import { existsSync as existsSync29, realpathSync as realpathSync6 } from "node:fs";
67410
67419
  import * as fsPromises5 from "node:fs/promises";
67411
67420
  import * as os7 from "node:os";
67412
- import * as path53 from "node:path";
67421
+ import * as path54 from "node:path";
67413
67422
 
67414
67423
  // src/utils/timeout.ts
67415
67424
  async function withTimeout(promise3, ms, timeoutError) {
@@ -67769,17 +67778,38 @@ var symbols = createSwarmTool({
67769
67778
  }
67770
67779
  });
67771
67780
 
67772
- // src/tools/repo-graph.ts
67773
- var WINDOWS_RENAME_MAX_RETRIES2 = 3;
67774
- var WINDOWS_RENAME_RETRY_DELAY_MS2 = 50;
67781
+ // src/tools/repo-graph/types.ts
67782
+ import * as path53 from "node:path";
67783
+ var REPO_GRAPH_FILENAME = "repo-graph.json";
67784
+ var GRAPH_SCHEMA_VERSION = "1.0.0";
67775
67785
  function normalizeGraphPath(filePath) {
67776
67786
  return path53.normalize(filePath).replace(/\\/g, "/");
67777
67787
  }
67778
- var REPO_GRAPH_FILENAME = "repo-graph.json";
67779
- var GRAPH_SCHEMA_VERSION = "1.0.0";
67780
- var graphCache = new Map;
67781
- var dirtyFlags = new Map;
67782
- var mtimeCache = new Map;
67788
+ function createEmptyGraph(workspaceRoot) {
67789
+ return {
67790
+ schema_version: GRAPH_SCHEMA_VERSION,
67791
+ workspaceRoot: path53.normalize(workspaceRoot),
67792
+ nodes: {},
67793
+ edges: [],
67794
+ metadata: {
67795
+ generatedAt: new Date().toISOString(),
67796
+ generator: "repo-graph",
67797
+ nodeCount: 0,
67798
+ edgeCount: 0
67799
+ }
67800
+ };
67801
+ }
67802
+ function updateGraphMetadata(graph) {
67803
+ graph.metadata = {
67804
+ generatedAt: new Date().toISOString(),
67805
+ generator: "repo-graph",
67806
+ nodeCount: Object.keys(graph.nodes).length,
67807
+ edgeCount: graph.edges.length
67808
+ };
67809
+ }
67810
+
67811
+ // src/tools/repo-graph/validation.ts
67812
+ init_path_security();
67783
67813
  function validateWorkspace(workspace) {
67784
67814
  if (!workspace || typeof workspace !== "string" || workspace.trim() === "") {
67785
67815
  throw new Error("Invalid workspace: must be a non-empty string");
@@ -67867,6 +67897,57 @@ function validateGraphEdge(edge) {
67867
67897
  throw new Error("Invalid edge: control characters detected");
67868
67898
  }
67869
67899
  }
67900
+
67901
+ // src/tools/repo-graph/builder.ts
67902
+ var SKIP_DIRECTORIES2 = new Set([
67903
+ "node_modules",
67904
+ ".git",
67905
+ "dist",
67906
+ "build",
67907
+ "out",
67908
+ "coverage",
67909
+ ".next",
67910
+ ".nuxt",
67911
+ ".cache",
67912
+ "vendor",
67913
+ ".svn",
67914
+ ".hg"
67915
+ ]);
67916
+ var SUPPORTED_EXTENSIONS = [
67917
+ ".ts",
67918
+ ".tsx",
67919
+ ".js",
67920
+ ".jsx",
67921
+ ".mjs",
67922
+ ".cjs",
67923
+ ".py"
67924
+ ];
67925
+ var DEFAULT_WALK_FILE_CAP = 1e4;
67926
+ var DEFAULT_WALK_BUDGET_MS = 5000;
67927
+ var ASYNC_WALK_YIELD_INTERVAL = 200;
67928
+ var EXTENSION_TO_LANGUAGE = {
67929
+ ".ts": "typescript",
67930
+ ".tsx": "typescript",
67931
+ ".js": "javascript",
67932
+ ".jsx": "javascript",
67933
+ ".mjs": "javascript",
67934
+ ".cjs": "javascript",
67935
+ ".py": "python"
67936
+ };
67937
+ function upsertNode(graph, node) {
67938
+ validateGraphNode(node);
67939
+ const key = normalizeGraphPath(node.filePath);
67940
+ graph.nodes[key] = node;
67941
+ updateGraphMetadata(graph);
67942
+ }
67943
+ function addEdge(graph, edge) {
67944
+ validateGraphEdge(edge);
67945
+ const exists = graph.edges.some((e) => e.source === edge.source && e.target === edge.target && e.importSpecifier === edge.importSpecifier);
67946
+ if (!exists) {
67947
+ graph.edges.push(edge);
67948
+ updateGraphMetadata(graph);
67949
+ }
67950
+ }
67870
67951
  function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
67871
67952
  if (containsControlChars(specifier)) {
67872
67953
  return null;
@@ -67882,8 +67963,8 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
67882
67963
  }
67883
67964
  try {
67884
67965
  if (specifier.startsWith(".")) {
67885
- const sourceDir = path53.dirname(sourceFile);
67886
- let resolved = path53.resolve(sourceDir, specifier);
67966
+ const sourceDir = path54.dirname(sourceFile);
67967
+ let resolved = path54.resolve(sourceDir, specifier);
67887
67968
  let realResolved;
67888
67969
  try {
67889
67970
  realResolved = realpathSync6(resolved);
@@ -67894,7 +67975,7 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
67894
67975
  try {
67895
67976
  realRoot = realpathSync6(workspaceRoot);
67896
67977
  } catch {
67897
- realRoot = path53.normalize(workspaceRoot);
67978
+ realRoot = path54.normalize(workspaceRoot);
67898
67979
  }
67899
67980
  if (!existsSync29(resolved)) {
67900
67981
  const EXTENSIONS = [
@@ -67926,9 +68007,9 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
67926
68007
  return null;
67927
68008
  }
67928
68009
  }
67929
- const normalizedResolved = path53.normalize(realResolved);
67930
- const normalizedRoot = path53.normalize(realRoot);
67931
- if (!normalizedResolved.startsWith(normalizedRoot + path53.sep) && normalizedResolved !== normalizedRoot) {
68010
+ const normalizedResolved = path54.normalize(realResolved);
68011
+ const normalizedRoot = path54.normalize(realRoot);
68012
+ if (!normalizedResolved.startsWith(normalizedRoot + path54.sep) && normalizedResolved !== normalizedRoot) {
67932
68013
  return null;
67933
68014
  }
67934
68015
  return resolved;
@@ -67938,275 +68019,17 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
67938
68019
  return null;
67939
68020
  }
67940
68021
  }
67941
- function createEmptyGraph(workspaceRoot) {
67942
- return {
67943
- schema_version: GRAPH_SCHEMA_VERSION,
67944
- workspaceRoot: path53.normalize(workspaceRoot),
67945
- nodes: {},
67946
- edges: [],
67947
- metadata: {
67948
- generatedAt: new Date().toISOString(),
67949
- generator: "repo-graph",
67950
- nodeCount: 0,
67951
- edgeCount: 0
67952
- }
67953
- };
67954
- }
67955
- function updateGraphMetadata(graph) {
67956
- graph.metadata = {
67957
- generatedAt: new Date().toISOString(),
67958
- generator: "repo-graph",
67959
- nodeCount: Object.keys(graph.nodes).length,
67960
- edgeCount: graph.edges.length
67961
- };
67962
- }
67963
- function upsertNode(graph, node) {
67964
- validateGraphNode(node);
67965
- const key = normalizeGraphPath(node.filePath);
67966
- graph.nodes[key] = node;
67967
- updateGraphMetadata(graph);
67968
- }
67969
- function addEdge(graph, edge) {
67970
- validateGraphEdge(edge);
67971
- const exists = graph.edges.some((e) => e.source === edge.source && e.target === edge.target && e.importSpecifier === edge.importSpecifier);
67972
- if (!exists) {
67973
- graph.edges.push(edge);
67974
- updateGraphMetadata(graph);
67975
- }
67976
- }
67977
- function getCachedGraph(workspace) {
67978
- return graphCache.get(path53.normalize(workspace));
67979
- }
67980
- function setCachedGraph(workspace, graph, mtime) {
67981
- const normalized = path53.normalize(workspace);
67982
- graphCache.set(normalized, graph);
67983
- dirtyFlags.set(normalized, false);
67984
- if (mtime !== undefined) {
67985
- mtimeCache.set(normalized, mtime);
67986
- }
67987
- }
67988
- function isDirty(workspace) {
67989
- return dirtyFlags.get(path53.normalize(workspace)) ?? false;
67990
- }
67991
- function clearCache(workspace) {
67992
- const normalized = path53.normalize(workspace);
67993
- graphCache.delete(normalized);
67994
- dirtyFlags.delete(normalized);
67995
- mtimeCache.delete(normalized);
67996
- }
67997
- function getGraphPath(workspace) {
67998
- validateWorkspace(workspace);
67999
- const basePath = validateSwarmPath(workspace, REPO_GRAPH_FILENAME);
68000
- validateSymlinkBoundary(basePath, workspace);
68001
- return basePath;
68002
- }
68003
- async function loadGraph(workspace) {
68004
- validateWorkspace(workspace);
68005
- const normalized = path53.normalize(workspace);
68006
- const cached3 = getCachedGraph(normalized);
68007
- if (cached3 && !isDirty(normalized)) {
68008
- try {
68009
- const graphPath = getGraphPath(workspace);
68010
- if (existsSync29(graphPath)) {
68011
- const stats = await fsPromises5.stat(graphPath);
68012
- const cachedMtime = mtimeCache.get(normalized);
68013
- if (cachedMtime !== undefined && stats.mtimeMs !== cachedMtime) {
68014
- clearCache(normalized);
68015
- } else {
68016
- return cached3;
68017
- }
68018
- } else {
68019
- clearCache(normalized);
68020
- }
68021
- } catch {
68022
- clearCache(normalized);
68023
- }
68024
- }
68025
- try {
68026
- const graphPath = getGraphPath(workspace);
68027
- if (!existsSync29(graphPath)) {
68028
- return null;
68029
- }
68030
- const stats = await fsPromises5.stat(graphPath);
68031
- const content = await fsPromises5.readFile(graphPath, "utf-8");
68032
- if (content.includes("\x00") || content.includes("�")) {
68033
- throw Object.assign(new Error("repo-graph.json contains null bytes or invalid encoding"), { code: "CORRUPTION" });
68034
- }
68035
- let parsed;
68036
- try {
68037
- parsed = JSON.parse(content);
68038
- } catch {
68039
- throw Object.assign(new Error("repo-graph.json contains invalid JSON"), {
68040
- code: "CORRUPTION"
68041
- });
68042
- }
68043
- if (!parsed.schema_version) {
68044
- throw Object.assign(new Error("repo-graph.json missing schema_version"), {
68045
- code: "CORRUPTION"
68046
- });
68047
- }
68048
- if (!parsed.nodes || typeof parsed.nodes !== "object") {
68049
- throw Object.assign(new Error("repo-graph.json missing or invalid nodes"), { code: "CORRUPTION" });
68050
- }
68051
- if (!Array.isArray(parsed.edges)) {
68052
- throw Object.assign(new Error("repo-graph.json missing or invalid edges"), { code: "CORRUPTION" });
68053
- }
68054
- for (const [key, node] of Object.entries(parsed.nodes)) {
68055
- if (!key || typeof key !== "string") {
68056
- throw Object.assign(new Error("repo-graph.json contains invalid node key"), { code: "CORRUPTION" });
68057
- }
68058
- try {
68059
- validateGraphNode(node);
68060
- } catch (err2) {
68061
- const msg = err2 instanceof Error ? err2.message : "Invalid node structure";
68062
- throw Object.assign(new Error(`repo-graph.json node validation failed: ${msg}`), { code: "CORRUPTION" });
68063
- }
68064
- }
68065
- for (const edge of parsed.edges) {
68066
- try {
68067
- validateGraphEdge(edge);
68068
- } catch (err2) {
68069
- const msg = err2 instanceof Error ? err2.message : "Invalid edge structure";
68070
- throw Object.assign(new Error(`repo-graph.json edge validation failed: ${msg}`), { code: "CORRUPTION" });
68071
- }
68072
- }
68073
- if (!parsed.metadata || typeof parsed.metadata !== "object" || typeof parsed.metadata.generatedAt !== "string" || typeof parsed.metadata.generator !== "string" || typeof parsed.metadata.nodeCount !== "number" || typeof parsed.metadata.edgeCount !== "number") {
68074
- throw Object.assign(new Error("repo-graph.json missing or invalid metadata"), { code: "CORRUPTION" });
68075
- }
68076
- setCachedGraph(normalized, parsed, stats.mtimeMs);
68077
- return parsed;
68078
- } catch (error93) {
68079
- if (error93 instanceof Error && "code" in error93 && error93.code === "CORRUPTION") {
68080
- throw error93;
68081
- }
68082
- if (error93 instanceof Error && "code" in error93 && error93.code === "ENOENT") {
68083
- return null;
68084
- }
68085
- throw error93;
68086
- }
68087
- }
68088
- async function saveGraph(workspace, graph, options) {
68089
- validateWorkspace(workspace);
68090
- if (!graph.schema_version) {
68091
- throw new Error("Graph must have schema_version");
68092
- }
68093
- if (!graph.nodes || typeof graph.nodes !== "object") {
68094
- throw new Error("Graph must have nodes object");
68095
- }
68096
- if (!Array.isArray(graph.edges)) {
68097
- throw new Error("Graph must have edges array");
68098
- }
68099
- const normalizedWorkspace = path53.normalize(workspace);
68100
- let realWorkspace;
68101
- try {
68102
- realWorkspace = realpathSync6(workspace);
68103
- } catch {
68104
- realWorkspace = normalizedWorkspace;
68105
- }
68106
- const normalizedGraphRoot = path53.normalize(graph.workspaceRoot);
68107
- let realGraphRoot;
68108
- try {
68109
- realGraphRoot = realpathSync6(graph.workspaceRoot);
68110
- } catch {
68111
- realGraphRoot = normalizedGraphRoot;
68112
- }
68113
- if (path53.normalize(realWorkspace) !== path53.normalize(realGraphRoot)) {
68114
- throw new Error(`Graph workspaceRoot mismatch: graph was built for "${graph.workspaceRoot}" but save was called for "${workspace}"`);
68115
- }
68116
- const normalized = normalizedWorkspace;
68117
- const graphPath = getGraphPath(workspace);
68118
- updateGraphMetadata(graph);
68119
- const tempPath = `${graphPath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
68120
- await fsPromises5.mkdir(path53.dirname(tempPath), { recursive: true });
68121
- let lastError = null;
68122
- try {
68123
- if (options?.createAtomic) {
68124
- try {
68125
- const handle2 = await fsPromises5.open(tempPath, "wx", 420);
68126
- await handle2.writeFile(JSON.stringify(graph, null, 2), "utf-8");
68127
- await handle2.close();
68128
- } catch (error93) {
68129
- if (error93 instanceof Error && "code" in error93 && error93.code === "EEXIST") {
68130
- throw new Error("file already exists");
68131
- }
68132
- throw error93;
68133
- }
68134
- } else {
68135
- await fsPromises5.writeFile(tempPath, JSON.stringify(graph, null, 2), "utf-8");
68136
- }
68137
- if (options?.createAtomic) {
68138
- try {
68139
- await fsPromises5.copyFile(tempPath, graphPath, constants4.COPYFILE_EXCL);
68140
- } catch (error93) {
68141
- lastError = error93 instanceof Error ? error93 : new Error(String(error93));
68142
- throw lastError;
68143
- }
68144
- } else {
68145
- let retries = 0;
68146
- while (retries < WINDOWS_RENAME_MAX_RETRIES2) {
68147
- try {
68148
- await fsPromises5.rename(tempPath, graphPath);
68149
- break;
68150
- } catch (error93) {
68151
- lastError = error93 instanceof Error ? error93 : new Error(String(error93));
68152
- if (lastError instanceof Error && "code" in lastError && lastError.code === "EEXIST" && retries < WINDOWS_RENAME_MAX_RETRIES2 - 1) {
68153
- retries++;
68154
- await new Promise((resolve18) => setTimeout(resolve18, WINDOWS_RENAME_RETRY_DELAY_MS2));
68155
- continue;
68156
- }
68157
- throw lastError;
68158
- }
68159
- }
68160
- }
68161
- } finally {
68162
- try {
68163
- await fsPromises5.unlink(tempPath);
68164
- } catch (error93) {
68165
- if (error93 instanceof Error && "code" in error93 && error93.code !== "ENOENT") {
68166
- error48(`Failed to clean up temp file ${tempPath}:`, error93);
68167
- }
68168
- }
68169
- }
68170
- const stats = await fsPromises5.stat(graphPath);
68171
- setCachedGraph(normalized, graph, stats.mtimeMs);
68172
- }
68173
- var SKIP_DIRECTORIES2 = new Set([
68174
- "node_modules",
68175
- ".git",
68176
- "dist",
68177
- "build",
68178
- "out",
68179
- "coverage",
68180
- ".next",
68181
- ".nuxt",
68182
- ".cache",
68183
- "vendor",
68184
- ".svn",
68185
- ".hg"
68186
- ]);
68187
- var SUPPORTED_EXTENSIONS = [
68188
- ".ts",
68189
- ".tsx",
68190
- ".js",
68191
- ".jsx",
68192
- ".mjs",
68193
- ".cjs",
68194
- ".py"
68195
- ];
68196
- var DEFAULT_WALK_FILE_CAP = 1e4;
68197
- var DEFAULT_WALK_BUDGET_MS = 5000;
68198
- var ASYNC_WALK_YIELD_INTERVAL = 200;
68199
68022
  function isRefusedWorkspaceRoot(target) {
68200
68023
  let resolved;
68201
68024
  try {
68202
68025
  resolved = realpathSync6(target);
68203
68026
  } catch {
68204
- resolved = path53.resolve(target);
68027
+ resolved = path54.resolve(target);
68205
68028
  }
68206
68029
  const refused = new Set;
68207
68030
  const add = (p) => {
68208
68031
  if (typeof p === "string" && p.length > 0) {
68209
- refused.add(path53.resolve(p));
68032
+ refused.add(path54.resolve(p));
68210
68033
  }
68211
68034
  };
68212
68035
  add(os7.homedir());
@@ -68221,15 +68044,6 @@ function isRefusedWorkspaceRoot(target) {
68221
68044
  }
68222
68045
  return refused.has(resolved);
68223
68046
  }
68224
- var EXTENSION_TO_LANGUAGE = {
68225
- ".ts": "typescript",
68226
- ".tsx": "typescript",
68227
- ".js": "javascript",
68228
- ".jsx": "javascript",
68229
- ".mjs": "javascript",
68230
- ".cjs": "javascript",
68231
- ".py": "python"
68232
- };
68233
68047
  function parseFileImports(content) {
68234
68048
  const imports = [];
68235
68049
  const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`\0\t\r\n]+)['"`]|import\s+['"`]([^'"`\0\t\r\n]+)['"`]|require\s*\(\s*['"`]([^'"`\0\t\r\n]+)['"`]\s*\)|export\s*\{[^}]*\}\s*from\s+['"`]([^'"`\0\t\r\n]+)['"`]|export\s+\*(?:\s+as\s+\w+)?\s+from\s+['"`]([^'"`\0\t\r\n]+)['"`]|import\s*\(\s*['"`]([^'"`\0\t\r\n]+)['"`]\s*\)/g;
@@ -68325,7 +68139,7 @@ async function findSourceFilesAsync(dir, stats, options) {
68325
68139
  ctx.stats.skippedDirs++;
68326
68140
  continue;
68327
68141
  }
68328
- const fullPath = path53.join(current, entry.name);
68142
+ const fullPath = path54.join(current, entry.name);
68329
68143
  if (entry.isSymbolicLink() && !ctx.followSymlinks) {
68330
68144
  ctx.stats.skippedDirs++;
68331
68145
  continue;
@@ -68333,7 +68147,7 @@ async function findSourceFilesAsync(dir, stats, options) {
68333
68147
  if (entry.isDirectory()) {
68334
68148
  queue.push(fullPath);
68335
68149
  } else if (entry.isFile()) {
68336
- const ext = path53.extname(fullPath).toLowerCase();
68150
+ const ext = path54.extname(fullPath).toLowerCase();
68337
68151
  if (SUPPORTED_EXTENSIONS.includes(ext)) {
68338
68152
  files.push(fullPath);
68339
68153
  }
@@ -68350,11 +68164,11 @@ async function findSourceFilesAsync(dir, stats, options) {
68350
68164
  return files;
68351
68165
  }
68352
68166
  function toModuleName(filePath, workspaceRoot) {
68353
- const relative9 = path53.relative(workspaceRoot, filePath);
68354
- return relative9.split(path53.sep).join("/");
68167
+ const relative9 = path54.relative(workspaceRoot, filePath);
68168
+ return relative9.split(path54.sep).join("/");
68355
68169
  }
68356
68170
  function getLanguage(filePath) {
68357
- const ext = path53.extname(filePath).toLowerCase();
68171
+ const ext = path54.extname(filePath).toLowerCase();
68358
68172
  return EXTENSION_TO_LANGUAGE[ext] ?? "unknown";
68359
68173
  }
68360
68174
  function isBinaryContent(content) {
@@ -68363,13 +68177,67 @@ function isBinaryContent(content) {
68363
68177
  }
68364
68178
  return false;
68365
68179
  }
68180
+ function scanFile(filePath, absoluteRoot, maxFileSize) {
68181
+ let content;
68182
+ let fileStats;
68183
+ try {
68184
+ fileStats = fsSync3.statSync(filePath);
68185
+ if (fileStats.size > maxFileSize) {
68186
+ return { node: null, edges: [] };
68187
+ }
68188
+ content = fsSync3.readFileSync(filePath, "utf-8");
68189
+ } catch {
68190
+ return { node: null, edges: [] };
68191
+ }
68192
+ if (isBinaryContent(content)) {
68193
+ return { node: null, edges: [] };
68194
+ }
68195
+ const ext = path54.extname(filePath).toLowerCase();
68196
+ let exports = [];
68197
+ try {
68198
+ if ([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext)) {
68199
+ const relativePath = path54.relative(absoluteRoot, filePath);
68200
+ const symbols2 = extractTSSymbols(relativePath, absoluteRoot);
68201
+ exports = symbols2.filter((s) => s.exported).map((s) => s.name);
68202
+ } else if (ext === ".py") {
68203
+ const relativePath = path54.relative(absoluteRoot, filePath);
68204
+ const symbols2 = extractPythonSymbols(relativePath, absoluteRoot);
68205
+ exports = symbols2.filter((s) => s.exported).map((s) => s.name);
68206
+ }
68207
+ const parsedImports = parseFileImports(content);
68208
+ const node = {
68209
+ filePath,
68210
+ moduleName: toModuleName(filePath, absoluteRoot),
68211
+ exports,
68212
+ imports: parsedImports.map((p) => p.specifier),
68213
+ language: getLanguage(filePath),
68214
+ mtime: fileStats.mtime.toISOString()
68215
+ };
68216
+ const edges = [];
68217
+ const sortedImports = [...parsedImports].sort((a, b) => a.specifier.localeCompare(b.specifier));
68218
+ for (const parsed of sortedImports) {
68219
+ const resolvedTarget = resolveModuleSpecifier(absoluteRoot, filePath, parsed.specifier);
68220
+ if (resolvedTarget !== null) {
68221
+ edges.push({
68222
+ source: filePath,
68223
+ target: resolvedTarget,
68224
+ importSpecifier: parsed.specifier,
68225
+ importType: parsed.importType
68226
+ });
68227
+ }
68228
+ }
68229
+ return { node, edges };
68230
+ } catch {
68231
+ return { node: null, edges: [] };
68232
+ }
68233
+ }
68366
68234
  async function buildWorkspaceGraphAsync(workspaceRoot, options) {
68367
68235
  validateWorkspace(workspaceRoot);
68368
68236
  const maxFileSize = options?.maxFileSizeBytes ?? 1024 * 1024;
68369
68237
  const maxFiles = options?.maxFiles ?? DEFAULT_WALK_FILE_CAP;
68370
68238
  const walkBudgetMs = options?.walkBudgetMs ?? DEFAULT_WALK_BUDGET_MS;
68371
68239
  const followSymlinks = options?.followSymlinks ?? false;
68372
- const absoluteRoot = path53.resolve(workspaceRoot);
68240
+ const absoluteRoot = path54.resolve(workspaceRoot);
68373
68241
  if (!existsSync29(absoluteRoot)) {
68374
68242
  throw new Error(`Workspace directory does not exist: ${workspaceRoot}`);
68375
68243
  }
@@ -68424,60 +68292,225 @@ async function buildWorkspaceGraphAsync(workspaceRoot, options) {
68424
68292
  }
68425
68293
  return graph;
68426
68294
  }
68427
- function scanFile(filePath, absoluteRoot, maxFileSize) {
68428
- let content;
68429
- let fileStats;
68295
+ // src/tools/repo-graph/cache.ts
68296
+ import * as path55 from "node:path";
68297
+ var graphCache = new Map;
68298
+ var dirtyFlags = new Map;
68299
+ var mtimeCache = new Map;
68300
+ function getCachedGraph(workspace) {
68301
+ return graphCache.get(path55.normalize(workspace));
68302
+ }
68303
+ function setCachedGraph(workspace, graph, mtime) {
68304
+ const normalized = path55.normalize(workspace);
68305
+ graphCache.set(normalized, graph);
68306
+ dirtyFlags.set(normalized, false);
68307
+ if (mtime !== undefined) {
68308
+ mtimeCache.set(normalized, mtime);
68309
+ }
68310
+ }
68311
+ function isDirty(workspace) {
68312
+ return dirtyFlags.get(path55.normalize(workspace)) ?? false;
68313
+ }
68314
+ function clearCache(workspace) {
68315
+ const normalized = path55.normalize(workspace);
68316
+ graphCache.delete(normalized);
68317
+ dirtyFlags.delete(normalized);
68318
+ mtimeCache.delete(normalized);
68319
+ }
68320
+ function getCachedMtime(workspace) {
68321
+ return mtimeCache.get(path55.normalize(workspace));
68322
+ }
68323
+ // src/tools/repo-graph/incremental.ts
68324
+ import { existsSync as existsSync31 } from "node:fs";
68325
+ import * as fsPromises7 from "node:fs/promises";
68326
+ import * as path57 from "node:path";
68327
+
68328
+ // src/tools/repo-graph/storage.ts
68329
+ init_utils2();
68330
+ init_path_security();
68331
+ import { constants as constants4, existsSync as existsSync30, realpathSync as realpathSync7 } from "node:fs";
68332
+ import * as fsPromises6 from "node:fs/promises";
68333
+ import * as path56 from "node:path";
68334
+ var WINDOWS_RENAME_MAX_RETRIES2 = 3;
68335
+ var WINDOWS_RENAME_RETRY_DELAY_MS2 = 50;
68336
+ function getGraphPath(workspace) {
68337
+ validateWorkspace(workspace);
68338
+ const basePath = validateSwarmPath(workspace, REPO_GRAPH_FILENAME);
68339
+ validateSymlinkBoundary(basePath, workspace);
68340
+ return basePath;
68341
+ }
68342
+ async function loadGraph(workspace) {
68343
+ validateWorkspace(workspace);
68344
+ const normalized = path56.normalize(workspace);
68345
+ const cached3 = getCachedGraph(normalized);
68346
+ if (cached3 && !isDirty(normalized)) {
68347
+ try {
68348
+ const graphPath = getGraphPath(workspace);
68349
+ if (existsSync30(graphPath)) {
68350
+ const stats = await fsPromises6.stat(graphPath);
68351
+ const cachedMtime = getCachedMtime(normalized);
68352
+ if (cachedMtime !== undefined && stats.mtimeMs !== cachedMtime) {
68353
+ clearCache(normalized);
68354
+ } else {
68355
+ return cached3;
68356
+ }
68357
+ } else {
68358
+ clearCache(normalized);
68359
+ }
68360
+ } catch {
68361
+ clearCache(normalized);
68362
+ }
68363
+ }
68430
68364
  try {
68431
- fileStats = fsSync3.statSync(filePath);
68432
- if (fileStats.size > maxFileSize) {
68433
- return { node: null, edges: [] };
68365
+ const graphPath = getGraphPath(workspace);
68366
+ if (!existsSync30(graphPath)) {
68367
+ return null;
68434
68368
  }
68435
- content = fsSync3.readFileSync(filePath, "utf-8");
68369
+ const stats = await fsPromises6.stat(graphPath);
68370
+ const content = await fsPromises6.readFile(graphPath, "utf-8");
68371
+ if (content.includes("\x00") || content.includes("�")) {
68372
+ throw Object.assign(new Error("repo-graph.json contains null bytes or invalid encoding"), { code: "CORRUPTION" });
68373
+ }
68374
+ let parsed;
68375
+ try {
68376
+ parsed = JSON.parse(content);
68377
+ } catch {
68378
+ throw Object.assign(new Error("repo-graph.json contains invalid JSON"), {
68379
+ code: "CORRUPTION"
68380
+ });
68381
+ }
68382
+ if (!parsed.schema_version) {
68383
+ throw Object.assign(new Error("repo-graph.json missing schema_version"), {
68384
+ code: "CORRUPTION"
68385
+ });
68386
+ }
68387
+ if (!parsed.nodes || typeof parsed.nodes !== "object") {
68388
+ throw Object.assign(new Error("repo-graph.json missing or invalid nodes"), { code: "CORRUPTION" });
68389
+ }
68390
+ if (!Array.isArray(parsed.edges)) {
68391
+ throw Object.assign(new Error("repo-graph.json missing or invalid edges"), { code: "CORRUPTION" });
68392
+ }
68393
+ for (const [key, node] of Object.entries(parsed.nodes)) {
68394
+ if (!key || typeof key !== "string") {
68395
+ throw Object.assign(new Error("repo-graph.json contains invalid node key"), { code: "CORRUPTION" });
68396
+ }
68397
+ try {
68398
+ validateGraphNode(node);
68399
+ } catch (err2) {
68400
+ const msg = err2 instanceof Error ? err2.message : "Invalid node structure";
68401
+ throw Object.assign(new Error(`repo-graph.json node validation failed: ${msg}`), { code: "CORRUPTION" });
68402
+ }
68403
+ }
68404
+ for (const edge of parsed.edges) {
68405
+ try {
68406
+ validateGraphEdge(edge);
68407
+ } catch (err2) {
68408
+ const msg = err2 instanceof Error ? err2.message : "Invalid edge structure";
68409
+ throw Object.assign(new Error(`repo-graph.json edge validation failed: ${msg}`), { code: "CORRUPTION" });
68410
+ }
68411
+ }
68412
+ 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") {
68413
+ throw Object.assign(new Error("repo-graph.json missing or invalid metadata"), { code: "CORRUPTION" });
68414
+ }
68415
+ setCachedGraph(normalized, parsed, stats.mtimeMs);
68416
+ return parsed;
68417
+ } catch (error93) {
68418
+ if (error93 instanceof Error && "code" in error93 && error93.code === "CORRUPTION") {
68419
+ throw error93;
68420
+ }
68421
+ if (error93 instanceof Error && "code" in error93 && error93.code === "ENOENT") {
68422
+ return null;
68423
+ }
68424
+ throw error93;
68425
+ }
68426
+ }
68427
+ async function saveGraph(workspace, graph, options) {
68428
+ validateWorkspace(workspace);
68429
+ if (!graph.schema_version) {
68430
+ throw new Error("Graph must have schema_version");
68431
+ }
68432
+ if (!graph.nodes || typeof graph.nodes !== "object") {
68433
+ throw new Error("Graph must have nodes object");
68434
+ }
68435
+ if (!Array.isArray(graph.edges)) {
68436
+ throw new Error("Graph must have edges array");
68437
+ }
68438
+ const normalizedWorkspace = path56.normalize(workspace);
68439
+ let realWorkspace;
68440
+ try {
68441
+ realWorkspace = realpathSync7(workspace);
68436
68442
  } catch {
68437
- return { node: null, edges: [] };
68443
+ realWorkspace = normalizedWorkspace;
68438
68444
  }
68439
- if (isBinaryContent(content)) {
68440
- return { node: null, edges: [] };
68445
+ const normalizedGraphRoot = path56.normalize(graph.workspaceRoot);
68446
+ let realGraphRoot;
68447
+ try {
68448
+ realGraphRoot = realpathSync7(graph.workspaceRoot);
68449
+ } catch {
68450
+ realGraphRoot = normalizedGraphRoot;
68441
68451
  }
68442
- const ext = path53.extname(filePath).toLowerCase();
68443
- let exports = [];
68452
+ if (path56.normalize(realWorkspace) !== path56.normalize(realGraphRoot)) {
68453
+ throw new Error(`Graph workspaceRoot mismatch: graph was built for "${graph.workspaceRoot}" but save was called for "${workspace}"`);
68454
+ }
68455
+ const normalized = normalizedWorkspace;
68456
+ const graphPath = getGraphPath(workspace);
68457
+ updateGraphMetadata(graph);
68458
+ const tempPath = `${graphPath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
68459
+ await fsPromises6.mkdir(path56.dirname(tempPath), { recursive: true });
68460
+ let lastError = null;
68444
68461
  try {
68445
- if ([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext)) {
68446
- const relativePath = path53.relative(absoluteRoot, filePath);
68447
- const symbols2 = extractTSSymbols(relativePath, absoluteRoot);
68448
- exports = symbols2.filter((s) => s.exported).map((s) => s.name);
68449
- } else if (ext === ".py") {
68450
- const relativePath = path53.relative(absoluteRoot, filePath);
68451
- const symbols2 = extractPythonSymbols(relativePath, absoluteRoot);
68452
- exports = symbols2.filter((s) => s.exported).map((s) => s.name);
68462
+ if (options?.createAtomic) {
68463
+ try {
68464
+ const handle2 = await fsPromises6.open(tempPath, "wx", 420);
68465
+ await handle2.writeFile(JSON.stringify(graph, null, 2), "utf-8");
68466
+ await handle2.close();
68467
+ } catch (error93) {
68468
+ if (error93 instanceof Error && "code" in error93 && error93.code === "EEXIST") {
68469
+ throw new Error("file already exists");
68470
+ }
68471
+ throw error93;
68472
+ }
68473
+ } else {
68474
+ await fsPromises6.writeFile(tempPath, JSON.stringify(graph, null, 2), "utf-8");
68453
68475
  }
68454
- const parsedImports = parseFileImports(content);
68455
- const node = {
68456
- filePath,
68457
- moduleName: toModuleName(filePath, absoluteRoot),
68458
- exports,
68459
- imports: parsedImports.map((p) => p.specifier),
68460
- language: getLanguage(filePath),
68461
- mtime: fileStats.mtime.toISOString()
68462
- };
68463
- const edges = [];
68464
- const sortedImports = [...parsedImports].sort((a, b) => a.specifier.localeCompare(b.specifier));
68465
- for (const parsed of sortedImports) {
68466
- const resolvedTarget = resolveModuleSpecifier(absoluteRoot, filePath, parsed.specifier);
68467
- if (resolvedTarget !== null) {
68468
- edges.push({
68469
- source: filePath,
68470
- target: resolvedTarget,
68471
- importSpecifier: parsed.specifier,
68472
- importType: parsed.importType
68473
- });
68476
+ if (options?.createAtomic) {
68477
+ try {
68478
+ await fsPromises6.copyFile(tempPath, graphPath, constants4.COPYFILE_EXCL);
68479
+ } catch (error93) {
68480
+ lastError = error93 instanceof Error ? error93 : new Error(String(error93));
68481
+ throw lastError;
68482
+ }
68483
+ } else {
68484
+ let retries = 0;
68485
+ while (retries < WINDOWS_RENAME_MAX_RETRIES2) {
68486
+ try {
68487
+ await fsPromises6.rename(tempPath, graphPath);
68488
+ break;
68489
+ } catch (error93) {
68490
+ lastError = error93 instanceof Error ? error93 : new Error(String(error93));
68491
+ if (lastError instanceof Error && "code" in lastError && lastError.code === "EEXIST" && retries < WINDOWS_RENAME_MAX_RETRIES2 - 1) {
68492
+ retries++;
68493
+ await new Promise((resolve18) => setTimeout(resolve18, WINDOWS_RENAME_RETRY_DELAY_MS2));
68494
+ continue;
68495
+ }
68496
+ throw lastError;
68497
+ }
68498
+ }
68499
+ }
68500
+ } finally {
68501
+ try {
68502
+ await fsPromises6.unlink(tempPath);
68503
+ } catch (error93) {
68504
+ if (error93 instanceof Error && "code" in error93 && error93.code !== "ENOENT") {
68505
+ error48(`Failed to clean up temp file ${tempPath}:`, error93);
68474
68506
  }
68475
68507
  }
68476
- return { node, edges };
68477
- } catch {
68478
- return { node: null, edges: [] };
68479
68508
  }
68509
+ const stats = await fsPromises6.stat(graphPath);
68510
+ setCachedGraph(normalized, graph, stats.mtimeMs);
68480
68511
  }
68512
+
68513
+ // src/tools/repo-graph/incremental.ts
68481
68514
  async function updateGraphForFiles(workspaceRoot, filePaths, options) {
68482
68515
  if (options?.forceRebuild) {
68483
68516
  const graph2 = await buildWorkspaceGraphAsync(workspaceRoot);
@@ -68491,12 +68524,12 @@ async function updateGraphForFiles(workspaceRoot, filePaths, options) {
68491
68524
  return graph2;
68492
68525
  }
68493
68526
  const graph = existingGraph;
68494
- const absoluteRoot = path53.resolve(workspaceRoot);
68527
+ const absoluteRoot = path57.resolve(workspaceRoot);
68495
68528
  const maxFileSize = 1024 * 1024;
68496
68529
  const updatedPaths = new Set;
68497
68530
  for (const rawFilePath of filePaths) {
68498
68531
  const normalizedPath = normalizeGraphPath(rawFilePath);
68499
- const fileExists = existsSync29(rawFilePath);
68532
+ const fileExists = existsSync31(rawFilePath);
68500
68533
  if (fileExists) {
68501
68534
  graph.edges = graph.edges.filter((e) => normalizeGraphPath(e.source) !== normalizedPath);
68502
68535
  const result = scanFile(rawFilePath, absoluteRoot, maxFileSize);
@@ -68531,6 +68564,22 @@ async function updateGraphForFiles(workspaceRoot, filePaths, options) {
68531
68564
  await saveGraph(workspaceRoot, rebuiltGraph);
68532
68565
  return rebuiltGraph;
68533
68566
  }
68567
+ const normalizedWorkspace = path57.normalize(workspaceRoot);
68568
+ const loadedMtime = getCachedMtime(normalizedWorkspace);
68569
+ if (loadedMtime !== undefined) {
68570
+ try {
68571
+ const graphPath = getGraphPath(workspaceRoot);
68572
+ if (existsSync31(graphPath)) {
68573
+ const currentStats = await fsPromises7.stat(graphPath);
68574
+ if (currentStats.mtimeMs !== loadedMtime) {
68575
+ warn(`[repo-graph] Concurrent modification detected — falling back to full rebuild`);
68576
+ const rebuiltGraph = await buildWorkspaceGraphAsync(workspaceRoot);
68577
+ await saveGraph(workspaceRoot, rebuiltGraph);
68578
+ return rebuiltGraph;
68579
+ }
68580
+ }
68581
+ } catch {}
68582
+ }
68534
68583
  updateGraphMetadata(graph);
68535
68584
  await saveGraph(workspaceRoot, graph);
68536
68585
  return graph;
@@ -68549,9 +68598,20 @@ function extractFilePath(args2) {
68549
68598
  if (!args2 || typeof args2 !== "object")
68550
68599
  return null;
68551
68600
  const a = args2;
68552
- const filePath = a.file_path ?? a.path ?? a.filePath;
68601
+ let filePath = a.file_path ?? a.path ?? a.filePath;
68553
68602
  if (!filePath || typeof filePath !== "string")
68554
68603
  return null;
68604
+ for (let i2 = 0;i2 < 3; i2++) {
68605
+ try {
68606
+ const decoded = decodeURIComponent(filePath);
68607
+ if (decoded === filePath)
68608
+ break;
68609
+ filePath = decoded;
68610
+ } catch {
68611
+ break;
68612
+ }
68613
+ }
68614
+ filePath = filePath.replace(/./g, ".").replace(///g, "/").replace(/․/g, ".");
68555
68615
  return filePath;
68556
68616
  }
68557
68617
  function isSupportedSourceFile(filePath) {
@@ -68564,6 +68624,8 @@ function createRepoGraphBuilderHook(workspaceRoot, deps) {
68564
68624
  const _updateGraphForFiles = deps?.updateGraphForFiles ?? updateGraphForFiles;
68565
68625
  let initStarted = false;
68566
68626
  let initPromise = Promise.resolve();
68627
+ let consecutiveFailures = 0;
68628
+ const FAILURE_ADVISORY_THRESHOLD = 3;
68567
68629
  async function doInit() {
68568
68630
  await yieldToEventLoop();
68569
68631
  try {
@@ -68592,37 +68654,48 @@ function createRepoGraphBuilderHook(workspaceRoot, deps) {
68592
68654
  if (!WRITE_TOOL_NAMES.includes(input.tool)) {
68593
68655
  return;
68594
68656
  }
68595
- const rawFilePath = extractFilePath(input.args);
68596
- if (!rawFilePath)
68657
+ const filePath = extractFilePath(input.args);
68658
+ if (!filePath)
68597
68659
  return;
68598
- if (rawFilePath.includes("\x00"))
68660
+ if (filePath.includes("\x00"))
68599
68661
  return;
68600
- let filePath = rawFilePath;
68601
- for (let i2 = 0;i2 < 3; i2++) {
68602
- try {
68603
- const decoded = decodeURIComponent(filePath);
68604
- if (decoded === filePath)
68605
- break;
68606
- filePath = decoded;
68607
- } catch {
68608
- break;
68609
- }
68610
- }
68611
- filePath = filePath.replace(/./g, ".").replace(///g, "/").replace(/․/g, ".");
68612
68662
  if (!isSupportedSourceFile(filePath))
68613
68663
  return;
68614
- const absoluteFilePath = path54.isAbsolute(filePath) ? filePath : path54.resolve(workspaceRoot, filePath);
68615
- const normalizedAbsolute = absoluteFilePath.replace(/\\/g, "/");
68616
- const normalizedWorkspace = workspaceRoot.replace(/\\/g, "/");
68664
+ const absoluteFilePath = path58.isAbsolute(filePath) ? filePath : path58.resolve(workspaceRoot, filePath);
68665
+ let realFilePath;
68666
+ try {
68667
+ realFilePath = realpathSync8(absoluteFilePath);
68668
+ } catch (error93) {
68669
+ if (!(error93 instanceof Error) || error93.code !== "ENOENT") {
68670
+ return;
68671
+ }
68672
+ realFilePath = absoluteFilePath;
68673
+ }
68674
+ let realWorkspace;
68675
+ try {
68676
+ realWorkspace = realpathSync8(workspaceRoot);
68677
+ } catch (error93) {
68678
+ if (!(error93 instanceof Error) || error93.code !== "ENOENT") {
68679
+ return;
68680
+ }
68681
+ realWorkspace = workspaceRoot;
68682
+ }
68683
+ const normalizedAbsolute = realFilePath.replace(/\\/g, "/");
68684
+ const normalizedWorkspace = realWorkspace.replace(/\\/g, "/");
68617
68685
  if (!normalizedAbsolute.startsWith(`${normalizedWorkspace}/`) && normalizedAbsolute !== normalizedWorkspace) {
68618
68686
  return;
68619
68687
  }
68620
68688
  try {
68621
68689
  await _updateGraphForFiles(workspaceRoot, [absoluteFilePath]);
68622
- log(`[repo-graph] Incremental update for ${path54.basename(filePath)}`);
68690
+ consecutiveFailures = 0;
68691
+ log(`[repo-graph] Incremental update for ${path58.basename(filePath)}`);
68623
68692
  } catch (error93) {
68624
68693
  const message = error93 instanceof Error ? error93.message : String(error93);
68694
+ consecutiveFailures++;
68625
68695
  error48(`[repo-graph] Incremental update failed: ${message}`);
68696
+ if (consecutiveFailures >= FAILURE_ADVISORY_THRESHOLD) {
68697
+ warn(`[repo-graph] ${consecutiveFailures} consecutive incremental update failures. ` + `The dependency graph may be stale. Consider reloading the workspace.`);
68698
+ }
68626
68699
  }
68627
68700
  }
68628
68701
  };
@@ -68638,14 +68711,14 @@ init_manager2();
68638
68711
  init_detector();
68639
68712
  init_manager();
68640
68713
  import * as fs46 from "node:fs";
68641
- import * as path64 from "node:path";
68714
+ import * as path68 from "node:path";
68642
68715
 
68643
68716
  // src/services/decision-drift-analyzer.ts
68644
68717
  init_utils2();
68645
68718
  init_manager();
68646
68719
  init_utils();
68647
68720
  import * as fs38 from "node:fs";
68648
- import * as path55 from "node:path";
68721
+ import * as path59 from "node:path";
68649
68722
  var DEFAULT_DRIFT_CONFIG = {
68650
68723
  staleThresholdPhases: 1,
68651
68724
  detectContradictions: true,
@@ -68799,7 +68872,7 @@ async function analyzeDecisionDrift(directory, config3 = {}) {
68799
68872
  currentPhase = legacyPhase;
68800
68873
  }
68801
68874
  }
68802
- const contextPath = path55.join(directory, ".swarm", "context.md");
68875
+ const contextPath = path59.join(directory, ".swarm", "context.md");
68803
68876
  let contextContent = "";
68804
68877
  try {
68805
68878
  if (fs38.existsSync(contextPath)) {
@@ -68938,7 +69011,7 @@ init_utils();
68938
69011
  init_constants();
68939
69012
  init_schema();
68940
69013
  import * as fs39 from "node:fs/promises";
68941
- import * as path56 from "node:path";
69014
+ import * as path60 from "node:path";
68942
69015
  function safeGet(obj, key) {
68943
69016
  if (!obj || !Object.hasOwn(obj, key))
68944
69017
  return;
@@ -69170,9 +69243,9 @@ async function handleDebuggingSpiral(match, taskId, directory) {
69170
69243
  let eventLogged = false;
69171
69244
  let checkpointCreated = false;
69172
69245
  try {
69173
- const swarmDir = path56.join(directory, ".swarm");
69246
+ const swarmDir = path60.join(directory, ".swarm");
69174
69247
  await fs39.mkdir(swarmDir, { recursive: true });
69175
- const eventsPath = path56.join(swarmDir, "events.jsonl");
69248
+ const eventsPath = path60.join(swarmDir, "events.jsonl");
69176
69249
  await fs39.appendFile(eventsPath, `${formatDebuggingSpiralEvent(match, taskId)}
69177
69250
  `);
69178
69251
  eventLogged = true;
@@ -69307,7 +69380,7 @@ import * as fs43 from "node:fs";
69307
69380
 
69308
69381
  // src/graph/graph-builder.ts
69309
69382
  import * as fs41 from "node:fs";
69310
- import * as path59 from "node:path";
69383
+ import * as path63 from "node:path";
69311
69384
 
69312
69385
  // node_modules/yocto-queue/index.js
69313
69386
  class Node {
@@ -69398,26 +69471,26 @@ function pLimit(concurrency) {
69398
69471
  activeCount--;
69399
69472
  resumeNext();
69400
69473
  };
69401
- const run2 = async (function_, resolve19, arguments_2) => {
69474
+ const run2 = async (function_, resolve20, arguments_2) => {
69402
69475
  const result = (async () => function_(...arguments_2))();
69403
- resolve19(result);
69476
+ resolve20(result);
69404
69477
  try {
69405
69478
  await result;
69406
69479
  } catch {}
69407
69480
  next();
69408
69481
  };
69409
- const enqueue = (function_, resolve19, reject, arguments_2) => {
69482
+ const enqueue = (function_, resolve20, reject, arguments_2) => {
69410
69483
  const queueItem = { reject };
69411
69484
  new Promise((internalResolve) => {
69412
69485
  queueItem.run = internalResolve;
69413
69486
  queue.enqueue(queueItem);
69414
- }).then(run2.bind(undefined, function_, resolve19, arguments_2));
69487
+ }).then(run2.bind(undefined, function_, resolve20, arguments_2));
69415
69488
  if (activeCount < concurrency) {
69416
69489
  resumeNext();
69417
69490
  }
69418
69491
  };
69419
- const generator = (function_, ...arguments_2) => new Promise((resolve19, reject) => {
69420
- enqueue(function_, resolve19, reject, arguments_2);
69492
+ const generator = (function_, ...arguments_2) => new Promise((resolve20, reject) => {
69493
+ enqueue(function_, resolve20, reject, arguments_2);
69421
69494
  });
69422
69495
  Object.defineProperties(generator, {
69423
69496
  activeCount: {
@@ -69468,7 +69541,7 @@ function validateConcurrency(concurrency) {
69468
69541
  // src/graph/import-extractor.ts
69469
69542
  init_path_security();
69470
69543
  import * as fs40 from "node:fs";
69471
- import * as path57 from "node:path";
69544
+ import * as path61 from "node:path";
69472
69545
  var SOURCE_EXTENSIONS2 = [
69473
69546
  ".ts",
69474
69547
  ".tsx",
@@ -69513,28 +69586,28 @@ function getLanguageFromExtension(ext) {
69513
69586
  return null;
69514
69587
  }
69515
69588
  function toRelForwardSlash(absPath, root) {
69516
- return path57.relative(root, absPath).replace(/\\/g, "/");
69589
+ return path61.relative(root, absPath).replace(/\\/g, "/");
69517
69590
  }
69518
69591
  function tryResolveTSJS(rawModule, sourceFileAbs) {
69519
69592
  if (!rawModule.startsWith(".") && !rawModule.startsWith("/")) {
69520
69593
  return null;
69521
69594
  }
69522
- const sourceDir = path57.dirname(sourceFileAbs);
69523
- const baseAbs = path57.resolve(sourceDir, rawModule);
69595
+ const sourceDir = path61.dirname(sourceFileAbs);
69596
+ const baseAbs = path61.resolve(sourceDir, rawModule);
69524
69597
  const probe = (basePath) => {
69525
69598
  for (const ext of RESOLVE_EXTENSION_CANDIDATES) {
69526
69599
  const test = basePath + ext;
69527
69600
  try {
69528
- const stat5 = fs40.statSync(test);
69529
- if (stat5.isFile())
69601
+ const stat6 = fs40.statSync(test);
69602
+ if (stat6.isFile())
69530
69603
  return test;
69531
69604
  } catch {}
69532
69605
  }
69533
69606
  for (const indexFile of RESOLVE_INDEX_CANDIDATES) {
69534
- const test = path57.join(basePath, indexFile);
69607
+ const test = path61.join(basePath, indexFile);
69535
69608
  try {
69536
- const stat5 = fs40.statSync(test);
69537
- if (stat5.isFile())
69609
+ const stat6 = fs40.statSync(test);
69610
+ if (stat6.isFile())
69538
69611
  return test;
69539
69612
  } catch {}
69540
69613
  }
@@ -69561,13 +69634,13 @@ function tryResolvePython(rawModule, sourceFileAbs, workspaceRoot) {
69561
69634
  }
69562
69635
  const remainder = rawModule.slice(leadingDots).replace(/\./g, "/");
69563
69636
  const upDirs = "../".repeat(Math.max(0, leadingDots - 1));
69564
- const sourceDir = path57.dirname(sourceFileAbs);
69565
- const baseAbs = path57.resolve(sourceDir, upDirs + remainder);
69637
+ const sourceDir = path61.dirname(sourceFileAbs);
69638
+ const baseAbs = path61.resolve(sourceDir, upDirs + remainder);
69566
69639
  const accept = (test) => {
69567
69640
  try {
69568
- const stat5 = fs40.statSync(test);
69569
- if (stat5.isFile()) {
69570
- const rel = path57.relative(workspaceRoot, test).replace(/\\/g, "/");
69641
+ const stat6 = fs40.statSync(test);
69642
+ if (stat6.isFile()) {
69643
+ const rel = path61.relative(workspaceRoot, test).replace(/\\/g, "/");
69571
69644
  if (rel.startsWith(".."))
69572
69645
  return null;
69573
69646
  return test;
@@ -69581,7 +69654,7 @@ function tryResolvePython(rawModule, sourceFileAbs, workspaceRoot) {
69581
69654
  return hit;
69582
69655
  }
69583
69656
  for (const indexFile of PY_INDEX_CANDIDATES) {
69584
- const hit = accept(path57.join(baseAbs, indexFile));
69657
+ const hit = accept(path61.join(baseAbs, indexFile));
69585
69658
  if (hit)
69586
69659
  return hit;
69587
69660
  }
@@ -69952,7 +70025,7 @@ function parseRustUses(content) {
69952
70025
  }
69953
70026
  function extractImports2(opts) {
69954
70027
  const { absoluteFilePath, workspaceRoot } = opts;
69955
- const ext = path57.extname(absoluteFilePath).toLowerCase();
70028
+ const ext = path61.extname(absoluteFilePath).toLowerCase();
69956
70029
  const language = getLanguageFromExtension(ext);
69957
70030
  if (!language)
69958
70031
  return [];
@@ -70003,9 +70076,9 @@ function extractImports2(opts) {
70003
70076
  }
70004
70077
 
70005
70078
  // src/graph/symbol-extractor.ts
70006
- import * as path58 from "node:path";
70079
+ import * as path62 from "node:path";
70007
70080
  function extractExportedSymbols(relativeFilePath, workspaceRoot) {
70008
- const ext = path58.extname(relativeFilePath).toLowerCase();
70081
+ const ext = path62.extname(relativeFilePath).toLowerCase();
70009
70082
  const language = getLanguageFromExtension(ext);
70010
70083
  if (!language)
70011
70084
  return [];
@@ -70094,15 +70167,15 @@ function findSourceFiles(workspaceRoot, skipDirs = DEFAULT_SKIP_DIRS) {
70094
70167
  if (entry.isDirectory()) {
70095
70168
  if (skipDirs.has(entry.name))
70096
70169
  continue;
70097
- stack.push(path59.join(dir, entry.name));
70170
+ stack.push(path63.join(dir, entry.name));
70098
70171
  continue;
70099
70172
  }
70100
70173
  if (!entry.isFile())
70101
70174
  continue;
70102
- const ext = path59.extname(entry.name).toLowerCase();
70175
+ const ext = path63.extname(entry.name).toLowerCase();
70103
70176
  if (!SOURCE_EXT_SET.has(ext))
70104
70177
  continue;
70105
- out2.push(path59.join(dir, entry.name));
70178
+ out2.push(path63.join(dir, entry.name));
70106
70179
  }
70107
70180
  }
70108
70181
  return out2;
@@ -70130,7 +70203,7 @@ async function buildRepoGraph(workspaceRoot, options = {}) {
70130
70203
  };
70131
70204
  }
70132
70205
  async function processFile(absoluteFilePath, workspaceRoot) {
70133
- const ext = path59.extname(absoluteFilePath).toLowerCase();
70206
+ const ext = path63.extname(absoluteFilePath).toLowerCase();
70134
70207
  const language = getLanguageFromExtension(ext);
70135
70208
  if (!language)
70136
70209
  return null;
@@ -70150,7 +70223,7 @@ async function processFile(absoluteFilePath, workspaceRoot) {
70150
70223
  } catch {
70151
70224
  return null;
70152
70225
  }
70153
- const relPath = path59.relative(workspaceRoot, absoluteFilePath).replace(/\\/g, "/");
70226
+ const relPath = path63.relative(workspaceRoot, absoluteFilePath).replace(/\\/g, "/");
70154
70227
  const imports = extractImports2({
70155
70228
  absoluteFilePath,
70156
70229
  workspaceRoot,
@@ -70392,10 +70465,10 @@ function formatSummary(opts) {
70392
70465
  // src/graph/graph-store.ts
70393
70466
  import * as crypto6 from "node:crypto";
70394
70467
  import * as fs42 from "node:fs";
70395
- import * as path60 from "node:path";
70468
+ import * as path64 from "node:path";
70396
70469
  var SWARM_DIR = ".swarm";
70397
70470
  function getGraphPath2(workspaceRoot) {
70398
- return path60.join(workspaceRoot, SWARM_DIR, REPO_GRAPH_FILENAME2);
70471
+ return path64.join(workspaceRoot, SWARM_DIR, REPO_GRAPH_FILENAME2);
70399
70472
  }
70400
70473
  function loadGraph2(workspaceRoot) {
70401
70474
  const file3 = getGraphPath2(workspaceRoot);
@@ -70417,10 +70490,10 @@ function loadGraph2(workspaceRoot) {
70417
70490
  }
70418
70491
  function saveGraph2(workspaceRoot, graph) {
70419
70492
  const file3 = getGraphPath2(workspaceRoot);
70420
- const dir = path60.dirname(file3);
70493
+ const dir = path64.dirname(file3);
70421
70494
  try {
70422
- const stat5 = fs42.lstatSync(dir);
70423
- if (stat5.isSymbolicLink()) {
70495
+ const stat6 = fs42.lstatSync(dir);
70496
+ if (stat6.isSymbolicLink()) {
70424
70497
  throw new Error(`refusing to write graph: ${SWARM_DIR}/ is a symbolic link`);
70425
70498
  }
70426
70499
  } catch (err2) {
@@ -70456,15 +70529,15 @@ function isGraphFresh(graph, maxAgeMs = 5 * 60 * 1000) {
70456
70529
  var cache = new Map;
70457
70530
  function getCachedGraph2(directory) {
70458
70531
  const file3 = getGraphPath2(directory);
70459
- let stat5;
70532
+ let stat6;
70460
70533
  try {
70461
- stat5 = fs43.statSync(file3);
70534
+ stat6 = fs43.statSync(file3);
70462
70535
  } catch {
70463
70536
  cache.delete(directory);
70464
70537
  return null;
70465
70538
  }
70466
70539
  const cached3 = cache.get(directory);
70467
- if (cached3 && cached3.mtimeMs === stat5.mtimeMs && cached3.size === stat5.size) {
70540
+ if (cached3 && cached3.mtimeMs === stat6.mtimeMs && cached3.size === stat6.size) {
70468
70541
  return cached3.graph;
70469
70542
  }
70470
70543
  const graph = loadGraph2(directory);
@@ -70472,7 +70545,7 @@ function getCachedGraph2(directory) {
70472
70545
  cache.delete(directory);
70473
70546
  return null;
70474
70547
  }
70475
- cache.set(directory, { graph, mtimeMs: stat5.mtimeMs, size: stat5.size });
70548
+ cache.set(directory, { graph, mtimeMs: stat6.mtimeMs, size: stat6.size });
70476
70549
  return graph;
70477
70550
  }
70478
70551
  function buildCoderLocalizationBlock(directory, targetFile) {
@@ -70523,7 +70596,7 @@ function buildReviewerBlastRadiusBlock(directory, changedFiles) {
70523
70596
  // src/hooks/semantic-diff-injection.ts
70524
70597
  import * as child_process5 from "node:child_process";
70525
70598
  import * as fs44 from "node:fs";
70526
- import * as path62 from "node:path";
70599
+ import * as path66 from "node:path";
70527
70600
 
70528
70601
  // src/diff/ast-diff.ts
70529
70602
  init_tree_sitter();
@@ -71270,17 +71343,17 @@ async function buildSemanticDiffBlock(directory, changedFiles, maxFiles = 10) {
71270
71343
  const fileConsumers = {};
71271
71344
  if (graph) {
71272
71345
  for (const f of filesToProcess) {
71273
- const relativePath = path62.isAbsolute(f) ? path62.relative(directory, f) : f;
71346
+ const relativePath = path66.isAbsolute(f) ? path66.relative(directory, f) : f;
71274
71347
  const normalized = normalizeGraphPath2(relativePath);
71275
71348
  fileConsumers[normalized] = getImporters(graph, normalized).length;
71276
71349
  fileConsumers[f] = fileConsumers[normalized];
71277
71350
  }
71278
71351
  }
71279
71352
  for (const filePath of filesToProcess) {
71280
- const normalizedPath = path62.normalize(filePath);
71281
- const resolvedPath = path62.resolve(directory, normalizedPath);
71282
- const relativeToDir = path62.relative(directory, resolvedPath);
71283
- if (relativeToDir.startsWith("..") || path62.isAbsolute(relativeToDir)) {
71353
+ const normalizedPath = path66.normalize(filePath);
71354
+ const resolvedPath = path66.resolve(directory, normalizedPath);
71355
+ const relativeToDir = path66.relative(directory, resolvedPath);
71356
+ if (relativeToDir.startsWith("..") || path66.isAbsolute(relativeToDir)) {
71284
71357
  continue;
71285
71358
  }
71286
71359
  try {
@@ -71307,7 +71380,7 @@ async function buildSemanticDiffBlock(directory, changedFiles, maxFiles = 10) {
71307
71380
  stdio: "pipe",
71308
71381
  maxBuffer: 5 * 1024 * 1024
71309
71382
  }) : "";
71310
- const newContent = fs44.readFileSync(path62.join(directory, filePath), "utf-8");
71383
+ const newContent = fs44.readFileSync(path66.join(directory, filePath), "utf-8");
71311
71384
  const astResult = await computeASTDiff(filePath, oldContent, newContent);
71312
71385
  if (astResult && (astResult.changes.length > 0 || astResult.error !== undefined)) {
71313
71386
  astDiffs.push(astResult);
@@ -71649,7 +71722,7 @@ function createSystemEnhancerHook(config3, directory) {
71649
71722
  await fs46.promises.writeFile(darkMatterPath, darkMatterReport, "utf-8");
71650
71723
  warn(`[system-enhancer] Dark matter scan complete: ${darkMatter.length} co-change patterns found`);
71651
71724
  try {
71652
- const projectName = path64.basename(path64.resolve(directory));
71725
+ const projectName = path68.basename(path68.resolve(directory));
71653
71726
  const knowledgeEntries = darkMatterToKnowledgeEntries2(darkMatter, projectName);
71654
71727
  const knowledgePath = resolveSwarmKnowledgePath(directory);
71655
71728
  const existingEntries = await readKnowledge(knowledgePath);
@@ -71848,7 +71921,7 @@ ${lines.join(`
71848
71921
  try {
71849
71922
  const taskId_ccp = ccpSession?.currentTaskId;
71850
71923
  if (taskId_ccp && !taskId_ccp.includes("..") && !taskId_ccp.includes("/") && !taskId_ccp.includes("\\") && !taskId_ccp.includes("\x00")) {
71851
- const evidencePath = path64.join(directory, ".swarm", "evidence", `${taskId_ccp}.json`);
71924
+ const evidencePath = path68.join(directory, ".swarm", "evidence", `${taskId_ccp}.json`);
71852
71925
  if (fs46.existsSync(evidencePath)) {
71853
71926
  const evidenceContent = fs46.readFileSync(evidencePath, "utf-8");
71854
71927
  const evidenceData = JSON.parse(evidenceContent);
@@ -72996,13 +73069,13 @@ init_hive_promoter();
72996
73069
 
72997
73070
  // src/hooks/incremental-verify.ts
72998
73071
  import * as fs47 from "node:fs";
72999
- import * as path65 from "node:path";
73072
+ import * as path69 from "node:path";
73000
73073
 
73001
73074
  // src/hooks/spawn-helper.ts
73002
73075
  import * as child_process6 from "node:child_process";
73003
73076
  var WIN32_CMD_BINARIES = new Set(["npm", "npx", "pnpm", "yarn"]);
73004
73077
  function spawnAsync(command, cwd, timeoutMs) {
73005
- return new Promise((resolve23) => {
73078
+ return new Promise((resolve24) => {
73006
73079
  try {
73007
73080
  const [rawCmd, ...args2] = command;
73008
73081
  const cmd = process.platform === "win32" && WIN32_CMD_BINARIES.has(rawCmd) && !rawCmd.includes(".") ? `${rawCmd}.cmd` : rawCmd;
@@ -73049,24 +73122,24 @@ function spawnAsync(command, cwd, timeoutMs) {
73049
73122
  try {
73050
73123
  proc.kill();
73051
73124
  } catch {}
73052
- resolve23(null);
73125
+ resolve24(null);
73053
73126
  }, timeoutMs);
73054
73127
  proc.on("close", (code) => {
73055
73128
  if (done)
73056
73129
  return;
73057
73130
  done = true;
73058
73131
  clearTimeout(timer);
73059
- resolve23({ exitCode: code ?? 1, stdout, stderr });
73132
+ resolve24({ exitCode: code ?? 1, stdout, stderr });
73060
73133
  });
73061
73134
  proc.on("error", () => {
73062
73135
  if (done)
73063
73136
  return;
73064
73137
  done = true;
73065
73138
  clearTimeout(timer);
73066
- resolve23(null);
73139
+ resolve24(null);
73067
73140
  });
73068
73141
  } catch {
73069
- resolve23(null);
73142
+ resolve24(null);
73070
73143
  }
73071
73144
  });
73072
73145
  }
@@ -73074,18 +73147,18 @@ function spawnAsync(command, cwd, timeoutMs) {
73074
73147
  // src/hooks/incremental-verify.ts
73075
73148
  var emittedSkipAdvisories = new Set;
73076
73149
  function detectPackageManager(projectDir) {
73077
- if (fs47.existsSync(path65.join(projectDir, "bun.lockb")))
73150
+ if (fs47.existsSync(path69.join(projectDir, "bun.lockb")))
73078
73151
  return "bun";
73079
- if (fs47.existsSync(path65.join(projectDir, "pnpm-lock.yaml")))
73152
+ if (fs47.existsSync(path69.join(projectDir, "pnpm-lock.yaml")))
73080
73153
  return "pnpm";
73081
- if (fs47.existsSync(path65.join(projectDir, "yarn.lock")))
73154
+ if (fs47.existsSync(path69.join(projectDir, "yarn.lock")))
73082
73155
  return "yarn";
73083
- if (fs47.existsSync(path65.join(projectDir, "package-lock.json")))
73156
+ if (fs47.existsSync(path69.join(projectDir, "package-lock.json")))
73084
73157
  return "npm";
73085
73158
  return "bun";
73086
73159
  }
73087
73160
  function detectTypecheckCommand(projectDir) {
73088
- const pkgPath = path65.join(projectDir, "package.json");
73161
+ const pkgPath = path69.join(projectDir, "package.json");
73089
73162
  if (fs47.existsSync(pkgPath)) {
73090
73163
  try {
73091
73164
  const pkg = JSON.parse(fs47.readFileSync(pkgPath, "utf8"));
@@ -73102,8 +73175,8 @@ function detectTypecheckCommand(projectDir) {
73102
73175
  ...pkg.dependencies,
73103
73176
  ...pkg.devDependencies
73104
73177
  };
73105
- if (!deps?.typescript && !fs47.existsSync(path65.join(projectDir, "tsconfig.json"))) {}
73106
- const hasTSMarkers = deps?.typescript || fs47.existsSync(path65.join(projectDir, "tsconfig.json"));
73178
+ if (!deps?.typescript && !fs47.existsSync(path69.join(projectDir, "tsconfig.json"))) {}
73179
+ const hasTSMarkers = deps?.typescript || fs47.existsSync(path69.join(projectDir, "tsconfig.json"));
73107
73180
  if (hasTSMarkers) {
73108
73181
  return { command: ["npx", "tsc", "--noEmit"], language: "typescript" };
73109
73182
  }
@@ -73111,13 +73184,13 @@ function detectTypecheckCommand(projectDir) {
73111
73184
  return null;
73112
73185
  }
73113
73186
  }
73114
- if (fs47.existsSync(path65.join(projectDir, "go.mod"))) {
73187
+ if (fs47.existsSync(path69.join(projectDir, "go.mod"))) {
73115
73188
  return { command: ["go", "vet", "./..."], language: "go" };
73116
73189
  }
73117
- if (fs47.existsSync(path65.join(projectDir, "Cargo.toml"))) {
73190
+ if (fs47.existsSync(path69.join(projectDir, "Cargo.toml"))) {
73118
73191
  return { command: ["cargo", "check"], language: "rust" };
73119
73192
  }
73120
- if (fs47.existsSync(path65.join(projectDir, "pyproject.toml")) || fs47.existsSync(path65.join(projectDir, "requirements.txt")) || fs47.existsSync(path65.join(projectDir, "setup.py"))) {
73193
+ if (fs47.existsSync(path69.join(projectDir, "pyproject.toml")) || fs47.existsSync(path69.join(projectDir, "requirements.txt")) || fs47.existsSync(path69.join(projectDir, "setup.py"))) {
73121
73194
  return { command: null, language: "python" };
73122
73195
  }
73123
73196
  try {
@@ -73467,7 +73540,7 @@ init_scope_persistence();
73467
73540
  init_state();
73468
73541
  init_delegation_gate();
73469
73542
  init_normalize_tool_name();
73470
- import * as path67 from "node:path";
73543
+ import * as path71 from "node:path";
73471
73544
  var WRITE_TOOLS = new Set(WRITE_TOOL_NAMES);
73472
73545
  function createScopeGuardHook(config3, directory, injectAdvisory) {
73473
73546
  const enabled = config3.enabled ?? true;
@@ -73525,13 +73598,13 @@ function createScopeGuardHook(config3, directory, injectAdvisory) {
73525
73598
  }
73526
73599
  function isFileInScope(filePath, scopeEntries, directory) {
73527
73600
  const dir = directory ?? process.cwd();
73528
- const resolvedFile = path67.resolve(dir, filePath);
73601
+ const resolvedFile = path71.resolve(dir, filePath);
73529
73602
  return scopeEntries.some((scope) => {
73530
- const resolvedScope = path67.resolve(dir, scope);
73603
+ const resolvedScope = path71.resolve(dir, scope);
73531
73604
  if (resolvedFile === resolvedScope)
73532
73605
  return true;
73533
- const rel = path67.relative(resolvedScope, resolvedFile);
73534
- return rel.length > 0 && !rel.startsWith("..") && !path67.isAbsolute(rel);
73606
+ const rel = path71.relative(resolvedScope, resolvedFile);
73607
+ return rel.length > 0 && !rel.startsWith("..") && !path71.isAbsolute(rel);
73535
73608
  });
73536
73609
  }
73537
73610
 
@@ -73583,7 +73656,7 @@ function createSelfReviewHook(config3, injectAdvisory) {
73583
73656
 
73584
73657
  // src/hooks/slop-detector.ts
73585
73658
  import * as fs49 from "node:fs";
73586
- import * as path68 from "node:path";
73659
+ import * as path72 from "node:path";
73587
73660
  var WRITE_EDIT_TOOLS = new Set([
73588
73661
  "write",
73589
73662
  "edit",
@@ -73633,7 +73706,7 @@ function walkFiles(dir, exts, deadline) {
73633
73706
  break;
73634
73707
  if (entry.isSymbolicLink())
73635
73708
  continue;
73636
- const full = path68.join(dir, entry.name);
73709
+ const full = path72.join(dir, entry.name);
73637
73710
  if (entry.isDirectory()) {
73638
73711
  if (entry.name === "node_modules" || entry.name === ".git")
73639
73712
  continue;
@@ -73648,7 +73721,7 @@ function walkFiles(dir, exts, deadline) {
73648
73721
  return results;
73649
73722
  }
73650
73723
  function checkDeadExports(content, projectDir, startTime) {
73651
- const hasPackageJson = fs49.existsSync(path68.join(projectDir, "package.json"));
73724
+ const hasPackageJson = fs49.existsSync(path72.join(projectDir, "package.json"));
73652
73725
  if (!hasPackageJson)
73653
73726
  return null;
73654
73727
  const exportMatches = content.matchAll(/^\+(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm);
@@ -73762,14 +73835,14 @@ function checkDuplicateUtility(content, projectDir, startTime, targetFile) {
73762
73835
  for (const utilDir of utilityDirs) {
73763
73836
  if (Date.now() > deadline)
73764
73837
  break;
73765
- const utilPath = path68.join(projectDir, utilDir);
73838
+ const utilPath = path72.join(projectDir, utilDir);
73766
73839
  if (!fs49.existsSync(utilPath))
73767
73840
  continue;
73768
73841
  const files = walkFiles(utilPath, [".ts", ".tsx", ".js", ".jsx"], deadline);
73769
73842
  for (const file3 of files) {
73770
73843
  if (Date.now() > deadline)
73771
73844
  break;
73772
- if (targetFile && path68.resolve(file3) === path68.resolve(targetFile))
73845
+ if (targetFile && path72.resolve(file3) === path72.resolve(targetFile))
73773
73846
  continue;
73774
73847
  try {
73775
73848
  const text = fs49.readFileSync(file3, "utf-8");
@@ -73907,14 +73980,14 @@ function createSteeringConsumedHook(directory) {
73907
73980
  // src/hooks/trajectory-logger.ts
73908
73981
  init_manager2();
73909
73982
  import * as fs52 from "node:fs/promises";
73910
- import * as path70 from "node:path";
73983
+ import * as path74 from "node:path";
73911
73984
 
73912
73985
  // src/prm/trajectory-store.ts
73913
73986
  init_utils2();
73914
73987
  import * as fs51 from "node:fs/promises";
73915
- import * as path69 from "node:path";
73988
+ import * as path73 from "node:path";
73916
73989
  function getTrajectoryPath(sessionId, directory) {
73917
- const relativePath = path69.join("trajectories", `${sessionId}.jsonl`);
73990
+ const relativePath = path73.join("trajectories", `${sessionId}.jsonl`);
73918
73991
  return validateSwarmPath(directory, relativePath);
73919
73992
  }
73920
73993
  var _inMemoryTrajectoryCache = new Map;
@@ -73933,7 +74006,7 @@ async function appendTrajectoryEntry(sessionId, entry, directory, maxLines = 100
73933
74006
  _inMemoryTrajectoryCache.set(sessionId, cached3);
73934
74007
  }
73935
74008
  const trajectoryPath = getTrajectoryPath(sessionId, directory);
73936
- await fs51.mkdir(path69.dirname(trajectoryPath), { recursive: true });
74009
+ await fs51.mkdir(path73.dirname(trajectoryPath), { recursive: true });
73937
74010
  const line = `${JSON.stringify(entry)}
73938
74011
  `;
73939
74012
  await fs51.appendFile(trajectoryPath, line, "utf-8");
@@ -73972,10 +74045,10 @@ async function cleanupOldTrajectoryFiles(directory, maxAgeDays = 7) {
73972
74045
  for (const entry of entries) {
73973
74046
  if (!entry.isFile())
73974
74047
  continue;
73975
- const filePath = path69.join(dirPath, entry.name);
74048
+ const filePath = path73.join(dirPath, entry.name);
73976
74049
  try {
73977
- const stat6 = await fs51.stat(filePath);
73978
- if (now - stat6.mtimeMs > cutoffMs) {
74050
+ const stat7 = await fs51.stat(filePath);
74051
+ if (now - stat7.mtimeMs > cutoffMs) {
73979
74052
  await fs51.unlink(filePath);
73980
74053
  }
73981
74054
  } catch {}
@@ -74164,10 +74237,10 @@ function createTrajectoryLoggerHook(config3, _directory) {
74164
74237
  elapsed_ms
74165
74238
  };
74166
74239
  const sanitized = sanitizeTaskId2(taskId);
74167
- const relativePath = path70.join("evidence", sanitized, "trajectory.jsonl");
74240
+ const relativePath = path74.join("evidence", sanitized, "trajectory.jsonl");
74168
74241
  const trajectoryPath = validateSwarmPath(_directory, relativePath);
74169
74242
  try {
74170
- await fs52.mkdir(path70.dirname(trajectoryPath), { recursive: true });
74243
+ await fs52.mkdir(path74.dirname(trajectoryPath), { recursive: true });
74171
74244
  const line = `${JSON.stringify(entry)}
74172
74245
  `;
74173
74246
  await fs52.appendFile(trajectoryPath, line, "utf-8");
@@ -74718,16 +74791,16 @@ init_telemetry();
74718
74791
 
74719
74792
  // src/prm/replay.ts
74720
74793
  import { promises as fs53 } from "node:fs";
74721
- import path71 from "node:path";
74794
+ import path75 from "node:path";
74722
74795
  function isPathSafe2(targetPath, basePath) {
74723
- const resolvedTarget = path71.resolve(targetPath);
74724
- const resolvedBase = path71.resolve(basePath);
74725
- const rel = path71.relative(resolvedBase, resolvedTarget);
74726
- return !rel.startsWith("..") && !path71.isAbsolute(rel);
74796
+ const resolvedTarget = path75.resolve(targetPath);
74797
+ const resolvedBase = path75.resolve(basePath);
74798
+ const rel = path75.relative(resolvedBase, resolvedTarget);
74799
+ return !rel.startsWith("..") && !path75.isAbsolute(rel);
74727
74800
  }
74728
74801
  function isWithinReplaysDir(targetPath) {
74729
- const resolved = path71.resolve(targetPath);
74730
- const parts2 = resolved.split(path71.sep);
74802
+ const resolved = path75.resolve(targetPath);
74803
+ const parts2 = resolved.split(path75.sep);
74731
74804
  for (let i2 = 0;i2 < parts2.length - 1; i2++) {
74732
74805
  if (parts2[i2] === ".swarm" && parts2[i2 + 1] === "replays") {
74733
74806
  return true;
@@ -74740,10 +74813,10 @@ function sanitizeFilename(input) {
74740
74813
  }
74741
74814
  async function startReplayRecording(sessionID, directory) {
74742
74815
  try {
74743
- const replayDir = path71.join(directory, ".swarm", "replays");
74816
+ const replayDir = path75.join(directory, ".swarm", "replays");
74744
74817
  const safeSessionID = sanitizeFilename(sessionID);
74745
74818
  const filename = `${safeSessionID}-${Date.now()}.jsonl`;
74746
- const filepath = path71.join(replayDir, filename);
74819
+ const filepath = path75.join(replayDir, filename);
74747
74820
  if (!isPathSafe2(filepath, replayDir)) {
74748
74821
  console.warn(`[replay] Invalid path detected - path traversal attempt blocked for session ${sessionID}`);
74749
74822
  return null;
@@ -75117,7 +75190,7 @@ init_telemetry();
75117
75190
  init_dist();
75118
75191
  init_create_tool();
75119
75192
  import * as fs54 from "node:fs";
75120
- import * as path72 from "node:path";
75193
+ import * as path76 from "node:path";
75121
75194
  init_path_security();
75122
75195
  var WINDOWS_RESERVED_NAMES2 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
75123
75196
  function containsWindowsAttacks2(str) {
@@ -75134,14 +75207,14 @@ function containsWindowsAttacks2(str) {
75134
75207
  }
75135
75208
  function isPathInWorkspace2(filePath, workspace) {
75136
75209
  try {
75137
- const resolvedPath = path72.resolve(workspace, filePath);
75210
+ const resolvedPath = path76.resolve(workspace, filePath);
75138
75211
  if (!fs54.existsSync(resolvedPath)) {
75139
75212
  return true;
75140
75213
  }
75141
75214
  const realWorkspace = fs54.realpathSync(workspace);
75142
75215
  const realResolvedPath = fs54.realpathSync(resolvedPath);
75143
- const relativePath = path72.relative(realWorkspace, realResolvedPath);
75144
- if (relativePath.startsWith("..") || path72.isAbsolute(relativePath)) {
75216
+ const relativePath = path76.relative(realWorkspace, realResolvedPath);
75217
+ if (relativePath.startsWith("..") || path76.isAbsolute(relativePath)) {
75145
75218
  return false;
75146
75219
  }
75147
75220
  return true;
@@ -75150,7 +75223,7 @@ function isPathInWorkspace2(filePath, workspace) {
75150
75223
  }
75151
75224
  }
75152
75225
  function processFile2(file3, cwd, exportedOnly) {
75153
- const ext = path72.extname(file3);
75226
+ const ext = path76.extname(file3);
75154
75227
  if (containsControlChars(file3)) {
75155
75228
  return {
75156
75229
  file: file3,
@@ -75183,7 +75256,7 @@ function processFile2(file3, cwd, exportedOnly) {
75183
75256
  errorType: "path-outside-workspace"
75184
75257
  };
75185
75258
  }
75186
- const fullPath = path72.join(cwd, file3);
75259
+ const fullPath = path76.join(cwd, file3);
75187
75260
  if (!fs54.existsSync(fullPath)) {
75188
75261
  return {
75189
75262
  file: file3,
@@ -75475,15 +75548,15 @@ init_task_id();
75475
75548
  init_create_tool();
75476
75549
  init_resolve_working_directory();
75477
75550
  import * as fs55 from "node:fs";
75478
- import * as path73 from "node:path";
75551
+ import * as path77 from "node:path";
75479
75552
  var EVIDENCE_DIR = ".swarm/evidence";
75480
75553
  function isValidTaskId3(taskId) {
75481
75554
  return isStrictTaskId(taskId);
75482
75555
  }
75483
75556
  function isPathWithinSwarm(filePath, workspaceRoot) {
75484
- const normalizedWorkspace = path73.resolve(workspaceRoot);
75485
- const swarmPath = path73.join(normalizedWorkspace, ".swarm", "evidence");
75486
- const normalizedPath = path73.resolve(filePath);
75557
+ const normalizedWorkspace = path77.resolve(workspaceRoot);
75558
+ const swarmPath = path77.join(normalizedWorkspace, ".swarm", "evidence");
75559
+ const normalizedPath = path77.resolve(filePath);
75487
75560
  return normalizedPath.startsWith(swarmPath);
75488
75561
  }
75489
75562
  function readEvidenceFile(evidencePath) {
@@ -75564,7 +75637,7 @@ var check_gate_status = createSwarmTool({
75564
75637
  };
75565
75638
  return JSON.stringify(errorResult, null, 2);
75566
75639
  }
75567
- const evidencePath = path73.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
75640
+ const evidencePath = path77.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
75568
75641
  if (!isPathWithinSwarm(evidencePath, directory)) {
75569
75642
  const errorResult = {
75570
75643
  taskId: taskIdInput,
@@ -75661,7 +75734,7 @@ init_state();
75661
75734
  init_create_tool();
75662
75735
  init_resolve_working_directory();
75663
75736
  import * as fs56 from "node:fs";
75664
- import * as path74 from "node:path";
75737
+ import * as path78 from "node:path";
75665
75738
  function extractMatches(regex, text) {
75666
75739
  return Array.from(text.matchAll(regex));
75667
75740
  }
@@ -75813,10 +75886,10 @@ async function executeCompletionVerify(args2, directory) {
75813
75886
  let hasFileReadFailure = false;
75814
75887
  for (const filePath of fileTargets) {
75815
75888
  const normalizedPath = filePath.replace(/\\/g, "/");
75816
- const resolvedPath = path74.resolve(directory, normalizedPath);
75817
- const projectRoot = path74.resolve(directory);
75818
- const relative16 = path74.relative(projectRoot, resolvedPath);
75819
- const withinProject = relative16 === "" || !relative16.startsWith("..") && !path74.isAbsolute(relative16);
75889
+ const resolvedPath = path78.resolve(directory, normalizedPath);
75890
+ const projectRoot = path78.resolve(directory);
75891
+ const relative16 = path78.relative(projectRoot, resolvedPath);
75892
+ const withinProject = relative16 === "" || !relative16.startsWith("..") && !path78.isAbsolute(relative16);
75820
75893
  if (!withinProject) {
75821
75894
  blockedTasks.push({
75822
75895
  task_id: task.id,
@@ -75871,8 +75944,8 @@ async function executeCompletionVerify(args2, directory) {
75871
75944
  blockedTasks
75872
75945
  };
75873
75946
  try {
75874
- const evidenceDir = path74.join(directory, ".swarm", "evidence", `${phase}`);
75875
- const evidencePath = path74.join(evidenceDir, "completion-verify.json");
75947
+ const evidenceDir = path78.join(directory, ".swarm", "evidence", `${phase}`);
75948
+ const evidencePath = path78.join(evidenceDir, "completion-verify.json");
75876
75949
  fs56.mkdirSync(evidenceDir, { recursive: true });
75877
75950
  const evidenceBundle = {
75878
75951
  schema_version: "1.0.0",
@@ -75949,11 +76022,11 @@ var completion_verify = createSwarmTool({
75949
76022
  // src/tools/complexity-hotspots.ts
75950
76023
  init_zod();
75951
76024
  import * as fs58 from "node:fs";
75952
- import * as path76 from "node:path";
76025
+ import * as path80 from "node:path";
75953
76026
 
75954
76027
  // src/quality/metrics.ts
75955
76028
  import * as fs57 from "node:fs";
75956
- import * as path75 from "node:path";
76029
+ import * as path79 from "node:path";
75957
76030
  var MAX_FILE_SIZE_BYTES4 = 256 * 1024;
75958
76031
  var MIN_DUPLICATION_LINES = 10;
75959
76032
  function estimateCyclomaticComplexity(content) {
@@ -75991,8 +76064,8 @@ function estimateCyclomaticComplexity(content) {
75991
76064
  }
75992
76065
  function getComplexityForFile(filePath) {
75993
76066
  try {
75994
- const stat6 = fs57.statSync(filePath);
75995
- if (stat6.size > MAX_FILE_SIZE_BYTES4) {
76067
+ const stat7 = fs57.statSync(filePath);
76068
+ if (stat7.size > MAX_FILE_SIZE_BYTES4) {
75996
76069
  return null;
75997
76070
  }
75998
76071
  const content = fs57.readFileSync(filePath, "utf-8");
@@ -76005,7 +76078,7 @@ async function computeComplexityDelta(files, workingDir) {
76005
76078
  let totalComplexity = 0;
76006
76079
  const analyzedFiles = [];
76007
76080
  for (const file3 of files) {
76008
- const fullPath = path75.isAbsolute(file3) ? file3 : path75.join(workingDir, file3);
76081
+ const fullPath = path79.isAbsolute(file3) ? file3 : path79.join(workingDir, file3);
76009
76082
  if (!fs57.existsSync(fullPath)) {
76010
76083
  continue;
76011
76084
  }
@@ -76128,7 +76201,7 @@ function countGoExports(content) {
76128
76201
  function getExportCountForFile(filePath) {
76129
76202
  try {
76130
76203
  const content = fs57.readFileSync(filePath, "utf-8");
76131
- const ext = path75.extname(filePath).toLowerCase();
76204
+ const ext = path79.extname(filePath).toLowerCase();
76132
76205
  switch (ext) {
76133
76206
  case ".ts":
76134
76207
  case ".tsx":
@@ -76154,7 +76227,7 @@ async function computePublicApiDelta(files, workingDir) {
76154
76227
  let totalExports = 0;
76155
76228
  const analyzedFiles = [];
76156
76229
  for (const file3 of files) {
76157
- const fullPath = path75.isAbsolute(file3) ? file3 : path75.join(workingDir, file3);
76230
+ const fullPath = path79.isAbsolute(file3) ? file3 : path79.join(workingDir, file3);
76158
76231
  if (!fs57.existsSync(fullPath)) {
76159
76232
  continue;
76160
76233
  }
@@ -76188,13 +76261,13 @@ async function computeDuplicationRatio(files, workingDir) {
76188
76261
  let duplicateLines = 0;
76189
76262
  const analyzedFiles = [];
76190
76263
  for (const file3 of files) {
76191
- const fullPath = path75.isAbsolute(file3) ? file3 : path75.join(workingDir, file3);
76264
+ const fullPath = path79.isAbsolute(file3) ? file3 : path79.join(workingDir, file3);
76192
76265
  if (!fs57.existsSync(fullPath)) {
76193
76266
  continue;
76194
76267
  }
76195
76268
  try {
76196
- const stat6 = fs57.statSync(fullPath);
76197
- if (stat6.size > MAX_FILE_SIZE_BYTES4) {
76269
+ const stat7 = fs57.statSync(fullPath);
76270
+ if (stat7.size > MAX_FILE_SIZE_BYTES4) {
76198
76271
  continue;
76199
76272
  }
76200
76273
  const content = fs57.readFileSync(fullPath, "utf-8");
@@ -76221,8 +76294,8 @@ function countCodeLines(content) {
76221
76294
  return lines.length;
76222
76295
  }
76223
76296
  function isTestFile(filePath) {
76224
- const basename11 = path75.basename(filePath);
76225
- const _ext = path75.extname(filePath).toLowerCase();
76297
+ const basename11 = path79.basename(filePath);
76298
+ const _ext = path79.extname(filePath).toLowerCase();
76226
76299
  const testPatterns = [
76227
76300
  ".test.",
76228
76301
  ".spec.",
@@ -76303,8 +76376,8 @@ function matchGlobSegment(globSegments, pathSegments) {
76303
76376
  }
76304
76377
  return gIndex === globSegments.length && pIndex === pathSegments.length;
76305
76378
  }
76306
- function matchesGlobSegment(path76, glob) {
76307
- const normalizedPath = path76.replace(/\\/g, "/");
76379
+ function matchesGlobSegment(path80, glob) {
76380
+ const normalizedPath = path80.replace(/\\/g, "/");
76308
76381
  const normalizedGlob = glob.replace(/\\/g, "/");
76309
76382
  if (normalizedPath.includes("//")) {
76310
76383
  return false;
@@ -76335,8 +76408,8 @@ function simpleGlobToRegex2(glob) {
76335
76408
  function hasGlobstar(glob) {
76336
76409
  return glob.includes("**");
76337
76410
  }
76338
- function globMatches(path76, glob) {
76339
- const normalizedPath = path76.replace(/\\/g, "/");
76411
+ function globMatches(path80, glob) {
76412
+ const normalizedPath = path80.replace(/\\/g, "/");
76340
76413
  if (!glob || glob === "") {
76341
76414
  if (normalizedPath.includes("//")) {
76342
76415
  return false;
@@ -76372,7 +76445,7 @@ function shouldExcludeFile(filePath, excludeGlobs) {
76372
76445
  async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
76373
76446
  let testLines = 0;
76374
76447
  let codeLines = 0;
76375
- const srcDir = path75.join(workingDir, "src");
76448
+ const srcDir = path79.join(workingDir, "src");
76376
76449
  if (fs57.existsSync(srcDir)) {
76377
76450
  await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
76378
76451
  codeLines += lines;
@@ -76380,14 +76453,14 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
76380
76453
  }
76381
76454
  const possibleSrcDirs = ["lib", "app", "source", "core"];
76382
76455
  for (const dir of possibleSrcDirs) {
76383
- const dirPath = path75.join(workingDir, dir);
76456
+ const dirPath = path79.join(workingDir, dir);
76384
76457
  if (fs57.existsSync(dirPath)) {
76385
76458
  await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
76386
76459
  codeLines += lines;
76387
76460
  });
76388
76461
  }
76389
76462
  }
76390
- const testsDir = path75.join(workingDir, "tests");
76463
+ const testsDir = path79.join(workingDir, "tests");
76391
76464
  if (fs57.existsSync(testsDir)) {
76392
76465
  await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
76393
76466
  testLines += lines;
@@ -76395,7 +76468,7 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
76395
76468
  }
76396
76469
  const possibleTestDirs = ["test", "__tests__", "specs"];
76397
76470
  for (const dir of possibleTestDirs) {
76398
- const dirPath = path75.join(workingDir, dir);
76471
+ const dirPath = path79.join(workingDir, dir);
76399
76472
  if (fs57.existsSync(dirPath) && dirPath !== testsDir) {
76400
76473
  await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
76401
76474
  testLines += lines;
@@ -76410,7 +76483,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
76410
76483
  try {
76411
76484
  const entries = fs57.readdirSync(dirPath, { withFileTypes: true });
76412
76485
  for (const entry of entries) {
76413
- const fullPath = path75.join(dirPath, entry.name);
76486
+ const fullPath = path79.join(dirPath, entry.name);
76414
76487
  if (entry.isDirectory()) {
76415
76488
  if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
76416
76489
  continue;
@@ -76418,7 +76491,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
76418
76491
  await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
76419
76492
  } else if (entry.isFile()) {
76420
76493
  const relativePath = fullPath.replace(`${dirPath}/`, "");
76421
- const ext = path75.extname(entry.name).toLowerCase();
76494
+ const ext = path79.extname(entry.name).toLowerCase();
76422
76495
  const validExts = [
76423
76496
  ".ts",
76424
76497
  ".tsx",
@@ -76654,8 +76727,8 @@ async function getGitChurn(days, directory) {
76654
76727
  }
76655
76728
  function getComplexityForFile2(filePath) {
76656
76729
  try {
76657
- const stat6 = fs58.statSync(filePath);
76658
- if (stat6.size > MAX_FILE_SIZE_BYTES5) {
76730
+ const stat7 = fs58.statSync(filePath);
76731
+ if (stat7.size > MAX_FILE_SIZE_BYTES5) {
76659
76732
  return null;
76660
76733
  }
76661
76734
  const content = fs58.readFileSync(filePath, "utf-8");
@@ -76669,7 +76742,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
76669
76742
  const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
76670
76743
  const filteredChurn = new Map;
76671
76744
  for (const [file3, count] of churnMap) {
76672
- const ext = path76.extname(file3).toLowerCase();
76745
+ const ext = path80.extname(file3).toLowerCase();
76673
76746
  if (extSet.has(ext)) {
76674
76747
  filteredChurn.set(file3, count);
76675
76748
  }
@@ -76680,7 +76753,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
76680
76753
  for (const [file3, churnCount] of filteredChurn) {
76681
76754
  let fullPath = file3;
76682
76755
  if (!fs58.existsSync(fullPath)) {
76683
- fullPath = path76.join(cwd, file3);
76756
+ fullPath = path80.join(cwd, file3);
76684
76757
  }
76685
76758
  const complexity = getComplexityForFile2(fullPath);
76686
76759
  if (complexity !== null) {
@@ -76849,7 +76922,7 @@ ${body2}`);
76849
76922
  // src/council/council-evidence-writer.ts
76850
76923
  import {
76851
76924
  appendFileSync as appendFileSync6,
76852
- existsSync as existsSync38,
76925
+ existsSync as existsSync40,
76853
76926
  mkdirSync as mkdirSync19,
76854
76927
  readFileSync as readFileSync36,
76855
76928
  writeFileSync as writeFileSync12
@@ -76892,7 +76965,7 @@ function writeCouncilEvidence(workingDir, synthesis) {
76892
76965
  mkdirSync19(dir, { recursive: true });
76893
76966
  const filePath = join69(dir, `${synthesis.taskId}.json`);
76894
76967
  const existingRoot = Object.create(null);
76895
- if (existsSync38(filePath)) {
76968
+ if (existsSync40(filePath)) {
76896
76969
  try {
76897
76970
  const parsed = JSON.parse(readFileSync36(filePath, "utf-8"));
76898
76971
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
@@ -76941,7 +77014,7 @@ function writeCouncilEvidence(workingDir, synthesis) {
76941
77014
 
76942
77015
  // src/council/council-service.ts
76943
77016
  import fs59 from "node:fs";
76944
- import path77 from "node:path";
77017
+ import path81 from "node:path";
76945
77018
 
76946
77019
  // src/council/types.ts
76947
77020
  var COUNCIL_DEFAULTS = {
@@ -77101,9 +77174,9 @@ function synthesizePhaseCouncilAdvisory(phaseNumber, phaseSummary, verdicts, rou
77101
77174
  const unifiedFeedbackMd = buildPhaseCouncilFeedback(phaseNumber, phaseSummary, overallVerdict, rejectingMembers, requiredFixes, advisoryFindings, unresolvedConflicts, roundNumber, cfg.maxRounds);
77102
77175
  const evidencePath = `.swarm/evidence/${phaseNumber}/phase-council.json`;
77103
77176
  const baseDir = workingDir ?? process.cwd();
77104
- const evidenceDir = path77.join(baseDir, ".swarm", "evidence", String(phaseNumber));
77177
+ const evidenceDir = path81.join(baseDir, ".swarm", "evidence", String(phaseNumber));
77105
77178
  fs59.mkdirSync(evidenceDir, { recursive: true });
77106
- const evidenceFile = path77.join(evidenceDir, "phase-council.json");
77179
+ const evidenceFile = path81.join(evidenceDir, "phase-council.json");
77107
77180
  const evidenceBundle = {
77108
77181
  entries: [
77109
77182
  {
@@ -77206,7 +77279,7 @@ function buildPhaseCouncilFeedback(phaseNumber, phaseSummary, verdict, vetoedBy,
77206
77279
  }
77207
77280
 
77208
77281
  // src/council/criteria-store.ts
77209
- import { existsSync as existsSync39, mkdirSync as mkdirSync20, readFileSync as readFileSync37, writeFileSync as writeFileSync13 } from "node:fs";
77282
+ import { existsSync as existsSync41, mkdirSync as mkdirSync20, readFileSync as readFileSync37, writeFileSync as writeFileSync13 } from "node:fs";
77210
77283
  import { join as join70 } from "node:path";
77211
77284
  var COUNCIL_DIR = ".swarm/council";
77212
77285
  function writeCriteria(workingDir, taskId, criteria) {
@@ -77221,7 +77294,7 @@ function writeCriteria(workingDir, taskId, criteria) {
77221
77294
  }
77222
77295
  function readCriteria(workingDir, taskId) {
77223
77296
  const filePath = join70(workingDir, COUNCIL_DIR, `${safeId(taskId)}.json`);
77224
- if (!existsSync39(filePath))
77297
+ if (!existsSync41(filePath))
77225
77298
  return null;
77226
77299
  try {
77227
77300
  const parsed = JSON.parse(readFileSync37(filePath, "utf-8"));
@@ -77373,7 +77446,7 @@ var submit_council_verdicts = createSwarmTool({
77373
77446
  init_zod();
77374
77447
  init_loader();
77375
77448
  import * as fs60 from "node:fs";
77376
- import * as path78 from "node:path";
77449
+ import * as path82 from "node:path";
77377
77450
 
77378
77451
  // src/council/general-council-advisory.ts
77379
77452
  var ADVISORY_HEADER = "[general_council] (advisory; not blocking)";
@@ -77801,10 +77874,10 @@ var convene_general_council = createSwarmTool({
77801
77874
  const round1 = input.round1Responses;
77802
77875
  const round2 = input.round2Responses ?? [];
77803
77876
  const result = synthesizeGeneralCouncil(input.question, input.mode, round1, round2);
77804
- const evidenceDir = path78.join(workingDir, ".swarm", "council", "general");
77877
+ const evidenceDir = path82.join(workingDir, ".swarm", "council", "general");
77805
77878
  const safeTimestamp = result.timestamp.replace(/[:.]/g, "-");
77806
77879
  const evidenceFile = `${safeTimestamp}-${input.mode}.json`;
77807
- const evidencePath = path78.join(evidenceDir, evidenceFile);
77880
+ const evidencePath = path82.join(evidenceDir, evidenceFile);
77808
77881
  try {
77809
77882
  await fs60.promises.mkdir(evidenceDir, { recursive: true });
77810
77883
  await fs60.promises.writeFile(evidencePath, JSON.stringify(result, null, 2));
@@ -78039,7 +78112,7 @@ init_state();
78039
78112
  init_task_id();
78040
78113
  init_create_tool();
78041
78114
  import * as fs61 from "node:fs";
78042
- import * as path79 from "node:path";
78115
+ import * as path83 from "node:path";
78043
78116
  function validateTaskIdFormat2(taskId) {
78044
78117
  return validateTaskIdFormat(taskId);
78045
78118
  }
@@ -78113,8 +78186,8 @@ async function executeDeclareScope(args2, fallbackDir) {
78113
78186
  };
78114
78187
  }
78115
78188
  }
78116
- normalizedDir = path79.normalize(args2.working_directory);
78117
- const pathParts = normalizedDir.split(path79.sep);
78189
+ normalizedDir = path83.normalize(args2.working_directory);
78190
+ const pathParts = normalizedDir.split(path83.sep);
78118
78191
  if (pathParts.includes("..")) {
78119
78192
  return {
78120
78193
  success: false,
@@ -78124,10 +78197,10 @@ async function executeDeclareScope(args2, fallbackDir) {
78124
78197
  ]
78125
78198
  };
78126
78199
  }
78127
- const resolvedDir = path79.resolve(normalizedDir);
78200
+ const resolvedDir = path83.resolve(normalizedDir);
78128
78201
  try {
78129
78202
  const realPath = fs61.realpathSync(resolvedDir);
78130
- const planPath2 = path79.join(realPath, ".swarm", "plan.json");
78203
+ const planPath2 = path83.join(realPath, ".swarm", "plan.json");
78131
78204
  if (!fs61.existsSync(planPath2)) {
78132
78205
  return {
78133
78206
  success: false,
@@ -78151,7 +78224,7 @@ async function executeDeclareScope(args2, fallbackDir) {
78151
78224
  console.warn("[declare-scope] fallbackDir is undefined, falling back to process.cwd()");
78152
78225
  }
78153
78226
  const directory = normalizedDir || fallbackDir;
78154
- const planPath = path79.resolve(directory, ".swarm", "plan.json");
78227
+ const planPath = path83.resolve(directory, ".swarm", "plan.json");
78155
78228
  if (!fs61.existsSync(planPath)) {
78156
78229
  return {
78157
78230
  success: false,
@@ -78191,8 +78264,8 @@ async function executeDeclareScope(args2, fallbackDir) {
78191
78264
  const normalizeErrors = [];
78192
78265
  const dir = normalizedDir || fallbackDir || process.cwd();
78193
78266
  const mergedFiles = rawMergedFiles.map((file3) => {
78194
- if (path79.isAbsolute(file3)) {
78195
- const relativePath = path79.relative(dir, file3).replace(/\\/g, "/");
78267
+ if (path83.isAbsolute(file3)) {
78268
+ const relativePath = path83.relative(dir, file3).replace(/\\/g, "/");
78196
78269
  if (relativePath.startsWith("..")) {
78197
78270
  normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
78198
78271
  return file3;
@@ -78253,7 +78326,7 @@ var declare_scope = createSwarmTool({
78253
78326
  init_zod();
78254
78327
  import * as child_process7 from "node:child_process";
78255
78328
  import * as fs62 from "node:fs";
78256
- import * as path80 from "node:path";
78329
+ import * as path84 from "node:path";
78257
78330
  init_create_tool();
78258
78331
  var MAX_DIFF_LINES = 500;
78259
78332
  var DIFF_TIMEOUT_MS = 30000;
@@ -78282,20 +78355,20 @@ function validateBase(base) {
78282
78355
  function validatePaths(paths) {
78283
78356
  if (!paths)
78284
78357
  return null;
78285
- for (const path81 of paths) {
78286
- if (!path81 || path81.length === 0) {
78358
+ for (const path85 of paths) {
78359
+ if (!path85 || path85.length === 0) {
78287
78360
  return "empty path not allowed";
78288
78361
  }
78289
- if (path81.length > MAX_PATH_LENGTH) {
78362
+ if (path85.length > MAX_PATH_LENGTH) {
78290
78363
  return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
78291
78364
  }
78292
- if (SHELL_METACHARACTERS2.test(path81)) {
78365
+ if (SHELL_METACHARACTERS2.test(path85)) {
78293
78366
  return "path contains shell metacharacters";
78294
78367
  }
78295
- if (path81.startsWith("-")) {
78368
+ if (path85.startsWith("-")) {
78296
78369
  return 'path cannot start with "-" (option-like arguments not allowed)';
78297
78370
  }
78298
- if (CONTROL_CHAR_PATTERN2.test(path81)) {
78371
+ if (CONTROL_CHAR_PATTERN2.test(path85)) {
78299
78372
  return "path contains control characters";
78300
78373
  }
78301
78374
  }
@@ -78401,8 +78474,8 @@ var diff = createSwarmTool({
78401
78474
  if (parts2.length >= 3) {
78402
78475
  const additions = parseInt(parts2[0], 10) || 0;
78403
78476
  const deletions = parseInt(parts2[1], 10) || 0;
78404
- const path81 = parts2[2];
78405
- files.push({ path: path81, additions, deletions });
78477
+ const path85 = parts2[2];
78478
+ files.push({ path: path85, additions, deletions });
78406
78479
  }
78407
78480
  }
78408
78481
  const contractChanges = [];
@@ -78442,7 +78515,7 @@ var diff = createSwarmTool({
78442
78515
  } else if (base === "unstaged") {
78443
78516
  const oldRef = `:${file3.path}`;
78444
78517
  oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
78445
- newContent = fs62.readFileSync(path80.join(directory, file3.path), "utf-8");
78518
+ newContent = fs62.readFileSync(path84.join(directory, file3.path), "utf-8");
78446
78519
  } else {
78447
78520
  const oldRef = `${base}:${file3.path}`;
78448
78521
  oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
@@ -78517,7 +78590,7 @@ var diff = createSwarmTool({
78517
78590
  init_zod();
78518
78591
  import * as child_process8 from "node:child_process";
78519
78592
  import * as fs63 from "node:fs";
78520
- import * as path81 from "node:path";
78593
+ import * as path85 from "node:path";
78521
78594
  init_create_tool();
78522
78595
  var diff_summary = createSwarmTool({
78523
78596
  description: "Generate a filtered semantic diff summary from AST analysis. Returns SemanticDiffSummary with optional filtering by classification or riskLevel.",
@@ -78565,7 +78638,7 @@ var diff_summary = createSwarmTool({
78565
78638
  }
78566
78639
  try {
78567
78640
  let oldContent;
78568
- const newContent = fs63.readFileSync(path81.join(workingDir, filePath), "utf-8");
78641
+ const newContent = fs63.readFileSync(path85.join(workingDir, filePath), "utf-8");
78569
78642
  if (fileExistsInHead) {
78570
78643
  oldContent = child_process8.execFileSync("git", ["show", `HEAD:${filePath}`], {
78571
78644
  encoding: "utf-8",
@@ -78794,7 +78867,7 @@ init_zod();
78794
78867
  init_create_tool();
78795
78868
  init_path_security();
78796
78869
  import * as fs64 from "node:fs";
78797
- import * as path82 from "node:path";
78870
+ import * as path86 from "node:path";
78798
78871
  var MAX_FILE_SIZE_BYTES6 = 1024 * 1024;
78799
78872
  var MAX_EVIDENCE_FILES = 1000;
78800
78873
  var EVIDENCE_DIR3 = ".swarm/evidence";
@@ -78821,9 +78894,9 @@ function validateRequiredTypes(input) {
78821
78894
  return null;
78822
78895
  }
78823
78896
  function isPathWithinSwarm2(filePath, cwd) {
78824
- const normalizedCwd = path82.resolve(cwd);
78825
- const swarmPath = path82.join(normalizedCwd, ".swarm");
78826
- const normalizedPath = path82.resolve(filePath);
78897
+ const normalizedCwd = path86.resolve(cwd);
78898
+ const swarmPath = path86.join(normalizedCwd, ".swarm");
78899
+ const normalizedPath = path86.resolve(filePath);
78827
78900
  return normalizedPath.startsWith(swarmPath);
78828
78901
  }
78829
78902
  function parseCompletedTasks(planContent) {
@@ -78853,15 +78926,15 @@ function readEvidenceFiles(evidenceDir, _cwd) {
78853
78926
  if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
78854
78927
  continue;
78855
78928
  }
78856
- const filePath = path82.join(evidenceDir, filename);
78929
+ const filePath = path86.join(evidenceDir, filename);
78857
78930
  try {
78858
- const resolvedPath = path82.resolve(filePath);
78859
- const evidenceDirResolved = path82.resolve(evidenceDir);
78931
+ const resolvedPath = path86.resolve(filePath);
78932
+ const evidenceDirResolved = path86.resolve(evidenceDir);
78860
78933
  if (!resolvedPath.startsWith(evidenceDirResolved)) {
78861
78934
  continue;
78862
78935
  }
78863
- const stat6 = fs64.lstatSync(filePath);
78864
- if (!stat6.isFile()) {
78936
+ const stat7 = fs64.lstatSync(filePath);
78937
+ if (!stat7.isFile()) {
78865
78938
  continue;
78866
78939
  }
78867
78940
  } catch {
@@ -78974,7 +79047,7 @@ var evidence_check = createSwarmTool({
78974
79047
  return JSON.stringify(errorResult, null, 2);
78975
79048
  }
78976
79049
  const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
78977
- const planPath = path82.join(cwd, PLAN_FILE);
79050
+ const planPath = path86.join(cwd, PLAN_FILE);
78978
79051
  if (!isPathWithinSwarm2(planPath, cwd)) {
78979
79052
  const errorResult = {
78980
79053
  error: "plan file path validation failed",
@@ -79006,7 +79079,7 @@ var evidence_check = createSwarmTool({
79006
79079
  };
79007
79080
  return JSON.stringify(result2, null, 2);
79008
79081
  }
79009
- const evidenceDir = path82.join(cwd, EVIDENCE_DIR3);
79082
+ const evidenceDir = path86.join(cwd, EVIDENCE_DIR3);
79010
79083
  const evidence = readEvidenceFiles(evidenceDir, cwd);
79011
79084
  const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
79012
79085
  const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
@@ -79024,7 +79097,7 @@ var evidence_check = createSwarmTool({
79024
79097
  init_zod();
79025
79098
  init_create_tool();
79026
79099
  import * as fs65 from "node:fs";
79027
- import * as path83 from "node:path";
79100
+ import * as path87 from "node:path";
79028
79101
  var EXT_MAP = {
79029
79102
  python: ".py",
79030
79103
  py: ".py",
@@ -79105,12 +79178,12 @@ var extract_code_blocks = createSwarmTool({
79105
79178
  if (prefix) {
79106
79179
  filename = `${prefix}_${filename}`;
79107
79180
  }
79108
- let filepath = path83.join(targetDir, filename);
79109
- const base = path83.basename(filepath, path83.extname(filepath));
79110
- const ext = path83.extname(filepath);
79181
+ let filepath = path87.join(targetDir, filename);
79182
+ const base = path87.basename(filepath, path87.extname(filepath));
79183
+ const ext = path87.extname(filepath);
79111
79184
  let counter = 1;
79112
79185
  while (fs65.existsSync(filepath)) {
79113
- filepath = path83.join(targetDir, `${base}_${counter}${ext}`);
79186
+ filepath = path87.join(targetDir, `${base}_${counter}${ext}`);
79114
79187
  counter++;
79115
79188
  }
79116
79189
  try {
@@ -79286,7 +79359,7 @@ init_create_tool();
79286
79359
  var GITINGEST_TIMEOUT_MS = 1e4;
79287
79360
  var GITINGEST_MAX_RESPONSE_BYTES = 5242880;
79288
79361
  var GITINGEST_MAX_RETRIES = 2;
79289
- var delay = (ms) => new Promise((resolve30) => setTimeout(resolve30, ms));
79362
+ var delay = (ms) => new Promise((resolve31) => setTimeout(resolve31, ms));
79290
79363
  async function fetchGitingest(args2) {
79291
79364
  for (let attempt = 0;attempt <= GITINGEST_MAX_RETRIES; attempt++) {
79292
79365
  try {
@@ -79374,7 +79447,7 @@ init_zod();
79374
79447
  init_create_tool();
79375
79448
  init_path_security();
79376
79449
  import * as fs66 from "node:fs";
79377
- import * as path84 from "node:path";
79450
+ import * as path88 from "node:path";
79378
79451
  var MAX_FILE_PATH_LENGTH2 = 500;
79379
79452
  var MAX_SYMBOL_LENGTH = 256;
79380
79453
  var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
@@ -79422,7 +79495,7 @@ function validateSymbolInput(symbol3) {
79422
79495
  return null;
79423
79496
  }
79424
79497
  function isBinaryFile2(filePath, buffer) {
79425
- const ext = path84.extname(filePath).toLowerCase();
79498
+ const ext = path88.extname(filePath).toLowerCase();
79426
79499
  if (ext === ".json" || ext === ".md" || ext === ".txt") {
79427
79500
  return false;
79428
79501
  }
@@ -79446,15 +79519,15 @@ function parseImports(content, targetFile, targetSymbol) {
79446
79519
  const imports = [];
79447
79520
  let _resolvedTarget;
79448
79521
  try {
79449
- _resolvedTarget = path84.resolve(targetFile);
79522
+ _resolvedTarget = path88.resolve(targetFile);
79450
79523
  } catch {
79451
79524
  _resolvedTarget = targetFile;
79452
79525
  }
79453
- const targetBasename = path84.basename(targetFile, path84.extname(targetFile));
79526
+ const targetBasename = path88.basename(targetFile, path88.extname(targetFile));
79454
79527
  const targetWithExt = targetFile;
79455
79528
  const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
79456
- const normalizedTargetWithExt = path84.normalize(targetWithExt).replace(/\\/g, "/");
79457
- const normalizedTargetWithoutExt = path84.normalize(targetWithoutExt).replace(/\\/g, "/");
79529
+ const normalizedTargetWithExt = path88.normalize(targetWithExt).replace(/\\/g, "/");
79530
+ const normalizedTargetWithoutExt = path88.normalize(targetWithoutExt).replace(/\\/g, "/");
79458
79531
  const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
79459
79532
  for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
79460
79533
  const modulePath = match[1] || match[2] || match[3];
@@ -79477,9 +79550,9 @@ function parseImports(content, targetFile, targetSymbol) {
79477
79550
  }
79478
79551
  const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
79479
79552
  let isMatch = false;
79480
- const _targetDir = path84.dirname(targetFile);
79481
- const targetExt = path84.extname(targetFile);
79482
- const targetBasenameNoExt = path84.basename(targetFile, targetExt);
79553
+ const _targetDir = path88.dirname(targetFile);
79554
+ const targetExt = path88.extname(targetFile);
79555
+ const targetBasenameNoExt = path88.basename(targetFile, targetExt);
79483
79556
  const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
79484
79557
  const moduleName = modulePath.split(/[/\\]/).pop() || "";
79485
79558
  const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
@@ -79547,13 +79620,13 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
79547
79620
  entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
79548
79621
  for (const entry of entries) {
79549
79622
  if (SKIP_DIRECTORIES4.has(entry)) {
79550
- stats.skippedDirs.push(path84.join(dir, entry));
79623
+ stats.skippedDirs.push(path88.join(dir, entry));
79551
79624
  continue;
79552
79625
  }
79553
- const fullPath = path84.join(dir, entry);
79554
- let stat6;
79626
+ const fullPath = path88.join(dir, entry);
79627
+ let stat7;
79555
79628
  try {
79556
- stat6 = fs66.statSync(fullPath);
79629
+ stat7 = fs66.statSync(fullPath);
79557
79630
  } catch (e) {
79558
79631
  stats.fileErrors.push({
79559
79632
  path: fullPath,
@@ -79561,10 +79634,10 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
79561
79634
  });
79562
79635
  continue;
79563
79636
  }
79564
- if (stat6.isDirectory()) {
79637
+ if (stat7.isDirectory()) {
79565
79638
  findSourceFiles2(fullPath, files, stats);
79566
- } else if (stat6.isFile()) {
79567
- const ext = path84.extname(fullPath).toLowerCase();
79639
+ } else if (stat7.isFile()) {
79640
+ const ext = path88.extname(fullPath).toLowerCase();
79568
79641
  if (SUPPORTED_EXTENSIONS3.includes(ext)) {
79569
79642
  files.push(fullPath);
79570
79643
  }
@@ -79621,7 +79694,7 @@ var imports = createSwarmTool({
79621
79694
  return JSON.stringify(errorResult, null, 2);
79622
79695
  }
79623
79696
  try {
79624
- const targetFile = path84.resolve(file3);
79697
+ const targetFile = path88.resolve(file3);
79625
79698
  if (!fs66.existsSync(targetFile)) {
79626
79699
  const errorResult = {
79627
79700
  error: `target file not found: ${file3}`,
@@ -79643,7 +79716,7 @@ var imports = createSwarmTool({
79643
79716
  };
79644
79717
  return JSON.stringify(errorResult, null, 2);
79645
79718
  }
79646
- const baseDir = path84.dirname(targetFile);
79719
+ const baseDir = path88.dirname(targetFile);
79647
79720
  const scanStats = {
79648
79721
  skippedDirs: [],
79649
79722
  skippedFiles: 0,
@@ -79658,8 +79731,8 @@ var imports = createSwarmTool({
79658
79731
  if (consumers.length >= MAX_CONSUMERS)
79659
79732
  break;
79660
79733
  try {
79661
- const stat6 = fs66.statSync(filePath);
79662
- if (stat6.size > MAX_FILE_SIZE_BYTES7) {
79734
+ const stat7 = fs66.statSync(filePath);
79735
+ if (stat7.size > MAX_FILE_SIZE_BYTES7) {
79663
79736
  skippedFileCount++;
79664
79737
  continue;
79665
79738
  }
@@ -79876,7 +79949,7 @@ init_zod();
79876
79949
  init_config();
79877
79950
  init_knowledge_store();
79878
79951
  init_create_tool();
79879
- import { existsSync as existsSync44 } from "node:fs";
79952
+ import { existsSync as existsSync46 } from "node:fs";
79880
79953
  var DEFAULT_LIMIT = 10;
79881
79954
  var MAX_LESSON_LENGTH = 200;
79882
79955
  var VALID_CATEGORIES3 = [
@@ -79946,14 +80019,14 @@ function validateLimit(limit) {
79946
80019
  }
79947
80020
  async function readSwarmKnowledge(directory) {
79948
80021
  const swarmPath = resolveSwarmKnowledgePath(directory);
79949
- if (!existsSync44(swarmPath)) {
80022
+ if (!existsSync46(swarmPath)) {
79950
80023
  return [];
79951
80024
  }
79952
80025
  return readKnowledge(swarmPath);
79953
80026
  }
79954
80027
  async function readHiveKnowledge() {
79955
80028
  const hivePath = resolveHiveKnowledgePath();
79956
- if (!existsSync44(hivePath)) {
80029
+ if (!existsSync46(hivePath)) {
79957
80030
  return [];
79958
80031
  }
79959
80032
  return readKnowledge(hivePath);
@@ -80189,7 +80262,7 @@ init_qa_gate_profile();
80189
80262
  init_manager2();
80190
80263
  init_curator();
80191
80264
  import * as fs68 from "node:fs";
80192
- import * as path86 from "node:path";
80265
+ import * as path90 from "node:path";
80193
80266
  init_knowledge_curator();
80194
80267
  init_knowledge_reader();
80195
80268
  init_knowledge_store();
@@ -80202,16 +80275,16 @@ init_plan_schema();
80202
80275
  init_ledger();
80203
80276
  init_manager();
80204
80277
  import * as fs67 from "node:fs";
80205
- import * as path85 from "node:path";
80278
+ import * as path89 from "node:path";
80206
80279
  async function writeCheckpoint(directory) {
80207
80280
  try {
80208
80281
  const plan = await loadPlan(directory);
80209
80282
  if (!plan)
80210
80283
  return;
80211
- const swarmDir = path85.join(directory, ".swarm");
80284
+ const swarmDir = path89.join(directory, ".swarm");
80212
80285
  fs67.mkdirSync(swarmDir, { recursive: true });
80213
- const jsonPath = path85.join(swarmDir, "SWARM_PLAN.json");
80214
- const mdPath = path85.join(swarmDir, "SWARM_PLAN.md");
80286
+ const jsonPath = path89.join(swarmDir, "SWARM_PLAN.json");
80287
+ const mdPath = path89.join(swarmDir, "SWARM_PLAN.md");
80215
80288
  fs67.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
80216
80289
  const md = derivePlanMarkdown(plan);
80217
80290
  fs67.writeFileSync(mdPath, md, "utf8");
@@ -80446,7 +80519,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
80446
80519
  let driftCheckEnabled = true;
80447
80520
  let driftHasSpecMd = false;
80448
80521
  try {
80449
- const specMdPath = path86.join(dir, ".swarm", "spec.md");
80522
+ const specMdPath = path90.join(dir, ".swarm", "spec.md");
80450
80523
  driftHasSpecMd = fs68.existsSync(specMdPath);
80451
80524
  const gatePlan = await loadPlan(dir);
80452
80525
  if (gatePlan) {
@@ -80468,7 +80541,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
80468
80541
  } else {
80469
80542
  let phaseType;
80470
80543
  try {
80471
- const planPath = path86.join(dir, ".swarm", "plan.json");
80544
+ const planPath = path90.join(dir, ".swarm", "plan.json");
80472
80545
  if (fs68.existsSync(planPath)) {
80473
80546
  const planRaw = fs68.readFileSync(planPath, "utf-8");
80474
80547
  const plan = JSON.parse(planRaw);
@@ -80481,7 +80554,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
80481
80554
  warnings.push(`Phase ${phase} is annotated as 'non-code'. Drift verification was skipped per phase type annotation.`);
80482
80555
  } else {
80483
80556
  try {
80484
- const driftEvidencePath = path86.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
80557
+ const driftEvidencePath = path90.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
80485
80558
  let driftVerdictFound = false;
80486
80559
  let driftVerdictApproved = false;
80487
80560
  try {
@@ -80519,7 +80592,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
80519
80592
  let incompleteTaskCount = 0;
80520
80593
  let planParseable = false;
80521
80594
  try {
80522
- const planPath = path86.join(dir, ".swarm", "plan.json");
80595
+ const planPath = path90.join(dir, ".swarm", "plan.json");
80523
80596
  if (fs68.existsSync(planPath)) {
80524
80597
  const planRaw = fs68.readFileSync(planPath, "utf-8");
80525
80598
  const plan = JSON.parse(planRaw);
@@ -80586,7 +80659,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
80586
80659
  const overrides = session2?.qaGateSessionOverrides ?? {};
80587
80660
  const effective = getEffectiveGates(profile, overrides);
80588
80661
  if (effective.hallucination_guard === true) {
80589
- const hgPath = path86.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
80662
+ const hgPath = path90.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
80590
80663
  let hgVerdictFound = false;
80591
80664
  let hgVerdictApproved = false;
80592
80665
  try {
@@ -80658,7 +80731,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
80658
80731
  const overrides = session2?.qaGateSessionOverrides ?? {};
80659
80732
  const effective = getEffectiveGates(profile, overrides);
80660
80733
  if (effective.mutation_test === true) {
80661
- const mgPath = path86.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
80734
+ const mgPath = path90.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
80662
80735
  let mgVerdictFound = false;
80663
80736
  let mgVerdict;
80664
80737
  try {
@@ -80732,7 +80805,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
80732
80805
  const effective = getEffectiveGates(profile, overrides);
80733
80806
  if (effective.council_mode === true) {
80734
80807
  councilModeEnabled = true;
80735
- const pcPath = path86.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
80808
+ const pcPath = path90.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
80736
80809
  let pcVerdictFound = false;
80737
80810
  let _pcVerdict;
80738
80811
  let pcQuorumSize;
@@ -80934,7 +81007,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
80934
81007
  }
80935
81008
  if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
80936
81009
  try {
80937
- const projectName = path86.basename(dir);
81010
+ const projectName = path90.basename(dir);
80938
81011
  const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
80939
81012
  if (curationResult) {
80940
81013
  const sessionState = swarmState.agentSessions.get(sessionID);
@@ -81304,7 +81377,7 @@ init_utils();
81304
81377
  init_bun_compat();
81305
81378
  init_create_tool();
81306
81379
  import * as fs69 from "node:fs";
81307
- import * as path87 from "node:path";
81380
+ import * as path91 from "node:path";
81308
81381
  var MAX_OUTPUT_BYTES5 = 52428800;
81309
81382
  var AUDIT_TIMEOUT_MS = 120000;
81310
81383
  function isValidEcosystem(value) {
@@ -81332,16 +81405,16 @@ function validateArgs3(args2) {
81332
81405
  function detectEcosystems(directory) {
81333
81406
  const ecosystems = [];
81334
81407
  const cwd = directory;
81335
- if (fs69.existsSync(path87.join(cwd, "package.json"))) {
81408
+ if (fs69.existsSync(path91.join(cwd, "package.json"))) {
81336
81409
  ecosystems.push("npm");
81337
81410
  }
81338
- if (fs69.existsSync(path87.join(cwd, "pyproject.toml")) || fs69.existsSync(path87.join(cwd, "requirements.txt"))) {
81411
+ if (fs69.existsSync(path91.join(cwd, "pyproject.toml")) || fs69.existsSync(path91.join(cwd, "requirements.txt"))) {
81339
81412
  ecosystems.push("pip");
81340
81413
  }
81341
- if (fs69.existsSync(path87.join(cwd, "Cargo.toml"))) {
81414
+ if (fs69.existsSync(path91.join(cwd, "Cargo.toml"))) {
81342
81415
  ecosystems.push("cargo");
81343
81416
  }
81344
- if (fs69.existsSync(path87.join(cwd, "go.mod"))) {
81417
+ if (fs69.existsSync(path91.join(cwd, "go.mod"))) {
81345
81418
  ecosystems.push("go");
81346
81419
  }
81347
81420
  try {
@@ -81350,13 +81423,13 @@ function detectEcosystems(directory) {
81350
81423
  ecosystems.push("dotnet");
81351
81424
  }
81352
81425
  } catch {}
81353
- if (fs69.existsSync(path87.join(cwd, "Gemfile")) || fs69.existsSync(path87.join(cwd, "Gemfile.lock"))) {
81426
+ if (fs69.existsSync(path91.join(cwd, "Gemfile")) || fs69.existsSync(path91.join(cwd, "Gemfile.lock"))) {
81354
81427
  ecosystems.push("ruby");
81355
81428
  }
81356
- if (fs69.existsSync(path87.join(cwd, "pubspec.yaml"))) {
81429
+ if (fs69.existsSync(path91.join(cwd, "pubspec.yaml"))) {
81357
81430
  ecosystems.push("dart");
81358
81431
  }
81359
- if (fs69.existsSync(path87.join(cwd, "composer.lock"))) {
81432
+ if (fs69.existsSync(path91.join(cwd, "composer.lock"))) {
81360
81433
  ecosystems.push("composer");
81361
81434
  }
81362
81435
  return ecosystems;
@@ -81369,7 +81442,7 @@ async function runNpmAudit(directory) {
81369
81442
  stderr: "pipe",
81370
81443
  cwd: directory
81371
81444
  });
81372
- const timeoutPromise = new Promise((resolve31) => setTimeout(() => resolve31("timeout"), AUDIT_TIMEOUT_MS));
81445
+ const timeoutPromise = new Promise((resolve32) => setTimeout(() => resolve32("timeout"), AUDIT_TIMEOUT_MS));
81373
81446
  const result = await Promise.race([
81374
81447
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr2]) => ({ stdout: stdout2, stderr: stderr2 })),
81375
81448
  timeoutPromise
@@ -81489,7 +81562,7 @@ async function runPipAudit(directory) {
81489
81562
  stderr: "pipe",
81490
81563
  cwd: directory
81491
81564
  });
81492
- const timeoutPromise = new Promise((resolve31) => setTimeout(() => resolve31("timeout"), AUDIT_TIMEOUT_MS));
81565
+ const timeoutPromise = new Promise((resolve32) => setTimeout(() => resolve32("timeout"), AUDIT_TIMEOUT_MS));
81493
81566
  const result = await Promise.race([
81494
81567
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr2]) => ({ stdout: stdout2, stderr: stderr2 })),
81495
81568
  timeoutPromise
@@ -81617,7 +81690,7 @@ async function runCargoAudit(directory) {
81617
81690
  stderr: "pipe",
81618
81691
  cwd: directory
81619
81692
  });
81620
- const timeoutPromise = new Promise((resolve31) => setTimeout(() => resolve31("timeout"), AUDIT_TIMEOUT_MS));
81693
+ const timeoutPromise = new Promise((resolve32) => setTimeout(() => resolve32("timeout"), AUDIT_TIMEOUT_MS));
81621
81694
  const result = await Promise.race([
81622
81695
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
81623
81696
  timeoutPromise
@@ -81741,7 +81814,7 @@ async function runGoAudit(directory) {
81741
81814
  stderr: "pipe",
81742
81815
  cwd: directory
81743
81816
  });
81744
- const timeoutPromise = new Promise((resolve31) => setTimeout(() => resolve31("timeout"), AUDIT_TIMEOUT_MS));
81817
+ const timeoutPromise = new Promise((resolve32) => setTimeout(() => resolve32("timeout"), AUDIT_TIMEOUT_MS));
81745
81818
  const result = await Promise.race([
81746
81819
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
81747
81820
  timeoutPromise
@@ -81874,7 +81947,7 @@ async function runDotnetAudit(directory) {
81874
81947
  stderr: "pipe",
81875
81948
  cwd: directory
81876
81949
  });
81877
- const timeoutPromise = new Promise((resolve31) => setTimeout(() => resolve31("timeout"), AUDIT_TIMEOUT_MS));
81950
+ const timeoutPromise = new Promise((resolve32) => setTimeout(() => resolve32("timeout"), AUDIT_TIMEOUT_MS));
81878
81951
  const result = await Promise.race([
81879
81952
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
81880
81953
  timeoutPromise
@@ -81990,7 +82063,7 @@ async function runBundleAudit(directory) {
81990
82063
  stderr: "pipe",
81991
82064
  cwd: directory
81992
82065
  });
81993
- const timeoutPromise = new Promise((resolve31) => setTimeout(() => resolve31("timeout"), AUDIT_TIMEOUT_MS));
82066
+ const timeoutPromise = new Promise((resolve32) => setTimeout(() => resolve32("timeout"), AUDIT_TIMEOUT_MS));
81994
82067
  const result = await Promise.race([
81995
82068
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
81996
82069
  timeoutPromise
@@ -82135,7 +82208,7 @@ async function runDartAudit(directory) {
82135
82208
  stderr: "pipe",
82136
82209
  cwd: directory
82137
82210
  });
82138
- const timeoutPromise = new Promise((resolve31) => setTimeout(() => resolve31("timeout"), AUDIT_TIMEOUT_MS));
82211
+ const timeoutPromise = new Promise((resolve32) => setTimeout(() => resolve32("timeout"), AUDIT_TIMEOUT_MS));
82139
82212
  const result = await Promise.race([
82140
82213
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
82141
82214
  timeoutPromise
@@ -82250,7 +82323,7 @@ async function runComposerAudit(directory) {
82250
82323
  stderr: "pipe",
82251
82324
  cwd: directory
82252
82325
  });
82253
- const timeoutPromise = new Promise((resolve31) => setTimeout(() => resolve31("timeout"), AUDIT_TIMEOUT_MS));
82326
+ const timeoutPromise = new Promise((resolve32) => setTimeout(() => resolve32("timeout"), AUDIT_TIMEOUT_MS));
82254
82327
  const result = await Promise.race([
82255
82328
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
82256
82329
  timeoutPromise
@@ -82492,7 +82565,7 @@ var pkg_audit = createSwarmTool({
82492
82565
  init_zod();
82493
82566
  init_manager2();
82494
82567
  import * as fs70 from "node:fs";
82495
- import * as path88 from "node:path";
82568
+ import * as path92 from "node:path";
82496
82569
  init_utils();
82497
82570
  init_create_tool();
82498
82571
  var MAX_FILE_SIZE = 1024 * 1024;
@@ -82615,7 +82688,7 @@ function isScaffoldFile(filePath) {
82615
82688
  if (SCAFFOLD_PATH_PATTERNS.some((pattern) => pattern.test(normalizedPath))) {
82616
82689
  return true;
82617
82690
  }
82618
- const filename = path88.basename(filePath);
82691
+ const filename = path92.basename(filePath);
82619
82692
  if (SCAFFOLD_FILENAME_PATTERNS.some((pattern) => pattern.test(filename))) {
82620
82693
  return true;
82621
82694
  }
@@ -82632,7 +82705,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
82632
82705
  if (regex.test(normalizedPath)) {
82633
82706
  return true;
82634
82707
  }
82635
- const filename = path88.basename(filePath);
82708
+ const filename = path92.basename(filePath);
82636
82709
  const filenameRegex = new RegExp(`^${regexPattern}$`, "i");
82637
82710
  if (filenameRegex.test(filename)) {
82638
82711
  return true;
@@ -82641,7 +82714,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
82641
82714
  return false;
82642
82715
  }
82643
82716
  function isParserSupported(filePath) {
82644
- const ext = path88.extname(filePath).toLowerCase();
82717
+ const ext = path92.extname(filePath).toLowerCase();
82645
82718
  return SUPPORTED_PARSER_EXTENSIONS.has(ext);
82646
82719
  }
82647
82720
  function isPlanFile(filePath) {
@@ -82888,9 +82961,9 @@ async function placeholderScan(input, directory) {
82888
82961
  let filesScanned = 0;
82889
82962
  const filesWithFindings = new Set;
82890
82963
  for (const filePath of changed_files) {
82891
- const fullPath = path88.isAbsolute(filePath) ? filePath : path88.resolve(directory, filePath);
82892
- const resolvedDirectory = path88.resolve(directory);
82893
- if (!fullPath.startsWith(resolvedDirectory + path88.sep) && fullPath !== resolvedDirectory) {
82964
+ const fullPath = path92.isAbsolute(filePath) ? filePath : path92.resolve(directory, filePath);
82965
+ const resolvedDirectory = path92.resolve(directory);
82966
+ if (!fullPath.startsWith(resolvedDirectory + path92.sep) && fullPath !== resolvedDirectory) {
82894
82967
  continue;
82895
82968
  }
82896
82969
  if (!fs70.existsSync(fullPath)) {
@@ -82899,14 +82972,14 @@ async function placeholderScan(input, directory) {
82899
82972
  if (isAllowedByGlobs(filePath, allow_globs)) {
82900
82973
  continue;
82901
82974
  }
82902
- const relativeFilePath = path88.relative(directory, fullPath).replace(/\\/g, "/");
82975
+ const relativeFilePath = path92.relative(directory, fullPath).replace(/\\/g, "/");
82903
82976
  if (FILE_ALLOWLIST.some((allowed) => relativeFilePath.endsWith(allowed))) {
82904
82977
  continue;
82905
82978
  }
82906
82979
  let content;
82907
82980
  try {
82908
- const stat6 = fs70.statSync(fullPath);
82909
- if (stat6.size > MAX_FILE_SIZE) {
82981
+ const stat7 = fs70.statSync(fullPath);
82982
+ if (stat7.size > MAX_FILE_SIZE) {
82910
82983
  continue;
82911
82984
  }
82912
82985
  content = fs70.readFileSync(fullPath, "utf-8");
@@ -82971,7 +83044,7 @@ var placeholder_scan = createSwarmTool({
82971
83044
  });
82972
83045
  // src/tools/pre-check-batch.ts
82973
83046
  import * as fs73 from "node:fs";
82974
- import * as path91 from "node:path";
83047
+ import * as path95 from "node:path";
82975
83048
  init_zod();
82976
83049
  init_manager2();
82977
83050
  init_utils();
@@ -83109,7 +83182,7 @@ init_zod();
83109
83182
  init_manager2();
83110
83183
  init_detector();
83111
83184
  import * as fs72 from "node:fs";
83112
- import * as path90 from "node:path";
83185
+ import * as path94 from "node:path";
83113
83186
  import { extname as extname18 } from "node:path";
83114
83187
 
83115
83188
  // src/sast/rules/c.ts
@@ -83890,7 +83963,7 @@ function mapSemgrepSeverity(severity) {
83890
83963
  }
83891
83964
  }
83892
83965
  async function executeWithTimeout(command, args2, options) {
83893
- return new Promise((resolve32) => {
83966
+ return new Promise((resolve33) => {
83894
83967
  const child = child_process9.spawn(command, args2, {
83895
83968
  shell: false,
83896
83969
  cwd: options.cwd
@@ -83899,7 +83972,7 @@ async function executeWithTimeout(command, args2, options) {
83899
83972
  let stderr = "";
83900
83973
  const timeout = setTimeout(() => {
83901
83974
  child.kill("SIGTERM");
83902
- resolve32({
83975
+ resolve33({
83903
83976
  stdout,
83904
83977
  stderr: "Process timed out",
83905
83978
  exitCode: 124
@@ -83913,7 +83986,7 @@ async function executeWithTimeout(command, args2, options) {
83913
83986
  });
83914
83987
  child.on("close", (code) => {
83915
83988
  clearTimeout(timeout);
83916
- resolve32({
83989
+ resolve33({
83917
83990
  stdout,
83918
83991
  stderr,
83919
83992
  exitCode: code ?? 0
@@ -83921,7 +83994,7 @@ async function executeWithTimeout(command, args2, options) {
83921
83994
  });
83922
83995
  child.on("error", (err2) => {
83923
83996
  clearTimeout(timeout);
83924
- resolve32({
83997
+ resolve33({
83925
83998
  stdout,
83926
83999
  stderr: err2.message,
83927
84000
  exitCode: 1
@@ -84003,24 +84076,24 @@ init_create_tool();
84003
84076
  init_utils2();
84004
84077
  import * as crypto8 from "node:crypto";
84005
84078
  import * as fs71 from "node:fs";
84006
- import * as path89 from "node:path";
84079
+ import * as path93 from "node:path";
84007
84080
  var BASELINE_SCHEMA_VERSION = "1.0.0";
84008
84081
  var MAX_BASELINE_FINDINGS = 2000;
84009
84082
  var MAX_BASELINE_BYTES = 2 * 1048576;
84010
84083
  var LOCK_RETRY_DELAYS_MS = [50, 100, 200, 400, 800];
84011
84084
  function normalizeFindingPath(directory, file3) {
84012
- const resolved = path89.isAbsolute(file3) ? file3 : path89.resolve(directory, file3);
84013
- const rel = path89.relative(path89.resolve(directory), resolved);
84085
+ const resolved = path93.isAbsolute(file3) ? file3 : path93.resolve(directory, file3);
84086
+ const rel = path93.relative(path93.resolve(directory), resolved);
84014
84087
  return rel.replace(/\\/g, "/");
84015
84088
  }
84016
84089
  function baselineRelPath(phase) {
84017
- return path89.join("evidence", String(phase), "sast-baseline.json");
84090
+ return path93.join("evidence", String(phase), "sast-baseline.json");
84018
84091
  }
84019
84092
  function tempRelPath(phase) {
84020
- return path89.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
84093
+ return path93.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
84021
84094
  }
84022
84095
  function lockRelPath(phase) {
84023
- return path89.join("evidence", String(phase), "sast-baseline.json.lock");
84096
+ return path93.join("evidence", String(phase), "sast-baseline.json.lock");
84024
84097
  }
84025
84098
  function getLine(lines, idx) {
84026
84099
  if (idx < 0 || idx >= lines.length)
@@ -84106,7 +84179,7 @@ async function acquireLock(lockPath) {
84106
84179
  };
84107
84180
  } catch {
84108
84181
  if (attempt < LOCK_RETRY_DELAYS_MS.length) {
84109
- await new Promise((resolve33) => setTimeout(resolve33, LOCK_RETRY_DELAYS_MS[attempt]));
84182
+ await new Promise((resolve34) => setTimeout(resolve34, LOCK_RETRY_DELAYS_MS[attempt]));
84110
84183
  }
84111
84184
  }
84112
84185
  }
@@ -84141,8 +84214,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
84141
84214
  message: e instanceof Error ? e.message : "Path validation failed"
84142
84215
  };
84143
84216
  }
84144
- fs71.mkdirSync(path89.dirname(baselinePath), { recursive: true });
84145
- fs71.mkdirSync(path89.dirname(tempPath), { recursive: true });
84217
+ fs71.mkdirSync(path93.dirname(baselinePath), { recursive: true });
84218
+ fs71.mkdirSync(path93.dirname(tempPath), { recursive: true });
84146
84219
  const releaseLock = await acquireLock(lockPath);
84147
84220
  try {
84148
84221
  let existing = null;
@@ -84409,9 +84482,9 @@ async function sastScan(input, directory, config3) {
84409
84482
  _filesSkipped++;
84410
84483
  continue;
84411
84484
  }
84412
- const resolvedPath = path90.isAbsolute(filePath) ? filePath : path90.resolve(directory, filePath);
84413
- const resolvedDirectory = path90.resolve(directory);
84414
- if (!resolvedPath.startsWith(resolvedDirectory + path90.sep) && resolvedPath !== resolvedDirectory) {
84485
+ const resolvedPath = path94.isAbsolute(filePath) ? filePath : path94.resolve(directory, filePath);
84486
+ const resolvedDirectory = path94.resolve(directory);
84487
+ if (!resolvedPath.startsWith(resolvedDirectory + path94.sep) && resolvedPath !== resolvedDirectory) {
84415
84488
  _filesSkipped++;
84416
84489
  continue;
84417
84490
  }
@@ -84722,18 +84795,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
84722
84795
  let resolved;
84723
84796
  const isWinAbs = isWindowsAbsolutePath(inputPath);
84724
84797
  if (isWinAbs) {
84725
- resolved = path91.win32.resolve(inputPath);
84726
- } else if (path91.isAbsolute(inputPath)) {
84727
- resolved = path91.resolve(inputPath);
84798
+ resolved = path95.win32.resolve(inputPath);
84799
+ } else if (path95.isAbsolute(inputPath)) {
84800
+ resolved = path95.resolve(inputPath);
84728
84801
  } else {
84729
- resolved = path91.resolve(baseDir, inputPath);
84802
+ resolved = path95.resolve(baseDir, inputPath);
84730
84803
  }
84731
- const workspaceResolved = path91.resolve(workspaceDir);
84804
+ const workspaceResolved = path95.resolve(workspaceDir);
84732
84805
  let relative20;
84733
84806
  if (isWinAbs) {
84734
- relative20 = path91.win32.relative(workspaceResolved, resolved);
84807
+ relative20 = path95.win32.relative(workspaceResolved, resolved);
84735
84808
  } else {
84736
- relative20 = path91.relative(workspaceResolved, resolved);
84809
+ relative20 = path95.relative(workspaceResolved, resolved);
84737
84810
  }
84738
84811
  if (relative20.startsWith("..")) {
84739
84812
  return "path traversal detected";
@@ -84798,7 +84871,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
84798
84871
  if (typeof file3 !== "string") {
84799
84872
  continue;
84800
84873
  }
84801
- const resolvedPath = path91.resolve(file3);
84874
+ const resolvedPath = path95.resolve(file3);
84802
84875
  const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
84803
84876
  if (validationError) {
84804
84877
  continue;
@@ -84955,7 +85028,7 @@ async function runSecretscanWithFiles(files, directory) {
84955
85028
  skippedFiles++;
84956
85029
  continue;
84957
85030
  }
84958
- const resolvedPath = path91.resolve(file3);
85031
+ const resolvedPath = path95.resolve(file3);
84959
85032
  const validationError = validatePath(resolvedPath, directory, directory);
84960
85033
  if (validationError) {
84961
85034
  skippedFiles++;
@@ -84973,19 +85046,19 @@ async function runSecretscanWithFiles(files, directory) {
84973
85046
  };
84974
85047
  }
84975
85048
  for (const file3 of validatedFiles) {
84976
- const ext = path91.extname(file3).toLowerCase();
85049
+ const ext = path95.extname(file3).toLowerCase();
84977
85050
  if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
84978
85051
  skippedFiles++;
84979
85052
  continue;
84980
85053
  }
84981
- let stat6;
85054
+ let stat7;
84982
85055
  try {
84983
- stat6 = fs73.statSync(file3);
85056
+ stat7 = fs73.statSync(file3);
84984
85057
  } catch {
84985
85058
  skippedFiles++;
84986
85059
  continue;
84987
85060
  }
84988
- if (stat6.size > MAX_FILE_SIZE_BYTES9) {
85061
+ if (stat7.size > MAX_FILE_SIZE_BYTES9) {
84989
85062
  skippedFiles++;
84990
85063
  continue;
84991
85064
  }
@@ -85192,7 +85265,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
85192
85265
  const preexistingFindings = [];
85193
85266
  for (const finding of findings) {
85194
85267
  const filePath = finding.location.file;
85195
- const normalised = path91.relative(directory, filePath).replace(/\\/g, "/");
85268
+ const normalised = path95.relative(directory, filePath).replace(/\\/g, "/");
85196
85269
  const changedLines = changedLineRanges.get(normalised);
85197
85270
  if (changedLines?.has(finding.location.line)) {
85198
85271
  newFindings.push(finding);
@@ -85243,7 +85316,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
85243
85316
  warn(`pre_check_batch: Invalid file path: ${file3}`);
85244
85317
  continue;
85245
85318
  }
85246
- changedFiles.push(path91.resolve(directory, file3));
85319
+ changedFiles.push(path95.resolve(directory, file3));
85247
85320
  }
85248
85321
  if (changedFiles.length === 0) {
85249
85322
  warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
@@ -85444,7 +85517,7 @@ var pre_check_batch = createSwarmTool({
85444
85517
  };
85445
85518
  return JSON.stringify(errorResult, null, 2);
85446
85519
  }
85447
- const resolvedDirectory = path91.resolve(typedArgs.directory);
85520
+ const resolvedDirectory = path95.resolve(typedArgs.directory);
85448
85521
  const workspaceAnchor = resolvedDirectory;
85449
85522
  const dirError = validateDirectory2(resolvedDirectory, workspaceAnchor);
85450
85523
  if (dirError) {
@@ -85485,7 +85558,7 @@ var pre_check_batch = createSwarmTool({
85485
85558
  });
85486
85559
  // src/tools/repo-map.ts
85487
85560
  init_zod();
85488
- import * as path92 from "node:path";
85561
+ import * as path96 from "node:path";
85489
85562
  init_path_security();
85490
85563
  init_create_tool();
85491
85564
  var VALID_ACTIONS = [
@@ -85510,7 +85583,7 @@ function validateFile(p) {
85510
85583
  return "file contains control characters";
85511
85584
  if (containsPathTraversal(p))
85512
85585
  return "file contains path traversal";
85513
- if (path92.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
85586
+ if (path96.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
85514
85587
  return "file must be a workspace-relative path, not absolute";
85515
85588
  }
85516
85589
  return null;
@@ -85533,8 +85606,8 @@ function ok(action, payload) {
85533
85606
  }
85534
85607
  function toRelativeGraphPath(input, workspaceRoot) {
85535
85608
  const normalized = input.replace(/\\/g, "/");
85536
- if (path92.isAbsolute(normalized)) {
85537
- const rel = path92.relative(workspaceRoot, normalized).replace(/\\/g, "/");
85609
+ if (path96.isAbsolute(normalized)) {
85610
+ const rel = path96.relative(workspaceRoot, normalized).replace(/\\/g, "/");
85538
85611
  return normalizeGraphPath2(rel);
85539
85612
  }
85540
85613
  return normalizeGraphPath2(normalized);
@@ -85679,7 +85752,7 @@ var repo_map = createSwarmTool({
85679
85752
  init_zod();
85680
85753
  init_create_tool();
85681
85754
  import * as fs74 from "node:fs";
85682
- import * as path93 from "node:path";
85755
+ import * as path97 from "node:path";
85683
85756
  var SPEC_FILE = ".swarm/spec.md";
85684
85757
  var EVIDENCE_DIR4 = ".swarm/evidence";
85685
85758
  var OBLIGATION_KEYWORDS = ["MUST", "SHOULD", "SHALL"];
@@ -85748,10 +85821,10 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
85748
85821
  return [];
85749
85822
  }
85750
85823
  for (const entry of entries) {
85751
- const entryPath = path93.join(evidenceDir, entry);
85824
+ const entryPath = path97.join(evidenceDir, entry);
85752
85825
  try {
85753
- const stat6 = fs74.statSync(entryPath);
85754
- if (!stat6.isDirectory()) {
85826
+ const stat7 = fs74.statSync(entryPath);
85827
+ if (!stat7.isDirectory()) {
85755
85828
  continue;
85756
85829
  }
85757
85830
  } catch {
@@ -85764,18 +85837,18 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
85764
85837
  if (entryPhase !== String(phase)) {
85765
85838
  continue;
85766
85839
  }
85767
- const evidenceFilePath = path93.join(entryPath, "evidence.json");
85840
+ const evidenceFilePath = path97.join(entryPath, "evidence.json");
85768
85841
  try {
85769
- const resolvedPath = path93.resolve(evidenceFilePath);
85770
- const evidenceDirResolved = path93.resolve(evidenceDir);
85771
- if (!resolvedPath.startsWith(evidenceDirResolved + path93.sep)) {
85842
+ const resolvedPath = path97.resolve(evidenceFilePath);
85843
+ const evidenceDirResolved = path97.resolve(evidenceDir);
85844
+ if (!resolvedPath.startsWith(evidenceDirResolved + path97.sep)) {
85772
85845
  continue;
85773
85846
  }
85774
- const stat6 = fs74.lstatSync(evidenceFilePath);
85775
- if (!stat6.isFile()) {
85847
+ const stat7 = fs74.lstatSync(evidenceFilePath);
85848
+ if (!stat7.isFile()) {
85776
85849
  continue;
85777
85850
  }
85778
- if (stat6.size > MAX_FILE_SIZE_BYTES9) {
85851
+ if (stat7.size > MAX_FILE_SIZE_BYTES9) {
85779
85852
  continue;
85780
85853
  }
85781
85854
  } catch {
@@ -85802,7 +85875,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
85802
85875
  if (Array.isArray(diffEntry.files_changed)) {
85803
85876
  for (const file3 of diffEntry.files_changed) {
85804
85877
  if (typeof file3 === "string") {
85805
- touchedFiles.add(path93.resolve(cwd, file3));
85878
+ touchedFiles.add(path97.resolve(cwd, file3));
85806
85879
  }
85807
85880
  }
85808
85881
  }
@@ -85815,8 +85888,8 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
85815
85888
  }
85816
85889
  function searchFileForKeywords(filePath, keywords, cwd) {
85817
85890
  try {
85818
- const resolvedPath = path93.resolve(filePath);
85819
- const cwdResolved = path93.resolve(cwd);
85891
+ const resolvedPath = path97.resolve(filePath);
85892
+ const cwdResolved = path97.resolve(cwd);
85820
85893
  if (!resolvedPath.startsWith(cwdResolved)) {
85821
85894
  return false;
85822
85895
  }
@@ -85950,7 +86023,7 @@ var req_coverage = createSwarmTool({
85950
86023
  }, null, 2);
85951
86024
  }
85952
86025
  const cwd = inputDirectory || directory;
85953
- const specPath = path93.join(cwd, SPEC_FILE);
86026
+ const specPath = path97.join(cwd, SPEC_FILE);
85954
86027
  let specContent;
85955
86028
  try {
85956
86029
  specContent = fs74.readFileSync(specPath, "utf-8");
@@ -85977,7 +86050,7 @@ var req_coverage = createSwarmTool({
85977
86050
  message: "No FR requirements found in spec.md"
85978
86051
  }, null, 2);
85979
86052
  }
85980
- const evidenceDir = path93.join(cwd, EVIDENCE_DIR4);
86053
+ const evidenceDir = path97.join(cwd, EVIDENCE_DIR4);
85981
86054
  const touchedFiles = readTouchedFiles(evidenceDir, phase, cwd);
85982
86055
  const analyzedRequirements = [];
85983
86056
  let coveredCount = 0;
@@ -86003,7 +86076,7 @@ var req_coverage = createSwarmTool({
86003
86076
  requirements: analyzedRequirements
86004
86077
  };
86005
86078
  const reportFilename = `req-coverage-phase-${phase}.json`;
86006
- const reportPath = path93.join(evidenceDir, reportFilename);
86079
+ const reportPath = path97.join(evidenceDir, reportFilename);
86007
86080
  try {
86008
86081
  if (!fs74.existsSync(evidenceDir)) {
86009
86082
  fs74.mkdirSync(evidenceDir, { recursive: true });
@@ -86091,7 +86164,7 @@ init_qa_gate_profile();
86091
86164
  init_file_locks();
86092
86165
  import * as crypto9 from "node:crypto";
86093
86166
  import * as fs75 from "node:fs";
86094
- import * as path94 from "node:path";
86167
+ import * as path98 from "node:path";
86095
86168
  init_ledger();
86096
86169
  init_manager();
86097
86170
  init_state();
@@ -86169,8 +86242,8 @@ async function executeSavePlan(args2, fallbackDir) {
86169
86242
  };
86170
86243
  }
86171
86244
  if (args2.working_directory && fallbackDir) {
86172
- const resolvedTarget = path94.resolve(args2.working_directory);
86173
- const resolvedRoot = path94.resolve(fallbackDir);
86245
+ const resolvedTarget = path98.resolve(args2.working_directory);
86246
+ const resolvedRoot = path98.resolve(fallbackDir);
86174
86247
  let fallbackExists = false;
86175
86248
  try {
86176
86249
  fs75.accessSync(resolvedRoot, fs75.constants.F_OK);
@@ -86179,7 +86252,7 @@ async function executeSavePlan(args2, fallbackDir) {
86179
86252
  fallbackExists = false;
86180
86253
  }
86181
86254
  if (fallbackExists) {
86182
- const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path94.sep);
86255
+ const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path98.sep);
86183
86256
  if (isSubdirectory) {
86184
86257
  return {
86185
86258
  success: false,
@@ -86195,10 +86268,10 @@ async function executeSavePlan(args2, fallbackDir) {
86195
86268
  let specMtime;
86196
86269
  let specHash;
86197
86270
  if (process.env.SWARM_SKIP_SPEC_GATE !== "1") {
86198
- const specPath = path94.join(targetWorkspace, ".swarm", "spec.md");
86271
+ const specPath = path98.join(targetWorkspace, ".swarm", "spec.md");
86199
86272
  try {
86200
- const stat6 = await fs75.promises.stat(specPath);
86201
- specMtime = stat6.mtime.toISOString();
86273
+ const stat7 = await fs75.promises.stat(specPath);
86274
+ specMtime = stat7.mtime.toISOString();
86202
86275
  const content = await fs75.promises.readFile(specPath, "utf8");
86203
86276
  specHash = crypto9.createHash("sha256").update(content).digest("hex");
86204
86277
  } catch {
@@ -86211,7 +86284,7 @@ async function executeSavePlan(args2, fallbackDir) {
86211
86284
  }
86212
86285
  }
86213
86286
  if (process.env.SWARM_SKIP_GATE_SELECTION !== "1") {
86214
- const contextPath = path94.join(targetWorkspace, ".swarm", "context.md");
86287
+ const contextPath = path98.join(targetWorkspace, ".swarm", "context.md");
86215
86288
  let contextContent = "";
86216
86289
  try {
86217
86290
  contextContent = await fs75.promises.readFile(contextPath, "utf8");
@@ -86361,7 +86434,7 @@ async function executeSavePlan(args2, fallbackDir) {
86361
86434
  }
86362
86435
  await writeCheckpoint(dir).catch(() => {});
86363
86436
  try {
86364
- const markerPath = path94.join(dir, ".swarm", ".plan-write-marker");
86437
+ const markerPath = path98.join(dir, ".swarm", ".plan-write-marker");
86365
86438
  const marker = JSON.stringify({
86366
86439
  source: "save_plan",
86367
86440
  timestamp: new Date().toISOString(),
@@ -86384,7 +86457,7 @@ async function executeSavePlan(args2, fallbackDir) {
86384
86457
  return {
86385
86458
  success: true,
86386
86459
  message: "Plan saved successfully",
86387
- plan_path: path94.join(dir, ".swarm", "plan.json"),
86460
+ plan_path: path98.join(dir, ".swarm", "plan.json"),
86388
86461
  phases_count: plan.phases.length,
86389
86462
  tasks_count: tasksCount,
86390
86463
  ...resolvedProfile !== undefined ? { execution_profile: resolvedProfile } : {},
@@ -86437,7 +86510,7 @@ var save_plan = createSwarmTool({
86437
86510
  init_zod();
86438
86511
  init_manager2();
86439
86512
  import * as fs76 from "node:fs";
86440
- import * as path95 from "node:path";
86513
+ import * as path99 from "node:path";
86441
86514
 
86442
86515
  // src/sbom/detectors/index.ts
86443
86516
  init_utils();
@@ -87287,7 +87360,7 @@ function findManifestFiles(rootDir) {
87287
87360
  try {
87288
87361
  const entries = fs76.readdirSync(dir, { withFileTypes: true });
87289
87362
  for (const entry of entries) {
87290
- const fullPath = path95.join(dir, entry.name);
87363
+ const fullPath = path99.join(dir, entry.name);
87291
87364
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
87292
87365
  continue;
87293
87366
  }
@@ -87296,7 +87369,7 @@ function findManifestFiles(rootDir) {
87296
87369
  } else if (entry.isFile()) {
87297
87370
  for (const pattern of patterns) {
87298
87371
  if (simpleGlobToRegex(pattern).test(entry.name)) {
87299
- manifestFiles.push(path95.relative(rootDir, fullPath));
87372
+ manifestFiles.push(path99.relative(rootDir, fullPath));
87300
87373
  break;
87301
87374
  }
87302
87375
  }
@@ -87314,11 +87387,11 @@ function findManifestFilesInDirs(directories, workingDir) {
87314
87387
  try {
87315
87388
  const entries = fs76.readdirSync(dir, { withFileTypes: true });
87316
87389
  for (const entry of entries) {
87317
- const fullPath = path95.join(dir, entry.name);
87390
+ const fullPath = path99.join(dir, entry.name);
87318
87391
  if (entry.isFile()) {
87319
87392
  for (const pattern of patterns) {
87320
87393
  if (simpleGlobToRegex(pattern).test(entry.name)) {
87321
- found.push(path95.relative(workingDir, fullPath));
87394
+ found.push(path99.relative(workingDir, fullPath));
87322
87395
  break;
87323
87396
  }
87324
87397
  }
@@ -87331,11 +87404,11 @@ function findManifestFilesInDirs(directories, workingDir) {
87331
87404
  function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
87332
87405
  const dirs = new Set;
87333
87406
  for (const file3 of changedFiles) {
87334
- let currentDir = path95.dirname(file3);
87407
+ let currentDir = path99.dirname(file3);
87335
87408
  while (true) {
87336
- if (currentDir && currentDir !== "." && currentDir !== path95.sep) {
87337
- dirs.add(path95.join(workingDir, currentDir));
87338
- const parent = path95.dirname(currentDir);
87409
+ if (currentDir && currentDir !== "." && currentDir !== path99.sep) {
87410
+ dirs.add(path99.join(workingDir, currentDir));
87411
+ const parent = path99.dirname(currentDir);
87339
87412
  if (parent === currentDir)
87340
87413
  break;
87341
87414
  currentDir = parent;
@@ -87419,7 +87492,7 @@ var sbom_generate = createSwarmTool({
87419
87492
  const changedFiles = obj.changed_files;
87420
87493
  const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
87421
87494
  const workingDir = directory;
87422
- const outputDir = path95.isAbsolute(relativeOutputDir) ? relativeOutputDir : path95.join(workingDir, relativeOutputDir);
87495
+ const outputDir = path99.isAbsolute(relativeOutputDir) ? relativeOutputDir : path99.join(workingDir, relativeOutputDir);
87423
87496
  let manifestFiles = [];
87424
87497
  if (scope === "all") {
87425
87498
  manifestFiles = findManifestFiles(workingDir);
@@ -87442,7 +87515,7 @@ var sbom_generate = createSwarmTool({
87442
87515
  const processedFiles = [];
87443
87516
  for (const manifestFile of manifestFiles) {
87444
87517
  try {
87445
- const fullPath = path95.isAbsolute(manifestFile) ? manifestFile : path95.join(workingDir, manifestFile);
87518
+ const fullPath = path99.isAbsolute(manifestFile) ? manifestFile : path99.join(workingDir, manifestFile);
87446
87519
  if (!fs76.existsSync(fullPath)) {
87447
87520
  continue;
87448
87521
  }
@@ -87459,7 +87532,7 @@ var sbom_generate = createSwarmTool({
87459
87532
  const bom = generateCycloneDX(allComponents);
87460
87533
  const bomJson = serializeCycloneDX(bom);
87461
87534
  const filename = generateSbomFilename();
87462
- const outputPath = path95.join(outputDir, filename);
87535
+ const outputPath = path99.join(outputDir, filename);
87463
87536
  fs76.writeFileSync(outputPath, bomJson, "utf-8");
87464
87537
  const verdict = processedFiles.length > 0 ? "pass" : "pass";
87465
87538
  try {
@@ -87503,7 +87576,7 @@ var sbom_generate = createSwarmTool({
87503
87576
  init_zod();
87504
87577
  init_create_tool();
87505
87578
  import * as fs77 from "node:fs";
87506
- import * as path96 from "node:path";
87579
+ import * as path100 from "node:path";
87507
87580
  var SPEC_CANDIDATES = [
87508
87581
  "openapi.json",
87509
87582
  "openapi.yaml",
@@ -87535,12 +87608,12 @@ function normalizePath3(p) {
87535
87608
  }
87536
87609
  function discoverSpecFile(cwd, specFileArg) {
87537
87610
  if (specFileArg) {
87538
- const resolvedPath = path96.resolve(cwd, specFileArg);
87539
- const normalizedCwd = cwd.endsWith(path96.sep) ? cwd : cwd + path96.sep;
87611
+ const resolvedPath = path100.resolve(cwd, specFileArg);
87612
+ const normalizedCwd = cwd.endsWith(path100.sep) ? cwd : cwd + path100.sep;
87540
87613
  if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
87541
87614
  throw new Error("Invalid spec_file: path traversal detected");
87542
87615
  }
87543
- const ext = path96.extname(resolvedPath).toLowerCase();
87616
+ const ext = path100.extname(resolvedPath).toLowerCase();
87544
87617
  if (!ALLOWED_EXTENSIONS.includes(ext)) {
87545
87618
  throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
87546
87619
  }
@@ -87554,7 +87627,7 @@ function discoverSpecFile(cwd, specFileArg) {
87554
87627
  return resolvedPath;
87555
87628
  }
87556
87629
  for (const candidate of SPEC_CANDIDATES) {
87557
- const candidatePath = path96.resolve(cwd, candidate);
87630
+ const candidatePath = path100.resolve(cwd, candidate);
87558
87631
  if (fs77.existsSync(candidatePath)) {
87559
87632
  const stats = fs77.statSync(candidatePath);
87560
87633
  if (stats.size <= MAX_SPEC_SIZE) {
@@ -87566,7 +87639,7 @@ function discoverSpecFile(cwd, specFileArg) {
87566
87639
  }
87567
87640
  function parseSpec(specFile) {
87568
87641
  const content = fs77.readFileSync(specFile, "utf-8");
87569
- const ext = path96.extname(specFile).toLowerCase();
87642
+ const ext = path100.extname(specFile).toLowerCase();
87570
87643
  if (ext === ".json") {
87571
87644
  return parseJsonSpec(content);
87572
87645
  }
@@ -87642,7 +87715,7 @@ function extractRoutes(cwd) {
87642
87715
  return;
87643
87716
  }
87644
87717
  for (const entry of entries) {
87645
- const fullPath = path96.join(dir, entry.name);
87718
+ const fullPath = path100.join(dir, entry.name);
87646
87719
  if (entry.isSymbolicLink()) {
87647
87720
  continue;
87648
87721
  }
@@ -87652,7 +87725,7 @@ function extractRoutes(cwd) {
87652
87725
  }
87653
87726
  walkDir(fullPath);
87654
87727
  } else if (entry.isFile()) {
87655
- const ext = path96.extname(entry.name).toLowerCase();
87728
+ const ext = path100.extname(entry.name).toLowerCase();
87656
87729
  const baseName = entry.name.toLowerCase();
87657
87730
  if (![".ts", ".js", ".mjs"].includes(ext)) {
87658
87731
  continue;
@@ -87820,7 +87893,7 @@ init_bun_compat();
87820
87893
  init_path_security();
87821
87894
  init_create_tool();
87822
87895
  import * as fs78 from "node:fs";
87823
- import * as path97 from "node:path";
87896
+ import * as path101 from "node:path";
87824
87897
  var DEFAULT_MAX_RESULTS = 100;
87825
87898
  var DEFAULT_MAX_LINES = 200;
87826
87899
  var REGEX_TIMEOUT_MS = 5000;
@@ -87856,11 +87929,11 @@ function containsWindowsAttacks3(str) {
87856
87929
  }
87857
87930
  function isPathInWorkspace3(filePath, workspace) {
87858
87931
  try {
87859
- const resolvedPath = path97.resolve(workspace, filePath);
87932
+ const resolvedPath = path101.resolve(workspace, filePath);
87860
87933
  const realWorkspace = fs78.realpathSync(workspace);
87861
87934
  const realResolvedPath = fs78.realpathSync(resolvedPath);
87862
- const relativePath = path97.relative(realWorkspace, realResolvedPath);
87863
- if (relativePath.startsWith("..") || path97.isAbsolute(relativePath)) {
87935
+ const relativePath = path101.relative(realWorkspace, realResolvedPath);
87936
+ if (relativePath.startsWith("..") || path101.isAbsolute(relativePath)) {
87864
87937
  return false;
87865
87938
  }
87866
87939
  return true;
@@ -87873,11 +87946,11 @@ function validatePathForRead2(filePath, workspace) {
87873
87946
  }
87874
87947
  function findRgInEnvPath() {
87875
87948
  const searchPath = process.env.PATH ?? "";
87876
- for (const dir of searchPath.split(path97.delimiter)) {
87949
+ for (const dir of searchPath.split(path101.delimiter)) {
87877
87950
  if (!dir)
87878
87951
  continue;
87879
87952
  const isWindows = process.platform === "win32";
87880
- const candidate = path97.join(dir, isWindows ? "rg.exe" : "rg");
87953
+ const candidate = path101.join(dir, isWindows ? "rg.exe" : "rg");
87881
87954
  if (fs78.existsSync(candidate))
87882
87955
  return candidate;
87883
87956
  }
@@ -87932,7 +88005,7 @@ async function ripgrepSearch(opts) {
87932
88005
  stderr: "pipe",
87933
88006
  cwd: opts.workspace
87934
88007
  });
87935
- const timeout = new Promise((resolve39) => setTimeout(() => resolve39("timeout"), REGEX_TIMEOUT_MS));
88008
+ const timeout = new Promise((resolve40) => setTimeout(() => resolve40("timeout"), REGEX_TIMEOUT_MS));
87936
88009
  const exitPromise = proc.exited;
87937
88010
  const result = await Promise.race([exitPromise, timeout]);
87938
88011
  if (result === "timeout") {
@@ -88007,8 +88080,8 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
88007
88080
  try {
88008
88081
  const entries = fs78.readdirSync(dir, { withFileTypes: true });
88009
88082
  for (const entry of entries) {
88010
- const fullPath = path97.join(dir, entry.name);
88011
- const relativePath = path97.relative(workspace, fullPath);
88083
+ const fullPath = path101.join(dir, entry.name);
88084
+ const relativePath = path101.relative(workspace, fullPath);
88012
88085
  if (!validatePathForRead2(fullPath, workspace)) {
88013
88086
  continue;
88014
88087
  }
@@ -88049,7 +88122,7 @@ async function fallbackSearch(opts) {
88049
88122
  const matches = [];
88050
88123
  let total = 0;
88051
88124
  for (const file3 of files) {
88052
- const fullPath = path97.join(opts.workspace, file3);
88125
+ const fullPath = path101.join(opts.workspace, file3);
88053
88126
  if (!validatePathForRead2(fullPath, opts.workspace)) {
88054
88127
  continue;
88055
88128
  }
@@ -88430,7 +88503,7 @@ init_zod();
88430
88503
  init_path_security();
88431
88504
  init_create_tool();
88432
88505
  import * as fs79 from "node:fs";
88433
- import * as path98 from "node:path";
88506
+ import * as path102 from "node:path";
88434
88507
  var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
88435
88508
  function containsWindowsAttacks4(str) {
88436
88509
  if (/:[^\\/]/.test(str))
@@ -88444,14 +88517,14 @@ function containsWindowsAttacks4(str) {
88444
88517
  }
88445
88518
  function isPathInWorkspace4(filePath, workspace) {
88446
88519
  try {
88447
- const resolvedPath = path98.resolve(workspace, filePath);
88520
+ const resolvedPath = path102.resolve(workspace, filePath);
88448
88521
  if (!fs79.existsSync(resolvedPath)) {
88449
88522
  return true;
88450
88523
  }
88451
88524
  const realWorkspace = fs79.realpathSync(workspace);
88452
88525
  const realResolvedPath = fs79.realpathSync(resolvedPath);
88453
- const relativePath = path98.relative(realWorkspace, realResolvedPath);
88454
- if (relativePath.startsWith("..") || path98.isAbsolute(relativePath)) {
88526
+ const relativePath = path102.relative(realWorkspace, realResolvedPath);
88527
+ if (relativePath.startsWith("..") || path102.isAbsolute(relativePath)) {
88455
88528
  return false;
88456
88529
  }
88457
88530
  return true;
@@ -88659,7 +88732,7 @@ var suggestPatch = createSwarmTool({
88659
88732
  });
88660
88733
  continue;
88661
88734
  }
88662
- const fullPath = path98.resolve(directory, change.file);
88735
+ const fullPath = path102.resolve(directory, change.file);
88663
88736
  if (!fs79.existsSync(fullPath)) {
88664
88737
  errors5.push({
88665
88738
  success: false,
@@ -88922,7 +88995,7 @@ var generate_mutants = createSwarmTool({
88922
88995
  init_spec_schema();
88923
88996
  init_create_tool();
88924
88997
  import * as fs80 from "node:fs";
88925
- import * as path99 from "node:path";
88998
+ import * as path103 from "node:path";
88926
88999
  var SPEC_FILE_NAME = "spec.md";
88927
89000
  var SWARM_DIR2 = ".swarm";
88928
89001
  var OBLIGATION_KEYWORDS2 = ["MUST", "SHALL", "SHOULD", "MAY"];
@@ -88975,7 +89048,7 @@ var lint_spec = createSwarmTool({
88975
89048
  async execute(_args, directory) {
88976
89049
  const errors5 = [];
88977
89050
  const warnings = [];
88978
- const specPath = path99.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
89051
+ const specPath = path103.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
88979
89052
  if (!fs80.existsSync(specPath)) {
88980
89053
  const result2 = {
88981
89054
  valid: false,
@@ -89046,12 +89119,12 @@ var lint_spec = createSwarmTool({
89046
89119
  // src/tools/mutation-test.ts
89047
89120
  init_zod();
89048
89121
  import * as fs81 from "node:fs";
89049
- import * as path101 from "node:path";
89122
+ import * as path105 from "node:path";
89050
89123
 
89051
89124
  // src/mutation/engine.ts
89052
89125
  import { spawnSync as spawnSync3 } from "node:child_process";
89053
89126
  import { unlinkSync as unlinkSync13, writeFileSync as writeFileSync20 } from "node:fs";
89054
- import * as path100 from "node:path";
89127
+ import * as path104 from "node:path";
89055
89128
 
89056
89129
  // src/mutation/equivalence.ts
89057
89130
  function isStaticallyEquivalent(originalCode, mutatedCode) {
@@ -89186,7 +89259,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
89186
89259
  let patchFile;
89187
89260
  try {
89188
89261
  const safeId2 = patch.id.replace(/[^a-zA-Z0-9_-]/g, "_");
89189
- patchFile = path100.join(workingDir, `.mutation_patch_${safeId2}.diff`);
89262
+ patchFile = path104.join(workingDir, `.mutation_patch_${safeId2}.diff`);
89190
89263
  try {
89191
89264
  writeFileSync20(patchFile, patch.patch);
89192
89265
  } catch (writeErr) {
@@ -89580,7 +89653,7 @@ var mutation_test = createSwarmTool({
89580
89653
  ];
89581
89654
  for (const filePath of uniquePaths) {
89582
89655
  try {
89583
- const resolvedPath = path101.resolve(cwd, filePath);
89656
+ const resolvedPath = path105.resolve(cwd, filePath);
89584
89657
  sourceFiles.set(filePath, fs81.readFileSync(resolvedPath, "utf-8"));
89585
89658
  } catch {}
89586
89659
  }
@@ -89600,7 +89673,7 @@ init_zod();
89600
89673
  init_manager2();
89601
89674
  init_detector();
89602
89675
  import * as fs82 from "node:fs";
89603
- import * as path102 from "node:path";
89676
+ import * as path106 from "node:path";
89604
89677
  init_create_tool();
89605
89678
  var MAX_FILE_SIZE2 = 2 * 1024 * 1024;
89606
89679
  var BINARY_CHECK_BYTES = 8192;
@@ -89666,7 +89739,7 @@ async function syntaxCheck(input, directory, config3) {
89666
89739
  if (languages?.length) {
89667
89740
  const lowerLangs = languages.map((l) => l.toLowerCase());
89668
89741
  filesToCheck = filesToCheck.filter((file3) => {
89669
- const ext = path102.extname(file3.path).toLowerCase();
89742
+ const ext = path106.extname(file3.path).toLowerCase();
89670
89743
  const langDef = getLanguageForExtension(ext);
89671
89744
  const fileProfile = getProfileForFile(file3.path);
89672
89745
  const langId = fileProfile?.id || langDef?.id;
@@ -89679,7 +89752,7 @@ async function syntaxCheck(input, directory, config3) {
89679
89752
  let skippedCount = 0;
89680
89753
  for (const fileInfo of filesToCheck) {
89681
89754
  const { path: filePath } = fileInfo;
89682
- const fullPath = path102.isAbsolute(filePath) ? filePath : path102.join(directory, filePath);
89755
+ const fullPath = path106.isAbsolute(filePath) ? filePath : path106.join(directory, filePath);
89683
89756
  const result = {
89684
89757
  path: filePath,
89685
89758
  language: "",
@@ -89728,7 +89801,7 @@ async function syntaxCheck(input, directory, config3) {
89728
89801
  results.push(result);
89729
89802
  continue;
89730
89803
  }
89731
- const ext = path102.extname(filePath).toLowerCase();
89804
+ const ext = path106.extname(filePath).toLowerCase();
89732
89805
  const langDef = getLanguageForExtension(ext);
89733
89806
  result.language = profile?.id || langDef?.id || "unknown";
89734
89807
  const errors5 = extractSyntaxErrors(parser, content);
@@ -89821,7 +89894,7 @@ init_utils();
89821
89894
  init_create_tool();
89822
89895
  init_path_security();
89823
89896
  import * as fs83 from "node:fs";
89824
- import * as path103 from "node:path";
89897
+ import * as path107 from "node:path";
89825
89898
  var MAX_TEXT_LENGTH = 200;
89826
89899
  var MAX_FILE_SIZE_BYTES11 = 1024 * 1024;
89827
89900
  var SUPPORTED_EXTENSIONS4 = new Set([
@@ -89887,9 +89960,9 @@ function validatePathsInput(paths, cwd) {
89887
89960
  return { error: "paths contains path traversal", resolvedPath: null };
89888
89961
  }
89889
89962
  try {
89890
- const resolvedPath = path103.resolve(paths);
89891
- const normalizedCwd = path103.resolve(cwd);
89892
- const normalizedResolved = path103.resolve(resolvedPath);
89963
+ const resolvedPath = path107.resolve(paths);
89964
+ const normalizedCwd = path107.resolve(cwd);
89965
+ const normalizedResolved = path107.resolve(resolvedPath);
89893
89966
  if (!normalizedResolved.startsWith(normalizedCwd)) {
89894
89967
  return {
89895
89968
  error: "paths must be within the current working directory",
@@ -89905,7 +89978,7 @@ function validatePathsInput(paths, cwd) {
89905
89978
  }
89906
89979
  }
89907
89980
  function isSupportedExtension(filePath) {
89908
- const ext = path103.extname(filePath).toLowerCase();
89981
+ const ext = path107.extname(filePath).toLowerCase();
89909
89982
  return SUPPORTED_EXTENSIONS4.has(ext);
89910
89983
  }
89911
89984
  function findSourceFiles3(dir, files = []) {
@@ -89920,16 +89993,16 @@ function findSourceFiles3(dir, files = []) {
89920
89993
  if (SKIP_DIRECTORIES5.has(entry)) {
89921
89994
  continue;
89922
89995
  }
89923
- const fullPath = path103.join(dir, entry);
89924
- let stat6;
89996
+ const fullPath = path107.join(dir, entry);
89997
+ let stat7;
89925
89998
  try {
89926
- stat6 = fs83.statSync(fullPath);
89999
+ stat7 = fs83.statSync(fullPath);
89927
90000
  } catch {
89928
90001
  continue;
89929
90002
  }
89930
- if (stat6.isDirectory()) {
90003
+ if (stat7.isDirectory()) {
89931
90004
  findSourceFiles3(fullPath, files);
89932
- } else if (stat6.isFile()) {
90005
+ } else if (stat7.isFile()) {
89933
90006
  if (isSupportedExtension(fullPath)) {
89934
90007
  files.push(fullPath);
89935
90008
  }
@@ -90026,13 +90099,13 @@ var todo_extract = createSwarmTool({
90026
90099
  return JSON.stringify(errorResult, null, 2);
90027
90100
  }
90028
90101
  const filesToScan = [];
90029
- const stat6 = fs83.statSync(scanPath);
90030
- if (stat6.isFile()) {
90102
+ const stat7 = fs83.statSync(scanPath);
90103
+ if (stat7.isFile()) {
90031
90104
  if (isSupportedExtension(scanPath)) {
90032
90105
  filesToScan.push(scanPath);
90033
90106
  } else {
90034
90107
  const errorResult = {
90035
- error: `unsupported file extension: ${path103.extname(scanPath)}`,
90108
+ error: `unsupported file extension: ${path107.extname(scanPath)}`,
90036
90109
  total: 0,
90037
90110
  byPriority: { high: 0, medium: 0, low: 0 },
90038
90111
  entries: []
@@ -90081,17 +90154,17 @@ init_schema();
90081
90154
  init_qa_gate_profile();
90082
90155
  init_gate_evidence();
90083
90156
  import * as fs86 from "node:fs";
90084
- import * as path106 from "node:path";
90157
+ import * as path110 from "node:path";
90085
90158
 
90086
90159
  // src/hooks/diff-scope.ts
90087
90160
  init_bun_compat();
90088
90161
  import * as fs85 from "node:fs";
90089
- import * as path105 from "node:path";
90162
+ import * as path109 from "node:path";
90090
90163
 
90091
90164
  // src/utils/gitignore-warning.ts
90092
90165
  init_bun_compat();
90093
90166
  import * as fs84 from "node:fs";
90094
- import * as path104 from "node:path";
90167
+ import * as path108 from "node:path";
90095
90168
  var _internals = { bunSpawn };
90096
90169
  var _swarmGitExcludedChecked = false;
90097
90170
  function fileCoversSwarm(content) {
@@ -90165,10 +90238,10 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
90165
90238
  const excludeRelPath = excludePathRaw.trim();
90166
90239
  if (!excludeRelPath)
90167
90240
  return;
90168
- const excludePath = path104.isAbsolute(excludeRelPath) ? excludeRelPath : path104.join(directory, excludeRelPath);
90241
+ const excludePath = path108.isAbsolute(excludeRelPath) ? excludeRelPath : path108.join(directory, excludeRelPath);
90169
90242
  if (checkIgnoreExitCode !== 0) {
90170
90243
  try {
90171
- fs84.mkdirSync(path104.dirname(excludePath), { recursive: true });
90244
+ fs84.mkdirSync(path108.dirname(excludePath), { recursive: true });
90172
90245
  let existing = "";
90173
90246
  try {
90174
90247
  existing = fs84.readFileSync(excludePath, "utf8");
@@ -90212,7 +90285,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
90212
90285
  var _internals2 = { bunSpawn };
90213
90286
  function getDeclaredScope(taskId, directory) {
90214
90287
  try {
90215
- const planPath = path105.join(directory, ".swarm", "plan.json");
90288
+ const planPath = path109.join(directory, ".swarm", "plan.json");
90216
90289
  if (!fs85.existsSync(planPath))
90217
90290
  return null;
90218
90291
  const raw = fs85.readFileSync(planPath, "utf-8");
@@ -90349,7 +90422,7 @@ var TIER_3_PATTERNS = [
90349
90422
  ];
90350
90423
  function matchesTier3Pattern(files) {
90351
90424
  for (const file3 of files) {
90352
- const fileName = path106.basename(file3);
90425
+ const fileName = path110.basename(file3);
90353
90426
  for (const pattern of TIER_3_PATTERNS) {
90354
90427
  if (pattern.test(fileName)) {
90355
90428
  return true;
@@ -90363,7 +90436,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
90363
90436
  if (hasActiveTurboMode()) {
90364
90437
  const resolvedDir2 = workingDirectory;
90365
90438
  try {
90366
- const planPath = path106.join(resolvedDir2, ".swarm", "plan.json");
90439
+ const planPath = path110.join(resolvedDir2, ".swarm", "plan.json");
90367
90440
  const planRaw = fs86.readFileSync(planPath, "utf-8");
90368
90441
  const plan = JSON.parse(planRaw);
90369
90442
  for (const planPhase of plan.phases ?? []) {
@@ -90433,7 +90506,7 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
90433
90506
  }
90434
90507
  try {
90435
90508
  const resolvedDir2 = workingDirectory;
90436
- const planPath = path106.join(resolvedDir2, ".swarm", "plan.json");
90509
+ const planPath = path110.join(resolvedDir2, ".swarm", "plan.json");
90437
90510
  const planRaw = fs86.readFileSync(planPath, "utf-8");
90438
90511
  const plan = JSON.parse(planRaw);
90439
90512
  for (const planPhase of plan.phases ?? []) {
@@ -90623,8 +90696,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
90623
90696
  };
90624
90697
  }
90625
90698
  }
90626
- normalizedDir = path106.normalize(args2.working_directory);
90627
- const pathParts = normalizedDir.split(path106.sep);
90699
+ normalizedDir = path110.normalize(args2.working_directory);
90700
+ const pathParts = normalizedDir.split(path110.sep);
90628
90701
  if (pathParts.includes("..")) {
90629
90702
  return {
90630
90703
  success: false,
@@ -90634,10 +90707,10 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
90634
90707
  ]
90635
90708
  };
90636
90709
  }
90637
- const resolvedDir = path106.resolve(normalizedDir);
90710
+ const resolvedDir = path110.resolve(normalizedDir);
90638
90711
  try {
90639
90712
  const realPath = fs86.realpathSync(resolvedDir);
90640
- const planPath = path106.join(realPath, ".swarm", "plan.json");
90713
+ const planPath = path110.join(realPath, ".swarm", "plan.json");
90641
90714
  if (!fs86.existsSync(planPath)) {
90642
90715
  return {
90643
90716
  success: false,
@@ -90669,8 +90742,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
90669
90742
  }
90670
90743
  if (args2.status === "in_progress") {
90671
90744
  try {
90672
- const evidencePath = path106.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
90673
- fs86.mkdirSync(path106.dirname(evidencePath), { recursive: true });
90745
+ const evidencePath = path110.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
90746
+ fs86.mkdirSync(path110.dirname(evidencePath), { recursive: true });
90674
90747
  const fd = fs86.openSync(evidencePath, "wx");
90675
90748
  let writeOk = false;
90676
90749
  try {
@@ -90694,7 +90767,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
90694
90767
  recoverTaskStateFromDelegations(args2.task_id);
90695
90768
  let phaseRequiresReviewer = true;
90696
90769
  try {
90697
- const planPath = path106.join(directory, ".swarm", "plan.json");
90770
+ const planPath = path110.join(directory, ".swarm", "plan.json");
90698
90771
  const planRaw = fs86.readFileSync(planPath, "utf-8");
90699
90772
  const plan = JSON.parse(planRaw);
90700
90773
  const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
@@ -91006,7 +91079,7 @@ init_ledger();
91006
91079
  init_manager();
91007
91080
  init_create_tool();
91008
91081
  import fs87 from "node:fs";
91009
- import path107 from "node:path";
91082
+ import path111 from "node:path";
91010
91083
  function derivePlanId5(plan) {
91011
91084
  return `${plan.swarm}-${plan.title}`.replace(/[^a-zA-Z0-9-_]/g, "_");
91012
91085
  }
@@ -91057,7 +91130,7 @@ async function executeWriteDriftEvidence(args2, directory) {
91057
91130
  entries: [evidenceEntry]
91058
91131
  };
91059
91132
  const filename = "drift-verifier.json";
91060
- const relativePath = path107.join("evidence", String(phase), filename);
91133
+ const relativePath = path111.join("evidence", String(phase), filename);
91061
91134
  let validatedPath;
91062
91135
  try {
91063
91136
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -91068,10 +91141,10 @@ async function executeWriteDriftEvidence(args2, directory) {
91068
91141
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
91069
91142
  }, null, 2);
91070
91143
  }
91071
- const evidenceDir = path107.dirname(validatedPath);
91144
+ const evidenceDir = path111.dirname(validatedPath);
91072
91145
  try {
91073
91146
  await fs87.promises.mkdir(evidenceDir, { recursive: true });
91074
- const tempPath = path107.join(evidenceDir, `.${filename}.tmp`);
91147
+ const tempPath = path111.join(evidenceDir, `.${filename}.tmp`);
91075
91148
  await fs87.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
91076
91149
  await fs87.promises.rename(tempPath, validatedPath);
91077
91150
  let snapshotInfo;
@@ -91168,7 +91241,7 @@ init_zod();
91168
91241
  init_utils2();
91169
91242
  init_create_tool();
91170
91243
  import fs88 from "node:fs";
91171
- import path108 from "node:path";
91244
+ import path112 from "node:path";
91172
91245
  function normalizeVerdict2(verdict) {
91173
91246
  switch (verdict) {
91174
91247
  case "APPROVED":
@@ -91216,7 +91289,7 @@ async function executeWriteHallucinationEvidence(args2, directory) {
91216
91289
  entries: [evidenceEntry]
91217
91290
  };
91218
91291
  const filename = "hallucination-guard.json";
91219
- const relativePath = path108.join("evidence", String(phase), filename);
91292
+ const relativePath = path112.join("evidence", String(phase), filename);
91220
91293
  let validatedPath;
91221
91294
  try {
91222
91295
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -91227,10 +91300,10 @@ async function executeWriteHallucinationEvidence(args2, directory) {
91227
91300
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
91228
91301
  }, null, 2);
91229
91302
  }
91230
- const evidenceDir = path108.dirname(validatedPath);
91303
+ const evidenceDir = path112.dirname(validatedPath);
91231
91304
  try {
91232
91305
  await fs88.promises.mkdir(evidenceDir, { recursive: true });
91233
- const tempPath = path108.join(evidenceDir, `.${filename}.tmp`);
91306
+ const tempPath = path112.join(evidenceDir, `.${filename}.tmp`);
91234
91307
  await fs88.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
91235
91308
  await fs88.promises.rename(tempPath, validatedPath);
91236
91309
  return JSON.stringify({
@@ -91279,7 +91352,7 @@ init_zod();
91279
91352
  init_utils2();
91280
91353
  init_create_tool();
91281
91354
  import fs89 from "node:fs";
91282
- import path109 from "node:path";
91355
+ import path113 from "node:path";
91283
91356
  function normalizeVerdict3(verdict) {
91284
91357
  switch (verdict) {
91285
91358
  case "PASS":
@@ -91353,7 +91426,7 @@ async function executeWriteMutationEvidence(args2, directory) {
91353
91426
  entries: [evidenceEntry]
91354
91427
  };
91355
91428
  const filename = "mutation-gate.json";
91356
- const relativePath = path109.join("evidence", String(phase), filename);
91429
+ const relativePath = path113.join("evidence", String(phase), filename);
91357
91430
  let validatedPath;
91358
91431
  try {
91359
91432
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -91364,10 +91437,10 @@ async function executeWriteMutationEvidence(args2, directory) {
91364
91437
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
91365
91438
  }, null, 2);
91366
91439
  }
91367
- const evidenceDir = path109.dirname(validatedPath);
91440
+ const evidenceDir = path113.dirname(validatedPath);
91368
91441
  try {
91369
91442
  await fs89.promises.mkdir(evidenceDir, { recursive: true });
91370
- const tempPath = path109.join(evidenceDir, `.${filename}.tmp`);
91443
+ const tempPath = path113.join(evidenceDir, `.${filename}.tmp`);
91371
91444
  await fs89.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
91372
91445
  await fs89.promises.rename(tempPath, validatedPath);
91373
91446
  return JSON.stringify({
@@ -91661,7 +91734,7 @@ async function initializeOpenCodeSwarm(ctx) {
91661
91734
  const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
91662
91735
  preflightTriggerManager = new PTM(automationConfig);
91663
91736
  const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
91664
- const swarmDir = path110.resolve(ctx.directory, ".swarm");
91737
+ const swarmDir = path114.resolve(ctx.directory, ".swarm");
91665
91738
  statusArtifact = new ASA(swarmDir);
91666
91739
  statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
91667
91740
  if (automationConfig.capabilities?.evidence_auto_summaries === true) {