opencode-swarm 7.50.4 → 7.51.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -69,7 +69,7 @@ var package_default;
69
69
  var init_package = __esm(() => {
70
70
  package_default = {
71
71
  name: "opencode-swarm",
72
- version: "7.50.4",
72
+ version: "7.51.1",
73
73
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
74
74
  main: "dist/index.js",
75
75
  types: "dist/index.d.ts",
@@ -191,7 +191,7 @@ var init_tool_metadata = __esm(() => {
191
191
  agents: ["architect", "reviewer", "critic_oversight"]
192
192
  },
193
193
  syntax_check: {
194
- description: "syntax validation",
194
+ description: "check syntax of source files using tree-sitter parsers across multiple languages, returning per-file errors",
195
195
  agents: ["architect", "coder", "test_engineer"]
196
196
  },
197
197
  placeholder_scan: {
@@ -199,7 +199,7 @@ var init_tool_metadata = __esm(() => {
199
199
  agents: ["architect", "reviewer"]
200
200
  },
201
201
  imports: {
202
- description: "dependency audit",
202
+ description: "find all consumers that import from a given file — use before refactoring shared modules to avoid breaking unseen dependents",
203
203
  agents: [
204
204
  "architect",
205
205
  "sme",
@@ -217,11 +217,11 @@ var init_tool_metadata = __esm(() => {
217
217
  ]
218
218
  },
219
219
  lint: {
220
- description: "code quality",
220
+ description: "run project linter in check or fix mode; supports biome, eslint, ruff, clippy, and more, returns structured results",
221
221
  agents: ["architect", "reviewer", "coder"]
222
222
  },
223
223
  secretscan: {
224
- description: "secret detection",
224
+ description: "scan for secrets (API keys, tokens, passwords) via regex and entropy; returns redacted previews, excludes common dirs",
225
225
  agents: ["architect", "reviewer", "critic_oversight"]
226
226
  },
227
227
  sast_scan: {
@@ -229,7 +229,7 @@ var init_tool_metadata = __esm(() => {
229
229
  agents: ["architect", "reviewer", "critic_oversight"]
230
230
  },
231
231
  build_check: {
232
- description: "build verification",
232
+ description: "discover and run build, typecheck, and test commands for various project ecosystems in the working directory",
233
233
  agents: ["architect", "coder", "test_engineer"]
234
234
  },
235
235
  pre_check_batch: {
@@ -241,7 +241,7 @@ var init_tool_metadata = __esm(() => {
241
241
  agents: ["architect"]
242
242
  },
243
243
  symbols: {
244
- description: "code symbol search",
244
+ description: "extract exported symbols (functions, classes, interfaces, types) from source files; supports TypeScript, JavaScript, and Python",
245
245
  agents: [
246
246
  "architect",
247
247
  "sme",
@@ -312,7 +312,7 @@ var init_tool_metadata = __esm(() => {
312
312
  agents: ["architect"]
313
313
  },
314
314
  checkpoint: {
315
- description: "state snapshots",
315
+ description: "create named git checkpoints for save, restore, and delete — use before risky operations to enable rollback",
316
316
  agents: ["architect"]
317
317
  },
318
318
  pkg_audit: {
@@ -356,6 +356,10 @@ var init_tool_metadata = __esm(() => {
356
356
  "explorer"
357
357
  ]
358
358
  },
359
+ git_blame: {
360
+ description: "per-line git blame metadata: sha, author, date, summary for each line in a file",
361
+ agents: ["reviewer", "explorer", "architect"]
362
+ },
359
363
  gitingest: {
360
364
  description: "fetch a GitHub repository full content via gitingest.com",
361
365
  agents: ["architect", "docs", "explorer"]
@@ -74605,11 +74609,14 @@ async function defaultSelectTestFramework(profile, dir) {
74605
74609
  function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}) {
74606
74610
  const scope = opts.scope ?? "all";
74607
74611
  const coverage = opts.coverage ?? false;
74612
+ const bail = opts.bail ?? false;
74608
74613
  switch (framework) {
74609
74614
  case "bun": {
74610
74615
  const args2 = ["bun", "test"];
74611
74616
  if (coverage)
74612
74617
  args2.push("--coverage");
74618
+ if (bail)
74619
+ args2.push("--bail");
74613
74620
  if (scope !== "all" && files.length > 0)
74614
74621
  args2.push(...files);
74615
74622
  return args2;
@@ -74625,6 +74632,8 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
74625
74632
  ];
74626
74633
  if (coverage)
74627
74634
  args2.push("--coverage");
74635
+ if (bail)
74636
+ args2.push("--bail");
74628
74637
  if (scope !== "all" && files.length > 0)
74629
74638
  args2.push(...files);
74630
74639
  return args2;
@@ -74633,12 +74642,16 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
74633
74642
  const args2 = ["npx", "jest", "--json"];
74634
74643
  if (coverage)
74635
74644
  args2.push("--coverage");
74645
+ if (bail)
74646
+ args2.push("--bail");
74636
74647
  if (scope !== "all" && files.length > 0)
74637
74648
  args2.push(...files);
74638
74649
  return args2;
74639
74650
  }
74640
74651
  case "mocha": {
74641
74652
  const args2 = ["npx", "mocha"];
74653
+ if (bail)
74654
+ args2.push("--bail");
74642
74655
  if (scope !== "all" && files.length > 0)
74643
74656
  args2.push(...files);
74644
74657
  return args2;
@@ -74648,6 +74661,8 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
74648
74661
  const args2 = isWindows ? ["python", "-m", "pytest"] : ["python3", "-m", "pytest"];
74649
74662
  if (coverage)
74650
74663
  args2.push("--cov=.", "--cov-report=term-missing");
74664
+ if (bail)
74665
+ args2.push("-x");
74651
74666
  if (scope !== "all" && files.length > 0)
74652
74667
  args2.push(...files);
74653
74668
  return args2;
@@ -74701,6 +74716,8 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
74701
74716
  return isCommandAvailable("flutter") ? ["flutter", "test", ...files] : ["dart", "test", ...files];
74702
74717
  case "rspec": {
74703
74718
  const args2 = isCommandAvailable("bundle") ? ["bundle", "exec", "rspec"] : ["rspec"];
74719
+ if (bail)
74720
+ args2.push("--fail-fast");
74704
74721
  if (scope !== "all" && files.length > 0)
74705
74722
  args2.push(...files);
74706
74723
  return args2;
@@ -76675,6 +76692,10 @@ function validateArgs2(args2) {
76675
76692
  if (typeof obj.coverage !== "boolean")
76676
76693
  return false;
76677
76694
  }
76695
+ if (obj.bail !== undefined) {
76696
+ if (typeof obj.bail !== "boolean")
76697
+ return false;
76698
+ }
76678
76699
  if (obj.timeout_ms !== undefined) {
76679
76700
  if (typeof obj.timeout_ms !== "number")
76680
76701
  return false;
@@ -76750,7 +76771,7 @@ async function detectTestFrameworkViaDispatch(cwd) {
76750
76771
  return "none";
76751
76772
  }
76752
76773
  }
76753
- async function buildTestCommandViaDispatch(framework, scope, files, coverage, baseDir) {
76774
+ async function buildTestCommandViaDispatch(framework, scope, files, coverage, baseDir, bail) {
76754
76775
  if (framework === "none")
76755
76776
  return null;
76756
76777
  try {
@@ -76759,7 +76780,8 @@ async function buildTestCommandViaDispatch(framework, scope, files, coverage, ba
76759
76780
  if (backend?.buildTestCommand) {
76760
76781
  const cmd = backend.buildTestCommand(framework, files, baseDir, {
76761
76782
  scope,
76762
- coverage
76783
+ coverage,
76784
+ bail
76763
76785
  });
76764
76786
  if (cmd)
76765
76787
  return cmd;
@@ -77128,12 +77150,14 @@ function getTargetedExecutionUnsupportedReason(framework) {
77128
77150
  return null;
77129
77151
  }
77130
77152
  }
77131
- function buildTestCommand2(framework, scope, files, coverage, baseDir) {
77153
+ function buildTestCommand2(framework, scope, files, coverage, baseDir, bail) {
77132
77154
  switch (framework) {
77133
77155
  case "bun": {
77134
77156
  const args2 = ["bun", "test"];
77135
77157
  if (coverage)
77136
77158
  args2.push("--coverage");
77159
+ if (bail)
77160
+ args2.push("--bail");
77137
77161
  if (scope !== "all" && files.length > 0) {
77138
77162
  args2.push(...files);
77139
77163
  }
@@ -77150,6 +77174,8 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
77150
77174
  ];
77151
77175
  if (coverage)
77152
77176
  args2.push("--coverage");
77177
+ if (bail)
77178
+ args2.push("--bail=1");
77153
77179
  if (scope !== "all" && files.length > 0) {
77154
77180
  args2.push(...files);
77155
77181
  }
@@ -77159,6 +77185,8 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
77159
77185
  const args2 = ["npx", "jest", "--json"];
77160
77186
  if (coverage)
77161
77187
  args2.push("--coverage");
77188
+ if (bail)
77189
+ args2.push("--bail");
77162
77190
  if (scope !== "all" && files.length > 0) {
77163
77191
  args2.push(...files);
77164
77192
  }
@@ -77166,6 +77194,8 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
77166
77194
  }
77167
77195
  case "mocha": {
77168
77196
  const args2 = ["npx", "mocha"];
77197
+ if (bail)
77198
+ args2.push("--bail");
77169
77199
  if (scope !== "all" && files.length > 0) {
77170
77200
  args2.push(...files);
77171
77201
  }
@@ -77176,6 +77206,8 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
77176
77206
  const args2 = isWindows ? ["python", "-m", "pytest"] : ["python3", "-m", "pytest"];
77177
77207
  if (coverage)
77178
77208
  args2.push("--cov=.", "--cov-report=term-missing");
77209
+ if (bail)
77210
+ args2.push("-x");
77179
77211
  if (scope !== "all" && files.length > 0) {
77180
77212
  args2.push(...files);
77181
77213
  }
@@ -77232,6 +77264,8 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
77232
77264
  return isCommandAvailable("flutter") ? ["flutter", "test", ...files] : ["dart", "test", ...files];
77233
77265
  case "rspec": {
77234
77266
  const args2 = isCommandAvailable("bundle") ? ["bundle", "exec", "rspec"] : ["rspec"];
77267
+ if (bail)
77268
+ args2.push("--fail-fast");
77235
77269
  if (scope !== "all" && files.length > 0) {
77236
77270
  args2.push(...files);
77237
77271
  }
@@ -77617,7 +77651,7 @@ async function readBoundedStream(stream, maxBytes) {
77617
77651
  }
77618
77652
  return { text: decoder.decode(combined), truncated };
77619
77653
  }
77620
- async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
77654
+ async function runTests(framework, scope, files, coverage, timeout_ms, cwd, bail) {
77621
77655
  if (scope !== "all" && files.length > 0) {
77622
77656
  const unsupportedReason = getTargetedExecutionUnsupportedReason(framework);
77623
77657
  if (unsupportedReason) {
@@ -77632,7 +77666,7 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
77632
77666
  }
77633
77667
  }
77634
77668
  const useDispatchBuild = process.env.SWARM_LANG_BACKEND !== "legacy";
77635
- const command = useDispatchBuild ? await buildTestCommandViaDispatch(framework, scope, files, coverage, cwd) ?? buildTestCommand2(framework, scope, files, coverage, cwd) : buildTestCommand2(framework, scope, files, coverage, cwd);
77669
+ const command = useDispatchBuild ? await buildTestCommandViaDispatch(framework, scope, files, coverage, cwd, bail) ?? buildTestCommand2(framework, scope, files, coverage, cwd, bail) : buildTestCommand2(framework, scope, files, coverage, cwd, bail);
77636
77670
  if (!command) {
77637
77671
  return {
77638
77672
  success: false,
@@ -77980,6 +78014,7 @@ var init_test_runner = __esm(() => {
77980
78014
  scope: exports_external.enum(["all", "convention", "graph", "impact"]).optional().describe('Test scope: "all" runs full suite, "convention" accepts direct test files or maps source files to tests by naming, "graph" finds related tests via imports from source files, "impact" finds tests covering changed source files via test-impact analysis'),
77981
78015
  files: exports_external.array(exports_external.string()).optional().describe('Specific files to test. For "convention", pass source files or direct test files. For "graph" and "impact", pass source files only.'),
77982
78016
  coverage: exports_external.boolean().optional().describe("Enable coverage reporting if supported"),
78017
+ bail: exports_external.boolean().optional().describe("Stop running tests after the first failure. Default false. Note: coverage may be incomplete when bail=true with coverage=true."),
77983
78018
  timeout_ms: exports_external.number().optional().describe("Timeout in milliseconds (default 60000, max 300000)"),
77984
78019
  allow_full_suite: exports_external.boolean().optional().describe('Explicit opt-in for scope "all". Required because full-suite output can destabilize SSE streaming.'),
77985
78020
  working_directory: exports_external.string().optional().describe("Explicit project root directory. When provided, tests run relative to this path instead of the plugin context directory. Use this when CWD differs from the actual project root.")
@@ -78080,6 +78115,7 @@ var init_test_runner = __esm(() => {
78080
78115
  }
78081
78116
  const _files = args2.files || [];
78082
78117
  const coverage = args2.coverage || false;
78118
+ const bail = args2.bail || false;
78083
78119
  const timeout_ms = Math.min(args2.timeout_ms || DEFAULT_TIMEOUT_MS, MAX_TIMEOUT_MS);
78084
78120
  const useDispatch = process.env.SWARM_LANG_BACKEND !== "legacy";
78085
78121
  let framework;
@@ -78318,7 +78354,7 @@ var init_test_runner = __esm(() => {
78318
78354
  };
78319
78355
  return JSON.stringify(errorResult, null, 2);
78320
78356
  }
78321
- const result = await runTests(framework, effectiveScope, testFiles, coverage, timeout_ms, workingDir);
78357
+ const result = await runTests(framework, effectiveScope, testFiles, coverage, timeout_ms, workingDir, bail);
78322
78358
  recordAndAnalyzeResults(result, testFiles, workingDir, _files.length > 0 ? _files : undefined, result.testCases);
78323
78359
  let historyReport;
78324
78360
  if (!result.success && result.totals && result.totals.failed > 0) {
@@ -78334,6 +78370,9 @@ var init_test_runner = __esm(() => {
78334
78370
  if (graphFallbackReason && result.message) {
78335
78371
  result.message = `${result.message} (${graphFallbackReason})`;
78336
78372
  }
78373
+ if (bail && coverage && result.message) {
78374
+ result.message = `${result.message} (coverage may be incomplete: bail=true stopped early)`;
78375
+ }
78337
78376
  return JSON.stringify(result, null, 2);
78338
78377
  }
78339
78378
  });
@@ -78538,7 +78577,7 @@ async function runLintCheck(dir, linter, timeoutMs) {
78538
78577
  async function runTestsCheck(_dir, scope, timeoutMs) {
78539
78578
  const startTime = Date.now();
78540
78579
  try {
78541
- const result = await runTests("none", scope, [], false, timeoutMs, _dir);
78580
+ const result = await runTests("none", scope, [], false, timeoutMs, _dir, false);
78542
78581
  if (!result.success) {
78543
78582
  return {
78544
78583
  type: "tests",
@@ -91330,7 +91369,7 @@ async function scanDocIndex(directory) {
91330
91369
  const resolvedDirectory = await realpath3(directory).catch(() => directory);
91331
91370
  const discoveredFiles = [];
91332
91371
  let rootReadable = false;
91333
- const walkDir = async (dir) => {
91372
+ const walkDir2 = async (dir) => {
91334
91373
  let entries;
91335
91374
  try {
91336
91375
  entries = await readdir6(dir, { withFileTypes: true });
@@ -91358,8 +91397,8 @@ async function scanDocIndex(directory) {
91358
91397
  }
91359
91398
  }
91360
91399
  if (isDir) {
91361
- if (!SKIP_DIRECTORIES3.has(entry.name)) {
91362
- await walkDir(path94.join(dir, entry.name));
91400
+ if (!SKIP_DIRECTORIES4.has(entry.name)) {
91401
+ await walkDir2(path94.join(dir, entry.name));
91363
91402
  }
91364
91403
  continue;
91365
91404
  }
@@ -91401,7 +91440,7 @@ async function scanDocIndex(directory) {
91401
91440
  });
91402
91441
  }
91403
91442
  };
91404
- await walkDir(directory);
91443
+ await walkDir2(directory);
91405
91444
  if (!rootReadable) {
91406
91445
  return {
91407
91446
  manifest: {
@@ -91546,13 +91585,13 @@ async function extractDocConstraints(directory, taskFiles, taskDescription) {
91546
91585
  }
91547
91586
  return { extracted: extractedCount, skipped: skippedCount, details };
91548
91587
  }
91549
- var SKIP_DIRECTORIES3, SKIP_PATTERNS, MAX_SUMMARY_LENGTH = 200, MAX_INDEXED_FILES = 100, READ_LINES_LIMIT = 30, MIN_LESSON_LENGTH = 15, MAX_CONSTRAINTS_PER_DOC = 5, MAX_CONSTRAINT_LENGTH = 200, RELEVANCE_THRESHOLD = 0.1, DEDUP_THRESHOLD = 0.6, CONSTRAINT_PATTERNS, ACTION_WORDS, doc_scan, doc_extract;
91588
+ var SKIP_DIRECTORIES4, SKIP_PATTERNS, MAX_SUMMARY_LENGTH = 200, MAX_INDEXED_FILES = 100, READ_LINES_LIMIT = 30, MIN_LESSON_LENGTH = 15, MAX_CONSTRAINTS_PER_DOC = 5, MAX_CONSTRAINT_LENGTH = 200, RELEVANCE_THRESHOLD = 0.1, DEDUP_THRESHOLD = 0.6, CONSTRAINT_PATTERNS, ACTION_WORDS, doc_scan, doc_extract;
91550
91589
  var init_doc_scan = __esm(() => {
91551
91590
  init_zod();
91552
91591
  init_schema();
91553
91592
  init_knowledge_store();
91554
91593
  init_create_tool();
91555
- SKIP_DIRECTORIES3 = new Set([
91594
+ SKIP_DIRECTORIES4 = new Set([
91556
91595
  "node_modules",
91557
91596
  ".git",
91558
91597
  ".swarm",
@@ -92406,11 +92445,11 @@ __export(exports_design_doc_drift, {
92406
92445
  runDesignDocDriftCheck: () => runDesignDocDriftCheck,
92407
92446
  _internals: () => _internals60
92408
92447
  });
92409
- import * as fs98 from "node:fs";
92410
- import * as path137 from "node:path";
92448
+ import * as fs99 from "node:fs";
92449
+ import * as path138 from "node:path";
92411
92450
  function mtimeMsOrNull(absPath) {
92412
92451
  try {
92413
- return fs98.statSync(absPath).mtimeMs;
92452
+ return fs99.statSync(absPath).mtimeMs;
92414
92453
  } catch {
92415
92454
  return null;
92416
92455
  }
@@ -92418,40 +92457,40 @@ function mtimeMsOrNull(absPath) {
92418
92457
  function resolveAnchorWithin(directory, anchor) {
92419
92458
  if (!anchor || typeof anchor !== "string")
92420
92459
  return null;
92421
- const root = path137.resolve(directory);
92422
- const resolved = path137.resolve(root, anchor);
92423
- const rel = path137.relative(root, resolved);
92424
- if (rel.startsWith("..") || path137.isAbsolute(rel))
92460
+ const root = path138.resolve(directory);
92461
+ const resolved = path138.resolve(root, anchor);
92462
+ const rel = path138.relative(root, resolved);
92463
+ if (rel.startsWith("..") || path138.isAbsolute(rel))
92425
92464
  return null;
92426
92465
  return resolved;
92427
92466
  }
92428
92467
  async function runDesignDocDriftCheck(directory, phase, outDir) {
92429
92468
  try {
92430
- const root = path137.resolve(directory);
92431
- const outAbs = path137.resolve(root, outDir);
92432
- const outRel = path137.relative(root, outAbs);
92433
- if (outRel.startsWith("..") || path137.isAbsolute(outRel)) {
92469
+ const root = path138.resolve(directory);
92470
+ const outAbs = path138.resolve(root, outDir);
92471
+ const outRel = path138.relative(root, outAbs);
92472
+ if (outRel.startsWith("..") || path138.isAbsolute(outRel)) {
92434
92473
  return null;
92435
92474
  }
92436
92475
  const docMtimes = new Map;
92437
92476
  const checkedDocs = [];
92438
92477
  const missingDocs = [];
92439
92478
  for (const [docName, relFile] of Object.entries(DESIGN_DOC_FILES)) {
92440
- const abs = path137.join(outAbs, relFile);
92479
+ const abs = path138.join(outAbs, relFile);
92441
92480
  const mtime = mtimeMsOrNull(abs);
92442
92481
  docMtimes.set(docName, mtime);
92443
92482
  if (mtime === null) {
92444
- missingDocs.push(path137.join(outDir, relFile));
92483
+ missingDocs.push(path138.join(outDir, relFile));
92445
92484
  } else {
92446
- checkedDocs.push(path137.join(outDir, relFile));
92485
+ checkedDocs.push(path138.join(outDir, relFile));
92447
92486
  }
92448
92487
  }
92449
- const traceabilityAbs = path137.join(outAbs, TRACEABILITY_REL);
92488
+ const traceabilityAbs = path138.join(outAbs, TRACEABILITY_REL);
92450
92489
  let registry3 = null;
92451
92490
  try {
92452
- const stat9 = await fs98.promises.stat(traceabilityAbs);
92491
+ const stat9 = await fs99.promises.stat(traceabilityAbs);
92453
92492
  if (stat9.size <= MAX_TRACEABILITY_BYTES) {
92454
- const raw = await fs98.promises.readFile(traceabilityAbs, "utf-8");
92493
+ const raw = await fs99.promises.readFile(traceabilityAbs, "utf-8");
92455
92494
  const parsed = JSON.parse(raw);
92456
92495
  registry3 = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
92457
92496
  }
@@ -92459,7 +92498,7 @@ async function runDesignDocDriftCheck(directory, phase, outDir) {
92459
92498
  registry3 = null;
92460
92499
  }
92461
92500
  const noDocs = checkedDocs.length === 0 || registry3 === null;
92462
- const specMtime = mtimeMsOrNull(path137.join(root, ".swarm", "spec.md"));
92501
+ const specMtime = mtimeMsOrNull(path138.join(root, ".swarm", "spec.md"));
92463
92502
  const staleSections = [];
92464
92503
  if (!noDocs && Array.isArray(registry3?.sections)) {
92465
92504
  for (const section of registry3.sections) {
@@ -92515,8 +92554,8 @@ async function runDesignDocDriftCheck(directory, phase, outDir) {
92515
92554
  };
92516
92555
  const filename = `${DOC_DRIFT_REPORT_PREFIX}${phase}.json`;
92517
92556
  const filePath = validateSwarmPath(directory, filename);
92518
- await fs98.promises.mkdir(path137.dirname(filePath), { recursive: true });
92519
- await fs98.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
92557
+ await fs99.promises.mkdir(path138.dirname(filePath), { recursive: true });
92558
+ await fs99.promises.writeFile(filePath, JSON.stringify(report, null, 2), "utf-8");
92520
92559
  getGlobalEventBus().publish("curator.docdrift.completed", {
92521
92560
  phase,
92522
92561
  verdict,
@@ -92546,10 +92585,10 @@ var init_design_doc_drift = __esm(() => {
92546
92585
  domain: "domain.md",
92547
92586
  "technical-spec": "technical-spec.md",
92548
92587
  "behavior-spec": "behavior-spec.md",
92549
- "reference-impl": path137.join("reference", "reference-impl.md"),
92550
- "idiom-notes": path137.join("reference", "idiom-notes.md")
92588
+ "reference-impl": path138.join("reference", "reference-impl.md"),
92589
+ "idiom-notes": path138.join("reference", "idiom-notes.md")
92551
92590
  };
92552
- TRACEABILITY_REL = path137.join("reference", "traceability.json");
92591
+ TRACEABILITY_REL = path138.join("reference", "traceability.json");
92553
92592
  _internals60 = {
92554
92593
  mtimeMsOrNull,
92555
92594
  resolveAnchorWithin,
@@ -92564,12 +92603,12 @@ __export(exports_project_context, {
92564
92603
  _internals: () => _internals71,
92565
92604
  LANG_BACKEND_DETECTION_TIMEOUT_MS: () => LANG_BACKEND_DETECTION_TIMEOUT_MS
92566
92605
  });
92567
- import * as fs122 from "node:fs";
92568
- import * as path166 from "node:path";
92606
+ import * as fs123 from "node:fs";
92607
+ import * as path167 from "node:path";
92569
92608
  function detectFileExists2(directory, pattern) {
92570
92609
  if (pattern.includes("*") || pattern.includes("?")) {
92571
92610
  try {
92572
- const files = fs122.readdirSync(directory);
92611
+ const files = fs123.readdirSync(directory);
92573
92612
  const regex = new RegExp(`^${pattern.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, ".")}$`);
92574
92613
  return files.some((f) => regex.test(f));
92575
92614
  } catch {
@@ -92577,7 +92616,7 @@ function detectFileExists2(directory, pattern) {
92577
92616
  }
92578
92617
  }
92579
92618
  try {
92580
- fs122.accessSync(path166.join(directory, pattern));
92619
+ fs123.accessSync(path167.join(directory, pattern));
92581
92620
  return true;
92582
92621
  } catch {
92583
92622
  return false;
@@ -92586,7 +92625,7 @@ function detectFileExists2(directory, pattern) {
92586
92625
  function selectTestCommandFromScriptsTest(backend, directory) {
92587
92626
  let pkgRaw;
92588
92627
  try {
92589
- pkgRaw = fs122.readFileSync(path166.join(directory, "package.json"), "utf-8");
92628
+ pkgRaw = fs123.readFileSync(path167.join(directory, "package.json"), "utf-8");
92590
92629
  } catch {
92591
92630
  return null;
92592
92631
  }
@@ -92695,7 +92734,7 @@ var init_project_context = __esm(() => {
92695
92734
  init_package();
92696
92735
  init_agents2();
92697
92736
  init_critic();
92698
- import * as path167 from "node:path";
92737
+ import * as path168 from "node:path";
92699
92738
 
92700
92739
  // src/background/index.ts
92701
92740
  init_event_bus();
@@ -95459,7 +95498,29 @@ init_path_security();
95459
95498
  import * as fs49 from "node:fs";
95460
95499
  import * as path79 from "node:path";
95461
95500
  var MAX_FILE_SIZE_BYTES2 = 1024 * 1024;
95501
+ var MAX_WORKSPACE_RESULTS = 50;
95502
+ var MAX_WORKSPACE_SCANNED_FILES = 200;
95503
+ var WORKSPACE_TIMEOUT_MS = 1e4;
95462
95504
  var WINDOWS_RESERVED_NAMES = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
95505
+ var SYMBOL_EXTENSIONS = new Set([
95506
+ ".ts",
95507
+ ".tsx",
95508
+ ".js",
95509
+ ".jsx",
95510
+ ".mjs",
95511
+ ".cjs",
95512
+ ".py"
95513
+ ]);
95514
+ var SKIP_DIRECTORIES2 = new Set([
95515
+ "node_modules",
95516
+ ".git",
95517
+ "dist",
95518
+ "build",
95519
+ "out",
95520
+ ".next",
95521
+ "coverage",
95522
+ "__pycache__"
95523
+ ]);
95463
95524
  function containsWindowsAttacks(str) {
95464
95525
  if (/:[^\\/]/.test(str)) {
95465
95526
  return true;
@@ -95704,28 +95765,135 @@ function extractPythonSymbols(filePath, cwd) {
95704
95765
  return a.name.localeCompare(b.name);
95705
95766
  });
95706
95767
  }
95768
+ function findSourceFiles(cwd, maxFiles) {
95769
+ const files = [];
95770
+ walkDir(cwd, cwd, files, maxFiles);
95771
+ return files;
95772
+ }
95773
+ function walkDir(currentDir, rootDir, files, maxFiles) {
95774
+ let entries;
95775
+ try {
95776
+ entries = fs49.readdirSync(currentDir, { withFileTypes: true });
95777
+ } catch {
95778
+ return;
95779
+ }
95780
+ entries.sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase()));
95781
+ for (const entry of entries) {
95782
+ if (files.length >= maxFiles)
95783
+ return;
95784
+ if (SKIP_DIRECTORIES2.has(entry.name))
95785
+ continue;
95786
+ const fullPath = path79.join(currentDir, entry.name);
95787
+ if (entry.isDirectory()) {
95788
+ walkDir(fullPath, rootDir, files, maxFiles);
95789
+ } else if (entry.isFile() && SYMBOL_EXTENSIONS.has(path79.extname(entry.name).toLowerCase())) {
95790
+ files.push(path79.relative(rootDir, fullPath));
95791
+ }
95792
+ }
95793
+ }
95794
+ function searchWorkspaceSymbols(cwd, name2, exportedOnly = true) {
95795
+ const startTime = Date.now();
95796
+ const sourceFiles = findSourceFiles(cwd, MAX_WORKSPACE_SCANNED_FILES);
95797
+ const files = [];
95798
+ let scannedCount = 0;
95799
+ let truncated = false;
95800
+ if (sourceFiles.length >= MAX_WORKSPACE_SCANNED_FILES) {
95801
+ truncated = true;
95802
+ }
95803
+ let totalSymbols = 0;
95804
+ for (const relFile of sourceFiles) {
95805
+ if (Date.now() - startTime > WORKSPACE_TIMEOUT_MS) {
95806
+ truncated = true;
95807
+ break;
95808
+ }
95809
+ scannedCount++;
95810
+ let syms;
95811
+ const ext = path79.extname(relFile).toLowerCase();
95812
+ switch (ext) {
95813
+ case ".ts":
95814
+ case ".tsx":
95815
+ case ".js":
95816
+ case ".jsx":
95817
+ case ".mjs":
95818
+ case ".cjs":
95819
+ syms = extractTSSymbols(relFile, cwd);
95820
+ break;
95821
+ case ".py":
95822
+ syms = extractPythonSymbols(relFile, cwd);
95823
+ break;
95824
+ default:
95825
+ continue;
95826
+ }
95827
+ if (exportedOnly) {
95828
+ syms = syms.filter((s) => s.exported);
95829
+ }
95830
+ if (name2) {
95831
+ syms = syms.filter((s) => s.name.includes(name2));
95832
+ }
95833
+ if (syms.length > 0) {
95834
+ const remaining = MAX_WORKSPACE_RESULTS - totalSymbols;
95835
+ if (remaining <= 0) {
95836
+ truncated = true;
95837
+ break;
95838
+ }
95839
+ const cappedSyms = syms.slice(0, remaining);
95840
+ files.push({
95841
+ file: relFile,
95842
+ symbolCount: cappedSyms.length,
95843
+ symbols: cappedSyms
95844
+ });
95845
+ totalSymbols += cappedSyms.length;
95846
+ if (totalSymbols >= MAX_WORKSPACE_RESULTS) {
95847
+ truncated = syms.length > remaining || scannedCount < sourceFiles.length;
95848
+ break;
95849
+ }
95850
+ }
95851
+ }
95852
+ return {
95853
+ query: { workspace: true, name: name2 },
95854
+ fileCount: files.length,
95855
+ scannedFileCount: scannedCount,
95856
+ totalSymbols,
95857
+ files,
95858
+ truncated
95859
+ };
95860
+ }
95707
95861
  var symbols = createSwarmTool({
95708
95862
  description: "Extract all exported symbols from a source file: functions with signatures, " + "classes with public members, interfaces, types, enums, constants. " + "Supports TypeScript/JavaScript and Python. Use for architect planning, " + "designer scaffolding, and understanding module public API surface.",
95709
95863
  args: {
95710
- file: exports_external.string().describe('File path to extract symbols from (e.g., "src/auth/login.ts")'),
95711
- exported_only: exports_external.boolean().default(true).describe("If true, only return exported/public symbols. If false, include all top-level symbols.")
95864
+ file: exports_external.string().optional().describe('File path to extract symbols from (e.g., "src/auth/login.ts"). Required when not using workspace mode.'),
95865
+ exported_only: exports_external.boolean().default(true).describe("If true, only return exported/public symbols. If false, include all top-level symbols."),
95866
+ workspace: exports_external.boolean().optional().describe("When true, search across the workspace instead of a single file. Returns per-file symbol summaries."),
95867
+ name: exports_external.string().optional().describe("Search for symbols by name (case-sensitive substring match). When provided without workspace, only searches the specified file.")
95712
95868
  },
95713
95869
  execute: async (args2, directory) => {
95714
95870
  let file3;
95715
95871
  let exportedOnly = true;
95872
+ let workspace = false;
95873
+ let name2;
95716
95874
  try {
95717
95875
  const obj = args2;
95718
- file3 = String(obj.file);
95876
+ file3 = obj.file != null && typeof obj.file === "string" ? obj.file : undefined;
95719
95877
  exportedOnly = obj.exported_only === true;
95878
+ workspace = obj.workspace === true;
95879
+ name2 = obj.name != null && typeof obj.name === "string" ? obj.name : undefined;
95720
95880
  } catch {
95721
95881
  return JSON.stringify({
95722
95882
  file: "<unknown>",
95723
- error: "Invalid arguments: could not extract file path",
95883
+ error: "Invalid arguments: could not extract parameters",
95724
95884
  symbols: []
95725
95885
  }, null, 2);
95726
95886
  }
95727
95887
  const cwd = directory;
95728
- const ext = path79.extname(file3);
95888
+ if (workspace) {
95889
+ return JSON.stringify(searchWorkspaceSymbols(cwd, name2, exportedOnly), null, 2);
95890
+ }
95891
+ if (!file3) {
95892
+ return JSON.stringify({
95893
+ error: "file parameter is required when not using workspace mode",
95894
+ symbols: []
95895
+ }, null, 2);
95896
+ }
95729
95897
  if (containsControlChars(file3)) {
95730
95898
  return JSON.stringify({
95731
95899
  file: file3,
@@ -95754,6 +95922,7 @@ var symbols = createSwarmTool({
95754
95922
  symbols: []
95755
95923
  }, null, 2);
95756
95924
  }
95925
+ const ext = path79.extname(file3);
95757
95926
  let syms;
95758
95927
  switch (ext) {
95759
95928
  case ".ts":
@@ -95777,6 +95946,9 @@ var symbols = createSwarmTool({
95777
95946
  if (exportedOnly) {
95778
95947
  syms = syms.filter((s) => s.exported);
95779
95948
  }
95949
+ if (name2) {
95950
+ syms = syms.filter((s) => s.name.includes(name2));
95951
+ }
95780
95952
  return JSON.stringify({
95781
95953
  file: file3,
95782
95954
  symbolCount: syms.length,
@@ -95925,7 +96097,7 @@ var _internals43 = {
95925
96097
  extractPythonSymbols,
95926
96098
  parseFileImports
95927
96099
  };
95928
- var SKIP_DIRECTORIES2 = new Set([
96100
+ var SKIP_DIRECTORIES3 = new Set([
95929
96101
  "node_modules",
95930
96102
  ".git",
95931
96103
  "dist",
@@ -96158,7 +96330,7 @@ async function findSourceFilesAsync(dir, stats, options) {
96158
96330
  if (isWalkBudgetExceeded(ctx) || isFileCapReached(ctx, files.length)) {
96159
96331
  break;
96160
96332
  }
96161
- if (SKIP_DIRECTORIES2.has(entry.name)) {
96333
+ if (SKIP_DIRECTORIES3.has(entry.name)) {
96162
96334
  ctx.stats.skippedDirs++;
96163
96335
  continue;
96164
96336
  }
@@ -98162,7 +98334,7 @@ var DEFAULT_SKIP_DIRS = new Set([
98162
98334
  var MAX_FILE_SIZE_BYTES3 = 1024 * 1024;
98163
98335
  var DEFAULT_MAX_FILES = 1e4;
98164
98336
  var SOURCE_EXT_SET = new Set(SOURCE_EXTENSIONS2);
98165
- function findSourceFiles(workspaceRoot, skipDirs = DEFAULT_SKIP_DIRS) {
98337
+ function findSourceFiles2(workspaceRoot, skipDirs = DEFAULT_SKIP_DIRS) {
98166
98338
  const out2 = [];
98167
98339
  const stack = [workspaceRoot];
98168
98340
  while (stack.length > 0) {
@@ -98199,7 +98371,7 @@ function findSourceFiles(workspaceRoot, skipDirs = DEFAULT_SKIP_DIRS) {
98199
98371
  }
98200
98372
  async function buildRepoGraph(workspaceRoot, options = {}) {
98201
98373
  const skipDirs = options.skipDirs ? new Set([...DEFAULT_SKIP_DIRS, ...options.skipDirs]) : DEFAULT_SKIP_DIRS;
98202
- let files = findSourceFiles(workspaceRoot, skipDirs);
98374
+ let files = findSourceFiles2(workspaceRoot, skipDirs);
98203
98375
  const cap = typeof options.maxFiles === "number" && options.maxFiles > 0 ? options.maxFiles : DEFAULT_MAX_FILES;
98204
98376
  if (files.length > cap) {
98205
98377
  files = files.slice(0, cap);
@@ -110252,10 +110424,12 @@ var diff = createSwarmTool({
110252
110424
  description: "Analyze git diff for changed files, exports, interfaces, and function signatures. Returns structured output with contract change detection.",
110253
110425
  args: {
110254
110426
  base: exports_external.string().optional().describe('Base ref to diff against (default: HEAD). Use "staged" for staged changes, "unstaged" for working tree changes.'),
110255
- paths: exports_external.array(exports_external.string()).optional().describe("Optional file paths to restrict diff scope.")
110427
+ paths: exports_external.array(exports_external.string()).optional().describe("Optional file paths to restrict diff scope."),
110428
+ summaryOnly: exports_external.boolean().optional().describe("When true, return only file list with additions/deletions counts and hasContractChanges. No hunk content or AST diff. Default false.")
110256
110429
  },
110257
110430
  async execute(args2, directory, _ctx) {
110258
110431
  const typedArgs = args2;
110432
+ const summaryOnly = typedArgs.summaryOnly === true;
110259
110433
  try {
110260
110434
  let fileExistsInRef = function(refPath) {
110261
110435
  try {
@@ -110333,13 +110507,6 @@ var diff = createSwarmTool({
110333
110507
  cwd: directory,
110334
110508
  stdio: ["ignore", "pipe", "pipe"]
110335
110509
  });
110336
- const fullDiffOutput = child_process7.execFileSync("git", fullDiffArgs, {
110337
- encoding: "utf-8",
110338
- timeout: DIFF_TIMEOUT_MS,
110339
- maxBuffer: MAX_BUFFER_BYTES,
110340
- cwd: directory,
110341
- stdio: ["ignore", "pipe", "pipe"]
110342
- });
110343
110510
  const files = [];
110344
110511
  const numstatLines = numstatOutput.split(`
110345
110512
  `);
@@ -110354,6 +110521,50 @@ var diff = createSwarmTool({
110354
110521
  files.push({ path: path118, additions, deletions });
110355
110522
  }
110356
110523
  }
110524
+ if (summaryOnly) {
110525
+ let hasContractChanges2 = false;
110526
+ try {
110527
+ const contractDiffArgs = [...gitArgs, "-U0"];
110528
+ if (typedArgs.paths?.length) {
110529
+ contractDiffArgs.push("--", ...typedArgs.paths);
110530
+ }
110531
+ const contractDiffOutput = child_process7.execFileSync("git", contractDiffArgs, {
110532
+ encoding: "utf-8",
110533
+ timeout: DIFF_TIMEOUT_MS,
110534
+ maxBuffer: MAX_BUFFER_BYTES,
110535
+ cwd: directory,
110536
+ stdio: ["ignore", "pipe", "pipe"]
110537
+ });
110538
+ const contractDiffLines = contractDiffOutput.split(`
110539
+ `);
110540
+ for (const line of contractDiffLines) {
110541
+ for (const pattern of CONTRACT_PATTERNS) {
110542
+ if (pattern.test(line)) {
110543
+ hasContractChanges2 = true;
110544
+ break;
110545
+ }
110546
+ }
110547
+ if (hasContractChanges2)
110548
+ break;
110549
+ }
110550
+ } catch {
110551
+ hasContractChanges2 = true;
110552
+ }
110553
+ const result2 = {
110554
+ files,
110555
+ contractChanges: [],
110556
+ hasContractChanges: hasContractChanges2,
110557
+ summary: `${files.length} files changed (summary only)`
110558
+ };
110559
+ return JSON.stringify(result2, null, 2);
110560
+ }
110561
+ const fullDiffOutput = child_process7.execFileSync("git", fullDiffArgs, {
110562
+ encoding: "utf-8",
110563
+ timeout: DIFF_TIMEOUT_MS,
110564
+ maxBuffer: MAX_BUFFER_BYTES,
110565
+ cwd: directory,
110566
+ stdio: ["ignore", "pipe", "pipe"]
110567
+ });
110357
110568
  const contractChanges = [];
110358
110569
  const diffLines = fullDiffOutput.split(`
110359
110570
  `);
@@ -111419,13 +111630,389 @@ var get_qa_gate_profile = createSwarmTool({
111419
111630
  }
111420
111631
  });
111421
111632
 
111633
+ // src/tools/git-blame.ts
111634
+ init_zod();
111635
+ init_path_security();
111636
+ init_create_tool();
111637
+ import * as child_process9 from "node:child_process";
111638
+ import * as fs83 from "node:fs";
111639
+ import * as path121 from "node:path";
111640
+ var BLAME_TIMEOUT_MS = 30000;
111641
+ var MAX_OUTPUT_LINES2 = 500;
111642
+ var MAX_PATH_LENGTH2 = 500;
111643
+ var MAX_LINE_NUMBER = 1e6;
111644
+ var SHELL_METACHARACTERS3 = /[;|&$`(){}<>!'"]/;
111645
+ var BINARY_EXTENSIONS = new Set([
111646
+ ".png",
111647
+ ".jpg",
111648
+ ".jpeg",
111649
+ ".gif",
111650
+ ".bmp",
111651
+ ".ico",
111652
+ ".svg",
111653
+ ".webp",
111654
+ ".mp3",
111655
+ ".mp4",
111656
+ ".wav",
111657
+ ".avi",
111658
+ ".mov",
111659
+ ".wmv",
111660
+ ".flv",
111661
+ ".zip",
111662
+ ".tar",
111663
+ ".gz",
111664
+ ".rar",
111665
+ ".7z",
111666
+ ".bz2",
111667
+ ".pdf",
111668
+ ".doc",
111669
+ ".docx",
111670
+ ".xls",
111671
+ ".xlsx",
111672
+ ".ppt",
111673
+ ".pptx",
111674
+ ".exe",
111675
+ ".dll",
111676
+ ".so",
111677
+ ".dylib",
111678
+ ".bin",
111679
+ ".dat",
111680
+ ".o",
111681
+ ".obj",
111682
+ ".woff",
111683
+ ".woff2",
111684
+ ".ttf",
111685
+ ".eot",
111686
+ ".otf",
111687
+ ".sqlite",
111688
+ ".db"
111689
+ ]);
111690
+ function validateFilePath(filePath) {
111691
+ if (!filePath || filePath.length === 0) {
111692
+ return "file path is required";
111693
+ }
111694
+ if (filePath.length > MAX_PATH_LENGTH2) {
111695
+ return `file path exceeds maximum length of ${MAX_PATH_LENGTH2}`;
111696
+ }
111697
+ if (path121.isAbsolute(filePath)) {
111698
+ return "absolute paths are not allowed; use a relative path from the project root";
111699
+ }
111700
+ if (containsPathTraversal(filePath)) {
111701
+ return "path traversal detected";
111702
+ }
111703
+ if (containsControlChars(filePath)) {
111704
+ return "file path contains control characters";
111705
+ }
111706
+ if (SHELL_METACHARACTERS3.test(filePath)) {
111707
+ return "file path contains shell metacharacters";
111708
+ }
111709
+ if (filePath.startsWith("-")) {
111710
+ return 'file path cannot start with "-"';
111711
+ }
111712
+ return null;
111713
+ }
111714
+ function validateLineNumber(value, name2) {
111715
+ if (typeof value === "undefined")
111716
+ return null;
111717
+ if (typeof value !== "number" || !Number.isInteger(value) || value < 1) {
111718
+ return `${name2} must be a positive integer`;
111719
+ }
111720
+ if (value > MAX_LINE_NUMBER) {
111721
+ return `${name2} exceeds maximum value of ${MAX_LINE_NUMBER}`;
111722
+ }
111723
+ return null;
111724
+ }
111725
+ function isBinaryFile2(filePath) {
111726
+ const ext = path121.extname(filePath).toLowerCase();
111727
+ return BINARY_EXTENSIONS.has(ext);
111728
+ }
111729
+ function parsePorcelainBlame(output, linesCap) {
111730
+ const entries = [];
111731
+ const outputLines = output.split(`
111732
+ `);
111733
+ const cappedLines = outputLines.slice(0, linesCap * 8);
111734
+ const commitCache = new Map;
111735
+ let currentSha = "";
111736
+ let currentLine = 0;
111737
+ let currentAuthor = "";
111738
+ let currentAuthorTime = "";
111739
+ let currentSummary = "";
111740
+ for (const rawLine of cappedLines) {
111741
+ const headerMatch = rawLine.match(/^([0-9a-f]{40})\s+(\d+)\s+(\d+)/);
111742
+ if (headerMatch) {
111743
+ currentSha = headerMatch[1];
111744
+ currentLine = Number.parseInt(headerMatch[3], 10);
111745
+ const cached3 = commitCache.get(currentSha);
111746
+ if (cached3) {
111747
+ currentAuthor = cached3.author;
111748
+ currentAuthorTime = cached3.authorTime;
111749
+ currentSummary = cached3.summary;
111750
+ } else {
111751
+ currentAuthor = "";
111752
+ currentAuthorTime = "";
111753
+ currentSummary = "";
111754
+ }
111755
+ continue;
111756
+ }
111757
+ if (rawLine.startsWith("author ")) {
111758
+ currentAuthor = rawLine.slice(7);
111759
+ let meta3 = commitCache.get(currentSha);
111760
+ if (!meta3) {
111761
+ meta3 = { author: "", authorTime: "", summary: "" };
111762
+ commitCache.set(currentSha, meta3);
111763
+ }
111764
+ meta3.author = currentAuthor;
111765
+ continue;
111766
+ }
111767
+ if (rawLine.startsWith("author-time ")) {
111768
+ currentAuthorTime = rawLine.slice(12);
111769
+ let meta3 = commitCache.get(currentSha);
111770
+ if (!meta3) {
111771
+ meta3 = { author: "", authorTime: "", summary: "" };
111772
+ commitCache.set(currentSha, meta3);
111773
+ }
111774
+ meta3.authorTime = currentAuthorTime;
111775
+ continue;
111776
+ }
111777
+ if (rawLine.startsWith("summary ")) {
111778
+ currentSummary = rawLine.slice(8);
111779
+ let meta3 = commitCache.get(currentSha);
111780
+ if (!meta3) {
111781
+ meta3 = { author: "", authorTime: "", summary: "" };
111782
+ commitCache.set(currentSha, meta3);
111783
+ }
111784
+ meta3.summary = currentSummary;
111785
+ continue;
111786
+ }
111787
+ if (rawLine.startsWith("\t")) {
111788
+ entries.push({
111789
+ line: currentLine,
111790
+ sha: currentSha.slice(0, 8),
111791
+ author: currentAuthor,
111792
+ authorTime: currentAuthorTime,
111793
+ summary: currentSummary,
111794
+ content: rawLine.slice(1)
111795
+ });
111796
+ if (entries.length >= linesCap)
111797
+ break;
111798
+ }
111799
+ }
111800
+ return entries.slice(0, linesCap);
111801
+ }
111802
+ var git_blame = createSwarmTool({
111803
+ description: "Analyze per-line git blame metadata for a file. Returns sha (abbreviated), author, date (ISO), summary, and content for each line. Uses git blame --porcelain. Rejects binary files and validates paths.",
111804
+ args: {
111805
+ file: exports_external.string().describe("Relative file path to blame (required, relative to project root)"),
111806
+ start: exports_external.number().optional().describe("Optional start line number (1-indexed). Requires end parameter."),
111807
+ end: exports_external.number().optional().describe("Optional end line number (1-indexed, inclusive). Requires start parameter.")
111808
+ },
111809
+ async execute(args2, directory) {
111810
+ let fileInput;
111811
+ let startInput;
111812
+ let endInput;
111813
+ try {
111814
+ if (args2 && typeof args2 === "object") {
111815
+ const obj = args2;
111816
+ fileInput = typeof obj.file === "string" ? obj.file : undefined;
111817
+ startInput = typeof obj.start === "number" ? obj.start : undefined;
111818
+ endInput = typeof obj.end === "number" ? obj.end : undefined;
111819
+ }
111820
+ } catch {}
111821
+ if (!fileInput) {
111822
+ return JSON.stringify({
111823
+ error: "file path is required",
111824
+ file: String(fileInput ?? ""),
111825
+ lineCount: 0,
111826
+ lines: []
111827
+ });
111828
+ }
111829
+ const file3 = fileInput;
111830
+ const pathError = validateFilePath(file3);
111831
+ if (pathError) {
111832
+ return JSON.stringify({
111833
+ error: pathError,
111834
+ file: file3,
111835
+ lineCount: 0,
111836
+ lines: []
111837
+ });
111838
+ }
111839
+ const startError = validateLineNumber(startInput, "start");
111840
+ if (startError) {
111841
+ return JSON.stringify({
111842
+ error: startError,
111843
+ file: file3,
111844
+ lineCount: 0,
111845
+ lines: []
111846
+ });
111847
+ }
111848
+ const endError = validateLineNumber(endInput, "end");
111849
+ if (endError) {
111850
+ return JSON.stringify({
111851
+ error: endError,
111852
+ file: file3,
111853
+ lineCount: 0,
111854
+ lines: []
111855
+ });
111856
+ }
111857
+ if (startInput !== undefined && endInput === undefined || startInput === undefined && endInput !== undefined) {
111858
+ return JSON.stringify({
111859
+ error: "both start and end must be provided together for a line range",
111860
+ file: file3,
111861
+ lineCount: 0,
111862
+ lines: []
111863
+ });
111864
+ }
111865
+ if (startInput !== undefined && endInput !== undefined && startInput > endInput) {
111866
+ return JSON.stringify({
111867
+ error: "start must be less than or equal to end",
111868
+ file: file3,
111869
+ lineCount: 0,
111870
+ lines: []
111871
+ });
111872
+ }
111873
+ const resolvedPath = path121.resolve(directory, file3);
111874
+ if (!fs83.existsSync(resolvedPath)) {
111875
+ return JSON.stringify({
111876
+ error: `file not found: ${file3}`,
111877
+ file: file3,
111878
+ lineCount: 0,
111879
+ lines: []
111880
+ });
111881
+ }
111882
+ const realDir = fs83.realpathSync(directory);
111883
+ const realPath = fs83.realpathSync(resolvedPath);
111884
+ const relative25 = path121.relative(realDir, realPath);
111885
+ if (relative25.startsWith("..") || path121.isAbsolute(relative25)) {
111886
+ return JSON.stringify({
111887
+ error: "file path resolves outside the workspace",
111888
+ file: file3,
111889
+ lineCount: 0,
111890
+ lines: []
111891
+ });
111892
+ }
111893
+ const stat9 = fs83.statSync(resolvedPath);
111894
+ if (stat9.isDirectory()) {
111895
+ return JSON.stringify({
111896
+ error: "path is a directory, not a file",
111897
+ file: file3,
111898
+ lineCount: 0,
111899
+ lines: []
111900
+ });
111901
+ }
111902
+ if (isBinaryFile2(file3)) {
111903
+ return JSON.stringify({
111904
+ error: "binary files are not supported for git blame",
111905
+ file: file3,
111906
+ lineCount: 0,
111907
+ lines: []
111908
+ });
111909
+ }
111910
+ const gitArgs = ["blame", "--porcelain"];
111911
+ if (startInput !== undefined && endInput !== undefined) {
111912
+ gitArgs.push("-L", `${startInput},${endInput}`);
111913
+ }
111914
+ gitArgs.push("--", file3);
111915
+ const result = child_process9.spawnSync("git", gitArgs, {
111916
+ cwd: directory,
111917
+ encoding: "utf-8",
111918
+ timeout: BLAME_TIMEOUT_MS,
111919
+ windowsHide: true,
111920
+ maxBuffer: 5 * 1024 * 1024,
111921
+ stdio: ["ignore", "pipe", "pipe"]
111922
+ });
111923
+ if (result.error) {
111924
+ const isTimeout = "code" in result.error && result.error.code === "ETIMEDOUT";
111925
+ if (isTimeout) {
111926
+ return JSON.stringify({
111927
+ error: "git blame timed out",
111928
+ file: file3,
111929
+ lineCount: 0,
111930
+ lines: []
111931
+ });
111932
+ }
111933
+ const message = result.error instanceof Error ? result.error.message : String(result.error);
111934
+ if (message.includes("ENOENT") || message.includes("not found")) {
111935
+ return JSON.stringify({
111936
+ error: "git is not available or not in PATH",
111937
+ file: file3,
111938
+ lineCount: 0,
111939
+ lines: []
111940
+ });
111941
+ }
111942
+ return JSON.stringify({
111943
+ error: `git execution failed: ${message}`,
111944
+ file: file3,
111945
+ lineCount: 0,
111946
+ lines: []
111947
+ });
111948
+ }
111949
+ if (result.status !== 0) {
111950
+ const stderr = (result.stderr ?? "").trim();
111951
+ if (stderr.includes("not a git repository") || stderr.includes("not in a git repository")) {
111952
+ return JSON.stringify({
111953
+ error: "not a git repository",
111954
+ file: file3,
111955
+ lineCount: 0,
111956
+ lines: []
111957
+ });
111958
+ }
111959
+ if (stderr.includes("no such path") || stderr.includes("did not match any files")) {
111960
+ return JSON.stringify({
111961
+ error: `file not tracked by git: ${file3}`,
111962
+ file: file3,
111963
+ lineCount: 0,
111964
+ lines: []
111965
+ });
111966
+ }
111967
+ return JSON.stringify({
111968
+ error: `git blame failed: ${stderr || `exit code ${result.status}`}`,
111969
+ file: file3,
111970
+ lineCount: 0,
111971
+ lines: []
111972
+ });
111973
+ }
111974
+ if (result.signal === "SIGTERM" || result.signal === "SIGKILL") {
111975
+ return JSON.stringify({
111976
+ error: "git blame timed out",
111977
+ file: file3,
111978
+ lineCount: 0,
111979
+ lines: []
111980
+ });
111981
+ }
111982
+ const stdout = result.stdout ?? "";
111983
+ if (!stdout.trim()) {
111984
+ return JSON.stringify({
111985
+ error: "no blame output (file may be empty or untracked)",
111986
+ file: file3,
111987
+ lineCount: 0,
111988
+ lines: []
111989
+ });
111990
+ }
111991
+ const rawEntries = parsePorcelainBlame(stdout, MAX_OUTPUT_LINES2);
111992
+ const lines = rawEntries.map((entry) => ({
111993
+ line: entry.line,
111994
+ sha: entry.sha,
111995
+ author: entry.author,
111996
+ date: Number.parseInt(entry.authorTime, 10) > 0 ? new Date(Number.parseInt(entry.authorTime, 10) * 1000).toISOString().slice(0, 10) : entry.authorTime,
111997
+ summary: entry.summary,
111998
+ content: entry.content
111999
+ }));
112000
+ const resultJson = {
112001
+ file: file3,
112002
+ lineCount: lines.length,
112003
+ lines
112004
+ };
112005
+ return JSON.stringify(resultJson, null, 2);
112006
+ }
112007
+ });
112008
+
111422
112009
  // src/tools/gitingest.ts
111423
112010
  init_zod();
111424
112011
  init_create_tool();
111425
112012
  var GITINGEST_TIMEOUT_MS = 1e4;
111426
112013
  var GITINGEST_MAX_RESPONSE_BYTES = 5242880;
111427
112014
  var GITINGEST_MAX_RETRIES = 2;
111428
- var delay = (ms) => new Promise((resolve43) => setTimeout(resolve43, ms));
112015
+ var delay = (ms) => new Promise((resolve44) => setTimeout(resolve44, ms));
111429
112016
  async function fetchGitingest(args2) {
111430
112017
  for (let attempt = 0;attempt <= GITINGEST_MAX_RETRIES; attempt++) {
111431
112018
  try {
@@ -111513,8 +112100,8 @@ var gitingest = createSwarmTool({
111513
112100
  init_zod();
111514
112101
  init_create_tool();
111515
112102
  init_path_security();
111516
- import * as fs83 from "node:fs";
111517
- import * as path121 from "node:path";
112103
+ import * as fs84 from "node:fs";
112104
+ import * as path122 from "node:path";
111518
112105
  var MAX_FILE_PATH_LENGTH2 = 500;
111519
112106
  var MAX_SYMBOL_LENGTH = 256;
111520
112107
  var MAX_FILE_SIZE_BYTES7 = 1024 * 1024;
@@ -111561,8 +112148,8 @@ function validateSymbolInput(symbol3) {
111561
112148
  }
111562
112149
  return null;
111563
112150
  }
111564
- function isBinaryFile2(filePath, buffer) {
111565
- const ext = path121.extname(filePath).toLowerCase();
112151
+ function isBinaryFile3(filePath, buffer) {
112152
+ const ext = path122.extname(filePath).toLowerCase();
111566
112153
  if (ext === ".json" || ext === ".md" || ext === ".txt") {
111567
112154
  return false;
111568
112155
  }
@@ -111586,15 +112173,15 @@ function parseImports(content, targetFile, targetSymbol) {
111586
112173
  const imports = [];
111587
112174
  let _resolvedTarget;
111588
112175
  try {
111589
- _resolvedTarget = path121.resolve(targetFile);
112176
+ _resolvedTarget = path122.resolve(targetFile);
111590
112177
  } catch {
111591
112178
  _resolvedTarget = targetFile;
111592
112179
  }
111593
- const targetBasename = path121.basename(targetFile, path121.extname(targetFile));
112180
+ const targetBasename = path122.basename(targetFile, path122.extname(targetFile));
111594
112181
  const targetWithExt = targetFile;
111595
112182
  const targetWithoutExt = targetFile.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
111596
- const normalizedTargetWithExt = path121.normalize(targetWithExt).replace(/\\/g, "/");
111597
- const normalizedTargetWithoutExt = path121.normalize(targetWithoutExt).replace(/\\/g, "/");
112183
+ const normalizedTargetWithExt = path122.normalize(targetWithExt).replace(/\\/g, "/");
112184
+ const normalizedTargetWithoutExt = path122.normalize(targetWithoutExt).replace(/\\/g, "/");
111598
112185
  const importRegex = /import\s+(?:\{[\s\S]*?\}|(?:\*\s+as\s+\w+)|\w+)\s+from\s+['"`]([^'"`]+)['"`]|import\s+['"`]([^'"`]+)['"`]|require\s*\(\s*['"`]([^'"`]+)['"`]\s*\)/g;
111599
112186
  for (let match = importRegex.exec(content);match !== null; match = importRegex.exec(content)) {
111600
112187
  const modulePath = match[1] || match[2] || match[3];
@@ -111617,9 +112204,9 @@ function parseImports(content, targetFile, targetSymbol) {
111617
112204
  }
111618
112205
  const _normalizedModule = modulePath.replace(/^\.\//, "").replace(/^\.\.\\/, "../");
111619
112206
  let isMatch = false;
111620
- const _targetDir = path121.dirname(targetFile);
111621
- const targetExt = path121.extname(targetFile);
111622
- const targetBasenameNoExt = path121.basename(targetFile, targetExt);
112207
+ const _targetDir = path122.dirname(targetFile);
112208
+ const targetExt = path122.extname(targetFile);
112209
+ const targetBasenameNoExt = path122.basename(targetFile, targetExt);
111623
112210
  const moduleNormalized = modulePath.replace(/\\/g, "/").replace(/^\.\//, "");
111624
112211
  const moduleName = modulePath.split(/[/\\]/).pop() || "";
111625
112212
  const moduleNameNoExt = moduleName.replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, "");
@@ -111659,7 +112246,7 @@ function parseImports(content, targetFile, targetSymbol) {
111659
112246
  }
111660
112247
  return imports;
111661
112248
  }
111662
- var SKIP_DIRECTORIES4 = new Set([
112249
+ var SKIP_DIRECTORIES5 = new Set([
111663
112250
  "node_modules",
111664
112251
  ".git",
111665
112252
  "dist",
@@ -111673,10 +112260,10 @@ var SKIP_DIRECTORIES4 = new Set([
111673
112260
  ".svn",
111674
112261
  ".hg"
111675
112262
  ]);
111676
- function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFiles: 0, fileErrors: [] }) {
112263
+ function findSourceFiles3(dir, files = [], stats = { skippedDirs: [], skippedFiles: 0, fileErrors: [] }) {
111677
112264
  let entries;
111678
112265
  try {
111679
- entries = fs83.readdirSync(dir);
112266
+ entries = fs84.readdirSync(dir);
111680
112267
  } catch (e) {
111681
112268
  stats.fileErrors.push({
111682
112269
  path: dir,
@@ -111686,14 +112273,14 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
111686
112273
  }
111687
112274
  entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
111688
112275
  for (const entry of entries) {
111689
- if (SKIP_DIRECTORIES4.has(entry)) {
111690
- stats.skippedDirs.push(path121.join(dir, entry));
112276
+ if (SKIP_DIRECTORIES5.has(entry)) {
112277
+ stats.skippedDirs.push(path122.join(dir, entry));
111691
112278
  continue;
111692
112279
  }
111693
- const fullPath = path121.join(dir, entry);
112280
+ const fullPath = path122.join(dir, entry);
111694
112281
  let stat9;
111695
112282
  try {
111696
- stat9 = fs83.statSync(fullPath);
112283
+ stat9 = fs84.statSync(fullPath);
111697
112284
  } catch (e) {
111698
112285
  stats.fileErrors.push({
111699
112286
  path: fullPath,
@@ -111702,9 +112289,9 @@ function findSourceFiles2(dir, files = [], stats = { skippedDirs: [], skippedFil
111702
112289
  continue;
111703
112290
  }
111704
112291
  if (stat9.isDirectory()) {
111705
- findSourceFiles2(fullPath, files, stats);
112292
+ findSourceFiles3(fullPath, files, stats);
111706
112293
  } else if (stat9.isFile()) {
111707
- const ext = path121.extname(fullPath).toLowerCase();
112294
+ const ext = path122.extname(fullPath).toLowerCase();
111708
112295
  if (SUPPORTED_EXTENSIONS3.includes(ext)) {
111709
112296
  files.push(fullPath);
111710
112297
  }
@@ -111761,8 +112348,8 @@ var imports = createSwarmTool({
111761
112348
  return JSON.stringify(errorResult, null, 2);
111762
112349
  }
111763
112350
  try {
111764
- const targetFile = path121.resolve(file3);
111765
- if (!fs83.existsSync(targetFile)) {
112351
+ const targetFile = path122.resolve(file3);
112352
+ if (!fs84.existsSync(targetFile)) {
111766
112353
  const errorResult = {
111767
112354
  error: `target file not found: ${file3}`,
111768
112355
  target: file3,
@@ -111772,7 +112359,7 @@ var imports = createSwarmTool({
111772
112359
  };
111773
112360
  return JSON.stringify(errorResult, null, 2);
111774
112361
  }
111775
- const targetStat = fs83.statSync(targetFile);
112362
+ const targetStat = fs84.statSync(targetFile);
111776
112363
  if (!targetStat.isFile()) {
111777
112364
  const errorResult = {
111778
112365
  error: "target must be a file, not a directory",
@@ -111783,13 +112370,13 @@ var imports = createSwarmTool({
111783
112370
  };
111784
112371
  return JSON.stringify(errorResult, null, 2);
111785
112372
  }
111786
- const baseDir = path121.dirname(targetFile);
112373
+ const baseDir = path122.dirname(targetFile);
111787
112374
  const scanStats = {
111788
112375
  skippedDirs: [],
111789
112376
  skippedFiles: 0,
111790
112377
  fileErrors: []
111791
112378
  };
111792
- const sourceFiles = findSourceFiles2(baseDir, [], scanStats);
112379
+ const sourceFiles = findSourceFiles3(baseDir, [], scanStats);
111793
112380
  const filesToScan = sourceFiles.filter((f) => f !== targetFile).sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())).slice(0, MAX_CONSUMERS * 10);
111794
112381
  const consumers = [];
111795
112382
  let skippedFileCount = 0;
@@ -111798,13 +112385,13 @@ var imports = createSwarmTool({
111798
112385
  if (consumers.length >= MAX_CONSUMERS)
111799
112386
  break;
111800
112387
  try {
111801
- const stat9 = fs83.statSync(filePath);
112388
+ const stat9 = fs84.statSync(filePath);
111802
112389
  if (stat9.size > MAX_FILE_SIZE_BYTES7) {
111803
112390
  skippedFileCount++;
111804
112391
  continue;
111805
112392
  }
111806
- const buffer = fs83.readFileSync(filePath);
111807
- if (isBinaryFile2(filePath, buffer)) {
112393
+ const buffer = fs84.readFileSync(filePath);
112394
+ if (isBinaryFile3(filePath, buffer)) {
111808
112395
  skippedFileCount++;
111809
112396
  continue;
111810
112397
  }
@@ -112171,7 +112758,7 @@ init_zod();
112171
112758
  init_config();
112172
112759
  init_knowledge_store();
112173
112760
  init_create_tool();
112174
- import { existsSync as existsSync69 } from "node:fs";
112761
+ import { existsSync as existsSync70 } from "node:fs";
112175
112762
  var DEFAULT_LIMIT = 10;
112176
112763
  var MAX_LESSON_LENGTH = 200;
112177
112764
  var VALID_CATEGORIES3 = [
@@ -112247,14 +112834,14 @@ function validateLimit(limit) {
112247
112834
  }
112248
112835
  async function readSwarmKnowledge(directory) {
112249
112836
  const swarmPath = resolveSwarmKnowledgePath(directory);
112250
- if (!existsSync69(swarmPath)) {
112837
+ if (!existsSync70(swarmPath)) {
112251
112838
  return [];
112252
112839
  }
112253
112840
  return readKnowledge(swarmPath);
112254
112841
  }
112255
112842
  async function readHiveKnowledge() {
112256
112843
  const hivePath = resolveHiveKnowledgePath();
112257
- if (!existsSync69(hivePath)) {
112844
+ if (!existsSync70(hivePath)) {
112258
112845
  return [];
112259
112846
  }
112260
112847
  return readKnowledge(hivePath);
@@ -112679,12 +113266,12 @@ var lean_turbo_acquire_locks = createSwarmTool({
112679
113266
  // src/tools/lean-turbo-plan-lanes.ts
112680
113267
  init_zod();
112681
113268
  init_constants();
112682
- import * as fs85 from "node:fs";
112683
- import * as path123 from "node:path";
113269
+ import * as fs86 from "node:fs";
113270
+ import * as path124 from "node:path";
112684
113271
 
112685
113272
  // src/turbo/lean/conflicts.ts
112686
- import * as fs84 from "node:fs";
112687
- import * as path122 from "node:path";
113273
+ import * as fs85 from "node:fs";
113274
+ import * as path123 from "node:path";
112688
113275
  var DEFAULT_GLOBAL_FILES = [
112689
113276
  "package.json",
112690
113277
  "package-lock.json",
@@ -112811,12 +113398,12 @@ function isProtectedPath3(normalizedPath) {
112811
113398
  return false;
112812
113399
  }
112813
113400
  function readTaskScopes(directory, taskId) {
112814
- const scopePath = path122.join(directory, ".swarm", "scopes", `scope-${taskId}.json`);
113401
+ const scopePath = path123.join(directory, ".swarm", "scopes", `scope-${taskId}.json`);
112815
113402
  try {
112816
- if (!fs84.existsSync(scopePath)) {
113403
+ if (!fs85.existsSync(scopePath)) {
112817
113404
  return null;
112818
113405
  }
112819
- const raw = fs84.readFileSync(scopePath, "utf-8");
113406
+ const raw = fs85.readFileSync(scopePath, "utf-8");
112820
113407
  const parsed = JSON.parse(raw);
112821
113408
  if (!parsed || !Array.isArray(parsed.files)) {
112822
113409
  return null;
@@ -113199,12 +113786,12 @@ function createEmptyPlan(phaseNumber, planId) {
113199
113786
  // src/tools/lean-turbo-plan-lanes.ts
113200
113787
  init_create_tool();
113201
113788
  function readPlanJson(directory) {
113202
- const planPath = path123.join(directory, ".swarm", "plan.json");
113203
- if (!fs85.existsSync(planPath)) {
113789
+ const planPath = path124.join(directory, ".swarm", "plan.json");
113790
+ if (!fs86.existsSync(planPath)) {
113204
113791
  return null;
113205
113792
  }
113206
113793
  try {
113207
- return JSON.parse(fs85.readFileSync(planPath, "utf-8"));
113794
+ return JSON.parse(fs86.readFileSync(planPath, "utf-8"));
113208
113795
  } catch {
113209
113796
  return null;
113210
113797
  }
@@ -113254,16 +113841,16 @@ init_config();
113254
113841
 
113255
113842
  // src/turbo/lean/reviewer.ts
113256
113843
  init_state();
113257
- import * as fs87 from "node:fs/promises";
113258
- import * as path125 from "node:path";
113844
+ import * as fs88 from "node:fs/promises";
113845
+ import * as path126 from "node:path";
113259
113846
 
113260
113847
  // src/turbo/lean/evidence.ts
113261
113848
  init_bun_compat();
113262
113849
  import { rmSync as rmSync6 } from "node:fs";
113263
- import * as fs86 from "node:fs/promises";
113264
- import * as path124 from "node:path";
113850
+ import * as fs87 from "node:fs/promises";
113851
+ import * as path125 from "node:path";
113265
113852
  function leanTurboEvidenceDir(directory, phase) {
113266
- return path124.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
113853
+ return path125.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
113267
113854
  }
113268
113855
  function validateLaneId(laneId) {
113269
113856
  if (laneId.length === 0) {
@@ -113285,21 +113872,21 @@ function validateLaneId(laneId) {
113285
113872
  function laneEvidencePath(directory, phase, laneId) {
113286
113873
  validateLaneId(laneId);
113287
113874
  const expectedDir = leanTurboEvidenceDir(directory, phase);
113288
- const resolvedPath = path124.resolve(path124.join(expectedDir, `${laneId}.json`));
113289
- const resolvedDir = path124.resolve(expectedDir);
113290
- if (!resolvedPath.startsWith(resolvedDir + path124.sep) && resolvedPath !== resolvedDir) {
113875
+ const resolvedPath = path125.resolve(path125.join(expectedDir, `${laneId}.json`));
113876
+ const resolvedDir = path125.resolve(expectedDir);
113877
+ if (!resolvedPath.startsWith(resolvedDir + path125.sep) && resolvedPath !== resolvedDir) {
113291
113878
  throw new Error(`Invalid laneId: path traversal detected (got "${laneId}")`);
113292
113879
  }
113293
113880
  return resolvedPath;
113294
113881
  }
113295
113882
  async function atomicWriteJson(filePath, data) {
113296
113883
  const content = JSON.stringify(data, null, 2);
113297
- const dir = path124.dirname(filePath);
113298
- await fs86.mkdir(dir, { recursive: true });
113884
+ const dir = path125.dirname(filePath);
113885
+ await fs87.mkdir(dir, { recursive: true });
113299
113886
  const tempPath = `${filePath}.tmp.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}`;
113300
113887
  try {
113301
113888
  await bunWrite(tempPath, content);
113302
- await fs86.rename(tempPath, filePath);
113889
+ await fs87.rename(tempPath, filePath);
113303
113890
  } catch (error93) {
113304
113891
  try {
113305
113892
  rmSync6(tempPath, { force: true });
@@ -113308,7 +113895,7 @@ async function atomicWriteJson(filePath, data) {
113308
113895
  }
113309
113896
  }
113310
113897
  function phaseEvidencePath(directory, phase) {
113311
- return path124.join(leanTurboEvidenceDir(directory, phase), "lean-turbo-phase.json");
113898
+ return path125.join(leanTurboEvidenceDir(directory, phase), "lean-turbo-phase.json");
113312
113899
  }
113313
113900
  async function writeLaneEvidence(directory, phase, evidence) {
113314
113901
  const targetPath = laneEvidencePath(directory, phase, evidence.laneId);
@@ -113318,7 +113905,7 @@ async function readPhaseEvidence(directory, phase) {
113318
113905
  const targetPath = phaseEvidencePath(directory, phase);
113319
113906
  let content;
113320
113907
  try {
113321
- content = await fs86.readFile(targetPath, "utf-8");
113908
+ content = await fs87.readFile(targetPath, "utf-8");
113322
113909
  } catch (error93) {
113323
113910
  const code = error93.code;
113324
113911
  if (code === "ENOENT" || code === "ENOTDIR") {
@@ -113336,7 +113923,7 @@ async function listLaneEvidence(directory, phase) {
113336
113923
  const evidenceDir = leanTurboEvidenceDir(directory, phase);
113337
113924
  let entries;
113338
113925
  try {
113339
- entries = await fs86.readdir(evidenceDir);
113926
+ entries = await fs87.readdir(evidenceDir);
113340
113927
  } catch (error93) {
113341
113928
  const code = error93.code;
113342
113929
  if (code === "ENOENT" || code === "ENOTDIR") {
@@ -113352,10 +113939,10 @@ async function listLaneEvidence(directory, phase) {
113352
113939
  if (entry === "lean-turbo-phase.json") {
113353
113940
  continue;
113354
113941
  }
113355
- const filePath = path124.join(evidenceDir, entry);
113942
+ const filePath = path125.join(evidenceDir, entry);
113356
113943
  let content;
113357
113944
  try {
113358
- content = await fs86.readFile(filePath, "utf-8");
113945
+ content = await fs87.readFile(filePath, "utf-8");
113359
113946
  } catch {
113360
113947
  continue;
113361
113948
  }
@@ -113483,9 +114070,9 @@ function parseReviewerVerdict(responseText) {
113483
114070
  return { verdict, reason };
113484
114071
  }
113485
114072
  async function writeReviewerEvidence(directory, phase, verdict, reason) {
113486
- const evidenceDir = path125.join(directory, ".swarm", "evidence", String(phase));
113487
- await fs87.mkdir(evidenceDir, { recursive: true });
113488
- const evidencePath = path125.join(evidenceDir, "lean-turbo-reviewer.json");
114073
+ const evidenceDir = path126.join(directory, ".swarm", "evidence", String(phase));
114074
+ await fs88.mkdir(evidenceDir, { recursive: true });
114075
+ const evidencePath = path126.join(evidenceDir, "lean-turbo-reviewer.json");
113489
114076
  const content = JSON.stringify({
113490
114077
  phase,
113491
114078
  verdict,
@@ -113494,11 +114081,11 @@ async function writeReviewerEvidence(directory, phase, verdict, reason) {
113494
114081
  }, null, 2);
113495
114082
  const tempPath = `${evidencePath}.tmp.${process.pid}.${Date.now()}`;
113496
114083
  try {
113497
- await fs87.writeFile(tempPath, content, "utf-8");
113498
- await fs87.rename(tempPath, evidencePath);
114084
+ await fs88.writeFile(tempPath, content, "utf-8");
114085
+ await fs88.rename(tempPath, evidencePath);
113499
114086
  } catch (error93) {
113500
114087
  try {
113501
- await fs87.unlink(tempPath);
114088
+ await fs88.unlink(tempPath);
113502
114089
  } catch {}
113503
114090
  throw error93;
113504
114091
  }
@@ -114296,8 +114883,8 @@ init_lint();
114296
114883
  // src/tools/lint-spec.ts
114297
114884
  init_spec_schema();
114298
114885
  init_create_tool();
114299
- import * as fs88 from "node:fs";
114300
- import * as path126 from "node:path";
114886
+ import * as fs89 from "node:fs";
114887
+ import * as path127 from "node:path";
114301
114888
  var SPEC_FILE_NAME = "spec.md";
114302
114889
  var SWARM_DIR2 = ".swarm";
114303
114890
  var OBLIGATION_KEYWORDS = ["MUST", "SHALL", "SHOULD", "MAY"];
@@ -114350,8 +114937,8 @@ var lint_spec = createSwarmTool({
114350
114937
  async execute(_args, directory) {
114351
114938
  const errors5 = [];
114352
114939
  const warnings = [];
114353
- const specPath = path126.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
114354
- if (!fs88.existsSync(specPath)) {
114940
+ const specPath = path127.join(directory, SWARM_DIR2, SPEC_FILE_NAME);
114941
+ if (!fs89.existsSync(specPath)) {
114355
114942
  const result2 = {
114356
114943
  valid: false,
114357
114944
  specMtime: null,
@@ -114370,12 +114957,12 @@ var lint_spec = createSwarmTool({
114370
114957
  }
114371
114958
  let specMtime = null;
114372
114959
  try {
114373
- const stats = fs88.statSync(specPath);
114960
+ const stats = fs89.statSync(specPath);
114374
114961
  specMtime = stats.mtime.toISOString();
114375
114962
  } catch {}
114376
114963
  let content;
114377
114964
  try {
114378
- content = fs88.readFileSync(specPath, "utf-8");
114965
+ content = fs89.readFileSync(specPath, "utf-8");
114379
114966
  } catch (e) {
114380
114967
  const result2 = {
114381
114968
  valid: false,
@@ -114421,13 +115008,13 @@ var lint_spec = createSwarmTool({
114421
115008
 
114422
115009
  // src/tools/mutation-test.ts
114423
115010
  init_zod();
114424
- import * as fs89 from "node:fs";
114425
- import * as path128 from "node:path";
115011
+ import * as fs90 from "node:fs";
115012
+ import * as path129 from "node:path";
114426
115013
 
114427
115014
  // src/mutation/engine.ts
114428
- import { spawnSync as spawnSync8 } from "node:child_process";
115015
+ import { spawnSync as spawnSync9 } from "node:child_process";
114429
115016
  import { unlinkSync as unlinkSync18, writeFileSync as writeFileSync24 } from "node:fs";
114430
- import * as path127 from "node:path";
115017
+ import * as path128 from "node:path";
114431
115018
 
114432
115019
  // src/mutation/equivalence.ts
114433
115020
  function isStaticallyEquivalent(originalCode, mutatedCode) {
@@ -114562,7 +115149,7 @@ var _internals57 = {
114562
115149
  executeMutation,
114563
115150
  computeReport,
114564
115151
  executeMutationSuite,
114565
- spawnSync: spawnSync8
115152
+ spawnSync: spawnSync9
114566
115153
  };
114567
115154
  async function executeMutation(patch, testCommand, _testFiles, workingDir) {
114568
115155
  const startTime = Date.now();
@@ -114573,7 +115160,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
114573
115160
  let patchFile;
114574
115161
  try {
114575
115162
  const safeId2 = patch.id.replace(/[^a-zA-Z0-9_-]/g, "_");
114576
- patchFile = path127.join(workingDir, `.mutation_patch_${safeId2}.diff`);
115163
+ patchFile = path128.join(workingDir, `.mutation_patch_${safeId2}.diff`);
114577
115164
  try {
114578
115165
  writeFileSync24(patchFile, patch.patch);
114579
115166
  } catch (writeErr) {
@@ -114977,8 +115564,8 @@ var mutation_test = createSwarmTool({
114977
115564
  ];
114978
115565
  for (const filePath of uniquePaths) {
114979
115566
  try {
114980
- const resolvedPath = path128.resolve(cwd, filePath);
114981
- sourceFiles.set(filePath, fs89.readFileSync(resolvedPath, "utf-8"));
115567
+ const resolvedPath = path129.resolve(cwd, filePath);
115568
+ sourceFiles.set(filePath, fs90.readFileSync(resolvedPath, "utf-8"));
114982
115569
  } catch {}
114983
115570
  }
114984
115571
  const report = await executeMutationSuite(typedArgs.patches, typedArgs.test_command, typedArgs.files, cwd, undefined, undefined, sourceFiles.size > 0 ? sourceFiles : undefined);
@@ -114998,30 +115585,30 @@ init_zod();
114998
115585
  init_config();
114999
115586
  init_schema();
115000
115587
  init_manager2();
115001
- import * as fs99 from "node:fs";
115002
- import * as path138 from "node:path";
115588
+ import * as fs100 from "node:fs";
115589
+ import * as path139 from "node:path";
115003
115590
 
115004
115591
  // src/full-auto/phase-approval.ts
115005
115592
  init_utils2();
115006
115593
  init_logger();
115007
115594
  init_state2();
115008
- import * as fs90 from "node:fs";
115009
- import * as path129 from "node:path";
115595
+ import * as fs91 from "node:fs";
115596
+ import * as path130 from "node:path";
115010
115597
  var APPROVAL_TTL_MS = 24 * 60 * 60 * 1000;
115011
115598
  function readEvidenceDir(directory, phase) {
115012
115599
  try {
115013
- const dirPath = validateSwarmPath(directory, path129.posix.join("evidence", String(phase)));
115014
- if (!fs90.existsSync(dirPath))
115600
+ const dirPath = validateSwarmPath(directory, path130.posix.join("evidence", String(phase)));
115601
+ if (!fs91.existsSync(dirPath))
115015
115602
  return [];
115016
- const entries = fs90.readdirSync(dirPath);
115017
- return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) => path129.join(dirPath, e));
115603
+ const entries = fs91.readdirSync(dirPath);
115604
+ return entries.filter((e) => e.startsWith("full-auto-") && e.endsWith(".json")).map((e) => path130.join(dirPath, e));
115018
115605
  } catch {
115019
115606
  return [];
115020
115607
  }
115021
115608
  }
115022
115609
  function parseEvidence(filePath) {
115023
115610
  try {
115024
- const raw = fs90.readFileSync(filePath, "utf-8");
115611
+ const raw = fs91.readFileSync(filePath, "utf-8");
115025
115612
  const parsed = JSON.parse(raw);
115026
115613
  return parsed;
115027
115614
  } catch (error93) {
@@ -115110,9 +115697,9 @@ function verifyFullAutoPhaseApproval(directory, sessionID, phase, config3) {
115110
115697
  function phaseIsExplicitlyNonCode(directory, phase) {
115111
115698
  try {
115112
115699
  const planPath = validateSwarmPath(directory, "plan.json");
115113
- if (!fs90.existsSync(planPath))
115700
+ if (!fs91.existsSync(planPath))
115114
115701
  return false;
115115
- const raw = fs90.readFileSync(planPath, "utf-8");
115702
+ const raw = fs91.readFileSync(planPath, "utf-8");
115116
115703
  const plan = JSON.parse(raw);
115117
115704
  const phases = Array.isArray(plan.phases) ? plan.phases : [];
115118
115705
  const entry = phases.find((p) => p.id === phase || p.phase === phase);
@@ -115154,20 +115741,20 @@ init_file_locks();
115154
115741
  init_plan_schema();
115155
115742
  init_ledger();
115156
115743
  init_manager();
115157
- import * as fs91 from "node:fs";
115158
- import * as path130 from "node:path";
115744
+ import * as fs92 from "node:fs";
115745
+ import * as path131 from "node:path";
115159
115746
  async function writeCheckpoint(directory) {
115160
115747
  try {
115161
115748
  const plan = await loadPlan(directory);
115162
115749
  if (!plan)
115163
115750
  return;
115164
- const swarmDir = path130.join(directory, ".swarm");
115165
- fs91.mkdirSync(swarmDir, { recursive: true });
115166
- const jsonPath = path130.join(swarmDir, "SWARM_PLAN.json");
115167
- const mdPath = path130.join(swarmDir, "SWARM_PLAN.md");
115168
- fs91.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
115751
+ const swarmDir = path131.join(directory, ".swarm");
115752
+ fs92.mkdirSync(swarmDir, { recursive: true });
115753
+ const jsonPath = path131.join(swarmDir, "SWARM_PLAN.json");
115754
+ const mdPath = path131.join(swarmDir, "SWARM_PLAN.md");
115755
+ fs92.writeFileSync(jsonPath, JSON.stringify(plan, null, 2), "utf8");
115169
115756
  const md = derivePlanMarkdown(plan);
115170
- fs91.writeFileSync(mdPath, md, "utf8");
115757
+ fs92.writeFileSync(mdPath, md, "utf8");
115171
115758
  } catch (error93) {
115172
115759
  console.warn(`[checkpoint] Failed to write SWARM_PLAN checkpoint: ${error93 instanceof Error ? error93.message : String(error93)}`);
115173
115760
  }
@@ -115182,8 +115769,8 @@ init_telemetry();
115182
115769
 
115183
115770
  // src/turbo/lean/phase-ready.ts
115184
115771
  init_file_locks();
115185
- import * as fs92 from "node:fs";
115186
- import * as path131 from "node:path";
115772
+ import * as fs93 from "node:fs";
115773
+ import * as path132 from "node:path";
115187
115774
  init_state3();
115188
115775
  var DEFAULT_CONFIG3 = {
115189
115776
  phase_reviewer: true,
@@ -115192,10 +115779,10 @@ var DEFAULT_CONFIG3 = {
115192
115779
  };
115193
115780
  function defaultReadPlanJson(dir) {
115194
115781
  try {
115195
- const planPath = path131.join(dir, ".swarm", "plan.json");
115196
- if (!fs92.existsSync(planPath))
115782
+ const planPath = path132.join(dir, ".swarm", "plan.json");
115783
+ if (!fs93.existsSync(planPath))
115197
115784
  return null;
115198
- const raw = fs92.readFileSync(planPath, "utf-8");
115785
+ const raw = fs93.readFileSync(planPath, "utf-8");
115199
115786
  const plan = JSON.parse(raw);
115200
115787
  if (typeof plan !== "object" || plan === null || !Array.isArray(plan.phases)) {
115201
115788
  return null;
@@ -115207,11 +115794,11 @@ function defaultReadPlanJson(dir) {
115207
115794
  }
115208
115795
  function readReviewerEvidenceFromFile(directory, phase) {
115209
115796
  try {
115210
- const evidencePath = path131.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-reviewer.json");
115211
- if (!fs92.existsSync(evidencePath)) {
115797
+ const evidencePath = path132.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-reviewer.json");
115798
+ if (!fs93.existsSync(evidencePath)) {
115212
115799
  return null;
115213
115800
  }
115214
- const raw = fs92.readFileSync(evidencePath, "utf-8");
115801
+ const raw = fs93.readFileSync(evidencePath, "utf-8");
115215
115802
  const parsed = JSON.parse(raw);
115216
115803
  if (typeof parsed !== "object" || parsed === null || typeof parsed.verdict !== "string") {
115217
115804
  return null;
@@ -115227,11 +115814,11 @@ function readReviewerEvidenceFromFile(directory, phase) {
115227
115814
  }
115228
115815
  function readCriticEvidenceFromFile(directory, phase) {
115229
115816
  try {
115230
- const evidencePath = path131.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-critic.json");
115231
- if (!fs92.existsSync(evidencePath)) {
115817
+ const evidencePath = path132.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-critic.json");
115818
+ if (!fs93.existsSync(evidencePath)) {
115232
115819
  return null;
115233
115820
  }
115234
- const raw = fs92.readFileSync(evidencePath, "utf-8");
115821
+ const raw = fs93.readFileSync(evidencePath, "utf-8");
115235
115822
  const parsed = JSON.parse(raw);
115236
115823
  if (typeof parsed !== "object" || parsed === null || typeof parsed.verdict !== "string") {
115237
115824
  return null;
@@ -115246,10 +115833,10 @@ function readCriticEvidenceFromFile(directory, phase) {
115246
115833
  }
115247
115834
  }
115248
115835
  function listLaneEvidenceSync(directory, phase) {
115249
- const evidenceDir = path131.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
115836
+ const evidenceDir = path132.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
115250
115837
  let entries;
115251
115838
  try {
115252
- entries = fs92.readdirSync(evidenceDir);
115839
+ entries = fs93.readdirSync(evidenceDir);
115253
115840
  } catch {
115254
115841
  return [];
115255
115842
  }
@@ -115316,8 +115903,8 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
115316
115903
  ...DEFAULT_CONFIG3,
115317
115904
  ...actualConfig
115318
115905
  };
115319
- const statePath = path131.join(directory, ".swarm", "turbo-state.json");
115320
- if (!fs92.existsSync(statePath)) {
115906
+ const statePath = path132.join(directory, ".swarm", "turbo-state.json");
115907
+ if (!fs93.existsSync(statePath)) {
115321
115908
  return {
115322
115909
  ok: false,
115323
115910
  reason: "Lean Turbo state unreadable or missing"
@@ -115504,10 +116091,10 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
115504
116091
  }
115505
116092
  }
115506
116093
  if (mergedConfig.integrated_diff_required) {
115507
- const evidencePath = path131.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-phase.json");
116094
+ const evidencePath = path132.join(directory, ".swarm", "evidence", String(phase), "lean-turbo-phase.json");
115508
116095
  let hasDiff = false;
115509
116096
  try {
115510
- const content = fs92.readFileSync(evidencePath, "utf-8");
116097
+ const content = fs93.readFileSync(evidencePath, "utf-8");
115511
116098
  const evidence = JSON.parse(content);
115512
116099
  hasDiff = !!evidence.integratedDiffSummary;
115513
116100
  } catch {}
@@ -115655,15 +116242,15 @@ async function runCompletionVerifyGate(ctx) {
115655
116242
  init_qa_gate_profile();
115656
116243
  init_manager();
115657
116244
  init_state();
115658
- import * as fs93 from "node:fs";
115659
- import * as path132 from "node:path";
116245
+ import * as fs94 from "node:fs";
116246
+ import * as path133 from "node:path";
115660
116247
  async function runDriftGate(ctx) {
115661
116248
  const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
115662
116249
  let driftCheckEnabled = true;
115663
116250
  let driftHasSpecMd = false;
115664
116251
  try {
115665
- const specMdPath = path132.join(dir, ".swarm", "spec.md");
115666
- driftHasSpecMd = fs93.existsSync(specMdPath);
116252
+ const specMdPath = path133.join(dir, ".swarm", "spec.md");
116253
+ driftHasSpecMd = fs94.existsSync(specMdPath);
115667
116254
  const gatePlan = await loadPlan(dir);
115668
116255
  if (gatePlan) {
115669
116256
  const gatePlanId = derivePlanId(gatePlan);
@@ -115690,9 +116277,9 @@ async function runDriftGate(ctx) {
115690
116277
  }
115691
116278
  let phaseType;
115692
116279
  try {
115693
- const planPath = path132.join(dir, ".swarm", "plan.json");
115694
- if (fs93.existsSync(planPath)) {
115695
- const planRaw = fs93.readFileSync(planPath, "utf-8");
116280
+ const planPath = path133.join(dir, ".swarm", "plan.json");
116281
+ if (fs94.existsSync(planPath)) {
116282
+ const planRaw = fs94.readFileSync(planPath, "utf-8");
115696
116283
  const plan = JSON.parse(planRaw);
115697
116284
  const targetPhase = plan.phases?.find((p) => p.id === phase);
115698
116285
  phaseType = targetPhase?.type;
@@ -115709,11 +116296,11 @@ async function runDriftGate(ctx) {
115709
116296
  };
115710
116297
  }
115711
116298
  try {
115712
- const driftEvidencePath = path132.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
116299
+ const driftEvidencePath = path133.join(dir, ".swarm", "evidence", String(phase), "drift-verifier.json");
115713
116300
  let driftVerdictFound = false;
115714
116301
  let driftVerdictApproved = false;
115715
116302
  try {
115716
- const driftEvidenceContent = fs93.readFileSync(driftEvidencePath, "utf-8");
116303
+ const driftEvidenceContent = fs94.readFileSync(driftEvidencePath, "utf-8");
115717
116304
  const driftEvidence = JSON.parse(driftEvidenceContent);
115718
116305
  const entries = driftEvidence.entries ?? [];
115719
116306
  for (const entry of entries) {
@@ -115745,9 +116332,9 @@ async function runDriftGate(ctx) {
115745
116332
  let incompleteTaskCount = 0;
115746
116333
  let planParseable = false;
115747
116334
  try {
115748
- const planPath = path132.join(dir, ".swarm", "plan.json");
115749
- if (fs93.existsSync(planPath)) {
115750
- const planRaw = fs93.readFileSync(planPath, "utf-8");
116335
+ const planPath = path133.join(dir, ".swarm", "plan.json");
116336
+ if (fs94.existsSync(planPath)) {
116337
+ const planRaw = fs94.readFileSync(planPath, "utf-8");
115751
116338
  const plan = JSON.parse(planRaw);
115752
116339
  planParseable = true;
115753
116340
  const planPhase = plan.phases?.find((p) => p.id === phase);
@@ -115826,8 +116413,8 @@ async function runDriftGate(ctx) {
115826
116413
  init_qa_gate_profile();
115827
116414
  init_manager();
115828
116415
  init_state();
115829
- import * as fs94 from "node:fs";
115830
- import * as path133 from "node:path";
116416
+ import * as fs95 from "node:fs";
116417
+ import * as path134 from "node:path";
115831
116418
  async function runFinalCouncilGate(ctx) {
115832
116419
  const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
115833
116420
  let finalCouncilEnabled = false;
@@ -115844,11 +116431,11 @@ async function runFinalCouncilGate(ctx) {
115844
116431
  const effective = getEffectiveGates(profile, overrides);
115845
116432
  if (effective.final_council === true) {
115846
116433
  finalCouncilEnabled = true;
115847
- const fcPath = path133.join(dir, ".swarm", "evidence", "final-council.json");
116434
+ const fcPath = path134.join(dir, ".swarm", "evidence", "final-council.json");
115848
116435
  let fcVerdictFound = false;
115849
116436
  let _fcVerdict;
115850
116437
  try {
115851
- const fcContent = fs94.readFileSync(fcPath, "utf-8");
116438
+ const fcContent = fs95.readFileSync(fcPath, "utf-8");
115852
116439
  const fcBundle = JSON.parse(fcContent);
115853
116440
  for (const entry of fcBundle.entries ?? []) {
115854
116441
  if (typeof entry.type === "string" && entry.type === "final-council" && typeof entry.verdict === "string") {
@@ -115973,8 +116560,8 @@ async function runFinalCouncilGate(ctx) {
115973
116560
  init_qa_gate_profile();
115974
116561
  init_manager();
115975
116562
  init_state();
115976
- import * as fs95 from "node:fs";
115977
- import * as path134 from "node:path";
116563
+ import * as fs96 from "node:fs";
116564
+ import * as path135 from "node:path";
115978
116565
  async function runHallucinationGate(ctx) {
115979
116566
  const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
115980
116567
  try {
@@ -115987,11 +116574,11 @@ async function runHallucinationGate(ctx) {
115987
116574
  const overrides = session?.qaGateSessionOverrides ?? {};
115988
116575
  const effective = getEffectiveGates(profile, overrides);
115989
116576
  if (effective.hallucination_guard === true) {
115990
- const hgPath = path134.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
116577
+ const hgPath = path135.join(dir, ".swarm", "evidence", String(phase), "hallucination-guard.json");
115991
116578
  let hgVerdictFound = false;
115992
116579
  let hgVerdictApproved = false;
115993
116580
  try {
115994
- const hgContent = fs95.readFileSync(hgPath, "utf-8");
116581
+ const hgContent = fs96.readFileSync(hgPath, "utf-8");
115995
116582
  const hgBundle = JSON.parse(hgContent);
115996
116583
  for (const entry of hgBundle.entries ?? []) {
115997
116584
  if (typeof entry.type === "string" && entry.type.includes("hallucination") && typeof entry.verdict === "string") {
@@ -116049,8 +116636,8 @@ async function runHallucinationGate(ctx) {
116049
116636
  init_qa_gate_profile();
116050
116637
  init_manager();
116051
116638
  init_state();
116052
- import * as fs96 from "node:fs";
116053
- import * as path135 from "node:path";
116639
+ import * as fs97 from "node:fs";
116640
+ import * as path136 from "node:path";
116054
116641
  async function runMutationGate(ctx) {
116055
116642
  const { phase, dir, sessionID, agentsDispatched, safeWarn } = ctx;
116056
116643
  try {
@@ -116063,11 +116650,11 @@ async function runMutationGate(ctx) {
116063
116650
  const overrides = session?.qaGateSessionOverrides ?? {};
116064
116651
  const effective = getEffectiveGates(profile, overrides);
116065
116652
  if (effective.mutation_test === true) {
116066
- const mgPath = path135.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
116653
+ const mgPath = path136.join(dir, ".swarm", "evidence", String(phase), "mutation-gate.json");
116067
116654
  let mgVerdictFound = false;
116068
116655
  let mgVerdict;
116069
116656
  try {
116070
- const mgContent = fs96.readFileSync(mgPath, "utf-8");
116657
+ const mgContent = fs97.readFileSync(mgPath, "utf-8");
116071
116658
  const mgBundle = JSON.parse(mgContent);
116072
116659
  for (const entry of mgBundle.entries ?? []) {
116073
116660
  if (typeof entry.type === "string" && entry.type === "mutation-gate" && typeof entry.verdict === "string") {
@@ -116125,8 +116712,8 @@ async function runMutationGate(ctx) {
116125
116712
  init_qa_gate_profile();
116126
116713
  init_manager();
116127
116714
  init_state();
116128
- import * as fs97 from "node:fs";
116129
- import * as path136 from "node:path";
116715
+ import * as fs98 from "node:fs";
116716
+ import * as path137 from "node:path";
116130
116717
  async function runPhaseCouncilGate(ctx) {
116131
116718
  const { phase, dir, sessionID, pluginConfig, agentsDispatched, safeWarn } = ctx;
116132
116719
  let councilModeEnabled = false;
@@ -116141,14 +116728,14 @@ async function runPhaseCouncilGate(ctx) {
116141
116728
  const effective = getEffectiveGates(profile, overrides);
116142
116729
  if (effective.council_mode === true) {
116143
116730
  councilModeEnabled = true;
116144
- const pcPath = path136.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
116731
+ const pcPath = path137.join(dir, ".swarm", "evidence", String(phase), "phase-council.json");
116145
116732
  let pcVerdictFound = false;
116146
116733
  let _pcVerdict;
116147
116734
  let pcQuorumSize;
116148
116735
  let pcTimestamp;
116149
116736
  let pcPhaseNumber;
116150
116737
  try {
116151
- const pcContent = fs97.readFileSync(pcPath, "utf-8");
116738
+ const pcContent = fs98.readFileSync(pcPath, "utf-8");
116152
116739
  const pcBundle = JSON.parse(pcContent);
116153
116740
  for (const entry of pcBundle.entries ?? []) {
116154
116741
  if (typeof entry.type === "string" && entry.type === "phase-council" && typeof entry.verdict === "string") {
@@ -116656,7 +117243,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
116656
117243
  }
116657
117244
  if (retroFound && retroEntry?.lessons_learned && retroEntry.lessons_learned.length > 0) {
116658
117245
  try {
116659
- const projectName = path138.basename(dir);
117246
+ const projectName = path139.basename(dir);
116660
117247
  const curationResult = await curateAndStoreSwarm(retroEntry.lessons_learned, projectName, { phase_number: phase }, dir, knowledgeConfig);
116661
117248
  if (curationResult) {
116662
117249
  const sessionState = swarmState.agentSessions.get(sessionID);
@@ -116756,14 +117343,14 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
116756
117343
  const markerPath = validateSwarmPath(dir, "skill-usage-last-processed.json");
116757
117344
  let sinceTimestamp;
116758
117345
  try {
116759
- const markerData = JSON.parse(fs99.readFileSync(markerPath, "utf-8"));
117346
+ const markerData = JSON.parse(fs100.readFileSync(markerPath, "utf-8"));
116760
117347
  sinceTimestamp = markerData.lastProcessedTimestamp;
116761
117348
  } catch {}
116762
117349
  const feedbackResult = await applySkillUsageFeedback(dir, {
116763
117350
  sinceTimestamp
116764
117351
  });
116765
117352
  try {
116766
- fs99.writeFileSync(markerPath, JSON.stringify({ lastProcessedTimestamp: new Date().toISOString() }), "utf-8");
117353
+ fs100.writeFileSync(markerPath, JSON.stringify({ lastProcessedTimestamp: new Date().toISOString() }), "utf-8");
116767
117354
  } catch {}
116768
117355
  if (feedbackResult.processed > 0) {
116769
117356
  const sessionState = swarmState.agentSessions.get(sessionID);
@@ -116783,7 +117370,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
116783
117370
  let phaseRequiredAgents;
116784
117371
  try {
116785
117372
  const planPath = validateSwarmPath(dir, "plan.json");
116786
- const planRaw = fs99.readFileSync(planPath, "utf-8");
117373
+ const planRaw = fs100.readFileSync(planPath, "utf-8");
116787
117374
  const plan = JSON.parse(planRaw);
116788
117375
  const phaseObj = plan.phases.find((p) => p.id === phase);
116789
117376
  phaseRequiredAgents = phaseObj?.required_agents;
@@ -116798,7 +117385,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
116798
117385
  if (agentsMissing.length > 0) {
116799
117386
  try {
116800
117387
  const planPath = validateSwarmPath(dir, "plan.json");
116801
- const planRaw = fs99.readFileSync(planPath, "utf-8");
117388
+ const planRaw = fs100.readFileSync(planPath, "utf-8");
116802
117389
  const plan = JSON.parse(planRaw);
116803
117390
  const targetPhase = plan.phases.find((p) => p.id === phase);
116804
117391
  if (targetPhase && targetPhase.tasks.length > 0 && canInferMissingAgentsFromTaskGates(agentsMissing) && await allCompletedTasksHavePassedGateEvidence(dir, targetPhase.tasks)) {
@@ -116838,7 +117425,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
116838
117425
  if (phaseCompleteConfig.regression_sweep?.enforce) {
116839
117426
  try {
116840
117427
  const planPath = validateSwarmPath(dir, "plan.json");
116841
- const planRaw = fs99.readFileSync(planPath, "utf-8");
117428
+ const planRaw = fs100.readFileSync(planPath, "utf-8");
116842
117429
  const plan = JSON.parse(planRaw);
116843
117430
  const targetPhase = plan.phases.find((p) => p.id === phase);
116844
117431
  if (targetPhase) {
@@ -116892,7 +117479,7 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
116892
117479
  }
116893
117480
  try {
116894
117481
  const eventsPath = validateSwarmPath(dir, "events.jsonl");
116895
- fs99.appendFileSync(eventsPath, `${JSON.stringify(event)}
117482
+ fs100.appendFileSync(eventsPath, `${JSON.stringify(event)}
116896
117483
  `, "utf-8");
116897
117484
  } catch (writeError) {
116898
117485
  warnings.push(`Warning: failed to write phase complete event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
@@ -116967,12 +117554,12 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
116967
117554
  warnings.push(`Warning: failed to update plan.json phase status`);
116968
117555
  try {
116969
117556
  const planPath = validateSwarmPath(dir, "plan.json");
116970
- const planRaw = fs99.readFileSync(planPath, "utf-8");
117557
+ const planRaw = fs100.readFileSync(planPath, "utf-8");
116971
117558
  const plan2 = JSON.parse(planRaw);
116972
117559
  const phaseObj = plan2.phases.find((p) => p.id === phase);
116973
117560
  if (phaseObj) {
116974
117561
  phaseObj.status = "complete";
116975
- fs99.writeFileSync(planPath, JSON.stringify(plan2, null, 2), "utf-8");
117562
+ fs100.writeFileSync(planPath, JSON.stringify(plan2, null, 2), "utf-8");
116976
117563
  }
116977
117564
  } catch {}
116978
117565
  } else if (plan) {
@@ -117009,12 +117596,12 @@ async function executePhaseComplete(args2, workingDirectory, directory) {
117009
117596
  warnings.push(`Warning: failed to update plan.json phase status`);
117010
117597
  try {
117011
117598
  const planPath = validateSwarmPath(dir, "plan.json");
117012
- const planRaw = fs99.readFileSync(planPath, "utf-8");
117599
+ const planRaw = fs100.readFileSync(planPath, "utf-8");
117013
117600
  const plan = JSON.parse(planRaw);
117014
117601
  const phaseObj = plan.phases.find((p) => p.id === phase);
117015
117602
  if (phaseObj) {
117016
117603
  phaseObj.status = "complete";
117017
- fs99.writeFileSync(planPath, JSON.stringify(plan, null, 2), "utf-8");
117604
+ fs100.writeFileSync(planPath, JSON.stringify(plan, null, 2), "utf-8");
117018
117605
  }
117019
117606
  } catch {}
117020
117607
  }
@@ -117098,8 +117685,8 @@ init_discovery();
117098
117685
  init_utils();
117099
117686
  init_bun_compat();
117100
117687
  init_create_tool();
117101
- import * as fs100 from "node:fs";
117102
- import * as path139 from "node:path";
117688
+ import * as fs101 from "node:fs";
117689
+ import * as path140 from "node:path";
117103
117690
  var MAX_OUTPUT_BYTES6 = 52428800;
117104
117691
  var AUDIT_TIMEOUT_MS = 120000;
117105
117692
  function isValidEcosystem(value) {
@@ -117127,31 +117714,31 @@ function validateArgs3(args2) {
117127
117714
  function detectEcosystems(directory) {
117128
117715
  const ecosystems = [];
117129
117716
  const cwd = directory;
117130
- if (fs100.existsSync(path139.join(cwd, "package.json"))) {
117717
+ if (fs101.existsSync(path140.join(cwd, "package.json"))) {
117131
117718
  ecosystems.push("npm");
117132
117719
  }
117133
- if (fs100.existsSync(path139.join(cwd, "pyproject.toml")) || fs100.existsSync(path139.join(cwd, "requirements.txt"))) {
117720
+ if (fs101.existsSync(path140.join(cwd, "pyproject.toml")) || fs101.existsSync(path140.join(cwd, "requirements.txt"))) {
117134
117721
  ecosystems.push("pip");
117135
117722
  }
117136
- if (fs100.existsSync(path139.join(cwd, "Cargo.toml"))) {
117723
+ if (fs101.existsSync(path140.join(cwd, "Cargo.toml"))) {
117137
117724
  ecosystems.push("cargo");
117138
117725
  }
117139
- if (fs100.existsSync(path139.join(cwd, "go.mod"))) {
117726
+ if (fs101.existsSync(path140.join(cwd, "go.mod"))) {
117140
117727
  ecosystems.push("go");
117141
117728
  }
117142
117729
  try {
117143
- const files = fs100.readdirSync(cwd);
117730
+ const files = fs101.readdirSync(cwd);
117144
117731
  if (files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"))) {
117145
117732
  ecosystems.push("dotnet");
117146
117733
  }
117147
117734
  } catch {}
117148
- if (fs100.existsSync(path139.join(cwd, "Gemfile")) || fs100.existsSync(path139.join(cwd, "Gemfile.lock"))) {
117735
+ if (fs101.existsSync(path140.join(cwd, "Gemfile")) || fs101.existsSync(path140.join(cwd, "Gemfile.lock"))) {
117149
117736
  ecosystems.push("ruby");
117150
117737
  }
117151
- if (fs100.existsSync(path139.join(cwd, "pubspec.yaml"))) {
117738
+ if (fs101.existsSync(path140.join(cwd, "pubspec.yaml"))) {
117152
117739
  ecosystems.push("dart");
117153
117740
  }
117154
- if (fs100.existsSync(path139.join(cwd, "composer.lock"))) {
117741
+ if (fs101.existsSync(path140.join(cwd, "composer.lock"))) {
117155
117742
  ecosystems.push("composer");
117156
117743
  }
117157
117744
  return ecosystems;
@@ -117164,7 +117751,7 @@ async function runNpmAudit(directory) {
117164
117751
  stderr: "pipe",
117165
117752
  cwd: directory
117166
117753
  });
117167
- const timeoutPromise = new Promise((resolve47) => setTimeout(() => resolve47("timeout"), AUDIT_TIMEOUT_MS));
117754
+ const timeoutPromise = new Promise((resolve48) => setTimeout(() => resolve48("timeout"), AUDIT_TIMEOUT_MS));
117168
117755
  const result = await Promise.race([
117169
117756
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr2]) => ({ stdout: stdout2, stderr: stderr2 })),
117170
117757
  timeoutPromise
@@ -117284,7 +117871,7 @@ async function runPipAudit(directory) {
117284
117871
  stderr: "pipe",
117285
117872
  cwd: directory
117286
117873
  });
117287
- const timeoutPromise = new Promise((resolve47) => setTimeout(() => resolve47("timeout"), AUDIT_TIMEOUT_MS));
117874
+ const timeoutPromise = new Promise((resolve48) => setTimeout(() => resolve48("timeout"), AUDIT_TIMEOUT_MS));
117288
117875
  const result = await Promise.race([
117289
117876
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr2]) => ({ stdout: stdout2, stderr: stderr2 })),
117290
117877
  timeoutPromise
@@ -117412,7 +117999,7 @@ async function runCargoAudit(directory) {
117412
117999
  stderr: "pipe",
117413
118000
  cwd: directory
117414
118001
  });
117415
- const timeoutPromise = new Promise((resolve47) => setTimeout(() => resolve47("timeout"), AUDIT_TIMEOUT_MS));
118002
+ const timeoutPromise = new Promise((resolve48) => setTimeout(() => resolve48("timeout"), AUDIT_TIMEOUT_MS));
117416
118003
  const result = await Promise.race([
117417
118004
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
117418
118005
  timeoutPromise
@@ -117536,7 +118123,7 @@ async function runGoAudit(directory) {
117536
118123
  stderr: "pipe",
117537
118124
  cwd: directory
117538
118125
  });
117539
- const timeoutPromise = new Promise((resolve47) => setTimeout(() => resolve47("timeout"), AUDIT_TIMEOUT_MS));
118126
+ const timeoutPromise = new Promise((resolve48) => setTimeout(() => resolve48("timeout"), AUDIT_TIMEOUT_MS));
117540
118127
  const result = await Promise.race([
117541
118128
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
117542
118129
  timeoutPromise
@@ -117669,7 +118256,7 @@ async function runDotnetAudit(directory) {
117669
118256
  stderr: "pipe",
117670
118257
  cwd: directory
117671
118258
  });
117672
- const timeoutPromise = new Promise((resolve47) => setTimeout(() => resolve47("timeout"), AUDIT_TIMEOUT_MS));
118259
+ const timeoutPromise = new Promise((resolve48) => setTimeout(() => resolve48("timeout"), AUDIT_TIMEOUT_MS));
117673
118260
  const result = await Promise.race([
117674
118261
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
117675
118262
  timeoutPromise
@@ -117785,7 +118372,7 @@ async function runBundleAudit(directory) {
117785
118372
  stderr: "pipe",
117786
118373
  cwd: directory
117787
118374
  });
117788
- const timeoutPromise = new Promise((resolve47) => setTimeout(() => resolve47("timeout"), AUDIT_TIMEOUT_MS));
118375
+ const timeoutPromise = new Promise((resolve48) => setTimeout(() => resolve48("timeout"), AUDIT_TIMEOUT_MS));
117789
118376
  const result = await Promise.race([
117790
118377
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
117791
118378
  timeoutPromise
@@ -117930,7 +118517,7 @@ async function runDartAudit(directory) {
117930
118517
  stderr: "pipe",
117931
118518
  cwd: directory
117932
118519
  });
117933
- const timeoutPromise = new Promise((resolve47) => setTimeout(() => resolve47("timeout"), AUDIT_TIMEOUT_MS));
118520
+ const timeoutPromise = new Promise((resolve48) => setTimeout(() => resolve48("timeout"), AUDIT_TIMEOUT_MS));
117934
118521
  const result = await Promise.race([
117935
118522
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
117936
118523
  timeoutPromise
@@ -118045,7 +118632,7 @@ async function runComposerAudit(directory) {
118045
118632
  stderr: "pipe",
118046
118633
  cwd: directory
118047
118634
  });
118048
- const timeoutPromise = new Promise((resolve47) => setTimeout(() => resolve47("timeout"), AUDIT_TIMEOUT_MS));
118635
+ const timeoutPromise = new Promise((resolve48) => setTimeout(() => resolve48("timeout"), AUDIT_TIMEOUT_MS));
118049
118636
  const result = await Promise.race([
118050
118637
  Promise.all([proc.stdout.text(), proc.stderr.text()]).then(([stdout2, stderr]) => ({ stdout: stdout2, stderr })),
118051
118638
  timeoutPromise
@@ -118287,8 +118874,8 @@ var pkg_audit = createSwarmTool({
118287
118874
  // src/tools/placeholder-scan.ts
118288
118875
  init_zod();
118289
118876
  init_manager2();
118290
- import * as fs101 from "node:fs";
118291
- import * as path140 from "node:path";
118877
+ import * as fs102 from "node:fs";
118878
+ import * as path141 from "node:path";
118292
118879
  init_utils();
118293
118880
  init_create_tool();
118294
118881
  var MAX_FILE_SIZE = 1024 * 1024;
@@ -118411,7 +118998,7 @@ function isScaffoldFile(filePath) {
118411
118998
  if (SCAFFOLD_PATH_PATTERNS.some((pattern) => pattern.test(normalizedPath))) {
118412
118999
  return true;
118413
119000
  }
118414
- const filename = path140.basename(filePath);
119001
+ const filename = path141.basename(filePath);
118415
119002
  if (SCAFFOLD_FILENAME_PATTERNS.some((pattern) => pattern.test(filename))) {
118416
119003
  return true;
118417
119004
  }
@@ -118428,7 +119015,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
118428
119015
  if (regex.test(normalizedPath)) {
118429
119016
  return true;
118430
119017
  }
118431
- const filename = path140.basename(filePath);
119018
+ const filename = path141.basename(filePath);
118432
119019
  const filenameRegex = new RegExp(`^${regexPattern}$`, "i");
118433
119020
  if (filenameRegex.test(filename)) {
118434
119021
  return true;
@@ -118437,7 +119024,7 @@ function isAllowedByGlobs(filePath, allowGlobs) {
118437
119024
  return false;
118438
119025
  }
118439
119026
  function isParserSupported(filePath) {
118440
- const ext = path140.extname(filePath).toLowerCase();
119027
+ const ext = path141.extname(filePath).toLowerCase();
118441
119028
  return SUPPORTED_PARSER_EXTENSIONS.has(ext);
118442
119029
  }
118443
119030
  function isPlanFile(filePath) {
@@ -118684,28 +119271,28 @@ async function placeholderScan(input, directory) {
118684
119271
  let filesScanned = 0;
118685
119272
  const filesWithFindings = new Set;
118686
119273
  for (const filePath of changed_files) {
118687
- const fullPath = path140.isAbsolute(filePath) ? filePath : path140.resolve(directory, filePath);
118688
- const resolvedDirectory = path140.resolve(directory);
118689
- if (!fullPath.startsWith(resolvedDirectory + path140.sep) && fullPath !== resolvedDirectory) {
119274
+ const fullPath = path141.isAbsolute(filePath) ? filePath : path141.resolve(directory, filePath);
119275
+ const resolvedDirectory = path141.resolve(directory);
119276
+ if (!fullPath.startsWith(resolvedDirectory + path141.sep) && fullPath !== resolvedDirectory) {
118690
119277
  continue;
118691
119278
  }
118692
- if (!fs101.existsSync(fullPath)) {
119279
+ if (!fs102.existsSync(fullPath)) {
118693
119280
  continue;
118694
119281
  }
118695
119282
  if (isAllowedByGlobs(filePath, allow_globs)) {
118696
119283
  continue;
118697
119284
  }
118698
- const relativeFilePath = path140.relative(directory, fullPath).replace(/\\/g, "/");
119285
+ const relativeFilePath = path141.relative(directory, fullPath).replace(/\\/g, "/");
118699
119286
  if (FILE_ALLOWLIST.some((allowed) => relativeFilePath.endsWith(allowed))) {
118700
119287
  continue;
118701
119288
  }
118702
119289
  let content;
118703
119290
  try {
118704
- const stat9 = fs101.statSync(fullPath);
119291
+ const stat9 = fs102.statSync(fullPath);
118705
119292
  if (stat9.size > MAX_FILE_SIZE) {
118706
119293
  continue;
118707
119294
  }
118708
- content = fs101.readFileSync(fullPath, "utf-8");
119295
+ content = fs102.readFileSync(fullPath, "utf-8");
118709
119296
  } catch {
118710
119297
  continue;
118711
119298
  }
@@ -118767,8 +119354,8 @@ var placeholder_scan = createSwarmTool({
118767
119354
  });
118768
119355
 
118769
119356
  // src/tools/pre-check-batch.ts
118770
- import * as fs105 from "node:fs";
118771
- import * as path144 from "node:path";
119357
+ import * as fs106 from "node:fs";
119358
+ import * as path145 from "node:path";
118772
119359
  init_zod();
118773
119360
  init_manager2();
118774
119361
  init_utils();
@@ -118908,9 +119495,9 @@ var _internals61 = {
118908
119495
  init_zod();
118909
119496
  init_manager2();
118910
119497
  init_detector();
118911
- import * as fs104 from "node:fs";
118912
- import * as path143 from "node:path";
118913
- import { extname as extname20 } from "node:path";
119498
+ import * as fs105 from "node:fs";
119499
+ import * as path144 from "node:path";
119500
+ import { extname as extname21 } from "node:path";
118914
119501
 
118915
119502
  // src/sast/rules/c.ts
118916
119503
  var cRules = [
@@ -119623,9 +120210,9 @@ function executeRulesSync(filePath, content, language) {
119623
120210
  }
119624
120211
 
119625
120212
  // src/sast/semgrep.ts
119626
- import * as child_process9 from "node:child_process";
119627
- import * as fs102 from "node:fs";
119628
- import * as path141 from "node:path";
120213
+ import * as child_process10 from "node:child_process";
120214
+ import * as fs103 from "node:fs";
120215
+ import * as path142 from "node:path";
119629
120216
  var semgrepAvailableCache = null;
119630
120217
  var DEFAULT_RULES_DIR = ".swarm/semgrep-rules";
119631
120218
  var DEFAULT_TIMEOUT_MS3 = 30000;
@@ -119642,7 +120229,7 @@ function isSemgrepAvailable() {
119642
120229
  return semgrepAvailableCache;
119643
120230
  }
119644
120231
  try {
119645
- child_process9.execFileSync("semgrep", ["--version"], {
120232
+ child_process10.execFileSync("semgrep", ["--version"], {
119646
120233
  encoding: "utf-8",
119647
120234
  stdio: "pipe"
119648
120235
  });
@@ -119706,8 +120293,8 @@ function mapSemgrepSeverity(severity) {
119706
120293
  }
119707
120294
  }
119708
120295
  async function executeWithTimeout(command, args2, options) {
119709
- return new Promise((resolve49) => {
119710
- const child = child_process9.spawn(command, args2, {
120296
+ return new Promise((resolve50) => {
120297
+ const child = child_process10.spawn(command, args2, {
119711
120298
  shell: false,
119712
120299
  cwd: options.cwd
119713
120300
  });
@@ -119715,7 +120302,7 @@ async function executeWithTimeout(command, args2, options) {
119715
120302
  let stderr = "";
119716
120303
  const timeout = setTimeout(() => {
119717
120304
  child.kill("SIGTERM");
119718
- resolve49({
120305
+ resolve50({
119719
120306
  stdout,
119720
120307
  stderr: "Process timed out",
119721
120308
  exitCode: 124
@@ -119729,7 +120316,7 @@ async function executeWithTimeout(command, args2, options) {
119729
120316
  });
119730
120317
  child.on("close", (code) => {
119731
120318
  clearTimeout(timeout);
119732
- resolve49({
120319
+ resolve50({
119733
120320
  stdout,
119734
120321
  stderr,
119735
120322
  exitCode: code ?? 0
@@ -119737,7 +120324,7 @@ async function executeWithTimeout(command, args2, options) {
119737
120324
  });
119738
120325
  child.on("error", (err2) => {
119739
120326
  clearTimeout(timeout);
119740
- resolve49({
120327
+ resolve50({
119741
120328
  stdout,
119742
120329
  stderr: err2.message,
119743
120330
  exitCode: 1
@@ -119812,14 +120399,14 @@ async function runSemgrep(options) {
119812
120399
  }
119813
120400
  function getRulesDirectory(projectRoot) {
119814
120401
  if (projectRoot) {
119815
- return path141.resolve(projectRoot, DEFAULT_RULES_DIR);
120402
+ return path142.resolve(projectRoot, DEFAULT_RULES_DIR);
119816
120403
  }
119817
120404
  return DEFAULT_RULES_DIR;
119818
120405
  }
119819
120406
  function hasBundledRules(projectRoot) {
119820
120407
  const rulesDir = getRulesDirectory(projectRoot);
119821
120408
  try {
119822
- return fs102.existsSync(rulesDir);
120409
+ return fs103.existsSync(rulesDir);
119823
120410
  } catch {
119824
120411
  return false;
119825
120412
  }
@@ -119832,25 +120419,25 @@ init_create_tool();
119832
120419
  // src/tools/sast-baseline.ts
119833
120420
  init_utils2();
119834
120421
  import * as crypto11 from "node:crypto";
119835
- import * as fs103 from "node:fs";
119836
- import * as path142 from "node:path";
120422
+ import * as fs104 from "node:fs";
120423
+ import * as path143 from "node:path";
119837
120424
  var BASELINE_SCHEMA_VERSION = "1.0.0";
119838
120425
  var MAX_BASELINE_FINDINGS = 2000;
119839
120426
  var MAX_BASELINE_BYTES = 2 * 1048576;
119840
120427
  var LOCK_RETRY_DELAYS_MS = [50, 100, 200, 400, 800];
119841
120428
  function normalizeFindingPath(directory, file3) {
119842
- const resolved = path142.isAbsolute(file3) ? file3 : path142.resolve(directory, file3);
119843
- const rel = path142.relative(path142.resolve(directory), resolved);
120429
+ const resolved = path143.isAbsolute(file3) ? file3 : path143.resolve(directory, file3);
120430
+ const rel = path143.relative(path143.resolve(directory), resolved);
119844
120431
  return rel.replace(/\\/g, "/");
119845
120432
  }
119846
120433
  function baselineRelPath(phase) {
119847
- return path142.join("evidence", String(phase), "sast-baseline.json");
120434
+ return path143.join("evidence", String(phase), "sast-baseline.json");
119848
120435
  }
119849
120436
  function tempRelPath(phase) {
119850
- return path142.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
120437
+ return path143.join("evidence", String(phase), `sast-baseline.json.tmp.${Date.now()}.${process.pid}`);
119851
120438
  }
119852
120439
  function lockRelPath(phase) {
119853
- return path142.join("evidence", String(phase), "sast-baseline.json.lock");
120440
+ return path143.join("evidence", String(phase), "sast-baseline.json.lock");
119854
120441
  }
119855
120442
  function getLine(lines, idx) {
119856
120443
  if (idx < 0 || idx >= lines.length)
@@ -119867,7 +120454,7 @@ function fingerprintFinding(finding, directory, occurrenceIndex) {
119867
120454
  }
119868
120455
  const lineNum = finding.location.line;
119869
120456
  try {
119870
- const content = fs103.readFileSync(finding.location.file, "utf-8");
120457
+ const content = fs104.readFileSync(finding.location.file, "utf-8");
119871
120458
  const lines = content.split(`
119872
120459
  `);
119873
120460
  const idx = lineNum - 1;
@@ -119898,7 +120485,7 @@ function assignOccurrenceIndices(findings, directory) {
119898
120485
  try {
119899
120486
  if (relFile.startsWith(".."))
119900
120487
  throw new Error("escapes workspace");
119901
- const content = fs103.readFileSync(finding.location.file, "utf-8");
120488
+ const content = fs104.readFileSync(finding.location.file, "utf-8");
119902
120489
  const lines = content.split(`
119903
120490
  `);
119904
120491
  const idx = lineNum - 1;
@@ -119927,16 +120514,16 @@ function assignOccurrenceIndices(findings, directory) {
119927
120514
  async function acquireLock2(lockPath) {
119928
120515
  for (let attempt = 0;attempt <= LOCK_RETRY_DELAYS_MS.length; attempt++) {
119929
120516
  try {
119930
- const fd = fs103.openSync(lockPath, "wx");
119931
- fs103.closeSync(fd);
120517
+ const fd = fs104.openSync(lockPath, "wx");
120518
+ fs104.closeSync(fd);
119932
120519
  return () => {
119933
120520
  try {
119934
- fs103.unlinkSync(lockPath);
120521
+ fs104.unlinkSync(lockPath);
119935
120522
  } catch {}
119936
120523
  };
119937
120524
  } catch {
119938
120525
  if (attempt < LOCK_RETRY_DELAYS_MS.length) {
119939
- await new Promise((resolve50) => setTimeout(resolve50, LOCK_RETRY_DELAYS_MS[attempt]));
120526
+ await new Promise((resolve51) => setTimeout(resolve51, LOCK_RETRY_DELAYS_MS[attempt]));
119940
120527
  }
119941
120528
  }
119942
120529
  }
@@ -119971,13 +120558,13 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
119971
120558
  message: e instanceof Error ? e.message : "Path validation failed"
119972
120559
  };
119973
120560
  }
119974
- fs103.mkdirSync(path142.dirname(baselinePath), { recursive: true });
119975
- fs103.mkdirSync(path142.dirname(tempPath), { recursive: true });
120561
+ fs104.mkdirSync(path143.dirname(baselinePath), { recursive: true });
120562
+ fs104.mkdirSync(path143.dirname(tempPath), { recursive: true });
119976
120563
  const releaseLock = await acquireLock2(lockPath);
119977
120564
  try {
119978
120565
  let existing = null;
119979
120566
  try {
119980
- const raw = fs103.readFileSync(baselinePath, "utf-8");
120567
+ const raw = fs104.readFileSync(baselinePath, "utf-8");
119981
120568
  const parsed = JSON.parse(raw);
119982
120569
  if (parsed.schema_version === BASELINE_SCHEMA_VERSION) {
119983
120570
  existing = parsed;
@@ -120037,8 +120624,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
120037
120624
  message: `Baseline would exceed size cap (${json4.length} bytes > ${MAX_BASELINE_BYTES})`
120038
120625
  };
120039
120626
  }
120040
- fs103.writeFileSync(tempPath, json4, "utf-8");
120041
- fs103.renameSync(tempPath, baselinePath);
120627
+ fs104.writeFileSync(tempPath, json4, "utf-8");
120628
+ fs104.renameSync(tempPath, baselinePath);
120042
120629
  return {
120043
120630
  status: "merged",
120044
120631
  path: baselinePath,
@@ -120069,8 +120656,8 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
120069
120656
  message: `Baseline would exceed size cap (${json3.length} bytes > ${MAX_BASELINE_BYTES})`
120070
120657
  };
120071
120658
  }
120072
- fs103.writeFileSync(tempPath, json3, "utf-8");
120073
- fs103.renameSync(tempPath, baselinePath);
120659
+ fs104.writeFileSync(tempPath, json3, "utf-8");
120660
+ fs104.renameSync(tempPath, baselinePath);
120074
120661
  return {
120075
120662
  status: "written",
120076
120663
  path: baselinePath,
@@ -120095,7 +120682,7 @@ function loadBaseline(directory, phase) {
120095
120682
  };
120096
120683
  }
120097
120684
  try {
120098
- const raw = fs103.readFileSync(baselinePath, "utf-8");
120685
+ const raw = fs104.readFileSync(baselinePath, "utf-8");
120099
120686
  const parsed = JSON.parse(raw);
120100
120687
  if (parsed.schema_version !== BASELINE_SCHEMA_VERSION) {
120101
120688
  return {
@@ -120143,17 +120730,17 @@ var SEVERITY_ORDER = {
120143
120730
  };
120144
120731
  function shouldSkipFile(filePath) {
120145
120732
  try {
120146
- const stats = fs104.statSync(filePath);
120733
+ const stats = fs105.statSync(filePath);
120147
120734
  if (stats.size > MAX_FILE_SIZE_BYTES8) {
120148
120735
  return { skip: true, reason: "file too large" };
120149
120736
  }
120150
120737
  if (stats.size === 0) {
120151
120738
  return { skip: true, reason: "empty file" };
120152
120739
  }
120153
- const fd = fs104.openSync(filePath, "r");
120740
+ const fd = fs105.openSync(filePath, "r");
120154
120741
  const buffer = Buffer.alloc(8192);
120155
- const bytesRead = fs104.readSync(fd, buffer, 0, 8192, 0);
120156
- fs104.closeSync(fd);
120742
+ const bytesRead = fs105.readSync(fd, buffer, 0, 8192, 0);
120743
+ fs105.closeSync(fd);
120157
120744
  if (bytesRead > 0) {
120158
120745
  let nullCount = 0;
120159
120746
  for (let i2 = 0;i2 < bytesRead; i2++) {
@@ -120192,7 +120779,7 @@ function countBySeverity(findings) {
120192
120779
  }
120193
120780
  function scanFileWithTierA(filePath, language) {
120194
120781
  try {
120195
- const content = fs104.readFileSync(filePath, "utf-8");
120782
+ const content = fs105.readFileSync(filePath, "utf-8");
120196
120783
  const findings = executeRulesSync(filePath, content, language);
120197
120784
  return findings.map((f) => ({
120198
120785
  rule_id: f.rule_id,
@@ -120245,13 +120832,13 @@ async function sastScan(input, directory, config3) {
120245
120832
  _filesSkipped++;
120246
120833
  continue;
120247
120834
  }
120248
- const resolvedPath = path143.isAbsolute(filePath) ? filePath : path143.resolve(directory, filePath);
120249
- const resolvedDirectory = path143.resolve(directory);
120250
- if (!resolvedPath.startsWith(resolvedDirectory + path143.sep) && resolvedPath !== resolvedDirectory) {
120835
+ const resolvedPath = path144.isAbsolute(filePath) ? filePath : path144.resolve(directory, filePath);
120836
+ const resolvedDirectory = path144.resolve(directory);
120837
+ if (!resolvedPath.startsWith(resolvedDirectory + path144.sep) && resolvedPath !== resolvedDirectory) {
120251
120838
  _filesSkipped++;
120252
120839
  continue;
120253
120840
  }
120254
- if (!fs104.existsSync(resolvedPath)) {
120841
+ if (!fs105.existsSync(resolvedPath)) {
120255
120842
  _filesSkipped++;
120256
120843
  continue;
120257
120844
  }
@@ -120260,7 +120847,7 @@ async function sastScan(input, directory, config3) {
120260
120847
  _filesSkipped++;
120261
120848
  continue;
120262
120849
  }
120263
- const ext = extname20(resolvedPath).toLowerCase();
120850
+ const ext = extname21(resolvedPath).toLowerCase();
120264
120851
  const profile = getProfileForFile(resolvedPath);
120265
120852
  const langDef = getLanguageForExtension(ext);
120266
120853
  if (!profile && !langDef) {
@@ -120562,20 +121149,20 @@ function validatePath(inputPath, baseDir, workspaceDir) {
120562
121149
  let resolved;
120563
121150
  const isWinAbs = isWindowsAbsolutePath(inputPath);
120564
121151
  if (isWinAbs) {
120565
- resolved = path144.win32.resolve(inputPath);
120566
- } else if (path144.isAbsolute(inputPath)) {
120567
- resolved = path144.resolve(inputPath);
121152
+ resolved = path145.win32.resolve(inputPath);
121153
+ } else if (path145.isAbsolute(inputPath)) {
121154
+ resolved = path145.resolve(inputPath);
120568
121155
  } else {
120569
- resolved = path144.resolve(baseDir, inputPath);
121156
+ resolved = path145.resolve(baseDir, inputPath);
120570
121157
  }
120571
- const workspaceResolved = path144.resolve(workspaceDir);
120572
- let relative28;
121158
+ const workspaceResolved = path145.resolve(workspaceDir);
121159
+ let relative29;
120573
121160
  if (isWinAbs) {
120574
- relative28 = path144.win32.relative(workspaceResolved, resolved);
121161
+ relative29 = path145.win32.relative(workspaceResolved, resolved);
120575
121162
  } else {
120576
- relative28 = path144.relative(workspaceResolved, resolved);
121163
+ relative29 = path145.relative(workspaceResolved, resolved);
120577
121164
  }
120578
- if (relative28.startsWith("..")) {
121165
+ if (relative29.startsWith("..")) {
120579
121166
  return "path traversal detected";
120580
121167
  }
120581
121168
  return null;
@@ -120638,7 +121225,7 @@ async function runLintOnFiles(linter, files, workspaceDir) {
120638
121225
  if (typeof file3 !== "string") {
120639
121226
  continue;
120640
121227
  }
120641
- const resolvedPath = path144.resolve(file3);
121228
+ const resolvedPath = path145.resolve(file3);
120642
121229
  const validationError = validatePath(resolvedPath, workspaceDir, workspaceDir);
120643
121230
  if (validationError) {
120644
121231
  continue;
@@ -120795,7 +121382,7 @@ async function runSecretscanWithFiles(files, directory) {
120795
121382
  skippedFiles++;
120796
121383
  continue;
120797
121384
  }
120798
- const resolvedPath = path144.resolve(file3);
121385
+ const resolvedPath = path145.resolve(file3);
120799
121386
  const validationError = validatePath(resolvedPath, directory, directory);
120800
121387
  if (validationError) {
120801
121388
  skippedFiles++;
@@ -120813,14 +121400,14 @@ async function runSecretscanWithFiles(files, directory) {
120813
121400
  };
120814
121401
  }
120815
121402
  for (const file3 of validatedFiles) {
120816
- const ext = path144.extname(file3).toLowerCase();
121403
+ const ext = path145.extname(file3).toLowerCase();
120817
121404
  if (DEFAULT_EXCLUDE_EXTENSIONS2.has(ext)) {
120818
121405
  skippedFiles++;
120819
121406
  continue;
120820
121407
  }
120821
121408
  let stat9;
120822
121409
  try {
120823
- stat9 = fs105.statSync(file3);
121410
+ stat9 = fs106.statSync(file3);
120824
121411
  } catch {
120825
121412
  skippedFiles++;
120826
121413
  continue;
@@ -120831,7 +121418,7 @@ async function runSecretscanWithFiles(files, directory) {
120831
121418
  }
120832
121419
  let content;
120833
121420
  try {
120834
- const buffer = fs105.readFileSync(file3);
121421
+ const buffer = fs106.readFileSync(file3);
120835
121422
  if (buffer.includes(0)) {
120836
121423
  skippedFiles++;
120837
121424
  continue;
@@ -121032,7 +121619,7 @@ function classifySastFindings(findings, changedLineRanges, directory) {
121032
121619
  const preexistingFindings = [];
121033
121620
  for (const finding of findings) {
121034
121621
  const filePath = finding.location.file;
121035
- const normalised = path144.relative(directory, filePath).replace(/\\/g, "/");
121622
+ const normalised = path145.relative(directory, filePath).replace(/\\/g, "/");
121036
121623
  const changedLines = changedLineRanges.get(normalised);
121037
121624
  if (changedLines?.has(finding.location.line)) {
121038
121625
  newFindings.push(finding);
@@ -121083,7 +121670,7 @@ async function runPreCheckBatch(input, workspaceDir, contextDir) {
121083
121670
  warn(`pre_check_batch: Invalid file path: ${file3}`);
121084
121671
  continue;
121085
121672
  }
121086
- changedFiles.push(path144.resolve(directory, file3));
121673
+ changedFiles.push(path145.resolve(directory, file3));
121087
121674
  }
121088
121675
  if (changedFiles.length === 0) {
121089
121676
  warn("pre_check_batch: No valid files after validation, skipping all tools (fail-closed)");
@@ -121284,9 +121871,9 @@ var pre_check_batch = createSwarmTool({
121284
121871
  };
121285
121872
  return JSON.stringify(errorResult, null, 2);
121286
121873
  }
121287
- const resolvedDirectory = path144.resolve(typedArgs.directory);
121288
- const workspaceAnchor = path144.resolve(directory);
121289
- if (resolvedDirectory !== workspaceAnchor && resolvedDirectory.startsWith(workspaceAnchor + path144.sep)) {
121874
+ const resolvedDirectory = path145.resolve(typedArgs.directory);
121875
+ const workspaceAnchor = path145.resolve(directory);
121876
+ if (resolvedDirectory !== workspaceAnchor && resolvedDirectory.startsWith(workspaceAnchor + path145.sep)) {
121290
121877
  const subDirError = `directory "${typedArgs.directory}" is a subdirectory of the project root — pre_check_batch requires the project root directory "${workspaceAnchor}"`;
121291
121878
  const subDirResult = {
121292
121879
  gates_passed: false,
@@ -121338,7 +121925,7 @@ var pre_check_batch = createSwarmTool({
121338
121925
 
121339
121926
  // src/tools/repo-map.ts
121340
121927
  init_zod();
121341
- import * as path145 from "node:path";
121928
+ import * as path146 from "node:path";
121342
121929
  init_path_security();
121343
121930
  init_create_tool();
121344
121931
  var VALID_ACTIONS = [
@@ -121363,7 +121950,7 @@ function validateFile(p) {
121363
121950
  return "file contains control characters";
121364
121951
  if (containsPathTraversal(p))
121365
121952
  return "file contains path traversal";
121366
- if (path145.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
121953
+ if (path146.isAbsolute(p) || /^[a-zA-Z]:[\\/]/.test(p)) {
121367
121954
  return "file must be a workspace-relative path, not absolute";
121368
121955
  }
121369
121956
  return null;
@@ -121386,8 +121973,8 @@ function ok(action, payload) {
121386
121973
  }
121387
121974
  function toRelativeGraphPath(input, workspaceRoot) {
121388
121975
  const normalized = input.replace(/\\/g, "/");
121389
- if (path145.isAbsolute(normalized)) {
121390
- const rel = path145.relative(workspaceRoot, normalized).replace(/\\/g, "/");
121976
+ if (path146.isAbsolute(normalized)) {
121977
+ const rel = path146.relative(workspaceRoot, normalized).replace(/\\/g, "/");
121391
121978
  return normalizeGraphPath2(rel);
121392
121979
  }
121393
121980
  return normalizeGraphPath2(normalized);
@@ -121532,8 +122119,8 @@ var repo_map = createSwarmTool({
121532
122119
  // src/tools/req-coverage.ts
121533
122120
  init_zod();
121534
122121
  init_create_tool();
121535
- import * as fs106 from "node:fs";
121536
- import * as path146 from "node:path";
122122
+ import * as fs107 from "node:fs";
122123
+ import * as path147 from "node:path";
121537
122124
  var SPEC_FILE = ".swarm/spec.md";
121538
122125
  var EVIDENCE_DIR4 = ".swarm/evidence";
121539
122126
  var OBLIGATION_KEYWORDS2 = ["MUST", "SHOULD", "SHALL"];
@@ -121592,19 +122179,19 @@ function extractObligationAndText(id, lineText) {
121592
122179
  var PHASE_TASK_ID_REGEX = /^\d+\.\d+(\.\d+)*$/;
121593
122180
  function readTouchedFiles(evidenceDir, phase, cwd) {
121594
122181
  const touchedFiles = new Set;
121595
- if (!fs106.existsSync(evidenceDir) || !fs106.statSync(evidenceDir).isDirectory()) {
122182
+ if (!fs107.existsSync(evidenceDir) || !fs107.statSync(evidenceDir).isDirectory()) {
121596
122183
  return [];
121597
122184
  }
121598
122185
  let entries;
121599
122186
  try {
121600
- entries = fs106.readdirSync(evidenceDir);
122187
+ entries = fs107.readdirSync(evidenceDir);
121601
122188
  } catch {
121602
122189
  return [];
121603
122190
  }
121604
122191
  for (const entry of entries) {
121605
- const entryPath = path146.join(evidenceDir, entry);
122192
+ const entryPath = path147.join(evidenceDir, entry);
121606
122193
  try {
121607
- const stat9 = fs106.statSync(entryPath);
122194
+ const stat9 = fs107.statSync(entryPath);
121608
122195
  if (!stat9.isDirectory()) {
121609
122196
  continue;
121610
122197
  }
@@ -121618,14 +122205,14 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
121618
122205
  if (entryPhase !== String(phase)) {
121619
122206
  continue;
121620
122207
  }
121621
- const evidenceFilePath = path146.join(entryPath, "evidence.json");
122208
+ const evidenceFilePath = path147.join(entryPath, "evidence.json");
121622
122209
  try {
121623
- const resolvedPath = path146.resolve(evidenceFilePath);
121624
- const evidenceDirResolved = path146.resolve(evidenceDir);
121625
- if (!resolvedPath.startsWith(evidenceDirResolved + path146.sep)) {
122210
+ const resolvedPath = path147.resolve(evidenceFilePath);
122211
+ const evidenceDirResolved = path147.resolve(evidenceDir);
122212
+ if (!resolvedPath.startsWith(evidenceDirResolved + path147.sep)) {
121626
122213
  continue;
121627
122214
  }
121628
- const stat9 = fs106.lstatSync(evidenceFilePath);
122215
+ const stat9 = fs107.lstatSync(evidenceFilePath);
121629
122216
  if (!stat9.isFile()) {
121630
122217
  continue;
121631
122218
  }
@@ -121637,7 +122224,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
121637
122224
  }
121638
122225
  let content;
121639
122226
  try {
121640
- content = fs106.readFileSync(evidenceFilePath, "utf-8");
122227
+ content = fs107.readFileSync(evidenceFilePath, "utf-8");
121641
122228
  } catch {
121642
122229
  continue;
121643
122230
  }
@@ -121656,7 +122243,7 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
121656
122243
  if (Array.isArray(diffEntry.files_changed)) {
121657
122244
  for (const file3 of diffEntry.files_changed) {
121658
122245
  if (typeof file3 === "string") {
121659
- touchedFiles.add(path146.resolve(cwd, file3));
122246
+ touchedFiles.add(path147.resolve(cwd, file3));
121660
122247
  }
121661
122248
  }
121662
122249
  }
@@ -121669,12 +122256,12 @@ function readTouchedFiles(evidenceDir, phase, cwd) {
121669
122256
  }
121670
122257
  function searchFileForKeywords(filePath, keywords, cwd) {
121671
122258
  try {
121672
- const resolvedPath = path146.resolve(filePath);
121673
- const cwdResolved = path146.resolve(cwd);
122259
+ const resolvedPath = path147.resolve(filePath);
122260
+ const cwdResolved = path147.resolve(cwd);
121674
122261
  if (!resolvedPath.startsWith(cwdResolved)) {
121675
122262
  return false;
121676
122263
  }
121677
- const content = fs106.readFileSync(resolvedPath, "utf-8");
122264
+ const content = fs107.readFileSync(resolvedPath, "utf-8");
121678
122265
  for (const keyword of keywords) {
121679
122266
  const regex = new RegExp(`\\b${keyword}\\b`, "i");
121680
122267
  if (regex.test(content)) {
@@ -121804,10 +122391,10 @@ var req_coverage = createSwarmTool({
121804
122391
  }, null, 2);
121805
122392
  }
121806
122393
  const cwd = inputDirectory || directory;
121807
- const specPath = path146.join(cwd, SPEC_FILE);
122394
+ const specPath = path147.join(cwd, SPEC_FILE);
121808
122395
  let specContent;
121809
122396
  try {
121810
- specContent = fs106.readFileSync(specPath, "utf-8");
122397
+ specContent = fs107.readFileSync(specPath, "utf-8");
121811
122398
  } catch (readError) {
121812
122399
  return JSON.stringify({
121813
122400
  success: false,
@@ -121831,7 +122418,7 @@ var req_coverage = createSwarmTool({
121831
122418
  message: "No FR requirements found in spec.md"
121832
122419
  }, null, 2);
121833
122420
  }
121834
- const evidenceDir = path146.join(cwd, EVIDENCE_DIR4);
122421
+ const evidenceDir = path147.join(cwd, EVIDENCE_DIR4);
121835
122422
  const touchedFiles = readTouchedFiles(evidenceDir, phase, cwd);
121836
122423
  const analyzedRequirements = [];
121837
122424
  let coveredCount = 0;
@@ -121857,12 +122444,12 @@ var req_coverage = createSwarmTool({
121857
122444
  requirements: analyzedRequirements
121858
122445
  };
121859
122446
  const reportFilename = `req-coverage-phase-${phase}.json`;
121860
- const reportPath = path146.join(evidenceDir, reportFilename);
122447
+ const reportPath = path147.join(evidenceDir, reportFilename);
121861
122448
  try {
121862
- if (!fs106.existsSync(evidenceDir)) {
121863
- fs106.mkdirSync(evidenceDir, { recursive: true });
122449
+ if (!fs107.existsSync(evidenceDir)) {
122450
+ fs107.mkdirSync(evidenceDir, { recursive: true });
121864
122451
  }
121865
- fs106.writeFileSync(reportPath, JSON.stringify(result, null, 2), "utf-8");
122452
+ fs107.writeFileSync(reportPath, JSON.stringify(result, null, 2), "utf-8");
121866
122453
  } catch (writeError) {
121867
122454
  console.warn(`Failed to write coverage report: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
121868
122455
  }
@@ -121946,8 +122533,8 @@ init_plan_schema();
121946
122533
  init_qa_gate_profile();
121947
122534
  init_file_locks();
121948
122535
  import * as crypto12 from "node:crypto";
121949
- import * as fs107 from "node:fs";
121950
- import * as path147 from "node:path";
122536
+ import * as fs108 from "node:fs";
122537
+ import * as path148 from "node:path";
121951
122538
  init_ledger();
121952
122539
  init_manager();
121953
122540
  init_state();
@@ -122028,17 +122615,17 @@ async function executeSavePlan(args2, fallbackDir) {
122028
122615
  };
122029
122616
  }
122030
122617
  if (args2.working_directory && fallbackDir) {
122031
- const resolvedTarget = path147.resolve(args2.working_directory);
122032
- const resolvedRoot = path147.resolve(fallbackDir);
122618
+ const resolvedTarget = path148.resolve(args2.working_directory);
122619
+ const resolvedRoot = path148.resolve(fallbackDir);
122033
122620
  let fallbackExists = false;
122034
122621
  try {
122035
- fs107.accessSync(resolvedRoot, fs107.constants.F_OK);
122622
+ fs108.accessSync(resolvedRoot, fs108.constants.F_OK);
122036
122623
  fallbackExists = true;
122037
122624
  } catch {
122038
122625
  fallbackExists = false;
122039
122626
  }
122040
122627
  if (fallbackExists) {
122041
- const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path147.sep);
122628
+ const isSubdirectory = resolvedTarget.startsWith(resolvedRoot + path148.sep);
122042
122629
  if (isSubdirectory) {
122043
122630
  return {
122044
122631
  success: false,
@@ -122054,11 +122641,11 @@ async function executeSavePlan(args2, fallbackDir) {
122054
122641
  let specMtime;
122055
122642
  let specHash;
122056
122643
  if (process.env.SWARM_SKIP_SPEC_GATE !== "1") {
122057
- const specPath = path147.join(targetWorkspace, ".swarm", "spec.md");
122644
+ const specPath = path148.join(targetWorkspace, ".swarm", "spec.md");
122058
122645
  try {
122059
- const stat9 = await fs107.promises.stat(specPath);
122646
+ const stat9 = await fs108.promises.stat(specPath);
122060
122647
  specMtime = stat9.mtime.toISOString();
122061
- const content = await fs107.promises.readFile(specPath, "utf8");
122648
+ const content = await fs108.promises.readFile(specPath, "utf8");
122062
122649
  specHash = crypto12.createHash("sha256").update(content).digest("hex");
122063
122650
  } catch {
122064
122651
  return {
@@ -122070,10 +122657,10 @@ async function executeSavePlan(args2, fallbackDir) {
122070
122657
  }
122071
122658
  }
122072
122659
  if (process.env.SWARM_SKIP_GATE_SELECTION !== "1") {
122073
- const contextPath = path147.join(targetWorkspace, ".swarm", "context.md");
122660
+ const contextPath = path148.join(targetWorkspace, ".swarm", "context.md");
122074
122661
  let contextContent = "";
122075
122662
  try {
122076
- contextContent = await fs107.promises.readFile(contextPath, "utf8");
122663
+ contextContent = await fs108.promises.readFile(contextPath, "utf8");
122077
122664
  } catch {}
122078
122665
  const hasPendingSection = contextContent.includes("## Pending QA Gate Selection");
122079
122666
  if (!hasPendingSection) {
@@ -122360,14 +122947,14 @@ async function executeSavePlan(args2, fallbackDir) {
122360
122947
  }
122361
122948
  await writeCheckpoint(dir).catch(() => {});
122362
122949
  try {
122363
- const markerPath = path147.join(dir, ".swarm", ".plan-write-marker");
122950
+ const markerPath = path148.join(dir, ".swarm", ".plan-write-marker");
122364
122951
  const marker = JSON.stringify({
122365
122952
  source: "save_plan",
122366
122953
  timestamp: new Date().toISOString(),
122367
122954
  phases_count: plan.phases.length,
122368
122955
  tasks_count: tasksCount
122369
122956
  });
122370
- await fs107.promises.writeFile(markerPath, marker, "utf8");
122957
+ await fs108.promises.writeFile(markerPath, marker, "utf8");
122371
122958
  } catch {}
122372
122959
  const warnings = [];
122373
122960
  let criticReviewFound = false;
@@ -122383,7 +122970,7 @@ async function executeSavePlan(args2, fallbackDir) {
122383
122970
  return {
122384
122971
  success: true,
122385
122972
  message: "Plan saved successfully",
122386
- plan_path: path147.join(dir, ".swarm", "plan.json"),
122973
+ plan_path: path148.join(dir, ".swarm", "plan.json"),
122387
122974
  phases_count: plan.phases.length,
122388
122975
  tasks_count: tasksCount,
122389
122976
  ...resolvedProfile !== undefined ? { execution_profile: resolvedProfile } : {},
@@ -122449,8 +123036,8 @@ var save_plan = createSwarmTool({
122449
123036
  // src/tools/sbom-generate.ts
122450
123037
  init_zod();
122451
123038
  init_manager2();
122452
- import * as fs108 from "node:fs";
122453
- import * as path148 from "node:path";
123039
+ import * as fs109 from "node:fs";
123040
+ import * as path149 from "node:path";
122454
123041
 
122455
123042
  // src/sbom/detectors/index.ts
122456
123043
  init_utils();
@@ -123298,9 +123885,9 @@ function findManifestFiles(rootDir) {
123298
123885
  const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
123299
123886
  function searchDir(dir) {
123300
123887
  try {
123301
- const entries = fs108.readdirSync(dir, { withFileTypes: true });
123888
+ const entries = fs109.readdirSync(dir, { withFileTypes: true });
123302
123889
  for (const entry of entries) {
123303
- const fullPath = path148.join(dir, entry.name);
123890
+ const fullPath = path149.join(dir, entry.name);
123304
123891
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "target") {
123305
123892
  continue;
123306
123893
  }
@@ -123309,7 +123896,7 @@ function findManifestFiles(rootDir) {
123309
123896
  } else if (entry.isFile()) {
123310
123897
  for (const pattern of patterns) {
123311
123898
  if (simpleGlobToRegex(pattern).test(entry.name)) {
123312
- manifestFiles.push(path148.relative(rootDir, fullPath));
123899
+ manifestFiles.push(path149.relative(rootDir, fullPath));
123313
123900
  break;
123314
123901
  }
123315
123902
  }
@@ -123325,13 +123912,13 @@ function findManifestFilesInDirs(directories, workingDir) {
123325
123912
  const patterns = [...new Set(allDetectors.flatMap((d) => d.patterns))];
123326
123913
  for (const dir of directories) {
123327
123914
  try {
123328
- const entries = fs108.readdirSync(dir, { withFileTypes: true });
123915
+ const entries = fs109.readdirSync(dir, { withFileTypes: true });
123329
123916
  for (const entry of entries) {
123330
- const fullPath = path148.join(dir, entry.name);
123917
+ const fullPath = path149.join(dir, entry.name);
123331
123918
  if (entry.isFile()) {
123332
123919
  for (const pattern of patterns) {
123333
123920
  if (simpleGlobToRegex(pattern).test(entry.name)) {
123334
- found.push(path148.relative(workingDir, fullPath));
123921
+ found.push(path149.relative(workingDir, fullPath));
123335
123922
  break;
123336
123923
  }
123337
123924
  }
@@ -123344,11 +123931,11 @@ function findManifestFilesInDirs(directories, workingDir) {
123344
123931
  function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
123345
123932
  const dirs = new Set;
123346
123933
  for (const file3 of changedFiles) {
123347
- let currentDir = path148.dirname(file3);
123934
+ let currentDir = path149.dirname(file3);
123348
123935
  while (true) {
123349
- if (currentDir && currentDir !== "." && currentDir !== path148.sep) {
123350
- dirs.add(path148.join(workingDir, currentDir));
123351
- const parent = path148.dirname(currentDir);
123936
+ if (currentDir && currentDir !== "." && currentDir !== path149.sep) {
123937
+ dirs.add(path149.join(workingDir, currentDir));
123938
+ const parent = path149.dirname(currentDir);
123352
123939
  if (parent === currentDir)
123353
123940
  break;
123354
123941
  currentDir = parent;
@@ -123362,7 +123949,7 @@ function getDirectoriesFromChangedFiles(changedFiles, workingDir) {
123362
123949
  }
123363
123950
  function ensureOutputDir(outputDir) {
123364
123951
  try {
123365
- fs108.mkdirSync(outputDir, { recursive: true });
123952
+ fs109.mkdirSync(outputDir, { recursive: true });
123366
123953
  } catch (error93) {
123367
123954
  if (!error93 || error93.code !== "EEXIST") {
123368
123955
  throw error93;
@@ -123432,7 +124019,7 @@ var sbom_generate = createSwarmTool({
123432
124019
  const changedFiles = obj.changed_files;
123433
124020
  const relativeOutputDir = obj.output_dir || DEFAULT_OUTPUT_DIR;
123434
124021
  const workingDir = directory;
123435
- const outputDir = path148.isAbsolute(relativeOutputDir) ? relativeOutputDir : path148.join(workingDir, relativeOutputDir);
124022
+ const outputDir = path149.isAbsolute(relativeOutputDir) ? relativeOutputDir : path149.join(workingDir, relativeOutputDir);
123436
124023
  let manifestFiles = [];
123437
124024
  if (scope === "all") {
123438
124025
  manifestFiles = findManifestFiles(workingDir);
@@ -123455,11 +124042,11 @@ var sbom_generate = createSwarmTool({
123455
124042
  const processedFiles = [];
123456
124043
  for (const manifestFile of manifestFiles) {
123457
124044
  try {
123458
- const fullPath = path148.isAbsolute(manifestFile) ? manifestFile : path148.join(workingDir, manifestFile);
123459
- if (!fs108.existsSync(fullPath)) {
124045
+ const fullPath = path149.isAbsolute(manifestFile) ? manifestFile : path149.join(workingDir, manifestFile);
124046
+ if (!fs109.existsSync(fullPath)) {
123460
124047
  continue;
123461
124048
  }
123462
- const content = fs108.readFileSync(fullPath, "utf-8");
124049
+ const content = fs109.readFileSync(fullPath, "utf-8");
123463
124050
  const components = detectComponents(manifestFile, content);
123464
124051
  processedFiles.push(manifestFile);
123465
124052
  if (components.length > 0) {
@@ -123472,8 +124059,8 @@ var sbom_generate = createSwarmTool({
123472
124059
  const bom = generateCycloneDX(allComponents);
123473
124060
  const bomJson = serializeCycloneDX(bom);
123474
124061
  const filename = generateSbomFilename();
123475
- const outputPath = path148.join(outputDir, filename);
123476
- fs108.writeFileSync(outputPath, bomJson, "utf-8");
124062
+ const outputPath = path149.join(outputDir, filename);
124063
+ fs109.writeFileSync(outputPath, bomJson, "utf-8");
123477
124064
  const verdict = processedFiles.length > 0 ? "pass" : "pass";
123478
124065
  try {
123479
124066
  const timestamp = new Date().toISOString();
@@ -123516,8 +124103,8 @@ var sbom_generate = createSwarmTool({
123516
124103
  // src/tools/schema-drift.ts
123517
124104
  init_zod();
123518
124105
  init_create_tool();
123519
- import * as fs109 from "node:fs";
123520
- import * as path149 from "node:path";
124106
+ import * as fs110 from "node:fs";
124107
+ import * as path150 from "node:path";
123521
124108
  var SPEC_CANDIDATES = [
123522
124109
  "openapi.json",
123523
124110
  "openapi.yaml",
@@ -123549,28 +124136,28 @@ function normalizePath5(p) {
123549
124136
  }
123550
124137
  function discoverSpecFile(cwd, specFileArg) {
123551
124138
  if (specFileArg) {
123552
- const resolvedPath = path149.resolve(cwd, specFileArg);
123553
- const normalizedCwd = cwd.endsWith(path149.sep) ? cwd : cwd + path149.sep;
124139
+ const resolvedPath = path150.resolve(cwd, specFileArg);
124140
+ const normalizedCwd = cwd.endsWith(path150.sep) ? cwd : cwd + path150.sep;
123554
124141
  if (!resolvedPath.startsWith(normalizedCwd) && resolvedPath !== cwd) {
123555
124142
  throw new Error("Invalid spec_file: path traversal detected");
123556
124143
  }
123557
- const ext = path149.extname(resolvedPath).toLowerCase();
124144
+ const ext = path150.extname(resolvedPath).toLowerCase();
123558
124145
  if (!ALLOWED_EXTENSIONS.includes(ext)) {
123559
124146
  throw new Error(`Invalid spec_file: must end in .json, .yaml, or .yml, got ${ext}`);
123560
124147
  }
123561
- const stats = fs109.statSync(resolvedPath);
124148
+ const stats = fs110.statSync(resolvedPath);
123562
124149
  if (stats.size > MAX_SPEC_SIZE) {
123563
124150
  throw new Error(`Invalid spec_file: file exceeds ${MAX_SPEC_SIZE / 1024 / 1024}MB limit`);
123564
124151
  }
123565
- if (!fs109.existsSync(resolvedPath)) {
124152
+ if (!fs110.existsSync(resolvedPath)) {
123566
124153
  throw new Error(`Spec file not found: ${resolvedPath}`);
123567
124154
  }
123568
124155
  return resolvedPath;
123569
124156
  }
123570
124157
  for (const candidate of SPEC_CANDIDATES) {
123571
- const candidatePath = path149.resolve(cwd, candidate);
123572
- if (fs109.existsSync(candidatePath)) {
123573
- const stats = fs109.statSync(candidatePath);
124158
+ const candidatePath = path150.resolve(cwd, candidate);
124159
+ if (fs110.existsSync(candidatePath)) {
124160
+ const stats = fs110.statSync(candidatePath);
123574
124161
  if (stats.size <= MAX_SPEC_SIZE) {
123575
124162
  return candidatePath;
123576
124163
  }
@@ -123579,8 +124166,8 @@ function discoverSpecFile(cwd, specFileArg) {
123579
124166
  return null;
123580
124167
  }
123581
124168
  function parseSpec(specFile) {
123582
- const content = fs109.readFileSync(specFile, "utf-8");
123583
- const ext = path149.extname(specFile).toLowerCase();
124169
+ const content = fs110.readFileSync(specFile, "utf-8");
124170
+ const ext = path150.extname(specFile).toLowerCase();
123584
124171
  if (ext === ".json") {
123585
124172
  return parseJsonSpec(content);
123586
124173
  }
@@ -123648,15 +124235,15 @@ function parseYamlSpec(content) {
123648
124235
  }
123649
124236
  function extractRoutes(cwd) {
123650
124237
  const routes = [];
123651
- function walkDir(dir) {
124238
+ function walkDir2(dir) {
123652
124239
  let entries;
123653
124240
  try {
123654
- entries = fs109.readdirSync(dir, { withFileTypes: true });
124241
+ entries = fs110.readdirSync(dir, { withFileTypes: true });
123655
124242
  } catch {
123656
124243
  return;
123657
124244
  }
123658
124245
  for (const entry of entries) {
123659
- const fullPath = path149.join(dir, entry.name);
124246
+ const fullPath = path150.join(dir, entry.name);
123660
124247
  if (entry.isSymbolicLink()) {
123661
124248
  continue;
123662
124249
  }
@@ -123664,9 +124251,9 @@ function extractRoutes(cwd) {
123664
124251
  if (SKIP_DIRS.includes(entry.name)) {
123665
124252
  continue;
123666
124253
  }
123667
- walkDir(fullPath);
124254
+ walkDir2(fullPath);
123668
124255
  } else if (entry.isFile()) {
123669
- const ext = path149.extname(entry.name).toLowerCase();
124256
+ const ext = path150.extname(entry.name).toLowerCase();
123670
124257
  const baseName = entry.name.toLowerCase();
123671
124258
  if (![".ts", ".js", ".mjs"].includes(ext)) {
123672
124259
  continue;
@@ -123679,12 +124266,12 @@ function extractRoutes(cwd) {
123679
124266
  }
123680
124267
  }
123681
124268
  }
123682
- walkDir(cwd);
124269
+ walkDir2(cwd);
123683
124270
  return routes;
123684
124271
  }
123685
124272
  function extractRoutesFromFile(filePath) {
123686
124273
  const routes = [];
123687
- const content = fs109.readFileSync(filePath, "utf-8");
124274
+ const content = fs110.readFileSync(filePath, "utf-8");
123688
124275
  const lines = content.split(/\r?\n/);
123689
124276
  const expressRegex = /(?:app|router|server|express)\.(get|post|put|patch|delete|options|head)\s*\(\s*['"`]([^'"`]+)['"`]/g;
123690
124277
  const flaskRegex = /@(?:app|blueprint|bp)\.route\s*\(\s*['"]([^'"]+)['"]/g;
@@ -123834,8 +124421,8 @@ init_zod();
123834
124421
  init_bun_compat();
123835
124422
  init_path_security();
123836
124423
  init_create_tool();
123837
- import * as fs110 from "node:fs";
123838
- import * as path150 from "node:path";
124424
+ import * as fs111 from "node:fs";
124425
+ import * as path151 from "node:path";
123839
124426
  var DEFAULT_MAX_RESULTS = 100;
123840
124427
  var DEFAULT_MAX_LINES = 200;
123841
124428
  var REGEX_TIMEOUT_MS = 5000;
@@ -123871,11 +124458,11 @@ function containsWindowsAttacks4(str) {
123871
124458
  }
123872
124459
  function isPathInWorkspace3(filePath, workspace) {
123873
124460
  try {
123874
- const resolvedPath = path150.resolve(workspace, filePath);
123875
- const realWorkspace = fs110.realpathSync(workspace);
123876
- const realResolvedPath = fs110.realpathSync(resolvedPath);
123877
- const relativePath = path150.relative(realWorkspace, realResolvedPath);
123878
- if (relativePath.startsWith("..") || path150.isAbsolute(relativePath)) {
124461
+ const resolvedPath = path151.resolve(workspace, filePath);
124462
+ const realWorkspace = fs111.realpathSync(workspace);
124463
+ const realResolvedPath = fs111.realpathSync(resolvedPath);
124464
+ const relativePath = path151.relative(realWorkspace, realResolvedPath);
124465
+ if (relativePath.startsWith("..") || path151.isAbsolute(relativePath)) {
123879
124466
  return false;
123880
124467
  }
123881
124468
  return true;
@@ -123888,12 +124475,12 @@ function validatePathForRead2(filePath, workspace) {
123888
124475
  }
123889
124476
  function findRgInEnvPath() {
123890
124477
  const searchPath = process.env.PATH ?? "";
123891
- for (const dir of searchPath.split(path150.delimiter)) {
124478
+ for (const dir of searchPath.split(path151.delimiter)) {
123892
124479
  if (!dir)
123893
124480
  continue;
123894
124481
  const isWindows = process.platform === "win32";
123895
- const candidate = path150.join(dir, isWindows ? "rg.exe" : "rg");
123896
- if (fs110.existsSync(candidate))
124482
+ const candidate = path151.join(dir, isWindows ? "rg.exe" : "rg");
124483
+ if (fs111.existsSync(candidate))
123897
124484
  return candidate;
123898
124485
  }
123899
124486
  return null;
@@ -123947,7 +124534,7 @@ async function ripgrepSearch(opts) {
123947
124534
  stderr: "pipe",
123948
124535
  cwd: opts.workspace
123949
124536
  });
123950
- const timeout = new Promise((resolve56) => setTimeout(() => resolve56("timeout"), REGEX_TIMEOUT_MS));
124537
+ const timeout = new Promise((resolve57) => setTimeout(() => resolve57("timeout"), REGEX_TIMEOUT_MS));
123951
124538
  const exitPromise = proc.exited;
123952
124539
  const result = await Promise.race([exitPromise, timeout]);
123953
124540
  if (result === "timeout") {
@@ -124020,10 +124607,10 @@ function collectFiles(dir, workspace, includeGlobs, excludeGlobs) {
124020
124607
  return files;
124021
124608
  }
124022
124609
  try {
124023
- const entries = fs110.readdirSync(dir, { withFileTypes: true });
124610
+ const entries = fs111.readdirSync(dir, { withFileTypes: true });
124024
124611
  for (const entry of entries) {
124025
- const fullPath = path150.join(dir, entry.name);
124026
- const relativePath = path150.relative(workspace, fullPath);
124612
+ const fullPath = path151.join(dir, entry.name);
124613
+ const relativePath = path151.relative(workspace, fullPath);
124027
124614
  if (!validatePathForRead2(fullPath, workspace)) {
124028
124615
  continue;
124029
124616
  }
@@ -124064,13 +124651,13 @@ async function fallbackSearch(opts) {
124064
124651
  const matches = [];
124065
124652
  let total = 0;
124066
124653
  for (const file3 of files) {
124067
- const fullPath = path150.join(opts.workspace, file3);
124654
+ const fullPath = path151.join(opts.workspace, file3);
124068
124655
  if (!validatePathForRead2(fullPath, opts.workspace)) {
124069
124656
  continue;
124070
124657
  }
124071
124658
  let stats;
124072
124659
  try {
124073
- stats = fs110.statSync(fullPath);
124660
+ stats = fs111.statSync(fullPath);
124074
124661
  if (stats.size > MAX_FILE_SIZE_BYTES10) {
124075
124662
  continue;
124076
124663
  }
@@ -124079,7 +124666,7 @@ async function fallbackSearch(opts) {
124079
124666
  }
124080
124667
  let content;
124081
124668
  try {
124082
- content = fs110.readFileSync(fullPath, "utf-8");
124669
+ content = fs111.readFileSync(fullPath, "utf-8");
124083
124670
  } catch {
124084
124671
  continue;
124085
124672
  }
@@ -124191,7 +124778,7 @@ var search = createSwarmTool({
124191
124778
  message: "Exclude pattern contains invalid Windows-specific sequence"
124192
124779
  }, null, 2);
124193
124780
  }
124194
- if (!fs110.existsSync(directory)) {
124781
+ if (!fs111.existsSync(directory)) {
124195
124782
  return JSON.stringify({
124196
124783
  error: true,
124197
124784
  type: "unknown",
@@ -124477,7 +125064,7 @@ init_config();
124477
125064
  init_schema();
124478
125065
  init_create_tool();
124479
125066
  import { mkdir as mkdir24, rename as rename10, writeFile as writeFile19 } from "node:fs/promises";
124480
- import * as path151 from "node:path";
125067
+ import * as path152 from "node:path";
124481
125068
  var MAX_SPEC_BYTES = 256 * 1024;
124482
125069
  var spec_write = createSwarmTool({
124483
125070
  description: "Write the canonical project spec to .swarm/spec.md. Atomic write, size-bounded (256 KiB), heading-required. Honors spec_writer.allow_spec_write.",
@@ -124518,14 +125105,14 @@ var spec_write = createSwarmTool({
124518
125105
  reason: 'spec must contain at least one top-level "# Heading"'
124519
125106
  }, null, 2);
124520
125107
  }
124521
- const target = path151.join(directory, ".swarm", "spec.md");
124522
- await mkdir24(path151.dirname(target), { recursive: true });
125108
+ const target = path152.join(directory, ".swarm", "spec.md");
125109
+ await mkdir24(path152.dirname(target), { recursive: true });
124523
125110
  const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
124524
125111
  let finalContent = content;
124525
125112
  if (mode === "append") {
124526
125113
  try {
124527
- const fs111 = await import("node:fs/promises");
124528
- const prior = await fs111.readFile(target, "utf-8");
125114
+ const fs112 = await import("node:fs/promises");
125115
+ const prior = await fs112.readFile(target, "utf-8");
124529
125116
  finalContent = `${prior.replace(/\s+$/, "")}
124530
125117
 
124531
125118
  ${content}
@@ -124548,14 +125135,14 @@ ${content}
124548
125135
  init_zod();
124549
125136
  init_loader();
124550
125137
  import {
124551
- existsSync as existsSync85,
125138
+ existsSync as existsSync86,
124552
125139
  mkdirSync as mkdirSync36,
124553
125140
  readFileSync as readFileSync72,
124554
125141
  renameSync as renameSync22,
124555
125142
  unlinkSync as unlinkSync20,
124556
125143
  writeFileSync as writeFileSync30
124557
125144
  } from "node:fs";
124558
- import path152 from "node:path";
125145
+ import path153 from "node:path";
124559
125146
  init_create_tool();
124560
125147
  init_resolve_working_directory();
124561
125148
  var VerdictSchema2 = exports_external.object({
@@ -124685,7 +125272,7 @@ var submit_phase_council_verdicts = createSwarmTool({
124685
125272
  }
124686
125273
  });
124687
125274
  function getPhaseMutationGapFinding(phaseNumber, workingDir) {
124688
- const mutationGatePath = path152.join(workingDir, ".swarm", "evidence", String(phaseNumber), "mutation-gate.json");
125275
+ const mutationGatePath = path153.join(workingDir, ".swarm", "evidence", String(phaseNumber), "mutation-gate.json");
124689
125276
  try {
124690
125277
  const raw = readFileSync72(mutationGatePath, "utf-8");
124691
125278
  const parsed = JSON.parse(raw);
@@ -124747,9 +125334,9 @@ function getPhaseMutationGapFinding(phaseNumber, workingDir) {
124747
125334
  }
124748
125335
  }
124749
125336
  function writePhaseCouncilEvidence(workingDir, synthesis) {
124750
- const evidenceDir = path152.join(workingDir, ".swarm", "evidence", String(synthesis.phaseNumber));
125337
+ const evidenceDir = path153.join(workingDir, ".swarm", "evidence", String(synthesis.phaseNumber));
124751
125338
  mkdirSync36(evidenceDir, { recursive: true });
124752
- const evidenceFile = path152.join(evidenceDir, "phase-council.json");
125339
+ const evidenceFile = path153.join(evidenceDir, "phase-council.json");
124753
125340
  const evidenceBundle = {
124754
125341
  entries: [
124755
125342
  {
@@ -124785,7 +125372,7 @@ function writePhaseCouncilEvidence(workingDir, synthesis) {
124785
125372
  writeFileSync30(tempFile, JSON.stringify(evidenceBundle, null, 2), "utf-8");
124786
125373
  renameSync22(tempFile, evidenceFile);
124787
125374
  } finally {
124788
- if (existsSync85(tempFile)) {
125375
+ if (existsSync86(tempFile)) {
124789
125376
  unlinkSync20(tempFile);
124790
125377
  }
124791
125378
  }
@@ -124810,8 +125397,30 @@ function formatMutationGapFeedback(finding) {
124810
125397
  init_zod();
124811
125398
  init_path_security();
124812
125399
  init_create_tool();
124813
- import * as fs111 from "node:fs";
124814
- import * as path153 from "node:path";
125400
+ import * as fs112 from "node:fs";
125401
+ import * as path154 from "node:path";
125402
+ var BINARY_EXTENSIONS2 = new Set([
125403
+ ".png",
125404
+ ".jpg",
125405
+ ".jpeg",
125406
+ ".gif",
125407
+ ".bmp",
125408
+ ".ico",
125409
+ ".svg",
125410
+ ".woff",
125411
+ ".woff2",
125412
+ ".ttf",
125413
+ ".eot",
125414
+ ".mp3",
125415
+ ".mp4",
125416
+ ".avi",
125417
+ ".mov",
125418
+ ".pdf",
125419
+ ".zip",
125420
+ ".tar",
125421
+ ".gz",
125422
+ ".rar"
125423
+ ]);
124815
125424
  var WINDOWS_RESERVED_NAMES5 = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])(\.|:|$)/i;
124816
125425
  function containsWindowsAttacks5(str) {
124817
125426
  if (/:[^\\/]/.test(str))
@@ -124825,14 +125434,14 @@ function containsWindowsAttacks5(str) {
124825
125434
  }
124826
125435
  function isPathInWorkspace4(filePath, workspace) {
124827
125436
  try {
124828
- const resolvedPath = path153.resolve(workspace, filePath);
124829
- if (!fs111.existsSync(resolvedPath)) {
125437
+ const resolvedPath = path154.resolve(workspace, filePath);
125438
+ if (!fs112.existsSync(resolvedPath)) {
124830
125439
  return true;
124831
125440
  }
124832
- const realWorkspace = fs111.realpathSync(workspace);
124833
- const realResolvedPath = fs111.realpathSync(resolvedPath);
124834
- const relativePath = path153.relative(realWorkspace, realResolvedPath);
124835
- if (relativePath.startsWith("..") || path153.isAbsolute(relativePath)) {
125441
+ const realWorkspace = fs112.realpathSync(workspace);
125442
+ const realResolvedPath = fs112.realpathSync(resolvedPath);
125443
+ const relativePath = path154.relative(realWorkspace, realResolvedPath);
125444
+ if (relativePath.startsWith("..") || path154.isAbsolute(relativePath)) {
124836
125445
  return false;
124837
125446
  }
124838
125447
  return true;
@@ -124840,7 +125449,7 @@ function isPathInWorkspace4(filePath, workspace) {
124840
125449
  return false;
124841
125450
  }
124842
125451
  }
124843
- function validateFilePath(filePath, workspace) {
125452
+ function validateFilePath2(filePath, workspace) {
124844
125453
  if (!filePath || filePath.trim() === "")
124845
125454
  return false;
124846
125455
  if (containsPathTraversal(filePath))
@@ -124852,8 +125461,7 @@ function validateFilePath(filePath, workspace) {
124852
125461
  return isPathInWorkspace4(filePath, workspace);
124853
125462
  }
124854
125463
  function findContextMatch(content, contextBefore, contextAfter, oldContent) {
124855
- const lines = content.split(`
124856
- `);
125464
+ const lines = splitDiffLines(content);
124857
125465
  if ((!contextBefore || contextBefore.length === 0) && (!contextAfter || contextAfter.length === 0)) {
124858
125466
  return null;
124859
125467
  }
@@ -124875,8 +125483,7 @@ function findContextMatch(content, contextBefore, contextAfter, oldContent) {
124875
125483
  };
124876
125484
  } else {
124877
125485
  if (oldContent && oldContent.length > 0) {
124878
- const oldContentLines = oldContent.split(`
124879
- `);
125486
+ const oldContentLines = splitDiffLines(oldContent);
124880
125487
  const betweenLines = lines.slice(afterStart, j);
124881
125488
  if (arraysEqual2(betweenLines, oldContentLines)) {
124882
125489
  return {
@@ -124900,8 +125507,7 @@ function findContextMatch(content, contextBefore, contextAfter, oldContent) {
124900
125507
  return null;
124901
125508
  } else {
124902
125509
  if (oldContent && oldContent.length > 0) {
124903
- const oldContentLines = oldContent.split(`
124904
- `);
125510
+ const oldContentLines = splitDiffLines(oldContent);
124905
125511
  for (let k = afterStart;k <= lines.length - oldContentLines.length; k++) {
124906
125512
  const candidate = lines.slice(k, k + oldContentLines.length);
124907
125513
  if (arraysEqual2(candidate, oldContentLines)) {
@@ -124949,23 +125555,117 @@ function arraysEqual2(a, b) {
124949
125555
  }
124950
125556
  return true;
124951
125557
  }
124952
- function validateOldContent(lines, startIndex, endIndex, oldContent) {
125558
+ function isBinaryFile4(filePath) {
125559
+ const ext = path154.extname(filePath).toLowerCase();
125560
+ return BINARY_EXTENSIONS2.has(ext);
125561
+ }
125562
+ function splitDiffLines(content) {
125563
+ if (content === "")
125564
+ return [];
125565
+ return content.endsWith(`
125566
+ `) ? content.slice(0, -1).split(`
125567
+ `) : content.split(`
125568
+ `);
125569
+ }
125570
+ function generateFileHeader(file3) {
125571
+ return `diff --git a/${file3} b/${file3}
125572
+ ` + `--- a/${file3}
125573
+ ` + `+++ b/${file3}
125574
+ `;
125575
+ }
125576
+ function generateHunk(content, contextMatch, oldContent, newContent) {
125577
+ const lines = splitDiffLines(content);
125578
+ const originalEndsWithNewline = content.endsWith(`
125579
+ `);
125580
+ const newContentEndsWithNewline = newContent.endsWith(`
125581
+ `);
125582
+ const removalStartIdx = contextMatch.startLineIndex + contextMatch.matchedBefore.length;
125583
+ const removalLines = oldContent ? splitDiffLines(oldContent) : [];
125584
+ const removalEndIdx = removalLines.length > 0 ? removalStartIdx + removalLines.length - 1 : removalStartIdx - 1;
125585
+ const additionLines = splitDiffLines(newContent);
125586
+ const isAdjacentCase = contextMatch.matchedAfter.length > 0 && contextMatch.endLineIndex >= 0 && contextMatch.endLineIndex < lines.length && lines[contextMatch.endLineIndex] === contextMatch.matchedAfter[contextMatch.matchedAfter.length - 1];
125587
+ const contextAfterStartInFile = isAdjacentCase ? contextMatch.endLineIndex - contextMatch.matchedAfter.length + 1 : contextMatch.endLineIndex + 1;
125588
+ const overlapSkipCount = Math.max(0, removalLines.length > 0 ? removalEndIdx + 1 - contextAfterStartInFile : 0);
125589
+ const effectiveContextAfterCount = Math.max(0, contextMatch.matchedAfter.length - overlapSkipCount);
125590
+ const oldStart = contextMatch.matchedBefore.length > 0 ? contextMatch.startLineIndex + 1 : removalStartIdx + 1;
125591
+ const newStart = oldStart;
125592
+ const oldCount = contextMatch.matchedBefore.length + removalLines.length + effectiveContextAfterCount;
125593
+ const newCount = contextMatch.matchedBefore.length + additionLines.length + effectiveContextAfterCount;
125594
+ const hunkLines = [];
125595
+ let lastOldSidePos = -1;
125596
+ let lastNewSidePos = -1;
125597
+ for (const line of contextMatch.matchedBefore) {
125598
+ const idx = hunkLines.length;
125599
+ hunkLines.push(` ${line}`);
125600
+ lastOldSidePos = idx;
125601
+ lastNewSidePos = idx;
125602
+ }
125603
+ for (const line of removalLines) {
125604
+ const idx = hunkLines.length;
125605
+ hunkLines.push(`-${line}`);
125606
+ lastOldSidePos = idx;
125607
+ }
125608
+ for (const line of additionLines) {
125609
+ const idx = hunkLines.length;
125610
+ hunkLines.push(`+${line}`);
125611
+ lastNewSidePos = idx;
125612
+ }
125613
+ for (let k = overlapSkipCount;k < contextMatch.matchedAfter.length; k++) {
125614
+ const idx = hunkLines.length;
125615
+ hunkLines.push(` ${contextMatch.matchedAfter[k]}`);
125616
+ lastOldSidePos = idx;
125617
+ lastNewSidePos = idx;
125618
+ }
125619
+ const lastOldSideFileIdx = effectiveContextAfterCount > 0 ? contextAfterStartInFile + contextMatch.matchedAfter.length - 1 : removalLines.length > 0 ? removalEndIdx : contextMatch.matchedBefore.length > 0 ? contextMatch.startLineIndex + contextMatch.matchedBefore.length - 1 : -1;
125620
+ const isAtEof = lastOldSideFileIdx === lines.length - 1;
125621
+ const needsOldMarker = isAtEof && !originalEndsWithNewline && lastOldSidePos >= 0;
125622
+ const newSideEndsWithNewline = effectiveContextAfterCount > 0 ? originalEndsWithNewline : additionLines.length > 0 ? newContentEndsWithNewline : true;
125623
+ const needsNewMarker = isAtEof && !newSideEndsWithNewline && lastNewSidePos >= 0;
125624
+ const finalLines = [];
125625
+ let pendingOldMarker = needsOldMarker;
125626
+ let pendingNewMarker = needsNewMarker;
125627
+ for (let i2 = 0;i2 < hunkLines.length; i2++) {
125628
+ finalLines.push(hunkLines[i2]);
125629
+ if (pendingOldMarker && i2 === lastOldSidePos) {
125630
+ finalLines.push("\");
125631
+ pendingOldMarker = false;
125632
+ }
125633
+ if (pendingNewMarker && i2 === lastNewSidePos) {
125634
+ finalLines.push("\");
125635
+ pendingNewMarker = false;
125636
+ }
125637
+ }
125638
+ const oldCountStr = oldCount === 0 ? "0" : String(oldCount);
125639
+ const newCountStr = newCount === 0 ? "0" : String(newCount);
125640
+ let diff2 = "";
125641
+ diff2 += `@@ -${oldStart},${oldCountStr} +${newStart},${newCountStr} @@
125642
+ `;
125643
+ diff2 += finalLines.join(`
125644
+ `);
125645
+ diff2 += `
125646
+ `;
125647
+ return diff2;
125648
+ }
125649
+ function validateOldContent(lines, contextMatch, oldContent) {
124953
125650
  if (!oldContent) {
124954
125651
  return { valid: true };
124955
125652
  }
124956
- const currentContent = lines.slice(startIndex, endIndex + 1).join(`
124957
- `);
124958
- if (currentContent !== oldContent) {
125653
+ const expectedLines = splitDiffLines(oldContent);
125654
+ const removalStartIdx = contextMatch.startLineIndex + contextMatch.matchedBefore.length;
125655
+ const actualLines = lines.slice(removalStartIdx, removalStartIdx + expectedLines.length);
125656
+ if (!arraysEqual2(actualLines, expectedLines)) {
124959
125657
  return {
124960
125658
  valid: false,
124961
- expected: oldContent,
124962
- actual: currentContent
125659
+ expected: expectedLines.join(`
125660
+ `),
125661
+ actual: actualLines.join(`
125662
+ `)
124963
125663
  };
124964
125664
  }
124965
125665
  return { valid: true };
124966
125666
  }
124967
125667
  var suggestPatch = createSwarmTool({
124968
- description: "Suggest a structured patch for specified files without modifying them. " + "Returns context-based patch proposals with anchors for reviewer use. " + "This is a read-only tool — it does not modify any files.",
125668
+ description: "Suggest a structured patch for specified files without modifying them. " + "Returns context-based patch proposals with anchors for reviewer use. " + 'When format="unified", also produces a unified diff string consumable by apply_patch. ' + "This is a read-only tool — it does not modify any files.",
124969
125669
  args: {
124970
125670
  targetFiles: exports_external.array(exports_external.string()).describe("Array of file paths to patch").min(1),
124971
125671
  changes: exports_external.array(exports_external.object({
@@ -124974,7 +125674,8 @@ var suggestPatch = createSwarmTool({
124974
125674
  contextAfter: exports_external.array(exports_external.string()).optional().describe("Lines after the change region (anchor)"),
124975
125675
  oldContent: exports_external.string().optional().describe("Current content to be replaced"),
124976
125676
  newContent: exports_external.string().describe("New content to replace with")
124977
- })).describe("Array of change descriptions with context anchors").min(1)
125677
+ })).describe("Array of change descriptions with context anchors").min(1),
125678
+ format: exports_external.enum(["json", "unified"]).optional().default("json").describe('Output format: "json" (default, existing structured output) or "unified" (unified diff string for apply_patch)')
124978
125679
  },
124979
125680
  execute: async (args2, directory) => {
124980
125681
  if (!args2 || typeof args2 !== "object") {
@@ -124988,6 +125689,7 @@ var suggestPatch = createSwarmTool({
124988
125689
  const obj = args2;
124989
125690
  const targetFiles = obj.targetFiles ?? [];
124990
125691
  const changes = obj.changes ?? [];
125692
+ const format = obj.format ?? "json";
124991
125693
  if (!targetFiles || targetFiles.length === 0) {
124992
125694
  return JSON.stringify({
124993
125695
  success: false,
@@ -125004,7 +125706,7 @@ var suggestPatch = createSwarmTool({
125004
125706
  message: "changes cannot be empty"
125005
125707
  }, null, 2);
125006
125708
  }
125007
- if (!fs111.existsSync(directory)) {
125709
+ if (!fs112.existsSync(directory)) {
125008
125710
  return JSON.stringify({
125009
125711
  success: false,
125010
125712
  error: true,
@@ -125015,9 +125717,28 @@ var suggestPatch = createSwarmTool({
125015
125717
  const patches = [];
125016
125718
  const filesModifiedSet = new Set;
125017
125719
  const errors5 = [];
125720
+ const unifiedDiffEntries = [];
125018
125721
  const targetFileSet = new Set(targetFiles);
125722
+ const skippedBinaryFiles = new Set;
125723
+ if (format === "unified") {
125724
+ for (const change of changes) {
125725
+ if (isBinaryFile4(change.file)) {
125726
+ errors5.push({
125727
+ success: false,
125728
+ error: true,
125729
+ type: "parse-error",
125730
+ message: `Binary files are not supported in unified diff mode: ${change.file}`,
125731
+ details: { location: change.file }
125732
+ });
125733
+ skippedBinaryFiles.add(change.file);
125734
+ }
125735
+ }
125736
+ }
125019
125737
  for (let changeIndex = 0;changeIndex < changes.length; changeIndex++) {
125020
125738
  const change = changes[changeIndex];
125739
+ if (format === "unified" && skippedBinaryFiles.has(change.file)) {
125740
+ continue;
125741
+ }
125021
125742
  if (!targetFileSet.has(change.file)) {
125022
125743
  errors5.push({
125023
125744
  success: false,
@@ -125028,7 +125749,7 @@ var suggestPatch = createSwarmTool({
125028
125749
  });
125029
125750
  continue;
125030
125751
  }
125031
- if (!validateFilePath(change.file, directory)) {
125752
+ if (!validateFilePath2(change.file, directory)) {
125032
125753
  errors5.push({
125033
125754
  success: false,
125034
125755
  error: true,
@@ -125040,8 +125761,8 @@ var suggestPatch = createSwarmTool({
125040
125761
  });
125041
125762
  continue;
125042
125763
  }
125043
- const fullPath = path153.resolve(directory, change.file);
125044
- if (!fs111.existsSync(fullPath)) {
125764
+ const fullPath = path154.resolve(directory, change.file);
125765
+ if (!fs112.existsSync(fullPath)) {
125045
125766
  errors5.push({
125046
125767
  success: false,
125047
125768
  error: true,
@@ -125055,7 +125776,7 @@ var suggestPatch = createSwarmTool({
125055
125776
  }
125056
125777
  let content;
125057
125778
  try {
125058
- content = fs111.readFileSync(fullPath, "utf-8");
125779
+ content = fs112.readFileSync(fullPath, "utf-8");
125059
125780
  } catch (err3) {
125060
125781
  errors5.push({
125061
125782
  success: false,
@@ -125081,9 +125802,8 @@ var suggestPatch = createSwarmTool({
125081
125802
  });
125082
125803
  continue;
125083
125804
  }
125084
- const lines = content.split(`
125085
- `);
125086
- const oldContentValidation = validateOldContent(lines, contextMatch.startLineIndex + contextMatch.matchedBefore.length, contextMatch.endLineIndex - contextMatch.matchedAfter.length + 1, change.oldContent);
125805
+ const lines = splitDiffLines(content);
125806
+ const oldContentValidation = validateOldContent(lines, contextMatch, change.oldContent);
125087
125807
  if (!oldContentValidation.valid) {
125088
125808
  errors5.push({
125089
125809
  success: false,
@@ -125110,14 +125830,51 @@ var suggestPatch = createSwarmTool({
125110
125830
  hunkIndex: changeIndex
125111
125831
  });
125112
125832
  filesModifiedSet.add(change.file);
125833
+ if (format === "unified") {
125834
+ unifiedDiffEntries.push({
125835
+ file: change.file,
125836
+ contextMatch,
125837
+ oldContent: change.oldContent,
125838
+ newContent: change.newContent
125839
+ });
125840
+ }
125113
125841
  }
125114
125842
  if (patches.length > 0) {
125115
- return JSON.stringify({
125843
+ const baseResult = {
125116
125844
  success: true,
125117
125845
  patches,
125118
125846
  filesModified: Array.from(filesModifiedSet),
125119
125847
  ...errors5.length > 0 && { errors: errors5 }
125120
- }, null, 2);
125848
+ };
125849
+ if (format === "unified") {
125850
+ const fileGroups = new Map;
125851
+ for (const entry of unifiedDiffEntries) {
125852
+ const group = fileGroups.get(entry.file) ?? [];
125853
+ group.push(entry);
125854
+ fileGroups.set(entry.file, group);
125855
+ }
125856
+ const unifiedParts = [];
125857
+ for (const [file3, entries] of fileGroups) {
125858
+ entries.sort((a, b) => a.contextMatch.startLineIndex - b.contextMatch.startLineIndex);
125859
+ const entryFullPath = path154.resolve(directory, file3);
125860
+ let entryContent;
125861
+ try {
125862
+ entryContent = fs112.readFileSync(entryFullPath, "utf-8");
125863
+ } catch {
125864
+ continue;
125865
+ }
125866
+ unifiedParts.push(generateFileHeader(file3));
125867
+ for (const entry of entries) {
125868
+ unifiedParts.push(generateHunk(entryContent, entry.contextMatch, entry.oldContent, entry.newContent));
125869
+ }
125870
+ }
125871
+ const unifiedPatch = unifiedParts.join("");
125872
+ return JSON.stringify({
125873
+ ...baseResult,
125874
+ unifiedPatch
125875
+ }, null, 2);
125876
+ }
125877
+ return JSON.stringify(baseResult, null, 2);
125121
125878
  }
125122
125879
  if (errors5.length === 1) {
125123
125880
  return JSON.stringify(errors5[0], null, 2);
@@ -125443,8 +126200,8 @@ function getContextAgent3(ctx) {
125443
126200
  init_zod();
125444
126201
  init_manager2();
125445
126202
  init_detector();
125446
- import * as fs112 from "node:fs";
125447
- import * as path154 from "node:path";
126203
+ import * as fs113 from "node:fs";
126204
+ import * as path155 from "node:path";
125448
126205
  init_create_tool();
125449
126206
  var MAX_FILE_SIZE2 = 2 * 1024 * 1024;
125450
126207
  var BINARY_CHECK_BYTES = 8192;
@@ -125510,7 +126267,7 @@ async function syntaxCheck(input, directory, config3) {
125510
126267
  if (languages?.length) {
125511
126268
  const lowerLangs = languages.map((l) => l.toLowerCase());
125512
126269
  filesToCheck = filesToCheck.filter((file3) => {
125513
- const ext = path154.extname(file3.path).toLowerCase();
126270
+ const ext = path155.extname(file3.path).toLowerCase();
125514
126271
  const langDef = getLanguageForExtension(ext);
125515
126272
  const fileProfile = getProfileForFile(file3.path);
125516
126273
  const langId = fileProfile?.id || langDef?.id;
@@ -125523,7 +126280,7 @@ async function syntaxCheck(input, directory, config3) {
125523
126280
  let skippedCount = 0;
125524
126281
  for (const fileInfo of filesToCheck) {
125525
126282
  const { path: filePath } = fileInfo;
125526
- const fullPath = path154.isAbsolute(filePath) ? filePath : path154.join(directory, filePath);
126283
+ const fullPath = path155.isAbsolute(filePath) ? filePath : path155.join(directory, filePath);
125527
126284
  const result = {
125528
126285
  path: filePath,
125529
126286
  language: "",
@@ -125553,7 +126310,7 @@ async function syntaxCheck(input, directory, config3) {
125553
126310
  }
125554
126311
  let content;
125555
126312
  try {
125556
- content = fs112.readFileSync(fullPath, "utf8");
126313
+ content = fs113.readFileSync(fullPath, "utf8");
125557
126314
  } catch {
125558
126315
  result.skipped_reason = "file_read_error";
125559
126316
  skippedCount++;
@@ -125572,7 +126329,7 @@ async function syntaxCheck(input, directory, config3) {
125572
126329
  results.push(result);
125573
126330
  continue;
125574
126331
  }
125575
- const ext = path154.extname(filePath).toLowerCase();
126332
+ const ext = path155.extname(filePath).toLowerCase();
125576
126333
  const langDef = getLanguageForExtension(ext);
125577
126334
  result.language = profile?.id || langDef?.id || "unknown";
125578
126335
  const errors5 = extractSyntaxErrors(parser, content);
@@ -125670,8 +126427,8 @@ init_zod();
125670
126427
  init_utils();
125671
126428
  init_create_tool();
125672
126429
  init_path_security();
125673
- import * as fs113 from "node:fs";
125674
- import * as path155 from "node:path";
126430
+ import * as fs114 from "node:fs";
126431
+ import * as path156 from "node:path";
125675
126432
  var MAX_TEXT_LENGTH = 200;
125676
126433
  var MAX_FILE_SIZE_BYTES11 = 1024 * 1024;
125677
126434
  var SUPPORTED_EXTENSIONS4 = new Set([
@@ -125694,7 +126451,7 @@ var SUPPORTED_EXTENSIONS4 = new Set([
125694
126451
  ".swift",
125695
126452
  ".kt"
125696
126453
  ]);
125697
- var SKIP_DIRECTORIES5 = new Set([
126454
+ var SKIP_DIRECTORIES6 = new Set([
125698
126455
  "node_modules",
125699
126456
  "dist",
125700
126457
  "build",
@@ -125737,9 +126494,9 @@ function validatePathsInput(paths, cwd) {
125737
126494
  return { error: "paths contains path traversal", resolvedPath: null };
125738
126495
  }
125739
126496
  try {
125740
- const resolvedPath = path155.resolve(paths);
125741
- const normalizedCwd = path155.resolve(cwd);
125742
- const normalizedResolved = path155.resolve(resolvedPath);
126497
+ const resolvedPath = path156.resolve(paths);
126498
+ const normalizedCwd = path156.resolve(cwd);
126499
+ const normalizedResolved = path156.resolve(resolvedPath);
125743
126500
  if (!normalizedResolved.startsWith(normalizedCwd)) {
125744
126501
  return {
125745
126502
  error: "paths must be within the current working directory",
@@ -125755,30 +126512,30 @@ function validatePathsInput(paths, cwd) {
125755
126512
  }
125756
126513
  }
125757
126514
  function isSupportedExtension(filePath) {
125758
- const ext = path155.extname(filePath).toLowerCase();
126515
+ const ext = path156.extname(filePath).toLowerCase();
125759
126516
  return SUPPORTED_EXTENSIONS4.has(ext);
125760
126517
  }
125761
- function findSourceFiles3(dir, files = []) {
126518
+ function findSourceFiles4(dir, files = []) {
125762
126519
  let entries;
125763
126520
  try {
125764
- entries = fs113.readdirSync(dir);
126521
+ entries = fs114.readdirSync(dir);
125765
126522
  } catch {
125766
126523
  return files;
125767
126524
  }
125768
126525
  entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
125769
126526
  for (const entry of entries) {
125770
- if (SKIP_DIRECTORIES5.has(entry)) {
126527
+ if (SKIP_DIRECTORIES6.has(entry)) {
125771
126528
  continue;
125772
126529
  }
125773
- const fullPath = path155.join(dir, entry);
126530
+ const fullPath = path156.join(dir, entry);
125774
126531
  let stat9;
125775
126532
  try {
125776
- stat9 = fs113.statSync(fullPath);
126533
+ stat9 = fs114.statSync(fullPath);
125777
126534
  } catch {
125778
126535
  continue;
125779
126536
  }
125780
126537
  if (stat9.isDirectory()) {
125781
- findSourceFiles3(fullPath, files);
126538
+ findSourceFiles4(fullPath, files);
125782
126539
  } else if (stat9.isFile()) {
125783
126540
  if (isSupportedExtension(fullPath)) {
125784
126541
  files.push(fullPath);
@@ -125866,7 +126623,7 @@ var todo_extract = createSwarmTool({
125866
126623
  return JSON.stringify(errorResult, null, 2);
125867
126624
  }
125868
126625
  const scanPath = resolvedPath;
125869
- if (!fs113.existsSync(scanPath)) {
126626
+ if (!fs114.existsSync(scanPath)) {
125870
126627
  const errorResult = {
125871
126628
  error: `path not found: ${pathsInput}`,
125872
126629
  total: 0,
@@ -125876,13 +126633,13 @@ var todo_extract = createSwarmTool({
125876
126633
  return JSON.stringify(errorResult, null, 2);
125877
126634
  }
125878
126635
  const filesToScan = [];
125879
- const stat9 = fs113.statSync(scanPath);
126636
+ const stat9 = fs114.statSync(scanPath);
125880
126637
  if (stat9.isFile()) {
125881
126638
  if (isSupportedExtension(scanPath)) {
125882
126639
  filesToScan.push(scanPath);
125883
126640
  } else {
125884
126641
  const errorResult = {
125885
- error: `unsupported file extension: ${path155.extname(scanPath)}`,
126642
+ error: `unsupported file extension: ${path156.extname(scanPath)}`,
125886
126643
  total: 0,
125887
126644
  byPriority: { high: 0, medium: 0, low: 0 },
125888
126645
  entries: []
@@ -125890,16 +126647,16 @@ var todo_extract = createSwarmTool({
125890
126647
  return JSON.stringify(errorResult, null, 2);
125891
126648
  }
125892
126649
  } else {
125893
- findSourceFiles3(scanPath, filesToScan);
126650
+ findSourceFiles4(scanPath, filesToScan);
125894
126651
  }
125895
126652
  const allEntries = [];
125896
126653
  for (const filePath of filesToScan) {
125897
126654
  try {
125898
- const fileStat = fs113.statSync(filePath);
126655
+ const fileStat = fs114.statSync(filePath);
125899
126656
  if (fileStat.size > MAX_FILE_SIZE_BYTES11) {
125900
126657
  continue;
125901
126658
  }
125902
- const content = fs113.readFileSync(filePath, "utf-8");
126659
+ const content = fs114.readFileSync(filePath, "utf-8");
125903
126660
  const entries = parseTodoComments(content, filePath, tagsSet);
125904
126661
  allEntries.push(...entries);
125905
126662
  } catch {}
@@ -125931,18 +126688,18 @@ init_loader();
125931
126688
  init_schema();
125932
126689
  init_qa_gate_profile();
125933
126690
  init_gate_evidence();
125934
- import * as fs117 from "node:fs";
125935
- import * as path159 from "node:path";
126691
+ import * as fs118 from "node:fs";
126692
+ import * as path160 from "node:path";
125936
126693
 
125937
126694
  // src/hooks/diff-scope.ts
125938
126695
  init_bun_compat();
125939
- import * as fs115 from "node:fs";
125940
- import * as path157 from "node:path";
126696
+ import * as fs116 from "node:fs";
126697
+ import * as path158 from "node:path";
125941
126698
 
125942
126699
  // src/utils/gitignore-warning.ts
125943
126700
  init_bun_compat();
125944
- import * as fs114 from "node:fs";
125945
- import * as path156 from "node:path";
126701
+ import * as fs115 from "node:fs";
126702
+ import * as path157 from "node:path";
125946
126703
  var _internals67 = { bunSpawn };
125947
126704
  var _swarmGitExcludedChecked = false;
125948
126705
  function fileCoversSwarm(content) {
@@ -126016,16 +126773,16 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
126016
126773
  const excludeRelPath = excludePathRaw.trim();
126017
126774
  if (!excludeRelPath)
126018
126775
  return;
126019
- const excludePath = path156.isAbsolute(excludeRelPath) ? excludeRelPath : path156.join(directory, excludeRelPath);
126776
+ const excludePath = path157.isAbsolute(excludeRelPath) ? excludeRelPath : path157.join(directory, excludeRelPath);
126020
126777
  if (checkIgnoreExitCode !== 0) {
126021
126778
  try {
126022
- fs114.mkdirSync(path156.dirname(excludePath), { recursive: true });
126779
+ fs115.mkdirSync(path157.dirname(excludePath), { recursive: true });
126023
126780
  let existing = "";
126024
126781
  try {
126025
- existing = fs114.readFileSync(excludePath, "utf8");
126782
+ existing = fs115.readFileSync(excludePath, "utf8");
126026
126783
  } catch {}
126027
126784
  if (!fileCoversSwarm(existing)) {
126028
- fs114.appendFileSync(excludePath, `
126785
+ fs115.appendFileSync(excludePath, `
126029
126786
  # opencode-swarm local runtime state
126030
126787
  .swarm/
126031
126788
  `, "utf8");
@@ -126063,10 +126820,10 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
126063
126820
  var _internals68 = { bunSpawn };
126064
126821
  function getDeclaredScope(taskId, directory) {
126065
126822
  try {
126066
- const planPath = path157.join(directory, ".swarm", "plan.json");
126067
- if (!fs115.existsSync(planPath))
126823
+ const planPath = path158.join(directory, ".swarm", "plan.json");
126824
+ if (!fs116.existsSync(planPath))
126068
126825
  return null;
126069
- const raw = fs115.readFileSync(planPath, "utf-8");
126826
+ const raw = fs116.readFileSync(planPath, "utf-8");
126070
126827
  const plan = JSON.parse(raw);
126071
126828
  for (const phase of plan.phases ?? []) {
126072
126829
  for (const task of phase.tasks ?? []) {
@@ -126168,8 +126925,8 @@ init_telemetry();
126168
126925
 
126169
126926
  // src/turbo/lean/task-completion.ts
126170
126927
  init_file_locks();
126171
- import * as fs116 from "node:fs";
126172
- import * as path158 from "node:path";
126928
+ import * as fs117 from "node:fs";
126929
+ import * as path159 from "node:path";
126173
126930
  var _internals69 = {
126174
126931
  listActiveLocks,
126175
126932
  verifyLeanTurboTaskCompletion
@@ -126188,7 +126945,7 @@ var TIER_3_PATTERNS = [
126188
126945
  ];
126189
126946
  function matchesTier3Pattern(files) {
126190
126947
  for (const file3 of files) {
126191
- const fileName = path158.basename(file3);
126948
+ const fileName = path159.basename(file3);
126192
126949
  for (const pattern of TIER_3_PATTERNS) {
126193
126950
  if (pattern.test(fileName)) {
126194
126951
  return true;
@@ -126200,14 +126957,14 @@ function matchesTier3Pattern(files) {
126200
126957
  function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
126201
126958
  let persisted = null;
126202
126959
  try {
126203
- const statePath = path158.join(directory, ".swarm", "turbo-state.json");
126204
- if (!fs116.existsSync(statePath)) {
126960
+ const statePath = path159.join(directory, ".swarm", "turbo-state.json");
126961
+ if (!fs117.existsSync(statePath)) {
126205
126962
  return {
126206
126963
  ok: false,
126207
126964
  reason: "Lean Turbo state file not found"
126208
126965
  };
126209
126966
  }
126210
- const raw = fs116.readFileSync(statePath, "utf-8");
126967
+ const raw = fs117.readFileSync(statePath, "utf-8");
126211
126968
  persisted = JSON.parse(raw);
126212
126969
  } catch {
126213
126970
  return {
@@ -126284,11 +127041,11 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
126284
127041
  };
126285
127042
  }
126286
127043
  const phase = runState.phase ?? 0;
126287
- const evidencePath = path158.join(directory, ".swarm", "evidence", String(phase), "lean-turbo", `${lane.laneId}.json`);
126288
- const expectedDir = path158.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
126289
- const resolvedPath = path158.resolve(evidencePath);
126290
- const resolvedDir = path158.resolve(expectedDir);
126291
- if (!resolvedPath.startsWith(resolvedDir + path158.sep) && resolvedPath !== resolvedDir) {
127044
+ const evidencePath = path159.join(directory, ".swarm", "evidence", String(phase), "lean-turbo", `${lane.laneId}.json`);
127045
+ const expectedDir = path159.join(directory, ".swarm", "evidence", String(phase), "lean-turbo");
127046
+ const resolvedPath = path159.resolve(evidencePath);
127047
+ const resolvedDir = path159.resolve(expectedDir);
127048
+ if (!resolvedPath.startsWith(resolvedDir + path159.sep) && resolvedPath !== resolvedDir) {
126292
127049
  return {
126293
127050
  ok: false,
126294
127051
  reason: `Lane ID causes path traversal: ${lane.laneId}`,
@@ -126300,7 +127057,7 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
126300
127057
  }
126301
127058
  };
126302
127059
  }
126303
- if (!fs116.existsSync(evidencePath)) {
127060
+ if (!fs117.existsSync(evidencePath)) {
126304
127061
  return {
126305
127062
  ok: false,
126306
127063
  reason: `Lane ${lane.laneId} evidence file not found: ${evidencePath}`,
@@ -126328,8 +127085,8 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
126328
127085
  }
126329
127086
  let filesTouched = [];
126330
127087
  try {
126331
- const planPath = path158.join(directory, ".swarm", "plan.json");
126332
- const planRaw = fs116.readFileSync(planPath, "utf-8");
127088
+ const planPath = path159.join(directory, ".swarm", "plan.json");
127089
+ const planRaw = fs117.readFileSync(planPath, "utf-8");
126333
127090
  const plan = JSON.parse(planRaw);
126334
127091
  for (const planPhase of plan.phases ?? []) {
126335
127092
  for (const task of planPhase.tasks ?? []) {
@@ -126412,7 +127169,7 @@ var TIER_3_PATTERNS2 = [
126412
127169
  ];
126413
127170
  function matchesTier3Pattern2(files) {
126414
127171
  for (const file3 of files) {
126415
- const fileName = path159.basename(file3);
127172
+ const fileName = path160.basename(file3);
126416
127173
  for (const pattern of TIER_3_PATTERNS2) {
126417
127174
  if (pattern.test(fileName)) {
126418
127175
  return true;
@@ -126451,8 +127208,8 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
126451
127208
  if (!skipStandardTurboBypass && hasActiveTurboMode()) {
126452
127209
  const resolvedDir2 = workingDirectory;
126453
127210
  try {
126454
- const planPath = path159.join(resolvedDir2, ".swarm", "plan.json");
126455
- const planRaw = fs117.readFileSync(planPath, "utf-8");
127211
+ const planPath = path160.join(resolvedDir2, ".swarm", "plan.json");
127212
+ const planRaw = fs118.readFileSync(planPath, "utf-8");
126456
127213
  const plan = JSON.parse(planRaw);
126457
127214
  for (const planPhase of plan.phases ?? []) {
126458
127215
  for (const task of planPhase.tasks ?? []) {
@@ -126529,8 +127286,8 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
126529
127286
  }
126530
127287
  if (resolvedDir) {
126531
127288
  try {
126532
- const planPath = path159.join(resolvedDir, ".swarm", "plan.json");
126533
- const planRaw = fs117.readFileSync(planPath, "utf-8");
127289
+ const planPath = path160.join(resolvedDir, ".swarm", "plan.json");
127290
+ const planRaw = fs118.readFileSync(planPath, "utf-8");
126534
127291
  const plan = JSON.parse(planRaw);
126535
127292
  for (const planPhase of plan.phases ?? []) {
126536
127293
  for (const task of planPhase.tasks ?? []) {
@@ -126765,8 +127522,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
126765
127522
  };
126766
127523
  }
126767
127524
  directory = resolveResult.directory;
126768
- const planPath = path159.join(directory, ".swarm", "plan.json");
126769
- if (!fs117.existsSync(planPath)) {
127525
+ const planPath = path160.join(directory, ".swarm", "plan.json");
127526
+ if (!fs118.existsSync(planPath)) {
126770
127527
  return {
126771
127528
  success: false,
126772
127529
  message: `Invalid working_directory: plan not found in "${directory}"`,
@@ -126774,9 +127531,9 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
126774
127531
  };
126775
127532
  }
126776
127533
  if (fallbackDir && directory !== fallbackDir) {
126777
- const canonicalDir = fs117.realpathSync(path159.resolve(directory));
126778
- const canonicalRoot = fs117.realpathSync(path159.resolve(fallbackDir));
126779
- if (canonicalDir.startsWith(canonicalRoot + path159.sep)) {
127534
+ const canonicalDir = fs118.realpathSync(path160.resolve(directory));
127535
+ const canonicalRoot = fs118.realpathSync(path160.resolve(fallbackDir));
127536
+ if (canonicalDir.startsWith(canonicalRoot + path160.sep)) {
126780
127537
  return {
126781
127538
  success: false,
126782
127539
  message: `Invalid working_directory: "${directory}" is a subdirectory of ` + `the project root "${fallbackDir}". Pass the project root path or ` + `omit working_directory entirely.`,
@@ -126788,22 +127545,22 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
126788
127545
  }
126789
127546
  if (args2.status === "in_progress") {
126790
127547
  try {
126791
- const evidencePath = path159.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
126792
- fs117.mkdirSync(path159.dirname(evidencePath), { recursive: true });
126793
- const fd = fs117.openSync(evidencePath, "wx");
127548
+ const evidencePath = path160.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
127549
+ fs118.mkdirSync(path160.dirname(evidencePath), { recursive: true });
127550
+ const fd = fs118.openSync(evidencePath, "wx");
126794
127551
  let writeOk = false;
126795
127552
  try {
126796
- fs117.writeSync(fd, JSON.stringify({
127553
+ fs118.writeSync(fd, JSON.stringify({
126797
127554
  taskId: args2.task_id,
126798
127555
  required_gates: [],
126799
127556
  gates: {}
126800
127557
  }, null, 2));
126801
127558
  writeOk = true;
126802
127559
  } finally {
126803
- fs117.closeSync(fd);
127560
+ fs118.closeSync(fd);
126804
127561
  if (!writeOk) {
126805
127562
  try {
126806
- fs117.unlinkSync(evidencePath);
127563
+ fs118.unlinkSync(evidencePath);
126807
127564
  } catch {}
126808
127565
  }
126809
127566
  }
@@ -126813,8 +127570,8 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
126813
127570
  recoverTaskStateFromDelegations(args2.task_id, directory);
126814
127571
  let phaseRequiresReviewer = true;
126815
127572
  try {
126816
- const planPath2 = path159.join(directory, ".swarm", "plan.json");
126817
- const planRaw = fs117.readFileSync(planPath2, "utf-8");
127573
+ const planPath2 = path160.join(directory, ".swarm", "plan.json");
127574
+ const planRaw = fs118.readFileSync(planPath2, "utf-8");
126818
127575
  const plan = JSON.parse(planRaw);
126819
127576
  const taskPhase = plan.phases.find((p) => p.tasks.some((t) => t.id === args2.task_id));
126820
127577
  if (taskPhase?.required_agents && !taskPhase.required_agents.includes("reviewer")) {
@@ -127042,7 +127799,7 @@ init_utils2();
127042
127799
  init_redaction();
127043
127800
  import { createHash as createHash12 } from "node:crypto";
127044
127801
  import { appendFile as appendFile14, mkdir as mkdir25 } from "node:fs/promises";
127045
- import * as path160 from "node:path";
127802
+ import * as path161 from "node:path";
127046
127803
  var EVIDENCE_CACHE_FILE = "evidence-cache/documents.jsonl";
127047
127804
  var MAX_EVIDENCE_TEXT_LENGTH = 4000;
127048
127805
  async function writeEvidenceDocuments(directory, inputs, now = () => new Date) {
@@ -127050,7 +127807,7 @@ async function writeEvidenceDocuments(directory, inputs, now = () => new Date) {
127050
127807
  const capturedAt = now().toISOString();
127051
127808
  const records = inputs.map((input) => createEvidenceDocumentRecord(input, capturedAt)).filter((record3) => record3 !== null);
127052
127809
  if (records.length > 0) {
127053
- await mkdir25(path160.dirname(filePath), { recursive: true });
127810
+ await mkdir25(path161.dirname(filePath), { recursive: true });
127054
127811
  await appendFile14(filePath, `${records.map((record3) => JSON.stringify(record3)).join(`
127055
127812
  `)}
127056
127813
  `, "utf-8");
@@ -127247,7 +128004,7 @@ init_schema3();
127247
128004
  init_store();
127248
128005
  init_create_tool();
127249
128006
  init_resolve_working_directory();
127250
- import * as path161 from "node:path";
128007
+ import * as path162 from "node:path";
127251
128008
  var FindingSchema2 = exports_external.object({
127252
128009
  severity: exports_external.enum(["low", "medium", "high", "critical"]),
127253
128010
  category: exports_external.string().min(1),
@@ -127311,7 +128068,7 @@ var write_architecture_supervisor_evidence = createSwarmTool({
127311
128068
  if (config3.architectural_supervision?.persist_knowledge_recommendations && args2.knowledge_recommendations.length > 0) {
127312
128069
  const knowledgeConfig = KnowledgeConfigSchema.parse(config3.knowledge ?? {});
127313
128070
  const lessons = args2.knowledge_recommendations.map((r) => r.lesson);
127314
- const result = await curateAndStoreSwarm(lessons, path161.basename(dirResult.directory), { phase_number: args2.phase }, dirResult.directory, knowledgeConfig, { skipAutoPromotion: true });
128071
+ const result = await curateAndStoreSwarm(lessons, path162.basename(dirResult.directory), { phase_number: args2.phase }, dirResult.directory, knowledgeConfig, { skipAutoPromotion: true });
127315
128072
  knowledgeProposed = result.stored;
127316
128073
  }
127317
128074
  } catch {}
@@ -127346,8 +128103,8 @@ init_utils2();
127346
128103
  init_ledger();
127347
128104
  init_manager();
127348
128105
  init_create_tool();
127349
- import fs118 from "node:fs";
127350
- import path162 from "node:path";
128106
+ import fs119 from "node:fs";
128107
+ import path163 from "node:path";
127351
128108
  function normalizeVerdict(verdict) {
127352
128109
  switch (verdict) {
127353
128110
  case "APPROVED":
@@ -127395,7 +128152,7 @@ async function executeWriteDriftEvidence(args2, directory) {
127395
128152
  entries: [evidenceEntry]
127396
128153
  };
127397
128154
  const filename = "drift-verifier.json";
127398
- const relativePath = path162.join("evidence", String(phase), filename);
128155
+ const relativePath = path163.join("evidence", String(phase), filename);
127399
128156
  let validatedPath;
127400
128157
  try {
127401
128158
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -127406,12 +128163,12 @@ async function executeWriteDriftEvidence(args2, directory) {
127406
128163
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
127407
128164
  }, null, 2);
127408
128165
  }
127409
- const evidenceDir = path162.dirname(validatedPath);
128166
+ const evidenceDir = path163.dirname(validatedPath);
127410
128167
  try {
127411
- await fs118.promises.mkdir(evidenceDir, { recursive: true });
127412
- const tempPath = path162.join(evidenceDir, `.${filename}.tmp`);
127413
- await fs118.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
127414
- await fs118.promises.rename(tempPath, validatedPath);
128168
+ await fs119.promises.mkdir(evidenceDir, { recursive: true });
128169
+ const tempPath = path163.join(evidenceDir, `.${filename}.tmp`);
128170
+ await fs119.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
128171
+ await fs119.promises.rename(tempPath, validatedPath);
127415
128172
  let snapshotInfo;
127416
128173
  let snapshotError;
127417
128174
  let qaProfileLocked;
@@ -127505,8 +128262,8 @@ var write_drift_evidence = createSwarmTool({
127505
128262
  // src/tools/write-final-council-evidence.ts
127506
128263
  init_zod();
127507
128264
  init_loader();
127508
- import fs119 from "node:fs";
127509
- import path163 from "node:path";
128265
+ import fs120 from "node:fs";
128266
+ import path164 from "node:path";
127510
128267
  init_utils2();
127511
128268
  init_manager();
127512
128269
  init_create_tool();
@@ -127594,7 +128351,7 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
127594
128351
  timestamp: synthesis.timestamp
127595
128352
  };
127596
128353
  const filename = "final-council.json";
127597
- const relativePath = path163.join("evidence", filename);
128354
+ const relativePath = path164.join("evidence", filename);
127598
128355
  let validatedPath;
127599
128356
  try {
127600
128357
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -127608,12 +128365,12 @@ async function executeWriteFinalCouncilEvidence(args2, directory) {
127608
128365
  const evidenceContent = {
127609
128366
  entries: [evidenceEntry]
127610
128367
  };
127611
- const evidenceDir = path163.dirname(validatedPath);
128368
+ const evidenceDir = path164.dirname(validatedPath);
127612
128369
  try {
127613
- await fs119.promises.mkdir(evidenceDir, { recursive: true });
127614
- const tempPath = path163.join(evidenceDir, `.${filename}.tmp`);
127615
- await fs119.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
127616
- await fs119.promises.rename(tempPath, validatedPath);
128370
+ await fs120.promises.mkdir(evidenceDir, { recursive: true });
128371
+ const tempPath = path164.join(evidenceDir, `.${filename}.tmp`);
128372
+ await fs120.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
128373
+ await fs120.promises.rename(tempPath, validatedPath);
127617
128374
  return JSON.stringify({
127618
128375
  success: true,
127619
128376
  phase: input.phase,
@@ -127670,8 +128427,8 @@ var write_final_council_evidence = createSwarmTool({
127670
128427
  init_zod();
127671
128428
  init_utils2();
127672
128429
  init_create_tool();
127673
- import fs120 from "node:fs";
127674
- import path164 from "node:path";
128430
+ import fs121 from "node:fs";
128431
+ import path165 from "node:path";
127675
128432
  function normalizeVerdict2(verdict) {
127676
128433
  switch (verdict) {
127677
128434
  case "APPROVED":
@@ -127719,7 +128476,7 @@ async function executeWriteHallucinationEvidence(args2, directory) {
127719
128476
  entries: [evidenceEntry]
127720
128477
  };
127721
128478
  const filename = "hallucination-guard.json";
127722
- const relativePath = path164.join("evidence", String(phase), filename);
128479
+ const relativePath = path165.join("evidence", String(phase), filename);
127723
128480
  let validatedPath;
127724
128481
  try {
127725
128482
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -127730,12 +128487,12 @@ async function executeWriteHallucinationEvidence(args2, directory) {
127730
128487
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
127731
128488
  }, null, 2);
127732
128489
  }
127733
- const evidenceDir = path164.dirname(validatedPath);
128490
+ const evidenceDir = path165.dirname(validatedPath);
127734
128491
  try {
127735
- await fs120.promises.mkdir(evidenceDir, { recursive: true });
127736
- const tempPath = path164.join(evidenceDir, `.${filename}.tmp`);
127737
- await fs120.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
127738
- await fs120.promises.rename(tempPath, validatedPath);
128492
+ await fs121.promises.mkdir(evidenceDir, { recursive: true });
128493
+ const tempPath = path165.join(evidenceDir, `.${filename}.tmp`);
128494
+ await fs121.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
128495
+ await fs121.promises.rename(tempPath, validatedPath);
127739
128496
  return JSON.stringify({
127740
128497
  success: true,
127741
128498
  phase,
@@ -127782,8 +128539,8 @@ var write_hallucination_evidence = createSwarmTool({
127782
128539
  init_zod();
127783
128540
  init_utils2();
127784
128541
  init_create_tool();
127785
- import fs121 from "node:fs";
127786
- import path165 from "node:path";
128542
+ import fs122 from "node:fs";
128543
+ import path166 from "node:path";
127787
128544
  function normalizeVerdict3(verdict) {
127788
128545
  switch (verdict) {
127789
128546
  case "PASS":
@@ -127857,7 +128614,7 @@ async function executeWriteMutationEvidence(args2, directory) {
127857
128614
  entries: [evidenceEntry]
127858
128615
  };
127859
128616
  const filename = "mutation-gate.json";
127860
- const relativePath = path165.join("evidence", String(phase), filename);
128617
+ const relativePath = path166.join("evidence", String(phase), filename);
127861
128618
  let validatedPath;
127862
128619
  try {
127863
128620
  validatedPath = validateSwarmPath(directory, relativePath);
@@ -127868,12 +128625,12 @@ async function executeWriteMutationEvidence(args2, directory) {
127868
128625
  message: error93 instanceof Error ? error93.message : "Failed to validate path"
127869
128626
  }, null, 2);
127870
128627
  }
127871
- const evidenceDir = path165.dirname(validatedPath);
128628
+ const evidenceDir = path166.dirname(validatedPath);
127872
128629
  try {
127873
- await fs121.promises.mkdir(evidenceDir, { recursive: true });
127874
- const tempPath = path165.join(evidenceDir, `.${filename}.tmp`);
127875
- await fs121.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
127876
- await fs121.promises.rename(tempPath, validatedPath);
128630
+ await fs122.promises.mkdir(evidenceDir, { recursive: true });
128631
+ const tempPath = path166.join(evidenceDir, `.${filename}.tmp`);
128632
+ await fs122.promises.writeFile(tempPath, JSON.stringify(evidenceContent, null, 2), "utf-8");
128633
+ await fs122.promises.rename(tempPath, validatedPath);
127877
128634
  return JSON.stringify({
127878
128635
  success: true,
127879
128636
  phase,
@@ -127955,6 +128712,7 @@ var TOOL_MANIFEST = defineHandlers({
127955
128712
  mutation_test: () => mutation_test,
127956
128713
  generate_mutants: () => generate_mutants,
127957
128714
  detect_domains: () => detect_domains,
128715
+ git_blame: () => git_blame,
127958
128716
  gitingest: () => gitingest,
127959
128717
  retrieve_summary: () => retrieve_summary,
127960
128718
  extract_code_blocks: () => extract_code_blocks,
@@ -128319,7 +129077,7 @@ async function initializeOpenCodeSwarm(ctx) {
128319
129077
  const { PreflightTriggerManager: PTM } = await Promise.resolve().then(() => (init_trigger(), exports_trigger));
128320
129078
  preflightTriggerManager = new PTM(automationConfig);
128321
129079
  const { AutomationStatusArtifact: ASA } = await Promise.resolve().then(() => (init_status_artifact(), exports_status_artifact));
128322
- const swarmDir = path167.resolve(ctx.directory, ".swarm");
129080
+ const swarmDir = path168.resolve(ctx.directory, ".swarm");
128323
129081
  statusArtifact = new ASA(swarmDir);
128324
129082
  statusArtifact.updateConfig(automationConfig.mode, automationConfig.capabilities);
128325
129083
  if (automationConfig.capabilities?.evidence_auto_summaries === true) {
@@ -128833,7 +129591,7 @@ ${promptRaw}`;
128833
129591
  const meta3 = readSkillMetadata(s.skillPath, ctx.directory);
128834
129592
  let desc = meta3.description || "";
128835
129593
  if (!desc || desc === "No description provided") {
128836
- desc = path167.basename(path167.dirname(s.skillPath));
129594
+ desc = path168.basename(path168.dirname(s.skillPath));
128837
129595
  }
128838
129596
  desc = desc.replace(/,/g, ";");
128839
129597
  return `file:${s.skillPath} (-- ${desc})`;
@@ -128843,7 +129601,7 @@ ${promptRaw}`;
128843
129601
 
128844
129602
  ${promptRaw}`;
128845
129603
  argsRecord.prompt = newPrompt;
128846
- const skillNames = topSkills.map((s) => `${path167.basename(s.skillPath)} (score: ${s.score.toFixed(2)})`).join(", ");
129604
+ const skillNames = topSkills.map((s) => `${path168.basename(s.skillPath)} (score: ${s.score.toFixed(2)})`).join(", ");
128847
129605
  console.warn(`[skill-propagation-gate] Injected skills: ${skillNames}`);
128848
129606
  for (const skill of topSkills) {
128849
129607
  try {