opencode-swarm 7.1.0 → 7.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -33,7 +33,7 @@ var package_default;
33
33
  var init_package = __esm(() => {
34
34
  package_default = {
35
35
  name: "opencode-swarm",
36
- version: "7.1.0",
36
+ version: "7.2.0",
37
37
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
38
38
  main: "dist/index.js",
39
39
  types: "dist/index.d.ts",
@@ -15873,8 +15873,11 @@ var init_errors3 = __esm(() => {
15873
15873
  });
15874
15874
 
15875
15875
  // src/utils/logger.ts
15876
+ function isDebug() {
15877
+ return process.env.OPENCODE_SWARM_DEBUG === "1";
15878
+ }
15876
15879
  function log(message, data) {
15877
- if (!DEBUG)
15880
+ if (!isDebug())
15878
15881
  return;
15879
15882
  const timestamp = new Date().toISOString();
15880
15883
  if (data !== undefined) {
@@ -15884,7 +15887,7 @@ function log(message, data) {
15884
15887
  }
15885
15888
  }
15886
15889
  function warn(message, data) {
15887
- if (!DEBUG)
15890
+ if (!isDebug())
15888
15891
  return;
15889
15892
  const timestamp = new Date().toISOString();
15890
15893
  if (data !== undefined) {
@@ -15901,10 +15904,6 @@ function error48(message, data) {
15901
15904
  console.error(`[opencode-swarm ${timestamp}] ERROR: ${message}`);
15902
15905
  }
15903
15906
  }
15904
- var DEBUG;
15905
- var init_logger = __esm(() => {
15906
- DEBUG = process.env.OPENCODE_SWARM_DEBUG === "1";
15907
- });
15908
15907
 
15909
15908
  // src/utils/regex.ts
15910
15909
  function escapeRegex2(s) {
@@ -15918,7 +15917,6 @@ function simpleGlobToRegex(pattern, flags2 = "i") {
15918
15917
  // src/utils/index.ts
15919
15918
  var init_utils = __esm(() => {
15920
15919
  init_errors3();
15921
- init_logger();
15922
15920
  });
15923
15921
 
15924
15922
  // src/utils/bun-compat.ts
@@ -25138,7 +25136,6 @@ var init_guardrails = __esm(() => {
25138
25136
  init_telemetry();
25139
25137
  init_utils();
25140
25138
  init_bun_compat();
25141
- init_logger();
25142
25139
  init_conflict_resolution();
25143
25140
  init_delegation_gate();
25144
25141
  init_loop_detector();
@@ -26098,7 +26095,6 @@ var init_delegation_gate = __esm(() => {
26098
26095
  init_schema();
26099
26096
  init_state();
26100
26097
  init_telemetry();
26101
- init_logger();
26102
26098
  init_guardrails();
26103
26099
  init_normalize_tool_name();
26104
26100
  init_utils2();
@@ -40586,9 +40582,7 @@ function resetToRemoteBranch(cwd, options) {
40586
40582
  }
40587
40583
  }
40588
40584
  var GIT_TIMEOUT_MS2 = 30000;
40589
- var init_branch = __esm(() => {
40590
- init_logger();
40591
- });
40585
+ var init_branch = () => {};
40592
40586
 
40593
40587
  // src/hooks/knowledge-store.ts
40594
40588
  import { existsSync as existsSync9 } from "node:fs";
@@ -40915,7 +40909,7 @@ async function recordLessonsShown(directory, lessonIds, currentPhase) {
40915
40909
  await mkdir4(path16.dirname(shownFile), { recursive: true });
40916
40910
  await writeFile4(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
40917
40911
  } catch {
40918
- console.warn("[swarm] Knowledge: failed to record shown lessons");
40912
+ warn("[swarm] Knowledge: failed to record shown lessons");
40919
40913
  }
40920
40914
  }
40921
40915
  async function readMergedKnowledge(directory, config3, context) {
@@ -41065,7 +41059,7 @@ async function updateRetrievalOutcome(directory, phaseInfo, phaseSucceeded) {
41065
41059
  delete shownData[phaseInfo];
41066
41060
  await writeFile4(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
41067
41061
  } catch {
41068
- console.warn("[swarm] Knowledge: failed to update retrieval outcomes");
41062
+ warn("[swarm] Knowledge: failed to update retrieval outcomes");
41069
41063
  }
41070
41064
  }
41071
41065
  var JACCARD_THRESHOLD = 0.6, HIVE_TIER_BOOST = 0.05, SAME_PROJECT_PENALTY = -0.05;
@@ -41216,12 +41210,12 @@ function validateLesson(candidate, existingLessons, meta3) {
41216
41210
  }
41217
41211
  async function quarantineEntry(directory, entryId, reason, reportedBy) {
41218
41212
  if (!directory || directory.includes("..")) {
41219
- console.warn("[knowledge-validator] quarantineEntry: directory traversal attempt blocked");
41213
+ warn("[knowledge-validator] quarantineEntry: directory traversal attempt blocked");
41220
41214
  return;
41221
41215
  }
41222
41216
  if (!entryId || entryId.includes("\x00") || entryId.includes(`
41223
41217
  `)) {
41224
- console.warn("[knowledge-validator] quarantineEntry: invalid entryId rejected");
41218
+ warn("[knowledge-validator] quarantineEntry: invalid entryId rejected");
41225
41219
  return;
41226
41220
  }
41227
41221
  const validReportedBy = ["architect", "user", "auto"];
@@ -41281,12 +41275,12 @@ async function quarantineEntry(directory, entryId, reason, reportedBy) {
41281
41275
  }
41282
41276
  async function restoreEntry(directory, entryId) {
41283
41277
  if (!directory || directory.includes("..")) {
41284
- console.warn("[knowledge-validator] restoreEntry: directory traversal attempt blocked");
41278
+ warn("[knowledge-validator] restoreEntry: directory traversal attempt blocked");
41285
41279
  return;
41286
41280
  }
41287
41281
  if (!entryId || entryId.includes("\x00") || entryId.includes(`
41288
41282
  `)) {
41289
- console.warn("[knowledge-validator] restoreEntry: invalid entryId rejected");
41283
+ warn("[knowledge-validator] restoreEntry: invalid entryId rejected");
41290
41284
  return;
41291
41285
  }
41292
41286
  const knowledgePath = path17.join(directory, ".swarm", "knowledge.jsonl");
@@ -43245,9 +43239,7 @@ async function readCuratorSummary(directory) {
43245
43239
  }
43246
43240
  return parsed;
43247
43241
  } catch {
43248
- if (process.env.DEBUG_SWARM) {
43249
- console.warn("Failed to parse curator-summary.json: invalid JSON");
43250
- }
43242
+ warn("Failed to parse curator-summary.json: invalid JSON");
43251
43243
  return null;
43252
43244
  }
43253
43245
  }
@@ -43280,9 +43272,7 @@ function filterPhaseEvents(eventsJsonl, phase, sinceTimestamp) {
43280
43272
  }
43281
43273
  }
43282
43274
  } catch {
43283
- if (process.env.DEBUG_SWARM) {
43284
- console.warn("filterPhaseEvents: skipping malformed line");
43285
- }
43275
+ warn("filterPhaseEvents: skipping malformed line");
43286
43276
  }
43287
43277
  }
43288
43278
  return filtered;
@@ -43831,7 +43821,6 @@ var init_curator = __esm(() => {
43831
43821
  init_event_bus();
43832
43822
  init_manager();
43833
43823
  init_bun_compat();
43834
- init_logger();
43835
43824
  init_knowledge_store();
43836
43825
  init_knowledge_validator();
43837
43826
  init_utils2();
@@ -49256,7 +49245,6 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
49256
49245
  await writeFile6(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
49257
49246
  }
49258
49247
  var init_knowledge_migrator = __esm(() => {
49259
- init_logger();
49260
49248
  init_knowledge_store();
49261
49249
  init_knowledge_validator();
49262
49250
  });
@@ -60219,13 +60207,13 @@ __export(exports_review_receipt, {
60219
60207
  buildApprovedReceipt: () => buildApprovedReceipt
60220
60208
  });
60221
60209
  import * as crypto5 from "node:crypto";
60222
- import * as fs34 from "node:fs";
60223
- import * as path48 from "node:path";
60210
+ import * as fs35 from "node:fs";
60211
+ import * as path49 from "node:path";
60224
60212
  function resolveReceiptsDir(directory) {
60225
- return path48.join(directory, ".swarm", "review-receipts");
60213
+ return path49.join(directory, ".swarm", "review-receipts");
60226
60214
  }
60227
60215
  function resolveReceiptIndexPath(directory) {
60228
- return path48.join(resolveReceiptsDir(directory), "index.json");
60216
+ return path49.join(resolveReceiptsDir(directory), "index.json");
60229
60217
  }
60230
60218
  function buildReceiptFilename(id, date9) {
60231
60219
  const dateStr = date9.toISOString().slice(0, 10);
@@ -60248,11 +60236,11 @@ function isScopeStale(receipt, currentContent) {
60248
60236
  }
60249
60237
  async function readReceiptIndex(directory) {
60250
60238
  const indexPath = resolveReceiptIndexPath(directory);
60251
- if (!fs34.existsSync(indexPath)) {
60239
+ if (!fs35.existsSync(indexPath)) {
60252
60240
  return { schema_version: 1, entries: [] };
60253
60241
  }
60254
60242
  try {
60255
- const content = await fs34.promises.readFile(indexPath, "utf-8");
60243
+ const content = await fs35.promises.readFile(indexPath, "utf-8");
60256
60244
  const parsed = JSON.parse(content);
60257
60245
  if (parsed.schema_version !== 1 || !Array.isArray(parsed.entries)) {
60258
60246
  return { schema_version: 1, entries: [] };
@@ -60264,21 +60252,21 @@ async function readReceiptIndex(directory) {
60264
60252
  }
60265
60253
  async function writeReceiptIndex(directory, index) {
60266
60254
  const indexPath = resolveReceiptIndexPath(directory);
60267
- const dir = path48.dirname(indexPath);
60268
- await fs34.promises.mkdir(dir, { recursive: true });
60255
+ const dir = path49.dirname(indexPath);
60256
+ await fs35.promises.mkdir(dir, { recursive: true });
60269
60257
  const tmpPath = `${indexPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
60270
- await fs34.promises.writeFile(tmpPath, JSON.stringify(index, null, 2), "utf-8");
60271
- fs34.renameSync(tmpPath, indexPath);
60258
+ await fs35.promises.writeFile(tmpPath, JSON.stringify(index, null, 2), "utf-8");
60259
+ fs35.renameSync(tmpPath, indexPath);
60272
60260
  }
60273
60261
  async function persistReviewReceipt(directory, receipt) {
60274
60262
  const receiptsDir = resolveReceiptsDir(directory);
60275
- await fs34.promises.mkdir(receiptsDir, { recursive: true });
60263
+ await fs35.promises.mkdir(receiptsDir, { recursive: true });
60276
60264
  const now = new Date(receipt.reviewed_at);
60277
60265
  const filename = buildReceiptFilename(receipt.id, now);
60278
- const receiptPath = path48.join(receiptsDir, filename);
60266
+ const receiptPath = path49.join(receiptsDir, filename);
60279
60267
  const tmpPath = `${receiptPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
60280
- await fs34.promises.writeFile(tmpPath, JSON.stringify(receipt, null, 2), "utf-8");
60281
- fs34.renameSync(tmpPath, receiptPath);
60268
+ await fs35.promises.writeFile(tmpPath, JSON.stringify(receipt, null, 2), "utf-8");
60269
+ fs35.renameSync(tmpPath, receiptPath);
60282
60270
  const index = await readReceiptIndex(directory);
60283
60271
  const entry = {
60284
60272
  id: receipt.id,
@@ -60297,9 +60285,9 @@ async function readReceiptById(directory, receiptId) {
60297
60285
  const entry = index.entries.find((e) => e.id === receiptId);
60298
60286
  if (!entry)
60299
60287
  return null;
60300
- const receiptPath = path48.join(resolveReceiptsDir(directory), entry.filename);
60288
+ const receiptPath = path49.join(resolveReceiptsDir(directory), entry.filename);
60301
60289
  try {
60302
- const content = await fs34.promises.readFile(receiptPath, "utf-8");
60290
+ const content = await fs35.promises.readFile(receiptPath, "utf-8");
60303
60291
  return JSON.parse(content);
60304
60292
  } catch {
60305
60293
  return null;
@@ -60310,9 +60298,9 @@ async function readReceiptsByScopeHash(directory, scopeHash) {
60310
60298
  const matching = index.entries.filter((e) => e.scope_hash === scopeHash).sort((a, b) => b.reviewed_at.localeCompare(a.reviewed_at));
60311
60299
  const receipts = [];
60312
60300
  for (const entry of matching) {
60313
- const receiptPath = path48.join(resolveReceiptsDir(directory), entry.filename);
60301
+ const receiptPath = path49.join(resolveReceiptsDir(directory), entry.filename);
60314
60302
  try {
60315
- const content = await fs34.promises.readFile(receiptPath, "utf-8");
60303
+ const content = await fs35.promises.readFile(receiptPath, "utf-8");
60316
60304
  receipts.push(JSON.parse(content));
60317
60305
  } catch {}
60318
60306
  }
@@ -60323,9 +60311,9 @@ async function readAllReceipts(directory) {
60323
60311
  const sorted = [...index.entries].sort((a, b) => b.reviewed_at.localeCompare(a.reviewed_at));
60324
60312
  const receipts = [];
60325
60313
  for (const entry of sorted) {
60326
- const receiptPath = path48.join(resolveReceiptsDir(directory), entry.filename);
60314
+ const receiptPath = path49.join(resolveReceiptsDir(directory), entry.filename);
60327
60315
  try {
60328
- const content = await fs34.promises.readFile(receiptPath, "utf-8");
60316
+ const content = await fs35.promises.readFile(receiptPath, "utf-8");
60329
60317
  receipts.push(JSON.parse(content));
60330
60318
  } catch {}
60331
60319
  }
@@ -60446,7 +60434,6 @@ var init_preflight_integration = __esm(() => {
60446
60434
  init_status_artifact();
60447
60435
  init_trigger();
60448
60436
  init_preflight_service();
60449
- init_logger();
60450
60437
  });
60451
60438
 
60452
60439
  // node_modules/web-tree-sitter/tree-sitter.js
@@ -61911,11 +61898,11 @@ ${JSON.stringify(symbolNames, null, 2)}`);
61911
61898
  throw toThrow;
61912
61899
  }, "quit_");
61913
61900
  var scriptDirectory = "";
61914
- function locateFile(path59) {
61901
+ function locateFile(path60) {
61915
61902
  if (Module["locateFile"]) {
61916
- return Module["locateFile"](path59, scriptDirectory);
61903
+ return Module["locateFile"](path60, scriptDirectory);
61917
61904
  }
61918
- return scriptDirectory + path59;
61905
+ return scriptDirectory + path60;
61919
61906
  }
61920
61907
  __name(locateFile, "locateFile");
61921
61908
  var readAsync, readBinary;
@@ -63664,13 +63651,13 @@ __export(exports_runtime, {
63664
63651
  getInitializedLanguages: () => getInitializedLanguages,
63665
63652
  clearParserCache: () => clearParserCache
63666
63653
  });
63667
- import * as path59 from "node:path";
63654
+ import * as path60 from "node:path";
63668
63655
  import { fileURLToPath as fileURLToPath2 } from "node:url";
63669
63656
  async function initTreeSitter() {
63670
63657
  if (treeSitterInitialized) {
63671
63658
  return;
63672
63659
  }
63673
- const thisDir = path59.dirname(fileURLToPath2(import.meta.url));
63660
+ const thisDir = path60.dirname(fileURLToPath2(import.meta.url));
63674
63661
  const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/lang");
63675
63662
  if (isSource) {
63676
63663
  await Parser.init();
@@ -63678,7 +63665,7 @@ async function initTreeSitter() {
63678
63665
  const grammarsDir = getGrammarsDirAbsolute();
63679
63666
  await Parser.init({
63680
63667
  locateFile(scriptName) {
63681
- return path59.join(grammarsDir, scriptName);
63668
+ return path60.join(grammarsDir, scriptName);
63682
63669
  }
63683
63670
  });
63684
63671
  }
@@ -63699,11 +63686,11 @@ function getWasmFileName(languageId) {
63699
63686
  return `tree-sitter-${sanitized}.wasm`;
63700
63687
  }
63701
63688
  function getGrammarsDirAbsolute() {
63702
- const thisDir = path59.dirname(fileURLToPath2(import.meta.url));
63689
+ const thisDir = path60.dirname(fileURLToPath2(import.meta.url));
63703
63690
  const normalized = thisDir.replace(/\\/g, "/");
63704
63691
  const isSource = normalized.endsWith("/src/lang");
63705
63692
  const isCliBundle = normalized.endsWith("/cli");
63706
- return isSource ? path59.join(thisDir, "grammars") : isCliBundle ? path59.join(thisDir, "..", "lang", "grammars") : path59.join(thisDir, "lang", "grammars");
63693
+ return isSource ? path60.join(thisDir, "grammars") : isCliBundle ? path60.join(thisDir, "..", "lang", "grammars") : path60.join(thisDir, "lang", "grammars");
63707
63694
  }
63708
63695
  async function loadGrammar(languageId) {
63709
63696
  if (typeof languageId !== "string" || languageId.length > 100) {
@@ -63719,9 +63706,9 @@ async function loadGrammar(languageId) {
63719
63706
  await initTreeSitter();
63720
63707
  const parser = new Parser;
63721
63708
  const wasmFileName = getWasmFileName(normalizedId);
63722
- const wasmPath = path59.join(getGrammarsDirAbsolute(), wasmFileName);
63723
- const { existsSync: existsSync30 } = await import("node:fs");
63724
- if (!existsSync30(wasmPath)) {
63709
+ const wasmPath = path60.join(getGrammarsDirAbsolute(), wasmFileName);
63710
+ const { existsSync: existsSync31 } = await import("node:fs");
63711
+ if (!existsSync31(wasmPath)) {
63725
63712
  throw new Error(`Grammar file not found for ${languageId}: ${wasmPath}
63726
63713
  Make sure to run 'bun run build' to copy grammar files to dist/lang/grammars/`);
63727
63714
  }
@@ -63754,7 +63741,7 @@ async function isGrammarAvailable(languageId) {
63754
63741
  }
63755
63742
  try {
63756
63743
  const wasmFileName = getWasmFileName(normalizedId);
63757
- const wasmPath = path59.join(getGrammarsDirAbsolute(), wasmFileName);
63744
+ const wasmPath = path60.join(getGrammarsDirAbsolute(), wasmFileName);
63758
63745
  const { statSync: statSync19 } = await import("node:fs");
63759
63746
  statSync19(wasmPath);
63760
63747
  return true;
@@ -63811,15 +63798,15 @@ __export(exports_doc_scan, {
63811
63798
  doc_extract: () => doc_extract
63812
63799
  });
63813
63800
  import * as crypto7 from "node:crypto";
63814
- import * as fs43 from "node:fs";
63801
+ import * as fs44 from "node:fs";
63815
63802
  import { mkdir as mkdir10, readFile as readFile10, writeFile as writeFile9 } from "node:fs/promises";
63816
- import * as path61 from "node:path";
63803
+ import * as path62 from "node:path";
63817
63804
  function normalizeSeparators(filePath) {
63818
63805
  return filePath.replace(/\\/g, "/");
63819
63806
  }
63820
63807
  function matchesDocPattern(filePath, patterns) {
63821
63808
  const normalizedPath = normalizeSeparators(filePath);
63822
- const basename9 = path61.basename(filePath);
63809
+ const basename9 = path62.basename(filePath);
63823
63810
  for (const pattern of patterns) {
63824
63811
  if (!pattern.includes("/") && !pattern.includes("\\")) {
63825
63812
  if (basename9 === pattern) {
@@ -63875,7 +63862,7 @@ function stripMarkdown(text) {
63875
63862
  return text.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/^\s*[-*•]\s+/gm, "").replace(/^\s*\d+\.\s+/gm, "").trim();
63876
63863
  }
63877
63864
  async function scanDocIndex(directory) {
63878
- const manifestPath = path61.join(directory, ".swarm", "doc-manifest.json");
63865
+ const manifestPath = path62.join(directory, ".swarm", "doc-manifest.json");
63879
63866
  const defaultPatterns = DocsConfigSchema.parse({}).doc_patterns;
63880
63867
  const extraPatterns = [
63881
63868
  "ARCHITECTURE.md",
@@ -63892,8 +63879,8 @@ async function scanDocIndex(directory) {
63892
63879
  let cacheValid = true;
63893
63880
  for (const file3 of existingManifest.files) {
63894
63881
  try {
63895
- const fullPath = path61.join(directory, file3.path);
63896
- const stat5 = fs43.statSync(fullPath);
63882
+ const fullPath = path62.join(directory, file3.path);
63883
+ const stat5 = fs44.statSync(fullPath);
63897
63884
  if (stat5.mtimeMs > file3.mtime) {
63898
63885
  cacheValid = false;
63899
63886
  break;
@@ -63911,7 +63898,7 @@ async function scanDocIndex(directory) {
63911
63898
  const discoveredFiles = [];
63912
63899
  let rawEntries;
63913
63900
  try {
63914
- rawEntries = fs43.readdirSync(directory, { recursive: true });
63901
+ rawEntries = fs44.readdirSync(directory, { recursive: true });
63915
63902
  } catch {
63916
63903
  const manifest2 = {
63917
63904
  schema_version: 1,
@@ -63922,10 +63909,10 @@ async function scanDocIndex(directory) {
63922
63909
  }
63923
63910
  const entries = rawEntries.filter((e) => typeof e === "string");
63924
63911
  for (const entry of entries) {
63925
- const fullPath = path61.join(directory, entry);
63912
+ const fullPath = path62.join(directory, entry);
63926
63913
  let stat5;
63927
63914
  try {
63928
- stat5 = fs43.statSync(fullPath);
63915
+ stat5 = fs44.statSync(fullPath);
63929
63916
  } catch {
63930
63917
  continue;
63931
63918
  }
@@ -63954,11 +63941,11 @@ async function scanDocIndex(directory) {
63954
63941
  }
63955
63942
  let content;
63956
63943
  try {
63957
- content = fs43.readFileSync(fullPath, "utf-8");
63944
+ content = fs44.readFileSync(fullPath, "utf-8");
63958
63945
  } catch {
63959
63946
  continue;
63960
63947
  }
63961
- const { title, summary } = extractTitleAndSummary(content, path61.basename(entry));
63948
+ const { title, summary } = extractTitleAndSummary(content, path62.basename(entry));
63962
63949
  const lineCount = content.split(`
63963
63950
  `).length;
63964
63951
  discoveredFiles.push({
@@ -63984,7 +63971,7 @@ async function scanDocIndex(directory) {
63984
63971
  files: discoveredFiles
63985
63972
  };
63986
63973
  try {
63987
- await mkdir10(path61.dirname(manifestPath), { recursive: true });
63974
+ await mkdir10(path62.dirname(manifestPath), { recursive: true });
63988
63975
  await writeFile9(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
63989
63976
  } catch {}
63990
63977
  return { manifest, cached: false };
@@ -64023,7 +64010,7 @@ function extractConstraintsFromContent(content) {
64023
64010
  return constraints;
64024
64011
  }
64025
64012
  async function extractDocConstraints(directory, taskFiles, taskDescription) {
64026
- const manifestPath = path61.join(directory, ".swarm", "doc-manifest.json");
64013
+ const manifestPath = path62.join(directory, ".swarm", "doc-manifest.json");
64027
64014
  let manifest;
64028
64015
  try {
64029
64016
  const content = await readFile10(manifestPath, "utf-8");
@@ -64049,7 +64036,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
64049
64036
  }
64050
64037
  let fullContent;
64051
64038
  try {
64052
- fullContent = await readFile10(path61.join(directory, docFile.path), "utf-8");
64039
+ fullContent = await readFile10(path62.join(directory, docFile.path), "utf-8");
64053
64040
  } catch {
64054
64041
  skippedCount++;
64055
64042
  continue;
@@ -64072,7 +64059,7 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
64072
64059
  tier: "swarm",
64073
64060
  lesson: constraint,
64074
64061
  category: "architecture",
64075
- tags: ["doc-scan", path61.basename(docFile.path)],
64062
+ tags: ["doc-scan", path62.basename(docFile.path)],
64076
64063
  scope: "global",
64077
64064
  confidence: 0.5,
64078
64065
  status: "candidate",
@@ -64145,9 +64132,9 @@ var init_doc_scan = __esm(() => {
64145
64132
  }
64146
64133
  } catch {}
64147
64134
  if (force) {
64148
- const manifestPath = path61.join(directory, ".swarm", "doc-manifest.json");
64135
+ const manifestPath = path62.join(directory, ".swarm", "doc-manifest.json");
64149
64136
  try {
64150
- fs43.unlinkSync(manifestPath);
64137
+ fs44.unlinkSync(manifestPath);
64151
64138
  } catch {}
64152
64139
  }
64153
64140
  const { manifest, cached: cached3 } = await scanDocIndex(directory);
@@ -64335,11 +64322,11 @@ __export(exports_curator_drift, {
64335
64322
  readPriorDriftReports: () => readPriorDriftReports,
64336
64323
  buildDriftInjectionText: () => buildDriftInjectionText
64337
64324
  });
64338
- import * as fs46 from "node:fs";
64339
- import * as path64 from "node:path";
64325
+ import * as fs47 from "node:fs";
64326
+ import * as path65 from "node:path";
64340
64327
  async function readPriorDriftReports(directory) {
64341
- const swarmDir = path64.join(directory, ".swarm");
64342
- const entries = await fs46.promises.readdir(swarmDir).catch(() => null);
64328
+ const swarmDir = path65.join(directory, ".swarm");
64329
+ const entries = await fs47.promises.readdir(swarmDir).catch(() => null);
64343
64330
  if (entries === null)
64344
64331
  return [];
64345
64332
  const reportFiles = entries.filter((name2) => name2.startsWith(DRIFT_REPORT_PREFIX) && name2.endsWith(".json")).sort();
@@ -64365,10 +64352,10 @@ async function readPriorDriftReports(directory) {
64365
64352
  async function writeDriftReport(directory, report) {
64366
64353
  const filename = `${DRIFT_REPORT_PREFIX}${report.phase}.json`;
64367
64354
  const filePath = validateSwarmPath(directory, filename);
64368
- const swarmDir = path64.dirname(filePath);
64369
- await fs46.promises.mkdir(swarmDir, { recursive: true });
64355
+ const swarmDir = path65.dirname(filePath);
64356
+ await fs47.promises.mkdir(swarmDir, { recursive: true });
64370
64357
  try {
64371
- await fs46.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
64358
+ await fs47.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
64372
64359
  } catch (err2) {
64373
64360
  throw new Error(`[curator-drift] Failed to write drift report to ${filePath}: ${String(err2)}`);
64374
64361
  }
@@ -64493,15 +64480,13 @@ function buildDriftInjectionText(report, maxChars) {
64493
64480
  var DRIFT_REPORT_PREFIX = "drift-report-phase-";
64494
64481
  var init_curator_drift = __esm(() => {
64495
64482
  init_event_bus();
64496
- init_logger();
64497
64483
  init_utils2();
64498
64484
  });
64499
64485
 
64500
64486
  // src/index.ts
64501
64487
  init_package();
64502
64488
  init_agents2();
64503
- import * as fs87 from "node:fs";
64504
- import * as path107 from "node:path";
64489
+ import * as path108 from "node:path";
64505
64490
 
64506
64491
  // src/background/index.ts
64507
64492
  init_event_bus();
@@ -64920,6 +64905,64 @@ function createSwarmCommandHandler(directory, agents) {
64920
64905
  // src/index.ts
64921
64906
  init_config();
64922
64907
  init_constants();
64908
+
64909
+ // src/config/project-init.ts
64910
+ init_constants();
64911
+ import * as fs31 from "node:fs";
64912
+ import * as path48 from "node:path";
64913
+ var STARTER_CONTENT = `{}
64914
+ `;
64915
+ function writeProjectConfigIfNew(directory, quiet = false) {
64916
+ try {
64917
+ const opencodeDir = path48.join(directory, ".opencode");
64918
+ const dest = path48.join(opencodeDir, "opencode-swarm.json");
64919
+ try {
64920
+ const stat4 = fs31.lstatSync(opencodeDir);
64921
+ if (stat4.isSymbolicLink())
64922
+ return;
64923
+ } catch (err2) {
64924
+ if (err2.code !== "ENOENT")
64925
+ return;
64926
+ }
64927
+ if (!fs31.existsSync(opencodeDir)) {
64928
+ fs31.mkdirSync(opencodeDir, { recursive: true });
64929
+ }
64930
+ try {
64931
+ fs31.writeFileSync(dest, STARTER_CONTENT, {
64932
+ encoding: "utf-8",
64933
+ flag: "wx"
64934
+ });
64935
+ if (!quiet) {
64936
+ console.warn("[opencode-swarm] Created .opencode/opencode-swarm.json — " + "edit it to customize agent LLMs for this project, or commit it to share settings with your team");
64937
+ }
64938
+ } catch (_writeErr) {}
64939
+ } catch {}
64940
+ }
64941
+ function writeSwarmConfigExampleIfNew(projectDirectory) {
64942
+ try {
64943
+ const swarmDir = path48.join(projectDirectory, ".swarm");
64944
+ const dest = path48.join(swarmDir, "config.example.json");
64945
+ if (fs31.existsSync(dest))
64946
+ return;
64947
+ if (!fs31.existsSync(swarmDir)) {
64948
+ fs31.mkdirSync(swarmDir, { recursive: true });
64949
+ }
64950
+ const example = {
64951
+ agents: Object.fromEntries(Object.entries(DEFAULT_MODELS).filter(([name2]) => name2 !== "default").map(([name2, model]) => [
64952
+ name2,
64953
+ {
64954
+ model,
64955
+ fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
64956
+ }
64957
+ ])),
64958
+ max_iterations: 5
64959
+ };
64960
+ fs31.writeFileSync(dest, `${JSON.stringify(example, null, 2)}
64961
+ `, "utf-8");
64962
+ } catch {}
64963
+ }
64964
+
64965
+ // src/index.ts
64923
64966
  init_schema();
64924
64967
 
64925
64968
  // src/hooks/agent-activity.ts
@@ -64997,11 +65040,11 @@ async function doFlush(directory) {
64997
65040
  const activitySection = renderActivitySection();
64998
65041
  const updated = replaceOrAppendSection(existing, "## Agent Activity", activitySection);
64999
65042
  const flushedCount = swarmState.pendingEvents;
65000
- const path48 = nodePath2.join(directory, ".swarm", "context.md");
65001
- const tempPath = `${path48}.tmp`;
65043
+ const path49 = nodePath2.join(directory, ".swarm", "context.md");
65044
+ const tempPath = `${path49}.tmp`;
65002
65045
  try {
65003
65046
  await bunWrite(tempPath, updated);
65004
- renameSync11(tempPath, path48);
65047
+ renameSync11(tempPath, path49);
65005
65048
  } catch (writeError) {
65006
65049
  try {
65007
65050
  unlinkSync8(tempPath);
@@ -65051,8 +65094,8 @@ ${content.substring(endIndex + 1)}`;
65051
65094
  // src/hooks/compaction-customizer.ts
65052
65095
  init_manager();
65053
65096
  init_utils2();
65054
- import * as fs31 from "node:fs";
65055
- import { join as join44 } from "node:path";
65097
+ import * as fs32 from "node:fs";
65098
+ import { join as join45 } from "node:path";
65056
65099
  function createCompactionCustomizerHook(config3, directory) {
65057
65100
  const enabled = config3.hooks?.compaction !== false;
65058
65101
  if (!enabled) {
@@ -65097,8 +65140,8 @@ function createCompactionCustomizerHook(config3, directory) {
65097
65140
  }
65098
65141
  }
65099
65142
  try {
65100
- const summariesDir = join44(directory, ".swarm", "summaries");
65101
- const files = await fs31.promises.readdir(summariesDir);
65143
+ const summariesDir = join45(directory, ".swarm", "summaries");
65144
+ const files = await fs32.promises.readdir(summariesDir);
65102
65145
  if (files.length > 0) {
65103
65146
  const count = files.length;
65104
65147
  output.context.push(`[CONTEXT OPTIMIZATION] Tool outputs from earlier in this session have been stored to disk. When compacting, replace any large tool output blocks (bash, test_runner, lint, diff results) with a one-line reference: "[Output stored — use /swarm retrieve to access full content]". Preserve the tool name, exit status, and any error messages. Discard raw output lines.`);
@@ -65584,7 +65627,7 @@ init_delegation_gate();
65584
65627
 
65585
65628
  // src/hooks/delegation-sanitizer.ts
65586
65629
  init_utils2();
65587
- import * as fs32 from "node:fs";
65630
+ import * as fs33 from "node:fs";
65588
65631
  var SANITIZATION_PATTERNS = [
65589
65632
  /\b\d+(st|nd|rd|th)\s+(attempt|try|time)\b/gi,
65590
65633
  /\b(5th|fifth|final|last)\s+attempt\b/gi,
@@ -65655,7 +65698,7 @@ function createDelegationSanitizerHook(directory) {
65655
65698
  stripped_patterns: result.stripped,
65656
65699
  timestamp: new Date().toISOString()
65657
65700
  };
65658
- fs32.appendFileSync(eventsPath, `${JSON.stringify(event)}
65701
+ fs33.appendFileSync(eventsPath, `${JSON.stringify(event)}
65659
65702
  `, "utf-8");
65660
65703
  } catch {}
65661
65704
  }
@@ -65721,9 +65764,8 @@ init_schema();
65721
65764
  init_file_locks();
65722
65765
  init_state();
65723
65766
  init_telemetry();
65724
- init_logger();
65725
65767
  init_utils2();
65726
- import * as fs33 from "node:fs";
65768
+ import * as fs34 from "node:fs";
65727
65769
  var END_OF_SENTENCE_QUESTION_PATTERN = /\?\s*$/;
65728
65770
  var PHASE_COMPLETION_PATTERNS = [
65729
65771
  /Ready for Phase (?:\d+|\[?N\+1\]?)\??/i,
@@ -65917,7 +65959,7 @@ async function writeAutoOversightEvent(directory, architectOutput, criticVerdict
65917
65959
  }
65918
65960
  try {
65919
65961
  const eventsPath = validateSwarmPath(dir, "events.jsonl");
65920
- fs33.appendFileSync(eventsPath, `${JSON.stringify(event)}
65962
+ fs34.appendFileSync(eventsPath, `${JSON.stringify(event)}
65921
65963
  `, "utf-8");
65922
65964
  } catch (writeError) {
65923
65965
  error48(`[full-auto-intercept] Warning: failed to write auto_oversight event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
@@ -66229,7 +66271,7 @@ async function writeEscalationReport(directory, reason, architectOutput, interac
66229
66271
  if (currentPhase === undefined) {
66230
66272
  try {
66231
66273
  const planPath = validateSwarmPath(directory, "plan.json");
66232
- const planContent = fs33.readFileSync(planPath, "utf-8");
66274
+ const planContent = fs34.readFileSync(planPath, "utf-8");
66233
66275
  const plan = JSON.parse(planContent);
66234
66276
  const incompletePhases = plan.phases.filter((p) => p.status !== "complete").sort((a, b) => b.id - a.id);
66235
66277
  currentPhase = incompletePhases[0]?.id;
@@ -66268,7 +66310,7 @@ ${currentPhase !== undefined ? `- **Phase Status**: Pending completion` : ""}
66268
66310
  This escalation requires human intervention. The swarm has been paused.
66269
66311
  Please review the architect's output above and provide guidance.
66270
66312
  `;
66271
- fs33.writeFileSync(reportPath, reportContent, "utf-8");
66313
+ fs34.writeFileSync(reportPath, reportContent, "utf-8");
66272
66314
  log(`[full-auto-intercept] Escalation report written to: ${reportPath}`);
66273
66315
  } catch (error93) {
66274
66316
  error48(`[full-auto-intercept] Failed to write escalation report:`, error93 instanceof Error ? error93.message : String(error93));
@@ -66362,7 +66404,7 @@ init_schema();
66362
66404
  init_manager();
66363
66405
  init_curator();
66364
66406
  init_utils2();
66365
- import * as path49 from "node:path";
66407
+ import * as path50 from "node:path";
66366
66408
  function createPhaseMonitorHook(directory, preflightManager, curatorRunner, delegateFactory) {
66367
66409
  let lastKnownPhase = null;
66368
66410
  const handler = async (input, _output) => {
@@ -66382,9 +66424,9 @@ function createPhaseMonitorHook(directory, preflightManager, curatorRunner, dele
66382
66424
  const llmDelegate = delegateFactory?.(sessionId);
66383
66425
  const initResult = await runner(directory, curatorConfig, llmDelegate);
66384
66426
  if (initResult.briefing) {
66385
- const briefingPath = path49.join(directory, ".swarm", "curator-briefing.md");
66427
+ const briefingPath = path50.join(directory, ".swarm", "curator-briefing.md");
66386
66428
  const { mkdir: mkdir8, writeFile: writeFile8 } = await import("node:fs/promises");
66387
- await mkdir8(path49.dirname(briefingPath), { recursive: true });
66429
+ await mkdir8(path50.dirname(briefingPath), { recursive: true });
66388
66430
  await writeFile8(briefingPath, initResult.briefing, "utf-8");
66389
66431
  const { buildApprovedReceipt: buildApprovedReceipt2, persistReviewReceipt: persistReviewReceipt2 } = await Promise.resolve().then(() => (init_review_receipt(), exports_review_receipt));
66390
66432
  const initReceipt = buildApprovedReceipt2({
@@ -66509,17 +66551,16 @@ ${originalText}`;
66509
66551
  }
66510
66552
  // src/hooks/repo-graph-builder.ts
66511
66553
  init_constants();
66512
- import * as path52 from "node:path";
66554
+ import * as path53 from "node:path";
66513
66555
 
66514
66556
  // src/tools/repo-graph.ts
66515
66557
  init_utils2();
66516
- init_logger();
66517
66558
  init_path_security();
66518
66559
  import * as fsSync3 from "node:fs";
66519
- import { constants as constants4, existsSync as existsSync28, realpathSync as realpathSync6 } from "node:fs";
66560
+ import { constants as constants4, existsSync as existsSync29, realpathSync as realpathSync6 } from "node:fs";
66520
66561
  import * as fsPromises5 from "node:fs/promises";
66521
66562
  import * as os7 from "node:os";
66522
- import * as path51 from "node:path";
66563
+ import * as path52 from "node:path";
66523
66564
 
66524
66565
  // src/utils/timeout.ts
66525
66566
  async function withTimeout(promise3, ms, timeoutError) {
@@ -66550,8 +66591,8 @@ function yieldToEventLoop() {
66550
66591
  init_zod();
66551
66592
  init_create_tool();
66552
66593
  init_path_security();
66553
- import * as fs35 from "node:fs";
66554
- import * as path50 from "node:path";
66594
+ import * as fs36 from "node:fs";
66595
+ import * as path51 from "node:path";
66555
66596
  var MAX_FILE_SIZE_BYTES2 = 1024 * 1024;
66556
66597
  var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
66557
66598
  function containsWindowsAttacks(str) {
@@ -66568,11 +66609,11 @@ function containsWindowsAttacks(str) {
66568
66609
  }
66569
66610
  function isPathInWorkspace(filePath, workspace) {
66570
66611
  try {
66571
- const resolvedPath = path50.resolve(workspace, filePath);
66572
- const realWorkspace = fs35.realpathSync(workspace);
66573
- const realResolvedPath = fs35.realpathSync(resolvedPath);
66574
- const relativePath = path50.relative(realWorkspace, realResolvedPath);
66575
- if (relativePath.startsWith("..") || path50.isAbsolute(relativePath)) {
66612
+ const resolvedPath = path51.resolve(workspace, filePath);
66613
+ const realWorkspace = fs36.realpathSync(workspace);
66614
+ const realResolvedPath = fs36.realpathSync(resolvedPath);
66615
+ const relativePath = path51.relative(realWorkspace, realResolvedPath);
66616
+ if (relativePath.startsWith("..") || path51.isAbsolute(relativePath)) {
66576
66617
  return false;
66577
66618
  }
66578
66619
  return true;
@@ -66584,17 +66625,17 @@ function validatePathForRead(filePath, workspace) {
66584
66625
  return isPathInWorkspace(filePath, workspace);
66585
66626
  }
66586
66627
  function extractTSSymbols(filePath, cwd) {
66587
- const fullPath = path50.join(cwd, filePath);
66628
+ const fullPath = path51.join(cwd, filePath);
66588
66629
  if (!validatePathForRead(fullPath, cwd)) {
66589
66630
  return [];
66590
66631
  }
66591
66632
  let content;
66592
66633
  try {
66593
- const stats = fs35.statSync(fullPath);
66634
+ const stats = fs36.statSync(fullPath);
66594
66635
  if (stats.size > MAX_FILE_SIZE_BYTES2) {
66595
66636
  throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES2})`);
66596
66637
  }
66597
- content = fs35.readFileSync(fullPath, "utf-8");
66638
+ content = fs36.readFileSync(fullPath, "utf-8");
66598
66639
  } catch {
66599
66640
  return [];
66600
66641
  }
@@ -66736,17 +66777,17 @@ function extractTSSymbols(filePath, cwd) {
66736
66777
  });
66737
66778
  }
66738
66779
  function extractPythonSymbols(filePath, cwd) {
66739
- const fullPath = path50.join(cwd, filePath);
66780
+ const fullPath = path51.join(cwd, filePath);
66740
66781
  if (!validatePathForRead(fullPath, cwd)) {
66741
66782
  return [];
66742
66783
  }
66743
66784
  let content;
66744
66785
  try {
66745
- const stats = fs35.statSync(fullPath);
66786
+ const stats = fs36.statSync(fullPath);
66746
66787
  if (stats.size > MAX_FILE_SIZE_BYTES2) {
66747
66788
  throw new Error(`File too large: ${stats.size} bytes (max: ${MAX_FILE_SIZE_BYTES2})`);
66748
66789
  }
66749
- content = fs35.readFileSync(fullPath, "utf-8");
66790
+ content = fs36.readFileSync(fullPath, "utf-8");
66750
66791
  } catch {
66751
66792
  return [];
66752
66793
  }
@@ -66819,7 +66860,7 @@ var symbols = createSwarmTool({
66819
66860
  }, null, 2);
66820
66861
  }
66821
66862
  const cwd = directory;
66822
- const ext = path50.extname(file3);
66863
+ const ext = path51.extname(file3);
66823
66864
  if (containsControlChars(file3)) {
66824
66865
  return JSON.stringify({
66825
66866
  file: file3,
@@ -66883,7 +66924,7 @@ var symbols = createSwarmTool({
66883
66924
  var WINDOWS_RENAME_MAX_RETRIES2 = 3;
66884
66925
  var WINDOWS_RENAME_RETRY_DELAY_MS2 = 50;
66885
66926
  function normalizeGraphPath(filePath) {
66886
- return path51.normalize(filePath).replace(/\\/g, "/");
66927
+ return path52.normalize(filePath).replace(/\\/g, "/");
66887
66928
  }
66888
66929
  var REPO_GRAPH_FILENAME = "repo-graph.json";
66889
66930
  var GRAPH_SCHEMA_VERSION = "1.0.0";
@@ -66992,8 +67033,8 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
66992
67033
  }
66993
67034
  try {
66994
67035
  if (specifier.startsWith(".")) {
66995
- const sourceDir = path51.dirname(sourceFile);
66996
- let resolved = path51.resolve(sourceDir, specifier);
67036
+ const sourceDir = path52.dirname(sourceFile);
67037
+ let resolved = path52.resolve(sourceDir, specifier);
66997
67038
  let realResolved;
66998
67039
  try {
66999
67040
  realResolved = realpathSync6(resolved);
@@ -67004,9 +67045,9 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
67004
67045
  try {
67005
67046
  realRoot = realpathSync6(workspaceRoot);
67006
67047
  } catch {
67007
- realRoot = path51.normalize(workspaceRoot);
67048
+ realRoot = path52.normalize(workspaceRoot);
67008
67049
  }
67009
- if (!existsSync28(resolved)) {
67050
+ if (!existsSync29(resolved)) {
67010
67051
  const EXTENSIONS = [
67011
67052
  ".ts",
67012
67053
  ".tsx",
@@ -67020,7 +67061,7 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
67020
67061
  let found = null;
67021
67062
  for (const ext of EXTENSIONS) {
67022
67063
  const candidate = resolved + ext;
67023
- if (existsSync28(candidate)) {
67064
+ if (existsSync29(candidate)) {
67024
67065
  found = candidate;
67025
67066
  break;
67026
67067
  }
@@ -67036,9 +67077,9 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
67036
67077
  return null;
67037
67078
  }
67038
67079
  }
67039
- const normalizedResolved = path51.normalize(realResolved);
67040
- const normalizedRoot = path51.normalize(realRoot);
67041
- if (!normalizedResolved.startsWith(normalizedRoot + path51.sep) && normalizedResolved !== normalizedRoot) {
67080
+ const normalizedResolved = path52.normalize(realResolved);
67081
+ const normalizedRoot = path52.normalize(realRoot);
67082
+ if (!normalizedResolved.startsWith(normalizedRoot + path52.sep) && normalizedResolved !== normalizedRoot) {
67042
67083
  return null;
67043
67084
  }
67044
67085
  return resolved;
@@ -67051,7 +67092,7 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
67051
67092
  function createEmptyGraph(workspaceRoot) {
67052
67093
  return {
67053
67094
  schema_version: GRAPH_SCHEMA_VERSION,
67054
- workspaceRoot: path51.normalize(workspaceRoot),
67095
+ workspaceRoot: path52.normalize(workspaceRoot),
67055
67096
  nodes: {},
67056
67097
  edges: [],
67057
67098
  metadata: {
@@ -67085,10 +67126,10 @@ function addEdge(graph, edge) {
67085
67126
  }
67086
67127
  }
67087
67128
  function getCachedGraph(workspace) {
67088
- return graphCache.get(path51.normalize(workspace));
67129
+ return graphCache.get(path52.normalize(workspace));
67089
67130
  }
67090
67131
  function setCachedGraph(workspace, graph, mtime) {
67091
- const normalized = path51.normalize(workspace);
67132
+ const normalized = path52.normalize(workspace);
67092
67133
  graphCache.set(normalized, graph);
67093
67134
  dirtyFlags.set(normalized, false);
67094
67135
  if (mtime !== undefined) {
@@ -67096,10 +67137,10 @@ function setCachedGraph(workspace, graph, mtime) {
67096
67137
  }
67097
67138
  }
67098
67139
  function isDirty(workspace) {
67099
- return dirtyFlags.get(path51.normalize(workspace)) ?? false;
67140
+ return dirtyFlags.get(path52.normalize(workspace)) ?? false;
67100
67141
  }
67101
67142
  function clearCache(workspace) {
67102
- const normalized = path51.normalize(workspace);
67143
+ const normalized = path52.normalize(workspace);
67103
67144
  graphCache.delete(normalized);
67104
67145
  dirtyFlags.delete(normalized);
67105
67146
  mtimeCache.delete(normalized);
@@ -67112,12 +67153,12 @@ function getGraphPath(workspace) {
67112
67153
  }
67113
67154
  async function loadGraph(workspace) {
67114
67155
  validateWorkspace(workspace);
67115
- const normalized = path51.normalize(workspace);
67156
+ const normalized = path52.normalize(workspace);
67116
67157
  const cached3 = getCachedGraph(normalized);
67117
67158
  if (cached3 && !isDirty(normalized)) {
67118
67159
  try {
67119
67160
  const graphPath = getGraphPath(workspace);
67120
- if (existsSync28(graphPath)) {
67161
+ if (existsSync29(graphPath)) {
67121
67162
  const stats = await fsPromises5.stat(graphPath);
67122
67163
  const cachedMtime = mtimeCache.get(normalized);
67123
67164
  if (cachedMtime !== undefined && stats.mtimeMs !== cachedMtime) {
@@ -67134,7 +67175,7 @@ async function loadGraph(workspace) {
67134
67175
  }
67135
67176
  try {
67136
67177
  const graphPath = getGraphPath(workspace);
67137
- if (!existsSync28(graphPath)) {
67178
+ if (!existsSync29(graphPath)) {
67138
67179
  return null;
67139
67180
  }
67140
67181
  const stats = await fsPromises5.stat(graphPath);
@@ -67206,28 +67247,28 @@ async function saveGraph(workspace, graph, options) {
67206
67247
  if (!Array.isArray(graph.edges)) {
67207
67248
  throw new Error("Graph must have edges array");
67208
67249
  }
67209
- const normalizedWorkspace = path51.normalize(workspace);
67250
+ const normalizedWorkspace = path52.normalize(workspace);
67210
67251
  let realWorkspace;
67211
67252
  try {
67212
67253
  realWorkspace = realpathSync6(workspace);
67213
67254
  } catch {
67214
67255
  realWorkspace = normalizedWorkspace;
67215
67256
  }
67216
- const normalizedGraphRoot = path51.normalize(graph.workspaceRoot);
67257
+ const normalizedGraphRoot = path52.normalize(graph.workspaceRoot);
67217
67258
  let realGraphRoot;
67218
67259
  try {
67219
67260
  realGraphRoot = realpathSync6(graph.workspaceRoot);
67220
67261
  } catch {
67221
67262
  realGraphRoot = normalizedGraphRoot;
67222
67263
  }
67223
- if (path51.normalize(realWorkspace) !== path51.normalize(realGraphRoot)) {
67264
+ if (path52.normalize(realWorkspace) !== path52.normalize(realGraphRoot)) {
67224
67265
  throw new Error(`Graph workspaceRoot mismatch: graph was built for "${graph.workspaceRoot}" but save was called for "${workspace}"`);
67225
67266
  }
67226
67267
  const normalized = normalizedWorkspace;
67227
67268
  const graphPath = getGraphPath(workspace);
67228
67269
  updateGraphMetadata(graph);
67229
67270
  const tempPath = `${graphPath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
67230
- await fsPromises5.mkdir(path51.dirname(tempPath), { recursive: true });
67271
+ await fsPromises5.mkdir(path52.dirname(tempPath), { recursive: true });
67231
67272
  let lastError = null;
67232
67273
  try {
67233
67274
  if (options?.createAtomic) {
@@ -67311,12 +67352,12 @@ function isRefusedWorkspaceRoot(target) {
67311
67352
  try {
67312
67353
  resolved = realpathSync6(target);
67313
67354
  } catch {
67314
- resolved = path51.resolve(target);
67355
+ resolved = path52.resolve(target);
67315
67356
  }
67316
67357
  const refused = new Set;
67317
67358
  const add = (p) => {
67318
67359
  if (typeof p === "string" && p.length > 0) {
67319
- refused.add(path51.resolve(p));
67360
+ refused.add(path52.resolve(p));
67320
67361
  }
67321
67362
  };
67322
67363
  add(os7.homedir());
@@ -67435,7 +67476,7 @@ async function findSourceFilesAsync(dir, stats, options) {
67435
67476
  ctx.stats.skippedDirs++;
67436
67477
  continue;
67437
67478
  }
67438
- const fullPath = path51.join(current, entry.name);
67479
+ const fullPath = path52.join(current, entry.name);
67439
67480
  if (entry.isSymbolicLink() && !ctx.followSymlinks) {
67440
67481
  ctx.stats.skippedDirs++;
67441
67482
  continue;
@@ -67443,7 +67484,7 @@ async function findSourceFilesAsync(dir, stats, options) {
67443
67484
  if (entry.isDirectory()) {
67444
67485
  queue.push(fullPath);
67445
67486
  } else if (entry.isFile()) {
67446
- const ext = path51.extname(fullPath).toLowerCase();
67487
+ const ext = path52.extname(fullPath).toLowerCase();
67447
67488
  if (SUPPORTED_EXTENSIONS.includes(ext)) {
67448
67489
  files.push(fullPath);
67449
67490
  }
@@ -67460,11 +67501,11 @@ async function findSourceFilesAsync(dir, stats, options) {
67460
67501
  return files;
67461
67502
  }
67462
67503
  function toModuleName(filePath, workspaceRoot) {
67463
- const relative9 = path51.relative(workspaceRoot, filePath);
67464
- return relative9.split(path51.sep).join("/");
67504
+ const relative9 = path52.relative(workspaceRoot, filePath);
67505
+ return relative9.split(path52.sep).join("/");
67465
67506
  }
67466
67507
  function getLanguage(filePath) {
67467
- const ext = path51.extname(filePath).toLowerCase();
67508
+ const ext = path52.extname(filePath).toLowerCase();
67468
67509
  return EXTENSION_TO_LANGUAGE[ext] ?? "unknown";
67469
67510
  }
67470
67511
  function isBinaryContent(content) {
@@ -67479,8 +67520,8 @@ async function buildWorkspaceGraphAsync(workspaceRoot, options) {
67479
67520
  const maxFiles = options?.maxFiles ?? DEFAULT_WALK_FILE_CAP;
67480
67521
  const walkBudgetMs = options?.walkBudgetMs ?? DEFAULT_WALK_BUDGET_MS;
67481
67522
  const followSymlinks = options?.followSymlinks ?? false;
67482
- const absoluteRoot = path51.resolve(workspaceRoot);
67483
- if (!existsSync28(absoluteRoot)) {
67523
+ const absoluteRoot = path52.resolve(workspaceRoot);
67524
+ if (!existsSync29(absoluteRoot)) {
67484
67525
  throw new Error(`Workspace directory does not exist: ${workspaceRoot}`);
67485
67526
  }
67486
67527
  if (isRefusedWorkspaceRoot(absoluteRoot)) {
@@ -67549,15 +67590,15 @@ function scanFile(filePath, absoluteRoot, maxFileSize) {
67549
67590
  if (isBinaryContent(content)) {
67550
67591
  return { node: null, edges: [] };
67551
67592
  }
67552
- const ext = path51.extname(filePath).toLowerCase();
67593
+ const ext = path52.extname(filePath).toLowerCase();
67553
67594
  let exports = [];
67554
67595
  try {
67555
67596
  if ([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(ext)) {
67556
- const relativePath = path51.relative(absoluteRoot, filePath);
67597
+ const relativePath = path52.relative(absoluteRoot, filePath);
67557
67598
  const symbols2 = extractTSSymbols(relativePath, absoluteRoot);
67558
67599
  exports = symbols2.filter((s) => s.exported).map((s) => s.name);
67559
67600
  } else if (ext === ".py") {
67560
- const relativePath = path51.relative(absoluteRoot, filePath);
67601
+ const relativePath = path52.relative(absoluteRoot, filePath);
67561
67602
  const symbols2 = extractPythonSymbols(relativePath, absoluteRoot);
67562
67603
  exports = symbols2.filter((s) => s.exported).map((s) => s.name);
67563
67604
  }
@@ -67601,12 +67642,12 @@ async function updateGraphForFiles(workspaceRoot, filePaths, options) {
67601
67642
  return graph2;
67602
67643
  }
67603
67644
  const graph = existingGraph;
67604
- const absoluteRoot = path51.resolve(workspaceRoot);
67645
+ const absoluteRoot = path52.resolve(workspaceRoot);
67605
67646
  const maxFileSize = 1024 * 1024;
67606
67647
  const updatedPaths = new Set;
67607
67648
  for (const rawFilePath of filePaths) {
67608
67649
  const normalizedPath = normalizeGraphPath(rawFilePath);
67609
- const fileExists = existsSync28(rawFilePath);
67650
+ const fileExists = existsSync29(rawFilePath);
67610
67651
  if (fileExists) {
67611
67652
  graph.edges = graph.edges.filter((e) => normalizeGraphPath(e.source) !== normalizedPath);
67612
67653
  const result = scanFile(rawFilePath, absoluteRoot, maxFileSize);
@@ -67645,9 +67686,7 @@ async function updateGraphForFiles(workspaceRoot, filePaths, options) {
67645
67686
  await saveGraph(workspaceRoot, graph);
67646
67687
  return graph;
67647
67688
  }
67648
-
67649
67689
  // src/hooks/repo-graph-builder.ts
67650
- init_logger();
67651
67690
  var SUPPORTED_EXTENSIONS2 = [
67652
67691
  ".ts",
67653
67692
  ".tsx",
@@ -67723,7 +67762,7 @@ function createRepoGraphBuilderHook(workspaceRoot, deps) {
67723
67762
  filePath = filePath.replace(/./g, ".").replace(///g, "/").replace(/․/g, ".");
67724
67763
  if (!isSupportedSourceFile(filePath))
67725
67764
  return;
67726
- const absoluteFilePath = path52.isAbsolute(filePath) ? filePath : path52.resolve(workspaceRoot, filePath);
67765
+ const absoluteFilePath = path53.isAbsolute(filePath) ? filePath : path53.resolve(workspaceRoot, filePath);
67727
67766
  const normalizedAbsolute = absoluteFilePath.replace(/\\/g, "/");
67728
67767
  const normalizedWorkspace = workspaceRoot.replace(/\\/g, "/");
67729
67768
  if (!normalizedAbsolute.startsWith(`${normalizedWorkspace}/`) && normalizedAbsolute !== normalizedWorkspace) {
@@ -67731,7 +67770,7 @@ function createRepoGraphBuilderHook(workspaceRoot, deps) {
67731
67770
  }
67732
67771
  try {
67733
67772
  await _updateGraphForFiles(workspaceRoot, [absoluteFilePath]);
67734
- log(`[repo-graph] Incremental update for ${path52.basename(filePath)}`);
67773
+ log(`[repo-graph] Incremental update for ${path53.basename(filePath)}`);
67735
67774
  } catch (error93) {
67736
67775
  const message = error93 instanceof Error ? error93.message : String(error93);
67737
67776
  error48(`[repo-graph] Incremental update failed: ${message}`);
@@ -67749,15 +67788,15 @@ init_schema();
67749
67788
  init_manager2();
67750
67789
  init_detector();
67751
67790
  init_manager();
67752
- import * as fs44 from "node:fs";
67753
- import * as path62 from "node:path";
67791
+ import * as fs45 from "node:fs";
67792
+ import * as path63 from "node:path";
67754
67793
 
67755
67794
  // src/services/decision-drift-analyzer.ts
67756
67795
  init_utils2();
67757
67796
  init_manager();
67758
67797
  init_utils();
67759
- import * as fs36 from "node:fs";
67760
- import * as path53 from "node:path";
67798
+ import * as fs37 from "node:fs";
67799
+ import * as path54 from "node:path";
67761
67800
  var DEFAULT_DRIFT_CONFIG = {
67762
67801
  staleThresholdPhases: 1,
67763
67802
  detectContradictions: true,
@@ -67911,11 +67950,11 @@ async function analyzeDecisionDrift(directory, config3 = {}) {
67911
67950
  currentPhase = legacyPhase;
67912
67951
  }
67913
67952
  }
67914
- const contextPath = path53.join(directory, ".swarm", "context.md");
67953
+ const contextPath = path54.join(directory, ".swarm", "context.md");
67915
67954
  let contextContent = "";
67916
67955
  try {
67917
- if (fs36.existsSync(contextPath)) {
67918
- contextContent = fs36.readFileSync(contextPath, "utf-8");
67956
+ if (fs37.existsSync(contextPath)) {
67957
+ contextContent = fs37.readFileSync(contextPath, "utf-8");
67919
67958
  }
67920
67959
  } catch (error93) {
67921
67960
  log("[DecisionDriftAnalyzer] context file read failed", {
@@ -68049,8 +68088,8 @@ init_utils();
68049
68088
  // src/hooks/adversarial-detector.ts
68050
68089
  init_constants();
68051
68090
  init_schema();
68052
- import * as fs37 from "node:fs/promises";
68053
- import * as path54 from "node:path";
68091
+ import * as fs38 from "node:fs/promises";
68092
+ import * as path55 from "node:path";
68054
68093
  function safeGet(obj, key) {
68055
68094
  if (!obj || !Object.hasOwn(obj, key))
68056
68095
  return;
@@ -68282,10 +68321,10 @@ async function handleDebuggingSpiral(match, taskId, directory) {
68282
68321
  let eventLogged = false;
68283
68322
  let checkpointCreated = false;
68284
68323
  try {
68285
- const swarmDir = path54.join(directory, ".swarm");
68286
- await fs37.mkdir(swarmDir, { recursive: true });
68287
- const eventsPath = path54.join(swarmDir, "events.jsonl");
68288
- await fs37.appendFile(eventsPath, `${formatDebuggingSpiralEvent(match, taskId)}
68324
+ const swarmDir = path55.join(directory, ".swarm");
68325
+ await fs38.mkdir(swarmDir, { recursive: true });
68326
+ const eventsPath = path55.join(swarmDir, "events.jsonl");
68327
+ await fs38.appendFile(eventsPath, `${formatDebuggingSpiralEvent(match, taskId)}
68289
68328
  `);
68290
68329
  eventLogged = true;
68291
68330
  } catch {}
@@ -68415,11 +68454,11 @@ function rankCandidates(candidates, config3) {
68415
68454
  init_knowledge_store();
68416
68455
 
68417
68456
  // src/hooks/repo-graph-injection.ts
68418
- import * as fs41 from "node:fs";
68457
+ import * as fs42 from "node:fs";
68419
68458
 
68420
68459
  // src/graph/graph-builder.ts
68421
- import * as fs39 from "node:fs";
68422
- import * as path57 from "node:path";
68460
+ import * as fs40 from "node:fs";
68461
+ import * as path58 from "node:path";
68423
68462
 
68424
68463
  // node_modules/yocto-queue/index.js
68425
68464
  class Node {
@@ -68579,8 +68618,8 @@ function validateConcurrency(concurrency) {
68579
68618
 
68580
68619
  // src/graph/import-extractor.ts
68581
68620
  init_path_security();
68582
- import * as fs38 from "node:fs";
68583
- import * as path55 from "node:path";
68621
+ import * as fs39 from "node:fs";
68622
+ import * as path56 from "node:path";
68584
68623
  var SOURCE_EXTENSIONS2 = [
68585
68624
  ".ts",
68586
68625
  ".tsx",
@@ -68625,27 +68664,27 @@ function getLanguageFromExtension(ext) {
68625
68664
  return null;
68626
68665
  }
68627
68666
  function toRelForwardSlash(absPath, root) {
68628
- return path55.relative(root, absPath).replace(/\\/g, "/");
68667
+ return path56.relative(root, absPath).replace(/\\/g, "/");
68629
68668
  }
68630
68669
  function tryResolveTSJS(rawModule, sourceFileAbs) {
68631
68670
  if (!rawModule.startsWith(".") && !rawModule.startsWith("/")) {
68632
68671
  return null;
68633
68672
  }
68634
- const sourceDir = path55.dirname(sourceFileAbs);
68635
- const baseAbs = path55.resolve(sourceDir, rawModule);
68673
+ const sourceDir = path56.dirname(sourceFileAbs);
68674
+ const baseAbs = path56.resolve(sourceDir, rawModule);
68636
68675
  const probe = (basePath) => {
68637
68676
  for (const ext of RESOLVE_EXTENSION_CANDIDATES) {
68638
68677
  const test = basePath + ext;
68639
68678
  try {
68640
- const stat5 = fs38.statSync(test);
68679
+ const stat5 = fs39.statSync(test);
68641
68680
  if (stat5.isFile())
68642
68681
  return test;
68643
68682
  } catch {}
68644
68683
  }
68645
68684
  for (const indexFile of RESOLVE_INDEX_CANDIDATES) {
68646
- const test = path55.join(basePath, indexFile);
68685
+ const test = path56.join(basePath, indexFile);
68647
68686
  try {
68648
- const stat5 = fs38.statSync(test);
68687
+ const stat5 = fs39.statSync(test);
68649
68688
  if (stat5.isFile())
68650
68689
  return test;
68651
68690
  } catch {}
@@ -68673,13 +68712,13 @@ function tryResolvePython(rawModule, sourceFileAbs, workspaceRoot) {
68673
68712
  }
68674
68713
  const remainder = rawModule.slice(leadingDots).replace(/\./g, "/");
68675
68714
  const upDirs = "../".repeat(Math.max(0, leadingDots - 1));
68676
- const sourceDir = path55.dirname(sourceFileAbs);
68677
- const baseAbs = path55.resolve(sourceDir, upDirs + remainder);
68715
+ const sourceDir = path56.dirname(sourceFileAbs);
68716
+ const baseAbs = path56.resolve(sourceDir, upDirs + remainder);
68678
68717
  const accept = (test) => {
68679
68718
  try {
68680
- const stat5 = fs38.statSync(test);
68719
+ const stat5 = fs39.statSync(test);
68681
68720
  if (stat5.isFile()) {
68682
- const rel = path55.relative(workspaceRoot, test).replace(/\\/g, "/");
68721
+ const rel = path56.relative(workspaceRoot, test).replace(/\\/g, "/");
68683
68722
  if (rel.startsWith(".."))
68684
68723
  return null;
68685
68724
  return test;
@@ -68693,7 +68732,7 @@ function tryResolvePython(rawModule, sourceFileAbs, workspaceRoot) {
68693
68732
  return hit;
68694
68733
  }
68695
68734
  for (const indexFile of PY_INDEX_CANDIDATES) {
68696
- const hit = accept(path55.join(baseAbs, indexFile));
68735
+ const hit = accept(path56.join(baseAbs, indexFile));
68697
68736
  if (hit)
68698
68737
  return hit;
68699
68738
  }
@@ -69064,14 +69103,14 @@ function parseRustUses(content) {
69064
69103
  }
69065
69104
  function extractImports2(opts) {
69066
69105
  const { absoluteFilePath, workspaceRoot } = opts;
69067
- const ext = path55.extname(absoluteFilePath).toLowerCase();
69106
+ const ext = path56.extname(absoluteFilePath).toLowerCase();
69068
69107
  const language = getLanguageFromExtension(ext);
69069
69108
  if (!language)
69070
69109
  return [];
69071
69110
  let content = opts.content;
69072
69111
  if (content === undefined) {
69073
69112
  try {
69074
- content = fs38.readFileSync(absoluteFilePath, "utf-8");
69113
+ content = fs39.readFileSync(absoluteFilePath, "utf-8");
69075
69114
  } catch {
69076
69115
  return [];
69077
69116
  }
@@ -69115,9 +69154,9 @@ function extractImports2(opts) {
69115
69154
  }
69116
69155
 
69117
69156
  // src/graph/symbol-extractor.ts
69118
- import * as path56 from "node:path";
69157
+ import * as path57 from "node:path";
69119
69158
  function extractExportedSymbols(relativeFilePath, workspaceRoot) {
69120
- const ext = path56.extname(relativeFilePath).toLowerCase();
69159
+ const ext = path57.extname(relativeFilePath).toLowerCase();
69121
69160
  const language = getLanguageFromExtension(ext);
69122
69161
  if (!language)
69123
69162
  return [];
@@ -69191,7 +69230,7 @@ function findSourceFiles(workspaceRoot, skipDirs = DEFAULT_SKIP_DIRS) {
69191
69230
  const dir = stack.pop();
69192
69231
  let entries;
69193
69232
  try {
69194
- entries = fs39.readdirSync(dir, { withFileTypes: true });
69233
+ entries = fs40.readdirSync(dir, { withFileTypes: true });
69195
69234
  } catch {
69196
69235
  continue;
69197
69236
  }
@@ -69206,15 +69245,15 @@ function findSourceFiles(workspaceRoot, skipDirs = DEFAULT_SKIP_DIRS) {
69206
69245
  if (entry.isDirectory()) {
69207
69246
  if (skipDirs.has(entry.name))
69208
69247
  continue;
69209
- stack.push(path57.join(dir, entry.name));
69248
+ stack.push(path58.join(dir, entry.name));
69210
69249
  continue;
69211
69250
  }
69212
69251
  if (!entry.isFile())
69213
69252
  continue;
69214
- const ext = path57.extname(entry.name).toLowerCase();
69253
+ const ext = path58.extname(entry.name).toLowerCase();
69215
69254
  if (!SOURCE_EXT_SET.has(ext))
69216
69255
  continue;
69217
- out2.push(path57.join(dir, entry.name));
69256
+ out2.push(path58.join(dir, entry.name));
69218
69257
  }
69219
69258
  }
69220
69259
  return out2;
@@ -69242,13 +69281,13 @@ async function buildRepoGraph(workspaceRoot, options = {}) {
69242
69281
  };
69243
69282
  }
69244
69283
  async function processFile(absoluteFilePath, workspaceRoot) {
69245
- const ext = path57.extname(absoluteFilePath).toLowerCase();
69284
+ const ext = path58.extname(absoluteFilePath).toLowerCase();
69246
69285
  const language = getLanguageFromExtension(ext);
69247
69286
  if (!language)
69248
69287
  return null;
69249
69288
  let stats;
69250
69289
  try {
69251
- stats = fs39.statSync(absoluteFilePath);
69290
+ stats = fs40.statSync(absoluteFilePath);
69252
69291
  } catch {
69253
69292
  return null;
69254
69293
  }
@@ -69258,11 +69297,11 @@ async function processFile(absoluteFilePath, workspaceRoot) {
69258
69297
  return null;
69259
69298
  let content;
69260
69299
  try {
69261
- content = fs39.readFileSync(absoluteFilePath, "utf-8");
69300
+ content = fs40.readFileSync(absoluteFilePath, "utf-8");
69262
69301
  } catch {
69263
69302
  return null;
69264
69303
  }
69265
- const relPath = path57.relative(workspaceRoot, absoluteFilePath).replace(/\\/g, "/");
69304
+ const relPath = path58.relative(workspaceRoot, absoluteFilePath).replace(/\\/g, "/");
69266
69305
  const imports = extractImports2({
69267
69306
  absoluteFilePath,
69268
69307
  workspaceRoot,
@@ -69503,17 +69542,17 @@ function formatSummary(opts) {
69503
69542
  }
69504
69543
  // src/graph/graph-store.ts
69505
69544
  import * as crypto6 from "node:crypto";
69506
- import * as fs40 from "node:fs";
69507
- import * as path58 from "node:path";
69545
+ import * as fs41 from "node:fs";
69546
+ import * as path59 from "node:path";
69508
69547
  var SWARM_DIR = ".swarm";
69509
69548
  function getGraphPath2(workspaceRoot) {
69510
- return path58.join(workspaceRoot, SWARM_DIR, REPO_GRAPH_FILENAME2);
69549
+ return path59.join(workspaceRoot, SWARM_DIR, REPO_GRAPH_FILENAME2);
69511
69550
  }
69512
69551
  function loadGraph2(workspaceRoot) {
69513
69552
  const file3 = getGraphPath2(workspaceRoot);
69514
69553
  let raw;
69515
69554
  try {
69516
- raw = fs40.readFileSync(file3, "utf-8");
69555
+ raw = fs41.readFileSync(file3, "utf-8");
69517
69556
  } catch {
69518
69557
  return null;
69519
69558
  }
@@ -69529,9 +69568,9 @@ function loadGraph2(workspaceRoot) {
69529
69568
  }
69530
69569
  function saveGraph2(workspaceRoot, graph) {
69531
69570
  const file3 = getGraphPath2(workspaceRoot);
69532
- const dir = path58.dirname(file3);
69571
+ const dir = path59.dirname(file3);
69533
69572
  try {
69534
- const stat5 = fs40.lstatSync(dir);
69573
+ const stat5 = fs41.lstatSync(dir);
69535
69574
  if (stat5.isSymbolicLink()) {
69536
69575
  throw new Error(`refusing to write graph: ${SWARM_DIR}/ is a symbolic link`);
69537
69576
  }
@@ -69539,14 +69578,14 @@ function saveGraph2(workspaceRoot, graph) {
69539
69578
  if (err2.code !== "ENOENT")
69540
69579
  throw err2;
69541
69580
  }
69542
- fs40.mkdirSync(dir, { recursive: true });
69581
+ fs41.mkdirSync(dir, { recursive: true });
69543
69582
  const tmp = `${file3}.tmp.${crypto6.randomUUID()}`;
69544
- fs40.writeFileSync(tmp, JSON.stringify(graph), "utf-8");
69583
+ fs41.writeFileSync(tmp, JSON.stringify(graph), "utf-8");
69545
69584
  try {
69546
- fs40.renameSync(tmp, file3);
69585
+ fs41.renameSync(tmp, file3);
69547
69586
  } catch (renameErr) {
69548
69587
  try {
69549
- fs40.unlinkSync(tmp);
69588
+ fs41.unlinkSync(tmp);
69550
69589
  } catch {}
69551
69590
  throw renameErr;
69552
69591
  }
@@ -69570,7 +69609,7 @@ function getCachedGraph2(directory) {
69570
69609
  const file3 = getGraphPath2(directory);
69571
69610
  let stat5;
69572
69611
  try {
69573
- stat5 = fs41.statSync(file3);
69612
+ stat5 = fs42.statSync(file3);
69574
69613
  } catch {
69575
69614
  cache.delete(directory);
69576
69615
  return null;
@@ -69634,8 +69673,8 @@ function buildReviewerBlastRadiusBlock(directory, changedFiles) {
69634
69673
 
69635
69674
  // src/hooks/semantic-diff-injection.ts
69636
69675
  import * as child_process5 from "node:child_process";
69637
- import * as fs42 from "node:fs";
69638
- import * as path60 from "node:path";
69676
+ import * as fs43 from "node:fs";
69677
+ import * as path61 from "node:path";
69639
69678
 
69640
69679
  // src/diff/ast-diff.ts
69641
69680
  init_tree_sitter();
@@ -70382,17 +70421,17 @@ async function buildSemanticDiffBlock(directory, changedFiles, maxFiles = 10) {
70382
70421
  const fileConsumers = {};
70383
70422
  if (graph) {
70384
70423
  for (const f of filesToProcess) {
70385
- const relativePath = path60.isAbsolute(f) ? path60.relative(directory, f) : f;
70424
+ const relativePath = path61.isAbsolute(f) ? path61.relative(directory, f) : f;
70386
70425
  const normalized = normalizeGraphPath2(relativePath);
70387
70426
  fileConsumers[normalized] = getImporters(graph, normalized).length;
70388
70427
  fileConsumers[f] = fileConsumers[normalized];
70389
70428
  }
70390
70429
  }
70391
70430
  for (const filePath of filesToProcess) {
70392
- const normalizedPath = path60.normalize(filePath);
70393
- const resolvedPath = path60.resolve(directory, normalizedPath);
70394
- const relativeToDir = path60.relative(directory, resolvedPath);
70395
- if (relativeToDir.startsWith("..") || path60.isAbsolute(relativeToDir)) {
70431
+ const normalizedPath = path61.normalize(filePath);
70432
+ const resolvedPath = path61.resolve(directory, normalizedPath);
70433
+ const relativeToDir = path61.relative(directory, resolvedPath);
70434
+ if (relativeToDir.startsWith("..") || path61.isAbsolute(relativeToDir)) {
70396
70435
  continue;
70397
70436
  }
70398
70437
  try {
@@ -70419,7 +70458,7 @@ async function buildSemanticDiffBlock(directory, changedFiles, maxFiles = 10) {
70419
70458
  stdio: "pipe",
70420
70459
  maxBuffer: 5 * 1024 * 1024
70421
70460
  }) : "";
70422
- const newContent = fs42.readFileSync(path60.join(directory, filePath), "utf-8");
70461
+ const newContent = fs43.readFileSync(path61.join(directory, filePath), "utf-8");
70423
70462
  const astResult = await computeASTDiff(filePath, oldContent, newContent);
70424
70463
  if (astResult && (astResult.changes.length > 0 || astResult.error !== undefined)) {
70425
70464
  astDiffs.push(astResult);
@@ -70746,7 +70785,7 @@ function createSystemEnhancerHook(config3, directory) {
70746
70785
  } catch {}
70747
70786
  try {
70748
70787
  const darkMatterPath = validateSwarmPath(directory, "dark-matter.md");
70749
- if (!fs44.existsSync(darkMatterPath)) {
70788
+ if (!fs45.existsSync(darkMatterPath)) {
70750
70789
  const {
70751
70790
  detectDarkMatter: detectDarkMatter2,
70752
70791
  formatDarkMatterOutput: formatDarkMatterOutput2,
@@ -70758,25 +70797,25 @@ function createSystemEnhancerHook(config3, directory) {
70758
70797
  });
70759
70798
  if (darkMatter && darkMatter.length > 0) {
70760
70799
  const darkMatterReport = formatDarkMatterOutput2(darkMatter);
70761
- await fs44.promises.writeFile(darkMatterPath, darkMatterReport, "utf-8");
70800
+ await fs45.promises.writeFile(darkMatterPath, darkMatterReport, "utf-8");
70762
70801
  warn(`[system-enhancer] Dark matter scan complete: ${darkMatter.length} co-change patterns found`);
70763
70802
  try {
70764
- const projectName = path62.basename(path62.resolve(directory));
70803
+ const projectName = path63.basename(path63.resolve(directory));
70765
70804
  const knowledgeEntries = darkMatterToKnowledgeEntries2(darkMatter, projectName);
70766
70805
  const knowledgePath = resolveSwarmKnowledgePath(directory);
70767
70806
  const existingEntries = await readKnowledge(knowledgePath);
70768
70807
  const existingLessons = new Set(existingEntries.map((e) => e.lesson));
70769
70808
  const newEntries = knowledgeEntries.filter((e) => !existingLessons.has(e.lesson));
70770
70809
  if (newEntries.length === 0) {
70771
- console.warn(`[system-enhancer] No new knowledge entries (all duplicates)`);
70810
+ warn(`[system-enhancer] No new knowledge entries (all duplicates)`);
70772
70811
  } else {
70773
70812
  for (const entry of newEntries) {
70774
70813
  await appendKnowledge(knowledgePath, entry);
70775
70814
  }
70776
- console.warn(`[system-enhancer] Created ${newEntries.length} new knowledge entries (${knowledgeEntries.length - newEntries.length} duplicates skipped)`);
70815
+ warn(`[system-enhancer] Created ${newEntries.length} new knowledge entries (${knowledgeEntries.length - newEntries.length} duplicates skipped)`);
70777
70816
  }
70778
70817
  } catch (e) {
70779
- console.warn(`[system-enhancer] Failed to create knowledge entries: ${e}`);
70818
+ warn(`[system-enhancer] Failed to create knowledge entries: ${e}`);
70780
70819
  }
70781
70820
  }
70782
70821
  }
@@ -70825,14 +70864,14 @@ function createSystemEnhancerHook(config3, directory) {
70825
70864
  if (handoffContent) {
70826
70865
  const handoffPath = validateSwarmPath(directory, "handoff.md");
70827
70866
  const consumedPath = validateSwarmPath(directory, "handoff-consumed.md");
70828
- if (fs44.existsSync(consumedPath)) {
70867
+ if (fs45.existsSync(consumedPath)) {
70829
70868
  warn("Duplicate handoff detected: handoff-consumed.md already exists");
70830
- fs44.unlinkSync(consumedPath);
70869
+ fs45.unlinkSync(consumedPath);
70831
70870
  }
70832
- fs44.renameSync(handoffPath, consumedPath);
70871
+ fs45.renameSync(handoffPath, consumedPath);
70833
70872
  try {
70834
70873
  const promptPath = validateSwarmPath(directory, "handoff-prompt.md");
70835
- fs44.unlinkSync(promptPath);
70874
+ fs45.unlinkSync(promptPath);
70836
70875
  } catch {}
70837
70876
  const handoffBlock = `## HANDOFF — Resuming from model switch
70838
70877
  The previous model's session ended. Here is your starting context:
@@ -70960,9 +70999,9 @@ ${lines.join(`
70960
70999
  try {
70961
71000
  const taskId_ccp = ccpSession?.currentTaskId;
70962
71001
  if (taskId_ccp && !taskId_ccp.includes("..") && !taskId_ccp.includes("/") && !taskId_ccp.includes("\\") && !taskId_ccp.includes("\x00")) {
70963
- const evidencePath = path62.join(directory, ".swarm", "evidence", `${taskId_ccp}.json`);
70964
- if (fs44.existsSync(evidencePath)) {
70965
- const evidenceContent = fs44.readFileSync(evidencePath, "utf-8");
71002
+ const evidencePath = path63.join(directory, ".swarm", "evidence", `${taskId_ccp}.json`);
71003
+ if (fs45.existsSync(evidencePath)) {
71004
+ const evidenceContent = fs45.readFileSync(evidencePath, "utf-8");
70966
71005
  const evidenceData = JSON.parse(evidenceContent);
70967
71006
  const rejections = (evidenceData.bundle?.entries ?? []).filter((e) => e.type === "gate" && e.gate_type === "reviewer" && e.verdict === "reject");
70968
71007
  if (rejections.length > 0) {
@@ -71226,11 +71265,11 @@ ${budgetWarning}`);
71226
71265
  if (handoffContent) {
71227
71266
  const handoffPath = validateSwarmPath(directory, "handoff.md");
71228
71267
  const consumedPath = validateSwarmPath(directory, "handoff-consumed.md");
71229
- if (fs44.existsSync(consumedPath)) {
71268
+ if (fs45.existsSync(consumedPath)) {
71230
71269
  warn("Duplicate handoff detected: handoff-consumed.md already exists");
71231
- fs44.unlinkSync(consumedPath);
71270
+ fs45.unlinkSync(consumedPath);
71232
71271
  }
71233
- fs44.renameSync(handoffPath, consumedPath);
71272
+ fs45.renameSync(handoffPath, consumedPath);
71234
71273
  const handoffBlock = `## HANDOFF — Resuming from model switch
71235
71274
  The previous model's session ended. Here is your starting context:
71236
71275
 
@@ -72107,8 +72146,8 @@ init_guardrails();
72107
72146
  init_hive_promoter();
72108
72147
 
72109
72148
  // src/hooks/incremental-verify.ts
72110
- import * as fs45 from "node:fs";
72111
- import * as path63 from "node:path";
72149
+ import * as fs46 from "node:fs";
72150
+ import * as path64 from "node:path";
72112
72151
 
72113
72152
  // src/hooks/spawn-helper.ts
72114
72153
  import * as child_process6 from "node:child_process";
@@ -72186,21 +72225,21 @@ function spawnAsync(command, cwd, timeoutMs) {
72186
72225
  // src/hooks/incremental-verify.ts
72187
72226
  var emittedSkipAdvisories = new Set;
72188
72227
  function detectPackageManager(projectDir) {
72189
- if (fs45.existsSync(path63.join(projectDir, "bun.lockb")))
72228
+ if (fs46.existsSync(path64.join(projectDir, "bun.lockb")))
72190
72229
  return "bun";
72191
- if (fs45.existsSync(path63.join(projectDir, "pnpm-lock.yaml")))
72230
+ if (fs46.existsSync(path64.join(projectDir, "pnpm-lock.yaml")))
72192
72231
  return "pnpm";
72193
- if (fs45.existsSync(path63.join(projectDir, "yarn.lock")))
72232
+ if (fs46.existsSync(path64.join(projectDir, "yarn.lock")))
72194
72233
  return "yarn";
72195
- if (fs45.existsSync(path63.join(projectDir, "package-lock.json")))
72234
+ if (fs46.existsSync(path64.join(projectDir, "package-lock.json")))
72196
72235
  return "npm";
72197
72236
  return "bun";
72198
72237
  }
72199
72238
  function detectTypecheckCommand(projectDir) {
72200
- const pkgPath = path63.join(projectDir, "package.json");
72201
- if (fs45.existsSync(pkgPath)) {
72239
+ const pkgPath = path64.join(projectDir, "package.json");
72240
+ if (fs46.existsSync(pkgPath)) {
72202
72241
  try {
72203
- const pkg = JSON.parse(fs45.readFileSync(pkgPath, "utf8"));
72242
+ const pkg = JSON.parse(fs46.readFileSync(pkgPath, "utf8"));
72204
72243
  const scripts = pkg.scripts;
72205
72244
  if (scripts?.typecheck) {
72206
72245
  const pm = detectPackageManager(projectDir);
@@ -72214,8 +72253,8 @@ function detectTypecheckCommand(projectDir) {
72214
72253
  ...pkg.dependencies,
72215
72254
  ...pkg.devDependencies
72216
72255
  };
72217
- if (!deps?.typescript && !fs45.existsSync(path63.join(projectDir, "tsconfig.json"))) {}
72218
- const hasTSMarkers = deps?.typescript || fs45.existsSync(path63.join(projectDir, "tsconfig.json"));
72256
+ if (!deps?.typescript && !fs46.existsSync(path64.join(projectDir, "tsconfig.json"))) {}
72257
+ const hasTSMarkers = deps?.typescript || fs46.existsSync(path64.join(projectDir, "tsconfig.json"));
72219
72258
  if (hasTSMarkers) {
72220
72259
  return { command: ["npx", "tsc", "--noEmit"], language: "typescript" };
72221
72260
  }
@@ -72223,17 +72262,17 @@ function detectTypecheckCommand(projectDir) {
72223
72262
  return null;
72224
72263
  }
72225
72264
  }
72226
- if (fs45.existsSync(path63.join(projectDir, "go.mod"))) {
72265
+ if (fs46.existsSync(path64.join(projectDir, "go.mod"))) {
72227
72266
  return { command: ["go", "vet", "./..."], language: "go" };
72228
72267
  }
72229
- if (fs45.existsSync(path63.join(projectDir, "Cargo.toml"))) {
72268
+ if (fs46.existsSync(path64.join(projectDir, "Cargo.toml"))) {
72230
72269
  return { command: ["cargo", "check"], language: "rust" };
72231
72270
  }
72232
- if (fs45.existsSync(path63.join(projectDir, "pyproject.toml")) || fs45.existsSync(path63.join(projectDir, "requirements.txt")) || fs45.existsSync(path63.join(projectDir, "setup.py"))) {
72271
+ if (fs46.existsSync(path64.join(projectDir, "pyproject.toml")) || fs46.existsSync(path64.join(projectDir, "requirements.txt")) || fs46.existsSync(path64.join(projectDir, "setup.py"))) {
72233
72272
  return { command: null, language: "python" };
72234
72273
  }
72235
72274
  try {
72236
- const entries = fs45.readdirSync(projectDir);
72275
+ const entries = fs46.readdirSync(projectDir);
72237
72276
  if (entries.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
72238
72277
  return {
72239
72278
  command: ["dotnet", "build", "--no-restore"],
@@ -72477,7 +72516,7 @@ function createKnowledgeInjectorHook(directory, config3) {
72477
72516
  const headroomChars = MODEL_LIMIT_CHARS - existingChars;
72478
72517
  const MIN_INJECT_CHARS = config3.context_budget_threshold ?? 300;
72479
72518
  if (headroomChars < MIN_INJECT_CHARS) {
72480
- console.warn(`[knowledge-injector] Skipping: only ${headroomChars} chars of headroom remain (existing: ${existingChars}, limit: ${MODEL_LIMIT_CHARS})`);
72519
+ warn(`[knowledge-injector] Skipping: only ${headroomChars} chars of headroom remain (existing: ${existingChars}, limit: ${MODEL_LIMIT_CHARS})`);
72481
72520
  return;
72482
72521
  }
72483
72522
  const maxInjectChars = config3.inject_char_budget ?? 2000;
@@ -72579,7 +72618,7 @@ init_scope_persistence();
72579
72618
  init_state();
72580
72619
  init_delegation_gate();
72581
72620
  init_normalize_tool_name();
72582
- import * as path65 from "node:path";
72621
+ import * as path66 from "node:path";
72583
72622
  var WRITE_TOOLS = new Set(WRITE_TOOL_NAMES);
72584
72623
  function createScopeGuardHook(config3, directory, injectAdvisory) {
72585
72624
  const enabled = config3.enabled ?? true;
@@ -72637,13 +72676,13 @@ function createScopeGuardHook(config3, directory, injectAdvisory) {
72637
72676
  }
72638
72677
  function isFileInScope(filePath, scopeEntries, directory) {
72639
72678
  const dir = directory ?? process.cwd();
72640
- const resolvedFile = path65.resolve(dir, filePath);
72679
+ const resolvedFile = path66.resolve(dir, filePath);
72641
72680
  return scopeEntries.some((scope) => {
72642
- const resolvedScope = path65.resolve(dir, scope);
72681
+ const resolvedScope = path66.resolve(dir, scope);
72643
72682
  if (resolvedFile === resolvedScope)
72644
72683
  return true;
72645
- const rel = path65.relative(resolvedScope, resolvedFile);
72646
- return rel.length > 0 && !rel.startsWith("..") && !path65.isAbsolute(rel);
72684
+ const rel = path66.relative(resolvedScope, resolvedFile);
72685
+ return rel.length > 0 && !rel.startsWith("..") && !path66.isAbsolute(rel);
72647
72686
  });
72648
72687
  }
72649
72688
 
@@ -72694,8 +72733,8 @@ function createSelfReviewHook(config3, injectAdvisory) {
72694
72733
  }
72695
72734
 
72696
72735
  // src/hooks/slop-detector.ts
72697
- import * as fs47 from "node:fs";
72698
- import * as path66 from "node:path";
72736
+ import * as fs48 from "node:fs";
72737
+ import * as path67 from "node:path";
72699
72738
  var WRITE_EDIT_TOOLS = new Set([
72700
72739
  "write",
72701
72740
  "edit",
@@ -72740,12 +72779,12 @@ function checkBoilerplateExplosion(content, taskDescription, threshold) {
72740
72779
  function walkFiles(dir, exts, deadline) {
72741
72780
  const results = [];
72742
72781
  try {
72743
- for (const entry of fs47.readdirSync(dir, { withFileTypes: true })) {
72782
+ for (const entry of fs48.readdirSync(dir, { withFileTypes: true })) {
72744
72783
  if (deadline !== undefined && Date.now() > deadline)
72745
72784
  break;
72746
72785
  if (entry.isSymbolicLink())
72747
72786
  continue;
72748
- const full = path66.join(dir, entry.name);
72787
+ const full = path67.join(dir, entry.name);
72749
72788
  if (entry.isDirectory()) {
72750
72789
  if (entry.name === "node_modules" || entry.name === ".git")
72751
72790
  continue;
@@ -72760,7 +72799,7 @@ function walkFiles(dir, exts, deadline) {
72760
72799
  return results;
72761
72800
  }
72762
72801
  function checkDeadExports(content, projectDir, startTime) {
72763
- const hasPackageJson = fs47.existsSync(path66.join(projectDir, "package.json"));
72802
+ const hasPackageJson = fs48.existsSync(path67.join(projectDir, "package.json"));
72764
72803
  if (!hasPackageJson)
72765
72804
  return null;
72766
72805
  const exportMatches = content.matchAll(/^\+(?:export)\s+(?:function|class|const|type|interface)\s+(\w{3,})/gm);
@@ -72783,7 +72822,7 @@ function checkDeadExports(content, projectDir, startTime) {
72783
72822
  if (found || Date.now() - startTime > 480)
72784
72823
  break;
72785
72824
  try {
72786
- const text = fs47.readFileSync(file3, "utf-8");
72825
+ const text = fs48.readFileSync(file3, "utf-8");
72787
72826
  if (importPattern.test(text))
72788
72827
  found = true;
72789
72828
  importPattern.lastIndex = 0;
@@ -72874,17 +72913,17 @@ function checkDuplicateUtility(content, projectDir, startTime, targetFile) {
72874
72913
  for (const utilDir of utilityDirs) {
72875
72914
  if (Date.now() > deadline)
72876
72915
  break;
72877
- const utilPath = path66.join(projectDir, utilDir);
72878
- if (!fs47.existsSync(utilPath))
72916
+ const utilPath = path67.join(projectDir, utilDir);
72917
+ if (!fs48.existsSync(utilPath))
72879
72918
  continue;
72880
72919
  const files = walkFiles(utilPath, [".ts", ".tsx", ".js", ".jsx"], deadline);
72881
72920
  for (const file3 of files) {
72882
72921
  if (Date.now() > deadline)
72883
72922
  break;
72884
- if (targetFile && path66.resolve(file3) === path66.resolve(targetFile))
72923
+ if (targetFile && path67.resolve(file3) === path67.resolve(targetFile))
72885
72924
  continue;
72886
72925
  try {
72887
- const text = fs47.readFileSync(file3, "utf-8");
72926
+ const text = fs48.readFileSync(file3, "utf-8");
72888
72927
  for (const name2 of newExports) {
72889
72928
  const exportPattern = new RegExp(`\\bexport\\s+(?:function|class|const|type|interface)\\s+${name2}\\b`);
72890
72929
  if (exportPattern.test(text)) {
@@ -72967,7 +73006,7 @@ Review before proceeding.`;
72967
73006
  // src/hooks/steering-consumed.ts
72968
73007
  init_bun_compat();
72969
73008
  init_utils2();
72970
- import * as fs48 from "node:fs";
73009
+ import * as fs49 from "node:fs";
72971
73010
  function recordSteeringConsumed(directory, directiveId) {
72972
73011
  try {
72973
73012
  const eventsPath = validateSwarmPath(directory, "events.jsonl");
@@ -72976,7 +73015,7 @@ function recordSteeringConsumed(directory, directiveId) {
72976
73015
  directiveId,
72977
73016
  timestamp: new Date().toISOString()
72978
73017
  };
72979
- fs48.appendFileSync(eventsPath, `${JSON.stringify(event)}
73018
+ fs49.appendFileSync(eventsPath, `${JSON.stringify(event)}
72980
73019
  `, "utf-8");
72981
73020
  } catch {}
72982
73021
  }
@@ -73018,15 +73057,15 @@ function createSteeringConsumedHook(directory) {
73018
73057
 
73019
73058
  // src/hooks/trajectory-logger.ts
73020
73059
  init_manager2();
73021
- import * as fs50 from "node:fs/promises";
73022
- import * as path68 from "node:path";
73060
+ import * as fs51 from "node:fs/promises";
73061
+ import * as path69 from "node:path";
73023
73062
 
73024
73063
  // src/prm/trajectory-store.ts
73025
73064
  init_utils2();
73026
- import * as fs49 from "node:fs/promises";
73027
- import * as path67 from "node:path";
73065
+ import * as fs50 from "node:fs/promises";
73066
+ import * as path68 from "node:path";
73028
73067
  function getTrajectoryPath(sessionId, directory) {
73029
- const relativePath = path67.join("trajectories", `${sessionId}.jsonl`);
73068
+ const relativePath = path68.join("trajectories", `${sessionId}.jsonl`);
73030
73069
  return validateSwarmPath(directory, relativePath);
73031
73070
  }
73032
73071
  var _inMemoryTrajectoryCache = new Map;
@@ -73045,10 +73084,10 @@ async function appendTrajectoryEntry(sessionId, entry, directory, maxLines = 100
73045
73084
  _inMemoryTrajectoryCache.set(sessionId, cached3);
73046
73085
  }
73047
73086
  const trajectoryPath = getTrajectoryPath(sessionId, directory);
73048
- await fs49.mkdir(path67.dirname(trajectoryPath), { recursive: true });
73087
+ await fs50.mkdir(path68.dirname(trajectoryPath), { recursive: true });
73049
73088
  const line = `${JSON.stringify(entry)}
73050
73089
  `;
73051
- await fs49.appendFile(trajectoryPath, line, "utf-8");
73090
+ await fs50.appendFile(trajectoryPath, line, "utf-8");
73052
73091
  } catch (err2) {
73053
73092
  console.warn(`[trajectory-store] Failed to append trajectory entry: ${err2}`);
73054
73093
  }
@@ -73056,7 +73095,7 @@ async function appendTrajectoryEntry(sessionId, entry, directory, maxLines = 100
73056
73095
  async function readTrajectory(sessionId, directory) {
73057
73096
  try {
73058
73097
  const trajectoryPath = getTrajectoryPath(sessionId, directory);
73059
- const content = await fs49.readFile(trajectoryPath, "utf-8");
73098
+ const content = await fs50.readFile(trajectoryPath, "utf-8");
73060
73099
  const lines = content.split(`
73061
73100
  `).filter((line) => line.trim().length > 0);
73062
73101
  const entries = [];
@@ -73080,15 +73119,15 @@ async function cleanupOldTrajectoryFiles(directory, maxAgeDays = 7) {
73080
73119
  for (const subdir of ["trajectories", "replays"]) {
73081
73120
  try {
73082
73121
  const dirPath = validateSwarmPath(directory, subdir);
73083
- const entries = await fs49.readdir(dirPath, { withFileTypes: true });
73122
+ const entries = await fs50.readdir(dirPath, { withFileTypes: true });
73084
73123
  for (const entry of entries) {
73085
73124
  if (!entry.isFile())
73086
73125
  continue;
73087
- const filePath = path67.join(dirPath, entry.name);
73126
+ const filePath = path68.join(dirPath, entry.name);
73088
73127
  try {
73089
- const stat6 = await fs49.stat(filePath);
73128
+ const stat6 = await fs50.stat(filePath);
73090
73129
  if (now - stat6.mtimeMs > cutoffMs) {
73091
- await fs49.unlink(filePath);
73130
+ await fs50.unlink(filePath);
73092
73131
  }
73093
73132
  } catch {}
73094
73133
  }
@@ -73138,7 +73177,7 @@ function isSensitiveKey(key) {
73138
73177
  }
73139
73178
  async function truncateTrajectoryFile(filePath, maxLines) {
73140
73179
  try {
73141
- const content = await fs50.readFile(filePath, "utf-8");
73180
+ const content = await fs51.readFile(filePath, "utf-8");
73142
73181
  const lines = content.split(`
73143
73182
  `).filter((line) => line.trim().length > 0);
73144
73183
  if (lines.length <= maxLines) {
@@ -73146,7 +73185,7 @@ async function truncateTrajectoryFile(filePath, maxLines) {
73146
73185
  }
73147
73186
  const keepCount = Math.floor(maxLines / 2);
73148
73187
  const keptLines = lines.slice(-keepCount);
73149
- await fs50.writeFile(filePath, `${keptLines.join(`
73188
+ await fs51.writeFile(filePath, `${keptLines.join(`
73150
73189
  `)}
73151
73190
  `, "utf-8");
73152
73191
  } catch {}
@@ -73276,13 +73315,13 @@ function createTrajectoryLoggerHook(config3, _directory) {
73276
73315
  elapsed_ms
73277
73316
  };
73278
73317
  const sanitized = sanitizeTaskId2(taskId);
73279
- const relativePath = path68.join("evidence", sanitized, "trajectory.jsonl");
73318
+ const relativePath = path69.join("evidence", sanitized, "trajectory.jsonl");
73280
73319
  const trajectoryPath = validateSwarmPath(_directory, relativePath);
73281
73320
  try {
73282
- await fs50.mkdir(path68.dirname(trajectoryPath), { recursive: true });
73321
+ await fs51.mkdir(path69.dirname(trajectoryPath), { recursive: true });
73283
73322
  const line = `${JSON.stringify(entry)}
73284
73323
  `;
73285
- await fs50.appendFile(trajectoryPath, line, "utf-8");
73324
+ await fs51.appendFile(trajectoryPath, line, "utf-8");
73286
73325
  await truncateTrajectoryFile(trajectoryPath, maxLines);
73287
73326
  } catch {}
73288
73327
  try {
@@ -73829,17 +73868,17 @@ init_state();
73829
73868
  init_telemetry();
73830
73869
 
73831
73870
  // src/prm/replay.ts
73832
- import { promises as fs51 } from "node:fs";
73833
- import path69 from "node:path";
73871
+ import { promises as fs52 } from "node:fs";
73872
+ import path70 from "node:path";
73834
73873
  function isPathSafe2(targetPath, basePath) {
73835
- const resolvedTarget = path69.resolve(targetPath);
73836
- const resolvedBase = path69.resolve(basePath);
73837
- const rel = path69.relative(resolvedBase, resolvedTarget);
73838
- return !rel.startsWith("..") && !path69.isAbsolute(rel);
73874
+ const resolvedTarget = path70.resolve(targetPath);
73875
+ const resolvedBase = path70.resolve(basePath);
73876
+ const rel = path70.relative(resolvedBase, resolvedTarget);
73877
+ return !rel.startsWith("..") && !path70.isAbsolute(rel);
73839
73878
  }
73840
73879
  function isWithinReplaysDir(targetPath) {
73841
- const resolved = path69.resolve(targetPath);
73842
- const parts2 = resolved.split(path69.sep);
73880
+ const resolved = path70.resolve(targetPath);
73881
+ const parts2 = resolved.split(path70.sep);
73843
73882
  for (let i2 = 0;i2 < parts2.length - 1; i2++) {
73844
73883
  if (parts2[i2] === ".swarm" && parts2[i2 + 1] === "replays") {
73845
73884
  return true;
@@ -73852,15 +73891,15 @@ function sanitizeFilename(input) {
73852
73891
  }
73853
73892
  async function startReplayRecording(sessionID, directory) {
73854
73893
  try {
73855
- const replayDir = path69.join(directory, ".swarm", "replays");
73894
+ const replayDir = path70.join(directory, ".swarm", "replays");
73856
73895
  const safeSessionID = sanitizeFilename(sessionID);
73857
73896
  const filename = `${safeSessionID}-${Date.now()}.jsonl`;
73858
- const filepath = path69.join(replayDir, filename);
73897
+ const filepath = path70.join(replayDir, filename);
73859
73898
  if (!isPathSafe2(filepath, replayDir)) {
73860
73899
  console.warn(`[replay] Invalid path detected - path traversal attempt blocked for session ${sessionID}`);
73861
73900
  return null;
73862
73901
  }
73863
- await fs51.mkdir(replayDir, { recursive: true });
73902
+ await fs52.mkdir(replayDir, { recursive: true });
73864
73903
  return filepath;
73865
73904
  } catch (err2) {
73866
73905
  console.warn(`[replay] Failed to start recording for session ${sessionID}: ${err2}`);
@@ -73880,7 +73919,7 @@ async function recordReplayEntry(artifactPath, sessionID, entry) {
73880
73919
  };
73881
73920
  const line = `${JSON.stringify(fullEntry)}
73882
73921
  `;
73883
- await fs51.appendFile(artifactPath, line, "utf-8");
73922
+ await fs52.appendFile(artifactPath, line, "utf-8");
73884
73923
  } catch (err2) {
73885
73924
  console.warn(`[replay] Failed to record entry: ${err2}`);
73886
73925
  }
@@ -74228,8 +74267,8 @@ init_telemetry();
74228
74267
  // src/tools/batch-symbols.ts
74229
74268
  init_dist();
74230
74269
  init_create_tool();
74231
- import * as fs52 from "node:fs";
74232
- import * as path70 from "node:path";
74270
+ import * as fs53 from "node:fs";
74271
+ import * as path71 from "node:path";
74233
74272
  init_path_security();
74234
74273
  var WINDOWS_RESERVED_NAMES2 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
74235
74274
  function containsWindowsAttacks2(str) {
@@ -74246,14 +74285,14 @@ function containsWindowsAttacks2(str) {
74246
74285
  }
74247
74286
  function isPathInWorkspace2(filePath, workspace) {
74248
74287
  try {
74249
- const resolvedPath = path70.resolve(workspace, filePath);
74250
- if (!fs52.existsSync(resolvedPath)) {
74288
+ const resolvedPath = path71.resolve(workspace, filePath);
74289
+ if (!fs53.existsSync(resolvedPath)) {
74251
74290
  return true;
74252
74291
  }
74253
- const realWorkspace = fs52.realpathSync(workspace);
74254
- const realResolvedPath = fs52.realpathSync(resolvedPath);
74255
- const relativePath = path70.relative(realWorkspace, realResolvedPath);
74256
- if (relativePath.startsWith("..") || path70.isAbsolute(relativePath)) {
74292
+ const realWorkspace = fs53.realpathSync(workspace);
74293
+ const realResolvedPath = fs53.realpathSync(resolvedPath);
74294
+ const relativePath = path71.relative(realWorkspace, realResolvedPath);
74295
+ if (relativePath.startsWith("..") || path71.isAbsolute(relativePath)) {
74257
74296
  return false;
74258
74297
  }
74259
74298
  return true;
@@ -74262,7 +74301,7 @@ function isPathInWorkspace2(filePath, workspace) {
74262
74301
  }
74263
74302
  }
74264
74303
  function processFile2(file3, cwd, exportedOnly) {
74265
- const ext = path70.extname(file3);
74304
+ const ext = path71.extname(file3);
74266
74305
  if (containsControlChars(file3)) {
74267
74306
  return {
74268
74307
  file: file3,
@@ -74295,8 +74334,8 @@ function processFile2(file3, cwd, exportedOnly) {
74295
74334
  errorType: "path-outside-workspace"
74296
74335
  };
74297
74336
  }
74298
- const fullPath = path70.join(cwd, file3);
74299
- if (!fs52.existsSync(fullPath)) {
74337
+ const fullPath = path71.join(cwd, file3);
74338
+ if (!fs53.existsSync(fullPath)) {
74300
74339
  return {
74301
74340
  file: file3,
74302
74341
  success: false,
@@ -74327,14 +74366,14 @@ function processFile2(file3, cwd, exportedOnly) {
74327
74366
  }
74328
74367
  let isEmptyFile = false;
74329
74368
  try {
74330
- const stats = fs52.statSync(fullPath);
74369
+ const stats = fs53.statSync(fullPath);
74331
74370
  if (stats.size === 0) {
74332
74371
  isEmptyFile = true;
74333
74372
  }
74334
74373
  } catch {}
74335
74374
  if (syms.length === 0) {
74336
74375
  try {
74337
- const content = fs52.readFileSync(fullPath, "utf-8");
74376
+ const content = fs53.readFileSync(fullPath, "utf-8");
74338
74377
  if (content.trim().length === 0) {
74339
74378
  isEmptyFile = true;
74340
74379
  }
@@ -74586,25 +74625,25 @@ init_manager2();
74586
74625
  init_task_id();
74587
74626
  init_create_tool();
74588
74627
  init_resolve_working_directory();
74589
- import * as fs53 from "node:fs";
74590
- import * as path71 from "node:path";
74628
+ import * as fs54 from "node:fs";
74629
+ import * as path72 from "node:path";
74591
74630
  var EVIDENCE_DIR = ".swarm/evidence";
74592
74631
  function isValidTaskId3(taskId) {
74593
74632
  return isStrictTaskId(taskId);
74594
74633
  }
74595
74634
  function isPathWithinSwarm(filePath, workspaceRoot) {
74596
- const normalizedWorkspace = path71.resolve(workspaceRoot);
74597
- const swarmPath = path71.join(normalizedWorkspace, ".swarm", "evidence");
74598
- const normalizedPath = path71.resolve(filePath);
74635
+ const normalizedWorkspace = path72.resolve(workspaceRoot);
74636
+ const swarmPath = path72.join(normalizedWorkspace, ".swarm", "evidence");
74637
+ const normalizedPath = path72.resolve(filePath);
74599
74638
  return normalizedPath.startsWith(swarmPath);
74600
74639
  }
74601
74640
  function readEvidenceFile(evidencePath) {
74602
- if (!fs53.existsSync(evidencePath)) {
74641
+ if (!fs54.existsSync(evidencePath)) {
74603
74642
  return null;
74604
74643
  }
74605
74644
  let content;
74606
74645
  try {
74607
- content = fs53.readFileSync(evidencePath, "utf-8");
74646
+ content = fs54.readFileSync(evidencePath, "utf-8");
74608
74647
  } catch {
74609
74648
  return null;
74610
74649
  }
@@ -74676,7 +74715,7 @@ var check_gate_status = createSwarmTool({
74676
74715
  };
74677
74716
  return JSON.stringify(errorResult, null, 2);
74678
74717
  }
74679
- const evidencePath = path71.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
74718
+ const evidencePath = path72.join(directory, EVIDENCE_DIR, `${taskIdInput}.json`);
74680
74719
  if (!isPathWithinSwarm(evidencePath, directory)) {
74681
74720
  const errorResult = {
74682
74721
  taskId: taskIdInput,
@@ -74772,8 +74811,8 @@ init_utils2();
74772
74811
  init_state();
74773
74812
  init_create_tool();
74774
74813
  init_resolve_working_directory();
74775
- import * as fs54 from "node:fs";
74776
- import * as path72 from "node:path";
74814
+ import * as fs55 from "node:fs";
74815
+ import * as path73 from "node:path";
74777
74816
  function extractMatches(regex, text) {
74778
74817
  return Array.from(text.matchAll(regex));
74779
74818
  }
@@ -74867,7 +74906,7 @@ async function executeCompletionVerify(args2, directory) {
74867
74906
  let plan;
74868
74907
  try {
74869
74908
  const planPath = validateSwarmPath(directory, "plan.json");
74870
- const planRaw = fs54.readFileSync(planPath, "utf-8");
74909
+ const planRaw = fs55.readFileSync(planPath, "utf-8");
74871
74910
  plan = JSON.parse(planRaw);
74872
74911
  } catch {
74873
74912
  const result2 = {
@@ -74925,10 +74964,10 @@ async function executeCompletionVerify(args2, directory) {
74925
74964
  let hasFileReadFailure = false;
74926
74965
  for (const filePath of fileTargets) {
74927
74966
  const normalizedPath = filePath.replace(/\\/g, "/");
74928
- const resolvedPath = path72.resolve(directory, normalizedPath);
74929
- const projectRoot = path72.resolve(directory);
74930
- const relative16 = path72.relative(projectRoot, resolvedPath);
74931
- const withinProject = relative16 === "" || !relative16.startsWith("..") && !path72.isAbsolute(relative16);
74967
+ const resolvedPath = path73.resolve(directory, normalizedPath);
74968
+ const projectRoot = path73.resolve(directory);
74969
+ const relative16 = path73.relative(projectRoot, resolvedPath);
74970
+ const withinProject = relative16 === "" || !relative16.startsWith("..") && !path73.isAbsolute(relative16);
74932
74971
  if (!withinProject) {
74933
74972
  blockedTasks.push({
74934
74973
  task_id: task.id,
@@ -74941,7 +74980,7 @@ async function executeCompletionVerify(args2, directory) {
74941
74980
  }
74942
74981
  let fileContent;
74943
74982
  try {
74944
- fileContent = fs54.readFileSync(resolvedPath, "utf-8");
74983
+ fileContent = fs55.readFileSync(resolvedPath, "utf-8");
74945
74984
  } catch {
74946
74985
  blockedTasks.push({
74947
74986
  task_id: task.id,
@@ -74983,9 +75022,9 @@ async function executeCompletionVerify(args2, directory) {
74983
75022
  blockedTasks
74984
75023
  };
74985
75024
  try {
74986
- const evidenceDir = path72.join(directory, ".swarm", "evidence", `${phase}`);
74987
- const evidencePath = path72.join(evidenceDir, "completion-verify.json");
74988
- fs54.mkdirSync(evidenceDir, { recursive: true });
75025
+ const evidenceDir = path73.join(directory, ".swarm", "evidence", `${phase}`);
75026
+ const evidencePath = path73.join(evidenceDir, "completion-verify.json");
75027
+ fs55.mkdirSync(evidenceDir, { recursive: true });
74989
75028
  const evidenceBundle = {
74990
75029
  schema_version: "1.0.0",
74991
75030
  task_id: "completion-verify",
@@ -75006,7 +75045,7 @@ async function executeCompletionVerify(args2, directory) {
75006
75045
  }
75007
75046
  ]
75008
75047
  };
75009
- fs54.writeFileSync(evidencePath, JSON.stringify(evidenceBundle, null, 2), "utf-8");
75048
+ fs55.writeFileSync(evidencePath, JSON.stringify(evidenceBundle, null, 2), "utf-8");
75010
75049
  } catch {}
75011
75050
  return JSON.stringify(result, null, 2);
75012
75051
  }
@@ -75060,12 +75099,12 @@ var completion_verify = createSwarmTool({
75060
75099
  });
75061
75100
  // src/tools/complexity-hotspots.ts
75062
75101
  init_zod();
75063
- import * as fs56 from "node:fs";
75064
- import * as path74 from "node:path";
75102
+ import * as fs57 from "node:fs";
75103
+ import * as path75 from "node:path";
75065
75104
 
75066
75105
  // src/quality/metrics.ts
75067
- import * as fs55 from "node:fs";
75068
- import * as path73 from "node:path";
75106
+ import * as fs56 from "node:fs";
75107
+ import * as path74 from "node:path";
75069
75108
  var MAX_FILE_SIZE_BYTES4 = 256 * 1024;
75070
75109
  var MIN_DUPLICATION_LINES = 10;
75071
75110
  function estimateCyclomaticComplexity(content) {
@@ -75103,11 +75142,11 @@ function estimateCyclomaticComplexity(content) {
75103
75142
  }
75104
75143
  function getComplexityForFile(filePath) {
75105
75144
  try {
75106
- const stat6 = fs55.statSync(filePath);
75145
+ const stat6 = fs56.statSync(filePath);
75107
75146
  if (stat6.size > MAX_FILE_SIZE_BYTES4) {
75108
75147
  return null;
75109
75148
  }
75110
- const content = fs55.readFileSync(filePath, "utf-8");
75149
+ const content = fs56.readFileSync(filePath, "utf-8");
75111
75150
  return estimateCyclomaticComplexity(content);
75112
75151
  } catch {
75113
75152
  return null;
@@ -75117,8 +75156,8 @@ async function computeComplexityDelta(files, workingDir) {
75117
75156
  let totalComplexity = 0;
75118
75157
  const analyzedFiles = [];
75119
75158
  for (const file3 of files) {
75120
- const fullPath = path73.isAbsolute(file3) ? file3 : path73.join(workingDir, file3);
75121
- if (!fs55.existsSync(fullPath)) {
75159
+ const fullPath = path74.isAbsolute(file3) ? file3 : path74.join(workingDir, file3);
75160
+ if (!fs56.existsSync(fullPath)) {
75122
75161
  continue;
75123
75162
  }
75124
75163
  const complexity = getComplexityForFile(fullPath);
@@ -75239,8 +75278,8 @@ function countGoExports(content) {
75239
75278
  }
75240
75279
  function getExportCountForFile(filePath) {
75241
75280
  try {
75242
- const content = fs55.readFileSync(filePath, "utf-8");
75243
- const ext = path73.extname(filePath).toLowerCase();
75281
+ const content = fs56.readFileSync(filePath, "utf-8");
75282
+ const ext = path74.extname(filePath).toLowerCase();
75244
75283
  switch (ext) {
75245
75284
  case ".ts":
75246
75285
  case ".tsx":
@@ -75266,8 +75305,8 @@ async function computePublicApiDelta(files, workingDir) {
75266
75305
  let totalExports = 0;
75267
75306
  const analyzedFiles = [];
75268
75307
  for (const file3 of files) {
75269
- const fullPath = path73.isAbsolute(file3) ? file3 : path73.join(workingDir, file3);
75270
- if (!fs55.existsSync(fullPath)) {
75308
+ const fullPath = path74.isAbsolute(file3) ? file3 : path74.join(workingDir, file3);
75309
+ if (!fs56.existsSync(fullPath)) {
75271
75310
  continue;
75272
75311
  }
75273
75312
  const exports = getExportCountForFile(fullPath);
@@ -75300,16 +75339,16 @@ async function computeDuplicationRatio(files, workingDir) {
75300
75339
  let duplicateLines = 0;
75301
75340
  const analyzedFiles = [];
75302
75341
  for (const file3 of files) {
75303
- const fullPath = path73.isAbsolute(file3) ? file3 : path73.join(workingDir, file3);
75304
- if (!fs55.existsSync(fullPath)) {
75342
+ const fullPath = path74.isAbsolute(file3) ? file3 : path74.join(workingDir, file3);
75343
+ if (!fs56.existsSync(fullPath)) {
75305
75344
  continue;
75306
75345
  }
75307
75346
  try {
75308
- const stat6 = fs55.statSync(fullPath);
75347
+ const stat6 = fs56.statSync(fullPath);
75309
75348
  if (stat6.size > MAX_FILE_SIZE_BYTES4) {
75310
75349
  continue;
75311
75350
  }
75312
- const content = fs55.readFileSync(fullPath, "utf-8");
75351
+ const content = fs56.readFileSync(fullPath, "utf-8");
75313
75352
  const lines = content.split(`
75314
75353
  `).filter((line) => line.trim().length > 0);
75315
75354
  if (lines.length < MIN_DUPLICATION_LINES) {
@@ -75333,8 +75372,8 @@ function countCodeLines(content) {
75333
75372
  return lines.length;
75334
75373
  }
75335
75374
  function isTestFile(filePath) {
75336
- const basename11 = path73.basename(filePath);
75337
- const _ext = path73.extname(filePath).toLowerCase();
75375
+ const basename11 = path74.basename(filePath);
75376
+ const _ext = path74.extname(filePath).toLowerCase();
75338
75377
  const testPatterns = [
75339
75378
  ".test.",
75340
75379
  ".spec.",
@@ -75415,8 +75454,8 @@ function matchGlobSegment(globSegments, pathSegments) {
75415
75454
  }
75416
75455
  return gIndex === globSegments.length && pIndex === pathSegments.length;
75417
75456
  }
75418
- function matchesGlobSegment(path74, glob) {
75419
- const normalizedPath = path74.replace(/\\/g, "/");
75457
+ function matchesGlobSegment(path75, glob) {
75458
+ const normalizedPath = path75.replace(/\\/g, "/");
75420
75459
  const normalizedGlob = glob.replace(/\\/g, "/");
75421
75460
  if (normalizedPath.includes("//")) {
75422
75461
  return false;
@@ -75447,8 +75486,8 @@ function simpleGlobToRegex2(glob) {
75447
75486
  function hasGlobstar(glob) {
75448
75487
  return glob.includes("**");
75449
75488
  }
75450
- function globMatches(path74, glob) {
75451
- const normalizedPath = path74.replace(/\\/g, "/");
75489
+ function globMatches(path75, glob) {
75490
+ const normalizedPath = path75.replace(/\\/g, "/");
75452
75491
  if (!glob || glob === "") {
75453
75492
  if (normalizedPath.includes("//")) {
75454
75493
  return false;
@@ -75484,31 +75523,31 @@ function shouldExcludeFile(filePath, excludeGlobs) {
75484
75523
  async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
75485
75524
  let testLines = 0;
75486
75525
  let codeLines = 0;
75487
- const srcDir = path73.join(workingDir, "src");
75488
- if (fs55.existsSync(srcDir)) {
75526
+ const srcDir = path74.join(workingDir, "src");
75527
+ if (fs56.existsSync(srcDir)) {
75489
75528
  await scanDirectoryForLines(srcDir, enforceGlobs, excludeGlobs, false, (lines) => {
75490
75529
  codeLines += lines;
75491
75530
  });
75492
75531
  }
75493
75532
  const possibleSrcDirs = ["lib", "app", "source", "core"];
75494
75533
  for (const dir of possibleSrcDirs) {
75495
- const dirPath = path73.join(workingDir, dir);
75496
- if (fs55.existsSync(dirPath)) {
75534
+ const dirPath = path74.join(workingDir, dir);
75535
+ if (fs56.existsSync(dirPath)) {
75497
75536
  await scanDirectoryForLines(dirPath, enforceGlobs, excludeGlobs, false, (lines) => {
75498
75537
  codeLines += lines;
75499
75538
  });
75500
75539
  }
75501
75540
  }
75502
- const testsDir = path73.join(workingDir, "tests");
75503
- if (fs55.existsSync(testsDir)) {
75541
+ const testsDir = path74.join(workingDir, "tests");
75542
+ if (fs56.existsSync(testsDir)) {
75504
75543
  await scanDirectoryForLines(testsDir, ["**"], ["node_modules", "dist"], true, (lines) => {
75505
75544
  testLines += lines;
75506
75545
  });
75507
75546
  }
75508
75547
  const possibleTestDirs = ["test", "__tests__", "specs"];
75509
75548
  for (const dir of possibleTestDirs) {
75510
- const dirPath = path73.join(workingDir, dir);
75511
- if (fs55.existsSync(dirPath) && dirPath !== testsDir) {
75549
+ const dirPath = path74.join(workingDir, dir);
75550
+ if (fs56.existsSync(dirPath) && dirPath !== testsDir) {
75512
75551
  await scanDirectoryForLines(dirPath, ["**"], ["node_modules", "dist"], true, (lines) => {
75513
75552
  testLines += lines;
75514
75553
  });
@@ -75520,9 +75559,9 @@ async function computeTestToCodeRatio(workingDir, enforceGlobs, excludeGlobs) {
75520
75559
  }
75521
75560
  async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTestScan, callback) {
75522
75561
  try {
75523
- const entries = fs55.readdirSync(dirPath, { withFileTypes: true });
75562
+ const entries = fs56.readdirSync(dirPath, { withFileTypes: true });
75524
75563
  for (const entry of entries) {
75525
- const fullPath = path73.join(dirPath, entry.name);
75564
+ const fullPath = path74.join(dirPath, entry.name);
75526
75565
  if (entry.isDirectory()) {
75527
75566
  if (entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === ".git") {
75528
75567
  continue;
@@ -75530,7 +75569,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
75530
75569
  await scanDirectoryForLines(fullPath, includeGlobs, excludeGlobs, isTestScan, callback);
75531
75570
  } else if (entry.isFile()) {
75532
75571
  const relativePath = fullPath.replace(`${dirPath}/`, "");
75533
- const ext = path73.extname(entry.name).toLowerCase();
75572
+ const ext = path74.extname(entry.name).toLowerCase();
75534
75573
  const validExts = [
75535
75574
  ".ts",
75536
75575
  ".tsx",
@@ -75566,7 +75605,7 @@ async function scanDirectoryForLines(dirPath, includeGlobs, excludeGlobs, isTest
75566
75605
  continue;
75567
75606
  }
75568
75607
  try {
75569
- const content = fs55.readFileSync(fullPath, "utf-8");
75608
+ const content = fs56.readFileSync(fullPath, "utf-8");
75570
75609
  const lines = countCodeLines(content);
75571
75610
  callback(lines);
75572
75611
  } catch {}
@@ -75766,11 +75805,11 @@ async function getGitChurn(days, directory) {
75766
75805
  }
75767
75806
  function getComplexityForFile2(filePath) {
75768
75807
  try {
75769
- const stat6 = fs56.statSync(filePath);
75808
+ const stat6 = fs57.statSync(filePath);
75770
75809
  if (stat6.size > MAX_FILE_SIZE_BYTES5) {
75771
75810
  return null;
75772
75811
  }
75773
- const content = fs56.readFileSync(filePath, "utf-8");
75812
+ const content = fs57.readFileSync(filePath, "utf-8");
75774
75813
  return estimateCyclomaticComplexity(content);
75775
75814
  } catch {
75776
75815
  return null;
@@ -75781,7 +75820,7 @@ async function analyzeHotspots(days, topN, extensions, directory) {
75781
75820
  const extSet = new Set(extensions.map((e) => e.startsWith(".") ? e : `.${e}`));
75782
75821
  const filteredChurn = new Map;
75783
75822
  for (const [file3, count] of churnMap) {
75784
- const ext = path74.extname(file3).toLowerCase();
75823
+ const ext = path75.extname(file3).toLowerCase();
75785
75824
  if (extSet.has(ext)) {
75786
75825
  filteredChurn.set(file3, count);
75787
75826
  }
@@ -75791,8 +75830,8 @@ async function analyzeHotspots(days, topN, extensions, directory) {
75791
75830
  let analyzedFiles = 0;
75792
75831
  for (const [file3, churnCount] of filteredChurn) {
75793
75832
  let fullPath = file3;
75794
- if (!fs56.existsSync(fullPath)) {
75795
- fullPath = path74.join(cwd, file3);
75833
+ if (!fs57.existsSync(fullPath)) {
75834
+ fullPath = path75.join(cwd, file3);
75796
75835
  }
75797
75836
  const complexity = getComplexityForFile2(fullPath);
75798
75837
  if (complexity !== null) {
@@ -75961,12 +76000,12 @@ ${body2}`);
75961
76000
  // src/council/council-evidence-writer.ts
75962
76001
  import {
75963
76002
  appendFileSync as appendFileSync6,
75964
- existsSync as existsSync37,
75965
- mkdirSync as mkdirSync18,
76003
+ existsSync as existsSync38,
76004
+ mkdirSync as mkdirSync19,
75966
76005
  readFileSync as readFileSync36,
75967
- writeFileSync as writeFileSync11
76006
+ writeFileSync as writeFileSync12
75968
76007
  } from "node:fs";
75969
- import { join as join68 } from "node:path";
76008
+ import { join as join69 } from "node:path";
75970
76009
  var EVIDENCE_DIR2 = ".swarm/evidence";
75971
76010
  var VALID_TASK_ID = /^\d+\.\d+(\.\d+)*$/;
75972
76011
  var COUNCIL_GATE_NAME = "council";
@@ -76000,11 +76039,11 @@ function writeCouncilEvidence(workingDir, synthesis) {
76000
76039
  if (!VALID_TASK_ID.test(synthesis.taskId)) {
76001
76040
  throw new Error(`writeCouncilEvidence: invalid taskId "${synthesis.taskId}" — must match N.M or N.M.P format`);
76002
76041
  }
76003
- const dir = join68(workingDir, EVIDENCE_DIR2);
76004
- mkdirSync18(dir, { recursive: true });
76005
- const filePath = join68(dir, `${synthesis.taskId}.json`);
76042
+ const dir = join69(workingDir, EVIDENCE_DIR2);
76043
+ mkdirSync19(dir, { recursive: true });
76044
+ const filePath = join69(dir, `${synthesis.taskId}.json`);
76006
76045
  const existingRoot = Object.create(null);
76007
- if (existsSync37(filePath)) {
76046
+ if (existsSync38(filePath)) {
76008
76047
  try {
76009
76048
  const parsed = JSON.parse(readFileSync36(filePath, "utf-8"));
76010
76049
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
@@ -76034,17 +76073,17 @@ function writeCouncilEvidence(workingDir, synthesis) {
76034
76073
  updated.taskId = synthesis.taskId;
76035
76074
  if (!Array.isArray(updated.required_gates))
76036
76075
  updated.required_gates = [];
76037
- writeFileSync11(filePath, JSON.stringify(updated, null, 2));
76076
+ writeFileSync12(filePath, JSON.stringify(updated, null, 2));
76038
76077
  try {
76039
- const councilDir = join68(workingDir, ".swarm", "council");
76040
- mkdirSync18(councilDir, { recursive: true });
76078
+ const councilDir = join69(workingDir, ".swarm", "council");
76079
+ mkdirSync19(councilDir, { recursive: true });
76041
76080
  const auditLine = JSON.stringify({
76042
76081
  round: synthesis.roundNumber,
76043
76082
  verdict: synthesis.overallVerdict,
76044
76083
  timestamp: synthesis.timestamp,
76045
76084
  vetoedBy: synthesis.vetoedBy
76046
76085
  });
76047
- appendFileSync6(join68(councilDir, `${synthesis.taskId}.rounds.jsonl`), `${auditLine}
76086
+ appendFileSync6(join69(councilDir, `${synthesis.taskId}.rounds.jsonl`), `${auditLine}
76048
76087
  `);
76049
76088
  } catch (auditError) {
76050
76089
  console.warn(`writeCouncilEvidence: failed to append round-history audit log: ${auditError instanceof Error ? auditError.message : String(auditError)}`);
@@ -76177,22 +76216,22 @@ function buildUnifiedFeedback(taskId, verdict, vetoedBy, requiredFixes, advisory
76177
76216
  }
76178
76217
 
76179
76218
  // src/council/criteria-store.ts
76180
- import { existsSync as existsSync38, mkdirSync as mkdirSync19, readFileSync as readFileSync37, writeFileSync as writeFileSync12 } from "node:fs";
76181
- import { join as join69 } from "node:path";
76219
+ import { existsSync as existsSync39, mkdirSync as mkdirSync20, readFileSync as readFileSync37, writeFileSync as writeFileSync13 } from "node:fs";
76220
+ import { join as join70 } from "node:path";
76182
76221
  var COUNCIL_DIR = ".swarm/council";
76183
76222
  function writeCriteria(workingDir, taskId, criteria) {
76184
- const dir = join69(workingDir, COUNCIL_DIR);
76185
- mkdirSync19(dir, { recursive: true });
76223
+ const dir = join70(workingDir, COUNCIL_DIR);
76224
+ mkdirSync20(dir, { recursive: true });
76186
76225
  const payload = {
76187
76226
  taskId,
76188
76227
  criteria,
76189
76228
  declaredAt: new Date().toISOString()
76190
76229
  };
76191
- writeFileSync12(join69(dir, `${safeId(taskId)}.json`), JSON.stringify(payload, null, 2));
76230
+ writeFileSync13(join70(dir, `${safeId(taskId)}.json`), JSON.stringify(payload, null, 2));
76192
76231
  }
76193
76232
  function readCriteria(workingDir, taskId) {
76194
- const filePath = join69(workingDir, COUNCIL_DIR, `${safeId(taskId)}.json`);
76195
- if (!existsSync38(filePath))
76233
+ const filePath = join70(workingDir, COUNCIL_DIR, `${safeId(taskId)}.json`);
76234
+ if (!existsSync39(filePath))
76196
76235
  return null;
76197
76236
  try {
76198
76237
  const parsed = JSON.parse(readFileSync37(filePath, "utf-8"));
@@ -76343,8 +76382,8 @@ var submit_council_verdicts = createSwarmTool({
76343
76382
  // src/tools/convene-general-council.ts
76344
76383
  init_zod();
76345
76384
  init_loader();
76346
- import * as fs57 from "node:fs";
76347
- import * as path75 from "node:path";
76385
+ import * as fs58 from "node:fs";
76386
+ import * as path76 from "node:path";
76348
76387
 
76349
76388
  // src/council/general-council-advisory.ts
76350
76389
  var ADVISORY_HEADER = "[general_council] (advisory; not blocking)";
@@ -76772,13 +76811,13 @@ var convene_general_council = createSwarmTool({
76772
76811
  const round1 = input.round1Responses;
76773
76812
  const round2 = input.round2Responses ?? [];
76774
76813
  const result = synthesizeGeneralCouncil(input.question, input.mode, round1, round2);
76775
- const evidenceDir = path75.join(workingDir, ".swarm", "council", "general");
76814
+ const evidenceDir = path76.join(workingDir, ".swarm", "council", "general");
76776
76815
  const safeTimestamp = result.timestamp.replace(/[:.]/g, "-");
76777
76816
  const evidenceFile = `${safeTimestamp}-${input.mode}.json`;
76778
- const evidencePath = path75.join(evidenceDir, evidenceFile);
76817
+ const evidencePath = path76.join(evidenceDir, evidenceFile);
76779
76818
  try {
76780
- await fs57.promises.mkdir(evidenceDir, { recursive: true });
76781
- await fs57.promises.writeFile(evidencePath, JSON.stringify(result, null, 2));
76819
+ await fs58.promises.mkdir(evidenceDir, { recursive: true });
76820
+ await fs58.promises.writeFile(evidencePath, JSON.stringify(result, null, 2));
76782
76821
  } catch (err2) {
76783
76822
  const message = err2 instanceof Error ? err2.message : String(err2);
76784
76823
  console.warn(`[convene_general_council] Failed to write evidence to ${evidencePath}: ${message}`);
@@ -77009,8 +77048,8 @@ init_scope_persistence();
77009
77048
  init_state();
77010
77049
  init_task_id();
77011
77050
  init_create_tool();
77012
- import * as fs58 from "node:fs";
77013
- import * as path76 from "node:path";
77051
+ import * as fs59 from "node:fs";
77052
+ import * as path77 from "node:path";
77014
77053
  function validateTaskIdFormat2(taskId) {
77015
77054
  return validateTaskIdFormat(taskId);
77016
77055
  }
@@ -77084,8 +77123,8 @@ async function executeDeclareScope(args2, fallbackDir) {
77084
77123
  };
77085
77124
  }
77086
77125
  }
77087
- normalizedDir = path76.normalize(args2.working_directory);
77088
- const pathParts = normalizedDir.split(path76.sep);
77126
+ normalizedDir = path77.normalize(args2.working_directory);
77127
+ const pathParts = normalizedDir.split(path77.sep);
77089
77128
  if (pathParts.includes("..")) {
77090
77129
  return {
77091
77130
  success: false,
@@ -77095,11 +77134,11 @@ async function executeDeclareScope(args2, fallbackDir) {
77095
77134
  ]
77096
77135
  };
77097
77136
  }
77098
- const resolvedDir = path76.resolve(normalizedDir);
77137
+ const resolvedDir = path77.resolve(normalizedDir);
77099
77138
  try {
77100
- const realPath = fs58.realpathSync(resolvedDir);
77101
- const planPath2 = path76.join(realPath, ".swarm", "plan.json");
77102
- if (!fs58.existsSync(planPath2)) {
77139
+ const realPath = fs59.realpathSync(resolvedDir);
77140
+ const planPath2 = path77.join(realPath, ".swarm", "plan.json");
77141
+ if (!fs59.existsSync(planPath2)) {
77103
77142
  return {
77104
77143
  success: false,
77105
77144
  message: `Invalid working_directory: plan not found in "${realPath}"`,
@@ -77122,8 +77161,8 @@ async function executeDeclareScope(args2, fallbackDir) {
77122
77161
  console.warn("[declare-scope] fallbackDir is undefined, falling back to process.cwd()");
77123
77162
  }
77124
77163
  const directory = normalizedDir || fallbackDir;
77125
- const planPath = path76.resolve(directory, ".swarm", "plan.json");
77126
- if (!fs58.existsSync(planPath)) {
77164
+ const planPath = path77.resolve(directory, ".swarm", "plan.json");
77165
+ if (!fs59.existsSync(planPath)) {
77127
77166
  return {
77128
77167
  success: false,
77129
77168
  message: "No plan found",
@@ -77132,7 +77171,7 @@ async function executeDeclareScope(args2, fallbackDir) {
77132
77171
  }
77133
77172
  let planContent;
77134
77173
  try {
77135
- planContent = JSON.parse(fs58.readFileSync(planPath, "utf-8"));
77174
+ planContent = JSON.parse(fs59.readFileSync(planPath, "utf-8"));
77136
77175
  } catch {
77137
77176
  return {
77138
77177
  success: false,
@@ -77162,8 +77201,8 @@ async function executeDeclareScope(args2, fallbackDir) {
77162
77201
  const normalizeErrors = [];
77163
77202
  const dir = normalizedDir || fallbackDir || process.cwd();
77164
77203
  const mergedFiles = rawMergedFiles.map((file3) => {
77165
- if (path76.isAbsolute(file3)) {
77166
- const relativePath = path76.relative(dir, file3).replace(/\\/g, "/");
77204
+ if (path77.isAbsolute(file3)) {
77205
+ const relativePath = path77.relative(dir, file3).replace(/\\/g, "/");
77167
77206
  if (relativePath.startsWith("..")) {
77168
77207
  normalizeErrors.push(`Path '${file3}' resolves outside the project directory`);
77169
77208
  return file3;
@@ -77223,8 +77262,8 @@ var declare_scope = createSwarmTool({
77223
77262
  // src/tools/diff.ts
77224
77263
  init_zod();
77225
77264
  import * as child_process7 from "node:child_process";
77226
- import * as fs59 from "node:fs";
77227
- import * as path77 from "node:path";
77265
+ import * as fs60 from "node:fs";
77266
+ import * as path78 from "node:path";
77228
77267
  init_create_tool();
77229
77268
  var MAX_DIFF_LINES = 500;
77230
77269
  var DIFF_TIMEOUT_MS = 30000;
@@ -77253,20 +77292,20 @@ function validateBase(base) {
77253
77292
  function validatePaths(paths) {
77254
77293
  if (!paths)
77255
77294
  return null;
77256
- for (const path78 of paths) {
77257
- if (!path78 || path78.length === 0) {
77295
+ for (const path79 of paths) {
77296
+ if (!path79 || path79.length === 0) {
77258
77297
  return "empty path not allowed";
77259
77298
  }
77260
- if (path78.length > MAX_PATH_LENGTH) {
77299
+ if (path79.length > MAX_PATH_LENGTH) {
77261
77300
  return `path exceeds maximum length of ${MAX_PATH_LENGTH}`;
77262
77301
  }
77263
- if (SHELL_METACHARACTERS2.test(path78)) {
77302
+ if (SHELL_METACHARACTERS2.test(path79)) {
77264
77303
  return "path contains shell metacharacters";
77265
77304
  }
77266
- if (path78.startsWith("-")) {
77305
+ if (path79.startsWith("-")) {
77267
77306
  return 'path cannot start with "-" (option-like arguments not allowed)';
77268
77307
  }
77269
- if (CONTROL_CHAR_PATTERN2.test(path78)) {
77308
+ if (CONTROL_CHAR_PATTERN2.test(path79)) {
77270
77309
  return "path contains control characters";
77271
77310
  }
77272
77311
  }
@@ -77372,8 +77411,8 @@ var diff = createSwarmTool({
77372
77411
  if (parts2.length >= 3) {
77373
77412
  const additions = parseInt(parts2[0], 10) || 0;
77374
77413
  const deletions = parseInt(parts2[1], 10) || 0;
77375
- const path78 = parts2[2];
77376
- files.push({ path: path78, additions, deletions });
77414
+ const path79 = parts2[2];
77415
+ files.push({ path: path79, additions, deletions });
77377
77416
  }
77378
77417
  }
77379
77418
  const contractChanges = [];
@@ -77413,7 +77452,7 @@ var diff = createSwarmTool({
77413
77452
  } else if (base === "unstaged") {
77414
77453
  const oldRef = `:${file3.path}`;
77415
77454
  oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
77416
- newContent = fs59.readFileSync(path77.join(directory, file3.path), "utf-8");
77455
+ newContent = fs60.readFileSync(path78.join(directory, file3.path), "utf-8");
77417
77456
  } else {
77418
77457
  const oldRef = `${base}:${file3.path}`;
77419
77458
  oldContent = fileExistsInRef(oldRef) ? getContentFromRef(oldRef) : "";
@@ -77487,8 +77526,8 @@ var diff = createSwarmTool({
77487
77526
  // src/tools/diff-summary.ts
77488
77527
  init_zod();
77489
77528
  import * as child_process8 from "node:child_process";
77490
- import * as fs60 from "node:fs";
77491
- import * as path78 from "node:path";
77529
+ import * as fs61 from "node:fs";
77530
+ import * as path79 from "node:path";
77492
77531
  init_create_tool();
77493
77532
  var diff_summary = createSwarmTool({
77494
77533
  description: "Generate a filtered semantic diff summary from AST analysis. Returns SemanticDiffSummary with optional filtering by classification or riskLevel.",
@@ -77536,7 +77575,7 @@ var diff_summary = createSwarmTool({
77536
77575
  }
77537
77576
  try {
77538
77577
  let oldContent;
77539
- const newContent = fs60.readFileSync(path78.join(workingDir, filePath), "utf-8");
77578
+ const newContent = fs61.readFileSync(path79.join(workingDir, filePath), "utf-8");
77540
77579
  if (fileExistsInHead) {
77541
77580
  oldContent = child_process8.execFileSync("git", ["show", `HEAD:${filePath}`], {
77542
77581
  encoding: "utf-8",
@@ -77764,8 +77803,8 @@ Use these as DOMAIN values when delegating to @sme.`;
77764
77803
  init_zod();
77765
77804
  init_create_tool();
77766
77805
  init_path_security();
77767
- import * as fs61 from "node:fs";
77768
- import * as path79 from "node:path";
77806
+ import * as fs62 from "node:fs";
77807
+ import * as path80 from "node:path";
77769
77808
  var MAX_FILE_SIZE_BYTES6 = 1024 * 1024;
77770
77809
  var MAX_EVIDENCE_FILES = 1000;
77771
77810
  var EVIDENCE_DIR3 = ".swarm/evidence";
@@ -77792,9 +77831,9 @@ function validateRequiredTypes(input) {
77792
77831
  return null;
77793
77832
  }
77794
77833
  function isPathWithinSwarm2(filePath, cwd) {
77795
- const normalizedCwd = path79.resolve(cwd);
77796
- const swarmPath = path79.join(normalizedCwd, ".swarm");
77797
- const normalizedPath = path79.resolve(filePath);
77834
+ const normalizedCwd = path80.resolve(cwd);
77835
+ const swarmPath = path80.join(normalizedCwd, ".swarm");
77836
+ const normalizedPath = path80.resolve(filePath);
77798
77837
  return normalizedPath.startsWith(swarmPath);
77799
77838
  }
77800
77839
  function parseCompletedTasks(planContent) {
@@ -77810,12 +77849,12 @@ function parseCompletedTasks(planContent) {
77810
77849
  }
77811
77850
  function readEvidenceFiles(evidenceDir, _cwd) {
77812
77851
  const evidence = [];
77813
- if (!fs61.existsSync(evidenceDir) || !fs61.statSync(evidenceDir).isDirectory()) {
77852
+ if (!fs62.existsSync(evidenceDir) || !fs62.statSync(evidenceDir).isDirectory()) {
77814
77853
  return evidence;
77815
77854
  }
77816
77855
  let files;
77817
77856
  try {
77818
- files = fs61.readdirSync(evidenceDir);
77857
+ files = fs62.readdirSync(evidenceDir);
77819
77858
  } catch {
77820
77859
  return evidence;
77821
77860
  }
@@ -77824,14 +77863,14 @@ function readEvidenceFiles(evidenceDir, _cwd) {
77824
77863
  if (!VALID_EVIDENCE_FILENAME_REGEX.test(filename)) {
77825
77864
  continue;
77826
77865
  }
77827
- const filePath = path79.join(evidenceDir, filename);
77866
+ const filePath = path80.join(evidenceDir, filename);
77828
77867
  try {
77829
- const resolvedPath = path79.resolve(filePath);
77830
- const evidenceDirResolved = path79.resolve(evidenceDir);
77868
+ const resolvedPath = path80.resolve(filePath);
77869
+ const evidenceDirResolved = path80.resolve(evidenceDir);
77831
77870
  if (!resolvedPath.startsWith(evidenceDirResolved)) {
77832
77871
  continue;
77833
77872
  }
77834
- const stat6 = fs61.lstatSync(filePath);
77873
+ const stat6 = fs62.lstatSync(filePath);
77835
77874
  if (!stat6.isFile()) {
77836
77875
  continue;
77837
77876
  }
@@ -77840,7 +77879,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
77840
77879
  }
77841
77880
  let fileStat;
77842
77881
  try {
77843
- fileStat = fs61.statSync(filePath);
77882
+ fileStat = fs62.statSync(filePath);
77844
77883
  if (fileStat.size > MAX_FILE_SIZE_BYTES6) {
77845
77884
  continue;
77846
77885
  }
@@ -77849,7 +77888,7 @@ function readEvidenceFiles(evidenceDir, _cwd) {
77849
77888
  }
77850
77889
  let content;
77851
77890
  try {
77852
- content = fs61.readFileSync(filePath, "utf-8");
77891
+ content = fs62.readFileSync(filePath, "utf-8");
77853
77892
  } catch {
77854
77893
  continue;
77855
77894
  }
@@ -77945,7 +77984,7 @@ var evidence_check = createSwarmTool({
77945
77984
  return JSON.stringify(errorResult, null, 2);
77946
77985
  }
77947
77986
  const requiredTypes = requiredTypesValue.split(",").map((t) => t.trim()).filter((t) => t.length > 0).map(normalizeEvidenceType);
77948
- const planPath = path79.join(cwd, PLAN_FILE);
77987
+ const planPath = path80.join(cwd, PLAN_FILE);
77949
77988
  if (!isPathWithinSwarm2(planPath, cwd)) {
77950
77989
  const errorResult = {
77951
77990
  error: "plan file path validation failed",
@@ -77959,7 +77998,7 @@ var evidence_check = createSwarmTool({
77959
77998
  }
77960
77999
  let planContent;
77961
78000
  try {
77962
- planContent = fs61.readFileSync(planPath, "utf-8");
78001
+ planContent = fs62.readFileSync(planPath, "utf-8");
77963
78002
  } catch {
77964
78003
  const result2 = {
77965
78004
  message: "No completed tasks found in plan.",
@@ -77977,7 +78016,7 @@ var evidence_check = createSwarmTool({
77977
78016
  };
77978
78017
  return JSON.stringify(result2, null, 2);
77979
78018
  }
77980
- const evidenceDir = path79.join(cwd, EVIDENCE_DIR3);
78019
+ const evidenceDir = path80.join(cwd, EVIDENCE_DIR3);
77981
78020
  const evidence = readEvidenceFiles(evidenceDir, cwd);
77982
78021
  const { tasksWithFullEvidence, gaps } = analyzeGaps(completedTasks, evidence, requiredTypes);
77983
78022
  const completeness = completedTasks.length > 0 ? Math.round(tasksWithFullEvidence.length / completedTasks.length * 100) / 100 : 1;
@@ -77994,8 +78033,8 @@ var evidence_check = createSwarmTool({
77994
78033
  // src/tools/file-extractor.ts
77995
78034
  init_zod();
77996
78035
  init_create_tool();
77997
- import * as fs62 from "node:fs";
77998
- import * as path80 from "node:path";
78036
+ import * as fs63 from "node:fs";
78037
+ import * as path81 from "node:path";
77999
78038
  var EXT_MAP = {
78000
78039
  python: ".py",
78001
78040
  py: ".py",
@@ -78057,8 +78096,8 @@ var extract_code_blocks = createSwarmTool({
78057
78096
  execute: async (args2, directory) => {
78058
78097
  const { content, output_dir, prefix } = args2;
78059
78098
  const targetDir = output_dir || directory;
78060
- if (!fs62.existsSync(targetDir)) {
78061
- fs62.mkdirSync(targetDir, { recursive: true });
78099
+ if (!fs63.existsSync(targetDir)) {
78100
+ fs63.mkdirSync(targetDir, { recursive: true });
78062
78101
  }
78063
78102
  if (!content) {
78064
78103
  return "Error: content is required";
@@ -78076,16 +78115,16 @@ var extract_code_blocks = createSwarmTool({
78076
78115
  if (prefix) {
78077
78116
  filename = `${prefix}_${filename}`;
78078
78117
  }
78079
- let filepath = path80.join(targetDir, filename);
78080
- const base = path80.basename(filepath, path80.extname(filepath));
78081
- const ext = path80.extname(filepath);
78118
+ let filepath = path81.join(targetDir, filename);
78119
+ const base = path81.basename(filepath, path81.extname(filepath));
78120
+ const ext = path81.extname(filepath);
78082
78121
  let counter = 1;
78083
- while (fs62.existsSync(filepath)) {
78084
- filepath = path80.join(targetDir, `${base}_${counter}${ext}`);
78122
+ while (fs63.existsSync(filepath)) {
78123
+ filepath = path81.join(targetDir, `${base}_${counter}${ext}`);
78085
78124
  counter++;
78086
78125
  }
78087
78126
  try {
78088
- fs62.writeFileSync(filepath, code.trim(), "utf-8");
78127
+ fs63.writeFileSync(filepath, code.trim(), "utf-8");
78089
78128
  savedFiles.push(filepath);
78090
78129
  } catch (error93) {
78091
78130
  errors5.push(`Failed to save ${filename}: ${error93 instanceof Error ? error93.message : String(error93)}`);
@@ -78344,8 +78383,8 @@ var gitingest = createSwarmTool({
78344
78383
  init_zod();
78345
78384
  init_create_tool();
78346
78385
  init_path_security();
78347
- import * as fs63 from "node:fs";
78348
- import * as path81 from "node:path";
78386
+ import * as fs64 from "node:fs";
78387
+ import * as path82 from "node:path";
78349
78388
  var MAX_FILE_PATH_LENGTH2 = 500;
78350
78389
  var MAX_SYMBOL_LENGTH = 256;
78351
78390
  var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
@@ -78393,7 +78432,7 @@ function validateSymbolInput(symbol3) {
78393
78432
  return null;
78394
78433
  }
78395
78434
  function isBinaryFile2(filePath, buffer) {
78396
- const ext = path81.extname(filePath).toLowerCase();
78435
+ const ext = path82.extname(filePath).toLowerCase();
78397
78436
  if (ext === ".json" || ext === ".md" || ext === ".txt") {
78398
78437
  return false;
78399
78438
  }
@@ -78417,15 +78456,15 @@ function parseImports(content, targetFile, targetSymbol) {
78417
78456
  const imports = [];
78418
78457
  let _resolvedTarget;
78419
78458
  try {
78420
- _resolvedTarget = path81.resolve(targetFile);
78459
+ _resolvedTarget = path82.resolve(targetFile);
78421
78460
  } catch {
78422
78461
  _resolvedTarget = targetFile;
78423
78462
  }
78424
- const targetBasename = path81.basename(targetFile, path81.extname(targetFile));
78463
+ const targetBasename = path82.basename(targetFile, path82.extname(targetFile));
78425
78464
  const targetWithExt = targetFile;
78426
78465
  const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
78427
- const normalizedTargetWithExt = path81.normalize(targetWithExt).replace(/\\/g, "/");
78428
- const normalizedTargetWithoutExt = path81.normalize(targetWithoutExt).replace(/\\/g, "/");
78466
+ const normalizedTargetWithExt = path82.normalize(targetWithExt).replace(/\\/g, "/");
78467
+ const normalizedTargetWithoutExt = path82.normalize(targetWithoutExt).replace(/\\/g, "/");
78429
78468
  const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
78430
78469
  for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
78431
78470
  const modulePath = match[1] || match[2] || match[3];
@@ -78448,9 +78487,9 @@ function parseImports(content, targetFile, targetSymbol) {
78448
78487
  }
78449
78488
  const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
78450
78489
  let isMatch = false;
78451
- const _targetDir = path81.dirname(targetFile);
78452
- const targetExt = path81.extname(targetFile);
78453
- const targetBasenameNoExt = path81.basename(targetFile, targetExt);
78490
+ const _targetDir = path82.dirname(targetFile);
78491
+ const targetExt = path82.extname(targetFile);
78492
+ const targetBasenameNoExt = path82.basename(targetFile, targetExt);
78454
78493
  const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
78455
78494
  const moduleName = modulePath.split(/[/\\]/).pop() || "";
78456
78495
  const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
@@ -78507,7 +78546,7 @@ var SKIP_DIRECTORIES4 = new Set([
78507
78546
  function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFiles: 0, fileErrors: [] }) {
78508
78547
  let entries;
78509
78548
  try {
78510
- entries = fs63.readdirSync(dir);
78549
+ entries = fs64.readdirSync(dir);
78511
78550
  } catch (e) {
78512
78551
  stats.fileErrors.push({
78513
78552
  path: dir,
@@ -78518,13 +78557,13 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
78518
78557
  entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
78519
78558
  for (const entry of entries) {
78520
78559
  if (SKIP_DIRECTORIES4.has(entry)) {
78521
- stats.skippedDirs.push(path81.join(dir, entry));
78560
+ stats.skippedDirs.push(path82.join(dir, entry));
78522
78561
  continue;
78523
78562
  }
78524
- const fullPath = path81.join(dir, entry);
78563
+ const fullPath = path82.join(dir, entry);
78525
78564
  let stat6;
78526
78565
  try {
78527
- stat6 = fs63.statSync(fullPath);
78566
+ stat6 = fs64.statSync(fullPath);
78528
78567
  } catch (e) {
78529
78568
  stats.fileErrors.push({
78530
78569
  path: fullPath,
@@ -78535,7 +78574,7 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
78535
78574
  if (stat6.isDirectory()) {
78536
78575
  findSourceFiles2(fullPath, files, stats);
78537
78576
  } else if (stat6.isFile()) {
78538
- const ext = path81.extname(fullPath).toLowerCase();
78577
+ const ext = path82.extname(fullPath).toLowerCase();
78539
78578
  if (SUPPORTED_EXTENSIONS3.includes(ext)) {
78540
78579
  files.push(fullPath);
78541
78580
  }
@@ -78592,8 +78631,8 @@ var imports = createSwarmTool({
78592
78631
  return JSON.stringify(errorResult, null, 2);
78593
78632
  }
78594
78633
  try {
78595
- const targetFile = path81.resolve(file3);
78596
- if (!fs63.existsSync(targetFile)) {
78634
+ const targetFile = path82.resolve(file3);
78635
+ if (!fs64.existsSync(targetFile)) {
78597
78636
  const errorResult = {
78598
78637
  error: `target file not found: ${file3}`,
78599
78638
  target: file3,
@@ -78603,7 +78642,7 @@ var imports = createSwarmTool({
78603
78642
  };
78604
78643
  return JSON.stringify(errorResult, null, 2);
78605
78644
  }
78606
- const targetStat = fs63.statSync(targetFile);
78645
+ const targetStat = fs64.statSync(targetFile);
78607
78646
  if (!targetStat.isFile()) {
78608
78647
  const errorResult = {
78609
78648
  error: "target must be a file, not a directory",
@@ -78614,7 +78653,7 @@ var imports = createSwarmTool({
78614
78653
  };
78615
78654
  return JSON.stringify(errorResult, null, 2);
78616
78655
  }
78617
- const baseDir = path81.dirname(targetFile);
78656
+ const baseDir = path82.dirname(targetFile);
78618
78657
  const scanStats = {
78619
78658
  skippedDirs: [],
78620
78659
  skippedFiles: 0,
@@ -78629,12 +78668,12 @@ var imports = createSwarmTool({
78629
78668
  if (consumers.length >= MAX_CONSUMERS)
78630
78669
  break;
78631
78670
  try {
78632
- const stat6 = fs63.statSync(filePath);
78671
+ const stat6 = fs64.statSync(filePath);
78633
78672
  if (stat6.size > MAX_FILE_SIZE_BYTES7) {
78634
78673
  skippedFileCount++;
78635
78674
  continue;
78636
78675
  }
78637
- const buffer = fs63.readFileSync(filePath);
78676
+ const buffer = fs64.readFileSync(filePath);
78638
78677
  if (isBinaryFile2(filePath, buffer)) {
78639
78678
  skippedFileCount++;
78640
78679
  continue;
@@ -78847,7 +78886,7 @@ init_zod();
78847
78886
  init_config();
78848
78887
  init_knowledge_store();
78849
78888
  init_create_tool();
78850
- import { existsSync as existsSync43 } from "node:fs";
78889
+ import { existsSync as existsSync44 } from "node:fs";
78851
78890
  var DEFAULT_LIMIT = 10;
78852
78891
  var MAX_LESSON_LENGTH = 200;
78853
78892
  var VALID_CATEGORIES3 = [
@@ -78917,14 +78956,14 @@ function validateLimit(limit) {
78917
78956
  }
78918
78957
  async function readSwarmKnowledge(directory) {
78919
78958
  const swarmPath = resolveSwarmKnowledgePath(directory);
78920
- if (!existsSync43(swarmPath)) {
78959
+ if (!existsSync44(swarmPath)) {
78921
78960
  return [];
78922
78961
  }
78923
78962
  return readKnowledge(swarmPath);
78924
78963
  }
78925
78964
  async function readHiveKnowledge() {
78926
78965
  const hivePath = resolveHiveKnowledgePath();
78927
- if (!existsSync43(hivePath)) {
78966
+ if (!existsSync44(hivePath)) {
78928
78967
  return [];
78929
78968
  }
78930
78969
  return readKnowledge(hivePath);
@@ -79159,8 +79198,8 @@ init_schema();
79159
79198
  init_qa_gate_profile();
79160
79199
  init_manager2();
79161
79200
  init_curator();
79162
- import * as fs65 from "node:fs";
79163
- import * as path83 from "node:path";
79201
+ import * as fs66 from "node:fs";
79202
+ import * as path84 from "node:path";
79164
79203
  init_knowledge_curator();
79165
79204
  init_knowledge_reader();
79166
79205
  init_knowledge_store();
@@ -79172,20 +79211,20 @@ init_file_locks();
79172
79211
  init_plan_schema();
79173
79212
  init_ledger();
79174
79213
  init_manager();
79175
- import * as fs64 from "node:fs";
79176
- import * as path82 from "node:path";
79214
+ import * as fs65 from "node:fs";
79215
+ import * as path83 from "node:path";
79177
79216
  async function writeCheckpoint(directory) {
79178
79217
  try {
79179
79218
  const plan = await loadPlan(directory);
79180
79219
  if (!plan)
79181
79220
  return;
79182
- const swarmDir = path82.join(directory, ".swarm");
79183
- fs64.mkdirSync(swarmDir, { recursive: true });
79184
- const jsonPath = path82.join(swarmDir, "SWARM_PLAN.json");
79185
- const mdPath = path82.join(swarmDir, "SWARM_PLAN.md");
79186
- fs64.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
79221
+ const swarmDir = path83.join(directory, ".swarm");
79222
+ fs65.mkdirSync(swarmDir, { recursive: true });
79223
+ const jsonPath = path83.join(swarmDir, "SWARM_PLAN.json");
79224
+ const mdPath = path83.join(swarmDir, "SWARM_PLAN.md");
79225
+ fs65.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
79187
79226
  const md = derivePlanMarkdown(plan);
79188
- fs64.writeFileSync(mdPath, md, "utf8");
79227
+ fs65.writeFileSync(mdPath, md, "utf8");
79189
79228
  } catch (error93) {
79190
79229
  console.warn(`[checkpoint] Failed to write SWARM_PLAN checkpoint: ${error93 instanceof Error ? error93.message : String(error93)}`);
79191
79230
  }
@@ -79417,8 +79456,8 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
79417
79456
  let driftCheckEnabled = true;
79418
79457
  let driftHasSpecMd = false;
79419
79458
  try {
79420
- const specMdPath = path83.join(dir, ".swarm", "spec.md");
79421
- driftHasSpecMd = fs65.existsSync(specMdPath);
79459
+ const specMdPath = path84.join(dir, ".swarm", "spec.md");
79460
+ driftHasSpecMd = fs66.existsSync(specMdPath);
79422
79461
  const gatePlan = await loadPlan(dir);
79423
79462
  if (gatePlan) {
79424
79463
  const gatePlanId = `${gatePlan.swarm}-${gatePlan.title}`.replace(/[^a-zA-Z0-9-_]/g, "_");
@@ -79439,9 +79478,9 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
79439
79478
  } else {
79440
79479
  let phaseType;
79441
79480
  try {
79442
- const planPath = path83.join(dir, ".swarm", "plan.json");
79443
- if (fs65.existsSync(planPath)) {
79444
- const planRaw = fs65.readFileSync(planPath, "utf-8");
79481
+ const planPath = path84.join(dir, ".swarm", "plan.json");
79482
+ if (fs66.existsSync(planPath)) {
79483
+ const planRaw = fs66.readFileSync(planPath, "utf-8");
79445
79484
  const plan = JSON.parse(planRaw);
79446
79485
  const targetPhase = plan.phases?.find((p) => p.id === phase);
79447
79486
  phaseType = targetPhase?.type;
@@ -79452,11 +79491,11 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
79452
79491
  warnings.push(`Phase ${phase} is annotated as 'non-code'. Drift verification was skipped per phase type annotation.`);
79453
79492
  } else {
79454
79493
  try {
79455
- const driftEvidencePath = path83.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
79494
+ const driftEvidencePath = path84.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
79456
79495
  let driftVerdictFound = false;
79457
79496
  let driftVerdictApproved = false;
79458
79497
  try {
79459
- const driftEvidenceContent = fs65.readFileSync(driftEvidencePath, "utf-8");
79498
+ const driftEvidenceContent = fs66.readFileSync(driftEvidencePath, "utf-8");
79460
79499
  const driftEvidence = JSON.parse(driftEvidenceContent);
79461
79500
  const entries = driftEvidence.entries ?? [];
79462
79501
  for (const entry of entries) {
@@ -79490,9 +79529,9 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
79490
79529
  let incompleteTaskCount = 0;
79491
79530
  let planParseable = false;
79492
79531
  try {
79493
- const planPath = path83.join(dir, ".swarm", "plan.json");
79494
- if (fs65.existsSync(planPath)) {
79495
- const planRaw = fs65.readFileSync(planPath, "utf-8");
79532
+ const planPath = path84.join(dir, ".swarm", "plan.json");
79533
+ if (fs66.existsSync(planPath)) {
79534
+ const planRaw = fs66.readFileSync(planPath, "utf-8");
79496
79535
  const plan = JSON.parse(planRaw);
79497
79536
  planParseable = true;
79498
79537
  const planPhase = plan.phases?.find((p) => p.id === phase);
@@ -79557,11 +79596,11 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
79557
79596
  const overrides = session2?.qaGateSessionOverrides ?? {};
79558
79597
  const effective = getEffectiveGates(profile, overrides);
79559
79598
  if (effective.hallucination_guard === true) {
79560
- const hgPath = path83.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
79599
+ const hgPath = path84.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
79561
79600
  let hgVerdictFound = false;
79562
79601
  let hgVerdictApproved = false;
79563
79602
  try {
79564
- const hgContent = fs65.readFileSync(hgPath, "utf-8");
79603
+ const hgContent = fs66.readFileSync(hgPath, "utf-8");
79565
79604
  const hgBundle = JSON.parse(hgContent);
79566
79605
  for (const entry of hgBundle.entries ?? []) {
79567
79606
  if (typeof entry.type === "string" && entry.type.includes("hallucination") && typeof entry.verdict === "string") {
@@ -79629,11 +79668,11 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
79629
79668
  const overrides = session2?.qaGateSessionOverrides ?? {};
79630
79669
  const effective = getEffectiveGates(profile, overrides);
79631
79670
  if (effective.mutation_test === true) {
79632
- const mgPath = path83.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
79671
+ const mgPath = path84.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
79633
79672
  let mgVerdictFound = false;
79634
79673
  let mgVerdict;
79635
79674
  try {
79636
- const mgContent = fs65.readFileSync(mgPath, "utf-8");
79675
+ const mgContent = fs66.readFileSync(mgPath, "utf-8");
79637
79676
  const mgBundle = JSON.parse(mgContent);
79638
79677
  for (const entry of mgBundle.entries ?? []) {
79639
79678
  if (typeof entry.type === "string" && entry.type === "mutation-gate" && typeof entry.verdict === "string") {
@@ -79703,14 +79742,14 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
79703
79742
  const effective = getEffectiveGates(profile, overrides);
79704
79743
  if (effective.council_mode === true) {
79705
79744
  councilModeEnabled = true;
79706
- const pcPath = path83.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
79745
+ const pcPath = path84.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
79707
79746
  let pcVerdictFound = false;
79708
79747
  let _pcVerdict;
79709
79748
  let pcQuorumSize;
79710
79749
  let pcTimestamp;
79711
79750
  let pcPhaseNumber;
79712
79751
  try {
79713
- const pcContent = fs65.readFileSync(pcPath, "utf-8");
79752
+ const pcContent = fs66.readFileSync(pcPath, "utf-8");
79714
79753
  const pcBundle = JSON.parse(pcContent);
79715
79754
  for (const entry of pcBundle.entries ?? []) {
79716
79755
  if (typeof entry.type === "string" && entry.type === "phase-council" && typeof entry.verdict === "string") {
@@ -79905,7 +79944,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
79905
79944
  }
79906
79945
  if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
79907
79946
  try {
79908
- const projectName = path83.basename(dir);
79947
+ const projectName = path84.basename(dir);
79909
79948
  const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
79910
79949
  if (curationResult) {
79911
79950
  const sessionState = swarmState.agentSessions.get(sessionID);
@@ -79985,7 +80024,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
79985
80024
  let phaseRequiredAgents;
79986
80025
  try {
79987
80026
  const planPath = validateSwarmPath(dir, "plan.json");
79988
- const planRaw = fs65.readFileSync(planPath, "utf-8");
80027
+ const planRaw = fs66.readFileSync(planPath, "utf-8");
79989
80028
  const plan = JSON.parse(planRaw);
79990
80029
  const phaseObj = plan.phases.find((p) => p.id === phase);
79991
80030
  phaseRequiredAgents = phaseObj?.required_agents;
@@ -80000,7 +80039,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
80000
80039
  if (agentsMissing.length > 0) {
80001
80040
  try {
80002
80041
  const planPath = validateSwarmPath(dir, "plan.json");
80003
- const planRaw = fs65.readFileSync(planPath, "utf-8");
80042
+ const planRaw = fs66.readFileSync(planPath, "utf-8");
80004
80043
  const plan = JSON.parse(planRaw);
80005
80044
  const targetPhase = plan.phases.find((p) => p.id === phase);
80006
80045
  if (targetPhase && targetPhase.tasks.length > 0 && targetPhase.tasks.every((t) => t.status === "completed")) {
@@ -80040,7 +80079,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
80040
80079
  if (phaseCompleteConfig.regression_sweep?.enforce) {
80041
80080
  try {
80042
80081
  const planPath = validateSwarmPath(dir, "plan.json");
80043
- const planRaw = fs65.readFileSync(planPath, "utf-8");
80082
+ const planRaw = fs66.readFileSync(planPath, "utf-8");
80044
80083
  const plan = JSON.parse(planRaw);
80045
80084
  const targetPhase = plan.phases.find((p) => p.id === phase);
80046
80085
  if (targetPhase) {
@@ -80094,7 +80133,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
80094
80133
  }
80095
80134
  try {
80096
80135
  const eventsPath = validateSwarmPath(dir, "events.jsonl");
80097
- fs65.appendFileSync(eventsPath, `${JSON.stringify(event)}
80136
+ fs66.appendFileSync(eventsPath, `${JSON.stringify(event)}
80098
80137
  `, "utf-8");
80099
80138
  } catch (writeError) {
80100
80139
  warnings.push(`Warning: failed to write phase complete event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
@@ -80169,12 +80208,12 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
80169
80208
  warnings.push(`Warning: failed to update plan.json phase status`);
80170
80209
  try {
80171
80210
  const planPath = validateSwarmPath(dir, "plan.json");
80172
- const planRaw = fs65.readFileSync(planPath, "utf-8");
80211
+ const planRaw = fs66.readFileSync(planPath, "utf-8");
80173
80212
  const plan2 = JSON.parse(planRaw);
80174
80213
  const phaseObj = plan2.phases.find((p) => p.id === phase);
80175
80214
  if (phaseObj) {
80176
80215
  phaseObj.status = "complete";
80177
- fs65.writeFileSync(planPath, JSON.stringify(plan2, null, 2), "utf-8");
80216
+ fs66.writeFileSync(planPath, JSON.stringify(plan2, null, 2), "utf-8");
80178
80217
  }
80179
80218
  } catch {}
80180
80219
  } else if (plan) {
@@ -80211,12 +80250,12 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
80211
80250
  warnings.push(`Warning: failed to update plan.json phase status`);
80212
80251
  try {
80213
80252
  const planPath = validateSwarmPath(dir, "plan.json");
80214
- const planRaw = fs65.readFileSync(planPath, "utf-8");
80253
+ const planRaw = fs66.readFileSync(planPath, "utf-8");
80215
80254
  const plan = JSON.parse(planRaw);
80216
80255
  const phaseObj = plan.phases.find((p) => p.id === phase);
80217
80256
  if (phaseObj) {
80218
80257
  phaseObj.status = "complete";
80219
- fs65.writeFileSync(planPath, JSON.stringify(plan, null, 2), "utf-8");
80258
+ fs66.writeFileSync(planPath, JSON.stringify(plan, null, 2), "utf-8");
80220
80259
  }
80221
80260
  } catch {}
80222
80261
  }
@@ -80274,8 +80313,8 @@ init_discovery();
80274
80313
  init_utils();
80275
80314
  init_bun_compat();
80276
80315
  init_create_tool();
80277
- import * as fs66 from "node:fs";
80278
- import * as path84 from "node:path";
80316
+ import * as fs67 from "node:fs";
80317
+ import * as path85 from "node:path";
80279
80318
  var MAX_OUTPUT_BYTES5 = 52428800;
80280
80319
  var AUDIT_TIMEOUT_MS = 120000;
80281
80320
  function isValidEcosystem(value) {
@@ -80303,31 +80342,31 @@ function validateArgs3(args2) {
80303
80342
  function detectEcosystems(directory) {
80304
80343
  const ecosystems = [];
80305
80344
  const cwd = directory;
80306
- if (fs66.existsSync(path84.join(cwd, "package.json"))) {
80345
+ if (fs67.existsSync(path85.join(cwd, "package.json"))) {
80307
80346
  ecosystems.push("npm");
80308
80347
  }
80309
- if (fs66.existsSync(path84.join(cwd, "pyproject.toml")) || fs66.existsSync(path84.join(cwd, "requirements.txt"))) {
80348
+ if (fs67.existsSync(path85.join(cwd, "pyproject.toml")) || fs67.existsSync(path85.join(cwd, "requirements.txt"))) {
80310
80349
  ecosystems.push("pip");
80311
80350
  }
80312
- if (fs66.existsSync(path84.join(cwd, "Cargo.toml"))) {
80351
+ if (fs67.existsSync(path85.join(cwd, "Cargo.toml"))) {
80313
80352
  ecosystems.push("cargo");
80314
80353
  }
80315
- if (fs66.existsSync(path84.join(cwd, "go.mod"))) {
80354
+ if (fs67.existsSync(path85.join(cwd, "go.mod"))) {
80316
80355
  ecosystems.push("go");
80317
80356
  }
80318
80357
  try {
80319
- const files = fs66.readdirSync(cwd);
80358
+ const files = fs67.readdirSync(cwd);
80320
80359
  if (files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
80321
80360
  ecosystems.push("dotnet");
80322
80361
  }
80323
80362
  } catch {}
80324
- if (fs66.existsSync(path84.join(cwd, "Gemfile")) || fs66.existsSync(path84.join(cwd, "Gemfile.lock"))) {
80363
+ if (fs67.existsSync(path85.join(cwd, "Gemfile")) || fs67.existsSync(path85.join(cwd, "Gemfile.lock"))) {
80325
80364
  ecosystems.push("ruby");
80326
80365
  }
80327
- if (fs66.existsSync(path84.join(cwd, "pubspec.yaml"))) {
80366
+ if (fs67.existsSync(path85.join(cwd, "pubspec.yaml"))) {
80328
80367
  ecosystems.push("dart");
80329
80368
  }
80330
- if (fs66.existsSync(path84.join(cwd, "composer.lock"))) {
80369
+ if (fs67.existsSync(path85.join(cwd, "composer.lock"))) {
80331
80370
  ecosystems.push("composer");
80332
80371
  }
80333
80372
  return ecosystems;
@@ -81462,8 +81501,8 @@ var pkg_audit = createSwarmTool({
81462
81501
  // src/tools/placeholder-scan.ts
81463
81502
  init_zod();
81464
81503
  init_manager2();
81465
- import * as fs67 from "node:fs";
81466
- import * as path85 from "node:path";
81504
+ import * as fs68 from "node:fs";
81505
+ import * as path86 from "node:path";
81467
81506
  init_utils();
81468
81507
  init_create_tool();
81469
81508
  var MAX_FILE_SIZE = 1024 * 1024;
@@ -81586,7 +81625,7 @@ function isScaffoldFile(filePath) {
81586
81625
  if (SCAFFOLD_PATH_PATTERNS.some((pattern) => pattern.test(normalizedPath))) {
81587
81626
  return true;
81588
81627
  }
81589
- const filename = path85.basename(filePath);
81628
+ const filename = path86.basename(filePath);
81590
81629
  if (SCAFFOLD_FILENAME_PATTERNS.some((pattern) => pattern.test(filename))) {
81591
81630
  return true;
81592
81631
  }
@@ -81603,7 +81642,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
81603
81642
  if (regex.test(normalizedPath)) {
81604
81643
  return true;
81605
81644
  }
81606
- const filename = path85.basename(filePath);
81645
+ const filename = path86.basename(filePath);
81607
81646
  const filenameRegex = new RegExp(`^${regexPattern}$`, "i");
81608
81647
  if (filenameRegex.test(filename)) {
81609
81648
  return true;
@@ -81612,7 +81651,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
81612
81651
  return false;
81613
81652
  }
81614
81653
  function isParserSupported(filePath) {
81615
- const ext = path85.extname(filePath).toLowerCase();
81654
+ const ext = path86.extname(filePath).toLowerCase();
81616
81655
  return SUPPORTED_PARSER_EXTENSIONS.has(ext);
81617
81656
  }
81618
81657
  function isPlanFile(filePath) {
@@ -81859,28 +81898,28 @@ async function placeholderScan(input, directory) {
81859
81898
  let filesScanned = 0;
81860
81899
  const filesWithFindings = new Set;
81861
81900
  for (const filePath of changed_files) {
81862
- const fullPath = path85.isAbsolute(filePath) ? filePath : path85.resolve(directory, filePath);
81863
- const resolvedDirectory = path85.resolve(directory);
81864
- if (!fullPath.startsWith(resolvedDirectory + path85.sep) && fullPath !== resolvedDirectory) {
81901
+ const fullPath = path86.isAbsolute(filePath) ? filePath : path86.resolve(directory, filePath);
81902
+ const resolvedDirectory = path86.resolve(directory);
81903
+ if (!fullPath.startsWith(resolvedDirectory + path86.sep) && fullPath !== resolvedDirectory) {
81865
81904
  continue;
81866
81905
  }
81867
- if (!fs67.existsSync(fullPath)) {
81906
+ if (!fs68.existsSync(fullPath)) {
81868
81907
  continue;
81869
81908
  }
81870
81909
  if (isAllowedByGlobs(filePath, allow_globs)) {
81871
81910
  continue;
81872
81911
  }
81873
- const relativeFilePath = path85.relative(directory, fullPath).replace(/\\/g, "/");
81912
+ const relativeFilePath = path86.relative(directory, fullPath).replace(/\\/g, "/");
81874
81913
  if (FILE_ALLOWLIST.some((allowed) => relativeFilePath.endsWith(allowed))) {
81875
81914
  continue;
81876
81915
  }
81877
81916
  let content;
81878
81917
  try {
81879
- const stat6 = fs67.statSync(fullPath);
81918
+ const stat6 = fs68.statSync(fullPath);
81880
81919
  if (stat6.size > MAX_FILE_SIZE) {
81881
81920
  continue;
81882
81921
  }
81883
- content = fs67.readFileSync(fullPath, "utf-8");
81922
+ content = fs68.readFileSync(fullPath, "utf-8");
81884
81923
  } catch {
81885
81924
  continue;
81886
81925
  }
@@ -81941,8 +81980,8 @@ var placeholder_scan = createSwarmTool({
81941
81980
  }
81942
81981
  });
81943
81982
  // src/tools/pre-check-batch.ts
81944
- import * as fs70 from "node:fs";
81945
- import * as path88 from "node:path";
81983
+ import * as fs71 from "node:fs";
81984
+ import * as path89 from "node:path";
81946
81985
  init_zod();
81947
81986
  init_manager2();
81948
81987
  init_utils();
@@ -82079,8 +82118,8 @@ var quality_budget = createSwarmTool({
82079
82118
  init_zod();
82080
82119
  init_manager2();
82081
82120
  init_detector();
82082
- import * as fs69 from "node:fs";
82083
- import * as path87 from "node:path";
82121
+ import * as fs70 from "node:fs";
82122
+ import * as path88 from "node:path";
82084
82123
  import { extname as extname18 } from "node:path";
82085
82124
 
82086
82125
  // src/sast/rules/c.ts
@@ -82973,25 +83012,25 @@ init_create_tool();
82973
83012
  // src/tools/sast-baseline.ts
82974
83013
  init_utils2();
82975
83014
  import * as crypto8 from "node:crypto";
82976
- import * as fs68 from "node:fs";
82977
- import * as path86 from "node:path";
83015
+ import * as fs69 from "node:fs";
83016
+ import * as path87 from "node:path";
82978
83017
  var BASELINE_SCHEMA_VERSION = "1.0.0";
82979
83018
  var MAX_BASELINE_FINDINGS = 2000;
82980
83019
  var MAX_BASELINE_BYTES = 2 * 1048576;
82981
83020
  var LOCK_RETRY_DELAYS_MS = [50, 100, 200, 400, 800];
82982
83021
  function normalizeFindingPath(directory, file3) {
82983
- const resolved = path86.isAbsolute(file3) ? file3 : path86.resolve(directory, file3);
82984
- const rel = path86.relative(path86.resolve(directory), resolved);
83022
+ const resolved = path87.isAbsolute(file3) ? file3 : path87.resolve(directory, file3);
83023
+ const rel = path87.relative(path87.resolve(directory), resolved);
82985
83024
  return rel.replace(/\\/g, "/");
82986
83025
  }
82987
83026
  function baselineRelPath(phase) {
82988
- return path86.join("evidence", String(phase), "sast-baseline.json");
83027
+ return path87.join("evidence", String(phase), "sast-baseline.json");
82989
83028
  }
82990
83029
  function tempRelPath(phase) {
82991
- return path86.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
83030
+ return path87.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
82992
83031
  }
82993
83032
  function lockRelPath(phase) {
82994
- return path86.join("evidence", String(phase), "sast-baseline.json.lock");
83033
+ return path87.join("evidence", String(phase), "sast-baseline.json.lock");
82995
83034
  }
82996
83035
  function getLine(lines, idx) {
82997
83036
  if (idx < 0 || idx >= lines.length)
@@ -83008,7 +83047,7 @@ function fingerprintFinding(finding, directory, occurrenceIndex) {
83008
83047
  }
83009
83048
  const lineNum = finding.location.line;
83010
83049
  try {
83011
- const content = fs68.readFileSync(finding.location.file, "utf-8");
83050
+ const content = fs69.readFileSync(finding.location.file, "utf-8");
83012
83051
  const lines = content.split(`
83013
83052
  `);
83014
83053
  const idx = lineNum - 1;
@@ -83039,7 +83078,7 @@ function assignOccurrenceIndices(findings, directory) {
83039
83078
  try {
83040
83079
  if (relFile.startsWith(".."))
83041
83080
  throw new Error("escapes workspace");
83042
- const content = fs68.readFileSync(finding.location.file, "utf-8");
83081
+ const content = fs69.readFileSync(finding.location.file, "utf-8");
83043
83082
  const lines = content.split(`
83044
83083
  `);
83045
83084
  const idx = lineNum - 1;
@@ -83068,11 +83107,11 @@ function assignOccurrenceIndices(findings, directory) {
83068
83107
  async function acquireLock(lockPath) {
83069
83108
  for (let attempt = 0;attempt <= LOCK_RETRY_DELAYS_MS.length; attempt++) {
83070
83109
  try {
83071
- const fd = fs68.openSync(lockPath, "wx");
83072
- fs68.closeSync(fd);
83110
+ const fd = fs69.openSync(lockPath, "wx");
83111
+ fs69.closeSync(fd);
83073
83112
  return () => {
83074
83113
  try {
83075
- fs68.unlinkSync(lockPath);
83114
+ fs69.unlinkSync(lockPath);
83076
83115
  } catch {}
83077
83116
  };
83078
83117
  } catch {
@@ -83112,13 +83151,13 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
83112
83151
  message: e instanceof Error ? e.message : "Path validation failed"
83113
83152
  };
83114
83153
  }
83115
- fs68.mkdirSync(path86.dirname(baselinePath), { recursive: true });
83116
- fs68.mkdirSync(path86.dirname(tempPath), { recursive: true });
83154
+ fs69.mkdirSync(path87.dirname(baselinePath), { recursive: true });
83155
+ fs69.mkdirSync(path87.dirname(tempPath), { recursive: true });
83117
83156
  const releaseLock = await acquireLock(lockPath);
83118
83157
  try {
83119
83158
  let existing = null;
83120
83159
  try {
83121
- const raw = fs68.readFileSync(baselinePath, "utf-8");
83160
+ const raw = fs69.readFileSync(baselinePath, "utf-8");
83122
83161
  const parsed = JSON.parse(raw);
83123
83162
  if (parsed.schema_version === BASELINE_SCHEMA_VERSION) {
83124
83163
  existing = parsed;
@@ -83178,8 +83217,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
83178
83217
  message: `Baseline would exceed size cap (${json4.length} bytes > ${MAX_BASELINE_BYTES})`
83179
83218
  };
83180
83219
  }
83181
- fs68.writeFileSync(tempPath, json4, "utf-8");
83182
- fs68.renameSync(tempPath, baselinePath);
83220
+ fs69.writeFileSync(tempPath, json4, "utf-8");
83221
+ fs69.renameSync(tempPath, baselinePath);
83183
83222
  return {
83184
83223
  status: "merged",
83185
83224
  path: baselinePath,
@@ -83210,8 +83249,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
83210
83249
  message: `Baseline would exceed size cap (${json3.length} bytes > ${MAX_BASELINE_BYTES})`
83211
83250
  };
83212
83251
  }
83213
- fs68.writeFileSync(tempPath, json3, "utf-8");
83214
- fs68.renameSync(tempPath, baselinePath);
83252
+ fs69.writeFileSync(tempPath, json3, "utf-8");
83253
+ fs69.renameSync(tempPath, baselinePath);
83215
83254
  return {
83216
83255
  status: "written",
83217
83256
  path: baselinePath,
@@ -83236,7 +83275,7 @@ function loadBaseline(directory, phase) {
83236
83275
  };
83237
83276
  }
83238
83277
  try {
83239
- const raw = fs68.readFileSync(baselinePath, "utf-8");
83278
+ const raw = fs69.readFileSync(baselinePath, "utf-8");
83240
83279
  const parsed = JSON.parse(raw);
83241
83280
  if (parsed.schema_version !== BASELINE_SCHEMA_VERSION) {
83242
83281
  return {
@@ -83278,17 +83317,17 @@ var SEVERITY_ORDER = {
83278
83317
  };
83279
83318
  function shouldSkipFile(filePath) {
83280
83319
  try {
83281
- const stats = fs69.statSync(filePath);
83320
+ const stats = fs70.statSync(filePath);
83282
83321
  if (stats.size > MAX_FILE_SIZE_BYTES8) {
83283
83322
  return { skip: true, reason: "file too large" };
83284
83323
  }
83285
83324
  if (stats.size === 0) {
83286
83325
  return { skip: true, reason: "empty file" };
83287
83326
  }
83288
- const fd = fs69.openSync(filePath, "r");
83327
+ const fd = fs70.openSync(filePath, "r");
83289
83328
  const buffer = Buffer.alloc(8192);
83290
- const bytesRead = fs69.readSync(fd, buffer, 0, 8192, 0);
83291
- fs69.closeSync(fd);
83329
+ const bytesRead = fs70.readSync(fd, buffer, 0, 8192, 0);
83330
+ fs70.closeSync(fd);
83292
83331
  if (bytesRead > 0) {
83293
83332
  let nullCount = 0;
83294
83333
  for (let i2 = 0;i2 < bytesRead; i2++) {
@@ -83327,7 +83366,7 @@ function countBySeverity(findings) {
83327
83366
  }
83328
83367
  function scanFileWithTierA(filePath, language) {
83329
83368
  try {
83330
- const content = fs69.readFileSync(filePath, "utf-8");
83369
+ const content = fs70.readFileSync(filePath, "utf-8");
83331
83370
  const findings = executeRulesSync(filePath, content, language);
83332
83371
  return findings.map((f) => ({
83333
83372
  rule_id: f.rule_id,
@@ -83380,13 +83419,13 @@ async function sastScan(input, directory, config3) {
83380
83419
  _filesSkipped++;
83381
83420
  continue;
83382
83421
  }
83383
- const resolvedPath = path87.isAbsolute(filePath) ? filePath : path87.resolve(directory, filePath);
83384
- const resolvedDirectory = path87.resolve(directory);
83385
- if (!resolvedPath.startsWith(resolvedDirectory + path87.sep) && resolvedPath !== resolvedDirectory) {
83422
+ const resolvedPath = path88.isAbsolute(filePath) ? filePath : path88.resolve(directory, filePath);
83423
+ const resolvedDirectory = path88.resolve(directory);
83424
+ if (!resolvedPath.startsWith(resolvedDirectory + path88.sep) && resolvedPath !== resolvedDirectory) {
83386
83425
  _filesSkipped++;
83387
83426
  continue;
83388
83427
  }
83389
- if (!fs69.existsSync(resolvedPath)) {
83428
+ if (!fs70.existsSync(resolvedPath)) {
83390
83429
  _filesSkipped++;
83391
83430
  continue;
83392
83431
  }
@@ -83693,18 +83732,18 @@ function validatePath(inputPath, baseDir, workspaceDir) {
83693
83732
  let resolved;
83694
83733
  const isWinAbs = isWindowsAbsolutePath(inputPath);
83695
83734
  if (isWinAbs) {
83696
- resolved = path88.win32.resolve(inputPath);
83697
- } else if (path88.isAbsolute(inputPath)) {
83698
- resolved = path88.resolve(inputPath);
83735
+ resolved = path89.win32.resolve(inputPath);
83736
+ } else if (path89.isAbsolute(inputPath)) {
83737
+ resolved = path89.resolve(inputPath);
83699
83738
  } else {
83700
- resolved = path88.resolve(baseDir, inputPath);
83739
+ resolved = path89.resolve(baseDir, inputPath);
83701
83740
  }
83702
- const workspaceResolved = path88.resolve(workspaceDir);
83741
+ const workspaceResolved = path89.resolve(workspaceDir);
83703
83742
  let relative20;
83704
83743
  if (isWinAbs) {
83705
- relative20 = path88.win32.relative(workspaceResolved, resolved);
83744
+ relative20 = path89.win32.relative(workspaceResolved, resolved);
83706
83745
  } else {
83707
- relative20 = path88.relative(workspaceResolved, resolved);
83746
+ relative20 = path89.relative(workspaceResolved, resolved);
83708
83747
  }
83709
83748
  if (relative20.startsWith("..")) {
83710
83749
  return "path traversal detected";
@@ -83769,7 +83808,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
83769
83808
  if (typeof file3 !== "string") {
83770
83809
  continue;
83771
83810
  }
83772
- const resolvedPath = path88.resolve(file3);
83811
+ const resolvedPath = path89.resolve(file3);
83773
83812
  const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
83774
83813
  if (validationError) {
83775
83814
  continue;
@@ -83926,7 +83965,7 @@ async function runSecretscanWithFiles(files, directory) {
83926
83965
  skippedFiles++;
83927
83966
  continue;
83928
83967
  }
83929
- const resolvedPath = path88.resolve(file3);
83968
+ const resolvedPath = path89.resolve(file3);
83930
83969
  const validationError = validatePath(resolvedPath, directory, directory);
83931
83970
  if (validationError) {
83932
83971
  skippedFiles++;
@@ -83944,14 +83983,14 @@ async function runSecretscanWithFiles(files, directory) {
83944
83983
  };
83945
83984
  }
83946
83985
  for (const file3 of validatedFiles) {
83947
- const ext = path88.extname(file3).toLowerCase();
83986
+ const ext = path89.extname(file3).toLowerCase();
83948
83987
  if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
83949
83988
  skippedFiles++;
83950
83989
  continue;
83951
83990
  }
83952
83991
  let stat6;
83953
83992
  try {
83954
- stat6 = fs70.statSync(file3);
83993
+ stat6 = fs71.statSync(file3);
83955
83994
  } catch {
83956
83995
  skippedFiles++;
83957
83996
  continue;
@@ -83962,7 +84001,7 @@ async function runSecretscanWithFiles(files, directory) {
83962
84001
  }
83963
84002
  let content;
83964
84003
  try {
83965
- const buffer = fs70.readFileSync(file3);
84004
+ const buffer = fs71.readFileSync(file3);
83966
84005
  if (buffer.includes(0)) {
83967
84006
  skippedFiles++;
83968
84007
  continue;
@@ -84163,7 +84202,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
84163
84202
  const preexistingFindings = [];
84164
84203
  for (const finding of findings) {
84165
84204
  const filePath = finding.location.file;
84166
- const normalised = path88.relative(directory, filePath).replace(/\\/g, "/");
84205
+ const normalised = path89.relative(directory, filePath).replace(/\\/g, "/");
84167
84206
  const changedLines = changedLineRanges.get(normalised);
84168
84207
  if (changedLines?.has(finding.location.line)) {
84169
84208
  newFindings.push(finding);
@@ -84214,7 +84253,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
84214
84253
  warn(`pre_check_batch: Invalid file path: ${file3}`);
84215
84254
  continue;
84216
84255
  }
84217
- changedFiles.push(path88.resolve(directory, file3));
84256
+ changedFiles.push(path89.resolve(directory, file3));
84218
84257
  }
84219
84258
  if (changedFiles.length === 0) {
84220
84259
  warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
@@ -84415,7 +84454,7 @@ var pre_check_batch = createSwarmTool({
84415
84454
  };
84416
84455
  return JSON.stringify(errorResult, null, 2);
84417
84456
  }
84418
- const resolvedDirectory = path88.resolve(typedArgs.directory);
84457
+ const resolvedDirectory = path89.resolve(typedArgs.directory);
84419
84458
  const workspaceAnchor = resolvedDirectory;
84420
84459
  const dirError = validateDirectory2(resolvedDirectory, workspaceAnchor);
84421
84460
  if (dirError) {
@@ -84456,7 +84495,7 @@ var pre_check_batch = createSwarmTool({
84456
84495
  });
84457
84496
  // src/tools/repo-map.ts
84458
84497
  init_zod();
84459
- import * as path89 from "node:path";
84498
+ import * as path90 from "node:path";
84460
84499
  init_path_security();
84461
84500
  init_create_tool();
84462
84501
  var VALID_ACTIONS = [
@@ -84481,7 +84520,7 @@ function validateFile(p) {
84481
84520
  return "file contains control characters";
84482
84521
  if (containsPathTraversal(p))
84483
84522
  return "file contains path traversal";
84484
- if (path89.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
84523
+ if (path90.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
84485
84524
  return "file must be a workspace-relative path, not absolute";
84486
84525
  }
84487
84526
  return null;
@@ -84504,8 +84543,8 @@ function ok(action, payload) {
84504
84543
  }
84505
84544
  function toRelativeGraphPath(input, workspaceRoot) {
84506
84545
  const normalized = input.replace(/\\/g, "/");
84507
- if (path89.isAbsolute(normalized)) {
84508
- const rel = path89.relative(workspaceRoot, normalized).replace(/\\/g, "/");
84546
+ if (path90.isAbsolute(normalized)) {
84547
+ const rel = path90.relative(workspaceRoot, normalized).replace(/\\/g, "/");
84509
84548
  return normalizeGraphPath2(rel);
84510
84549
  }
84511
84550
  return normalizeGraphPath2(normalized);
@@ -84649,8 +84688,8 @@ var repo_map = createSwarmTool({
84649
84688
  // src/tools/req-coverage.ts
84650
84689
  init_zod();
84651
84690
  init_create_tool();
84652
- import * as fs71 from "node:fs";
84653
- import * as path90 from "node:path";
84691
+ import * as fs72 from "node:fs";
84692
+ import * as path91 from "node:path";
84654
84693
  var SPEC_FILE = ".swarm/spec.md";
84655
84694
  var EVIDENCE_DIR4 = ".swarm/evidence";
84656
84695
  var OBLIGATION_KEYWORDS = ["MUST", "SHOULD", "SHALL"];
@@ -84709,19 +84748,19 @@ function extractObligationAndText(id, lineText) {
84709
84748
  var PHASE_TASK_ID_REGEX = /^\d+\.\d+(\.\d+)*$/;
84710
84749
  function readTouchedFiles(evidenceDir, phase, cwd) {
84711
84750
  const touchedFiles = new Set;
84712
- if (!fs71.existsSync(evidenceDir) || !fs71.statSync(evidenceDir).isDirectory()) {
84751
+ if (!fs72.existsSync(evidenceDir) || !fs72.statSync(evidenceDir).isDirectory()) {
84713
84752
  return [];
84714
84753
  }
84715
84754
  let entries;
84716
84755
  try {
84717
- entries = fs71.readdirSync(evidenceDir);
84756
+ entries = fs72.readdirSync(evidenceDir);
84718
84757
  } catch {
84719
84758
  return [];
84720
84759
  }
84721
84760
  for (const entry of entries) {
84722
- const entryPath = path90.join(evidenceDir, entry);
84761
+ const entryPath = path91.join(evidenceDir, entry);
84723
84762
  try {
84724
- const stat6 = fs71.statSync(entryPath);
84763
+ const stat6 = fs72.statSync(entryPath);
84725
84764
  if (!stat6.isDirectory()) {
84726
84765
  continue;
84727
84766
  }
@@ -84735,14 +84774,14 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
84735
84774
  if (entryPhase !== String(phase)) {
84736
84775
  continue;
84737
84776
  }
84738
- const evidenceFilePath = path90.join(entryPath, "evidence.json");
84777
+ const evidenceFilePath = path91.join(entryPath, "evidence.json");
84739
84778
  try {
84740
- const resolvedPath = path90.resolve(evidenceFilePath);
84741
- const evidenceDirResolved = path90.resolve(evidenceDir);
84742
- if (!resolvedPath.startsWith(evidenceDirResolved + path90.sep)) {
84779
+ const resolvedPath = path91.resolve(evidenceFilePath);
84780
+ const evidenceDirResolved = path91.resolve(evidenceDir);
84781
+ if (!resolvedPath.startsWith(evidenceDirResolved + path91.sep)) {
84743
84782
  continue;
84744
84783
  }
84745
- const stat6 = fs71.lstatSync(evidenceFilePath);
84784
+ const stat6 = fs72.lstatSync(evidenceFilePath);
84746
84785
  if (!stat6.isFile()) {
84747
84786
  continue;
84748
84787
  }
@@ -84754,7 +84793,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
84754
84793
  }
84755
84794
  let content;
84756
84795
  try {
84757
- content = fs71.readFileSync(evidenceFilePath, "utf-8");
84796
+ content = fs72.readFileSync(evidenceFilePath, "utf-8");
84758
84797
  } catch {
84759
84798
  continue;
84760
84799
  }
@@ -84773,7 +84812,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
84773
84812
  if (Array.isArray(diffEntry.files_changed)) {
84774
84813
  for (const file3 of diffEntry.files_changed) {
84775
84814
  if (typeof file3 === "string") {
84776
- touchedFiles.add(path90.resolve(cwd, file3));
84815
+ touchedFiles.add(path91.resolve(cwd, file3));
84777
84816
  }
84778
84817
  }
84779
84818
  }
@@ -84786,12 +84825,12 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
84786
84825
  }
84787
84826
  function searchFileForKeywords(filePath, keywords, cwd) {
84788
84827
  try {
84789
- const resolvedPath = path90.resolve(filePath);
84790
- const cwdResolved = path90.resolve(cwd);
84828
+ const resolvedPath = path91.resolve(filePath);
84829
+ const cwdResolved = path91.resolve(cwd);
84791
84830
  if (!resolvedPath.startsWith(cwdResolved)) {
84792
84831
  return false;
84793
84832
  }
84794
- const content = fs71.readFileSync(resolvedPath, "utf-8");
84833
+ const content = fs72.readFileSync(resolvedPath, "utf-8");
84795
84834
  for (const keyword of keywords) {
84796
84835
  const regex = new RegExp(`\\b${keyword}\\b`, "i");
84797
84836
  if (regex.test(content)) {
@@ -84921,10 +84960,10 @@ var req_coverage = createSwarmTool({
84921
84960
  }, null, 2);
84922
84961
  }
84923
84962
  const cwd = inputDirectory || directory;
84924
- const specPath = path90.join(cwd, SPEC_FILE);
84963
+ const specPath = path91.join(cwd, SPEC_FILE);
84925
84964
  let specContent;
84926
84965
  try {
84927
- specContent = fs71.readFileSync(specPath, "utf-8");
84966
+ specContent = fs72.readFileSync(specPath, "utf-8");
84928
84967
  } catch (readError) {
84929
84968
  return JSON.stringify({
84930
84969
  success: false,
@@ -84948,7 +84987,7 @@ var req_coverage = createSwarmTool({
84948
84987
  message: "No FR requirements found in spec.md"
84949
84988
  }, null, 2);
84950
84989
  }
84951
- const evidenceDir = path90.join(cwd, EVIDENCE_DIR4);
84990
+ const evidenceDir = path91.join(cwd, EVIDENCE_DIR4);
84952
84991
  const touchedFiles = readTouchedFiles(evidenceDir, phase, cwd);
84953
84992
  const analyzedRequirements = [];
84954
84993
  let coveredCount = 0;
@@ -84974,12 +85013,12 @@ var req_coverage = createSwarmTool({
84974
85013
  requirements: analyzedRequirements
84975
85014
  };
84976
85015
  const reportFilename = `req-coverage-phase-${phase}.json`;
84977
- const reportPath = path90.join(evidenceDir, reportFilename);
85016
+ const reportPath = path91.join(evidenceDir, reportFilename);
84978
85017
  try {
84979
- if (!fs71.existsSync(evidenceDir)) {
84980
- fs71.mkdirSync(evidenceDir, { recursive: true });
85018
+ if (!fs72.existsSync(evidenceDir)) {
85019
+ fs72.mkdirSync(evidenceDir, { recursive: true });
84981
85020
  }
84982
- fs71.writeFileSync(reportPath, JSON.stringify(result, null, 2), "utf-8");
85021
+ fs72.writeFileSync(reportPath, JSON.stringify(result, null, 2), "utf-8");
84983
85022
  } catch (writeError) {
84984
85023
  console.warn(`Failed to write coverage report: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
84985
85024
  }
@@ -85061,8 +85100,8 @@ init_plan_schema();
85061
85100
  init_qa_gate_profile();
85062
85101
  init_file_locks();
85063
85102
  import * as crypto9 from "node:crypto";
85064
- import * as fs72 from "node:fs";
85065
- import * as path91 from "node:path";
85103
+ import * as fs73 from "node:fs";
85104
+ import * as path92 from "node:path";
85066
85105
  init_ledger();
85067
85106
  init_manager();
85068
85107
  init_state();
@@ -85140,17 +85179,17 @@ async function executeSavePlan(args2, fallbackDir) {
85140
85179
  };
85141
85180
  }
85142
85181
  if (args2.working_directory && fallbackDir) {
85143
- const resolvedTarget = path91.resolve(args2.working_directory);
85144
- const resolvedRoot = path91.resolve(fallbackDir);
85182
+ const resolvedTarget = path92.resolve(args2.working_directory);
85183
+ const resolvedRoot = path92.resolve(fallbackDir);
85145
85184
  let fallbackExists = false;
85146
85185
  try {
85147
- fs72.accessSync(resolvedRoot, fs72.constants.F_OK);
85186
+ fs73.accessSync(resolvedRoot, fs73.constants.F_OK);
85148
85187
  fallbackExists = true;
85149
85188
  } catch {
85150
85189
  fallbackExists = false;
85151
85190
  }
85152
85191
  if (fallbackExists) {
85153
- const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path91.sep);
85192
+ const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path92.sep);
85154
85193
  if (isSubdirectory) {
85155
85194
  return {
85156
85195
  success: false,
@@ -85166,11 +85205,11 @@ async function executeSavePlan(args2, fallbackDir) {
85166
85205
  let specMtime;
85167
85206
  let specHash;
85168
85207
  if (process.env.SWARM_SKIP_SPEC_GATE !== "1") {
85169
- const specPath = path91.join(targetWorkspace, ".swarm", "spec.md");
85208
+ const specPath = path92.join(targetWorkspace, ".swarm", "spec.md");
85170
85209
  try {
85171
- const stat6 = await fs72.promises.stat(specPath);
85210
+ const stat6 = await fs73.promises.stat(specPath);
85172
85211
  specMtime = stat6.mtime.toISOString();
85173
- const content = await fs72.promises.readFile(specPath, "utf8");
85212
+ const content = await fs73.promises.readFile(specPath, "utf8");
85174
85213
  specHash = crypto9.createHash("sha256").update(content).digest("hex");
85175
85214
  } catch {
85176
85215
  return {
@@ -85182,10 +85221,10 @@ async function executeSavePlan(args2, fallbackDir) {
85182
85221
  }
85183
85222
  }
85184
85223
  if (process.env.SWARM_SKIP_GATE_SELECTION !== "1") {
85185
- const contextPath = path91.join(targetWorkspace, ".swarm", "context.md");
85224
+ const contextPath = path92.join(targetWorkspace, ".swarm", "context.md");
85186
85225
  let contextContent = "";
85187
85226
  try {
85188
- contextContent = await fs72.promises.readFile(contextPath, "utf8");
85227
+ contextContent = await fs73.promises.readFile(contextPath, "utf8");
85189
85228
  } catch {}
85190
85229
  const hasPendingSection = contextContent.includes("## Pending QA Gate Selection");
85191
85230
  if (!hasPendingSection) {
@@ -85332,14 +85371,14 @@ async function executeSavePlan(args2, fallbackDir) {
85332
85371
  }
85333
85372
  await writeCheckpoint(dir).catch(() => {});
85334
85373
  try {
85335
- const markerPath = path91.join(dir, ".swarm", ".plan-write-marker");
85374
+ const markerPath = path92.join(dir, ".swarm", ".plan-write-marker");
85336
85375
  const marker = JSON.stringify({
85337
85376
  source: "save_plan",
85338
85377
  timestamp: new Date().toISOString(),
85339
85378
  phases_count: plan.phases.length,
85340
85379
  tasks_count: tasksCount
85341
85380
  });
85342
- await fs72.promises.writeFile(markerPath, marker, "utf8");
85381
+ await fs73.promises.writeFile(markerPath, marker, "utf8");
85343
85382
  } catch {}
85344
85383
  const warnings = [];
85345
85384
  let criticReviewFound = false;
@@ -85355,7 +85394,7 @@ async function executeSavePlan(args2, fallbackDir) {
85355
85394
  return {
85356
85395
  success: true,
85357
85396
  message: "Plan saved successfully",
85358
- plan_path: path91.join(dir, ".swarm", "plan.json"),
85397
+ plan_path: path92.join(dir, ".swarm", "plan.json"),
85359
85398
  phases_count: plan.phases.length,
85360
85399
  tasks_count: tasksCount,
85361
85400
  ...resolvedProfile !== undefined ? { execution_profile: resolvedProfile } : {},
@@ -85407,8 +85446,8 @@ var save_plan = createSwarmTool({
85407
85446
  // src/tools/sbom-generate.ts
85408
85447
  init_zod();
85409
85448
  init_manager2();
85410
- import * as fs73 from "node:fs";
85411
- import * as path92 from "node:path";
85449
+ import * as fs74 from "node:fs";
85450
+ import * as path93 from "node:path";
85412
85451
 
85413
85452
  // src/sbom/detectors/index.ts
85414
85453
  init_utils();
@@ -86256,9 +86295,9 @@ function findManifestFiles(rootDir) {
86256
86295
  const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
86257
86296
  function searchDir(dir) {
86258
86297
  try {
86259
- const entries = fs73.readdirSync(dir, { withFileTypes: true });
86298
+ const entries = fs74.readdirSync(dir, { withFileTypes: true });
86260
86299
  for (const entry of entries) {
86261
- const fullPath = path92.join(dir, entry.name);
86300
+ const fullPath = path93.join(dir, entry.name);
86262
86301
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
86263
86302
  continue;
86264
86303
  }
@@ -86267,7 +86306,7 @@ function findManifestFiles(rootDir) {
86267
86306
  } else if (entry.isFile()) {
86268
86307
  for (const pattern of patterns) {
86269
86308
  if (simpleGlobToRegex(pattern).test(entry.name)) {
86270
- manifestFiles.push(path92.relative(rootDir, fullPath));
86309
+ manifestFiles.push(path93.relative(rootDir, fullPath));
86271
86310
  break;
86272
86311
  }
86273
86312
  }
@@ -86283,13 +86322,13 @@ function findManifestFilesInDirs(directories, workingDir) {
86283
86322
  const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
86284
86323
  for (const dir of directories) {
86285
86324
  try {
86286
- const entries = fs73.readdirSync(dir, { withFileTypes: true });
86325
+ const entries = fs74.readdirSync(dir, { withFileTypes: true });
86287
86326
  for (const entry of entries) {
86288
- const fullPath = path92.join(dir, entry.name);
86327
+ const fullPath = path93.join(dir, entry.name);
86289
86328
  if (entry.isFile()) {
86290
86329
  for (const pattern of patterns) {
86291
86330
  if (simpleGlobToRegex(pattern).test(entry.name)) {
86292
- found.push(path92.relative(workingDir, fullPath));
86331
+ found.push(path93.relative(workingDir, fullPath));
86293
86332
  break;
86294
86333
  }
86295
86334
  }
@@ -86302,11 +86341,11 @@ function findManifestFilesInDirs(directories, workingDir) {
86302
86341
  function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
86303
86342
  const dirs = new Set;
86304
86343
  for (const file3 of changedFiles) {
86305
- let currentDir = path92.dirname(file3);
86344
+ let currentDir = path93.dirname(file3);
86306
86345
  while (true) {
86307
- if (currentDir && currentDir !== "." && currentDir !== path92.sep) {
86308
- dirs.add(path92.join(workingDir, currentDir));
86309
- const parent = path92.dirname(currentDir);
86346
+ if (currentDir && currentDir !== "." && currentDir !== path93.sep) {
86347
+ dirs.add(path93.join(workingDir, currentDir));
86348
+ const parent = path93.dirname(currentDir);
86310
86349
  if (parent === currentDir)
86311
86350
  break;
86312
86351
  currentDir = parent;
@@ -86320,7 +86359,7 @@ function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
86320
86359
  }
86321
86360
  function ensureOutputDir(outputDir) {
86322
86361
  try {
86323
- fs73.mkdirSync(outputDir, { recursive: true });
86362
+ fs74.mkdirSync(outputDir, { recursive: true });
86324
86363
  } catch (error93) {
86325
86364
  if (!error93 || error93.code !== "EEXIST") {
86326
86365
  throw error93;
@@ -86390,7 +86429,7 @@ var sbom_generate = createSwarmTool({
86390
86429
  const changedFiles = obj.changed_files;
86391
86430
  const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
86392
86431
  const workingDir = directory;
86393
- const outputDir = path92.isAbsolute(relativeOutputDir) ? relativeOutputDir : path92.join(workingDir, relativeOutputDir);
86432
+ const outputDir = path93.isAbsolute(relativeOutputDir) ? relativeOutputDir : path93.join(workingDir, relativeOutputDir);
86394
86433
  let manifestFiles = [];
86395
86434
  if (scope === "all") {
86396
86435
  manifestFiles = findManifestFiles(workingDir);
@@ -86413,11 +86452,11 @@ var sbom_generate = createSwarmTool({
86413
86452
  const processedFiles = [];
86414
86453
  for (const manifestFile of manifestFiles) {
86415
86454
  try {
86416
- const fullPath = path92.isAbsolute(manifestFile) ? manifestFile : path92.join(workingDir, manifestFile);
86417
- if (!fs73.existsSync(fullPath)) {
86455
+ const fullPath = path93.isAbsolute(manifestFile) ? manifestFile : path93.join(workingDir, manifestFile);
86456
+ if (!fs74.existsSync(fullPath)) {
86418
86457
  continue;
86419
86458
  }
86420
- const content = fs73.readFileSync(fullPath, "utf-8");
86459
+ const content = fs74.readFileSync(fullPath, "utf-8");
86421
86460
  const components = detectComponents(manifestFile, content);
86422
86461
  processedFiles.push(manifestFile);
86423
86462
  if (components.length > 0) {
@@ -86430,8 +86469,8 @@ var sbom_generate = createSwarmTool({
86430
86469
  const bom = generateCycloneDX(allComponents);
86431
86470
  const bomJson = serializeCycloneDX(bom);
86432
86471
  const filename = generateSbomFilename();
86433
- const outputPath = path92.join(outputDir, filename);
86434
- fs73.writeFileSync(outputPath, bomJson, "utf-8");
86472
+ const outputPath = path93.join(outputDir, filename);
86473
+ fs74.writeFileSync(outputPath, bomJson, "utf-8");
86435
86474
  const verdict = processedFiles.length > 0 ? "pass" : "pass";
86436
86475
  try {
86437
86476
  const timestamp = new Date().toISOString();
@@ -86473,8 +86512,8 @@ var sbom_generate = createSwarmTool({
86473
86512
  // src/tools/schema-drift.ts
86474
86513
  init_zod();
86475
86514
  init_create_tool();
86476
- import * as fs74 from "node:fs";
86477
- import * as path93 from "node:path";
86515
+ import * as fs75 from "node:fs";
86516
+ import * as path94 from "node:path";
86478
86517
  var SPEC_CANDIDATES = [
86479
86518
  "openapi.json",
86480
86519
  "openapi.yaml",
@@ -86506,28 +86545,28 @@ function normalizePath3(p) {
86506
86545
  }
86507
86546
  function discoverSpecFile(cwd, specFileArg) {
86508
86547
  if (specFileArg) {
86509
- const resolvedPath = path93.resolve(cwd, specFileArg);
86510
- const normalizedCwd = cwd.endsWith(path93.sep) ? cwd : cwd + path93.sep;
86548
+ const resolvedPath = path94.resolve(cwd, specFileArg);
86549
+ const normalizedCwd = cwd.endsWith(path94.sep) ? cwd : cwd + path94.sep;
86511
86550
  if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
86512
86551
  throw new Error("Invalid spec_file: path traversal detected");
86513
86552
  }
86514
- const ext = path93.extname(resolvedPath).toLowerCase();
86553
+ const ext = path94.extname(resolvedPath).toLowerCase();
86515
86554
  if (!ALLOWED_EXTENSIONS.includes(ext)) {
86516
86555
  throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
86517
86556
  }
86518
- const stats = fs74.statSync(resolvedPath);
86557
+ const stats = fs75.statSync(resolvedPath);
86519
86558
  if (stats.size > MAX_SPEC_SIZE) {
86520
86559
  throw new Error(`Invalid spec_file: file exceeds ${MAX_SPEC_SIZE / 1024 / 1024}MB limit`);
86521
86560
  }
86522
- if (!fs74.existsSync(resolvedPath)) {
86561
+ if (!fs75.existsSync(resolvedPath)) {
86523
86562
  throw new Error(`Spec file not found: ${resolvedPath}`);
86524
86563
  }
86525
86564
  return resolvedPath;
86526
86565
  }
86527
86566
  for (const candidate of SPEC_CANDIDATES) {
86528
- const candidatePath = path93.resolve(cwd, candidate);
86529
- if (fs74.existsSync(candidatePath)) {
86530
- const stats = fs74.statSync(candidatePath);
86567
+ const candidatePath = path94.resolve(cwd, candidate);
86568
+ if (fs75.existsSync(candidatePath)) {
86569
+ const stats = fs75.statSync(candidatePath);
86531
86570
  if (stats.size <= MAX_SPEC_SIZE) {
86532
86571
  return candidatePath;
86533
86572
  }
@@ -86536,8 +86575,8 @@ function discoverSpecFile(cwd, specFileArg) {
86536
86575
  return null;
86537
86576
  }
86538
86577
  function parseSpec(specFile) {
86539
- const content = fs74.readFileSync(specFile, "utf-8");
86540
- const ext = path93.extname(specFile).toLowerCase();
86578
+ const content = fs75.readFileSync(specFile, "utf-8");
86579
+ const ext = path94.extname(specFile).toLowerCase();
86541
86580
  if (ext === ".json") {
86542
86581
  return parseJsonSpec(content);
86543
86582
  }
@@ -86608,12 +86647,12 @@ function extractRoutes(cwd) {
86608
86647
  function walkDir(dir) {
86609
86648
  let entries;
86610
86649
  try {
86611
- entries = fs74.readdirSync(dir, { withFileTypes: true });
86650
+ entries = fs75.readdirSync(dir, { withFileTypes: true });
86612
86651
  } catch {
86613
86652
  return;
86614
86653
  }
86615
86654
  for (const entry of entries) {
86616
- const fullPath = path93.join(dir, entry.name);
86655
+ const fullPath = path94.join(dir, entry.name);
86617
86656
  if (entry.isSymbolicLink()) {
86618
86657
  continue;
86619
86658
  }
@@ -86623,7 +86662,7 @@ function extractRoutes(cwd) {
86623
86662
  }
86624
86663
  walkDir(fullPath);
86625
86664
  } else if (entry.isFile()) {
86626
- const ext = path93.extname(entry.name).toLowerCase();
86665
+ const ext = path94.extname(entry.name).toLowerCase();
86627
86666
  const baseName = entry.name.toLowerCase();
86628
86667
  if (![".ts", ".js", ".mjs"].includes(ext)) {
86629
86668
  continue;
@@ -86641,7 +86680,7 @@ function extractRoutes(cwd) {
86641
86680
  }
86642
86681
  function extractRoutesFromFile(filePath) {
86643
86682
  const routes = [];
86644
- const content = fs74.readFileSync(filePath, "utf-8");
86683
+ const content = fs75.readFileSync(filePath, "utf-8");
86645
86684
  const lines = content.split(/\r?\n/);
86646
86685
  const expressRegex = /(?:app|router|server|express)\.(get|post|put|patch|delete|options|head)\s*\(\s*['"`]([^'"`]+)['"`]/g;
86647
86686
  const flaskRegex = /@(?:app|blueprint|bp)\.route\s*\(\s*['"]([^'"]+)['"]/g;
@@ -86790,8 +86829,8 @@ init_zod();
86790
86829
  init_bun_compat();
86791
86830
  init_path_security();
86792
86831
  init_create_tool();
86793
- import * as fs75 from "node:fs";
86794
- import * as path94 from "node:path";
86832
+ import * as fs76 from "node:fs";
86833
+ import * as path95 from "node:path";
86795
86834
  var DEFAULT_MAX_RESULTS = 100;
86796
86835
  var DEFAULT_MAX_LINES = 200;
86797
86836
  var REGEX_TIMEOUT_MS = 5000;
@@ -86827,11 +86866,11 @@ function containsWindowsAttacks3(str) {
86827
86866
  }
86828
86867
  function isPathInWorkspace3(filePath, workspace) {
86829
86868
  try {
86830
- const resolvedPath = path94.resolve(workspace, filePath);
86831
- const realWorkspace = fs75.realpathSync(workspace);
86832
- const realResolvedPath = fs75.realpathSync(resolvedPath);
86833
- const relativePath = path94.relative(realWorkspace, realResolvedPath);
86834
- if (relativePath.startsWith("..") || path94.isAbsolute(relativePath)) {
86869
+ const resolvedPath = path95.resolve(workspace, filePath);
86870
+ const realWorkspace = fs76.realpathSync(workspace);
86871
+ const realResolvedPath = fs76.realpathSync(resolvedPath);
86872
+ const relativePath = path95.relative(realWorkspace, realResolvedPath);
86873
+ if (relativePath.startsWith("..") || path95.isAbsolute(relativePath)) {
86835
86874
  return false;
86836
86875
  }
86837
86876
  return true;
@@ -86844,12 +86883,12 @@ function validatePathForRead2(filePath, workspace) {
86844
86883
  }
86845
86884
  function findRgInEnvPath() {
86846
86885
  const searchPath = process.env.PATH ?? "";
86847
- for (const dir of searchPath.split(path94.delimiter)) {
86886
+ for (const dir of searchPath.split(path95.delimiter)) {
86848
86887
  if (!dir)
86849
86888
  continue;
86850
86889
  const isWindows = process.platform === "win32";
86851
- const candidate = path94.join(dir, isWindows ? "rg.exe" : "rg");
86852
- if (fs75.existsSync(candidate))
86890
+ const candidate = path95.join(dir, isWindows ? "rg.exe" : "rg");
86891
+ if (fs76.existsSync(candidate))
86853
86892
  return candidate;
86854
86893
  }
86855
86894
  return null;
@@ -86976,10 +87015,10 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
86976
87015
  return files;
86977
87016
  }
86978
87017
  try {
86979
- const entries = fs75.readdirSync(dir, { withFileTypes: true });
87018
+ const entries = fs76.readdirSync(dir, { withFileTypes: true });
86980
87019
  for (const entry of entries) {
86981
- const fullPath = path94.join(dir, entry.name);
86982
- const relativePath = path94.relative(workspace, fullPath);
87020
+ const fullPath = path95.join(dir, entry.name);
87021
+ const relativePath = path95.relative(workspace, fullPath);
86983
87022
  if (!validatePathForRead2(fullPath, workspace)) {
86984
87023
  continue;
86985
87024
  }
@@ -87020,13 +87059,13 @@ async function fallbackSearch(opts) {
87020
87059
  const matches = [];
87021
87060
  let total = 0;
87022
87061
  for (const file3 of files) {
87023
- const fullPath = path94.join(opts.workspace, file3);
87062
+ const fullPath = path95.join(opts.workspace, file3);
87024
87063
  if (!validatePathForRead2(fullPath, opts.workspace)) {
87025
87064
  continue;
87026
87065
  }
87027
87066
  let stats;
87028
87067
  try {
87029
- stats = fs75.statSync(fullPath);
87068
+ stats = fs76.statSync(fullPath);
87030
87069
  if (stats.size > MAX_FILE_SIZE_BYTES10) {
87031
87070
  continue;
87032
87071
  }
@@ -87035,7 +87074,7 @@ async function fallbackSearch(opts) {
87035
87074
  }
87036
87075
  let content;
87037
87076
  try {
87038
- content = fs75.readFileSync(fullPath, "utf-8");
87077
+ content = fs76.readFileSync(fullPath, "utf-8");
87039
87078
  } catch {
87040
87079
  continue;
87041
87080
  }
@@ -87147,7 +87186,7 @@ var search = createSwarmTool({
87147
87186
  message: "Exclude pattern contains invalid Windows-specific sequence"
87148
87187
  }, null, 2);
87149
87188
  }
87150
- if (!fs75.existsSync(directory)) {
87189
+ if (!fs76.existsSync(directory)) {
87151
87190
  return JSON.stringify({
87152
87191
  error: true,
87153
87192
  type: "unknown",
@@ -87276,8 +87315,8 @@ var set_qa_gates = createSwarmTool({
87276
87315
  init_zod();
87277
87316
  init_path_security();
87278
87317
  init_create_tool();
87279
- import * as fs76 from "node:fs";
87280
- import * as path95 from "node:path";
87318
+ import * as fs77 from "node:fs";
87319
+ import * as path96 from "node:path";
87281
87320
  var WINDOWS_RESERVED_NAMES4 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
87282
87321
  function containsWindowsAttacks4(str) {
87283
87322
  if (/:[^\\/]/.test(str))
@@ -87291,14 +87330,14 @@ function containsWindowsAttacks4(str) {
87291
87330
  }
87292
87331
  function isPathInWorkspace4(filePath, workspace) {
87293
87332
  try {
87294
- const resolvedPath = path95.resolve(workspace, filePath);
87295
- if (!fs76.existsSync(resolvedPath)) {
87333
+ const resolvedPath = path96.resolve(workspace, filePath);
87334
+ if (!fs77.existsSync(resolvedPath)) {
87296
87335
  return true;
87297
87336
  }
87298
- const realWorkspace = fs76.realpathSync(workspace);
87299
- const realResolvedPath = fs76.realpathSync(resolvedPath);
87300
- const relativePath = path95.relative(realWorkspace, realResolvedPath);
87301
- if (relativePath.startsWith("..") || path95.isAbsolute(relativePath)) {
87337
+ const realWorkspace = fs77.realpathSync(workspace);
87338
+ const realResolvedPath = fs77.realpathSync(resolvedPath);
87339
+ const relativePath = path96.relative(realWorkspace, realResolvedPath);
87340
+ if (relativePath.startsWith("..") || path96.isAbsolute(relativePath)) {
87302
87341
  return false;
87303
87342
  }
87304
87343
  return true;
@@ -87470,7 +87509,7 @@ var suggestPatch = createSwarmTool({
87470
87509
  message: "changes cannot be empty"
87471
87510
  }, null, 2);
87472
87511
  }
87473
- if (!fs76.existsSync(directory)) {
87512
+ if (!fs77.existsSync(directory)) {
87474
87513
  return JSON.stringify({
87475
87514
  success: false,
87476
87515
  error: true,
@@ -87506,8 +87545,8 @@ var suggestPatch = createSwarmTool({
87506
87545
  });
87507
87546
  continue;
87508
87547
  }
87509
- const fullPath = path95.resolve(directory, change.file);
87510
- if (!fs76.existsSync(fullPath)) {
87548
+ const fullPath = path96.resolve(directory, change.file);
87549
+ if (!fs77.existsSync(fullPath)) {
87511
87550
  errors5.push({
87512
87551
  success: false,
87513
87552
  error: true,
@@ -87521,7 +87560,7 @@ var suggestPatch = createSwarmTool({
87521
87560
  }
87522
87561
  let content;
87523
87562
  try {
87524
- content = fs76.readFileSync(fullPath, "utf-8");
87563
+ content = fs77.readFileSync(fullPath, "utf-8");
87525
87564
  } catch (err3) {
87526
87565
  errors5.push({
87527
87566
  success: false,
@@ -87768,8 +87807,8 @@ var generate_mutants = createSwarmTool({
87768
87807
  // src/tools/lint-spec.ts
87769
87808
  init_spec_schema();
87770
87809
  init_create_tool();
87771
- import * as fs77 from "node:fs";
87772
- import * as path96 from "node:path";
87810
+ import * as fs78 from "node:fs";
87811
+ import * as path97 from "node:path";
87773
87812
  var SPEC_FILE_NAME = "spec.md";
87774
87813
  var SWARM_DIR2 = ".swarm";
87775
87814
  var OBLIGATION_KEYWORDS2 = ["MUST", "SHALL", "SHOULD", "MAY"];
@@ -87822,8 +87861,8 @@ var lint_spec = createSwarmTool({
87822
87861
  async execute(_args, directory) {
87823
87862
  const errors5 = [];
87824
87863
  const warnings = [];
87825
- const specPath = path96.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
87826
- if (!fs77.existsSync(specPath)) {
87864
+ const specPath = path97.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
87865
+ if (!fs78.existsSync(specPath)) {
87827
87866
  const result2 = {
87828
87867
  valid: false,
87829
87868
  specMtime: null,
@@ -87842,12 +87881,12 @@ var lint_spec = createSwarmTool({
87842
87881
  }
87843
87882
  let specMtime = null;
87844
87883
  try {
87845
- const stats = fs77.statSync(specPath);
87884
+ const stats = fs78.statSync(specPath);
87846
87885
  specMtime = stats.mtime.toISOString();
87847
87886
  } catch {}
87848
87887
  let content;
87849
87888
  try {
87850
- content = fs77.readFileSync(specPath, "utf-8");
87889
+ content = fs78.readFileSync(specPath, "utf-8");
87851
87890
  } catch (e) {
87852
87891
  const result2 = {
87853
87892
  valid: false,
@@ -87892,13 +87931,13 @@ var lint_spec = createSwarmTool({
87892
87931
  });
87893
87932
  // src/tools/mutation-test.ts
87894
87933
  init_zod();
87895
- import * as fs78 from "node:fs";
87896
- import * as path98 from "node:path";
87934
+ import * as fs79 from "node:fs";
87935
+ import * as path99 from "node:path";
87897
87936
 
87898
87937
  // src/mutation/engine.ts
87899
87938
  import { spawnSync as spawnSync3 } from "node:child_process";
87900
- import { unlinkSync as unlinkSync13, writeFileSync as writeFileSync19 } from "node:fs";
87901
- import * as path97 from "node:path";
87939
+ import { unlinkSync as unlinkSync13, writeFileSync as writeFileSync20 } from "node:fs";
87940
+ import * as path98 from "node:path";
87902
87941
 
87903
87942
  // src/mutation/equivalence.ts
87904
87943
  function isStaticallyEquivalent(originalCode, mutatedCode) {
@@ -88033,9 +88072,9 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
88033
88072
  let patchFile;
88034
88073
  try {
88035
88074
  const safeId2 = patch.id.replace(/[^a-zA-Z0-9_-]/g, "_");
88036
- patchFile = path97.join(workingDir, `.mutation_patch_${safeId2}.diff`);
88075
+ patchFile = path98.join(workingDir, `.mutation_patch_${safeId2}.diff`);
88037
88076
  try {
88038
- writeFileSync19(patchFile, patch.patch);
88077
+ writeFileSync20(patchFile, patch.patch);
88039
88078
  } catch (writeErr) {
88040
88079
  error93 = `Failed to write patch file: ${writeErr}`;
88041
88080
  outcome = "error";
@@ -88427,8 +88466,8 @@ var mutation_test = createSwarmTool({
88427
88466
  ];
88428
88467
  for (const filePath of uniquePaths) {
88429
88468
  try {
88430
- const resolvedPath = path98.resolve(cwd, filePath);
88431
- sourceFiles.set(filePath, fs78.readFileSync(resolvedPath, "utf-8"));
88469
+ const resolvedPath = path99.resolve(cwd, filePath);
88470
+ sourceFiles.set(filePath, fs79.readFileSync(resolvedPath, "utf-8"));
88432
88471
  } catch {}
88433
88472
  }
88434
88473
  const report = await executeMutationSuite(typedArgs.patches, typedArgs.test_command, typedArgs.files, cwd, undefined, undefined, sourceFiles.size > 0 ? sourceFiles : undefined);
@@ -88446,8 +88485,8 @@ var mutation_test = createSwarmTool({
88446
88485
  init_zod();
88447
88486
  init_manager2();
88448
88487
  init_detector();
88449
- import * as fs79 from "node:fs";
88450
- import * as path99 from "node:path";
88488
+ import * as fs80 from "node:fs";
88489
+ import * as path100 from "node:path";
88451
88490
  init_create_tool();
88452
88491
  var MAX_FILE_SIZE2 = 2 * 1024 * 1024;
88453
88492
  var BINARY_CHECK_BYTES = 8192;
@@ -88513,7 +88552,7 @@ async function syntaxCheck(input, directory, config3) {
88513
88552
  if (languages?.length) {
88514
88553
  const lowerLangs = languages.map((l) => l.toLowerCase());
88515
88554
  filesToCheck = filesToCheck.filter((file3) => {
88516
- const ext = path99.extname(file3.path).toLowerCase();
88555
+ const ext = path100.extname(file3.path).toLowerCase();
88517
88556
  const langDef = getLanguageForExtension(ext);
88518
88557
  const fileProfile = getProfileForFile(file3.path);
88519
88558
  const langId = fileProfile?.id || langDef?.id;
@@ -88526,7 +88565,7 @@ async function syntaxCheck(input, directory, config3) {
88526
88565
  let skippedCount = 0;
88527
88566
  for (const fileInfo of filesToCheck) {
88528
88567
  const { path: filePath } = fileInfo;
88529
- const fullPath = path99.isAbsolute(filePath) ? filePath : path99.join(directory, filePath);
88568
+ const fullPath = path100.isAbsolute(filePath) ? filePath : path100.join(directory, filePath);
88530
88569
  const result = {
88531
88570
  path: filePath,
88532
88571
  language: "",
@@ -88556,7 +88595,7 @@ async function syntaxCheck(input, directory, config3) {
88556
88595
  }
88557
88596
  let content;
88558
88597
  try {
88559
- content = fs79.readFileSync(fullPath, "utf8");
88598
+ content = fs80.readFileSync(fullPath, "utf8");
88560
88599
  } catch {
88561
88600
  result.skipped_reason = "file_read_error";
88562
88601
  skippedCount++;
@@ -88575,7 +88614,7 @@ async function syntaxCheck(input, directory, config3) {
88575
88614
  results.push(result);
88576
88615
  continue;
88577
88616
  }
88578
- const ext = path99.extname(filePath).toLowerCase();
88617
+ const ext = path100.extname(filePath).toLowerCase();
88579
88618
  const langDef = getLanguageForExtension(ext);
88580
88619
  result.language = profile?.id || langDef?.id || "unknown";
88581
88620
  const errors5 = extractSyntaxErrors(parser, content);
@@ -88667,8 +88706,8 @@ init_zod();
88667
88706
  init_utils();
88668
88707
  init_create_tool();
88669
88708
  init_path_security();
88670
- import * as fs80 from "node:fs";
88671
- import * as path100 from "node:path";
88709
+ import * as fs81 from "node:fs";
88710
+ import * as path101 from "node:path";
88672
88711
  var MAX_TEXT_LENGTH = 200;
88673
88712
  var MAX_FILE_SIZE_BYTES11 = 1024 * 1024;
88674
88713
  var SUPPORTED_EXTENSIONS4 = new Set([
@@ -88734,9 +88773,9 @@ function validatePathsInput(paths, cwd) {
88734
88773
  return { error: "paths contains path traversal", resolvedPath: null };
88735
88774
  }
88736
88775
  try {
88737
- const resolvedPath = path100.resolve(paths);
88738
- const normalizedCwd = path100.resolve(cwd);
88739
- const normalizedResolved = path100.resolve(resolvedPath);
88776
+ const resolvedPath = path101.resolve(paths);
88777
+ const normalizedCwd = path101.resolve(cwd);
88778
+ const normalizedResolved = path101.resolve(resolvedPath);
88740
88779
  if (!normalizedResolved.startsWith(normalizedCwd)) {
88741
88780
  return {
88742
88781
  error: "paths must be within the current working directory",
@@ -88752,13 +88791,13 @@ function validatePathsInput(paths, cwd) {
88752
88791
  }
88753
88792
  }
88754
88793
  function isSupportedExtension(filePath) {
88755
- const ext = path100.extname(filePath).toLowerCase();
88794
+ const ext = path101.extname(filePath).toLowerCase();
88756
88795
  return SUPPORTED_EXTENSIONS4.has(ext);
88757
88796
  }
88758
88797
  function findSourceFiles3(dir, files = []) {
88759
88798
  let entries;
88760
88799
  try {
88761
- entries = fs80.readdirSync(dir);
88800
+ entries = fs81.readdirSync(dir);
88762
88801
  } catch {
88763
88802
  return files;
88764
88803
  }
@@ -88767,10 +88806,10 @@ function findSourceFiles3(dir, files = []) {
88767
88806
  if (SKIP_DIRECTORIES5.has(entry)) {
88768
88807
  continue;
88769
88808
  }
88770
- const fullPath = path100.join(dir, entry);
88809
+ const fullPath = path101.join(dir, entry);
88771
88810
  let stat6;
88772
88811
  try {
88773
- stat6 = fs80.statSync(fullPath);
88812
+ stat6 = fs81.statSync(fullPath);
88774
88813
  } catch {
88775
88814
  continue;
88776
88815
  }
@@ -88863,7 +88902,7 @@ var todo_extract = createSwarmTool({
88863
88902
  return JSON.stringify(errorResult, null, 2);
88864
88903
  }
88865
88904
  const scanPath = resolvedPath;
88866
- if (!fs80.existsSync(scanPath)) {
88905
+ if (!fs81.existsSync(scanPath)) {
88867
88906
  const errorResult = {
88868
88907
  error: `path not found: ${pathsInput}`,
88869
88908
  total: 0,
@@ -88873,13 +88912,13 @@ var todo_extract = createSwarmTool({
88873
88912
  return JSON.stringify(errorResult, null, 2);
88874
88913
  }
88875
88914
  const filesToScan = [];
88876
- const stat6 = fs80.statSync(scanPath);
88915
+ const stat6 = fs81.statSync(scanPath);
88877
88916
  if (stat6.isFile()) {
88878
88917
  if (isSupportedExtension(scanPath)) {
88879
88918
  filesToScan.push(scanPath);
88880
88919
  } else {
88881
88920
  const errorResult = {
88882
- error: `unsupported file extension: ${path100.extname(scanPath)}`,
88921
+ error: `unsupported file extension: ${path101.extname(scanPath)}`,
88883
88922
  total: 0,
88884
88923
  byPriority: { high: 0, medium: 0, low: 0 },
88885
88924
  entries: []
@@ -88892,11 +88931,11 @@ var todo_extract = createSwarmTool({
88892
88931
  const allEntries = [];
88893
88932
  for (const filePath of filesToScan) {
88894
88933
  try {
88895
- const fileStat = fs80.statSync(filePath);
88934
+ const fileStat = fs81.statSync(filePath);
88896
88935
  if (fileStat.size > MAX_FILE_SIZE_BYTES11) {
88897
88936
  continue;
88898
88937
  }
88899
- const content = fs80.readFileSync(filePath, "utf-8");
88938
+ const content = fs81.readFileSync(filePath, "utf-8");
88900
88939
  const entries = parseTodoComments(content, filePath, tagsSet);
88901
88940
  allEntries.push(...entries);
88902
88941
  } catch {}
@@ -88927,19 +88966,19 @@ init_loader();
88927
88966
  init_schema();
88928
88967
  init_qa_gate_profile();
88929
88968
  init_gate_evidence();
88930
- import * as fs82 from "node:fs";
88931
- import * as path102 from "node:path";
88969
+ import * as fs83 from "node:fs";
88970
+ import * as path103 from "node:path";
88932
88971
 
88933
88972
  // src/hooks/diff-scope.ts
88934
88973
  init_bun_compat();
88935
- import * as fs81 from "node:fs";
88936
- import * as path101 from "node:path";
88974
+ import * as fs82 from "node:fs";
88975
+ import * as path102 from "node:path";
88937
88976
  function getDeclaredScope(taskId, directory) {
88938
88977
  try {
88939
- const planPath = path101.join(directory, ".swarm", "plan.json");
88940
- if (!fs81.existsSync(planPath))
88978
+ const planPath = path102.join(directory, ".swarm", "plan.json");
88979
+ if (!fs82.existsSync(planPath))
88941
88980
  return null;
88942
- const raw = fs81.readFileSync(planPath, "utf-8");
88981
+ const raw = fs82.readFileSync(planPath, "utf-8");
88943
88982
  const plan = JSON.parse(raw);
88944
88983
  for (const phase of plan.phases ?? []) {
88945
88984
  for (const task of phase.tasks ?? []) {
@@ -89055,7 +89094,7 @@ var TIER_3_PATTERNS = [
89055
89094
  ];
89056
89095
  function matchesTier3Pattern(files) {
89057
89096
  for (const file3 of files) {
89058
- const fileName = path102.basename(file3);
89097
+ const fileName = path103.basename(file3);
89059
89098
  for (const pattern of TIER_3_PATTERNS) {
89060
89099
  if (pattern.test(fileName)) {
89061
89100
  return true;
@@ -89069,8 +89108,8 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
89069
89108
  if (hasActiveTurboMode()) {
89070
89109
  const resolvedDir2 = workingDirectory;
89071
89110
  try {
89072
- const planPath = path102.join(resolvedDir2, ".swarm", "plan.json");
89073
- const planRaw = fs82.readFileSync(planPath, "utf-8");
89111
+ const planPath = path103.join(resolvedDir2, ".swarm", "plan.json");
89112
+ const planRaw = fs83.readFileSync(planPath, "utf-8");
89074
89113
  const plan = JSON.parse(planRaw);
89075
89114
  for (const planPhase of plan.phases ?? []) {
89076
89115
  for (const task of planPhase.tasks ?? []) {
@@ -89139,8 +89178,8 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
89139
89178
  }
89140
89179
  try {
89141
89180
  const resolvedDir2 = workingDirectory;
89142
- const planPath = path102.join(resolvedDir2, ".swarm", "plan.json");
89143
- const planRaw = fs82.readFileSync(planPath, "utf-8");
89181
+ const planPath = path103.join(resolvedDir2, ".swarm", "plan.json");
89182
+ const planRaw = fs83.readFileSync(planPath, "utf-8");
89144
89183
  const plan = JSON.parse(planRaw);
89145
89184
  for (const planPhase of plan.phases ?? []) {
89146
89185
  for (const task of planPhase.tasks ?? []) {
@@ -89297,8 +89336,8 @@ function checkCouncilGate(workingDirectory, taskId) {
89297
89336
  return { blocked: false, reason: "" };
89298
89337
  }
89299
89338
  try {
89300
- const planPath = path102.join(workingDirectory, ".swarm", "plan.json");
89301
- const planRaw = fs82.readFileSync(planPath, "utf-8");
89339
+ const planPath = path103.join(workingDirectory, ".swarm", "plan.json");
89340
+ const planRaw = fs83.readFileSync(planPath, "utf-8");
89302
89341
  const planObj = JSON.parse(planRaw);
89303
89342
  if (planObj.swarm && planObj.title) {
89304
89343
  const planId = `${planObj.swarm}-${planObj.title}`.replace(/[^a-zA-Z0-9-_]/g, "_");
@@ -89388,8 +89427,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
89388
89427
  };
89389
89428
  }
89390
89429
  }
89391
- normalizedDir = path102.normalize(args2.working_directory);
89392
- const pathParts = normalizedDir.split(path102.sep);
89430
+ normalizedDir = path103.normalize(args2.working_directory);
89431
+ const pathParts = normalizedDir.split(path103.sep);
89393
89432
  if (pathParts.includes("..")) {
89394
89433
  return {
89395
89434
  success: false,
@@ -89399,11 +89438,11 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
89399
89438
  ]
89400
89439
  };
89401
89440
  }
89402
- const resolvedDir = path102.resolve(normalizedDir);
89441
+ const resolvedDir = path103.resolve(normalizedDir);
89403
89442
  try {
89404
- const realPath = fs82.realpathSync(resolvedDir);
89405
- const planPath = path102.join(realPath, ".swarm", "plan.json");
89406
- if (!fs82.existsSync(planPath)) {
89443
+ const realPath = fs83.realpathSync(resolvedDir);
89444
+ const planPath = path103.join(realPath, ".swarm", "plan.json");
89445
+ if (!fs83.existsSync(planPath)) {
89407
89446
  return {
89408
89447
  success: false,
89409
89448
  message: `Invalid working_directory: plan not found in "${realPath}"`,
@@ -89434,22 +89473,22 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
89434
89473
  }
89435
89474
  if (args2.status === "in_progress") {
89436
89475
  try {
89437
- const evidencePath = path102.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
89438
- fs82.mkdirSync(path102.dirname(evidencePath), { recursive: true });
89439
- const fd = fs82.openSync(evidencePath, "wx");
89476
+ const evidencePath = path103.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
89477
+ fs83.mkdirSync(path103.dirname(evidencePath), { recursive: true });
89478
+ const fd = fs83.openSync(evidencePath, "wx");
89440
89479
  let writeOk = false;
89441
89480
  try {
89442
- fs82.writeSync(fd, JSON.stringify({
89481
+ fs83.writeSync(fd, JSON.stringify({
89443
89482
  taskId: args2.task_id,
89444
89483
  required_gates: ["reviewer", "test_engineer"],
89445
89484
  gates: {}
89446
89485
  }, null, 2));
89447
89486
  writeOk = true;
89448
89487
  } finally {
89449
- fs82.closeSync(fd);
89488
+ fs83.closeSync(fd);
89450
89489
  if (!writeOk) {
89451
89490
  try {
89452
- fs82.unlinkSync(evidencePath);
89491
+ fs83.unlinkSync(evidencePath);
89453
89492
  } catch {}
89454
89493
  }
89455
89494
  }
@@ -89459,8 +89498,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir) {
89459
89498
  recoverTaskStateFromDelegations(args2.task_id);
89460
89499
  let phaseRequiresReviewer = true;
89461
89500
  try {
89462
- const planPath = path102.join(directory, ".swarm", "plan.json");
89463
- const planRaw = fs82.readFileSync(planPath, "utf-8");
89501
+ const planPath = path103.join(directory, ".swarm", "plan.json");
89502
+ const planRaw = fs83.readFileSync(planPath, "utf-8");
89464
89503
  const plan = JSON.parse(planRaw);
89465
89504
  const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
89466
89505
  if (taskPhase?.required_agents && !taskPhase.required_agents.includes("reviewer")) {
@@ -89778,8 +89817,8 @@ init_utils2();
89778
89817
  init_ledger();
89779
89818
  init_manager();
89780
89819
  init_create_tool();
89781
- import fs83 from "node:fs";
89782
- import path103 from "node:path";
89820
+ import fs84 from "node:fs";
89821
+ import path104 from "node:path";
89783
89822
  function derivePlanId5(plan) {
89784
89823
  return `${plan.swarm}-${plan.title}`.replace(/[^a-zA-Z0-9-_]/g, "_");
89785
89824
  }
@@ -89830,7 +89869,7 @@ async function executeWriteDriftEvidence(args2, directory) {
89830
89869
  entries: [evidenceEntry]
89831
89870
  };
89832
89871
  const filename = "drift-verifier.json";
89833
- const relativePath = path103.join("evidence", String(phase), filename);
89872
+ const relativePath = path104.join("evidence", String(phase), filename);
89834
89873
  let validatedPath;
89835
89874
  try {
89836
89875
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -89841,12 +89880,12 @@ async function executeWriteDriftEvidence(args2, directory) {
89841
89880
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
89842
89881
  }, null, 2);
89843
89882
  }
89844
- const evidenceDir = path103.dirname(validatedPath);
89883
+ const evidenceDir = path104.dirname(validatedPath);
89845
89884
  try {
89846
- await fs83.promises.mkdir(evidenceDir, { recursive: true });
89847
- const tempPath = path103.join(evidenceDir, `.${filename}.tmp`);
89848
- await fs83.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
89849
- await fs83.promises.rename(tempPath, validatedPath);
89885
+ await fs84.promises.mkdir(evidenceDir, { recursive: true });
89886
+ const tempPath = path104.join(evidenceDir, `.${filename}.tmp`);
89887
+ await fs84.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
89888
+ await fs84.promises.rename(tempPath, validatedPath);
89850
89889
  let snapshotInfo;
89851
89890
  let snapshotError;
89852
89891
  let qaProfileLocked;
@@ -89940,8 +89979,8 @@ var write_drift_evidence = createSwarmTool({
89940
89979
  init_zod();
89941
89980
  init_utils2();
89942
89981
  init_create_tool();
89943
- import fs84 from "node:fs";
89944
- import path104 from "node:path";
89982
+ import fs85 from "node:fs";
89983
+ import path105 from "node:path";
89945
89984
  function normalizeVerdict2(verdict) {
89946
89985
  switch (verdict) {
89947
89986
  case "APPROVED":
@@ -89989,7 +90028,7 @@ async function executeWriteHallucinationEvidence(args2, directory) {
89989
90028
  entries: [evidenceEntry]
89990
90029
  };
89991
90030
  const filename = "hallucination-guard.json";
89992
- const relativePath = path104.join("evidence", String(phase), filename);
90031
+ const relativePath = path105.join("evidence", String(phase), filename);
89993
90032
  let validatedPath;
89994
90033
  try {
89995
90034
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -90000,12 +90039,12 @@ async function executeWriteHallucinationEvidence(args2, directory) {
90000
90039
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
90001
90040
  }, null, 2);
90002
90041
  }
90003
- const evidenceDir = path104.dirname(validatedPath);
90042
+ const evidenceDir = path105.dirname(validatedPath);
90004
90043
  try {
90005
- await fs84.promises.mkdir(evidenceDir, { recursive: true });
90006
- const tempPath = path104.join(evidenceDir, `.${filename}.tmp`);
90007
- await fs84.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
90008
- await fs84.promises.rename(tempPath, validatedPath);
90044
+ await fs85.promises.mkdir(evidenceDir, { recursive: true });
90045
+ const tempPath = path105.join(evidenceDir, `.${filename}.tmp`);
90046
+ await fs85.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
90047
+ await fs85.promises.rename(tempPath, validatedPath);
90009
90048
  return JSON.stringify({
90010
90049
  success: true,
90011
90050
  phase,
@@ -90051,8 +90090,8 @@ var write_hallucination_evidence = createSwarmTool({
90051
90090
  init_zod();
90052
90091
  init_utils2();
90053
90092
  init_create_tool();
90054
- import fs85 from "node:fs";
90055
- import path105 from "node:path";
90093
+ import fs86 from "node:fs";
90094
+ import path106 from "node:path";
90056
90095
  function normalizeVerdict3(verdict) {
90057
90096
  switch (verdict) {
90058
90097
  case "PASS":
@@ -90126,7 +90165,7 @@ async function executeWriteMutationEvidence(args2, directory) {
90126
90165
  entries: [evidenceEntry]
90127
90166
  };
90128
90167
  const filename = "mutation-gate.json";
90129
- const relativePath = path105.join("evidence", String(phase), filename);
90168
+ const relativePath = path106.join("evidence", String(phase), filename);
90130
90169
  let validatedPath;
90131
90170
  try {
90132
90171
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -90137,12 +90176,12 @@ async function executeWriteMutationEvidence(args2, directory) {
90137
90176
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
90138
90177
  }, null, 2);
90139
90178
  }
90140
- const evidenceDir = path105.dirname(validatedPath);
90179
+ const evidenceDir = path106.dirname(validatedPath);
90141
90180
  try {
90142
- await fs85.promises.mkdir(evidenceDir, { recursive: true });
90143
- const tempPath = path105.join(evidenceDir, `.${filename}.tmp`);
90144
- await fs85.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
90145
- await fs85.promises.rename(tempPath, validatedPath);
90181
+ await fs86.promises.mkdir(evidenceDir, { recursive: true });
90182
+ const tempPath = path106.join(evidenceDir, `.${filename}.tmp`);
90183
+ await fs86.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
90184
+ await fs86.promises.rename(tempPath, validatedPath);
90146
90185
  return JSON.stringify({
90147
90186
  success: true,
90148
90187
  phase,
@@ -90196,20 +90235,20 @@ init_write_retro();
90196
90235
  init_utils();
90197
90236
 
90198
90237
  // src/utils/gitignore-warning.ts
90199
- import * as fs86 from "node:fs";
90200
- import * as path106 from "node:path";
90238
+ import * as fs87 from "node:fs";
90239
+ import * as path107 from "node:path";
90201
90240
  var _gitignoreWarningEmitted = false;
90202
90241
  function findGitRoot(startDir) {
90203
90242
  let current = startDir;
90204
90243
  while (true) {
90205
90244
  try {
90206
- const gitPath = path106.join(current, ".git");
90207
- const stat6 = fs86.statSync(gitPath);
90245
+ const gitPath = path107.join(current, ".git");
90246
+ const stat6 = fs87.statSync(gitPath);
90208
90247
  if (stat6.isDirectory()) {
90209
90248
  return current;
90210
90249
  }
90211
90250
  } catch {}
90212
- const parent = path106.dirname(current);
90251
+ const parent = path107.dirname(current);
90213
90252
  if (parent === current) {
90214
90253
  return null;
90215
90254
  }
@@ -90229,7 +90268,7 @@ function fileCoversSwarm(content) {
90229
90268
  }
90230
90269
  function readFileSafe(filePath) {
90231
90270
  try {
90232
- return fs86.readFileSync(filePath, "utf8");
90271
+ return fs87.readFileSync(filePath, "utf8");
90233
90272
  } catch {
90234
90273
  return null;
90235
90274
  }
@@ -90241,12 +90280,12 @@ function warnIfSwarmNotGitignored(directory, quiet = false) {
90241
90280
  const gitRoot = findGitRoot(directory);
90242
90281
  if (!gitRoot)
90243
90282
  return;
90244
- const gitignoreContent = readFileSafe(path106.join(gitRoot, ".gitignore"));
90283
+ const gitignoreContent = readFileSafe(path107.join(gitRoot, ".gitignore"));
90245
90284
  if (gitignoreContent !== null && fileCoversSwarm(gitignoreContent)) {
90246
90285
  _gitignoreWarningEmitted = true;
90247
90286
  return;
90248
90287
  }
90249
- const excludeContent = readFileSafe(path106.join(gitRoot, ".git", "info", "exclude"));
90288
+ const excludeContent = readFileSafe(path107.join(gitRoot, ".git", "info", "exclude"));
90250
90289
  if (excludeContent !== null && fileCoversSwarm(excludeContent)) {
90251
90290
  _gitignoreWarningEmitted = true;
90252
90291
  return;
@@ -90292,26 +90331,6 @@ ${footerLines.join(`
90292
90331
  // src/index.ts
90293
90332
  init_warning_buffer();
90294
90333
  var _heartbeatTimers = new Map;
90295
- function writeSwarmConfigExampleIfNew(projectDirectory) {
90296
- try {
90297
- const swarmDir = path107.join(projectDirectory, ".swarm");
90298
- const dest = path107.join(swarmDir, "config.example.json");
90299
- if (fs87.existsSync(dest))
90300
- return;
90301
- const example = {
90302
- agents: Object.fromEntries(Object.entries(DEFAULT_MODELS).filter(([name2]) => name2 !== "default").map(([name2, model]) => [
90303
- name2,
90304
- {
90305
- model,
90306
- fallback_models: ["opencode/gpt-5-nano", "opencode/big-pickle"]
90307
- }
90308
- ])),
90309
- max_iterations: 5
90310
- };
90311
- fs87.writeFileSync(dest, `${JSON.stringify(example, null, 2)}
90312
- `, "utf-8");
90313
- } catch {}
90314
- }
90315
90334
  var OpenCodeSwarm = async (ctx) => {
90316
90335
  try {
90317
90336
  return await initializeOpenCodeSwarm(ctx);
@@ -90383,6 +90402,7 @@ async function initializeOpenCodeSwarm(ctx) {
90383
90402
  });
90384
90403
  initTelemetry(ctx.directory);
90385
90404
  writeSwarmConfigExampleIfNew(ctx.directory);
90405
+ writeProjectConfigIfNew(ctx.directory, config3.quiet);
90386
90406
  warnIfSwarmNotGitignored(ctx.directory, config3.quiet);
90387
90407
  if (config3.version_check !== false) {
90388
90408
  scheduleVersionCheck(package_default.version, (msg) => {
@@ -90510,7 +90530,7 @@ async function initializeOpenCodeSwarm(ctx) {
90510
90530
  const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
90511
90531
  preflightTriggerManager = new PTM(automationConfig);
90512
90532
  const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
90513
- const swarmDir = path107.resolve(ctx.directory, ".swarm");
90533
+ const swarmDir = path108.resolve(ctx.directory, ".swarm");
90514
90534
  statusArtifact = new ASA(swarmDir);
90515
90535
  statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
90516
90536
  if (automationConfig.capabilities?.evidence_auto_summaries === true) {