opencode-swarm 6.86.8 → 6.86.10

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/cli/index.js CHANGED
@@ -17669,14 +17669,14 @@ __export(exports_config_doctor, {
17669
17669
  });
17670
17670
  import * as crypto3 from "crypto";
17671
17671
  import * as fs8 from "fs";
17672
- import * as os5 from "os";
17673
- import * as path18 from "path";
17672
+ import * as os6 from "os";
17673
+ import * as path19 from "path";
17674
17674
  function getUserConfigDir3() {
17675
- return process.env.XDG_CONFIG_HOME || path18.join(os5.homedir(), ".config");
17675
+ return process.env.XDG_CONFIG_HOME || path19.join(os6.homedir(), ".config");
17676
17676
  }
17677
17677
  function getConfigPaths(directory) {
17678
- const userConfigPath = path18.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
17679
- const projectConfigPath = path18.join(directory, ".opencode", "opencode-swarm.json");
17678
+ const userConfigPath = path19.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
17679
+ const projectConfigPath = path19.join(directory, ".opencode", "opencode-swarm.json");
17680
17680
  return { userConfigPath, projectConfigPath };
17681
17681
  }
17682
17682
  function computeHash(content) {
@@ -17701,9 +17701,9 @@ function isValidConfigPath(configPath, directory) {
17701
17701
  const normalizedUser = userConfigPath.replace(/\\/g, "/");
17702
17702
  const normalizedProject = projectConfigPath.replace(/\\/g, "/");
17703
17703
  try {
17704
- const resolvedConfig = path18.resolve(configPath);
17705
- const resolvedUser = path18.resolve(normalizedUser);
17706
- const resolvedProject = path18.resolve(normalizedProject);
17704
+ const resolvedConfig = path19.resolve(configPath);
17705
+ const resolvedUser = path19.resolve(normalizedUser);
17706
+ const resolvedProject = path19.resolve(normalizedProject);
17707
17707
  return resolvedConfig === resolvedUser || resolvedConfig === resolvedProject;
17708
17708
  } catch {
17709
17709
  return false;
@@ -17743,12 +17743,12 @@ function createConfigBackup(directory) {
17743
17743
  };
17744
17744
  }
17745
17745
  function writeBackupArtifact(directory, backup) {
17746
- const swarmDir = path18.join(directory, ".swarm");
17746
+ const swarmDir = path19.join(directory, ".swarm");
17747
17747
  if (!fs8.existsSync(swarmDir)) {
17748
17748
  fs8.mkdirSync(swarmDir, { recursive: true });
17749
17749
  }
17750
17750
  const backupFilename = `config-backup-${backup.createdAt}.json`;
17751
- const backupPath = path18.join(swarmDir, backupFilename);
17751
+ const backupPath = path19.join(swarmDir, backupFilename);
17752
17752
  const artifact = {
17753
17753
  createdAt: backup.createdAt,
17754
17754
  configPath: backup.configPath,
@@ -17778,7 +17778,7 @@ function restoreFromBackup(backupPath, directory) {
17778
17778
  return null;
17779
17779
  }
17780
17780
  const targetPath = artifact.configPath;
17781
- const targetDir = path18.dirname(targetPath);
17781
+ const targetDir = path19.dirname(targetPath);
17782
17782
  if (!fs8.existsSync(targetDir)) {
17783
17783
  fs8.mkdirSync(targetDir, { recursive: true });
17784
17784
  }
@@ -17809,9 +17809,9 @@ function readConfigFromFile(directory) {
17809
17809
  return null;
17810
17810
  }
17811
17811
  }
17812
- function validateConfigKey(path19, value, _config) {
17812
+ function validateConfigKey(path20, value, _config) {
17813
17813
  const findings = [];
17814
- switch (path19) {
17814
+ switch (path20) {
17815
17815
  case "agents": {
17816
17816
  if (value !== undefined) {
17817
17817
  findings.push({
@@ -18058,27 +18058,27 @@ function validateConfigKey(path19, value, _config) {
18058
18058
  }
18059
18059
  return findings;
18060
18060
  }
18061
- function walkConfigAndValidate(obj, path19, config3, findings) {
18061
+ function walkConfigAndValidate(obj, path20, config3, findings) {
18062
18062
  if (obj === null || obj === undefined) {
18063
18063
  return;
18064
18064
  }
18065
- if (path19 && typeof obj === "object" && !Array.isArray(obj)) {
18066
- const keyFindings = validateConfigKey(path19, obj, config3);
18065
+ if (path20 && typeof obj === "object" && !Array.isArray(obj)) {
18066
+ const keyFindings = validateConfigKey(path20, obj, config3);
18067
18067
  findings.push(...keyFindings);
18068
18068
  }
18069
18069
  if (typeof obj !== "object") {
18070
- const keyFindings = validateConfigKey(path19, obj, config3);
18070
+ const keyFindings = validateConfigKey(path20, obj, config3);
18071
18071
  findings.push(...keyFindings);
18072
18072
  return;
18073
18073
  }
18074
18074
  if (Array.isArray(obj)) {
18075
18075
  obj.forEach((item, index) => {
18076
- walkConfigAndValidate(item, `${path19}[${index}]`, config3, findings);
18076
+ walkConfigAndValidate(item, `${path20}[${index}]`, config3, findings);
18077
18077
  });
18078
18078
  return;
18079
18079
  }
18080
18080
  for (const [key, value] of Object.entries(obj)) {
18081
- const newPath = path19 ? `${path19}.${key}` : key;
18081
+ const newPath = path20 ? `${path20}.${key}` : key;
18082
18082
  walkConfigAndValidate(value, newPath, config3, findings);
18083
18083
  }
18084
18084
  }
@@ -18198,7 +18198,7 @@ function applySafeAutoFixes(directory, result) {
18198
18198
  }
18199
18199
  }
18200
18200
  if (appliedFixes.length > 0) {
18201
- const configDir = path18.dirname(configPath);
18201
+ const configDir = path19.dirname(configPath);
18202
18202
  if (!fs8.existsSync(configDir)) {
18203
18203
  fs8.mkdirSync(configDir, { recursive: true });
18204
18204
  }
@@ -18208,12 +18208,12 @@ function applySafeAutoFixes(directory, result) {
18208
18208
  return { appliedFixes, updatedConfigPath };
18209
18209
  }
18210
18210
  function writeDoctorArtifact(directory, result) {
18211
- const swarmDir = path18.join(directory, ".swarm");
18211
+ const swarmDir = path19.join(directory, ".swarm");
18212
18212
  if (!fs8.existsSync(swarmDir)) {
18213
18213
  fs8.mkdirSync(swarmDir, { recursive: true });
18214
18214
  }
18215
18215
  const artifactFilename = "config-doctor.json";
18216
- const artifactPath = path18.join(swarmDir, artifactFilename);
18216
+ const artifactPath = path19.join(swarmDir, artifactFilename);
18217
18217
  const guiOutput = {
18218
18218
  timestamp: result.timestamp,
18219
18219
  summary: result.summary,
@@ -18575,12 +18575,12 @@ var init_evidence_summary_service = __esm(() => {
18575
18575
 
18576
18576
  // src/cli/index.ts
18577
18577
  import * as fs21 from "fs";
18578
- import * as os6 from "os";
18579
- import * as path32 from "path";
18578
+ import * as os7 from "os";
18579
+ import * as path33 from "path";
18580
18580
  // package.json
18581
18581
  var package_default = {
18582
18582
  name: "opencode-swarm",
18583
- version: "6.86.8",
18583
+ version: "6.86.10",
18584
18584
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
18585
18585
  main: "dist/index.js",
18586
18586
  types: "dist/index.d.ts",
@@ -20170,6 +20170,7 @@ function getEffectiveGates(profile, sessionOverrides) {
20170
20170
 
20171
20171
  // src/hooks/delegation-gate.ts
20172
20172
  init_telemetry();
20173
+ init_logger();
20173
20174
 
20174
20175
  // node_modules/quick-lru/index.js
20175
20176
  class QuickLRU extends Map {
@@ -20533,6 +20534,7 @@ function clearAllScopes(directory) {
20533
20534
  // src/hooks/guardrails.ts
20534
20535
  init_telemetry();
20535
20536
  init_utils();
20537
+ init_logger();
20536
20538
 
20537
20539
  // src/hooks/conflict-resolution.ts
20538
20540
  init_telemetry();
@@ -35625,6 +35627,7 @@ function getGlobalEventBus() {
35625
35627
 
35626
35628
  // src/hooks/curator.ts
35627
35629
  init_manager();
35630
+ init_logger();
35628
35631
  init_utils2();
35629
35632
 
35630
35633
  // src/hooks/hive-promoter.ts
@@ -36269,31 +36272,49 @@ async function handleDarkMatterCommand(directory, args) {
36269
36272
  // src/services/diagnose-service.ts
36270
36273
  import * as child_process4 from "child_process";
36271
36274
  import { existsSync as existsSync9, readdirSync as readdirSync4, readFileSync as readFileSync6, statSync as statSync5 } from "fs";
36272
- import path17 from "path";
36275
+ import path18 from "path";
36273
36276
  import { fileURLToPath } from "url";
36277
+
36278
+ // src/config/cache-paths.ts
36279
+ import * as os5 from "os";
36280
+ import * as path17 from "path";
36281
+ function getPluginConfigDir() {
36282
+ return path17.join(process.env.XDG_CONFIG_HOME || path17.join(os5.homedir(), ".config"), "opencode");
36283
+ }
36284
+ function getPluginCachePaths() {
36285
+ const cacheBase = process.env.XDG_CACHE_HOME || path17.join(os5.homedir(), ".cache");
36286
+ const configDir = getPluginConfigDir();
36287
+ return [
36288
+ path17.join(cacheBase, "opencode", "packages", "opencode-swarm@latest"),
36289
+ path17.join(configDir, "node_modules", "opencode-swarm"),
36290
+ path17.join(cacheBase, "opencode", "node_modules", "opencode-swarm")
36291
+ ];
36292
+ }
36293
+
36294
+ // src/services/diagnose-service.ts
36274
36295
  init_manager2();
36275
36296
  init_utils2();
36276
36297
  init_manager();
36277
36298
 
36278
36299
  // src/services/version-check.ts
36279
36300
  import { existsSync as existsSync8, mkdirSync as mkdirSync8, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
36280
- import { homedir as homedir4 } from "os";
36281
- import { join as join14 } from "path";
36301
+ import { homedir as homedir5 } from "os";
36302
+ import { join as join15 } from "path";
36282
36303
  var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
36283
36304
  function cacheDir() {
36284
36305
  const xdg = process.env.XDG_CACHE_HOME;
36285
- const base = xdg && xdg.length > 0 ? xdg : join14(homedir4(), ".cache");
36286
- return join14(base, "opencode-swarm");
36306
+ const base = xdg && xdg.length > 0 ? xdg : join15(homedir5(), ".cache");
36307
+ return join15(base, "opencode-swarm");
36287
36308
  }
36288
36309
  function cacheFile() {
36289
- return join14(cacheDir(), "version-check.json");
36310
+ return join15(cacheDir(), "version-check.json");
36290
36311
  }
36291
36312
  function readVersionCache() {
36292
36313
  try {
36293
- const path17 = cacheFile();
36294
- if (!existsSync8(path17))
36314
+ const path18 = cacheFile();
36315
+ if (!existsSync8(path18))
36295
36316
  return null;
36296
- const raw = readFileSync5(path17, "utf-8");
36317
+ const raw = readFileSync5(path18, "utf-8");
36297
36318
  const parsed = JSON.parse(raw);
36298
36319
  if (typeof parsed?.checkedAt !== "number")
36299
36320
  return null;
@@ -36623,7 +36644,7 @@ async function checkSpecStaleness(directory, plan) {
36623
36644
  };
36624
36645
  }
36625
36646
  async function checkConfigParseability(directory) {
36626
- const configPath = path17.join(directory, ".opencode/opencode-swarm.json");
36647
+ const configPath = path18.join(directory, ".opencode/opencode-swarm.json");
36627
36648
  if (!existsSync9(configPath)) {
36628
36649
  return {
36629
36650
  name: "Config Parseability",
@@ -36652,7 +36673,7 @@ function resolveGrammarDir(thisDir) {
36652
36673
  const normalized = thisDir.replace(/\\/g, "/");
36653
36674
  const isSource = normalized.endsWith("/src/services");
36654
36675
  const isCliBundle = normalized.endsWith("/cli");
36655
- return isSource || isCliBundle ? path17.join(thisDir, "..", "lang", "grammars") : path17.join(thisDir, "lang", "grammars");
36676
+ return isSource || isCliBundle ? path18.join(thisDir, "..", "lang", "grammars") : path18.join(thisDir, "lang", "grammars");
36656
36677
  }
36657
36678
  async function checkGrammarWasmFiles() {
36658
36679
  const grammarFiles = [
@@ -36676,14 +36697,14 @@ async function checkGrammarWasmFiles() {
36676
36697
  "tree-sitter-ini.wasm",
36677
36698
  "tree-sitter-regex.wasm"
36678
36699
  ];
36679
- const thisDir = path17.dirname(fileURLToPath(import.meta.url));
36700
+ const thisDir = path18.dirname(fileURLToPath(import.meta.url));
36680
36701
  const grammarDir = resolveGrammarDir(thisDir);
36681
36702
  const missing = [];
36682
- if (!existsSync9(path17.join(grammarDir, "tree-sitter.wasm"))) {
36703
+ if (!existsSync9(path18.join(grammarDir, "tree-sitter.wasm"))) {
36683
36704
  missing.push("tree-sitter.wasm (core runtime)");
36684
36705
  }
36685
36706
  for (const file3 of grammarFiles) {
36686
- if (!existsSync9(path17.join(grammarDir, file3))) {
36707
+ if (!existsSync9(path18.join(grammarDir, file3))) {
36687
36708
  missing.push(file3);
36688
36709
  }
36689
36710
  }
@@ -36701,7 +36722,7 @@ async function checkGrammarWasmFiles() {
36701
36722
  };
36702
36723
  }
36703
36724
  async function checkCheckpointManifest(directory) {
36704
- const manifestPath = path17.join(directory, ".swarm/checkpoints.json");
36725
+ const manifestPath = path18.join(directory, ".swarm/checkpoints.json");
36705
36726
  if (!existsSync9(manifestPath)) {
36706
36727
  return {
36707
36728
  name: "Checkpoint Manifest",
@@ -36753,7 +36774,7 @@ async function checkCheckpointManifest(directory) {
36753
36774
  }
36754
36775
  }
36755
36776
  async function checkEventStreamIntegrity(directory) {
36756
- const eventsPath = path17.join(directory, ".swarm/events.jsonl");
36777
+ const eventsPath = path18.join(directory, ".swarm/events.jsonl");
36757
36778
  if (!existsSync9(eventsPath)) {
36758
36779
  return {
36759
36780
  name: "Event Stream",
@@ -36794,7 +36815,7 @@ async function checkEventStreamIntegrity(directory) {
36794
36815
  }
36795
36816
  }
36796
36817
  async function checkSteeringDirectives(directory) {
36797
- const eventsPath = path17.join(directory, ".swarm/events.jsonl");
36818
+ const eventsPath = path18.join(directory, ".swarm/events.jsonl");
36798
36819
  if (!existsSync9(eventsPath)) {
36799
36820
  return {
36800
36821
  name: "Steering Directives",
@@ -36850,7 +36871,7 @@ async function checkCurator(directory) {
36850
36871
  detail: "Disabled (enable via curator.enabled)"
36851
36872
  };
36852
36873
  }
36853
- const summaryPath = path17.join(directory, ".swarm/curator-summary.json");
36874
+ const summaryPath = path18.join(directory, ".swarm/curator-summary.json");
36854
36875
  if (!existsSync9(summaryPath)) {
36855
36876
  return {
36856
36877
  name: "Curator",
@@ -37016,7 +37037,7 @@ async function getDiagnoseData(directory) {
37016
37037
  checks5.push(await checkSteeringDirectives(directory));
37017
37038
  checks5.push(await checkCurator(directory));
37018
37039
  try {
37019
- const evidenceDir = path17.join(directory, ".swarm", "evidence");
37040
+ const evidenceDir = path18.join(directory, ".swarm", "evidence");
37020
37041
  const snapshotFiles = existsSync9(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
37021
37042
  if (snapshotFiles.length > 0) {
37022
37043
  const latest = snapshotFiles.sort().pop();
@@ -37046,7 +37067,36 @@ async function getDiagnoseData(directory) {
37046
37067
  detail: `${deferredWarnings.length} warning(s) deferred from init (run with verbose logs for details)`
37047
37068
  });
37048
37069
  }
37049
- const passCount = checks5.filter((c) => c.status === "\u2705").length;
37070
+ const cachePaths = getPluginCachePaths();
37071
+ const cacheRows = [];
37072
+ for (const cachePath of cachePaths) {
37073
+ try {
37074
+ if (!existsSync9(cachePath)) {
37075
+ cacheRows.push(`\u2B1C ${cachePath} \u2014 absent`);
37076
+ continue;
37077
+ }
37078
+ const pkgJsonPath = path18.join(cachePath, "package.json");
37079
+ try {
37080
+ const raw = readFileSync6(pkgJsonPath, "utf-8");
37081
+ const parsed = JSON.parse(raw);
37082
+ const installedVersion = typeof parsed.version === "string" ? parsed.version : "?";
37083
+ cacheRows.push(`\u2705 ${cachePath} \u2014 v${installedVersion}`);
37084
+ } catch {
37085
+ cacheRows.push(`\u26A0\uFE0F ${cachePath} \u2014 present (package.json unreadable)`);
37086
+ }
37087
+ } catch {
37088
+ cacheRows.push(`\u26A0\uFE0F ${cachePath} \u2014 status unknown (read error)`);
37089
+ }
37090
+ }
37091
+ const hasCacheEntry = cacheRows.some((r) => r.startsWith("\u2705"));
37092
+ const hasCacheWarning = cacheRows.some((r) => r.startsWith("\u26A0\uFE0F"));
37093
+ const cacheStatus = hasCacheWarning ? "\u26A0\uFE0F" : hasCacheEntry ? "\u2705" : "\u2B1C";
37094
+ checks5.push({
37095
+ name: "Plugin Caches",
37096
+ status: cacheStatus,
37097
+ detail: cacheRows.join(" | ")
37098
+ });
37099
+ const passCount = checks5.filter((c) => c.status === "\u2705" || c.status === "\u2B1C").length;
37050
37100
  const totalCount = checks5.length;
37051
37101
  const allPassed = passCount === totalCount;
37052
37102
  return {
@@ -37084,15 +37134,15 @@ init_config_doctor();
37084
37134
 
37085
37135
  // src/services/tool-doctor.ts
37086
37136
  import * as fs10 from "fs";
37087
- import * as path20 from "path";
37137
+ import * as path21 from "path";
37088
37138
 
37089
37139
  // src/build/discovery.ts
37090
37140
  import * as fs9 from "fs";
37091
- import * as path19 from "path";
37141
+ import * as path20 from "path";
37092
37142
 
37093
37143
  // src/lang/detector.ts
37094
37144
  import { access as access2, readdir as readdir2 } from "fs/promises";
37095
- import { extname as extname2, join as join16 } from "path";
37145
+ import { extname as extname2, join as join17 } from "path";
37096
37146
 
37097
37147
  // src/lang/profiles.ts
37098
37148
  class LanguageRegistry {
@@ -38072,7 +38122,7 @@ async function detectProjectLanguages(projectDir) {
38072
38122
  if (detectFile.includes("*") || detectFile.includes("?"))
38073
38123
  continue;
38074
38124
  try {
38075
- await access2(join16(dir, detectFile));
38125
+ await access2(join17(dir, detectFile));
38076
38126
  detected.add(profile.id);
38077
38127
  break;
38078
38128
  } catch {}
@@ -38093,7 +38143,7 @@ async function detectProjectLanguages(projectDir) {
38093
38143
  const topEntries = await readdir2(projectDir, { withFileTypes: true });
38094
38144
  for (const entry of topEntries) {
38095
38145
  if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
38096
- await scanDir(join16(projectDir, entry.name));
38146
+ await scanDir(join17(projectDir, entry.name));
38097
38147
  }
38098
38148
  }
38099
38149
  } catch {}
@@ -38252,11 +38302,11 @@ function findBuildFiles(workingDir, patterns) {
38252
38302
  const regex = simpleGlobToRegex(pattern);
38253
38303
  const matches = files.filter((f) => regex.test(f));
38254
38304
  if (matches.length > 0) {
38255
- return path19.join(dir, matches[0]);
38305
+ return path20.join(dir, matches[0]);
38256
38306
  }
38257
38307
  } catch {}
38258
38308
  } else {
38259
- const filePath = path19.join(workingDir, pattern);
38309
+ const filePath = path20.join(workingDir, pattern);
38260
38310
  if (fs9.existsSync(filePath)) {
38261
38311
  return filePath;
38262
38312
  }
@@ -38265,7 +38315,7 @@ function findBuildFiles(workingDir, patterns) {
38265
38315
  return null;
38266
38316
  }
38267
38317
  function getRepoDefinedScripts(workingDir, scripts) {
38268
- const packageJsonPath = path19.join(workingDir, "package.json");
38318
+ const packageJsonPath = path20.join(workingDir, "package.json");
38269
38319
  if (!fs9.existsSync(packageJsonPath)) {
38270
38320
  return [];
38271
38321
  }
@@ -38306,7 +38356,7 @@ function findAllBuildFiles(workingDir) {
38306
38356
  const regex = simpleGlobToRegex(pattern);
38307
38357
  findFilesRecursive(workingDir, regex, allBuildFiles);
38308
38358
  } else {
38309
- const filePath = path19.join(workingDir, pattern);
38359
+ const filePath = path20.join(workingDir, pattern);
38310
38360
  if (fs9.existsSync(filePath)) {
38311
38361
  allBuildFiles.add(filePath);
38312
38362
  }
@@ -38319,7 +38369,7 @@ function findFilesRecursive(dir, regex, results) {
38319
38369
  try {
38320
38370
  const entries = fs9.readdirSync(dir, { withFileTypes: true });
38321
38371
  for (const entry of entries) {
38322
- const fullPath = path19.join(dir, entry.name);
38372
+ const fullPath = path20.join(dir, entry.name);
38323
38373
  if (entry.isDirectory() && !["node_modules", ".git", "dist", "build", "target"].includes(entry.name)) {
38324
38374
  findFilesRecursive(fullPath, regex, results);
38325
38375
  } else if (entry.isFile() && regex.test(entry.name)) {
@@ -38342,7 +38392,7 @@ async function discoverBuildCommandsFromProfiles(workingDir) {
38342
38392
  let foundCommand = false;
38343
38393
  for (const cmd of sortedCommands) {
38344
38394
  if (cmd.detectFile) {
38345
- const detectFilePath = path19.join(workingDir, cmd.detectFile);
38395
+ const detectFilePath = path20.join(workingDir, cmd.detectFile);
38346
38396
  if (!fs9.existsSync(detectFilePath)) {
38347
38397
  continue;
38348
38398
  }
@@ -38517,8 +38567,8 @@ function checkBinaryReadiness() {
38517
38567
  }
38518
38568
  function runToolDoctor(_directory, pluginRoot) {
38519
38569
  const findings = [];
38520
- const resolvedPluginRoot = pluginRoot ?? path20.resolve(import.meta.dir, "..", "..");
38521
- const indexPath = path20.join(resolvedPluginRoot, "src", "index.ts");
38570
+ const resolvedPluginRoot = pluginRoot ?? path21.resolve(import.meta.dir, "..", "..");
38571
+ const indexPath = path21.join(resolvedPluginRoot, "src", "index.ts");
38522
38572
  if (!fs10.existsSync(indexPath)) {
38523
38573
  return {
38524
38574
  findings: [
@@ -39438,13 +39488,14 @@ async function handleHistoryCommand(directory, _args) {
39438
39488
  return formatHistoryMarkdown(historyData);
39439
39489
  }
39440
39490
  // src/hooks/knowledge-migrator.ts
39491
+ init_logger();
39441
39492
  import { randomUUID as randomUUID2 } from "crypto";
39442
39493
  import { existsSync as existsSync13, readFileSync as readFileSync10 } from "fs";
39443
39494
  import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
39444
- import * as path21 from "path";
39495
+ import * as path22 from "path";
39445
39496
  async function migrateContextToKnowledge(directory, config3) {
39446
- const sentinelPath = path21.join(directory, ".swarm", ".knowledge-migrated");
39447
- const contextPath = path21.join(directory, ".swarm", "context.md");
39497
+ const sentinelPath = path22.join(directory, ".swarm", ".knowledge-migrated");
39498
+ const contextPath = path22.join(directory, ".swarm", "context.md");
39448
39499
  const knowledgePath = resolveSwarmKnowledgePath(directory);
39449
39500
  if (existsSync13(sentinelPath)) {
39450
39501
  return {
@@ -39535,7 +39586,7 @@ async function migrateContextToKnowledge(directory, config3) {
39535
39586
  await rewriteKnowledge(knowledgePath, existing);
39536
39587
  }
39537
39588
  await writeSentinel(sentinelPath, migrated, dropped);
39538
- console.log(`[knowledge-migrator] Migrated ${migrated} entries, dropped ${dropped}`);
39589
+ log(`[knowledge-migrator] Migrated ${migrated} entries, dropped ${dropped}`);
39539
39590
  return {
39540
39591
  migrated: true,
39541
39592
  entriesMigrated: migrated,
@@ -39640,7 +39691,7 @@ function truncateLesson(text) {
39640
39691
  return `${text.slice(0, 277)}...`;
39641
39692
  }
39642
39693
  function inferProjectName(directory) {
39643
- const packageJsonPath = path21.join(directory, "package.json");
39694
+ const packageJsonPath = path22.join(directory, "package.json");
39644
39695
  if (existsSync13(packageJsonPath)) {
39645
39696
  try {
39646
39697
  const pkg = JSON.parse(readFileSync10(packageJsonPath, "utf-8"));
@@ -39649,7 +39700,7 @@ function inferProjectName(directory) {
39649
39700
  }
39650
39701
  } catch {}
39651
39702
  }
39652
- return path21.basename(directory);
39703
+ return path22.basename(directory);
39653
39704
  }
39654
39705
  async function writeSentinel(sentinelPath, migrated, dropped) {
39655
39706
  const sentinel = {
@@ -39661,7 +39712,7 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
39661
39712
  schema_version: 1,
39662
39713
  migration_tool: "knowledge-migrator.ts"
39663
39714
  };
39664
- await mkdir3(path21.dirname(sentinelPath), { recursive: true });
39715
+ await mkdir3(path22.dirname(sentinelPath), { recursive: true });
39665
39716
  await writeFile4(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
39666
39717
  }
39667
39718
 
@@ -39898,12 +39949,12 @@ async function handlePlanCommand(directory, args) {
39898
39949
  init_manager2();
39899
39950
  init_manager();
39900
39951
  import * as fs17 from "fs";
39901
- import * as path28 from "path";
39952
+ import * as path29 from "path";
39902
39953
 
39903
39954
  // src/tools/lint.ts
39904
39955
  init_zod();
39905
39956
  import * as fs11 from "fs";
39906
- import * as path22 from "path";
39957
+ import * as path23 from "path";
39907
39958
  init_utils();
39908
39959
 
39909
39960
  // src/utils/path-security.ts
@@ -39949,9 +40000,9 @@ function validateArgs(args) {
39949
40000
  }
39950
40001
  function getLinterCommand(linter, mode, projectDir) {
39951
40002
  const isWindows = process.platform === "win32";
39952
- const binDir = path22.join(projectDir, "node_modules", ".bin");
39953
- const biomeBin = isWindows ? path22.join(binDir, "biome.EXE") : path22.join(binDir, "biome");
39954
- const eslintBin = isWindows ? path22.join(binDir, "eslint.cmd") : path22.join(binDir, "eslint");
40003
+ const binDir = path23.join(projectDir, "node_modules", ".bin");
40004
+ const biomeBin = isWindows ? path23.join(binDir, "biome.EXE") : path23.join(binDir, "biome");
40005
+ const eslintBin = isWindows ? path23.join(binDir, "eslint.cmd") : path23.join(binDir, "eslint");
39955
40006
  switch (linter) {
39956
40007
  case "biome":
39957
40008
  if (mode === "fix") {
@@ -39967,7 +40018,7 @@ function getLinterCommand(linter, mode, projectDir) {
39967
40018
  }
39968
40019
  function getAdditionalLinterCommand(linter, mode, cwd) {
39969
40020
  const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
39970
- const gradlew = fs11.existsSync(path22.join(cwd, gradlewName)) ? path22.join(cwd, gradlewName) : null;
40021
+ const gradlew = fs11.existsSync(path23.join(cwd, gradlewName)) ? path23.join(cwd, gradlewName) : null;
39971
40022
  switch (linter) {
39972
40023
  case "ruff":
39973
40024
  return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
@@ -40001,10 +40052,10 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
40001
40052
  }
40002
40053
  }
40003
40054
  function detectRuff(cwd) {
40004
- if (fs11.existsSync(path22.join(cwd, "ruff.toml")))
40055
+ if (fs11.existsSync(path23.join(cwd, "ruff.toml")))
40005
40056
  return isCommandAvailable("ruff");
40006
40057
  try {
40007
- const pyproject = path22.join(cwd, "pyproject.toml");
40058
+ const pyproject = path23.join(cwd, "pyproject.toml");
40008
40059
  if (fs11.existsSync(pyproject)) {
40009
40060
  const content = fs11.readFileSync(pyproject, "utf-8");
40010
40061
  if (content.includes("[tool.ruff]"))
@@ -40014,19 +40065,19 @@ function detectRuff(cwd) {
40014
40065
  return false;
40015
40066
  }
40016
40067
  function detectClippy(cwd) {
40017
- return fs11.existsSync(path22.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
40068
+ return fs11.existsSync(path23.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
40018
40069
  }
40019
40070
  function detectGolangciLint(cwd) {
40020
- return fs11.existsSync(path22.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
40071
+ return fs11.existsSync(path23.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
40021
40072
  }
40022
40073
  function detectCheckstyle(cwd) {
40023
- const hasMaven = fs11.existsSync(path22.join(cwd, "pom.xml"));
40024
- const hasGradle = fs11.existsSync(path22.join(cwd, "build.gradle")) || fs11.existsSync(path22.join(cwd, "build.gradle.kts"));
40025
- const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs11.existsSync(path22.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
40074
+ const hasMaven = fs11.existsSync(path23.join(cwd, "pom.xml"));
40075
+ const hasGradle = fs11.existsSync(path23.join(cwd, "build.gradle")) || fs11.existsSync(path23.join(cwd, "build.gradle.kts"));
40076
+ const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs11.existsSync(path23.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
40026
40077
  return (hasMaven || hasGradle) && hasBinary;
40027
40078
  }
40028
40079
  function detectKtlint(cwd) {
40029
- const hasKotlin = fs11.existsSync(path22.join(cwd, "build.gradle.kts")) || fs11.existsSync(path22.join(cwd, "build.gradle")) || (() => {
40080
+ const hasKotlin = fs11.existsSync(path23.join(cwd, "build.gradle.kts")) || fs11.existsSync(path23.join(cwd, "build.gradle")) || (() => {
40030
40081
  try {
40031
40082
  return fs11.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
40032
40083
  } catch {
@@ -40045,11 +40096,11 @@ function detectDotnetFormat(cwd) {
40045
40096
  }
40046
40097
  }
40047
40098
  function detectCppcheck(cwd) {
40048
- if (fs11.existsSync(path22.join(cwd, "CMakeLists.txt"))) {
40099
+ if (fs11.existsSync(path23.join(cwd, "CMakeLists.txt"))) {
40049
40100
  return isCommandAvailable("cppcheck");
40050
40101
  }
40051
40102
  try {
40052
- const dirsToCheck = [cwd, path22.join(cwd, "src")];
40103
+ const dirsToCheck = [cwd, path23.join(cwd, "src")];
40053
40104
  const hasCpp = dirsToCheck.some((dir) => {
40054
40105
  try {
40055
40106
  return fs11.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
@@ -40063,13 +40114,13 @@ function detectCppcheck(cwd) {
40063
40114
  }
40064
40115
  }
40065
40116
  function detectSwiftlint(cwd) {
40066
- return fs11.existsSync(path22.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
40117
+ return fs11.existsSync(path23.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
40067
40118
  }
40068
40119
  function detectDartAnalyze(cwd) {
40069
- return fs11.existsSync(path22.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
40120
+ return fs11.existsSync(path23.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
40070
40121
  }
40071
40122
  function detectRubocop(cwd) {
40072
- return (fs11.existsSync(path22.join(cwd, "Gemfile")) || fs11.existsSync(path22.join(cwd, "gems.rb")) || fs11.existsSync(path22.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
40123
+ return (fs11.existsSync(path23.join(cwd, "Gemfile")) || fs11.existsSync(path23.join(cwd, "gems.rb")) || fs11.existsSync(path23.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
40073
40124
  }
40074
40125
  function detectAdditionalLinter(cwd) {
40075
40126
  if (detectRuff(cwd))
@@ -40097,10 +40148,10 @@ function detectAdditionalLinter(cwd) {
40097
40148
  function findBinInAncestors(startDir, binName) {
40098
40149
  let dir = startDir;
40099
40150
  while (true) {
40100
- const candidate = path22.join(dir, "node_modules", ".bin", binName);
40151
+ const candidate = path23.join(dir, "node_modules", ".bin", binName);
40101
40152
  if (fs11.existsSync(candidate))
40102
40153
  return candidate;
40103
- const parent = path22.dirname(dir);
40154
+ const parent = path23.dirname(dir);
40104
40155
  if (parent === dir)
40105
40156
  break;
40106
40157
  dir = parent;
@@ -40109,10 +40160,10 @@ function findBinInAncestors(startDir, binName) {
40109
40160
  }
40110
40161
  function findBinInEnvPath(binName) {
40111
40162
  const searchPath = process.env.PATH ?? "";
40112
- for (const dir of searchPath.split(path22.delimiter)) {
40163
+ for (const dir of searchPath.split(path23.delimiter)) {
40113
40164
  if (!dir)
40114
40165
  continue;
40115
- const candidate = path22.join(dir, binName);
40166
+ const candidate = path23.join(dir, binName);
40116
40167
  if (fs11.existsSync(candidate))
40117
40168
  return candidate;
40118
40169
  }
@@ -40125,13 +40176,13 @@ async function detectAvailableLinter(directory) {
40125
40176
  return null;
40126
40177
  const projectDir = directory;
40127
40178
  const isWindows = process.platform === "win32";
40128
- const biomeBin = isWindows ? path22.join(projectDir, "node_modules", ".bin", "biome.EXE") : path22.join(projectDir, "node_modules", ".bin", "biome");
40129
- const eslintBin = isWindows ? path22.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path22.join(projectDir, "node_modules", ".bin", "eslint");
40179
+ const biomeBin = isWindows ? path23.join(projectDir, "node_modules", ".bin", "biome.EXE") : path23.join(projectDir, "node_modules", ".bin", "biome");
40180
+ const eslintBin = isWindows ? path23.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path23.join(projectDir, "node_modules", ".bin", "eslint");
40130
40181
  const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
40131
40182
  if (localResult)
40132
40183
  return localResult;
40133
- const biomeAncestor = findBinInAncestors(path22.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
40134
- const eslintAncestor = findBinInAncestors(path22.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
40184
+ const biomeAncestor = findBinInAncestors(path23.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
40185
+ const eslintAncestor = findBinInAncestors(path23.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
40135
40186
  if (biomeAncestor || eslintAncestor) {
40136
40187
  return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
40137
40188
  }
@@ -40340,7 +40391,7 @@ For Rust: rustup component add clippy`
40340
40391
  // src/tools/secretscan.ts
40341
40392
  init_zod();
40342
40393
  import * as fs12 from "fs";
40343
- import * as path23 from "path";
40394
+ import * as path24 from "path";
40344
40395
  var MAX_FILE_PATH_LENGTH = 500;
40345
40396
  var MAX_FILE_SIZE_BYTES = 512 * 1024;
40346
40397
  var MAX_FILES_SCANNED = 1000;
@@ -40567,7 +40618,7 @@ function isGlobOrPathPattern(pattern) {
40567
40618
  return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
40568
40619
  }
40569
40620
  function loadSecretScanIgnore(scanDir) {
40570
- const ignorePath = path23.join(scanDir, ".secretscanignore");
40621
+ const ignorePath = path24.join(scanDir, ".secretscanignore");
40571
40622
  try {
40572
40623
  if (!fs12.existsSync(ignorePath))
40573
40624
  return [];
@@ -40590,7 +40641,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
40590
40641
  if (exactNames.has(entry))
40591
40642
  return true;
40592
40643
  for (const pattern of globPatterns) {
40593
- if (path23.matchesGlob(relPath, pattern))
40644
+ if (path24.matchesGlob(relPath, pattern))
40594
40645
  return true;
40595
40646
  }
40596
40647
  return false;
@@ -40611,7 +40662,7 @@ function validateDirectoryInput(dir) {
40611
40662
  return null;
40612
40663
  }
40613
40664
  function isBinaryFile(filePath, buffer) {
40614
- const ext = path23.extname(filePath).toLowerCase();
40665
+ const ext = path24.extname(filePath).toLowerCase();
40615
40666
  if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
40616
40667
  return true;
40617
40668
  }
@@ -40748,9 +40799,9 @@ function isSymlinkLoop(realPath, visited) {
40748
40799
  return false;
40749
40800
  }
40750
40801
  function isPathWithinScope(realPath, scanDir) {
40751
- const resolvedScanDir = path23.resolve(scanDir);
40752
- const resolvedRealPath = path23.resolve(realPath);
40753
- return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path23.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
40802
+ const resolvedScanDir = path24.resolve(scanDir);
40803
+ const resolvedRealPath = path24.resolve(realPath);
40804
+ return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path24.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
40754
40805
  }
40755
40806
  function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
40756
40807
  skippedDirs: 0,
@@ -40776,8 +40827,8 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
40776
40827
  return a.localeCompare(b);
40777
40828
  });
40778
40829
  for (const entry of entries) {
40779
- const fullPath = path23.join(dir, entry);
40780
- const relPath = path23.relative(scanDir, fullPath).replace(/\\/g, "/");
40830
+ const fullPath = path24.join(dir, entry);
40831
+ const relPath = path24.relative(scanDir, fullPath).replace(/\\/g, "/");
40781
40832
  if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
40782
40833
  stats.skippedDirs++;
40783
40834
  continue;
@@ -40812,7 +40863,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
40812
40863
  const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
40813
40864
  files.push(...subFiles);
40814
40865
  } else if (lstat.isFile()) {
40815
- const ext = path23.extname(fullPath).toLowerCase();
40866
+ const ext = path24.extname(fullPath).toLowerCase();
40816
40867
  if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
40817
40868
  files.push(fullPath);
40818
40869
  } else {
@@ -40878,7 +40929,7 @@ var secretscan = createSwarmTool({
40878
40929
  }
40879
40930
  }
40880
40931
  try {
40881
- const _scanDirRaw = path23.resolve(directory);
40932
+ const _scanDirRaw = path24.resolve(directory);
40882
40933
  const scanDir = (() => {
40883
40934
  try {
40884
40935
  return fs12.realpathSync(_scanDirRaw);
@@ -41038,11 +41089,11 @@ async function runSecretscan(directory) {
41038
41089
  // src/tools/test-runner.ts
41039
41090
  init_zod();
41040
41091
  import * as fs16 from "fs";
41041
- import * as path27 from "path";
41092
+ import * as path28 from "path";
41042
41093
 
41043
41094
  // src/test-impact/analyzer.ts
41044
41095
  import fs13 from "fs";
41045
- import path24 from "path";
41096
+ import path25 from "path";
41046
41097
  var IMPORT_REGEX_ES = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
41047
41098
  var IMPORT_REGEX_REQUIRE = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
41048
41099
  var IMPORT_REGEX_REEXPORT = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
@@ -41067,8 +41118,8 @@ function resolveRelativeImport(fromDir, importPath) {
41067
41118
  if (!importPath.startsWith(".")) {
41068
41119
  return null;
41069
41120
  }
41070
- const resolved = path24.resolve(fromDir, importPath);
41071
- if (path24.extname(resolved)) {
41121
+ const resolved = path25.resolve(fromDir, importPath);
41122
+ if (path25.extname(resolved)) {
41072
41123
  if (fs13.existsSync(resolved) && fs13.statSync(resolved).isFile()) {
41073
41124
  return normalizePath(resolved);
41074
41125
  }
@@ -41113,12 +41164,12 @@ function findTestFilesSync(cwd) {
41113
41164
  for (const entry of entries) {
41114
41165
  if (entry.isDirectory()) {
41115
41166
  if (!skipDirs.has(entry.name)) {
41116
- walk(path24.join(dir, entry.name), visitedInodes);
41167
+ walk(path25.join(dir, entry.name), visitedInodes);
41117
41168
  }
41118
41169
  } else if (entry.isFile()) {
41119
41170
  const name = entry.name;
41120
41171
  if (/\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name)) {
41121
- testFiles.push(normalizePath(path24.join(dir, entry.name)));
41172
+ testFiles.push(normalizePath(path25.join(dir, entry.name)));
41122
41173
  }
41123
41174
  }
41124
41175
  }
@@ -41156,7 +41207,7 @@ async function buildImpactMapInternal(cwd) {
41156
41207
  continue;
41157
41208
  }
41158
41209
  const imports = extractImports(content);
41159
- const testDir = path24.dirname(testFile);
41210
+ const testDir = path25.dirname(testFile);
41160
41211
  for (const importPath of imports) {
41161
41212
  const resolvedSource = resolveRelativeImport(testDir, importPath);
41162
41213
  if (resolvedSource === null) {
@@ -41178,7 +41229,7 @@ async function buildImpactMap(cwd) {
41178
41229
  return impactMap;
41179
41230
  }
41180
41231
  async function loadImpactMap(cwd) {
41181
- const cachePath = path24.join(cwd, ".swarm", "cache", "impact-map.json");
41232
+ const cachePath = path25.join(cwd, ".swarm", "cache", "impact-map.json");
41182
41233
  if (fs13.existsSync(cachePath)) {
41183
41234
  try {
41184
41235
  const content = fs13.readFileSync(cachePath, "utf-8");
@@ -41193,8 +41244,8 @@ async function loadImpactMap(cwd) {
41193
41244
  return buildImpactMap(cwd);
41194
41245
  }
41195
41246
  async function saveImpactMap(cwd, impactMap) {
41196
- const cacheDir2 = path24.join(cwd, ".swarm", "cache");
41197
- const cachePath = path24.join(cacheDir2, "impact-map.json");
41247
+ const cacheDir2 = path25.join(cwd, ".swarm", "cache");
41248
+ const cachePath = path25.join(cacheDir2, "impact-map.json");
41198
41249
  if (!fs13.existsSync(cacheDir2)) {
41199
41250
  fs13.mkdirSync(cacheDir2, { recursive: true });
41200
41251
  }
@@ -41220,7 +41271,7 @@ async function analyzeImpact(changedFiles, cwd) {
41220
41271
  const impactedTestsSet = new Set;
41221
41272
  const untestedFiles = [];
41222
41273
  for (const changedFile of validFiles) {
41223
- const normalizedChanged = normalizePath(path24.resolve(changedFile));
41274
+ const normalizedChanged = normalizePath(path25.resolve(changedFile));
41224
41275
  const tests = impactMap[normalizedChanged];
41225
41276
  if (tests && tests.length > 0) {
41226
41277
  for (const test of tests) {
@@ -41467,13 +41518,13 @@ function detectFlakyTests(allHistory) {
41467
41518
 
41468
41519
  // src/test-impact/history-store.ts
41469
41520
  import fs14 from "fs";
41470
- import path25 from "path";
41521
+ import path26 from "path";
41471
41522
  var MAX_HISTORY_PER_TEST = 20;
41472
41523
  var MAX_ERROR_LENGTH = 500;
41473
41524
  var MAX_STACK_LENGTH = 200;
41474
41525
  var MAX_CHANGED_FILES = 50;
41475
41526
  function getHistoryPath(workingDir) {
41476
- return path25.join(workingDir || process.cwd(), ".swarm", "cache", "test-history.jsonl");
41527
+ return path26.join(workingDir || process.cwd(), ".swarm", "cache", "test-history.jsonl");
41477
41528
  }
41478
41529
  function sanitizeErrorMessage(errorMessage) {
41479
41530
  if (errorMessage === undefined) {
@@ -41533,7 +41584,7 @@ function appendTestRun(record3, workingDir) {
41533
41584
  changedFiles: sanitizeChangedFiles(record3.changedFiles || [])
41534
41585
  };
41535
41586
  const historyPath = getHistoryPath(workingDir);
41536
- const historyDir = path25.dirname(historyPath);
41587
+ const historyDir = path26.dirname(historyPath);
41537
41588
  if (!fs14.existsSync(historyDir)) {
41538
41589
  fs14.mkdirSync(historyDir, { recursive: true });
41539
41590
  }
@@ -41607,7 +41658,7 @@ function getAllHistory(workingDir) {
41607
41658
 
41608
41659
  // src/tools/resolve-working-directory.ts
41609
41660
  import * as fs15 from "fs";
41610
- import * as path26 from "path";
41661
+ import * as path27 from "path";
41611
41662
  function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
41612
41663
  if (workingDirectory == null || workingDirectory === "") {
41613
41664
  return { success: true, directory: fallbackDirectory };
@@ -41627,15 +41678,15 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
41627
41678
  };
41628
41679
  }
41629
41680
  }
41630
- const normalizedDir = path26.normalize(workingDirectory);
41631
- const pathParts = normalizedDir.split(path26.sep);
41681
+ const normalizedDir = path27.normalize(workingDirectory);
41682
+ const pathParts = normalizedDir.split(path27.sep);
41632
41683
  if (pathParts.includes("..")) {
41633
41684
  return {
41634
41685
  success: false,
41635
41686
  message: "Invalid working_directory: path traversal sequences (..) are not allowed"
41636
41687
  };
41637
41688
  }
41638
- const resolvedDir = path26.resolve(normalizedDir);
41689
+ const resolvedDir = path27.resolve(normalizedDir);
41639
41690
  let statResult;
41640
41691
  try {
41641
41692
  statResult = fs15.statSync(resolvedDir);
@@ -41651,7 +41702,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
41651
41702
  message: `Invalid working_directory: path "${resolvedDir}" is not a directory`
41652
41703
  };
41653
41704
  }
41654
- const resolvedFallback = path26.resolve(fallbackDirectory);
41705
+ const resolvedFallback = path27.resolve(fallbackDirectory);
41655
41706
  let fallbackExists = false;
41656
41707
  try {
41657
41708
  fs15.statSync(resolvedFallback);
@@ -41661,7 +41712,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
41661
41712
  }
41662
41713
  if (workingDirectory != null && workingDirectory !== "") {
41663
41714
  if (fallbackExists) {
41664
- const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path26.sep);
41715
+ const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path27.sep);
41665
41716
  if (isSubdirectory) {
41666
41717
  return {
41667
41718
  success: false,
@@ -41751,14 +41802,14 @@ function hasDevDependency(devDeps, ...patterns) {
41751
41802
  return hasPackageJsonDependency(devDeps, ...patterns);
41752
41803
  }
41753
41804
  function detectGoTest(cwd) {
41754
- return fs16.existsSync(path27.join(cwd, "go.mod")) && isCommandAvailable("go");
41805
+ return fs16.existsSync(path28.join(cwd, "go.mod")) && isCommandAvailable("go");
41755
41806
  }
41756
41807
  function detectJavaMaven(cwd) {
41757
- return fs16.existsSync(path27.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
41808
+ return fs16.existsSync(path28.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
41758
41809
  }
41759
41810
  function detectGradle(cwd) {
41760
- const hasBuildFile = fs16.existsSync(path27.join(cwd, "build.gradle")) || fs16.existsSync(path27.join(cwd, "build.gradle.kts"));
41761
- const hasGradlew = fs16.existsSync(path27.join(cwd, "gradlew")) || fs16.existsSync(path27.join(cwd, "gradlew.bat"));
41811
+ const hasBuildFile = fs16.existsSync(path28.join(cwd, "build.gradle")) || fs16.existsSync(path28.join(cwd, "build.gradle.kts"));
41812
+ const hasGradlew = fs16.existsSync(path28.join(cwd, "gradlew")) || fs16.existsSync(path28.join(cwd, "gradlew.bat"));
41762
41813
  return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
41763
41814
  }
41764
41815
  function detectDotnetTest(cwd) {
@@ -41771,30 +41822,30 @@ function detectDotnetTest(cwd) {
41771
41822
  }
41772
41823
  }
41773
41824
  function detectCTest(cwd) {
41774
- const hasSource = fs16.existsSync(path27.join(cwd, "CMakeLists.txt"));
41775
- const hasBuildCache = fs16.existsSync(path27.join(cwd, "CMakeCache.txt")) || fs16.existsSync(path27.join(cwd, "build", "CMakeCache.txt"));
41825
+ const hasSource = fs16.existsSync(path28.join(cwd, "CMakeLists.txt"));
41826
+ const hasBuildCache = fs16.existsSync(path28.join(cwd, "CMakeCache.txt")) || fs16.existsSync(path28.join(cwd, "build", "CMakeCache.txt"));
41776
41827
  return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
41777
41828
  }
41778
41829
  function detectSwiftTest(cwd) {
41779
- return fs16.existsSync(path27.join(cwd, "Package.swift")) && isCommandAvailable("swift");
41830
+ return fs16.existsSync(path28.join(cwd, "Package.swift")) && isCommandAvailable("swift");
41780
41831
  }
41781
41832
  function detectDartTest(cwd) {
41782
- return fs16.existsSync(path27.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
41833
+ return fs16.existsSync(path28.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
41783
41834
  }
41784
41835
  function detectRSpec(cwd) {
41785
- const hasRSpecFile = fs16.existsSync(path27.join(cwd, ".rspec"));
41786
- const hasGemfile = fs16.existsSync(path27.join(cwd, "Gemfile"));
41787
- const hasSpecDir = fs16.existsSync(path27.join(cwd, "spec"));
41836
+ const hasRSpecFile = fs16.existsSync(path28.join(cwd, ".rspec"));
41837
+ const hasGemfile = fs16.existsSync(path28.join(cwd, "Gemfile"));
41838
+ const hasSpecDir = fs16.existsSync(path28.join(cwd, "spec"));
41788
41839
  const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
41789
41840
  return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
41790
41841
  }
41791
41842
  function detectMinitest(cwd) {
41792
- return fs16.existsSync(path27.join(cwd, "test")) && (fs16.existsSync(path27.join(cwd, "Gemfile")) || fs16.existsSync(path27.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
41843
+ return fs16.existsSync(path28.join(cwd, "test")) && (fs16.existsSync(path28.join(cwd, "Gemfile")) || fs16.existsSync(path28.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
41793
41844
  }
41794
41845
  async function detectTestFramework(cwd) {
41795
41846
  const baseDir = cwd;
41796
41847
  try {
41797
- const packageJsonPath = path27.join(baseDir, "package.json");
41848
+ const packageJsonPath = path28.join(baseDir, "package.json");
41798
41849
  if (fs16.existsSync(packageJsonPath)) {
41799
41850
  const content = fs16.readFileSync(packageJsonPath, "utf-8");
41800
41851
  const pkg = JSON.parse(content);
@@ -41815,16 +41866,16 @@ async function detectTestFramework(cwd) {
41815
41866
  return "jest";
41816
41867
  if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
41817
41868
  return "mocha";
41818
- if (fs16.existsSync(path27.join(baseDir, "bun.lockb")) || fs16.existsSync(path27.join(baseDir, "bun.lock"))) {
41869
+ if (fs16.existsSync(path28.join(baseDir, "bun.lockb")) || fs16.existsSync(path28.join(baseDir, "bun.lock"))) {
41819
41870
  if (scripts.test?.includes("bun"))
41820
41871
  return "bun";
41821
41872
  }
41822
41873
  }
41823
41874
  } catch {}
41824
41875
  try {
41825
- const pyprojectTomlPath = path27.join(baseDir, "pyproject.toml");
41826
- const setupCfgPath = path27.join(baseDir, "setup.cfg");
41827
- const requirementsTxtPath = path27.join(baseDir, "requirements.txt");
41876
+ const pyprojectTomlPath = path28.join(baseDir, "pyproject.toml");
41877
+ const setupCfgPath = path28.join(baseDir, "setup.cfg");
41878
+ const requirementsTxtPath = path28.join(baseDir, "requirements.txt");
41828
41879
  if (fs16.existsSync(pyprojectTomlPath)) {
41829
41880
  const content = fs16.readFileSync(pyprojectTomlPath, "utf-8");
41830
41881
  if (content.includes("[tool.pytest"))
@@ -41844,7 +41895,7 @@ async function detectTestFramework(cwd) {
41844
41895
  }
41845
41896
  } catch {}
41846
41897
  try {
41847
- const cargoTomlPath = path27.join(baseDir, "Cargo.toml");
41898
+ const cargoTomlPath = path28.join(baseDir, "Cargo.toml");
41848
41899
  if (fs16.existsSync(cargoTomlPath)) {
41849
41900
  const content = fs16.readFileSync(cargoTomlPath, "utf-8");
41850
41901
  if (content.includes("[dev-dependencies]")) {
@@ -41855,9 +41906,9 @@ async function detectTestFramework(cwd) {
41855
41906
  }
41856
41907
  } catch {}
41857
41908
  try {
41858
- const pesterConfigPath = path27.join(baseDir, "pester.config.ps1");
41859
- const pesterConfigJsonPath = path27.join(baseDir, "pester.config.ps1.json");
41860
- const pesterPs1Path = path27.join(baseDir, "tests.ps1");
41909
+ const pesterConfigPath = path28.join(baseDir, "pester.config.ps1");
41910
+ const pesterConfigJsonPath = path28.join(baseDir, "pester.config.ps1.json");
41911
+ const pesterPs1Path = path28.join(baseDir, "tests.ps1");
41861
41912
  if (fs16.existsSync(pesterConfigPath) || fs16.existsSync(pesterConfigJsonPath) || fs16.existsSync(pesterPs1Path)) {
41862
41913
  return "pester";
41863
41914
  }
@@ -41900,12 +41951,12 @@ function isTestDirectoryPath(normalizedPath) {
41900
41951
  return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
41901
41952
  }
41902
41953
  function resolveWorkspacePath(file3, workingDir) {
41903
- return path27.isAbsolute(file3) ? path27.resolve(file3) : path27.resolve(workingDir, file3);
41954
+ return path28.isAbsolute(file3) ? path28.resolve(file3) : path28.resolve(workingDir, file3);
41904
41955
  }
41905
41956
  function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
41906
41957
  if (!preferRelative)
41907
41958
  return absolutePath;
41908
- return path27.relative(workingDir, absolutePath);
41959
+ return path28.relative(workingDir, absolutePath);
41909
41960
  }
41910
41961
  function dedupePush(target, value) {
41911
41962
  if (!target.includes(value)) {
@@ -41942,18 +41993,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
41942
41993
  }
41943
41994
  }
41944
41995
  function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
41945
- const relativeDir = path27.dirname(relativePath);
41996
+ const relativeDir = path28.dirname(relativePath);
41946
41997
  const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
41947
41998
  const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
41948
- const rootDir = path27.join(workingDir, dirName);
41949
- return nestedRelativeDir ? [rootDir, path27.join(rootDir, nestedRelativeDir)] : [rootDir];
41999
+ const rootDir = path28.join(workingDir, dirName);
42000
+ return nestedRelativeDir ? [rootDir, path28.join(rootDir, nestedRelativeDir)] : [rootDir];
41950
42001
  });
41951
42002
  const normalizedRelativePath = relativePath.replace(/\\/g, "/");
41952
42003
  if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
41953
- directories.push(path27.join(workingDir, "src/test/java", path27.dirname(normalizedRelativePath.slice("src/main/java/".length))));
42004
+ directories.push(path28.join(workingDir, "src/test/java", path28.dirname(normalizedRelativePath.slice("src/main/java/".length))));
41954
42005
  }
41955
42006
  if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
41956
- directories.push(path27.join(workingDir, "src/test/kotlin", path27.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
42007
+ directories.push(path28.join(workingDir, "src/test/kotlin", path28.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
41957
42008
  }
41958
42009
  return [...new Set(directories)];
41959
42010
  }
@@ -41981,23 +42032,23 @@ function isLanguageSpecificTestFile(basename4) {
41981
42032
  }
41982
42033
  function isConventionTestFilePath(filePath) {
41983
42034
  const normalizedPath = filePath.replace(/\\/g, "/");
41984
- const basename4 = path27.basename(filePath);
42035
+ const basename4 = path28.basename(filePath);
41985
42036
  return hasCompoundTestExtension(basename4) || basename4.includes(".spec.") || basename4.includes(".test.") || isLanguageSpecificTestFile(basename4) || isTestDirectoryPath(normalizedPath);
41986
42037
  }
41987
42038
  function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
41988
42039
  const testFiles = [];
41989
42040
  for (const file3 of sourceFiles) {
41990
42041
  const absoluteFile = resolveWorkspacePath(file3, workingDir);
41991
- const relativeFile = path27.relative(workingDir, absoluteFile);
41992
- const basename4 = path27.basename(absoluteFile);
41993
- const dirname11 = path27.dirname(absoluteFile);
41994
- const preferRelativeOutput = !path27.isAbsolute(file3);
42042
+ const relativeFile = path28.relative(workingDir, absoluteFile);
42043
+ const basename4 = path28.basename(absoluteFile);
42044
+ const dirname11 = path28.dirname(absoluteFile);
42045
+ const preferRelativeOutput = !path28.isAbsolute(file3);
41995
42046
  if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file3)) {
41996
42047
  dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
41997
42048
  continue;
41998
42049
  }
41999
42050
  const nameWithoutExt = basename4.replace(/\.[^.]+$/, "");
42000
- const ext = path27.extname(basename4);
42051
+ const ext = path28.extname(basename4);
42001
42052
  const genericTestNames = [
42002
42053
  `${nameWithoutExt}.spec${ext}`,
42003
42054
  `${nameWithoutExt}.test${ext}`
@@ -42006,7 +42057,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
42006
42057
  const colocatedCandidates = [
42007
42058
  ...genericTestNames,
42008
42059
  ...languageSpecificTestNames
42009
- ].map((candidateName) => path27.join(dirname11, candidateName));
42060
+ ].map((candidateName) => path28.join(dirname11, candidateName));
42010
42061
  const testDirectoryNames = [
42011
42062
  basename4,
42012
42063
  ...genericTestNames,
@@ -42015,8 +42066,8 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
42015
42066
  const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
42016
42067
  const possibleTestFiles = [
42017
42068
  ...colocatedCandidates,
42018
- ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path27.join(dirname11, dirName, candidateName))),
42019
- ...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path27.join(candidateDir, candidateName)))
42069
+ ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path28.join(dirname11, dirName, candidateName))),
42070
+ ...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path28.join(candidateDir, candidateName)))
42020
42071
  ];
42021
42072
  for (const testFile of possibleTestFiles) {
42022
42073
  if (fs16.existsSync(testFile)) {
@@ -42037,7 +42088,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
42037
42088
  try {
42038
42089
  const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
42039
42090
  const content = fs16.readFileSync(absoluteTestFile, "utf-8");
42040
- const testDir = path27.dirname(absoluteTestFile);
42091
+ const testDir = path28.dirname(absoluteTestFile);
42041
42092
  const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
42042
42093
  let match;
42043
42094
  match = importRegex.exec(content);
@@ -42045,8 +42096,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
42045
42096
  const importPath = match[1];
42046
42097
  let resolvedImport;
42047
42098
  if (importPath.startsWith(".")) {
42048
- resolvedImport = path27.resolve(testDir, importPath);
42049
- const existingExt = path27.extname(resolvedImport);
42099
+ resolvedImport = path28.resolve(testDir, importPath);
42100
+ const existingExt = path28.extname(resolvedImport);
42050
42101
  if (!existingExt) {
42051
42102
  for (const extToTry of [
42052
42103
  ".ts",
@@ -42066,12 +42117,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
42066
42117
  } else {
42067
42118
  continue;
42068
42119
  }
42069
- const importBasename = path27.basename(resolvedImport, path27.extname(resolvedImport));
42070
- const importDir = path27.dirname(resolvedImport);
42120
+ const importBasename = path28.basename(resolvedImport, path28.extname(resolvedImport));
42121
+ const importDir = path28.dirname(resolvedImport);
42071
42122
  for (const sourceFile of absoluteSourceFiles) {
42072
- const sourceDir = path27.dirname(sourceFile);
42073
- const sourceBasename = path27.basename(sourceFile, path27.extname(sourceFile));
42074
- const isRelatedDir = importDir === sourceDir || importDir === path27.join(sourceDir, "__tests__") || importDir === path27.join(sourceDir, "tests") || importDir === path27.join(sourceDir, "test") || importDir === path27.join(sourceDir, "spec");
42123
+ const sourceDir = path28.dirname(sourceFile);
42124
+ const sourceBasename = path28.basename(sourceFile, path28.extname(sourceFile));
42125
+ const isRelatedDir = importDir === sourceDir || importDir === path28.join(sourceDir, "__tests__") || importDir === path28.join(sourceDir, "tests") || importDir === path28.join(sourceDir, "test") || importDir === path28.join(sourceDir, "spec");
42075
42126
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
42076
42127
  dedupePush(testFiles, testFile);
42077
42128
  break;
@@ -42084,8 +42135,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
42084
42135
  while (match !== null) {
42085
42136
  const importPath = match[1];
42086
42137
  if (importPath.startsWith(".")) {
42087
- let resolvedImport = path27.resolve(testDir, importPath);
42088
- const existingExt = path27.extname(resolvedImport);
42138
+ let resolvedImport = path28.resolve(testDir, importPath);
42139
+ const existingExt = path28.extname(resolvedImport);
42089
42140
  if (!existingExt) {
42090
42141
  for (const extToTry of [
42091
42142
  ".ts",
@@ -42102,12 +42153,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
42102
42153
  }
42103
42154
  }
42104
42155
  }
42105
- const importDir = path27.dirname(resolvedImport);
42106
- const importBasename = path27.basename(resolvedImport, path27.extname(resolvedImport));
42156
+ const importDir = path28.dirname(resolvedImport);
42157
+ const importBasename = path28.basename(resolvedImport, path28.extname(resolvedImport));
42107
42158
  for (const sourceFile of absoluteSourceFiles) {
42108
- const sourceDir = path27.dirname(sourceFile);
42109
- const sourceBasename = path27.basename(sourceFile, path27.extname(sourceFile));
42110
- const isRelatedDir = importDir === sourceDir || importDir === path27.join(sourceDir, "__tests__") || importDir === path27.join(sourceDir, "tests") || importDir === path27.join(sourceDir, "test") || importDir === path27.join(sourceDir, "spec");
42159
+ const sourceDir = path28.dirname(sourceFile);
42160
+ const sourceBasename = path28.basename(sourceFile, path28.extname(sourceFile));
42161
+ const isRelatedDir = importDir === sourceDir || importDir === path28.join(sourceDir, "__tests__") || importDir === path28.join(sourceDir, "tests") || importDir === path28.join(sourceDir, "test") || importDir === path28.join(sourceDir, "spec");
42111
42162
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
42112
42163
  dedupePush(testFiles, testFile);
42113
42164
  break;
@@ -42210,8 +42261,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
42210
42261
  return ["mvn", "test"];
42211
42262
  case "gradle": {
42212
42263
  const isWindows = process.platform === "win32";
42213
- const hasGradlewBat = fs16.existsSync(path27.join(baseDir, "gradlew.bat"));
42214
- const hasGradlew = fs16.existsSync(path27.join(baseDir, "gradlew"));
42264
+ const hasGradlewBat = fs16.existsSync(path28.join(baseDir, "gradlew.bat"));
42265
+ const hasGradlew = fs16.existsSync(path28.join(baseDir, "gradlew"));
42215
42266
  if (hasGradlewBat && isWindows)
42216
42267
  return ["gradlew.bat", "test"];
42217
42268
  if (hasGradlew)
@@ -42228,7 +42279,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
42228
42279
  "cmake-build-release",
42229
42280
  "out"
42230
42281
  ];
42231
- const actualBuildDir = buildDirCandidates.find((d) => fs16.existsSync(path27.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
42282
+ const actualBuildDir = buildDirCandidates.find((d) => fs16.existsSync(path28.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
42232
42283
  return ["ctest", "--test-dir", actualBuildDir];
42233
42284
  }
42234
42285
  case "swift-test":
@@ -42856,7 +42907,7 @@ var test_runner = createSwarmTool({
42856
42907
  const sourceFiles = args.files.filter((file3) => {
42857
42908
  if (directTestFiles.includes(file3))
42858
42909
  return false;
42859
- const ext = path27.extname(file3).toLowerCase();
42910
+ const ext = path28.extname(file3).toLowerCase();
42860
42911
  return SOURCE_EXTENSIONS.has(ext);
42861
42912
  });
42862
42913
  const invalidFiles = args.files.filter((file3) => !directTestFiles.includes(file3) && !sourceFiles.includes(file3));
@@ -42891,7 +42942,7 @@ var test_runner = createSwarmTool({
42891
42942
  if (isConventionTestFilePath(f)) {
42892
42943
  return false;
42893
42944
  }
42894
- const ext = path27.extname(f).toLowerCase();
42945
+ const ext = path28.extname(f).toLowerCase();
42895
42946
  return SOURCE_EXTENSIONS.has(ext);
42896
42947
  });
42897
42948
  if (sourceFiles.length === 0) {
@@ -42918,7 +42969,7 @@ var test_runner = createSwarmTool({
42918
42969
  if (isConventionTestFilePath(f)) {
42919
42970
  return false;
42920
42971
  }
42921
- const ext = path27.extname(f).toLowerCase();
42972
+ const ext = path28.extname(f).toLowerCase();
42922
42973
  return SOURCE_EXTENSIONS.has(ext);
42923
42974
  });
42924
42975
  if (sourceFiles.length === 0) {
@@ -42936,8 +42987,8 @@ var test_runner = createSwarmTool({
42936
42987
  const impactResult = await analyzeImpact(sourceFiles, workingDir);
42937
42988
  if (impactResult.impactedTests.length > 0) {
42938
42989
  testFiles = impactResult.impactedTests.map((absPath) => {
42939
- const relativePath = path27.relative(workingDir, absPath);
42940
- return path27.isAbsolute(relativePath) ? absPath : relativePath;
42990
+ const relativePath = path28.relative(workingDir, absPath);
42991
+ return path28.isAbsolute(relativePath) ? absPath : relativePath;
42941
42992
  });
42942
42993
  } else {
42943
42994
  graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
@@ -43030,8 +43081,8 @@ function validateDirectoryPath(dir) {
43030
43081
  if (dir.includes("..")) {
43031
43082
  throw new Error("Directory path must not contain path traversal sequences");
43032
43083
  }
43033
- const normalized = path28.normalize(dir);
43034
- const absolutePath = path28.isAbsolute(normalized) ? normalized : path28.resolve(normalized);
43084
+ const normalized = path29.normalize(dir);
43085
+ const absolutePath = path29.isAbsolute(normalized) ? normalized : path29.resolve(normalized);
43035
43086
  return absolutePath;
43036
43087
  }
43037
43088
  function validateTimeout(timeoutMs, defaultValue) {
@@ -43054,7 +43105,7 @@ function validateTimeout(timeoutMs, defaultValue) {
43054
43105
  }
43055
43106
  function getPackageVersion(dir) {
43056
43107
  try {
43057
- const packagePath = path28.join(dir, "package.json");
43108
+ const packagePath = path29.join(dir, "package.json");
43058
43109
  if (fs17.existsSync(packagePath)) {
43059
43110
  const content = fs17.readFileSync(packagePath, "utf-8");
43060
43111
  const pkg = JSON.parse(content);
@@ -43065,7 +43116,7 @@ function getPackageVersion(dir) {
43065
43116
  }
43066
43117
  function getChangelogVersion(dir) {
43067
43118
  try {
43068
- const changelogPath = path28.join(dir, "CHANGELOG.md");
43119
+ const changelogPath = path29.join(dir, "CHANGELOG.md");
43069
43120
  if (fs17.existsSync(changelogPath)) {
43070
43121
  const content = fs17.readFileSync(changelogPath, "utf-8");
43071
43122
  const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
@@ -43079,7 +43130,7 @@ function getChangelogVersion(dir) {
43079
43130
  function getVersionFileVersion(dir) {
43080
43131
  const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
43081
43132
  for (const file3 of possibleFiles) {
43082
- const filePath = path28.join(dir, file3);
43133
+ const filePath = path29.join(dir, file3);
43083
43134
  if (fs17.existsSync(filePath)) {
43084
43135
  try {
43085
43136
  const content = fs17.readFileSync(filePath, "utf-8").trim();
@@ -43406,7 +43457,7 @@ async function runEvidenceCheck(dir) {
43406
43457
  async function runRequirementCoverageCheck(dir, currentPhase) {
43407
43458
  const startTime = Date.now();
43408
43459
  try {
43409
- const specPath = path28.join(dir, ".swarm", "spec.md");
43460
+ const specPath = path29.join(dir, ".swarm", "spec.md");
43410
43461
  if (!fs17.existsSync(specPath)) {
43411
43462
  return {
43412
43463
  type: "req_coverage",
@@ -44529,7 +44580,7 @@ async function handleResetCommand(directory, args) {
44529
44580
  // src/commands/reset-session.ts
44530
44581
  init_utils2();
44531
44582
  import * as fs19 from "fs";
44532
- import * as path29 from "path";
44583
+ import * as path30 from "path";
44533
44584
  async function handleResetSessionCommand(directory, _args) {
44534
44585
  const results = [];
44535
44586
  try {
@@ -44544,13 +44595,13 @@ async function handleResetSessionCommand(directory, _args) {
44544
44595
  results.push("\u274C Failed to delete state.json");
44545
44596
  }
44546
44597
  try {
44547
- const sessionDir = path29.dirname(validateSwarmPath(directory, "session/state.json"));
44598
+ const sessionDir = path30.dirname(validateSwarmPath(directory, "session/state.json"));
44548
44599
  if (fs19.existsSync(sessionDir)) {
44549
44600
  const files = fs19.readdirSync(sessionDir);
44550
44601
  const otherFiles = files.filter((f) => f !== "state.json");
44551
44602
  let deletedCount = 0;
44552
44603
  for (const file3 of otherFiles) {
44553
- const filePath = path29.join(sessionDir, file3);
44604
+ const filePath = path30.join(sessionDir, file3);
44554
44605
  if (fs19.lstatSync(filePath).isFile()) {
44555
44606
  fs19.unlinkSync(filePath);
44556
44607
  deletedCount++;
@@ -44580,7 +44631,7 @@ async function handleResetSessionCommand(directory, _args) {
44580
44631
  // src/summaries/manager.ts
44581
44632
  init_utils2();
44582
44633
  init_utils();
44583
- import * as path30 from "path";
44634
+ import * as path31 from "path";
44584
44635
  var SUMMARY_ID_REGEX = /^S\d+$/;
44585
44636
  function sanitizeSummaryId(id) {
44586
44637
  if (!id || id.length === 0) {
@@ -44604,7 +44655,7 @@ function sanitizeSummaryId(id) {
44604
44655
  }
44605
44656
  async function loadFullOutput(directory, id) {
44606
44657
  const sanitizedId = sanitizeSummaryId(id);
44607
- const relativePath = path30.join("summaries", `${sanitizedId}.json`);
44658
+ const relativePath = path31.join("summaries", `${sanitizedId}.json`);
44608
44659
  validateSwarmPath(directory, relativePath);
44609
44660
  const content = await readSwarmFileAsync(directory, relativePath);
44610
44661
  if (content === null) {
@@ -44660,7 +44711,7 @@ init_plan_schema();
44660
44711
  init_utils2();
44661
44712
  init_ledger();
44662
44713
  import * as fs20 from "fs";
44663
- import * as path31 from "path";
44714
+ import * as path32 from "path";
44664
44715
  async function handleRollbackCommand(directory, args) {
44665
44716
  const phaseArg = args[0];
44666
44717
  if (!phaseArg) {
@@ -44725,8 +44776,8 @@ async function handleRollbackCommand(directory, args) {
44725
44776
  if (EXCLUDE_FILES.has(file3) || file3.startsWith("plan-ledger.archived-")) {
44726
44777
  continue;
44727
44778
  }
44728
- const src = path31.join(checkpointDir, file3);
44729
- const dest = path31.join(swarmDir, file3);
44779
+ const src = path32.join(checkpointDir, file3);
44780
+ const dest = path32.join(swarmDir, file3);
44730
44781
  try {
44731
44782
  fs20.cpSync(src, dest, { recursive: true, force: true });
44732
44783
  successes.push(file3);
@@ -44745,12 +44796,12 @@ async function handleRollbackCommand(directory, args) {
44745
44796
  ].join(`
44746
44797
  `);
44747
44798
  }
44748
- const existingLedgerPath = path31.join(swarmDir, "plan-ledger.jsonl");
44799
+ const existingLedgerPath = path32.join(swarmDir, "plan-ledger.jsonl");
44749
44800
  if (fs20.existsSync(existingLedgerPath)) {
44750
44801
  fs20.unlinkSync(existingLedgerPath);
44751
44802
  }
44752
44803
  try {
44753
- const planJsonPath = path31.join(swarmDir, "plan.json");
44804
+ const planJsonPath = path32.join(swarmDir, "plan.json");
44754
44805
  if (fs20.existsSync(planJsonPath)) {
44755
44806
  const planRaw = fs20.readFileSync(planJsonPath, "utf-8");
44756
44807
  const plan = PlanSchema.parse(JSON.parse(planRaw));
@@ -44823,9 +44874,9 @@ async function handleSimulateCommand(directory, args) {
44823
44874
  const report = reportLines.filter(Boolean).join(`
44824
44875
  `);
44825
44876
  const fs21 = await import("fs/promises");
44826
- const path32 = await import("path");
44827
- const reportPath = path32.join(directory, ".swarm", "simulate-report.md");
44828
- await fs21.mkdir(path32.dirname(reportPath), { recursive: true });
44877
+ const path33 = await import("path");
44878
+ const reportPath = path33.join(directory, ".swarm", "simulate-report.md");
44879
+ await fs21.mkdir(path33.dirname(reportPath), { recursive: true });
44829
44880
  await fs21.writeFile(reportPath, report, "utf-8");
44830
44881
  return `${darkMatterPairs.length} hidden coupling pairs detected`;
44831
44882
  }
@@ -45360,21 +45411,34 @@ function resolveCommand(tokens) {
45360
45411
 
45361
45412
  // src/cli/index.ts
45362
45413
  var { version: version4 } = package_default;
45363
- var CONFIG_DIR = path32.join(process.env.XDG_CONFIG_HOME || path32.join(os6.homedir(), ".config"), "opencode");
45364
- var OPENCODE_CONFIG_PATH = path32.join(CONFIG_DIR, "opencode.json");
45365
- var PLUGIN_CONFIG_PATH = path32.join(CONFIG_DIR, "opencode-swarm.json");
45366
- var PROMPTS_DIR = path32.join(CONFIG_DIR, "opencode-swarm");
45367
- var OPENCODE_PLUGIN_CACHE_PATHS = [
45368
- path32.join(process.env.XDG_CACHE_HOME || path32.join(os6.homedir(), ".cache"), "opencode", "packages", "opencode-swarm@latest"),
45369
- path32.join(CONFIG_DIR, "node_modules", "opencode-swarm")
45370
- ];
45414
+ var CONFIG_DIR = getPluginConfigDir();
45415
+ var OPENCODE_CONFIG_PATH = path33.join(CONFIG_DIR, "opencode.json");
45416
+ var PLUGIN_CONFIG_PATH = path33.join(CONFIG_DIR, "opencode-swarm.json");
45417
+ var PROMPTS_DIR = path33.join(CONFIG_DIR, "opencode-swarm");
45418
+ var OPENCODE_PLUGIN_CACHE_PATHS = getPluginCachePaths();
45371
45419
  function isSafeCachePath(p) {
45372
- const resolved = path32.resolve(p);
45373
- const home = path32.resolve(os6.homedir());
45374
- if (resolved === "/" || resolved === home || resolved.length <= home.length)
45420
+ const resolved = path33.resolve(p);
45421
+ const home = path33.resolve(os7.homedir());
45422
+ if (resolved === "/" || resolved === home || resolved.length <= home.length) {
45423
+ return false;
45424
+ }
45425
+ const segments = resolved.split(path33.sep).filter((s) => s.length > 0);
45426
+ if (segments.length < 4) {
45375
45427
  return false;
45376
- const leaf = path32.basename(resolved);
45377
- return leaf === "opencode-swarm@latest" || leaf === "opencode-swarm";
45428
+ }
45429
+ const leaf = path33.basename(resolved);
45430
+ if (leaf !== "opencode-swarm@latest" && leaf !== "opencode-swarm") {
45431
+ return false;
45432
+ }
45433
+ const parent = path33.basename(path33.dirname(resolved));
45434
+ if (parent !== "packages" && parent !== "node_modules") {
45435
+ return false;
45436
+ }
45437
+ const grandparent = path33.basename(path33.dirname(path33.dirname(resolved)));
45438
+ if (grandparent !== "opencode") {
45439
+ return false;
45440
+ }
45441
+ return true;
45378
45442
  }
45379
45443
  function ensureDir(dir) {
45380
45444
  if (!fs21.existsSync(dir)) {
@@ -45396,8 +45460,8 @@ function saveJson(filepath, data) {
45396
45460
  }
45397
45461
  function writeProjectConfigIfMissing(cwd) {
45398
45462
  try {
45399
- const opencodeDir = path32.join(cwd, ".opencode");
45400
- const projectConfigPath = path32.join(opencodeDir, "opencode-swarm.json");
45463
+ const opencodeDir = path33.join(cwd, ".opencode");
45464
+ const projectConfigPath = path33.join(opencodeDir, "opencode-swarm.json");
45401
45465
  if (fs21.existsSync(projectConfigPath)) {
45402
45466
  return;
45403
45467
  }
@@ -45415,7 +45479,7 @@ async function install() {
45415
45479
  `);
45416
45480
  ensureDir(CONFIG_DIR);
45417
45481
  ensureDir(PROMPTS_DIR);
45418
- const LEGACY_CONFIG_PATH = path32.join(CONFIG_DIR, "config.json");
45482
+ const LEGACY_CONFIG_PATH = path33.join(CONFIG_DIR, "config.json");
45419
45483
  let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
45420
45484
  if (!opencodeConfig) {
45421
45485
  const legacyConfig = loadJson(LEGACY_CONFIG_PATH);