opencode-swarm 7.25.0 → 7.25.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -33,7 +33,7 @@ var package_default;
33
33
  var init_package = __esm(() => {
34
34
  package_default = {
35
35
  name: "opencode-swarm",
36
- version: "7.25.0",
36
+ version: "7.25.2",
37
37
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
38
38
  main: "dist/index.js",
39
39
  types: "dist/index.d.ts",
@@ -20612,7 +20612,13 @@ var init_task_id = __esm(() => {
20612
20612
  });
20613
20613
 
20614
20614
  // src/evidence/manager.ts
20615
- import { mkdirSync as mkdirSync4, readdirSync as readdirSync3, rmSync, statSync as statSync5 } from "node:fs";
20615
+ import {
20616
+ mkdirSync as mkdirSync4,
20617
+ readdirSync as readdirSync3,
20618
+ realpathSync,
20619
+ rmSync,
20620
+ statSync as statSync5
20621
+ } from "node:fs";
20616
20622
  import * as fs6 from "node:fs/promises";
20617
20623
  import * as path8 from "node:path";
20618
20624
  function isValidEvidenceType(type) {
@@ -20621,7 +20627,35 @@ function isValidEvidenceType(type) {
20621
20627
  function isSecretscanEvidence(evidence) {
20622
20628
  return evidence.type === "secretscan";
20623
20629
  }
20630
+ function validateProjectRoot(directory) {
20631
+ let resolved;
20632
+ try {
20633
+ resolved = realpathSync(directory);
20634
+ } catch {
20635
+ warn(`[evidence] Cannot canonicalize directory "${directory}" — failing closed`);
20636
+ throw new Error(`Cannot verify project root for "${directory}" — directory may not exist or is inaccessible`);
20637
+ }
20638
+ let current = resolved;
20639
+ while (true) {
20640
+ const parent = path8.dirname(current);
20641
+ if (parent === current)
20642
+ break;
20643
+ const parentSwarm = path8.join(parent, ".swarm");
20644
+ try {
20645
+ if (statSync5(parentSwarm).isDirectory()) {
20646
+ warn(`[evidence] Rejecting write to subdirectory "${resolved}" — parent "${parent}" already contains .swarm/`);
20647
+ throw new Error(`Cannot write evidence in "${resolved}" — parent directory "${parent}" already contains a .swarm/ folder. Evidence must be written to the project root.`);
20648
+ }
20649
+ } catch (error49) {
20650
+ if (error49 instanceof Error && error49.message.startsWith("Cannot write evidence")) {
20651
+ throw error49;
20652
+ }
20653
+ }
20654
+ current = parent;
20655
+ }
20656
+ }
20624
20657
  async function saveEvidence(directory, taskId, evidence) {
20658
+ _internals8.validateProjectRoot(directory);
20625
20659
  const sanitizedTaskId = sanitizeTaskId2(taskId);
20626
20660
  const relativePath = path8.join("evidence", sanitizedTaskId, "evidence.json");
20627
20661
  validateSwarmPath(directory, relativePath);
@@ -20886,7 +20920,8 @@ var init_manager2 = __esm(() => {
20886
20920
  _internals8 = {
20887
20921
  wrapFlatRetrospective,
20888
20922
  loadEvidence,
20889
- listEvidenceTaskIds
20923
+ listEvidenceTaskIds,
20924
+ validateProjectRoot
20890
20925
  };
20891
20926
  });
20892
20927
 
@@ -48735,7 +48770,9 @@ __export(exports_config_doctor, {
48735
48770
  runConfigDoctorWithFixes: () => runConfigDoctorWithFixes,
48736
48771
  runConfigDoctor: () => runConfigDoctor,
48737
48772
  restoreFromBackup: () => restoreFromBackup,
48773
+ removeStraySwarmDir: () => removeStraySwarmDir,
48738
48774
  getConfigPaths: () => getConfigPaths,
48775
+ detectStraySwarmDirs: () => detectStraySwarmDirs,
48739
48776
  createConfigBackup: () => createConfigBackup,
48740
48777
  applySafeAutoFixes: () => applySafeAutoFixes
48741
48778
  });
@@ -49351,6 +49388,114 @@ async function runConfigDoctorWithFixes(directory, config3, autoFix = false) {
49351
49388
  artifactPath
49352
49389
  };
49353
49390
  }
49391
+ function detectStraySwarmDirs(projectRoot) {
49392
+ const findings = [];
49393
+ const SKIP_DIRS = new Set([
49394
+ "node_modules",
49395
+ ".git",
49396
+ "dist",
49397
+ ".cache",
49398
+ ".next",
49399
+ "coverage",
49400
+ ".turbo",
49401
+ ".vercel",
49402
+ ".terraform",
49403
+ "__pycache__",
49404
+ ".tox"
49405
+ ]);
49406
+ const MAX_DEPTH = 10;
49407
+ const MAX_CONTENTS_ENTRIES = 20;
49408
+ function walk(dir, depth) {
49409
+ if (depth > MAX_DEPTH)
49410
+ return;
49411
+ let entries;
49412
+ try {
49413
+ entries = fs14.readdirSync(dir, { withFileTypes: true });
49414
+ } catch {
49415
+ return;
49416
+ }
49417
+ for (const entry of entries) {
49418
+ if (!entry.isDirectory())
49419
+ continue;
49420
+ const name2 = entry.name;
49421
+ const fullPath = path29.join(dir, name2);
49422
+ if (SKIP_DIRS.has(name2))
49423
+ continue;
49424
+ const gitPath = path29.join(fullPath, ".git");
49425
+ try {
49426
+ const gitStat = fs14.statSync(gitPath);
49427
+ if (gitStat.isFile() || gitStat.isDirectory())
49428
+ continue;
49429
+ } catch {}
49430
+ if (name2 === ".swarm") {
49431
+ const parentDir = path29.dirname(fullPath);
49432
+ if (parentDir === projectRoot)
49433
+ continue;
49434
+ let contents = [];
49435
+ try {
49436
+ contents = fs14.readdirSync(fullPath);
49437
+ } catch {
49438
+ contents = ["<unreadable>"];
49439
+ }
49440
+ findings.push({
49441
+ path: path29.relative(projectRoot, fullPath).replace(/\\/g, "/"),
49442
+ absolutePath: fullPath,
49443
+ contents: contents.slice(0, MAX_CONTENTS_ENTRIES),
49444
+ totalEntries: contents.length
49445
+ });
49446
+ continue;
49447
+ }
49448
+ walk(fullPath, depth + 1);
49449
+ }
49450
+ }
49451
+ walk(projectRoot, 0);
49452
+ return findings;
49453
+ }
49454
+ function removeStraySwarmDir(projectRoot, strayPath) {
49455
+ let canonicalRoot;
49456
+ let canonicalStray;
49457
+ try {
49458
+ canonicalRoot = fs14.realpathSync(projectRoot);
49459
+ canonicalStray = fs14.realpathSync(path29.isAbsolute(strayPath) ? strayPath : path29.resolve(projectRoot, strayPath));
49460
+ } catch (err2) {
49461
+ return {
49462
+ success: false,
49463
+ message: `Failed to resolve paths: ${err2 instanceof Error ? err2.message : String(err2)}`
49464
+ };
49465
+ }
49466
+ const rootSwarm = path29.join(canonicalRoot, ".swarm");
49467
+ if (canonicalStray === rootSwarm || canonicalStray === canonicalRoot) {
49468
+ return {
49469
+ success: false,
49470
+ message: "Refusing to remove root .swarm/ directory"
49471
+ };
49472
+ }
49473
+ if (!canonicalStray.startsWith(canonicalRoot + path29.sep)) {
49474
+ return {
49475
+ success: false,
49476
+ message: "Path is outside project root — refusing to remove"
49477
+ };
49478
+ }
49479
+ const normalizedStray = canonicalStray.replace(/\\/g, "/");
49480
+ if (!normalizedStray.endsWith("/.swarm")) {
49481
+ return {
49482
+ success: false,
49483
+ message: "Path is not a .swarm directory — refusing to remove"
49484
+ };
49485
+ }
49486
+ try {
49487
+ fs14.rmSync(canonicalStray, { recursive: true, force: true });
49488
+ return {
49489
+ success: true,
49490
+ message: `Removed stray .swarm directory: ${canonicalStray}`
49491
+ };
49492
+ } catch (err2) {
49493
+ return {
49494
+ success: false,
49495
+ message: `Failed to remove: ${err2 instanceof Error ? err2.message : String(err2)}`
49496
+ };
49497
+ }
49498
+ }
49354
49499
  var VALID_CONFIG_PATTERNS, DANGEROUS_PATH_SEGMENTS;
49355
49500
  var init_config_doctor = __esm(() => {
49356
49501
  init_utils();
@@ -51061,12 +51206,62 @@ async function handleDoctorCommand(directory, args2) {
51061
51206
  const enableAutoFix = args2.includes("--fix") || args2.includes("-f");
51062
51207
  const config3 = loadPluginConfig(directory);
51063
51208
  const result = runConfigDoctor(config3, directory);
51209
+ let output;
51064
51210
  if (enableAutoFix && result.hasAutoFixableIssues) {
51065
51211
  const { runConfigDoctorWithFixes: runConfigDoctorWithFixes2 } = await Promise.resolve().then(() => (init_config_doctor(), exports_config_doctor));
51066
51212
  const fixResult = await runConfigDoctorWithFixes2(directory, config3, true);
51067
- return formatDoctorMarkdown(fixResult.result);
51213
+ output = formatDoctorMarkdown(fixResult.result);
51214
+ } else {
51215
+ output = formatDoctorMarkdown(result);
51068
51216
  }
51069
- return formatDoctorMarkdown(result);
51217
+ const strayDirs = detectStraySwarmDirs(directory);
51218
+ if (strayDirs.length > 0) {
51219
+ if (enableAutoFix) {
51220
+ let fixOutput = `
51221
+ ---
51222
+
51223
+ ## Stray .swarm Directories
51224
+
51225
+ `;
51226
+ let removed = 0;
51227
+ let failed = 0;
51228
+ for (const finding of strayDirs) {
51229
+ const cleanupResult = removeStraySwarmDir(directory, finding.path);
51230
+ if (cleanupResult.success) {
51231
+ removed++;
51232
+ } else {
51233
+ failed++;
51234
+ fixOutput += `- \`${finding.path}\`: ${cleanupResult.message}
51235
+ `;
51236
+ }
51237
+ }
51238
+ fixOutput += `
51239
+ Cleaned up ${removed} stray director${removed === 1 ? "y" : "ies"}.`;
51240
+ if (failed > 0) {
51241
+ fixOutput += ` ${failed} could not be removed.`;
51242
+ }
51243
+ output += fixOutput;
51244
+ } else {
51245
+ output += `
51246
+ ---
51247
+
51248
+ ## Stray .swarm Directories
51249
+
51250
+ `;
51251
+ output += `Found ${strayDirs.length} stray .swarm director${strayDirs.length === 1 ? "y" : "ies"} in subdirectories:
51252
+
51253
+ `;
51254
+ for (const finding of strayDirs) {
51255
+ const contentsPreview = finding.contents.length > 5 ? `${finding.contents.slice(0, 5).join(", ")}, ...` : finding.contents.join(", ");
51256
+ output += `- \`${finding.path}\` (${finding.totalEntries} entries: ${contentsPreview})
51257
+ `;
51258
+ }
51259
+ output += `
51260
+ These are likely from a prior bug (Issue #922). `;
51261
+ output += "Re-run with `--fix` to auto-clean.\n";
51262
+ }
51263
+ }
51264
+ return output;
51070
51265
  }
51071
51266
  async function handleDoctorToolsCommand(directory, _args) {
51072
51267
  const result = runToolDoctor(directory);
@@ -55890,6 +56085,10 @@ async function loadImpactMap(cwd, options) {
55890
56085
  return _internals29.buildImpactMap(cwd);
55891
56086
  }
55892
56087
  async function saveImpactMap(cwd, impactMap) {
56088
+ if (!path41.isAbsolute(cwd)) {
56089
+ throw new Error(`saveImpactMap requires an absolute project root path, got: "${cwd}"`);
56090
+ }
56091
+ _internals29.validateProjectRoot(cwd);
55893
56092
  const cacheDir2 = path41.join(cwd, ".swarm", "cache");
55894
56093
  const cachePath = path41.join(cacheDir2, "impact-map.json");
55895
56094
  if (!fs24.existsSync(cacheDir2)) {
@@ -55982,6 +56181,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
55982
56181
  }
55983
56182
  var IMPORT_REGEX_ES, IMPORT_REGEX_REQUIRE, IMPORT_REGEX_REEXPORT, TS_EXTENSIONS, PYTHON_EXTENSIONS, GO_EXTENSIONS, EXTENSIONS_TO_TRY, goModuleCache, _internals29;
55984
56183
  var init_analyzer = __esm(() => {
56184
+ init_manager2();
55985
56185
  init_go();
55986
56186
  init_python();
55987
56187
  IMPORT_REGEX_ES = /import\s+[\s\S]*?\s+from\s+['"]([^'"]+)['"]/g;
@@ -55993,6 +56193,7 @@ var init_analyzer = __esm(() => {
55993
56193
  EXTENSIONS_TO_TRY = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
55994
56194
  goModuleCache = new Map;
55995
56195
  _internals29 = {
56196
+ validateProjectRoot,
55996
56197
  normalizePath,
55997
56198
  isCacheStale,
55998
56199
  resolveRelativeImport,
@@ -56216,7 +56417,13 @@ var FLAKY_THRESHOLD = 0.3, MIN_RUNS_FOR_QUARANTINE = 5, MAX_HISTORY_RUNS = 20;
56216
56417
  import fs25 from "node:fs";
56217
56418
  import path42 from "node:path";
56218
56419
  function getHistoryPath(workingDir) {
56219
- return path42.join(workingDir || process.cwd(), ".swarm", "cache", "test-history.jsonl");
56420
+ if (!workingDir) {
56421
+ throw new Error("getHistoryPath requires a working directory — project root must be provided by the caller");
56422
+ }
56423
+ if (!path42.isAbsolute(workingDir)) {
56424
+ throw new Error(`getHistoryPath requires an absolute project root path, got: "${workingDir}"`);
56425
+ }
56426
+ return path42.join(workingDir, ".swarm", "cache", "test-history.jsonl");
56220
56427
  }
56221
56428
  function sanitizeErrorMessage(errorMessage) {
56222
56429
  if (errorMessage === undefined) {
@@ -56308,6 +56515,7 @@ function appendTestRun(record3, workingDir) {
56308
56515
  };
56309
56516
  const historyPath = getHistoryPath(workingDir);
56310
56517
  const historyDir = path42.dirname(historyPath);
56518
+ _internals30.validateProjectRoot(workingDir);
56311
56519
  if (!fs25.existsSync(historyDir)) {
56312
56520
  fs25.mkdirSync(historyDir, { recursive: true });
56313
56521
  }
@@ -56379,13 +56587,17 @@ function getAllHistory(workingDir) {
56379
56587
  records.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
56380
56588
  return records;
56381
56589
  }
56382
- var MAX_HISTORY_PER_TEST = 20, MAX_ERROR_LENGTH = 500, MAX_STACK_LENGTH = 200, MAX_CHANGED_FILES = 50, DANGEROUS_PROPERTY_NAMES;
56590
+ var MAX_HISTORY_PER_TEST = 20, MAX_ERROR_LENGTH = 500, MAX_STACK_LENGTH = 200, MAX_CHANGED_FILES = 50, DANGEROUS_PROPERTY_NAMES, _internals30;
56383
56591
  var init_history_store = __esm(() => {
56592
+ init_manager2();
56384
56593
  DANGEROUS_PROPERTY_NAMES = new Set([
56385
56594
  "__proto__",
56386
56595
  "constructor",
56387
56596
  "prototype"
56388
56597
  ]);
56598
+ _internals30 = {
56599
+ validateProjectRoot
56600
+ };
56389
56601
  });
56390
56602
 
56391
56603
  // src/tools/resolve-working-directory.ts
@@ -56509,7 +56721,7 @@ function readPackageJsonRaw(dir) {
56509
56721
  }
56510
56722
  }
56511
56723
  function readPackageJson(dir) {
56512
- return _internals30.readPackageJsonRaw(dir);
56724
+ return _internals31.readPackageJsonRaw(dir);
56513
56725
  }
56514
56726
  function readPackageJsonTestScript(dir) {
56515
56727
  return readPackageJson(dir)?.scripts?.test ?? null;
@@ -56679,7 +56891,7 @@ function buildTypescriptBackend() {
56679
56891
  selectEntryPoints: selectEntryPoints3
56680
56892
  };
56681
56893
  }
56682
- var PROFILE_ID3 = "typescript", IMPORT_REGEX_ES2, IMPORT_REGEX_BARE, IMPORT_REGEX_REQUIRE2, IMPORT_REGEX_DYNAMIC, IMPORT_REGEX_REEXPORT2, _internals30;
56894
+ var PROFILE_ID3 = "typescript", IMPORT_REGEX_ES2, IMPORT_REGEX_BARE, IMPORT_REGEX_REQUIRE2, IMPORT_REGEX_DYNAMIC, IMPORT_REGEX_REEXPORT2, _internals31;
56683
56895
  var init_typescript = __esm(() => {
56684
56896
  init_default_backend();
56685
56897
  init_profiles();
@@ -56688,7 +56900,7 @@ var init_typescript = __esm(() => {
56688
56900
  IMPORT_REGEX_REQUIRE2 = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
56689
56901
  IMPORT_REGEX_DYNAMIC = /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
56690
56902
  IMPORT_REGEX_REEXPORT2 = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
56691
- _internals30 = {
56903
+ _internals31 = {
56692
56904
  readPackageJsonRaw,
56693
56905
  readPackageJsonTestScript,
56694
56906
  frameworkFromScriptsTest
@@ -56719,7 +56931,7 @@ __export(exports_dispatch, {
56719
56931
  pickedProfiles: () => pickedProfiles,
56720
56932
  pickBackend: () => pickBackend,
56721
56933
  clearDispatchCache: () => clearDispatchCache,
56722
- _internals: () => _internals31
56934
+ _internals: () => _internals32
56723
56935
  });
56724
56936
  import * as fs28 from "node:fs";
56725
56937
  import * as path45 from "node:path";
@@ -56774,7 +56986,7 @@ function findManifestRoot(start2) {
56774
56986
  return start2;
56775
56987
  }
56776
56988
  function evictIfNeeded() {
56777
- if (cache.size <= _internals31.cacheCapacity)
56989
+ if (cache.size <= _internals32.cacheCapacity)
56778
56990
  return;
56779
56991
  let oldestKey;
56780
56992
  let oldestOrder = Infinity;
@@ -56805,7 +57017,7 @@ async function pickBackend(dir) {
56805
57017
  evictIfNeeded();
56806
57018
  return null;
56807
57019
  }
56808
- const profiles = await _internals31.detectProjectLanguages(root);
57020
+ const profiles = await _internals32.detectProjectLanguages(root);
56809
57021
  if (profiles.length === 0) {
56810
57022
  cache.set(cacheKey, {
56811
57023
  hash: hash3,
@@ -56837,12 +57049,12 @@ function clearDispatchCache() {
56837
57049
  manifestRootCache.clear();
56838
57050
  insertCounter = 0;
56839
57051
  }
56840
- var _internals31, cache, insertCounter = 0, MANIFEST_FILES, _MANIFEST_SET, manifestRootCache;
57052
+ var _internals32, cache, insertCounter = 0, MANIFEST_FILES, _MANIFEST_SET, manifestRootCache;
56841
57053
  var init_dispatch = __esm(() => {
56842
57054
  init_backends();
56843
57055
  init_detector();
56844
57056
  init_registry_backend();
56845
- _internals31 = {
57057
+ _internals32 = {
56846
57058
  detectProjectLanguages,
56847
57059
  cacheCapacity: 64
56848
57060
  };
@@ -58040,11 +58252,11 @@ function normalizeHistoryTestFile(testFile, workingDir) {
58040
58252
  const normalized = testFile.replace(/\\/g, "/");
58041
58253
  if (!path46.isAbsolute(testFile))
58042
58254
  return normalized;
58043
- const relative9 = path46.relative(workingDir, testFile);
58044
- if (relative9.startsWith("..") || path46.isAbsolute(relative9)) {
58255
+ const relative10 = path46.relative(workingDir, testFile);
58256
+ if (relative10.startsWith("..") || path46.isAbsolute(relative10)) {
58045
58257
  return normalized;
58046
58258
  }
58047
- return relative9.replace(/\\/g, "/");
58259
+ return relative10.replace(/\\/g, "/");
58048
58260
  }
58049
58261
  function combineAggregateResult(current, next) {
58050
58262
  if (current === "fail" || next === "fail")
@@ -58677,9 +58889,9 @@ function getVersionFileVersion(dir) {
58677
58889
  async function runVersionCheck2(dir, _timeoutMs) {
58678
58890
  const startTime = Date.now();
58679
58891
  try {
58680
- const packageVersion = _internals32.getPackageVersion(dir);
58681
- const changelogVersion = _internals32.getChangelogVersion(dir);
58682
- const versionFileVersion = _internals32.getVersionFileVersion(dir);
58892
+ const packageVersion = _internals33.getPackageVersion(dir);
58893
+ const changelogVersion = _internals33.getChangelogVersion(dir);
58894
+ const versionFileVersion = _internals33.getVersionFileVersion(dir);
58683
58895
  const versions3 = [];
58684
58896
  if (packageVersion)
58685
58897
  versions3.push(`package.json: ${packageVersion}`);
@@ -59029,7 +59241,7 @@ async function runPreflight(dir, phase, config3) {
59029
59241
  const reportId = `preflight-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
59030
59242
  let validatedDir;
59031
59243
  try {
59032
- validatedDir = _internals32.validateDirectoryPath(dir);
59244
+ validatedDir = _internals33.validateDirectoryPath(dir);
59033
59245
  } catch (error93) {
59034
59246
  return {
59035
59247
  id: reportId,
@@ -59049,7 +59261,7 @@ async function runPreflight(dir, phase, config3) {
59049
59261
  }
59050
59262
  let validatedTimeout;
59051
59263
  try {
59052
- validatedTimeout = _internals32.validateTimeout(config3?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
59264
+ validatedTimeout = _internals33.validateTimeout(config3?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
59053
59265
  } catch (error93) {
59054
59266
  return {
59055
59267
  id: reportId,
@@ -59090,12 +59302,12 @@ async function runPreflight(dir, phase, config3) {
59090
59302
  });
59091
59303
  const checks5 = [];
59092
59304
  log("[Preflight] Running lint check...");
59093
- const lintResult = await _internals32.runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
59305
+ const lintResult = await _internals33.runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
59094
59306
  checks5.push(lintResult);
59095
59307
  log(`[Preflight] Lint check: ${lintResult.status} ${lintResult.message}`);
59096
59308
  if (!cfg.skipTests) {
59097
59309
  log("[Preflight] Running tests check...");
59098
- const testsResult = await _internals32.runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
59310
+ const testsResult = await _internals33.runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
59099
59311
  checks5.push(testsResult);
59100
59312
  log(`[Preflight] Tests check: ${testsResult.status} ${testsResult.message}`);
59101
59313
  } else {
@@ -59107,7 +59319,7 @@ async function runPreflight(dir, phase, config3) {
59107
59319
  }
59108
59320
  if (!cfg.skipSecrets) {
59109
59321
  log("[Preflight] Running secrets check...");
59110
- const secretsResult = await _internals32.runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
59322
+ const secretsResult = await _internals33.runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
59111
59323
  checks5.push(secretsResult);
59112
59324
  log(`[Preflight] Secrets check: ${secretsResult.status} ${secretsResult.message}`);
59113
59325
  } else {
@@ -59119,7 +59331,7 @@ async function runPreflight(dir, phase, config3) {
59119
59331
  }
59120
59332
  if (!cfg.skipEvidence) {
59121
59333
  log("[Preflight] Running evidence check...");
59122
- const evidenceResult = await _internals32.runEvidenceCheck(validatedDir);
59334
+ const evidenceResult = await _internals33.runEvidenceCheck(validatedDir);
59123
59335
  checks5.push(evidenceResult);
59124
59336
  log(`[Preflight] Evidence check: ${evidenceResult.status} ${evidenceResult.message}`);
59125
59337
  } else {
@@ -59130,12 +59342,12 @@ async function runPreflight(dir, phase, config3) {
59130
59342
  });
59131
59343
  }
59132
59344
  log("[Preflight] Running requirement coverage check...");
59133
- const reqCoverageResult = await _internals32.runRequirementCoverageCheck(validatedDir, phase);
59345
+ const reqCoverageResult = await _internals33.runRequirementCoverageCheck(validatedDir, phase);
59134
59346
  checks5.push(reqCoverageResult);
59135
59347
  log(`[Preflight] Requirement coverage check: ${reqCoverageResult.status} ${reqCoverageResult.message}`);
59136
59348
  if (!cfg.skipVersion) {
59137
59349
  log("[Preflight] Running version check...");
59138
- const versionResult = await _internals32.runVersionCheck(validatedDir, cfg.checkTimeoutMs);
59350
+ const versionResult = await _internals33.runVersionCheck(validatedDir, cfg.checkTimeoutMs);
59139
59351
  checks5.push(versionResult);
59140
59352
  log(`[Preflight] Version check: ${versionResult.status} ${versionResult.message}`);
59141
59353
  } else {
@@ -59198,10 +59410,10 @@ function formatPreflightMarkdown(report) {
59198
59410
  async function handlePreflightCommand(directory, _args) {
59199
59411
  const plan = await loadPlan(directory);
59200
59412
  const phase = plan?.current_phase ?? 1;
59201
- const report = await _internals32.runPreflight(directory, phase);
59202
- return _internals32.formatPreflightMarkdown(report);
59413
+ const report = await _internals33.runPreflight(directory, phase);
59414
+ return _internals33.formatPreflightMarkdown(report);
59203
59415
  }
59204
- var MIN_CHECK_TIMEOUT_MS = 5000, MAX_CHECK_TIMEOUT_MS = 300000, DEFAULT_CONFIG, _internals32;
59416
+ var MIN_CHECK_TIMEOUT_MS = 5000, MAX_CHECK_TIMEOUT_MS = 300000, DEFAULT_CONFIG, _internals33;
59205
59417
  var init_preflight_service = __esm(() => {
59206
59418
  init_manager2();
59207
59419
  init_manager();
@@ -59218,7 +59430,7 @@ var init_preflight_service = __esm(() => {
59218
59430
  testScope: "convention",
59219
59431
  linter: "biome"
59220
59432
  };
59221
- _internals32 = {
59433
+ _internals33 = {
59222
59434
  runPreflight,
59223
59435
  formatPreflightMarkdown,
59224
59436
  handlePreflightCommand,
@@ -60259,7 +60471,7 @@ var init_reset_session = __esm(() => {
60259
60471
  });
60260
60472
 
60261
60473
  // src/summaries/manager.ts
60262
- import { mkdirSync as mkdirSync15, readdirSync as readdirSync13, renameSync as renameSync11, rmSync as rmSync4, statSync as statSync12 } from "node:fs";
60474
+ import { mkdirSync as mkdirSync15, readdirSync as readdirSync14, renameSync as renameSync11, rmSync as rmSync5, statSync as statSync13 } from "node:fs";
60263
60475
  import * as path50 from "node:path";
60264
60476
  function sanitizeSummaryId(id) {
60265
60477
  if (!id || id.length === 0) {
@@ -60312,7 +60524,7 @@ async function storeSummary(directory, id, fullOutput, summaryText, maxStoredByt
60312
60524
  renameSync11(tempPath, summaryPath);
60313
60525
  } catch (error93) {
60314
60526
  try {
60315
- rmSync4(tempPath, { force: true });
60527
+ rmSync5(tempPath, { force: true });
60316
60528
  } catch {}
60317
60529
  throw error93;
60318
60530
  }
@@ -61113,7 +61325,7 @@ async function getStatusData(directory, agents) {
61113
61325
  }
61114
61326
  function enrichWithLeanTurbo(status, directory) {
61115
61327
  const turboMode = hasActiveTurboMode();
61116
- const leanActive = _internals33.hasActiveLeanTurbo();
61328
+ const leanActive = _internals34.hasActiveLeanTurbo();
61117
61329
  let turboStrategy = "off";
61118
61330
  if (leanActive) {
61119
61331
  turboStrategy = "lean";
@@ -61132,7 +61344,7 @@ function enrichWithLeanTurbo(status, directory) {
61132
61344
  }
61133
61345
  }
61134
61346
  if (leanSessionID) {
61135
- const runState = _internals33.loadLeanTurboRunState(directory, leanSessionID);
61347
+ const runState = _internals34.loadLeanTurboRunState(directory, leanSessionID);
61136
61348
  if (runState) {
61137
61349
  status.leanTurboPhase = runState.phase;
61138
61350
  status.leanMaxParallelCoders = runState.maxParallelCoders;
@@ -61164,7 +61376,7 @@ function enrichWithLeanTurbo(status, directory) {
61164
61376
  }
61165
61377
  }
61166
61378
  }
61167
- status.fullAutoActive = _internals33.hasActiveFullAuto();
61379
+ status.fullAutoActive = _internals34.hasActiveFullAuto();
61168
61380
  return status;
61169
61381
  }
61170
61382
  function formatStatusMarkdown(status) {
@@ -61246,7 +61458,7 @@ async function handleStatusCommand(directory, agents) {
61246
61458
  }
61247
61459
  return formatStatusMarkdown(statusData);
61248
61460
  }
61249
- var _internals33;
61461
+ var _internals34;
61250
61462
  var init_status_service = __esm(() => {
61251
61463
  init_extractors();
61252
61464
  init_utils2();
@@ -61255,7 +61467,7 @@ var init_status_service = __esm(() => {
61255
61467
  init_state3();
61256
61468
  init_compaction_service();
61257
61469
  init_context_budget_service();
61258
- _internals33 = {
61470
+ _internals34 = {
61259
61471
  loadLeanTurboRunState,
61260
61472
  hasActiveLeanTurbo,
61261
61473
  hasActiveFullAuto
@@ -61346,7 +61558,7 @@ async function handleTurboCommand(directory, args2, sessionID) {
61346
61558
  if (arg0 === "on") {
61347
61559
  let strategy = "standard";
61348
61560
  try {
61349
- const { config: config3 } = _internals34.loadPluginConfigWithMeta(directory);
61561
+ const { config: config3 } = _internals35.loadPluginConfigWithMeta(directory);
61350
61562
  if (config3.turbo?.strategy === "lean") {
61351
61563
  strategy = "lean";
61352
61564
  }
@@ -61401,7 +61613,7 @@ function enableLeanTurbo(session, directory, sessionID) {
61401
61613
  let maxParallelCoders = 4;
61402
61614
  let conflictPolicy = "serialize";
61403
61615
  try {
61404
- const { config: config3 } = _internals34.loadPluginConfigWithMeta(directory);
61616
+ const { config: config3 } = _internals35.loadPluginConfigWithMeta(directory);
61405
61617
  const leanConfig = config3.turbo?.lean;
61406
61618
  if (leanConfig) {
61407
61619
  maxParallelCoders = leanConfig.max_parallel_coders ?? 4;
@@ -61471,13 +61683,13 @@ function buildStatusMessage(session, directory, sessionID) {
61471
61683
  ].join(`
61472
61684
  `);
61473
61685
  }
61474
- var _internals34;
61686
+ var _internals35;
61475
61687
  var init_turbo = __esm(() => {
61476
61688
  init_config();
61477
61689
  init_state();
61478
61690
  init_state3();
61479
61691
  init_logger();
61480
- _internals34 = {
61692
+ _internals35 = {
61481
61693
  loadPluginConfigWithMeta
61482
61694
  };
61483
61695
  });
@@ -61570,7 +61782,7 @@ function formatCommandNotFound(tokens) {
61570
61782
  const attemptedCommand = tokens[0] || "";
61571
61783
  const MAX_DISPLAY = 100;
61572
61784
  const displayCommand = attemptedCommand.length > MAX_DISPLAY ? `${attemptedCommand.slice(0, MAX_DISPLAY)}...` : attemptedCommand;
61573
- const similar = _internals35.findSimilarCommands(attemptedCommand);
61785
+ const similar = _internals36.findSimilarCommands(attemptedCommand);
61574
61786
  const header = `Command \`/swarm ${displayCommand}\` not found.`;
61575
61787
  const suggestions = similar.length > 0 ? `Did you mean:
61576
61788
  ${similar.map((cmd) => ` - /swarm ${cmd}`).join(`
@@ -62019,7 +62231,7 @@ async function buildSwarmCommandPrompt(args2) {
62019
62231
  activeAgentName,
62020
62232
  registeredAgents
62021
62233
  } = args2;
62022
- const resolved = _internals35.resolveCommand(tokens);
62234
+ const resolved = _internals36.resolveCommand(tokens);
62023
62235
  if (!resolved) {
62024
62236
  if (tokens.length === 0) {
62025
62237
  return buildHelpText();
@@ -62170,7 +62382,7 @@ function findSimilarCommands(query) {
62170
62382
  }
62171
62383
  const scored = VALID_COMMANDS.map((cmd) => {
62172
62384
  const cmdLower = cmd.toLowerCase();
62173
- const fullScore = _internals35.levenshteinDistance(q, cmdLower);
62385
+ const fullScore = _internals36.levenshteinDistance(q, cmdLower);
62174
62386
  let tokenScore = Infinity;
62175
62387
  if (cmd.includes(" ") || cmd.includes("-")) {
62176
62388
  const qTokens = q.split(/[\s-]+/);
@@ -62183,7 +62395,7 @@ function findSimilarCommands(query) {
62183
62395
  for (const ct of cmdTokens) {
62184
62396
  if (ct.length === 0)
62185
62397
  continue;
62186
- const dist = _internals35.levenshteinDistance(qt, ct);
62398
+ const dist = _internals36.levenshteinDistance(qt, ct);
62187
62399
  if (dist < minDist)
62188
62400
  minDist = dist;
62189
62401
  }
@@ -62193,7 +62405,7 @@ function findSimilarCommands(query) {
62193
62405
  }
62194
62406
  const dashStrippedQ = q.replace(/-/g, "");
62195
62407
  const dashStrippedCmd = cmdLower.replace(/-/g, "");
62196
- const dashScore = _internals35.levenshteinDistance(dashStrippedQ, dashStrippedCmd);
62408
+ const dashScore = _internals36.levenshteinDistance(dashStrippedQ, dashStrippedCmd);
62197
62409
  const score = Math.min(fullScore, tokenScore, dashScore);
62198
62410
  return { cmd, score };
62199
62411
  });
@@ -62225,11 +62437,11 @@ async function handleHelpCommand(ctx) {
62225
62437
  return buildHelpText2();
62226
62438
  }
62227
62439
  const tokens = targetCommand.split(/\s+/);
62228
- const resolved = _internals35.resolveCommand(tokens);
62440
+ const resolved = _internals36.resolveCommand(tokens);
62229
62441
  if (resolved) {
62230
- return _internals35.buildDetailedHelp(resolved.key, resolved.entry);
62442
+ return _internals36.buildDetailedHelp(resolved.key, resolved.entry);
62231
62443
  }
62232
- const similar = _internals35.findSimilarCommands(targetCommand);
62444
+ const similar = _internals36.findSimilarCommands(targetCommand);
62233
62445
  const { buildHelpText: fullHelp } = await Promise.resolve().then(() => (init_commands(), exports_commands));
62234
62446
  if (similar.length > 0) {
62235
62447
  return `Command '/swarm ${targetCommand}' not found.
@@ -62323,7 +62535,7 @@ function resolveCommand(tokens) {
62323
62535
  }
62324
62536
  return null;
62325
62537
  }
62326
- var COMMAND_REGISTRY, VALID_COMMANDS, _internals35, validation;
62538
+ var COMMAND_REGISTRY, VALID_COMMANDS, _internals36, validation;
62327
62539
  var init_registry = __esm(() => {
62328
62540
  init_acknowledge_spec_drift();
62329
62541
  init_agents();
@@ -62393,7 +62605,7 @@ var init_registry = __esm(() => {
62393
62605
  clashesWithNativeCcCommand: "/agents"
62394
62606
  },
62395
62607
  help: {
62396
- handler: (ctx) => _internals35.handleHelpCommand(ctx),
62608
+ handler: (ctx) => _internals36.handleHelpCommand(ctx),
62397
62609
  description: "Show help for swarm commands",
62398
62610
  category: "core",
62399
62611
  args: "[command]",
@@ -62765,7 +62977,7 @@ Subcommands:
62765
62977
  }
62766
62978
  };
62767
62979
  VALID_COMMANDS = Object.keys(COMMAND_REGISTRY);
62768
- _internals35 = {
62980
+ _internals36 = {
62769
62981
  handleHelpCommand,
62770
62982
  validateAliases,
62771
62983
  resolveCommand,
@@ -62773,7 +62985,7 @@ Subcommands:
62773
62985
  findSimilarCommands,
62774
62986
  buildDetailedHelp
62775
62987
  };
62776
- validation = _internals35.validateAliases();
62988
+ validation = _internals36.validateAliases();
62777
62989
  if (!validation.valid) {
62778
62990
  throw new Error(`COMMAND_REGISTRY alias validation failed:
62779
62991
  ${validation.errors.join(`
@@ -67566,9 +67778,9 @@ function validateFilename(filename) {
67566
67778
  throw new Error("Invalid filename: contains null byte");
67567
67779
  }
67568
67780
  const pathSeparators = ["/", "\\", ".."];
67569
- for (const sep7 of pathSeparators) {
67570
- if (filename.includes(sep7)) {
67571
- throw new Error(`Invalid filename: contains path separator '${sep7}'`);
67781
+ for (const sep8 of pathSeparators) {
67782
+ if (filename.includes(sep8)) {
67783
+ throw new Error(`Invalid filename: contains path separator '${sep8}'`);
67572
67784
  }
67573
67785
  }
67574
67786
  if (filename.startsWith("/") || filename.startsWith("\\") || /^[a-zA-Z]:/.test(filename)) {
@@ -71463,7 +71675,7 @@ __export(exports_runtime, {
71463
71675
  getSupportedLanguages: () => getSupportedLanguages,
71464
71676
  getInitializedLanguages: () => getInitializedLanguages,
71465
71677
  clearParserCache: () => clearParserCache,
71466
- _internals: () => _internals36
71678
+ _internals: () => _internals37
71467
71679
  });
71468
71680
  import * as path77 from "node:path";
71469
71681
  import { fileURLToPath as fileURLToPath2 } from "node:url";
@@ -71473,10 +71685,10 @@ async function initTreeSitter() {
71473
71685
  const thisDir = path77.dirname(fileURLToPath2(import.meta.url));
71474
71686
  const isSource = thisDir.replace(/\\/g, "/").endsWith("/src/lang");
71475
71687
  if (isSource) {
71476
- await _internals36.parserInit();
71688
+ await _internals37.parserInit();
71477
71689
  } else {
71478
71690
  const grammarsDir = getGrammarsDirAbsolute();
71479
- await _internals36.parserInit({
71691
+ await _internals37.parserInit({
71480
71692
  locateFile(scriptName) {
71481
71693
  return path77.join(grammarsDir, scriptName);
71482
71694
  }
@@ -71560,8 +71772,8 @@ async function isGrammarAvailable(languageId) {
71560
71772
  try {
71561
71773
  const wasmFileName = getWasmFileName(normalizedId);
71562
71774
  const wasmPath = path77.join(getGrammarsDirAbsolute(), wasmFileName);
71563
- const { statSync: statSync20 } = await import("node:fs");
71564
- statSync20(wasmPath);
71775
+ const { statSync: statSync21 } = await import("node:fs");
71776
+ statSync21(wasmPath);
71565
71777
  return true;
71566
71778
  } catch {
71567
71779
  return false;
@@ -71578,12 +71790,12 @@ function getInitializedLanguages() {
71578
71790
  function getSupportedLanguages() {
71579
71791
  return Object.keys(LANGUAGE_WASM_MAP);
71580
71792
  }
71581
- var parserCache, initializedLanguages, treeSitterInitPromise = null, _internals36, LANGUAGE_WASM_MAP;
71793
+ var parserCache, initializedLanguages, treeSitterInitPromise = null, _internals37, LANGUAGE_WASM_MAP;
71582
71794
  var init_runtime = __esm(() => {
71583
71795
  init_tree_sitter();
71584
71796
  parserCache = new Map;
71585
71797
  initializedLanguages = new Set;
71586
- _internals36 = {
71798
+ _internals37 = {
71587
71799
  parserInit: Parser.init
71588
71800
  };
71589
71801
  LANGUAGE_WASM_MAP = {
@@ -72040,9 +72252,9 @@ var init_doc_scan = __esm(() => {
72040
72252
  var exports_knowledge_recall = {};
72041
72253
  __export(exports_knowledge_recall, {
72042
72254
  knowledge_recall: () => knowledge_recall,
72043
- _internals: () => _internals37
72255
+ _internals: () => _internals38
72044
72256
  });
72045
- var knowledge_recall, _internals37;
72257
+ var knowledge_recall, _internals38;
72046
72258
  var init_knowledge_recall = __esm(() => {
72047
72259
  init_zod();
72048
72260
  init_knowledge_store();
@@ -72128,7 +72340,7 @@ var init_knowledge_recall = __esm(() => {
72128
72340
  return JSON.stringify(result);
72129
72341
  }
72130
72342
  });
72131
- _internals37 = {
72343
+ _internals38 = {
72132
72344
  knowledge_recall
72133
72345
  };
72134
72346
  });
@@ -72183,7 +72395,7 @@ __export(exports_curator_drift, {
72183
72395
  runDeterministicDriftCheck: () => runDeterministicDriftCheck,
72184
72396
  readPriorDriftReports: () => readPriorDriftReports,
72185
72397
  buildDriftInjectionText: () => buildDriftInjectionText,
72186
- _internals: () => _internals39
72398
+ _internals: () => _internals40
72187
72399
  });
72188
72400
  import * as fs60 from "node:fs";
72189
72401
  import * as path85 from "node:path";
@@ -72228,7 +72440,7 @@ async function runDeterministicDriftCheck(directory, phase, curatorResult, confi
72228
72440
  try {
72229
72441
  const planMd = await readSwarmFileAsync(directory, "plan.md");
72230
72442
  const specMd = await readSwarmFileAsync(directory, "spec.md");
72231
- const priorReports = await _internals39.readPriorDriftReports(directory);
72443
+ const priorReports = await _internals40.readPriorDriftReports(directory);
72232
72444
  const complianceCount = curatorResult.compliance.length;
72233
72445
  const warningCompliance = curatorResult.compliance.filter((obs) => obs.severity === "warning");
72234
72446
  let alignment = "ALIGNED";
@@ -72277,7 +72489,7 @@ async function runDeterministicDriftCheck(directory, phase, curatorResult, confi
72277
72489
  scope_additions: [],
72278
72490
  injection_summary: injectionSummary
72279
72491
  };
72280
- const reportPath = await _internals39.writeDriftReport(directory, report);
72492
+ const reportPath = await _internals40.writeDriftReport(directory, report);
72281
72493
  getGlobalEventBus().publish("curator.drift.completed", {
72282
72494
  phase,
72283
72495
  alignment,
@@ -72340,12 +72552,12 @@ function buildDriftInjectionText(report, maxChars) {
72340
72552
  }
72341
72553
  return text.slice(0, maxChars);
72342
72554
  }
72343
- var DRIFT_REPORT_PREFIX = "drift-report-phase-", _internals39;
72555
+ var DRIFT_REPORT_PREFIX = "drift-report-phase-", _internals40;
72344
72556
  var init_curator_drift = __esm(() => {
72345
72557
  init_event_bus();
72346
72558
  init_logger();
72347
72559
  init_utils2();
72348
- _internals39 = {
72560
+ _internals40 = {
72349
72561
  readPriorDriftReports,
72350
72562
  writeDriftReport,
72351
72563
  runDeterministicDriftCheck,
@@ -72357,7 +72569,7 @@ var init_curator_drift = __esm(() => {
72357
72569
  var exports_project_context = {};
72358
72570
  __export(exports_project_context, {
72359
72571
  buildProjectContext: () => buildProjectContext,
72360
- _internals: () => _internals56,
72572
+ _internals: () => _internals57,
72361
72573
  LANG_BACKEND_DETECTION_TIMEOUT_MS: () => LANG_BACKEND_DETECTION_TIMEOUT_MS
72362
72574
  });
72363
72575
  import * as fs112 from "node:fs";
@@ -72441,7 +72653,7 @@ function selectLintCommand(backend, directory) {
72441
72653
  return null;
72442
72654
  }
72443
72655
  async function buildProjectContext(directory) {
72444
- const backend = await _internals56.pickBackend(directory);
72656
+ const backend = await _internals57.pickBackend(directory);
72445
72657
  if (!backend)
72446
72658
  return null;
72447
72659
  const ctx = emptyProjectContext();
@@ -72472,16 +72684,16 @@ async function buildProjectContext(directory) {
72472
72684
  if (backend.prompts.reviewerChecklist.length > 0) {
72473
72685
  ctx.REVIEWER_CHECKLIST = bulletList(backend.prompts.reviewerChecklist);
72474
72686
  }
72475
- const profiles = _internals56.pickedProfiles(directory);
72687
+ const profiles = _internals57.pickedProfiles(directory);
72476
72688
  if (profiles.length > 1) {
72477
72689
  ctx.PROJECT_CONTEXT_SECONDARY_LANGUAGES = profiles.slice(1).map((p) => p.id).join(", ");
72478
72690
  }
72479
72691
  return ctx;
72480
72692
  }
72481
- var LANG_BACKEND_DETECTION_TIMEOUT_MS = 300, _internals56;
72693
+ var LANG_BACKEND_DETECTION_TIMEOUT_MS = 300, _internals57;
72482
72694
  var init_project_context = __esm(() => {
72483
72695
  init_dispatch();
72484
- _internals56 = {
72696
+ _internals57 = {
72485
72697
  pickBackend,
72486
72698
  pickedProfiles
72487
72699
  };
@@ -75265,14 +75477,14 @@ ${originalText}`;
75265
75477
  }
75266
75478
  // src/hooks/repo-graph-builder.ts
75267
75479
  init_constants();
75268
- import { realpathSync as realpathSync8 } from "node:fs";
75480
+ import { realpathSync as realpathSync10 } from "node:fs";
75269
75481
  import * as path70 from "node:path";
75270
75482
 
75271
75483
  // src/tools/repo-graph/builder.ts
75272
75484
  init_logger();
75273
75485
  init_path_security();
75274
75486
  import * as fsSync4 from "node:fs";
75275
- import { existsSync as existsSync38, realpathSync as realpathSync6 } from "node:fs";
75487
+ import { existsSync as existsSync38, realpathSync as realpathSync8 } from "node:fs";
75276
75488
  import * as fsPromises5 from "node:fs/promises";
75277
75489
  import * as os7 from "node:os";
75278
75490
  import * as path66 from "node:path";
@@ -75824,13 +76036,13 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
75824
76036
  let resolved = path66.resolve(sourceDir, specifier);
75825
76037
  let realResolved;
75826
76038
  try {
75827
- realResolved = realpathSync6(resolved);
76039
+ realResolved = realpathSync8(resolved);
75828
76040
  } catch {
75829
76041
  realResolved = resolved;
75830
76042
  }
75831
76043
  let realRoot;
75832
76044
  try {
75833
- realRoot = realpathSync6(workspaceRoot);
76045
+ realRoot = realpathSync8(workspaceRoot);
75834
76046
  } catch {
75835
76047
  realRoot = path66.normalize(workspaceRoot);
75836
76048
  }
@@ -75855,7 +76067,7 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
75855
76067
  }
75856
76068
  if (found) {
75857
76069
  try {
75858
- realResolved = realpathSync6(found);
76070
+ realResolved = realpathSync8(found);
75859
76071
  } catch {
75860
76072
  realResolved = found;
75861
76073
  }
@@ -75879,7 +76091,7 @@ function resolveModuleSpecifier(workspaceRoot, sourceFile, specifier) {
75879
76091
  function isRefusedWorkspaceRoot(target) {
75880
76092
  let resolved;
75881
76093
  try {
75882
- resolved = realpathSync6(target);
76094
+ resolved = realpathSync8(target);
75883
76095
  } catch {
75884
76096
  resolved = path66.resolve(target);
75885
76097
  }
@@ -76021,8 +76233,8 @@ async function findSourceFilesAsync(dir, stats, options) {
76021
76233
  return files;
76022
76234
  }
76023
76235
  function toModuleName(filePath, workspaceRoot) {
76024
- const relative11 = path66.relative(workspaceRoot, filePath);
76025
- return relative11.split(path66.sep).join("/");
76236
+ const relative12 = path66.relative(workspaceRoot, filePath);
76237
+ return relative12.split(path66.sep).join("/");
76026
76238
  }
76027
76239
  function getLanguage(filePath) {
76028
76240
  const ext = path66.extname(filePath).toLowerCase();
@@ -76187,7 +76399,7 @@ import * as path69 from "node:path";
76187
76399
  init_utils2();
76188
76400
  init_logger();
76189
76401
  init_path_security();
76190
- import { constants as constants4, existsSync as existsSync39, realpathSync as realpathSync7 } from "node:fs";
76402
+ import { constants as constants4, existsSync as existsSync39, realpathSync as realpathSync9 } from "node:fs";
76191
76403
  import * as fsPromises6 from "node:fs/promises";
76192
76404
  import * as path68 from "node:path";
76193
76405
  var WINDOWS_RENAME_MAX_RETRIES2 = 3;
@@ -76297,14 +76509,14 @@ async function saveGraph(workspace, graph, options) {
76297
76509
  const normalizedWorkspace = path68.normalize(workspace);
76298
76510
  let realWorkspace;
76299
76511
  try {
76300
- realWorkspace = realpathSync7(workspace);
76512
+ realWorkspace = realpathSync9(workspace);
76301
76513
  } catch {
76302
76514
  realWorkspace = normalizedWorkspace;
76303
76515
  }
76304
76516
  const normalizedGraphRoot = path68.normalize(graph.workspaceRoot);
76305
76517
  let realGraphRoot;
76306
76518
  try {
76307
- realGraphRoot = realpathSync7(graph.workspaceRoot);
76519
+ realGraphRoot = realpathSync9(graph.workspaceRoot);
76308
76520
  } catch {
76309
76521
  realGraphRoot = normalizedGraphRoot;
76310
76522
  }
@@ -76524,7 +76736,7 @@ function createRepoGraphBuilderHook(workspaceRoot, deps) {
76524
76736
  const absoluteFilePath = path70.isAbsolute(filePath) ? filePath : path70.resolve(workspaceRoot, filePath);
76525
76737
  let realFilePath;
76526
76738
  try {
76527
- realFilePath = realpathSync8(absoluteFilePath);
76739
+ realFilePath = realpathSync10(absoluteFilePath);
76528
76740
  } catch (error93) {
76529
76741
  if (!(error93 instanceof Error) || error93.code !== "ENOENT") {
76530
76742
  return;
@@ -76533,7 +76745,7 @@ function createRepoGraphBuilderHook(workspaceRoot, deps) {
76533
76745
  }
76534
76746
  let realWorkspace;
76535
76747
  try {
76536
- realWorkspace = realpathSync8(workspaceRoot);
76748
+ realWorkspace = realpathSync10(workspaceRoot);
76537
76749
  } catch (error93) {
76538
76750
  if (!(error93 instanceof Error) || error93.code !== "ENOENT") {
76539
76751
  return;
@@ -81286,22 +81498,22 @@ function classifyPathRisk(filePath, context) {
81286
81498
  }
81287
81499
  })();
81288
81500
  const withinProjectRoot = isWithinDirectory(absolute, context.directory) && isWithinDirectory(resolvedAbsolute, context.directory);
81289
- const relative17 = path81.relative(context.directory, absolute).replace(/\\/g, "/");
81501
+ const relative18 = path81.relative(context.directory, absolute).replace(/\\/g, "/");
81290
81502
  let withinDeclaredScope = null;
81291
81503
  if (Array.isArray(context.declaredScope)) {
81292
81504
  withinDeclaredScope = context.declaredScope.length === 0 ? false : context.declaredScope.some((scope) => {
81293
81505
  const s = normalizePath3(scope);
81294
81506
  if (!s)
81295
81507
  return false;
81296
- return relative17 === s || relative17.startsWith(`${s}/`);
81508
+ return relative18 === s || relative18.startsWith(`${s}/`);
81297
81509
  });
81298
81510
  }
81299
81511
  const highRiskBuild = HIGH_RISK_BUILD_PATHS.some((entry) => {
81300
81512
  const e = normalizePath3(entry);
81301
81513
  if (e.endsWith("/")) {
81302
- return relative17.startsWith(e);
81514
+ return relative18.startsWith(e);
81303
81515
  }
81304
- return relative17 === e || relative17.startsWith(`${e}/`);
81516
+ return relative18 === e || relative18.startsWith(`${e}/`);
81305
81517
  });
81306
81518
  return {
81307
81519
  withinProjectRoot,
@@ -82921,10 +83133,10 @@ async function getRunMemorySummary(directory) {
82921
83133
  if (entries.length === 0) {
82922
83134
  return null;
82923
83135
  }
82924
- const groups = _internals38.groupByTaskId(entries);
83136
+ const groups = _internals39.groupByTaskId(entries);
82925
83137
  const summaries = [];
82926
83138
  for (const [taskId, taskEntries] of groups) {
82927
- const summary = _internals38.summarizeTask(taskId, taskEntries);
83139
+ const summary = _internals39.summarizeTask(taskId, taskEntries);
82928
83140
  if (summary) {
82929
83141
  summaries.push(summary);
82930
83142
  }
@@ -82957,7 +83169,7 @@ Use this data to avoid repeating known failure patterns.`;
82957
83169
  }
82958
83170
  return prefix + summaryText + suffix;
82959
83171
  }
82960
- var _internals38 = {
83172
+ var _internals39 = {
82961
83173
  generateTaskFingerprint,
82962
83174
  recordOutcome,
82963
83175
  getTaskHistory,
@@ -83395,7 +83607,7 @@ import * as path87 from "node:path";
83395
83607
  function resolveLogPath(directory) {
83396
83608
  return validateSwarmPath(directory, "skill-usage.jsonl");
83397
83609
  }
83398
- var _internals40 = {
83610
+ var _internals41 = {
83399
83611
  generateId: () => crypto9.randomUUID(),
83400
83612
  appendFileSync: fs61.appendFileSync.bind(fs61),
83401
83613
  readFileSync: fs61.readFileSync.bind(fs61),
@@ -83441,11 +83653,11 @@ function appendSkillUsageEntry(directory, entry) {
83441
83653
  }
83442
83654
  const resolved = validateSwarmPath(directory, "skill-usage.jsonl");
83443
83655
  const dir = path87.dirname(resolved);
83444
- if (!_internals40.existsSync(dir)) {
83445
- _internals40.mkdirSync(dir, { recursive: true });
83656
+ if (!_internals41.existsSync(dir)) {
83657
+ _internals41.mkdirSync(dir, { recursive: true });
83446
83658
  }
83447
83659
  const fullEntry = {
83448
- id: _internals40.generateId(),
83660
+ id: _internals41.generateId(),
83449
83661
  skillPath,
83450
83662
  agentName,
83451
83663
  taskID,
@@ -83454,15 +83666,15 @@ function appendSkillUsageEntry(directory, entry) {
83454
83666
  sessionID,
83455
83667
  ...reviewerNotes !== undefined && { reviewerNotes }
83456
83668
  };
83457
- _internals40.appendFileSync(resolved, `${JSON.stringify(fullEntry)}
83669
+ _internals41.appendFileSync(resolved, `${JSON.stringify(fullEntry)}
83458
83670
  `, "utf-8");
83459
83671
  }
83460
83672
  function readSkillUsageEntries(directory, options) {
83461
83673
  const resolved = resolveLogPath(directory);
83462
- if (!_internals40.existsSync(resolved)) {
83674
+ if (!_internals41.existsSync(resolved)) {
83463
83675
  return [];
83464
83676
  }
83465
- const raw = _internals40.readFileSync(resolved, "utf-8");
83677
+ const raw = _internals41.readFileSync(resolved, "utf-8");
83466
83678
  const entries = [];
83467
83679
  for (const line of raw.split(`
83468
83680
  `)) {
@@ -83500,18 +83712,18 @@ function readSkillUsageEntries(directory, options) {
83500
83712
  var TAIL_BYTES_DEFAULT = 64 * 1024;
83501
83713
  function readSkillUsageEntriesTail(directory, filters, maxBytes = TAIL_BYTES_DEFAULT) {
83502
83714
  const logPath = resolveLogPath(directory);
83503
- if (!_internals40.existsSync(logPath))
83715
+ if (!_internals41.existsSync(logPath))
83504
83716
  return [];
83505
83717
  try {
83506
- const stat7 = _internals40.statSync(logPath);
83718
+ const stat7 = _internals41.statSync(logPath);
83507
83719
  const start2 = Math.max(0, stat7.size - maxBytes);
83508
- const fd = _internals40.openSync(logPath, "r");
83720
+ const fd = _internals41.openSync(logPath, "r");
83509
83721
  try {
83510
83722
  const readLen = stat7.size - start2;
83511
83723
  if (readLen === 0)
83512
83724
  return [];
83513
83725
  const buf = Buffer.alloc(readLen);
83514
- _internals40.readSync(fd, buf, 0, buf.length, start2);
83726
+ _internals41.readSync(fd, buf, 0, buf.length, start2);
83515
83727
  const content = buf.toString("utf-8");
83516
83728
  let usable;
83517
83729
  if (start2 > 0) {
@@ -83536,7 +83748,7 @@ function readSkillUsageEntriesTail(directory, filters, maxBytes = TAIL_BYTES_DEF
83536
83748
  }
83537
83749
  return entries;
83538
83750
  } finally {
83539
- _internals40.closeSync(fd);
83751
+ _internals41.closeSync(fd);
83540
83752
  }
83541
83753
  } catch {
83542
83754
  return [];
@@ -83551,7 +83763,7 @@ var RECENCY_WEIGHT = 0.15;
83551
83763
  var TASK_DIVERSITY_WEIGHT = 0.05;
83552
83764
  var CONTEXT_WEIGHT = 0.2;
83553
83765
  var RECENCY_DECAY_MS = 30 * 24 * 60 * 60 * 1000;
83554
- var _internals41 = {
83766
+ var _internals42 = {
83555
83767
  computeSkillRelevanceScore: null,
83556
83768
  rankSkillsForContext: null,
83557
83769
  getSkillStats: null,
@@ -83685,13 +83897,13 @@ function formatSkillIndexWithContext(skills, directory) {
83685
83897
  return lines.join(`
83686
83898
  `);
83687
83899
  }
83688
- _internals41.computeSkillRelevanceScore = computeSkillRelevanceScore;
83689
- _internals41.rankSkillsForContext = rankSkillsForContext;
83690
- _internals41.getSkillStats = getSkillStats;
83691
- _internals41.formatSkillIndexWithContext = formatSkillIndexWithContext;
83692
- _internals41.extractSkillName = extractSkillName;
83693
- _internals41.computeRecencyScore = computeRecencyScore;
83694
- _internals41.computeContextMatchScore = computeContextMatchScore;
83900
+ _internals42.computeSkillRelevanceScore = computeSkillRelevanceScore;
83901
+ _internals42.rankSkillsForContext = rankSkillsForContext;
83902
+ _internals42.getSkillStats = getSkillStats;
83903
+ _internals42.formatSkillIndexWithContext = formatSkillIndexWithContext;
83904
+ _internals42.extractSkillName = extractSkillName;
83905
+ _internals42.computeRecencyScore = computeRecencyScore;
83906
+ _internals42.computeContextMatchScore = computeContextMatchScore;
83695
83907
 
83696
83908
  // src/hooks/skill-propagation-gate.ts
83697
83909
  var SKILL_CAPABLE_AGENTS = new Set([
@@ -83708,7 +83920,7 @@ var SKILL_SEARCH_ROOTS = [
83708
83920
  ".claude/skills"
83709
83921
  ];
83710
83922
  var MAX_SCORING_SESSION_ENTRIES = 500;
83711
- var _internals42 = {
83923
+ var _internals43 = {
83712
83924
  readdirSync: fs62.readdirSync.bind(fs62),
83713
83925
  existsSync: fs62.existsSync.bind(fs62),
83714
83926
  statSync: fs62.statSync.bind(fs62),
@@ -83735,11 +83947,11 @@ function discoverAvailableSkills(directory) {
83735
83947
  const results = [];
83736
83948
  for (const root of SKILL_SEARCH_ROOTS) {
83737
83949
  const rootPath = path89.join(directory, root);
83738
- if (!_internals42.existsSync(rootPath))
83950
+ if (!_internals43.existsSync(rootPath))
83739
83951
  continue;
83740
83952
  let entries;
83741
83953
  try {
83742
- entries = _internals42.readdirSync(rootPath);
83954
+ entries = _internals43.readdirSync(rootPath);
83743
83955
  } catch {
83744
83956
  continue;
83745
83957
  }
@@ -83749,7 +83961,7 @@ function discoverAvailableSkills(directory) {
83749
83961
  const skillDir = path89.join(rootPath, entry);
83750
83962
  const skillFile = path89.join(skillDir, "SKILL.md");
83751
83963
  try {
83752
- if (_internals42.statSync(skillDir).isDirectory() && _internals42.existsSync(skillFile)) {
83964
+ if (_internals43.statSync(skillDir).isDirectory() && _internals43.existsSync(skillFile)) {
83753
83965
  results.push(path89.join(root, entry, "SKILL.md"));
83754
83966
  }
83755
83967
  } catch (err2) {
@@ -83799,10 +84011,10 @@ function writeWarnEvent2(directory, record3) {
83799
84011
  const filePath = path89.join(directory, ".swarm", "events.jsonl");
83800
84012
  try {
83801
84013
  const dir = path89.dirname(filePath);
83802
- if (!_internals42.existsSync(dir)) {
83803
- _internals42.mkdirSync(dir, { recursive: true });
84014
+ if (!_internals43.existsSync(dir)) {
84015
+ _internals43.mkdirSync(dir, { recursive: true });
83804
84016
  }
83805
- _internals42.appendFileSync(filePath, `${JSON.stringify(record3)}
84017
+ _internals43.appendFileSync(filePath, `${JSON.stringify(record3)}
83806
84018
  `, "utf-8");
83807
84019
  } catch (err2) {
83808
84020
  warn(`[skill-propagation-gate] failed to write warning event: ${err2 instanceof Error ? err2.message : String(err2)}`);
@@ -83839,19 +84051,19 @@ async function skillPropagationGateBefore(directory, input, config3) {
83839
84051
  const baseAgent = stripKnownSwarmPrefix(agentRaw);
83840
84052
  if (baseAgent !== "architect")
83841
84053
  return { blocked: false, reason: null };
83842
- const parsed = _internals42.parseDelegationArgs(input.args);
84054
+ const parsed = _internals43.parseDelegationArgs(input.args);
83843
84055
  if (!parsed)
83844
84056
  return { blocked: false, reason: null };
83845
84057
  const targetBase = stripKnownSwarmPrefix(parsed.targetAgent);
83846
- if (!_internals42.SKILL_CAPABLE_AGENTS.has(targetBase))
84058
+ if (!_internals43.SKILL_CAPABLE_AGENTS.has(targetBase))
83847
84059
  return { blocked: false, reason: null };
83848
84060
  const sessionID = typeof input.sessionID === "string" ? input.sessionID : "unknown";
83849
- const availableSkills = _internals42.discoverAvailableSkills(directory);
84061
+ const availableSkills = _internals43.discoverAvailableSkills(directory);
83850
84062
  const skillsValue = parsed.skillsField.trim();
83851
84063
  if (skillsValue && skillsValue.toLowerCase() !== "none") {
83852
84064
  const prompt = typeof input.args?.prompt === "string" ? String(input.args.prompt) : "";
83853
- const taskId = _internals42.extractTaskIdFromPrompt(prompt);
83854
- const skillPaths = _internals42.parseSkillPaths(skillsValue);
84065
+ const taskId = _internals43.extractTaskIdFromPrompt(prompt);
84066
+ const skillPaths = _internals43.parseSkillPaths(skillsValue);
83855
84067
  let coderSkillPaths = [];
83856
84068
  if (prompt) {
83857
84069
  for (const line of prompt.split(`
@@ -83859,7 +84071,7 @@ async function skillPropagationGateBefore(directory, input, config3) {
83859
84071
  const trimmed = line.trim();
83860
84072
  if (trimmed.startsWith("SKILLS_USED_BY_CODER:")) {
83861
84073
  const fieldVal = trimmed.slice("SKILLS_USED_BY_CODER:".length).trim();
83862
- coderSkillPaths = _internals42.parseSkillPaths(fieldVal);
84074
+ coderSkillPaths = _internals43.parseSkillPaths(fieldVal);
83863
84075
  break;
83864
84076
  }
83865
84077
  }
@@ -83867,7 +84079,7 @@ async function skillPropagationGateBefore(directory, input, config3) {
83867
84079
  const allPaths = [...new Set([...skillPaths, ...coderSkillPaths])];
83868
84080
  for (const skillPath of allPaths) {
83869
84081
  try {
83870
- _internals42.appendSkillUsageEntry(directory, {
84082
+ _internals43.appendSkillUsageEntry(directory, {
83871
84083
  skillPath,
83872
84084
  agentName: targetBase,
83873
84085
  taskID: taskId,
@@ -83884,17 +84096,17 @@ async function skillPropagationGateBefore(directory, input, config3) {
83884
84096
  let scored = [];
83885
84097
  if (skillsValue && skillsValue.toLowerCase() !== "none" && availableSkills.length > 0) {
83886
84098
  try {
83887
- const sessionEntries = _internals42.readSkillUsageEntriesTail(directory, {
84099
+ const sessionEntries = _internals43.readSkillUsageEntriesTail(directory, {
83888
84100
  sessionID
83889
84101
  });
83890
- if (sessionEntries.length > _internals42.MAX_SCORING_SESSION_ENTRIES) {
84102
+ if (sessionEntries.length > _internals43.MAX_SCORING_SESSION_ENTRIES) {
83891
84103
  scoringSkipped = true;
83892
- warn(`[skill-propagation-gate] skipping scoring — session has ${sessionEntries.length} entries (limit: ${_internals42.MAX_SCORING_SESSION_ENTRIES})`);
84104
+ warn(`[skill-propagation-gate] skipping scoring — session has ${sessionEntries.length} entries (limit: ${_internals43.MAX_SCORING_SESSION_ENTRIES})`);
83893
84105
  } else {
83894
84106
  const prompt = typeof input.args?.prompt === "string" ? String(input.args.prompt) : "";
83895
84107
  scored = availableSkills.map((skillPath) => {
83896
84108
  const skillEntries = sessionEntries.filter((e) => e.skillPath === skillPath);
83897
- const score = _internals42.computeSkillRelevanceScore(skillPath, prompt, skillEntries);
84109
+ const score = _internals43.computeSkillRelevanceScore(skillPath, prompt, skillEntries);
83898
84110
  return { skillPath, score, usageCount: skillEntries.length };
83899
84111
  }).sort((a, b) => b.score - a.score || b.usageCount - a.usageCount);
83900
84112
  if (scored.length > 0) {
@@ -83919,12 +84131,12 @@ async function skillPropagationGateBefore(directory, input, config3) {
83919
84131
  } else if (typeof scored !== "undefined" && scored.length > 0) {
83920
84132
  skillsForIndex = scored.map((r) => r.skillPath);
83921
84133
  }
83922
- const formattedIndex = _internals42.formatSkillIndexWithContext(skillsForIndex, directory);
84134
+ const formattedIndex = _internals43.formatSkillIndexWithContext(skillsForIndex, directory);
83923
84135
  if (formattedIndex.length > 0) {
83924
84136
  const contextPath = path89.join(directory, ".swarm", "context.md");
83925
84137
  let existingContent = "";
83926
- if (_internals42.existsSync(contextPath)) {
83927
- existingContent = _internals42.readFileSync(contextPath, "utf-8");
84138
+ if (_internals43.existsSync(contextPath)) {
84139
+ existingContent = _internals43.readFileSync(contextPath, "utf-8");
83928
84140
  }
83929
84141
  const sectionHeader = "## Available Skills";
83930
84142
  const newSection = `${sectionHeader}
@@ -83950,10 +84162,10 @@ ${newSection}`;
83950
84162
  }
83951
84163
  }
83952
84164
  const swarmDir = path89.dirname(contextPath);
83953
- if (!_internals42.existsSync(swarmDir)) {
83954
- _internals42.mkdirSync(swarmDir, { recursive: true });
84165
+ if (!_internals43.existsSync(swarmDir)) {
84166
+ _internals43.mkdirSync(swarmDir, { recursive: true });
83955
84167
  }
83956
- _internals42.writeFileSync(contextPath, updatedContent, "utf-8");
84168
+ _internals43.writeFileSync(contextPath, updatedContent, "utf-8");
83957
84169
  }
83958
84170
  } catch (err2) {
83959
84171
  warn(`[skill-propagation-gate] failed to write skill index to context.md: ${err2 instanceof Error ? err2.message : String(err2)}`);
@@ -83979,7 +84191,7 @@ ${newSection}`;
83979
84191
  });
83980
84192
  const warningMsg = `Skill propagation warning: Delegating to ${targetBase} without SKILLS field. ` + `Available skills: ${skillNames.join(", ")}`;
83981
84193
  try {
83982
- _internals42.writeWarnEvent(directory, {
84194
+ _internals43.writeWarnEvent(directory, {
83983
84195
  type: "skill_propagation_warn",
83984
84196
  timestamp: new Date().toISOString(),
83985
84197
  tool: toolName,
@@ -84008,7 +84220,7 @@ async function skillPropagationTransformScan(directory, output, sessionID) {
84008
84220
  let dedupKeys = new Set;
84009
84221
  let existingEntries = [];
84010
84222
  try {
84011
- existingEntries = _internals42.readSkillUsageEntriesTail(directory, {
84223
+ existingEntries = _internals43.readSkillUsageEntriesTail(directory, {
84012
84224
  sessionID
84013
84225
  });
84014
84226
  dedupKeys = new Set(existingEntries.map((e, i2) => {
@@ -84040,7 +84252,7 @@ async function skillPropagationTransformScan(directory, output, sessionID) {
84040
84252
  `)) {
84041
84253
  const coderMatch = line.trim().match(CODER_SKILLS_PATTERN);
84042
84254
  if (coderMatch) {
84043
- const parsed = _internals42.parseSkillPaths(coderMatch[1]);
84255
+ const parsed = _internals43.parseSkillPaths(coderMatch[1]);
84044
84256
  skillPaths.push(...parsed);
84045
84257
  }
84046
84258
  }
@@ -84071,7 +84283,7 @@ async function skillPropagationTransformScan(directory, output, sessionID) {
84071
84283
  if (isDuplicate(skillPath, "reviewer", resolvedTaskID))
84072
84284
  continue;
84073
84285
  try {
84074
- _internals42.appendSkillUsageEntry(directory, {
84286
+ _internals43.appendSkillUsageEntry(directory, {
84075
84287
  skillPath,
84076
84288
  agentName: "reviewer",
84077
84289
  taskID: resolvedTaskID,
@@ -84115,15 +84327,15 @@ async function skillPropagationTransformScan(directory, output, sessionID) {
84115
84327
  skillsField = trimmed.slice("SKILLS:".length).trim();
84116
84328
  }
84117
84329
  if (currentTargetAgent && skillsField && skillsField.toLowerCase() !== "none") {
84118
- const skillPaths = _internals42.parseSkillPaths(skillsField);
84119
- const taskId = _internals42.extractTaskIdFromPrompt(text);
84330
+ const skillPaths = _internals43.parseSkillPaths(skillsField);
84331
+ const taskId = _internals43.extractTaskIdFromPrompt(text);
84120
84332
  for (const skillPath of skillPaths) {
84121
84333
  if (hadRecordingError)
84122
84334
  break;
84123
84335
  if (isDuplicate(skillPath, currentTargetAgent, taskId))
84124
84336
  continue;
84125
84337
  try {
84126
- _internals42.appendSkillUsageEntry(directory, {
84338
+ _internals43.appendSkillUsageEntry(directory, {
84127
84339
  skillPath,
84128
84340
  agentName: currentTargetAgent,
84129
84341
  taskID: taskId,
@@ -84143,14 +84355,14 @@ async function skillPropagationTransformScan(directory, output, sessionID) {
84143
84355
  break;
84144
84356
  }
84145
84357
  }
84146
- _internals42.skillPropagationGateBefore = skillPropagationGateBefore;
84147
- _internals42.skillPropagationTransformScan = skillPropagationTransformScan;
84148
- _internals42.writeWarnEvent = writeWarnEvent2;
84149
- _internals42.discoverAvailableSkills = discoverAvailableSkills;
84150
- _internals42.parseDelegationArgs = parseDelegationArgs;
84151
- _internals42.parseSkillPaths = parseSkillPaths;
84152
- _internals42.extractTaskIdFromPrompt = extractTaskIdFromPrompt;
84153
- _internals42.formatSkillIndexWithContext = formatSkillIndexWithContext;
84358
+ _internals43.skillPropagationGateBefore = skillPropagationGateBefore;
84359
+ _internals43.skillPropagationTransformScan = skillPropagationTransformScan;
84360
+ _internals43.writeWarnEvent = writeWarnEvent2;
84361
+ _internals43.discoverAvailableSkills = discoverAvailableSkills;
84362
+ _internals43.parseDelegationArgs = parseDelegationArgs;
84363
+ _internals43.parseSkillPaths = parseSkillPaths;
84364
+ _internals43.extractTaskIdFromPrompt = extractTaskIdFromPrompt;
84365
+ _internals43.formatSkillIndexWithContext = formatSkillIndexWithContext;
84154
84366
 
84155
84367
  // src/hooks/slop-detector.ts
84156
84368
  import * as fs63 from "node:fs";
@@ -86393,8 +86605,8 @@ async function executeCompletionVerify(args2, directory) {
86393
86605
  const normalizedPath = filePath.replace(/\\/g, "/");
86394
86606
  const resolvedPath = path96.resolve(directory, normalizedPath);
86395
86607
  const projectRoot = path96.resolve(directory);
86396
- const relative20 = path96.relative(projectRoot, resolvedPath);
86397
- const withinProject = relative20 === "" || !relative20.startsWith("..") && !path96.isAbsolute(relative20);
86608
+ const relative21 = path96.relative(projectRoot, resolvedPath);
86609
+ const withinProject = relative21 === "" || !relative21.startsWith("..") && !path96.isAbsolute(relative21);
86398
86610
  if (!withinProject) {
86399
86611
  blockedTasks.push({
86400
86612
  task_id: task.id,
@@ -88782,9 +88994,30 @@ async function executeDeclareScope(args2, fallbackDir) {
88782
88994
  ]
88783
88995
  };
88784
88996
  }
88997
+ if (normalizedDir && fallbackDir) {
88998
+ try {
88999
+ const canonicalWorkingDir = fs74.realpathSync(path100.resolve(normalizedDir));
89000
+ const canonicalProjectRoot = fs74.realpathSync(path100.resolve(fallbackDir));
89001
+ if (canonicalWorkingDir.startsWith(canonicalProjectRoot + path100.sep)) {
89002
+ return {
89003
+ success: false,
89004
+ message: `working_directory "${normalizedDir}" is a subdirectory of the project root. Use the project root "${fallbackDir}" instead.`,
89005
+ errors: [
89006
+ `Subdirectory working_directory not allowed — use project root "${fallbackDir}"`
89007
+ ]
89008
+ };
89009
+ }
89010
+ } catch {}
89011
+ }
88785
89012
  }
88786
- if (!fallbackDir) {
88787
- console.warn("[declare-scope] fallbackDir is undefined, falling back to process.cwd()");
89013
+ if (!normalizedDir && !fallbackDir) {
89014
+ return {
89015
+ success: false,
89016
+ message: "Cannot resolve project directory",
89017
+ errors: [
89018
+ "Provide working_directory or ensure the tool is invoked from a project root"
89019
+ ]
89020
+ };
88788
89021
  }
88789
89022
  const directory = normalizedDir || fallbackDir;
88790
89023
  const planPath = path100.resolve(directory, ".swarm", "plan.json");
@@ -88825,7 +89058,7 @@ async function executeDeclareScope(args2, fallbackDir) {
88825
89058
  const rawMergedFiles = [...args2.files, ...args2.whitelist ?? []];
88826
89059
  const warnings = [];
88827
89060
  const normalizeErrors = [];
88828
- const dir = normalizedDir || fallbackDir || process.cwd();
89061
+ const dir = directory;
88829
89062
  const mergedFiles = rawMergedFiles.map((file3) => {
88830
89063
  if (path100.isAbsolute(file3)) {
88831
89064
  const relativePath = path100.relative(dir, file3).replace(/\\/g, "/");
@@ -89157,6 +89390,7 @@ import * as child_process8 from "node:child_process";
89157
89390
  import * as fs76 from "node:fs";
89158
89391
  import * as path102 from "node:path";
89159
89392
  init_create_tool();
89393
+ init_resolve_working_directory();
89160
89394
  var diff_summary = createSwarmTool({
89161
89395
  description: "Generate a filtered semantic diff summary from AST analysis. Returns SemanticDiffSummary with optional filtering by classification or riskLevel.",
89162
89396
  args: {
@@ -89174,7 +89408,11 @@ var diff_summary = createSwarmTool({
89174
89408
  };
89175
89409
  return JSON.stringify(errorResult, null, 2);
89176
89410
  }
89177
- const workingDir = directory || process.cwd();
89411
+ const resolved = resolveWorkingDirectory(undefined, directory);
89412
+ if (!resolved.success) {
89413
+ return JSON.stringify({ success: false, error: resolved.message }, null, 2);
89414
+ }
89415
+ const workingDir = resolved.directory;
89178
89416
  const astDiffs = [];
89179
89417
  for (const filePath of typedArgs.files) {
89180
89418
  let astResult = null;
@@ -91065,7 +91303,7 @@ import * as path109 from "node:path";
91065
91303
 
91066
91304
  // src/turbo/lean/evidence.ts
91067
91305
  init_bun_compat();
91068
- import { rmSync as rmSync5 } from "node:fs";
91306
+ import { rmSync as rmSync6 } from "node:fs";
91069
91307
  import * as fs82 from "node:fs/promises";
91070
91308
  import * as path108 from "node:path";
91071
91309
  function leanTurboEvidenceDir(directory, phase) {
@@ -91108,7 +91346,7 @@ async function atomicWriteJson(filePath, data) {
91108
91346
  await fs82.rename(tempPath, filePath);
91109
91347
  } catch (error93) {
91110
91348
  try {
91111
- rmSync5(tempPath, { force: true });
91349
+ rmSync6(tempPath, { force: true });
91112
91350
  } catch {}
91113
91351
  throw error93;
91114
91352
  }
@@ -91252,7 +91490,7 @@ function listLaneEvidenceSync(directory, phase) {
91252
91490
  }
91253
91491
  return laneIds;
91254
91492
  }
91255
- var _internals43 = {
91493
+ var _internals44 = {
91256
91494
  listActiveLocks,
91257
91495
  readPersisted: readPersisted2,
91258
91496
  readPlanJson: defaultReadPlanJson,
@@ -91313,7 +91551,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
91313
91551
  reason: "Lean Turbo state unreadable or missing"
91314
91552
  };
91315
91553
  }
91316
- const persisted = _internals43.readPersisted(directory);
91554
+ const persisted = _internals44.readPersisted(directory);
91317
91555
  if (!persisted) {
91318
91556
  return {
91319
91557
  ok: false,
@@ -91377,7 +91615,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
91377
91615
  }
91378
91616
  }
91379
91617
  if (runState.lanes.length > 0) {
91380
- const evidenceLaneIds = new Set(_internals43.listLaneEvidenceSync(directory, phase));
91618
+ const evidenceLaneIds = new Set(_internals44.listLaneEvidenceSync(directory, phase));
91381
91619
  for (const lane of runState.lanes) {
91382
91620
  if ((lane.status === "completed" || lane.status === "failed") && !evidenceLaneIds.has(lane.laneId)) {
91383
91621
  return {
@@ -91387,7 +91625,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
91387
91625
  }
91388
91626
  }
91389
91627
  }
91390
- const activeLocks = _internals43.listActiveLocks(directory);
91628
+ const activeLocks = _internals44.listActiveLocks(directory);
91391
91629
  const phaseLaneIds = new Set(laneIds);
91392
91630
  for (const lock of activeLocks) {
91393
91631
  if (lock.laneId && phaseLaneIds.has(lock.laneId)) {
@@ -91407,7 +91645,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
91407
91645
  }
91408
91646
  const serialDegradedTasks = runState.degradedTasks.filter((dt) => !laneTaskIds.has(dt.taskId));
91409
91647
  if (serialDegradedTasks.length > 0) {
91410
- const plan = _internals43.readPlanJson(directory);
91648
+ const plan = _internals44.readPlanJson(directory);
91411
91649
  if (!plan) {
91412
91650
  return {
91413
91651
  ok: false,
@@ -91451,7 +91689,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
91451
91689
  }
91452
91690
  const serializedTasks = runState.serializedTasks;
91453
91691
  if (Array.isArray(serializedTasks) && serializedTasks.length > 0) {
91454
- const plan = _internals43.readPlanJson(directory);
91692
+ const plan = _internals44.readPlanJson(directory);
91455
91693
  if (!plan) {
91456
91694
  return {
91457
91695
  ok: false,
@@ -91510,7 +91748,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
91510
91748
  }
91511
91749
  let reviewerVerdict = runState.lastReviewerVerdict;
91512
91750
  if (!reviewerVerdict) {
91513
- const evidence = _internals43.readReviewerEvidence(directory, phase);
91751
+ const evidence = _internals44.readReviewerEvidence(directory, phase);
91514
91752
  reviewerVerdict = evidence?.verdict ?? undefined;
91515
91753
  }
91516
91754
  if (mergedConfig.phase_reviewer) {
@@ -91523,7 +91761,7 @@ function verifyLeanTurboPhaseReady(directory, phase, sessionIDOrConfig, config3)
91523
91761
  }
91524
91762
  let criticVerdict = runState.lastCriticVerdict;
91525
91763
  if (!criticVerdict) {
91526
- const evidence = _internals43.readCriticEvidence(directory, phase);
91764
+ const evidence = _internals44.readCriticEvidence(directory, phase);
91527
91765
  criticVerdict = evidence?.verdict ?? undefined;
91528
91766
  }
91529
91767
  if (mergedConfig.phase_critic) {
@@ -92446,7 +92684,7 @@ Advisory notes: ${advisoryNotes.join("; ")}` : "";
92446
92684
  phase_critic: leanConfig.phase_critic,
92447
92685
  integrated_diff_required: leanConfig.integrated_diff_required
92448
92686
  } : undefined;
92449
- const leanCheck = _internals43.verifyLeanTurboPhaseReady(dir, phase, sessionID, leanPhaseReadyConfig);
92687
+ const leanCheck = _internals44.verifyLeanTurboPhaseReady(dir, phase, sessionID, leanPhaseReadyConfig);
92450
92688
  if (!leanCheck.ok) {
92451
92689
  return JSON.stringify({
92452
92690
  success: false,
@@ -94634,11 +94872,11 @@ var quality_budget = createSwarmTool({
94634
94872
  }).optional().describe("Quality budget thresholds")
94635
94873
  },
94636
94874
  async execute(args2, directory) {
94637
- const result = await _internals44.qualityBudget(args2, directory);
94875
+ const result = await _internals45.qualityBudget(args2, directory);
94638
94876
  return JSON.stringify(result);
94639
94877
  }
94640
94878
  });
94641
- var _internals44 = {
94879
+ var _internals45 = {
94642
94880
  qualityBudget
94643
94881
  };
94644
94882
 
@@ -95367,7 +95605,7 @@ import * as path113 from "node:path";
95367
95605
  var semgrepAvailableCache = null;
95368
95606
  var DEFAULT_RULES_DIR = ".swarm/semgrep-rules";
95369
95607
  var DEFAULT_TIMEOUT_MS3 = 30000;
95370
- var _internals45 = {
95608
+ var _internals46 = {
95371
95609
  isSemgrepAvailable,
95372
95610
  checkSemgrepAvailable,
95373
95611
  resetSemgrepCache,
@@ -95392,7 +95630,7 @@ function isSemgrepAvailable() {
95392
95630
  }
95393
95631
  }
95394
95632
  async function checkSemgrepAvailable() {
95395
- return _internals45.isSemgrepAvailable();
95633
+ return _internals46.isSemgrepAvailable();
95396
95634
  }
95397
95635
  function resetSemgrepCache() {
95398
95636
  semgrepAvailableCache = null;
@@ -95489,12 +95727,12 @@ async function runSemgrep(options) {
95489
95727
  const timeoutMs = options.timeoutMs || DEFAULT_TIMEOUT_MS3;
95490
95728
  if (files.length === 0) {
95491
95729
  return {
95492
- available: _internals45.isSemgrepAvailable(),
95730
+ available: _internals46.isSemgrepAvailable(),
95493
95731
  findings: [],
95494
95732
  engine: "tier_a"
95495
95733
  };
95496
95734
  }
95497
- if (!_internals45.isSemgrepAvailable()) {
95735
+ if (!_internals46.isSemgrepAvailable()) {
95498
95736
  return {
95499
95737
  available: false,
95500
95738
  findings: [],
@@ -95653,7 +95891,7 @@ function assignOccurrenceIndices(findings, directory) {
95653
95891
  }
95654
95892
  const occIdx = countMap.get(baseKey) ?? 0;
95655
95893
  countMap.set(baseKey, occIdx + 1);
95656
- const fp = _internals46.fingerprintFinding(finding, directory, occIdx);
95894
+ const fp = _internals47.fingerprintFinding(finding, directory, occIdx);
95657
95895
  return {
95658
95896
  finding,
95659
95897
  index: occIdx,
@@ -95722,7 +95960,7 @@ async function captureOrMergeBaseline(directory, phase, findings, engine, scanne
95722
95960
  }
95723
95961
  } catch {}
95724
95962
  const scannedRelFiles = new Set(scannedFiles.map((f) => normalizeFindingPath(directory, f)));
95725
- const indexed = _internals46.assignOccurrenceIndices(findings, directory);
95963
+ const indexed = _internals47.assignOccurrenceIndices(findings, directory);
95726
95964
  if (existing && !opts?.force) {
95727
95965
  const prunedFingerprints = existing.fingerprints.filter((fp) => {
95728
95966
  const relFile = fp.slice(0, fp.indexOf("|"));
@@ -95862,7 +96100,7 @@ function loadBaseline(directory, phase) {
95862
96100
  };
95863
96101
  }
95864
96102
  }
95865
- var _internals46 = {
96103
+ var _internals47 = {
95866
96104
  fingerprintFinding,
95867
96105
  assignOccurrenceIndices,
95868
96106
  captureOrMergeBaseline,
@@ -96272,11 +96510,11 @@ var sast_scan = createSwarmTool({
96272
96510
  capture_baseline: safeArgs.capture_baseline,
96273
96511
  phase: safeArgs.phase
96274
96512
  };
96275
- const result = await _internals47.sastScan(input, directory);
96513
+ const result = await _internals48.sastScan(input, directory);
96276
96514
  return JSON.stringify(result, null, 2);
96277
96515
  }
96278
96516
  });
96279
- var _internals47 = {
96517
+ var _internals48 = {
96280
96518
  sastScan,
96281
96519
  sast_scan
96282
96520
  };
@@ -96307,13 +96545,13 @@ function validatePath(inputPath, baseDir, workspaceDir) {
96307
96545
  resolved = path116.resolve(baseDir, inputPath);
96308
96546
  }
96309
96547
  const workspaceResolved = path116.resolve(workspaceDir);
96310
- let relative24;
96548
+ let relative25;
96311
96549
  if (isWinAbs) {
96312
- relative24 = path116.win32.relative(workspaceResolved, resolved);
96550
+ relative25 = path116.win32.relative(workspaceResolved, resolved);
96313
96551
  } else {
96314
- relative24 = path116.relative(workspaceResolved, resolved);
96552
+ relative25 = path116.relative(workspaceResolved, resolved);
96315
96553
  }
96316
- if (relative24.startsWith("..")) {
96554
+ if (relative25.startsWith("..")) {
96317
96555
  return "path traversal detected";
96318
96556
  }
96319
96557
  return null;
@@ -96951,7 +97189,7 @@ var pre_check_batch = createSwarmTool({
96951
97189
  description: "Run multiple verification tools in parallel: lint, secretscan, SAST scan, and quality budget. Returns unified result with gates_passed status. Security tools (secretscan, sast_scan) are HARD GATES - failures block merging.",
96952
97190
  args: {
96953
97191
  files: exports_external.array(exports_external.string()).optional().describe("Specific files to check (optional, scans directory if not provided)"),
96954
- directory: exports_external.string().describe('Directory to run checks in (e.g., "." or "./src")'),
97192
+ directory: exports_external.string().describe("Project root directory must be the workspace root, subdirectories are rejected"),
96955
97193
  sast_threshold: exports_external.enum(["low", "medium", "high", "critical"]).optional().describe("Minimum severity for SAST findings to cause failure (default: medium)"),
96956
97194
  phase: exports_external.number().int().min(1).optional().describe("Current phase number (positive integer >= 1). When provided, enables SAST baseline diffing: only findings absent from the phase-scoped baseline fail the gate.")
96957
97195
  },
@@ -97023,7 +97261,19 @@ var pre_check_batch = createSwarmTool({
97023
97261
  return JSON.stringify(errorResult, null, 2);
97024
97262
  }
97025
97263
  const resolvedDirectory = path116.resolve(typedArgs.directory);
97026
- const workspaceAnchor = resolvedDirectory;
97264
+ const workspaceAnchor = path116.resolve(directory);
97265
+ if (resolvedDirectory !== workspaceAnchor && resolvedDirectory.startsWith(workspaceAnchor + path116.sep)) {
97266
+ const subDirError = `directory "${typedArgs.directory}" is a subdirectory of the project root — pre_check_batch requires the project root directory "${workspaceAnchor}"`;
97267
+ const subDirResult = {
97268
+ gates_passed: false,
97269
+ lint: { ran: false, error: subDirError, duration_ms: 0 },
97270
+ secretscan: { ran: false, error: subDirError, duration_ms: 0 },
97271
+ sast_scan: { ran: false, error: subDirError, duration_ms: 0 },
97272
+ quality_budget: { ran: false, error: subDirError, duration_ms: 0 },
97273
+ total_duration_ms: 0
97274
+ };
97275
+ return JSON.stringify(subDirResult, null, 2);
97276
+ }
97027
97277
  const dirError = validateDirectory2(resolvedDirectory, workspaceAnchor);
97028
97278
  if (dirError) {
97029
97279
  const errorResult = {
@@ -101600,7 +101850,7 @@ function resolveDefaultReviewerAgent(generatedAgentNames) {
101600
101850
  }
101601
101851
  async function compileReviewPackage(directory, phase, sessionID, requireDiffSummary) {
101602
101852
  const lanes = await listLaneEvidence(directory, phase);
101603
- const persisted = _internals48.readPersisted?.(directory) ?? null;
101853
+ const persisted = _internals49.readPersisted?.(directory) ?? null;
101604
101854
  if (persisted) {
101605
101855
  let matchingRunState = null;
101606
101856
  for (const sessionState of Object.values(persisted.sessions)) {
@@ -101792,7 +102042,7 @@ Be specific and evidence-based. Do not approve a phase with unresolved degraded
101792
102042
  client.session.delete({ path: { id: sessionId } }).catch(() => {});
101793
102043
  }
101794
102044
  }
101795
- var _internals48 = {
102045
+ var _internals49 = {
101796
102046
  compileReviewPackage,
101797
102047
  parseReviewerVerdict,
101798
102048
  writeReviewerEvidence,
@@ -101809,28 +102059,28 @@ async function dispatchPhaseReviewer(directory, phase, sessionID, config3) {
101809
102059
  };
101810
102060
  const generatedAgentNames = swarmState.generatedAgentNames;
101811
102061
  const agentName = mergedConfig.reviewerAgent || resolveDefaultReviewerAgent(generatedAgentNames);
101812
- const pkg = await _internals48.compileReviewPackage(directory, phase, sessionID, mergedConfig.requireDiffSummary);
102062
+ const pkg = await _internals49.compileReviewPackage(directory, phase, sessionID, mergedConfig.requireDiffSummary);
101813
102063
  let responseText;
101814
102064
  try {
101815
- responseText = await _internals48.dispatchReviewerAgent(directory, pkg, agentName, mergedConfig.timeoutMs);
102065
+ responseText = await _internals49.dispatchReviewerAgent(directory, pkg, agentName, mergedConfig.timeoutMs);
101816
102066
  } catch (error93) {
101817
- const evidencePath2 = await _internals48.writeReviewerEvidence(directory, phase, "REJECTED", error93 instanceof Error ? error93.message : String(error93));
102067
+ const evidencePath2 = await _internals49.writeReviewerEvidence(directory, phase, "REJECTED", error93 instanceof Error ? error93.message : String(error93));
101818
102068
  return {
101819
102069
  verdict: "REJECTED",
101820
102070
  reason: `Reviewer dispatch failed: ${error93 instanceof Error ? error93.message : String(error93)}`,
101821
102071
  evidencePath: evidencePath2
101822
102072
  };
101823
102073
  }
101824
- const parsed = _internals48.parseReviewerVerdict(responseText);
102074
+ const parsed = _internals49.parseReviewerVerdict(responseText);
101825
102075
  if (!parsed) {
101826
- const evidencePath2 = await _internals48.writeReviewerEvidence(directory, phase, "REJECTED", "Reviewer response could not be parsed");
102076
+ const evidencePath2 = await _internals49.writeReviewerEvidence(directory, phase, "REJECTED", "Reviewer response could not be parsed");
101827
102077
  return {
101828
102078
  verdict: "REJECTED",
101829
102079
  reason: "Reviewer response could not be parsed",
101830
102080
  evidencePath: evidencePath2
101831
102081
  };
101832
102082
  }
101833
- const evidencePath = await _internals48.writeReviewerEvidence(directory, phase, parsed.verdict, parsed.reason);
102083
+ const evidencePath = await _internals49.writeReviewerEvidence(directory, phase, parsed.verdict, parsed.reason);
101834
102084
  return {
101835
102085
  verdict: parsed.verdict,
101836
102086
  reason: parsed.reason,
@@ -102336,7 +102586,7 @@ ${fileList}
102336
102586
 
102337
102587
  // src/tools/lean-turbo-run-phase.ts
102338
102588
  init_create_tool();
102339
- var _internals49 = {
102589
+ var _internals50 = {
102340
102590
  LeanTurboRunner,
102341
102591
  loadPluginConfigWithMeta
102342
102592
  };
@@ -102346,9 +102596,9 @@ async function executeLeanTurboRunPhase(args2) {
102346
102596
  let runError = null;
102347
102597
  let runner = null;
102348
102598
  try {
102349
- const { config: config3 } = _internals49.loadPluginConfigWithMeta(directory);
102599
+ const { config: config3 } = _internals50.loadPluginConfigWithMeta(directory);
102350
102600
  const leanConfig = config3.turbo?.strategy === "lean" ? config3.turbo.lean : undefined;
102351
- runner = new _internals49.LeanTurboRunner({
102601
+ runner = new _internals50.LeanTurboRunner({
102352
102602
  directory,
102353
102603
  sessionID,
102354
102604
  opencodeClient: swarmState.opencodeClient ?? null,
@@ -102702,7 +102952,7 @@ function isStaticallyEquivalent(originalCode, mutatedCode) {
102702
102952
  const strippedMutated = stripCode(mutatedCode);
102703
102953
  return strippedOriginal === strippedMutated;
102704
102954
  }
102705
- var _internals50 = {
102955
+ var _internals51 = {
102706
102956
  isStaticallyEquivalent,
102707
102957
  checkEquivalence,
102708
102958
  batchCheckEquivalence
@@ -102742,7 +102992,7 @@ async function batchCheckEquivalence(patches, llmJudge) {
102742
102992
  const results = [];
102743
102993
  for (const { patch, originalCode, mutatedCode } of patches) {
102744
102994
  try {
102745
- const result = await _internals50.checkEquivalence(patch, originalCode, mutatedCode, llmJudge);
102995
+ const result = await _internals51.checkEquivalence(patch, originalCode, mutatedCode, llmJudge);
102746
102996
  results.push(result);
102747
102997
  } catch (err3) {
102748
102998
  results.push({
@@ -102761,7 +103011,7 @@ async function batchCheckEquivalence(patches, llmJudge) {
102761
103011
  var MUTATION_TIMEOUT_MS = 30000;
102762
103012
  var TOTAL_BUDGET_MS = 300000;
102763
103013
  var GIT_APPLY_TIMEOUT_MS = 5000;
102764
- var _internals51 = {
103014
+ var _internals52 = {
102765
103015
  executeMutation,
102766
103016
  computeReport,
102767
103017
  executeMutationSuite,
@@ -102793,7 +103043,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
102793
103043
  };
102794
103044
  }
102795
103045
  try {
102796
- const applyResult = _internals51.spawnSync("git", ["apply", "--", patchFile], {
103046
+ const applyResult = _internals52.spawnSync("git", ["apply", "--", patchFile], {
102797
103047
  cwd: workingDir,
102798
103048
  timeout: GIT_APPLY_TIMEOUT_MS,
102799
103049
  stdio: "pipe"
@@ -102822,7 +103072,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
102822
103072
  }
102823
103073
  let testPassed = false;
102824
103074
  try {
102825
- const spawnResult = _internals51.spawnSync(testCommand[0], testCommand.slice(1), {
103075
+ const spawnResult = _internals52.spawnSync(testCommand[0], testCommand.slice(1), {
102826
103076
  cwd: workingDir,
102827
103077
  timeout: MUTATION_TIMEOUT_MS,
102828
103078
  stdio: "pipe"
@@ -102855,7 +103105,7 @@ async function executeMutation(patch, testCommand, _testFiles, workingDir) {
102855
103105
  } finally {
102856
103106
  if (patchFile) {
102857
103107
  try {
102858
- const revertResult = _internals51.spawnSync("git", ["apply", "-R", "--", patchFile], {
103108
+ const revertResult = _internals52.spawnSync("git", ["apply", "-R", "--", patchFile], {
102859
103109
  cwd: workingDir,
102860
103110
  timeout: GIT_APPLY_TIMEOUT_MS,
102861
103111
  stdio: "pipe"
@@ -103048,7 +103298,7 @@ async function executeMutationSuite(patches, testCommand, testFiles, workingDir,
103048
103298
  }
103049
103299
 
103050
103300
  // src/mutation/gate.ts
103051
- var _internals52 = {
103301
+ var _internals53 = {
103052
103302
  evaluateMutationGate,
103053
103303
  buildTestImprovementPrompt,
103054
103304
  buildMessage
@@ -103069,8 +103319,8 @@ function evaluateMutationGate(report, passThreshold = PASS_THRESHOLD, warnThresh
103069
103319
  } else {
103070
103320
  verdict = "fail";
103071
103321
  }
103072
- const testImprovementPrompt = _internals52.buildTestImprovementPrompt(report, passThreshold, verdict);
103073
- const message = _internals52.buildMessage(verdict, adjustedKillRate, report.killed, report.totalMutants, report.equivalent, warnThreshold);
103322
+ const testImprovementPrompt = _internals53.buildTestImprovementPrompt(report, passThreshold, verdict);
103323
+ const message = _internals53.buildMessage(verdict, adjustedKillRate, report.killed, report.totalMutants, report.equivalent, warnThreshold);
103074
103324
  return {
103075
103325
  verdict,
103076
103326
  killRate: report.killRate,
@@ -103122,6 +103372,7 @@ function buildMessage(verdict, adjustedKillRate, killed, totalMutants, equivalen
103122
103372
 
103123
103373
  // src/tools/mutation-test.ts
103124
103374
  init_create_tool();
103375
+ init_resolve_working_directory();
103125
103376
  var mutation_test = createSwarmTool({
103126
103377
  description: "Execute mutation testing with pre-generated patches — applies each mutant patch, runs tests, and evaluates kill rate against quality gate thresholds. Returns verdict (pass/warn/fail) with per-function kill rates and survived mutant details.",
103127
103378
  args: {
@@ -103166,7 +103417,11 @@ var mutation_test = createSwarmTool({
103166
103417
  success: false
103167
103418
  }, null, 2);
103168
103419
  }
103169
- const cwd = typedArgs.working_directory || directory || process.cwd();
103420
+ const resolved = resolveWorkingDirectory(typedArgs.working_directory, directory);
103421
+ if (!resolved.success) {
103422
+ return JSON.stringify({ success: false, error: resolved.message }, null, 2);
103423
+ }
103424
+ const cwd = resolved.directory;
103170
103425
  const passThreshold = typedArgs.pass_threshold ?? 0.8;
103171
103426
  const warnThreshold = typedArgs.warn_threshold ?? 0.6;
103172
103427
  const sourceFiles = new Map;
@@ -103380,6 +103635,7 @@ var syntax_check = createSwarmTool({
103380
103635
  init_zod();
103381
103636
  init_analyzer();
103382
103637
  init_create_tool();
103638
+ init_resolve_working_directory();
103383
103639
  var test_impact = createSwarmTool({
103384
103640
  description: "Analyze which test files are impacted by changes to the given source files. Returns TestImpactResult with impactedTests, untestedFiles, and the full impact map.",
103385
103641
  args: {
@@ -103395,7 +103651,11 @@ var test_impact = createSwarmTool({
103395
103651
  success: false
103396
103652
  }, null, 2);
103397
103653
  }
103398
- const cwd = typedArgs.working_directory || directory || process.cwd();
103654
+ const resolved = resolveWorkingDirectory(typedArgs.working_directory, directory);
103655
+ if (!resolved.success) {
103656
+ return JSON.stringify({ error: resolved.message, success: false }, null, 2);
103657
+ }
103658
+ const cwd = resolved.directory;
103399
103659
  const result = await analyzeImpact(typedArgs.changedFiles, cwd);
103400
103660
  return JSON.stringify(result, null, 2);
103401
103661
  } catch (e) {
@@ -103687,7 +103947,7 @@ import * as path135 from "node:path";
103687
103947
  init_bun_compat();
103688
103948
  import * as fs104 from "node:fs";
103689
103949
  import * as path134 from "node:path";
103690
- var _internals53 = { bunSpawn };
103950
+ var _internals54 = { bunSpawn };
103691
103951
  var _swarmGitExcludedChecked = false;
103692
103952
  function fileCoversSwarm(content) {
103693
103953
  for (const rawLine of content.split(`
@@ -103720,7 +103980,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
103720
103980
  checkIgnoreExitCode
103721
103981
  ] = await Promise.all([
103722
103982
  (async () => {
103723
- const proc = _internals53.bunSpawn(["git", "-C", directory, "rev-parse", "--show-toplevel"], GIT_SPAWN_OPTIONS);
103983
+ const proc = _internals54.bunSpawn(["git", "-C", directory, "rev-parse", "--show-toplevel"], GIT_SPAWN_OPTIONS);
103724
103984
  try {
103725
103985
  return await Promise.all([proc.exited, proc.stdout.text()]);
103726
103986
  } finally {
@@ -103730,7 +103990,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
103730
103990
  }
103731
103991
  })(),
103732
103992
  (async () => {
103733
- const proc = _internals53.bunSpawn(["git", "-C", directory, "rev-parse", "--git-path", "info/exclude"], GIT_SPAWN_OPTIONS);
103993
+ const proc = _internals54.bunSpawn(["git", "-C", directory, "rev-parse", "--git-path", "info/exclude"], GIT_SPAWN_OPTIONS);
103734
103994
  try {
103735
103995
  return await Promise.all([proc.exited, proc.stdout.text()]);
103736
103996
  } finally {
@@ -103740,7 +104000,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
103740
104000
  }
103741
104001
  })(),
103742
104002
  (async () => {
103743
- const proc = _internals53.bunSpawn(["git", "-C", directory, "check-ignore", "-q", ".swarm/.gitkeep"], GIT_SPAWN_OPTIONS);
104003
+ const proc = _internals54.bunSpawn(["git", "-C", directory, "check-ignore", "-q", ".swarm/.gitkeep"], GIT_SPAWN_OPTIONS);
103744
104004
  try {
103745
104005
  return await proc.exited;
103746
104006
  } finally {
@@ -103779,7 +104039,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
103779
104039
  }
103780
104040
  } catch {}
103781
104041
  }
103782
- const trackedProc = _internals53.bunSpawn(["git", "-C", directory, "ls-files", "--", ".swarm"], GIT_SPAWN_OPTIONS);
104042
+ const trackedProc = _internals54.bunSpawn(["git", "-C", directory, "ls-files", "--", ".swarm"], GIT_SPAWN_OPTIONS);
103783
104043
  let trackedExitCode;
103784
104044
  let trackedOutput;
103785
104045
  try {
@@ -103804,7 +104064,7 @@ async function ensureSwarmGitExcluded(directory, options = {}) {
103804
104064
  }
103805
104065
 
103806
104066
  // src/hooks/diff-scope.ts
103807
- var _internals54 = { bunSpawn };
104067
+ var _internals55 = { bunSpawn };
103808
104068
  function getDeclaredScope(taskId, directory) {
103809
104069
  try {
103810
104070
  const planPath = path135.join(directory, ".swarm", "plan.json");
@@ -103839,7 +104099,7 @@ var GIT_DIFF_SPAWN_OPTIONS = {
103839
104099
  };
103840
104100
  async function getChangedFiles(directory) {
103841
104101
  try {
103842
- const proc = _internals54.bunSpawn(["git", "diff", "--name-only", "HEAD~1"], {
104102
+ const proc = _internals55.bunSpawn(["git", "diff", "--name-only", "HEAD~1"], {
103843
104103
  cwd: directory,
103844
104104
  ...GIT_DIFF_SPAWN_OPTIONS
103845
104105
  });
@@ -103856,7 +104116,7 @@ async function getChangedFiles(directory) {
103856
104116
  return stdout.trim().split(`
103857
104117
  `).map((f) => f.trim()).filter((f) => f.length > 0);
103858
104118
  }
103859
- const proc2 = _internals54.bunSpawn(["git", "diff", "--name-only", "HEAD"], {
104119
+ const proc2 = _internals55.bunSpawn(["git", "diff", "--name-only", "HEAD"], {
103860
104120
  cwd: directory,
103861
104121
  ...GIT_DIFF_SPAWN_OPTIONS
103862
104122
  });
@@ -103914,7 +104174,7 @@ init_telemetry();
103914
104174
  init_file_locks();
103915
104175
  import * as fs106 from "node:fs";
103916
104176
  import * as path136 from "node:path";
103917
- var _internals55 = {
104177
+ var _internals56 = {
103918
104178
  listActiveLocks,
103919
104179
  verifyLeanTurboTaskCompletion
103920
104180
  };
@@ -104056,7 +104316,7 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
104056
104316
  }
104057
104317
  };
104058
104318
  }
104059
- const activeLocks = _internals55.listActiveLocks(directory);
104319
+ const activeLocks = _internals56.listActiveLocks(directory);
104060
104320
  const laneLocks = activeLocks.filter((lock) => lock.laneId === lane.laneId);
104061
104321
  if (laneLocks.length > 0) {
104062
104322
  return {
@@ -104122,6 +104382,7 @@ function verifyLeanTurboTaskCompletion(directory, taskId, sessionID) {
104122
104382
  // src/tools/update-task-status.ts
104123
104383
  init_task_id();
104124
104384
  init_create_tool();
104385
+ init_resolve_working_directory();
104125
104386
  var VALID_STATUSES2 = [
104126
104387
  "pending",
104127
104388
  "in_progress",
@@ -104171,7 +104432,7 @@ function hasPassedDurableGateEvidence(workingDirectory, taskId) {
104171
104432
  }
104172
104433
  return evidence.required_gates.every((gate) => evidence.gates?.[gate] != null);
104173
104434
  }
104174
- function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = false, sessionID) {
104435
+ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = false, sessionID, fallbackDir) {
104175
104436
  try {
104176
104437
  let skipStandardTurboBypass = false;
104177
104438
  if (hasActiveLeanTurbo()) {
@@ -104212,16 +104473,28 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
104212
104473
  }
104213
104474
  } catch {}
104214
104475
  }
104215
- const resolvedDir = workingDirectory ?? process.cwd();
104476
+ let resolvedDir;
104477
+ if (fallbackDir) {
104478
+ const resolveResult = resolveWorkingDirectory(workingDirectory, fallbackDir);
104479
+ if (resolveResult.success) {
104480
+ resolvedDir = resolveResult.directory;
104481
+ } else {
104482
+ resolvedDir = fallbackDir;
104483
+ }
104484
+ } else if (workingDirectory) {
104485
+ resolvedDir = workingDirectory;
104486
+ }
104216
104487
  let evidenceIncompleteReason = null;
104217
104488
  try {
104218
- const evidence = readTaskEvidenceRaw(resolvedDir, taskId);
104219
- if (evidence === null) {} else if (evidence.required_gates && Array.isArray(evidence.required_gates) && evidence.gates) {
104220
- if (evidence.required_gates.length > 0 && evidence.required_gates.every((gate) => evidence.gates[gate] != null)) {
104221
- return { blocked: false, reason: "" };
104489
+ if (!resolvedDir) {} else {
104490
+ const evidence = readTaskEvidenceRaw(resolvedDir, taskId);
104491
+ if (evidence === null) {} else if (evidence.required_gates && Array.isArray(evidence.required_gates) && evidence.gates) {
104492
+ if (evidence.required_gates.length > 0 && evidence.required_gates.every((gate) => evidence.gates[gate] != null)) {
104493
+ return { blocked: false, reason: "" };
104494
+ }
104495
+ const missingGates = evidence.required_gates.filter((gate) => evidence.gates[gate] == null);
104496
+ evidenceIncompleteReason = evidence.required_gates.length === 0 ? `Task ${taskId} has an evidence file with no required gates. Delegate reviewer and test_engineer before marking task as completed.` : `Task ${taskId} is missing required gates: [${missingGates.join(", ")}]. ` + `Required: [${evidence.required_gates.join(", ")}]. ` + `Completed: [${Object.keys(evidence.gates).join(", ")}]. ` + `Delegate the missing gate agents before marking task as completed.`;
104222
104497
  }
104223
- const missingGates = evidence.required_gates.filter((gate) => evidence.gates[gate] == null);
104224
- evidenceIncompleteReason = evidence.required_gates.length === 0 ? `Task ${taskId} has an evidence file with no required gates. Delegate reviewer and test_engineer before marking task as completed.` : `Task ${taskId} is missing required gates: [${missingGates.join(", ")}]. ` + `Required: [${evidence.required_gates.join(", ")}]. ` + `Completed: [${Object.keys(evidence.gates).join(", ")}]. ` + `Delegate the missing gate agents before marking task as completed.`;
104225
104498
  }
104226
104499
  } catch (error93) {
104227
104500
  console.warn(`[gate-evidence] Evidence file for task ${taskId} is corrupt or unreadable:`, error93 instanceof Error ? error93.message : String(error93));
@@ -104258,19 +104531,20 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
104258
104531
  const state = getTaskState(session, taskId);
104259
104532
  stateEntries.push(`${sessionId}: ${state}`);
104260
104533
  }
104261
- try {
104262
- const resolvedDir2 = workingDirectory;
104263
- const planPath = path137.join(resolvedDir2, ".swarm", "plan.json");
104264
- const planRaw = fs107.readFileSync(planPath, "utf-8");
104265
- const plan = JSON.parse(planRaw);
104266
- for (const planPhase of plan.phases ?? []) {
104267
- for (const task of planPhase.tasks ?? []) {
104268
- if (task.id === taskId && task.status === "completed" && hasPassedDurableGateEvidence(resolvedDir2, taskId)) {
104269
- return { blocked: false, reason: "" };
104534
+ if (resolvedDir) {
104535
+ try {
104536
+ const planPath = path137.join(resolvedDir, ".swarm", "plan.json");
104537
+ const planRaw = fs107.readFileSync(planPath, "utf-8");
104538
+ const plan = JSON.parse(planRaw);
104539
+ for (const planPhase of plan.phases ?? []) {
104540
+ for (const task of planPhase.tasks ?? []) {
104541
+ if (task.id === taskId && task.status === "completed" && hasPassedDurableGateEvidence(resolvedDir, taskId)) {
104542
+ return { blocked: false, reason: "" };
104543
+ }
104270
104544
  }
104271
104545
  }
104272
- }
104273
- } catch {}
104546
+ } catch {}
104547
+ }
104274
104548
  {
104275
104549
  let hasReviewer = false;
104276
104550
  let hasTestEngineer = false;
@@ -104289,6 +104563,23 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
104289
104563
  if (hasReviewer && hasTestEngineer) {
104290
104564
  return { blocked: false, reason: "" };
104291
104565
  }
104566
+ if (!evidenceIncompleteReason && (!hasReviewer || !hasTestEngineer)) {
104567
+ for (const [, chain] of swarmState.delegationChains) {
104568
+ const hasCoder = chain.some((d) => stripKnownSwarmPrefix(d.to) === "coder");
104569
+ if (hasCoder)
104570
+ continue;
104571
+ for (const delegation of chain) {
104572
+ const target = stripKnownSwarmPrefix(delegation.to);
104573
+ if (target === "reviewer")
104574
+ hasReviewer = true;
104575
+ if (target === "test_engineer")
104576
+ hasTestEngineer = true;
104577
+ }
104578
+ }
104579
+ if (hasReviewer && hasTestEngineer) {
104580
+ return { blocked: false, reason: "" };
104581
+ }
104582
+ }
104292
104583
  }
104293
104584
  const currentStateStr = stateEntries.length > 0 ? stateEntries.join(", ") : "no active sessions";
104294
104585
  const chainEntries = [];
@@ -104321,9 +104612,9 @@ function checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled = fal
104321
104612
  return { blocked: false, reason: "" };
104322
104613
  }
104323
104614
  }
104324
- async function checkReviewerGateWithScope(taskId, workingDirectory, sessionID) {
104615
+ async function checkReviewerGateWithScope(taskId, workingDirectory, sessionID, fallbackDir) {
104325
104616
  const stageBParallelEnabled = true;
104326
- const result = checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled, sessionID);
104617
+ const result = checkReviewerGate(taskId, workingDirectory, stageBParallelEnabled, sessionID, fallbackDir);
104327
104618
  const scopeWarning = await validateDiffScope(taskId, workingDirectory).catch(() => null);
104328
104619
  if (!scopeWarning)
104329
104620
  return result;
@@ -104348,10 +104639,36 @@ function recoverTaskStateFromDelegations(taskId, directory) {
104348
104639
  }
104349
104640
  }
104350
104641
  }
104642
+ let hasDurableIncompleteGates = false;
104643
+ if (directory) {
104644
+ try {
104645
+ const taskEvidence = readTaskEvidenceRaw(directory, taskId);
104646
+ if (taskEvidence?.gates && Array.isArray(taskEvidence.required_gates) && taskEvidence.required_gates.length > 0) {
104647
+ const gates = taskEvidence.gates;
104648
+ hasDurableIncompleteGates = taskEvidence.required_gates.some((g) => gates[g] == null);
104649
+ }
104650
+ } catch {
104651
+ hasDurableIncompleteGates = true;
104652
+ }
104653
+ }
104654
+ if (!hasDurableIncompleteGates && (!hasReviewer || !hasTestEngineer)) {
104655
+ for (const [, chain] of swarmState.delegationChains) {
104656
+ const hasCoder = chain.some((d) => stripKnownSwarmPrefix(d.to) === "coder");
104657
+ if (hasCoder)
104658
+ continue;
104659
+ for (const delegation of chain) {
104660
+ const target = stripKnownSwarmPrefix(delegation.to);
104661
+ if (target === "reviewer")
104662
+ hasReviewer = true;
104663
+ if (target === "test_engineer")
104664
+ hasTestEngineer = true;
104665
+ }
104666
+ }
104667
+ }
104351
104668
  if ((!hasReviewer || !hasTestEngineer) && directory) {
104352
104669
  try {
104353
104670
  const evidence = readTaskEvidenceRaw(directory, taskId);
104354
- if (evidence && evidence.gates && Array.isArray(evidence.required_gates)) {
104671
+ if (evidence?.gates && Array.isArray(evidence.required_gates)) {
104355
104672
  if (evidence.gates.reviewer != null)
104356
104673
  hasReviewer = true;
104357
104674
  if (evidence.gates.test_engineer != null)
@@ -104485,6 +104802,19 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
104485
104802
  }
104486
104803
  directory = fallbackDir;
104487
104804
  }
104805
+ if (fallbackDir && directory !== fallbackDir) {
104806
+ const canonicalDir = fs107.realpathSync(path137.resolve(directory));
104807
+ const canonicalRoot = fs107.realpathSync(path137.resolve(fallbackDir));
104808
+ if (canonicalDir.startsWith(canonicalRoot + path137.sep)) {
104809
+ return {
104810
+ success: false,
104811
+ message: `Invalid working_directory: "${directory}" is a subdirectory of ` + `the project root "${fallbackDir}". Pass the project root path or ` + `omit working_directory entirely.`,
104812
+ errors: [
104813
+ `Subdirectory rejected: use project root "${fallbackDir}" instead`
104814
+ ]
104815
+ };
104816
+ }
104817
+ }
104488
104818
  if (args2.status === "in_progress") {
104489
104819
  try {
104490
104820
  const evidencePath = path137.join(directory, ".swarm", "evidence", `${args2.task_id}.json`);
@@ -104494,7 +104824,7 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
104494
104824
  try {
104495
104825
  fs107.writeSync(fd, JSON.stringify({
104496
104826
  taskId: args2.task_id,
104497
- required_gates: ["reviewer", "test_engineer"],
104827
+ required_gates: [],
104498
104828
  gates: {}
104499
104829
  }, null, 2));
104500
104830
  writeOk = true;
@@ -104521,11 +104851,11 @@ async function executeUpdateTaskStatus(args2, fallbackDir, ctx) {
104521
104851
  }
104522
104852
  } catch {}
104523
104853
  if (phaseRequiresReviewer) {
104524
- const reviewerCheck = await checkReviewerGateWithScope(args2.task_id, directory, ctx?.sessionID);
104854
+ const reviewerCheck = await checkReviewerGateWithScope(args2.task_id, directory, ctx?.sessionID, fallbackDir);
104525
104855
  if (reviewerCheck.blocked) {
104526
104856
  return {
104527
104857
  success: false,
104528
- message: "Gate check failed: reviewer delegation required before marking task as completed",
104858
+ message: "Gate check failed: required QA gates not yet satisfied for task " + args2.task_id,
104529
104859
  errors: [reviewerCheck.reason]
104530
104860
  };
104531
104861
  }