opencode-swarm 7.16.0 → 7.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -34,7 +34,7 @@ var package_default;
34
34
  var init_package = __esm(() => {
35
35
  package_default = {
36
36
  name: "opencode-swarm",
37
- version: "7.16.0",
37
+ version: "7.17.0",
38
38
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
39
39
  main: "dist/index.js",
40
40
  types: "dist/index.d.ts",
@@ -40347,11 +40347,34 @@ class LanguageRegistry {
40347
40347
  this.profiles = new Map;
40348
40348
  this.extensionIndex = new Map;
40349
40349
  }
40350
+ unregister(id) {
40351
+ const profile = this.profiles.get(id);
40352
+ if (!profile)
40353
+ return;
40354
+ this.profiles.delete(id);
40355
+ if (!profile.parserOnly) {
40356
+ for (const ext of profile.extensions) {
40357
+ if (this.extensionIndex.get(ext) === id) {
40358
+ this.extensionIndex.delete(ext);
40359
+ }
40360
+ }
40361
+ }
40362
+ }
40350
40363
  register(profile) {
40351
- this.profiles.set(profile.id, profile);
40352
- for (const ext of profile.extensions) {
40353
- this.extensionIndex.set(ext, profile.id);
40364
+ const existing = this.profiles.get(profile.id);
40365
+ if (existing && existing !== profile) {
40366
+ throw new Error(`LanguageRegistry: profile id "${profile.id}" registered twice. ` + `Each LanguageProfile.id must be unique. ` + `Got: ${profile.displayName} vs existing ${existing.displayName}.`);
40354
40367
  }
40368
+ if (!profile.parserOnly) {
40369
+ for (const ext of profile.extensions) {
40370
+ const claimedBy = this.extensionIndex.get(ext);
40371
+ if (claimedBy && claimedBy !== profile.id) {
40372
+ throw new Error(`LanguageRegistry: extension "${ext}" registered by both ` + `"${claimedBy}" and "${profile.id}". A non-parserOnly profile ` + `must not collide on extensions. If both languages legitimately ` + `share an extension, mark one parserOnly: true.`);
40373
+ }
40374
+ this.extensionIndex.set(ext, profile.id);
40375
+ }
40376
+ }
40377
+ this.profiles.set(profile.id, profile);
40355
40378
  }
40356
40379
  get(id) {
40357
40380
  return this.profiles.get(id);
@@ -40383,7 +40406,8 @@ var init_profiles = __esm(() => {
40383
40406
  extensions: [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"],
40384
40407
  treeSitter: {
40385
40408
  grammarId: "typescript",
40386
- wasmFile: "tree-sitter-typescript.wasm"
40409
+ wasmFile: "tree-sitter-typescript.wasm",
40410
+ commentNodes: ["comment", "line_comment", "block_comment"]
40387
40411
  },
40388
40412
  build: {
40389
40413
  detectFiles: ["package.json"],
@@ -40409,7 +40433,13 @@ var init_profiles = __esm(() => {
40409
40433
  ]
40410
40434
  },
40411
40435
  test: {
40412
- detectFiles: ["package.json", "vitest.config.ts", "jest.config.js"],
40436
+ detectFiles: [
40437
+ "package.json",
40438
+ "vitest.config.ts",
40439
+ "jest.config.js",
40440
+ ".mocharc.js",
40441
+ ".mocharc.json"
40442
+ ],
40413
40443
  frameworks: [
40414
40444
  {
40415
40445
  name: "vitest",
@@ -40420,9 +40450,15 @@ var init_profiles = __esm(() => {
40420
40450
  { name: "jest", detect: "jest.config.js", cmd: "npx jest", priority: 9 },
40421
40451
  {
40422
40452
  name: "bun:test",
40423
- detect: "package.json",
40453
+ detect: "bun.lock",
40424
40454
  cmd: "bun test",
40425
40455
  priority: 8
40456
+ },
40457
+ {
40458
+ name: "mocha",
40459
+ detect: ".mocharc.json",
40460
+ cmd: "npx mocha",
40461
+ priority: 7
40426
40462
  }
40427
40463
  ]
40428
40464
  },
@@ -40476,7 +40512,11 @@ var init_profiles = __esm(() => {
40476
40512
  displayName: "Python",
40477
40513
  tier: 1,
40478
40514
  extensions: [".py", ".pyw"],
40479
- treeSitter: { grammarId: "python", wasmFile: "tree-sitter-python.wasm" },
40515
+ treeSitter: {
40516
+ grammarId: "python",
40517
+ wasmFile: "tree-sitter-python.wasm",
40518
+ commentNodes: ["comment"]
40519
+ },
40480
40520
  build: {
40481
40521
  detectFiles: ["setup.py", "pyproject.toml", "setup.cfg"],
40482
40522
  commands: [
@@ -40546,7 +40586,11 @@ var init_profiles = __esm(() => {
40546
40586
  displayName: "Rust",
40547
40587
  tier: 1,
40548
40588
  extensions: [".rs"],
40549
- treeSitter: { grammarId: "rust", wasmFile: "tree-sitter-rust.wasm" },
40589
+ treeSitter: {
40590
+ grammarId: "rust",
40591
+ wasmFile: "tree-sitter-rust.wasm",
40592
+ commentNodes: ["line_comment", "block_comment"]
40593
+ },
40550
40594
  build: {
40551
40595
  detectFiles: ["Cargo.toml"],
40552
40596
  commands: [
@@ -40615,7 +40659,11 @@ var init_profiles = __esm(() => {
40615
40659
  displayName: "Go",
40616
40660
  tier: 1,
40617
40661
  extensions: [".go"],
40618
- treeSitter: { grammarId: "go", wasmFile: "tree-sitter-go.wasm" },
40662
+ treeSitter: {
40663
+ grammarId: "go",
40664
+ wasmFile: "tree-sitter-go.wasm",
40665
+ commentNodes: ["comment"]
40666
+ },
40619
40667
  build: {
40620
40668
  detectFiles: ["go.mod"],
40621
40669
  commands: [
@@ -40679,7 +40727,11 @@ var init_profiles = __esm(() => {
40679
40727
  displayName: "Java",
40680
40728
  tier: 2,
40681
40729
  extensions: [".java"],
40682
- treeSitter: { grammarId: "java", wasmFile: "tree-sitter-java.wasm" },
40730
+ treeSitter: {
40731
+ grammarId: "java",
40732
+ wasmFile: "tree-sitter-java.wasm",
40733
+ commentNodes: ["line_comment", "block_comment"]
40734
+ },
40683
40735
  build: {
40684
40736
  detectFiles: ["pom.xml", "build.gradle", "build.gradle.kts"],
40685
40737
  commands: [
@@ -40759,7 +40811,11 @@ var init_profiles = __esm(() => {
40759
40811
  displayName: "Kotlin",
40760
40812
  tier: 2,
40761
40813
  extensions: [".kt", ".kts"],
40762
- treeSitter: { grammarId: "kotlin", wasmFile: "tree-sitter-kotlin.wasm" },
40814
+ treeSitter: {
40815
+ grammarId: "kotlin",
40816
+ wasmFile: "tree-sitter-kotlin.wasm",
40817
+ commentNodes: ["line_comment", "multiline_comment"]
40818
+ },
40763
40819
  build: {
40764
40820
  detectFiles: ["build.gradle.kts", "build.gradle", "pom.xml"],
40765
40821
  commands: [
@@ -40839,7 +40895,11 @@ var init_profiles = __esm(() => {
40839
40895
  displayName: "C# / .NET",
40840
40896
  tier: 2,
40841
40897
  extensions: [".cs", ".csx"],
40842
- treeSitter: { grammarId: "csharp", wasmFile: "tree-sitter-c-sharp.wasm" },
40898
+ treeSitter: {
40899
+ grammarId: "csharp",
40900
+ wasmFile: "tree-sitter-c-sharp.wasm",
40901
+ commentNodes: ["comment"]
40902
+ },
40843
40903
  build: {
40844
40904
  detectFiles: ["*.csproj", "*.sln", "Directory.Build.props"],
40845
40905
  commands: [
@@ -40907,7 +40967,11 @@ var init_profiles = __esm(() => {
40907
40967
  displayName: "C / C++",
40908
40968
  tier: 2,
40909
40969
  extensions: [".c", ".h", ".cpp", ".hpp", ".cc", ".cxx"],
40910
- treeSitter: { grammarId: "cpp", wasmFile: "tree-sitter-cpp.wasm" },
40970
+ treeSitter: {
40971
+ grammarId: "cpp",
40972
+ wasmFile: "tree-sitter-cpp.wasm",
40973
+ commentNodes: ["comment"]
40974
+ },
40911
40975
  build: {
40912
40976
  detectFiles: ["CMakeLists.txt", "Makefile", "meson.build"],
40913
40977
  commands: [
@@ -40982,7 +41046,11 @@ var init_profiles = __esm(() => {
40982
41046
  displayName: "Swift",
40983
41047
  tier: 2,
40984
41048
  extensions: [".swift"],
40985
- treeSitter: { grammarId: "swift", wasmFile: "tree-sitter-swift.wasm" },
41049
+ treeSitter: {
41050
+ grammarId: "swift",
41051
+ wasmFile: "tree-sitter-swift.wasm",
41052
+ commentNodes: ["comment", "multiline_comment"]
41053
+ },
40986
41054
  build: {
40987
41055
  detectFiles: ["Package.swift", "*.xcodeproj", "*.xcworkspace"],
40988
41056
  commands: [
@@ -41056,7 +41124,11 @@ var init_profiles = __esm(() => {
41056
41124
  displayName: "Dart / Flutter",
41057
41125
  tier: 3,
41058
41126
  extensions: [".dart"],
41059
- treeSitter: { grammarId: "dart", wasmFile: "tree-sitter-dart.wasm" },
41127
+ treeSitter: {
41128
+ grammarId: "dart",
41129
+ wasmFile: "tree-sitter-dart.wasm",
41130
+ commentNodes: ["comment", "documentation_comment"]
41131
+ },
41060
41132
  build: {
41061
41133
  detectFiles: ["pubspec.yaml"],
41062
41134
  commands: [
@@ -41130,7 +41202,11 @@ var init_profiles = __esm(() => {
41130
41202
  displayName: "Ruby",
41131
41203
  tier: 3,
41132
41204
  extensions: [".rb", ".rake", ".gemspec"],
41133
- treeSitter: { grammarId: "ruby", wasmFile: "tree-sitter-ruby.wasm" },
41205
+ treeSitter: {
41206
+ grammarId: "ruby",
41207
+ wasmFile: "tree-sitter-ruby.wasm",
41208
+ commentNodes: ["comment"]
41209
+ },
41134
41210
  build: {
41135
41211
  detectFiles: ["Gemfile", "Rakefile"],
41136
41212
  commands: [
@@ -41199,7 +41275,11 @@ var init_profiles = __esm(() => {
41199
41275
  displayName: "PHP",
41200
41276
  tier: 3,
41201
41277
  extensions: [".php", ".phtml", ".blade.php"],
41202
- treeSitter: { grammarId: "php", wasmFile: "tree-sitter-php.wasm" },
41278
+ treeSitter: {
41279
+ grammarId: "php",
41280
+ wasmFile: "tree-sitter-php.wasm",
41281
+ commentNodes: ["comment"]
41282
+ },
41203
41283
  build: {
41204
41284
  detectFiles: ["composer.json"],
41205
41285
  commands: [
@@ -41207,7 +41287,7 @@ var init_profiles = __esm(() => {
41207
41287
  name: "Composer Install",
41208
41288
  cmd: "composer install --no-interaction --prefer-dist",
41209
41289
  detectFile: "composer.json",
41210
- priority: 1
41290
+ priority: 10
41211
41291
  }
41212
41292
  ]
41213
41293
  },
@@ -41218,19 +41298,19 @@ var init_profiles = __esm(() => {
41218
41298
  name: "Pest",
41219
41299
  detect: "Pest.php",
41220
41300
  cmd: "vendor/bin/pest",
41221
- priority: 1
41301
+ priority: 10
41222
41302
  },
41223
41303
  {
41224
41304
  name: "PHPUnit",
41225
41305
  detect: "phpunit.xml",
41226
41306
  cmd: "vendor/bin/phpunit",
41227
- priority: 3
41307
+ priority: 8
41228
41308
  },
41229
41309
  {
41230
41310
  name: "PHPUnit",
41231
41311
  detect: "phpunit.xml.dist",
41232
41312
  cmd: "vendor/bin/phpunit",
41233
- priority: 4
41313
+ priority: 7
41234
41314
  }
41235
41315
  ]
41236
41316
  },
@@ -41247,25 +41327,25 @@ var init_profiles = __esm(() => {
41247
41327
  name: "PHPStan",
41248
41328
  detect: "phpstan.neon",
41249
41329
  cmd: "vendor/bin/phpstan analyse",
41250
- priority: 1
41330
+ priority: 10
41251
41331
  },
41252
41332
  {
41253
41333
  name: "PHPStan",
41254
41334
  detect: "phpstan.neon.dist",
41255
41335
  cmd: "vendor/bin/phpstan analyse",
41256
- priority: 2
41336
+ priority: 9
41257
41337
  },
41258
41338
  {
41259
41339
  name: "Pint",
41260
41340
  detect: "pint.json",
41261
41341
  cmd: "vendor/bin/pint --test",
41262
- priority: 3
41342
+ priority: 8
41263
41343
  },
41264
41344
  {
41265
41345
  name: "PHP-CS-Fixer",
41266
41346
  detect: ".php-cs-fixer.php",
41267
41347
  cmd: "vendor/bin/php-cs-fixer fix --dry-run --diff",
41268
- priority: 4
41348
+ priority: 7
41269
41349
  }
41270
41350
  ]
41271
41351
  },
@@ -41370,9 +41450,12 @@ function isCommandAvailable(command) {
41370
41450
  const isWindows = process.platform === "win32";
41371
41451
  const cmd = isWindows ? `${command}.exe` : command;
41372
41452
  try {
41373
- const result = bunSpawnSync(isWindows ? ["where", cmd] : ["which", cmd], {
41374
- stdout: "pipe",
41375
- stderr: "pipe"
41453
+ const result = _internals11.spawnSyncImpl(isWindows ? ["where", cmd] : ["which", cmd], {
41454
+ cwd: process.cwd(),
41455
+ stdin: "ignore",
41456
+ stdout: "ignore",
41457
+ stderr: "ignore",
41458
+ timeout: IS_COMMAND_AVAILABLE_TIMEOUT_MS
41376
41459
  });
41377
41460
  const available = result.success;
41378
41461
  toolchainCache.set(command, available);
@@ -41580,7 +41663,7 @@ function clearToolchainCache() {
41580
41663
  function getEcosystems() {
41581
41664
  return ECOSYSTEMS.map((e) => e.ecosystem);
41582
41665
  }
41583
- var ECOSYSTEMS, PROFILE_TO_ECOSYSTEM_NAMES, toolchainCache, _internals11, build_discovery;
41666
+ var ECOSYSTEMS, PROFILE_TO_ECOSYSTEM_NAMES, toolchainCache, IS_COMMAND_AVAILABLE_TIMEOUT_MS = 3000, _internals11, build_discovery;
41584
41667
  var init_discovery = __esm(() => {
41585
41668
  init_dist();
41586
41669
  init_detector();
@@ -41703,7 +41786,8 @@ var init_discovery = __esm(() => {
41703
41786
  discoverBuildCommandsFromProfiles,
41704
41787
  discoverBuildCommands,
41705
41788
  clearToolchainCache,
41706
- getEcosystems
41789
+ getEcosystems,
41790
+ spawnSyncImpl: bunSpawnSync
41707
41791
  };
41708
41792
  build_discovery = tool({
41709
41793
  description: "Discover build commands for various ecosystems in a project directory",
@@ -45582,16 +45666,710 @@ var init_secretscan = __esm(() => {
45582
45666
  };
45583
45667
  });
45584
45668
 
45669
+ // src/lang/default-backend.ts
45670
+ import * as fs14 from "fs";
45671
+ import * as path31 from "path";
45672
+ function detectFileExists(dir, pattern) {
45673
+ if (pattern.includes("*") || pattern.includes("?")) {
45674
+ try {
45675
+ const files = fs14.readdirSync(dir);
45676
+ const regex = new RegExp(`^${pattern.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, ".")}$`);
45677
+ return files.some((f) => regex.test(f));
45678
+ } catch {
45679
+ return false;
45680
+ }
45681
+ }
45682
+ try {
45683
+ fs14.accessSync(path31.join(dir, pattern));
45684
+ return true;
45685
+ } catch {
45686
+ return false;
45687
+ }
45688
+ }
45689
+ function tokenizeCommand(cmd) {
45690
+ const out = [];
45691
+ let buf = "";
45692
+ let quote = null;
45693
+ for (const ch of cmd) {
45694
+ if (quote) {
45695
+ if (ch === quote) {
45696
+ quote = null;
45697
+ } else {
45698
+ buf += ch;
45699
+ }
45700
+ continue;
45701
+ }
45702
+ if (ch === '"' || ch === "'") {
45703
+ quote = ch;
45704
+ continue;
45705
+ }
45706
+ if (ch === " " || ch === "\t") {
45707
+ if (buf.length > 0) {
45708
+ out.push(buf);
45709
+ buf = "";
45710
+ }
45711
+ continue;
45712
+ }
45713
+ buf += ch;
45714
+ }
45715
+ if (buf.length > 0)
45716
+ out.push(buf);
45717
+ return out;
45718
+ }
45719
+ async function defaultSelectTestFramework(profile, dir) {
45720
+ const sorted = [...profile.test.frameworks].sort((a, b) => b.priority - a.priority);
45721
+ for (const fw of sorted) {
45722
+ if (!detectFileExists(dir, fw.detect))
45723
+ continue;
45724
+ const argv = tokenizeCommand(fw.cmd);
45725
+ if (argv.length === 0)
45726
+ continue;
45727
+ if (!isCommandAvailable(argv[0]))
45728
+ continue;
45729
+ return {
45730
+ name: fw.name,
45731
+ cmd: argv,
45732
+ cwd: dir,
45733
+ detectedVia: fw.detect,
45734
+ filesIgnored: false
45735
+ };
45736
+ }
45737
+ return null;
45738
+ }
45739
+ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}) {
45740
+ const scope = opts.scope ?? "all";
45741
+ const coverage = opts.coverage ?? false;
45742
+ switch (framework) {
45743
+ case "bun": {
45744
+ const args = ["bun", "test"];
45745
+ if (coverage)
45746
+ args.push("--coverage");
45747
+ if (scope !== "all" && files.length > 0)
45748
+ args.push(...files);
45749
+ return args;
45750
+ }
45751
+ case "vitest": {
45752
+ const args = ["npx", "vitest", "run"];
45753
+ if (coverage)
45754
+ args.push("--coverage");
45755
+ if (scope !== "all" && files.length > 0)
45756
+ args.push(...files);
45757
+ return args;
45758
+ }
45759
+ case "jest": {
45760
+ const args = ["npx", "jest"];
45761
+ if (coverage)
45762
+ args.push("--coverage");
45763
+ if (scope !== "all" && files.length > 0)
45764
+ args.push(...files);
45765
+ return args;
45766
+ }
45767
+ case "mocha": {
45768
+ const args = ["npx", "mocha"];
45769
+ if (scope !== "all" && files.length > 0)
45770
+ args.push(...files);
45771
+ return args;
45772
+ }
45773
+ case "pytest": {
45774
+ const isWindows = process.platform === "win32";
45775
+ const args = isWindows ? ["python", "-m", "pytest"] : ["python3", "-m", "pytest"];
45776
+ if (coverage)
45777
+ args.push("--cov=.", "--cov-report=term-missing");
45778
+ if (scope !== "all" && files.length > 0)
45779
+ args.push(...files);
45780
+ return args;
45781
+ }
45782
+ case "cargo": {
45783
+ const args = ["cargo", "test"];
45784
+ if (scope !== "all" && files.length > 0)
45785
+ args.push(...files);
45786
+ return args;
45787
+ }
45788
+ case "pester": {
45789
+ if (scope !== "all" && files.length > 0) {
45790
+ const escapedFiles = files.map((f) => f.replace(/'/g, "''").replace(/`/g, "``").replace(/\$/g, "`$"));
45791
+ const psCommand = `Invoke-Pester -Path @('${escapedFiles.join("','")}')`;
45792
+ const utf16Bytes = Buffer.from(psCommand, "utf16le");
45793
+ const base64Command = utf16Bytes.toString("base64");
45794
+ return ["pwsh", "-EncodedCommand", base64Command];
45795
+ }
45796
+ return ["pwsh", "-Command", "Invoke-Pester"];
45797
+ }
45798
+ case "go-test":
45799
+ return ["go", "test", "./..."];
45800
+ case "maven":
45801
+ return ["mvn", "test"];
45802
+ case "gradle": {
45803
+ const isWindows = process.platform === "win32";
45804
+ const hasGradlewBat = fs14.existsSync(path31.join(dir, "gradlew.bat"));
45805
+ const hasGradlew = fs14.existsSync(path31.join(dir, "gradlew"));
45806
+ if (hasGradlewBat && isWindows)
45807
+ return ["gradlew.bat", "test"];
45808
+ if (hasGradlew)
45809
+ return ["./gradlew", "test"];
45810
+ return ["gradle", "test"];
45811
+ }
45812
+ case "dotnet-test":
45813
+ return ["dotnet", "test"];
45814
+ case "ctest": {
45815
+ const buildDirCandidates = [
45816
+ "build",
45817
+ "_build",
45818
+ "cmake-build-debug",
45819
+ "cmake-build-release",
45820
+ "out"
45821
+ ];
45822
+ const actualBuildDir = buildDirCandidates.find((d) => fs14.existsSync(path31.join(dir, d, "CMakeCache.txt"))) ?? "build";
45823
+ return ["ctest", "--test-dir", actualBuildDir];
45824
+ }
45825
+ case "swift-test":
45826
+ return ["swift", "test"];
45827
+ case "dart-test":
45828
+ return isCommandAvailable("flutter") ? ["flutter", "test", ...files] : ["dart", "test", ...files];
45829
+ case "rspec": {
45830
+ const args = isCommandAvailable("bundle") ? ["bundle", "exec", "rspec"] : ["rspec"];
45831
+ if (scope !== "all" && files.length > 0)
45832
+ args.push(...files);
45833
+ return args;
45834
+ }
45835
+ case "minitest":
45836
+ if (scope !== "all" && files.length > 0) {
45837
+ const requires = files.map((f) => `require_relative '${f.replace(/\\/g, "/").replace(/'/g, "\\'")}'`).join("; ");
45838
+ return ["ruby", "-Itest", "-e", requires];
45839
+ }
45840
+ return [
45841
+ "ruby",
45842
+ "-Itest",
45843
+ "-e",
45844
+ 'Dir.glob("test/**/*_test.rb").sort.each { |f| require_relative f }'
45845
+ ];
45846
+ default: {
45847
+ const fw = profile.test.frameworks.find((f) => f.name === framework);
45848
+ if (!fw)
45849
+ return null;
45850
+ const argv = tokenizeCommand(fw.cmd);
45851
+ if (argv.length === 0)
45852
+ return null;
45853
+ if (files.length === 0)
45854
+ return argv;
45855
+ return [...argv, ...files];
45856
+ }
45857
+ }
45858
+ }
45859
+ function defaultParseTestOutput(framework, stdout, stderr, exitCode) {
45860
+ const output = stdout && stderr ? `${stdout}
45861
+ ${stderr}` : stdout || stderr || "";
45862
+ let passed = 0;
45863
+ let failed = 0;
45864
+ let skipped = 0;
45865
+ let total;
45866
+ let coveragePercent;
45867
+ switch (framework) {
45868
+ case "vitest":
45869
+ case "jest":
45870
+ case "bun": {
45871
+ const jsonMatch = output.match(/\{[\s\S]*"testResults"[\s\S]*\}/);
45872
+ if (jsonMatch) {
45873
+ try {
45874
+ const parsed = JSON.parse(jsonMatch[0]);
45875
+ if (parsed.numTotalTests !== undefined) {
45876
+ passed = parsed.numPassedTests || 0;
45877
+ failed = parsed.numFailedTests || 0;
45878
+ skipped = parsed.numPendingTests || 0;
45879
+ total = parsed.numTotalTests || 0;
45880
+ }
45881
+ if (parsed.coverage !== undefined) {
45882
+ coveragePercent = parsed.coverage;
45883
+ }
45884
+ } catch {}
45885
+ }
45886
+ if (total === undefined || total === 0) {
45887
+ const passMatch = output.match(/(\d+)\s+pass(ing|ed)?/);
45888
+ const failMatch = output.match(/(\d+)\s+fail(ing|ed)?/);
45889
+ const skipMatch = output.match(/(\d+)\s+skip(ping|ped)?/);
45890
+ if (passMatch)
45891
+ passed = parseInt(passMatch[1], 10);
45892
+ if (failMatch)
45893
+ failed = parseInt(failMatch[1], 10);
45894
+ if (skipMatch)
45895
+ skipped = parseInt(skipMatch[1], 10);
45896
+ total = passed + failed + skipped;
45897
+ }
45898
+ const coverageMatch = output.match(/All files[^\d]*(\d+\.?\d*)\s*%/);
45899
+ if (coveragePercent === undefined && coverageMatch) {
45900
+ coveragePercent = parseFloat(coverageMatch[1]);
45901
+ }
45902
+ break;
45903
+ }
45904
+ case "mocha": {
45905
+ const passMatch = output.match(/(\d+)\s+passing/);
45906
+ const failMatch = output.match(/(\d+)\s+failing/);
45907
+ const pendingMatch = output.match(/(\d+)\s+pending/);
45908
+ if (passMatch)
45909
+ passed = parseInt(passMatch[1], 10);
45910
+ if (failMatch)
45911
+ failed = parseInt(failMatch[1], 10);
45912
+ if (pendingMatch)
45913
+ skipped = parseInt(pendingMatch[1], 10);
45914
+ total = passed + failed + skipped;
45915
+ break;
45916
+ }
45917
+ case "pytest": {
45918
+ const passMatch = output.match(/(\d+)\s+passed/);
45919
+ const failMatch = output.match(/(\d+)\s+failed/);
45920
+ const skipMatch = output.match(/(\d+)\s+skipped/);
45921
+ if (passMatch)
45922
+ passed = parseInt(passMatch[1], 10);
45923
+ if (failMatch)
45924
+ failed = parseInt(failMatch[1], 10);
45925
+ if (skipMatch)
45926
+ skipped = parseInt(skipMatch[1], 10);
45927
+ total = passed + failed + skipped;
45928
+ const coverageMatch = output.match(/TOTAL\s+(\d+\.?\d*)\s*%/);
45929
+ if (coverageMatch)
45930
+ coveragePercent = parseFloat(coverageMatch[1]);
45931
+ break;
45932
+ }
45933
+ case "cargo": {
45934
+ const passMatch = output.match(/test result: ok\. (\d+) passed/);
45935
+ const failMatch = output.match(/test result: FAILED\. (\d+) passed; (\d+) failed/);
45936
+ if (failMatch) {
45937
+ passed = parseInt(failMatch[1], 10);
45938
+ failed = parseInt(failMatch[2], 10);
45939
+ } else if (passMatch) {
45940
+ passed = parseInt(passMatch[1], 10);
45941
+ }
45942
+ total = passed + failed;
45943
+ break;
45944
+ }
45945
+ case "pester": {
45946
+ const passMatch = output.match(/Passed:\s*(\d+)/);
45947
+ const failMatch = output.match(/Failed:\s*(\d+)/);
45948
+ const skipMatch = output.match(/Skipped:\s*(\d+)/);
45949
+ if (passMatch)
45950
+ passed = parseInt(passMatch[1], 10);
45951
+ if (failMatch)
45952
+ failed = parseInt(failMatch[1], 10);
45953
+ if (skipMatch)
45954
+ skipped = parseInt(skipMatch[1], 10);
45955
+ total = passed + failed + skipped;
45956
+ break;
45957
+ }
45958
+ case "go-test": {
45959
+ const passMatches = [...output.matchAll(/--- PASS:/g)];
45960
+ const failMatches = [...output.matchAll(/--- FAIL:/g)];
45961
+ const skipMatches = [...output.matchAll(/--- SKIP:/g)];
45962
+ passed = passMatches.length;
45963
+ failed = failMatches.length;
45964
+ skipped = skipMatches.length;
45965
+ total = passed + failed + skipped;
45966
+ const covMatch = output.match(/coverage:\s*(\d+\.?\d*)\s*%/);
45967
+ if (covMatch)
45968
+ coveragePercent = parseFloat(covMatch[1]);
45969
+ break;
45970
+ }
45971
+ case "maven": {
45972
+ const mavenMatch = output.match(/Tests run:\s*(\d+),\s*Failures:\s*(\d+),\s*Errors:\s*(\d+),\s*Skipped:\s*(\d+)/);
45973
+ if (mavenMatch) {
45974
+ const tot = parseInt(mavenMatch[1], 10);
45975
+ const failures = parseInt(mavenMatch[2], 10);
45976
+ const errors5 = parseInt(mavenMatch[3], 10);
45977
+ const sk = parseInt(mavenMatch[4], 10);
45978
+ failed = failures + errors5;
45979
+ skipped = sk;
45980
+ passed = tot - failed - sk;
45981
+ total = tot;
45982
+ }
45983
+ break;
45984
+ }
45985
+ case "gradle": {
45986
+ const gradleMatch = output.match(/(\d+) tests? completed(?:,\s*(\d+) failed)?(?:,\s*(\d+) skipped)?/);
45987
+ if (gradleMatch) {
45988
+ total = parseInt(gradleMatch[1], 10);
45989
+ failed = gradleMatch[2] ? parseInt(gradleMatch[2], 10) : 0;
45990
+ skipped = gradleMatch[3] ? parseInt(gradleMatch[3], 10) : 0;
45991
+ passed = total - failed - skipped;
45992
+ }
45993
+ break;
45994
+ }
45995
+ case "dotnet-test": {
45996
+ const passMatch = output.match(/Passed[!:]?\s*(\d+)/i);
45997
+ const failMatch = output.match(/Failed[!:]?\s*(\d+)/i);
45998
+ const skipMatch = output.match(/Skipped[!:]?\s*(\d+)/i);
45999
+ if (passMatch)
46000
+ passed = parseInt(passMatch[1], 10);
46001
+ if (failMatch)
46002
+ failed = parseInt(failMatch[1], 10);
46003
+ if (skipMatch)
46004
+ skipped = parseInt(skipMatch[1], 10);
46005
+ total = passed + failed + skipped;
46006
+ break;
46007
+ }
46008
+ case "ctest": {
46009
+ const ctestMatch = output.match(/(\d+) tests? failed out of (\d+)/);
46010
+ if (ctestMatch) {
46011
+ failed = parseInt(ctestMatch[1], 10);
46012
+ total = parseInt(ctestMatch[2], 10);
46013
+ passed = total - failed;
46014
+ } else {
46015
+ const allPassMatch = output.match(/100% tests passed.*?(\d+) tests?/);
46016
+ if (allPassMatch) {
46017
+ total = parseInt(allPassMatch[1], 10);
46018
+ passed = total;
46019
+ }
46020
+ }
46021
+ break;
46022
+ }
46023
+ case "swift-test": {
46024
+ const swiftMatch = output.match(/Executed (\d+) tests?,\s*with (\d+) failures?/);
46025
+ if (swiftMatch) {
46026
+ total = parseInt(swiftMatch[1], 10);
46027
+ failed = parseInt(swiftMatch[2], 10);
46028
+ passed = total - failed;
46029
+ }
46030
+ break;
46031
+ }
46032
+ case "dart-test": {
46033
+ const dartPassMatch = output.match(/\+(\d+):\s*All tests passed/);
46034
+ const dartMixMatch = output.match(/\+(\d+)\s+-(\d+):/);
46035
+ if (dartPassMatch) {
46036
+ passed = parseInt(dartPassMatch[1], 10);
46037
+ total = passed;
46038
+ } else if (dartMixMatch) {
46039
+ passed = parseInt(dartMixMatch[1], 10);
46040
+ failed = parseInt(dartMixMatch[2], 10);
46041
+ total = passed + failed;
46042
+ }
46043
+ break;
46044
+ }
46045
+ case "rspec": {
46046
+ const rspecMatch = output.match(/(\d+) examples?,\s*(\d+) failures?(?:,\s*(\d+) pending)?/);
46047
+ if (rspecMatch) {
46048
+ total = parseInt(rspecMatch[1], 10);
46049
+ failed = parseInt(rspecMatch[2], 10);
46050
+ skipped = rspecMatch[3] ? parseInt(rspecMatch[3], 10) : 0;
46051
+ passed = total - failed - skipped;
46052
+ }
46053
+ break;
46054
+ }
46055
+ case "minitest": {
46056
+ const minitestMatch = output.match(/(\d+) runs?,\s*\d+ assertions?,\s*(\d+) failures?,\s*(\d+) errors?,\s*(\d+) skips?/);
46057
+ if (minitestMatch) {
46058
+ total = parseInt(minitestMatch[1], 10);
46059
+ const failures = parseInt(minitestMatch[2], 10);
46060
+ const errors5 = parseInt(minitestMatch[3], 10);
46061
+ skipped = parseInt(minitestMatch[4], 10);
46062
+ failed = failures + errors5;
46063
+ passed = total - failed - skipped;
46064
+ }
46065
+ break;
46066
+ }
46067
+ default:
46068
+ break;
46069
+ }
46070
+ if (total === undefined)
46071
+ total = passed + failed + skipped;
46072
+ return {
46073
+ ok: exitCode === 0,
46074
+ raw: { stdout, stderr, exitCode },
46075
+ passed,
46076
+ failed,
46077
+ skipped,
46078
+ total,
46079
+ ...coveragePercent !== undefined ? { coveragePercent } : {}
46080
+ };
46081
+ }
46082
+ async function defaultDetectProject(profile, dir) {
46083
+ for (const f of profile.build.detectFiles) {
46084
+ if (detectFileExists(dir, f))
46085
+ return true;
46086
+ }
46087
+ return false;
46088
+ }
46089
+ async function defaultSelectBuildCommand(profile, dir) {
46090
+ const sorted = [...profile.build.commands].sort((a, b) => b.priority - a.priority);
46091
+ for (const cmd of sorted) {
46092
+ if (cmd.detectFile && !detectFileExists(dir, cmd.detectFile))
46093
+ continue;
46094
+ const argv = tokenizeCommand(cmd.cmd);
46095
+ if (argv.length === 0)
46096
+ continue;
46097
+ if (!isCommandAvailable(argv[0]))
46098
+ continue;
46099
+ return {
46100
+ name: cmd.name,
46101
+ cmd: argv,
46102
+ cwd: dir,
46103
+ detectedVia: cmd.detectFile ?? `${profile.id} default`
46104
+ };
46105
+ }
46106
+ return null;
46107
+ }
46108
+ async function defaultTestFilesFor(profile, sourceFile, dir) {
46109
+ const ext = path31.extname(sourceFile);
46110
+ if (!profile.extensions.includes(ext))
46111
+ return [];
46112
+ const base = path31.basename(sourceFile, ext);
46113
+ const rel = path31.relative(dir, sourceFile);
46114
+ const relDir = path31.dirname(rel);
46115
+ const stripSrc = relDir.replace(/^src(\/|\\)/, "");
46116
+ const candidates = new Set;
46117
+ for (const tDir of ["tests", "test", "__tests__", "spec"]) {
46118
+ for (const suffix of ["", "_test", ".test", "_spec", ".spec"]) {
46119
+ candidates.add(path31.join(dir, tDir, stripSrc, `${base}${suffix}${ext}`));
46120
+ }
46121
+ }
46122
+ const existing = [];
46123
+ for (const c of candidates) {
46124
+ try {
46125
+ fs14.accessSync(c);
46126
+ existing.push(c);
46127
+ } catch {}
46128
+ }
46129
+ return existing;
46130
+ }
46131
+ function defaultExtractImports() {
46132
+ return [];
46133
+ }
46134
+ async function defaultSelectFramework() {
46135
+ return null;
46136
+ }
46137
+ async function defaultSelectEntryPoints() {
46138
+ return [];
46139
+ }
46140
+ function defaultBackendFor(profile) {
46141
+ return {
46142
+ ...profile,
46143
+ detectProject: (dir) => defaultDetectProject(profile, dir),
46144
+ selectTestFramework: (dir) => defaultSelectTestFramework(profile, dir),
46145
+ buildTestCommand: (framework, files, dir, opts) => defaultBuildTestCommand(profile, framework, files, dir, opts),
46146
+ parseTestOutput: (framework, stdout, stderr, exitCode) => defaultParseTestOutput(framework, stdout, stderr, exitCode),
46147
+ testFilesFor: (sourceFile, dir) => defaultTestFilesFor(profile, sourceFile, dir),
46148
+ extractImports: () => defaultExtractImports(),
46149
+ selectBuildCommand: (dir) => defaultSelectBuildCommand(profile, dir),
46150
+ selectFramework: () => defaultSelectFramework(),
46151
+ selectEntryPoints: () => defaultSelectEntryPoints()
46152
+ };
46153
+ }
46154
+ var init_default_backend = __esm(() => {
46155
+ init_discovery();
46156
+ });
46157
+
46158
+ // src/lang/backends/go.ts
46159
+ import * as fs15 from "fs";
46160
+ import * as path32 from "path";
46161
+ function extractImports(_sourceFile, source) {
46162
+ const out = new Set;
46163
+ IMPORT_REGEX_SINGLE.lastIndex = 0;
46164
+ let m = IMPORT_REGEX_SINGLE.exec(source);
46165
+ while (m !== null) {
46166
+ out.add(m[1]);
46167
+ m = IMPORT_REGEX_SINGLE.exec(source);
46168
+ }
46169
+ IMPORT_REGEX_GROUP.lastIndex = 0;
46170
+ m = IMPORT_REGEX_GROUP.exec(source);
46171
+ while (m !== null) {
46172
+ const block = m[1];
46173
+ IMPORT_REGEX_GROUP_LINE.lastIndex = 0;
46174
+ let inner = IMPORT_REGEX_GROUP_LINE.exec(block);
46175
+ while (inner !== null) {
46176
+ out.add(inner[1]);
46177
+ inner = IMPORT_REGEX_GROUP_LINE.exec(block);
46178
+ }
46179
+ m = IMPORT_REGEX_GROUP.exec(source);
46180
+ }
46181
+ return [...out];
46182
+ }
46183
+ async function selectFramework(dir) {
46184
+ let content;
46185
+ try {
46186
+ content = fs15.readFileSync(path32.join(dir, "go.mod"), "utf-8");
46187
+ } catch {
46188
+ return null;
46189
+ }
46190
+ const candidates = [
46191
+ ["github.com/gin-gonic/gin", "gin"],
46192
+ ["github.com/labstack/echo", "echo"],
46193
+ ["github.com/gofiber/fiber", "fiber"],
46194
+ ["github.com/gorilla/mux", "gorilla"],
46195
+ ["github.com/go-chi/chi", "chi"]
46196
+ ];
46197
+ for (const [pkg, name] of candidates) {
46198
+ if (content.includes(pkg)) {
46199
+ return { name, detectedVia: `go.mod require ${pkg}` };
46200
+ }
46201
+ }
46202
+ return null;
46203
+ }
46204
+ async function selectEntryPoints(dir) {
46205
+ const points = [];
46206
+ try {
46207
+ fs15.accessSync(path32.join(dir, "main.go"));
46208
+ points.push("main.go");
46209
+ } catch {}
46210
+ try {
46211
+ const cmdDir = path32.join(dir, "cmd");
46212
+ const subdirs = fs15.readdirSync(cmdDir, { withFileTypes: true }).filter((d) => d.isDirectory());
46213
+ for (const sub of subdirs) {
46214
+ const main = path32.join("cmd", sub.name, "main.go");
46215
+ try {
46216
+ fs15.accessSync(path32.join(dir, main));
46217
+ points.push(main);
46218
+ } catch {}
46219
+ }
46220
+ } catch {}
46221
+ return points;
46222
+ }
46223
+ function buildGoBackend() {
46224
+ const profile = LANGUAGE_REGISTRY.get(PROFILE_ID);
46225
+ if (!profile) {
46226
+ throw new Error("buildGoBackend: go profile not in LANGUAGE_REGISTRY. " + "profiles.ts must be imported before this backend.");
46227
+ }
46228
+ return {
46229
+ ...defaultBackendFor(profile),
46230
+ extractImports,
46231
+ selectFramework,
46232
+ selectEntryPoints
46233
+ };
46234
+ }
46235
+ var PROFILE_ID = "go", IMPORT_REGEX_SINGLE, IMPORT_REGEX_GROUP, IMPORT_REGEX_GROUP_LINE, _internals18;
46236
+ var init_go = __esm(() => {
46237
+ init_default_backend();
46238
+ init_profiles();
46239
+ IMPORT_REGEX_SINGLE = /^\s*import\s+(?:[a-zA-Z_.][a-zA-Z0-9_]*\s+)?"([^"]+)"/gm;
46240
+ IMPORT_REGEX_GROUP = /^\s*import\s*\(([\s\S]*?)\)/gm;
46241
+ IMPORT_REGEX_GROUP_LINE = /(?:[a-zA-Z_.][a-zA-Z0-9_]*\s+)?"([^"]+)"/g;
46242
+ _internals18 = { extractImports };
46243
+ });
46244
+
46245
+ // src/lang/backends/python.ts
46246
+ import * as fs16 from "fs";
46247
+ import * as path33 from "path";
46248
+ function parseImportTargets(rawTargets) {
46249
+ const cleaned = rawTargets.replace(/[()]/g, "").split(`
46250
+ `).map((line) => line.replace(/#.*$/, "").replace(/\\\s*$/, "")).join(" ");
46251
+ const out = [];
46252
+ for (const seg of cleaned.split(",")) {
46253
+ const trimmed = seg.trim();
46254
+ if (trimmed.length === 0)
46255
+ continue;
46256
+ const name = trimmed.split(/\s+as\s+/)[0].trim();
46257
+ if (/^[\w]+$/.test(name))
46258
+ out.push(name);
46259
+ }
46260
+ return out;
46261
+ }
46262
+ function extractImports2(_sourceFile, source) {
46263
+ const out = new Set;
46264
+ source = source.replace(/\\\r?\n[ \t]*/g, " ");
46265
+ IMPORT_REGEX_FROM_WITH_TARGETS.lastIndex = 0;
46266
+ let m = IMPORT_REGEX_FROM_WITH_TARGETS.exec(source);
46267
+ while (m !== null) {
46268
+ const fromClause = m[1];
46269
+ const targets = parseImportTargets(m[2]);
46270
+ const isPurelyRelative = fromClause.length > 0 && /^\.+$/.test(fromClause);
46271
+ if (isPurelyRelative && targets.length > 0) {
46272
+ for (const t of targets)
46273
+ out.add(`${fromClause}${t}`);
46274
+ } else if (fromClause.length > 0) {
46275
+ out.add(fromClause);
46276
+ }
46277
+ m = IMPORT_REGEX_FROM_WITH_TARGETS.exec(source);
46278
+ }
46279
+ IMPORT_REGEX_IMPORT.lastIndex = 0;
46280
+ m = IMPORT_REGEX_IMPORT.exec(source);
46281
+ while (m !== null) {
46282
+ const segments = m[1].split(",");
46283
+ for (const seg of segments) {
46284
+ const trimmed = seg.trim();
46285
+ if (trimmed.length === 0)
46286
+ continue;
46287
+ const mod = trimmed.split(/\s+as\s+/)[0].trim();
46288
+ if (/^[\w.]+$/.test(mod))
46289
+ out.add(mod);
46290
+ }
46291
+ m = IMPORT_REGEX_IMPORT.exec(source);
46292
+ }
46293
+ return [...out];
46294
+ }
46295
+ async function selectFramework2(dir) {
46296
+ const candidates = [
46297
+ ["django", "django"],
46298
+ ["flask", "flask"],
46299
+ ["fastapi", "fastapi"],
46300
+ ["starlette", "starlette"],
46301
+ ["tornado", "tornado"],
46302
+ ["aiohttp", "aiohttp"],
46303
+ ["bottle", "bottle"]
46304
+ ];
46305
+ for (const candidate of ["pyproject.toml", "requirements.txt", "setup.py"]) {
46306
+ try {
46307
+ const content = fs16.readFileSync(path33.join(dir, candidate), "utf-8");
46308
+ const lower = content.toLowerCase();
46309
+ for (const [pkg, name] of candidates) {
46310
+ if (lower.includes(pkg)) {
46311
+ return { name, detectedVia: candidate };
46312
+ }
46313
+ }
46314
+ } catch {}
46315
+ }
46316
+ return null;
46317
+ }
46318
+ async function selectEntryPoints2(dir) {
46319
+ const points = new Set;
46320
+ try {
46321
+ const content = fs16.readFileSync(path33.join(dir, "pyproject.toml"), "utf-8");
46322
+ const scriptsBlock = content.match(/\[project\.scripts\][\s\S]*?(?=\n\[|$)/);
46323
+ if (scriptsBlock) {
46324
+ for (const line of scriptsBlock[0].split(`
46325
+ `)) {
46326
+ const m = line.match(/=\s*['"]([^'":]+)/);
46327
+ if (m) {
46328
+ const modPath = m[1].replace(/\./g, "/") + ".py";
46329
+ points.add(modPath);
46330
+ }
46331
+ }
46332
+ }
46333
+ } catch {}
46334
+ for (const name of ["manage.py", "main.py", "app.py", "__main__.py"]) {
46335
+ try {
46336
+ fs16.accessSync(path33.join(dir, name));
46337
+ points.add(name);
46338
+ } catch {}
46339
+ }
46340
+ return [...points];
46341
+ }
46342
+ function buildPythonBackend() {
46343
+ const profile = LANGUAGE_REGISTRY.get(PROFILE_ID2);
46344
+ if (!profile) {
46345
+ throw new Error("buildPythonBackend: python profile not in LANGUAGE_REGISTRY. " + "profiles.ts must be imported before this backend.");
46346
+ }
46347
+ return {
46348
+ ...defaultBackendFor(profile),
46349
+ extractImports: extractImports2,
46350
+ selectFramework: selectFramework2,
46351
+ selectEntryPoints: selectEntryPoints2
46352
+ };
46353
+ }
46354
+ var PROFILE_ID2 = "python", IMPORT_REGEX_FROM_WITH_TARGETS, IMPORT_REGEX_IMPORT, _internals19;
46355
+ var init_python = __esm(() => {
46356
+ init_default_backend();
46357
+ init_profiles();
46358
+ IMPORT_REGEX_FROM_WITH_TARGETS = /^\s*from\s+(\.*[\w.]*)\s+import\s+(\([^)]*\)|[^\n#]+)/gm;
46359
+ IMPORT_REGEX_IMPORT = /^\s*import\s+([^\n#]+)/gm;
46360
+ _internals19 = { extractImports: extractImports2 };
46361
+ });
46362
+
45585
46363
  // src/test-impact/analyzer.ts
45586
- import fs14 from "fs";
45587
- import path31 from "path";
46364
+ import fs17 from "fs";
46365
+ import path34 from "path";
45588
46366
  function normalizePath(p) {
45589
46367
  return p.replace(/\\/g, "/");
45590
46368
  }
45591
46369
  function isCacheStale(impactMap, generatedAtMs) {
45592
46370
  for (const sourcePath of Object.keys(impactMap)) {
45593
46371
  try {
45594
- const stat3 = fs14.statSync(sourcePath);
46372
+ const stat3 = fs17.statSync(sourcePath);
45595
46373
  if (stat3.mtimeMs > generatedAtMs) {
45596
46374
  return true;
45597
46375
  }
@@ -45605,21 +46383,108 @@ function resolveRelativeImport(fromDir, importPath) {
45605
46383
  if (!importPath.startsWith(".")) {
45606
46384
  return null;
45607
46385
  }
45608
- const resolved = path31.resolve(fromDir, importPath);
45609
- if (path31.extname(resolved)) {
45610
- if (fs14.existsSync(resolved) && fs14.statSync(resolved).isFile()) {
46386
+ const resolved = path34.resolve(fromDir, importPath);
46387
+ if (path34.extname(resolved)) {
46388
+ if (fs17.existsSync(resolved) && fs17.statSync(resolved).isFile()) {
45611
46389
  return normalizePath(resolved);
45612
46390
  }
45613
46391
  } else {
45614
46392
  for (const ext of EXTENSIONS_TO_TRY) {
45615
46393
  const withExt = resolved + ext;
45616
- if (fs14.existsSync(withExt) && fs14.statSync(withExt).isFile()) {
46394
+ if (fs17.existsSync(withExt) && fs17.statSync(withExt).isFile()) {
45617
46395
  return normalizePath(withExt);
45618
46396
  }
45619
46397
  }
45620
46398
  }
45621
46399
  return null;
45622
46400
  }
46401
+ function resolvePythonImport(fromDir, module) {
46402
+ if (!module.startsWith("."))
46403
+ return null;
46404
+ const leadingDots = module.match(/^\.+/)?.[0].length ?? 0;
46405
+ let baseDir = fromDir;
46406
+ for (let i = 1;i < leadingDots; i++) {
46407
+ baseDir = path34.dirname(baseDir);
46408
+ }
46409
+ const rest = module.slice(leadingDots);
46410
+ if (rest.length === 0) {
46411
+ const initPath = path34.join(baseDir, "__init__.py");
46412
+ if (fs17.existsSync(initPath) && fs17.statSync(initPath).isFile()) {
46413
+ return normalizePath(initPath);
46414
+ }
46415
+ return null;
46416
+ }
46417
+ const subpath = rest.replace(/\./g, path34.sep);
46418
+ const candidates = [
46419
+ `${path34.join(baseDir, subpath)}.py`,
46420
+ path34.join(baseDir, subpath, "__init__.py")
46421
+ ];
46422
+ for (const c of candidates) {
46423
+ if (fs17.existsSync(c) && fs17.statSync(c).isFile())
46424
+ return normalizePath(c);
46425
+ }
46426
+ return null;
46427
+ }
46428
+ function findGoModule(fromDir) {
46429
+ const resolved = path34.resolve(fromDir);
46430
+ let cur = resolved;
46431
+ const walked = [];
46432
+ for (let i = 0;i < 16; i++) {
46433
+ const cached3 = goModuleCache.get(cur);
46434
+ if (cached3 !== undefined) {
46435
+ for (const d of walked)
46436
+ goModuleCache.set(d, cached3);
46437
+ return cached3;
46438
+ }
46439
+ walked.push(cur);
46440
+ try {
46441
+ const goMod = path34.join(cur, "go.mod");
46442
+ const content = fs17.readFileSync(goMod, "utf-8");
46443
+ const moduleMatch = content.match(/^\s*module\s+"?([^"\s/]+(?:\/[^"\s]+)*)"?/m);
46444
+ if (moduleMatch) {
46445
+ const result = { moduleRoot: cur, modulePath: moduleMatch[1] };
46446
+ for (const d of walked)
46447
+ goModuleCache.set(d, result);
46448
+ return result;
46449
+ }
46450
+ } catch {}
46451
+ try {
46452
+ fs17.accessSync(path34.join(cur, ".git"));
46453
+ break;
46454
+ } catch {}
46455
+ const parent = path34.dirname(cur);
46456
+ if (parent === cur)
46457
+ break;
46458
+ cur = parent;
46459
+ }
46460
+ for (const d of walked)
46461
+ goModuleCache.set(d, null);
46462
+ return null;
46463
+ }
46464
+ function resolveGoImport(fromDir, importPath) {
46465
+ let dir = null;
46466
+ if (importPath.startsWith(".")) {
46467
+ dir = path34.resolve(fromDir, importPath);
46468
+ } else {
46469
+ const mod = findGoModule(fromDir);
46470
+ if (mod && (importPath === mod.modulePath || importPath.startsWith(`${mod.modulePath}/`))) {
46471
+ const subpath = importPath.slice(mod.modulePath.length);
46472
+ dir = path34.join(mod.moduleRoot, subpath);
46473
+ }
46474
+ }
46475
+ if (dir === null)
46476
+ return [];
46477
+ if (!fs17.existsSync(dir) || !fs17.statSync(dir).isDirectory())
46478
+ return [];
46479
+ try {
46480
+ return fs17.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath(path34.join(dir, f)));
46481
+ } catch {
46482
+ return [];
46483
+ }
46484
+ }
46485
+ function _clearGoModuleCache() {
46486
+ goModuleCache.clear();
46487
+ }
45623
46488
  function findTestFilesSync(cwd) {
45624
46489
  const testFiles = [];
45625
46490
  const skipDirs = new Set([
@@ -45632,13 +46497,13 @@ function findTestFilesSync(cwd) {
45632
46497
  function walk(dir, visitedInodes) {
45633
46498
  let entries;
45634
46499
  try {
45635
- entries = fs14.readdirSync(dir, { withFileTypes: true });
46500
+ entries = fs17.readdirSync(dir, { withFileTypes: true });
45636
46501
  } catch {
45637
46502
  return;
45638
46503
  }
45639
46504
  let dirInode;
45640
46505
  try {
45641
- dirInode = fs14.statSync(dir).ino;
46506
+ dirInode = fs17.statSync(dir).ino;
45642
46507
  } catch {
45643
46508
  return;
45644
46509
  }
@@ -45651,12 +46516,15 @@ function findTestFilesSync(cwd) {
45651
46516
  for (const entry of entries) {
45652
46517
  if (entry.isDirectory()) {
45653
46518
  if (!skipDirs.has(entry.name)) {
45654
- walk(path31.join(dir, entry.name), visitedInodes);
46519
+ walk(path34.join(dir, entry.name), visitedInodes);
45655
46520
  }
45656
46521
  } else if (entry.isFile()) {
45657
46522
  const name = entry.name;
45658
- if (/\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name)) {
45659
- testFiles.push(normalizePath(path31.join(dir, entry.name)));
46523
+ const isTsTest = /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name);
46524
+ const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${path34.sep}tests${path34.sep}`) && name.endsWith(".py");
46525
+ const isGoTest = /.+_test\.go$/.test(name);
46526
+ if (isTsTest || isPyTest || isGoTest) {
46527
+ testFiles.push(normalizePath(path34.join(dir, entry.name)));
45660
46528
  }
45661
46529
  }
45662
46530
  }
@@ -45664,7 +46532,7 @@ function findTestFilesSync(cwd) {
45664
46532
  walk(cwd, new Set);
45665
46533
  return [...new Set(testFiles)];
45666
46534
  }
45667
- function extractImports(content) {
46535
+ function extractImports3(content) {
45668
46536
  function execRegex(regex, content2) {
45669
46537
  const results = [];
45670
46538
  regex.lastIndex = 0;
@@ -45680,68 +46548,93 @@ function extractImports(content) {
45680
46548
  ...execRegex(IMPORT_REGEX_REEXPORT, content)
45681
46549
  ];
45682
46550
  }
46551
+ function addImpactEdgesForTestFile(testFile, content, impactMap) {
46552
+ const ext = path34.extname(testFile).toLowerCase();
46553
+ const testDir = path34.dirname(testFile);
46554
+ function addEdge(source) {
46555
+ if (!impactMap[source])
46556
+ impactMap[source] = [];
46557
+ if (!impactMap[source].includes(testFile)) {
46558
+ impactMap[source].push(testFile);
46559
+ }
46560
+ }
46561
+ if (TS_EXTENSIONS.has(ext)) {
46562
+ const imports = extractImports3(content);
46563
+ for (const importPath of imports) {
46564
+ const resolved = resolveRelativeImport(testDir, importPath);
46565
+ if (resolved !== null)
46566
+ addEdge(resolved);
46567
+ }
46568
+ return;
46569
+ }
46570
+ if (PYTHON_EXTENSIONS.has(ext)) {
46571
+ const modules = _internals19.extractImports(testFile, content);
46572
+ for (const mod of modules) {
46573
+ const resolved = resolvePythonImport(testDir, mod);
46574
+ if (resolved !== null)
46575
+ addEdge(resolved);
46576
+ }
46577
+ return;
46578
+ }
46579
+ if (GO_EXTENSIONS.has(ext)) {
46580
+ const imports = _internals18.extractImports(testFile, content);
46581
+ for (const importPath of imports) {
46582
+ const sourceFiles = resolveGoImport(testDir, importPath);
46583
+ for (const source of sourceFiles)
46584
+ addEdge(source);
46585
+ }
46586
+ return;
46587
+ }
46588
+ }
45683
46589
  async function buildImpactMapInternal(cwd) {
45684
46590
  const testFiles = findTestFilesSync(cwd);
45685
46591
  const impactMap = {};
45686
46592
  for (const testFile of testFiles) {
45687
46593
  let content;
45688
46594
  try {
45689
- content = fs14.readFileSync(testFile, "utf-8");
46595
+ content = fs17.readFileSync(testFile, "utf-8");
45690
46596
  } catch {
45691
46597
  continue;
45692
46598
  }
45693
46599
  if (content.substring(0, 8192).includes("\x00")) {
45694
46600
  continue;
45695
46601
  }
45696
- const imports = extractImports(content);
45697
- const testDir = path31.dirname(testFile);
45698
- for (const importPath of imports) {
45699
- const resolvedSource = resolveRelativeImport(testDir, importPath);
45700
- if (resolvedSource === null) {
45701
- continue;
45702
- }
45703
- if (!impactMap[resolvedSource]) {
45704
- impactMap[resolvedSource] = [];
45705
- }
45706
- if (!impactMap[resolvedSource].includes(testFile)) {
45707
- impactMap[resolvedSource].push(testFile);
45708
- }
45709
- }
46602
+ addImpactEdgesForTestFile(testFile, content, impactMap);
45710
46603
  }
45711
46604
  return impactMap;
45712
46605
  }
45713
46606
  async function buildImpactMap(cwd) {
45714
- const impactMap = await _internals18.buildImpactMapInternal(cwd);
45715
- await _internals18.saveImpactMap(cwd, impactMap);
46607
+ const impactMap = await _internals20.buildImpactMapInternal(cwd);
46608
+ await _internals20.saveImpactMap(cwd, impactMap);
45716
46609
  return impactMap;
45717
46610
  }
45718
46611
  async function loadImpactMap(cwd) {
45719
- const cachePath = path31.join(cwd, ".swarm", "cache", "impact-map.json");
45720
- if (fs14.existsSync(cachePath)) {
46612
+ const cachePath = path34.join(cwd, ".swarm", "cache", "impact-map.json");
46613
+ if (fs17.existsSync(cachePath)) {
45721
46614
  try {
45722
- const content = fs14.readFileSync(cachePath, "utf-8");
46615
+ const content = fs17.readFileSync(cachePath, "utf-8");
45723
46616
  const data = JSON.parse(content);
45724
46617
  const map3 = data.map;
45725
46618
  const generatedAt = new Date(data.generatedAt).getTime();
45726
- if (!_internals18.isCacheStale(map3, generatedAt)) {
46619
+ if (!_internals20.isCacheStale(map3, generatedAt)) {
45727
46620
  return map3;
45728
46621
  }
45729
46622
  } catch {}
45730
46623
  }
45731
- return _internals18.buildImpactMap(cwd);
46624
+ return _internals20.buildImpactMap(cwd);
45732
46625
  }
45733
46626
  async function saveImpactMap(cwd, impactMap) {
45734
- const cacheDir2 = path31.join(cwd, ".swarm", "cache");
45735
- const cachePath = path31.join(cacheDir2, "impact-map.json");
45736
- if (!fs14.existsSync(cacheDir2)) {
45737
- fs14.mkdirSync(cacheDir2, { recursive: true });
46627
+ const cacheDir2 = path34.join(cwd, ".swarm", "cache");
46628
+ const cachePath = path34.join(cacheDir2, "impact-map.json");
46629
+ if (!fs17.existsSync(cacheDir2)) {
46630
+ fs17.mkdirSync(cacheDir2, { recursive: true });
45738
46631
  }
45739
46632
  const data = {
45740
46633
  generatedAt: new Date().toISOString(),
45741
46634
  fileCount: Object.keys(impactMap).length,
45742
46635
  map: impactMap
45743
46636
  };
45744
- fs14.writeFileSync(cachePath, JSON.stringify(data, null, 2), "utf-8");
46637
+ fs17.writeFileSync(cachePath, JSON.stringify(data, null, 2), "utf-8");
45745
46638
  }
45746
46639
  async function analyzeImpact(changedFiles, cwd) {
45747
46640
  if (!Array.isArray(changedFiles)) {
@@ -45754,11 +46647,11 @@ async function analyzeImpact(changedFiles, cwd) {
45754
46647
  };
45755
46648
  }
45756
46649
  const validFiles = changedFiles.filter((f) => typeof f === "string" && f.length > 0 && !f.includes("\x00"));
45757
- const impactMap = await _internals18.loadImpactMap(cwd);
46650
+ const impactMap = await _internals20.loadImpactMap(cwd);
45758
46651
  const impactedTestsSet = new Set;
45759
46652
  const untestedFiles = [];
45760
46653
  for (const changedFile of validFiles) {
45761
- const normalizedChanged = normalizePath(path31.resolve(changedFile));
46654
+ const normalizedChanged = normalizePath(path34.resolve(changedFile));
45762
46655
  const tests = impactMap[normalizedChanged];
45763
46656
  if (tests && tests.length > 0) {
45764
46657
  for (const test of tests) {
@@ -45795,23 +46688,30 @@ async function analyzeImpact(changedFiles, cwd) {
45795
46688
  impactMap
45796
46689
  };
45797
46690
  }
45798
- var IMPORT_REGEX_ES, IMPORT_REGEX_REQUIRE, IMPORT_REGEX_REEXPORT, EXTENSIONS_TO_TRY, _internals18;
46691
+ var IMPORT_REGEX_ES, IMPORT_REGEX_REQUIRE, IMPORT_REGEX_REEXPORT, TS_EXTENSIONS, PYTHON_EXTENSIONS, GO_EXTENSIONS, EXTENSIONS_TO_TRY, goModuleCache, _internals20;
45799
46692
  var init_analyzer = __esm(() => {
45800
- IMPORT_REGEX_ES = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
46693
+ init_go();
46694
+ init_python();
46695
+ IMPORT_REGEX_ES = /import\s+[\s\S]*?\s+from\s+['"]([^'"]+)['"]/g;
45801
46696
  IMPORT_REGEX_REQUIRE = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
45802
46697
  IMPORT_REGEX_REEXPORT = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
46698
+ TS_EXTENSIONS = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
46699
+ PYTHON_EXTENSIONS = new Set([".py"]);
46700
+ GO_EXTENSIONS = new Set([".go"]);
45803
46701
  EXTENSIONS_TO_TRY = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
45804
- _internals18 = {
46702
+ goModuleCache = new Map;
46703
+ _internals20 = {
45805
46704
  normalizePath,
45806
46705
  isCacheStale,
45807
46706
  resolveRelativeImport,
45808
46707
  findTestFilesSync,
45809
- extractImports,
46708
+ extractImports: extractImports3,
45810
46709
  buildImpactMapInternal,
45811
46710
  buildImpactMap,
45812
46711
  loadImpactMap,
45813
46712
  saveImpactMap,
45814
- analyzeImpact
46713
+ analyzeImpact,
46714
+ _clearGoModuleCache
45815
46715
  };
45816
46716
  });
45817
46717
 
@@ -46021,10 +46921,10 @@ function detectFlakyTests(allHistory) {
46021
46921
  var FLAKY_THRESHOLD = 0.3, MIN_RUNS_FOR_QUARANTINE = 5, MAX_HISTORY_RUNS = 20;
46022
46922
 
46023
46923
  // src/test-impact/history-store.ts
46024
- import fs15 from "fs";
46025
- import path32 from "path";
46924
+ import fs18 from "fs";
46925
+ import path35 from "path";
46026
46926
  function getHistoryPath(workingDir) {
46027
- return path32.join(workingDir || process.cwd(), ".swarm", "cache", "test-history.jsonl");
46927
+ return path35.join(workingDir || process.cwd(), ".swarm", "cache", "test-history.jsonl");
46028
46928
  }
46029
46929
  function sanitizeErrorMessage(errorMessage) {
46030
46930
  if (errorMessage === undefined) {
@@ -46079,9 +46979,9 @@ function appendTestRun(record3, workingDir) {
46079
46979
  changedFiles: sanitizeChangedFiles(record3.changedFiles || [])
46080
46980
  };
46081
46981
  const historyPath = getHistoryPath(workingDir);
46082
- const historyDir = path32.dirname(historyPath);
46083
- if (!fs15.existsSync(historyDir)) {
46084
- fs15.mkdirSync(historyDir, { recursive: true });
46982
+ const historyDir = path35.dirname(historyPath);
46983
+ if (!fs18.existsSync(historyDir)) {
46984
+ fs18.mkdirSync(historyDir, { recursive: true });
46085
46985
  }
46086
46986
  const existingRecords = readAllRecords(historyPath);
46087
46987
  existingRecords.push(sanitizedRecord);
@@ -46106,24 +47006,24 @@ function appendTestRun(record3, workingDir) {
46106
47006
  `)}
46107
47007
  `;
46108
47008
  const tempPath = `${historyPath}.tmp`;
46109
- fs15.writeFileSync(tempPath, content, "utf-8");
46110
- fs15.renameSync(tempPath, historyPath);
47009
+ fs18.writeFileSync(tempPath, content, "utf-8");
47010
+ fs18.renameSync(tempPath, historyPath);
46111
47011
  } catch (err) {
46112
47012
  try {
46113
47013
  const tempPath = `${historyPath}.tmp`;
46114
- if (fs15.existsSync(tempPath)) {
46115
- fs15.unlinkSync(tempPath);
47014
+ if (fs18.existsSync(tempPath)) {
47015
+ fs18.unlinkSync(tempPath);
46116
47016
  }
46117
47017
  } catch {}
46118
47018
  throw new Error(`Failed to write test history: ${err instanceof Error ? err.message : String(err)}`);
46119
47019
  }
46120
47020
  }
46121
47021
  function readAllRecords(historyPath) {
46122
- if (!fs15.existsSync(historyPath)) {
47022
+ if (!fs18.existsSync(historyPath)) {
46123
47023
  return [];
46124
47024
  }
46125
47025
  try {
46126
- const content = fs15.readFileSync(historyPath, "utf-8");
47026
+ const content = fs18.readFileSync(historyPath, "utf-8");
46127
47027
  const lines = content.split(`
46128
47028
  `);
46129
47029
  const records = [];
@@ -46160,8 +47060,8 @@ var init_history_store = __esm(() => {
46160
47060
  });
46161
47061
 
46162
47062
  // src/tools/resolve-working-directory.ts
46163
- import * as fs16 from "fs";
46164
- import * as path33 from "path";
47063
+ import * as fs19 from "fs";
47064
+ import * as path36 from "path";
46165
47065
  function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
46166
47066
  if (workingDirectory == null || workingDirectory === "") {
46167
47067
  return { success: true, directory: fallbackDirectory };
@@ -46181,18 +47081,18 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
46181
47081
  };
46182
47082
  }
46183
47083
  }
46184
- const normalizedDir = path33.normalize(workingDirectory);
46185
- const pathParts = normalizedDir.split(path33.sep);
47084
+ const normalizedDir = path36.normalize(workingDirectory);
47085
+ const pathParts = normalizedDir.split(path36.sep);
46186
47086
  if (pathParts.includes("..")) {
46187
47087
  return {
46188
47088
  success: false,
46189
47089
  message: "Invalid working_directory: path traversal sequences (..) are not allowed"
46190
47090
  };
46191
47091
  }
46192
- const resolvedDir = path33.resolve(normalizedDir);
47092
+ const resolvedDir = path36.resolve(normalizedDir);
46193
47093
  let statResult;
46194
47094
  try {
46195
- statResult = fs16.statSync(resolvedDir);
47095
+ statResult = fs19.statSync(resolvedDir);
46196
47096
  } catch {
46197
47097
  return {
46198
47098
  success: false,
@@ -46205,17 +47105,17 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
46205
47105
  message: `Invalid working_directory: path "${resolvedDir}" is not a directory`
46206
47106
  };
46207
47107
  }
46208
- const resolvedFallback = path33.resolve(fallbackDirectory);
47108
+ const resolvedFallback = path36.resolve(fallbackDirectory);
46209
47109
  let fallbackExists = false;
46210
47110
  try {
46211
- fs16.statSync(resolvedFallback);
47111
+ fs19.statSync(resolvedFallback);
46212
47112
  fallbackExists = true;
46213
47113
  } catch {
46214
47114
  fallbackExists = false;
46215
47115
  }
46216
47116
  if (workingDirectory != null && workingDirectory !== "") {
46217
47117
  if (fallbackExists) {
46218
- const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path33.sep);
47118
+ const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path36.sep);
46219
47119
  if (isSubdirectory) {
46220
47120
  return {
46221
47121
  success: false,
@@ -46235,9 +47135,418 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
46235
47135
  }
46236
47136
  var init_resolve_working_directory = () => {};
46237
47137
 
47138
+ // src/lang/registry-backend.ts
47139
+ class LanguageBackendRegistry {
47140
+ backends = new Map;
47141
+ register(backend) {
47142
+ const existing = this.backends.get(backend.id);
47143
+ if (existing && existing !== backend) {
47144
+ throw new Error(`LanguageBackendRegistry: backend id "${backend.id}" registered twice. ` + `Each LanguageBackend.id must be unique.`);
47145
+ }
47146
+ this.backends.set(backend.id, backend);
47147
+ }
47148
+ get(id) {
47149
+ return this.backends.get(id);
47150
+ }
47151
+ getOrDefault(id) {
47152
+ const registered = this.backends.get(id);
47153
+ if (registered)
47154
+ return registered;
47155
+ const profile = LANGUAGE_REGISTRY.get(id);
47156
+ if (!profile)
47157
+ return;
47158
+ return defaultBackendFor(profile);
47159
+ }
47160
+ unregister(id) {
47161
+ this.backends.delete(id);
47162
+ }
47163
+ }
47164
+ var LANGUAGE_BACKEND_REGISTRY;
47165
+ var init_registry_backend = __esm(() => {
47166
+ init_default_backend();
47167
+ init_profiles();
47168
+ LANGUAGE_BACKEND_REGISTRY = new LanguageBackendRegistry;
47169
+ });
47170
+
47171
+ // src/lang/backends/typescript.ts
47172
+ import * as fs20 from "fs";
47173
+ import * as path37 from "path";
47174
+ function readPackageJsonRaw(dir) {
47175
+ try {
47176
+ const content = fs20.readFileSync(path37.join(dir, "package.json"), "utf-8");
47177
+ return JSON.parse(content);
47178
+ } catch {
47179
+ return null;
47180
+ }
47181
+ }
47182
+ function readPackageJson(dir) {
47183
+ return _internals21.readPackageJsonRaw(dir);
47184
+ }
47185
+ function readPackageJsonTestScript(dir) {
47186
+ return readPackageJson(dir)?.scripts?.test ?? null;
47187
+ }
47188
+ function frameworkFromScriptsTest(script) {
47189
+ if (script.includes("vitest"))
47190
+ return "vitest";
47191
+ if (script.includes("jest"))
47192
+ return "jest";
47193
+ if (script.includes("mocha"))
47194
+ return "mocha";
47195
+ if (script.includes("bun test"))
47196
+ return "bun:test";
47197
+ return null;
47198
+ }
47199
+ function frameworkFromDevDeps(devDeps) {
47200
+ if (!devDeps)
47201
+ return null;
47202
+ if (devDeps.vitest || devDeps["@vitest/ui"])
47203
+ return "vitest";
47204
+ if (devDeps.jest || devDeps["@types/jest"])
47205
+ return "jest";
47206
+ if (devDeps.mocha || devDeps["@types/mocha"])
47207
+ return "mocha";
47208
+ return null;
47209
+ }
47210
+ function selectionFromFramework(profile, fwName, dir, detectedVia) {
47211
+ const fw = profile.test.frameworks.find((f) => f.name === fwName);
47212
+ if (!fw)
47213
+ return null;
47214
+ const argv = tokenizeCommand(fw.cmd);
47215
+ if (argv.length === 0)
47216
+ return null;
47217
+ return {
47218
+ name: fw.name,
47219
+ cmd: argv,
47220
+ cwd: dir,
47221
+ detectedVia,
47222
+ filesIgnored: false
47223
+ };
47224
+ }
47225
+ async function selectTestFramework(dir) {
47226
+ const profile = LANGUAGE_REGISTRY.get(PROFILE_ID3);
47227
+ if (!profile)
47228
+ return null;
47229
+ const pkg = readPackageJson(dir);
47230
+ const script = pkg?.scripts?.test;
47231
+ if (script) {
47232
+ const fwName = frameworkFromScriptsTest(script);
47233
+ if (fwName) {
47234
+ const sel = selectionFromFramework(profile, fwName, dir, "package.json#scripts.test");
47235
+ if (sel)
47236
+ return sel;
47237
+ }
47238
+ }
47239
+ const devDepsFw = frameworkFromDevDeps(pkg?.devDependencies);
47240
+ if (devDepsFw) {
47241
+ const sel = selectionFromFramework(profile, devDepsFw, dir, "package.json#devDependencies");
47242
+ if (sel)
47243
+ return sel;
47244
+ }
47245
+ return defaultSelectTestFramework(profile, dir);
47246
+ }
47247
+ function buildTestCommand(framework, files, dir, opts) {
47248
+ const profile = LANGUAGE_REGISTRY.get(PROFILE_ID3);
47249
+ if (!profile)
47250
+ return null;
47251
+ return defaultBuildTestCommand(profile, framework, files, dir, opts);
47252
+ }
47253
+ function parseTestOutput(framework, stdout, stderr, exitCode) {
47254
+ return defaultParseTestOutput(framework, stdout, stderr, exitCode);
47255
+ }
47256
+ async function selectFramework3(dir) {
47257
+ const pkg = readPackageJson(dir);
47258
+ if (!pkg)
47259
+ return null;
47260
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
47261
+ const order = [
47262
+ ["next", "next"],
47263
+ ["nuxt", "nuxt"],
47264
+ ["@angular/core", "angular"],
47265
+ ["svelte", "svelte"],
47266
+ ["react", "react"],
47267
+ ["vue", "vue"],
47268
+ ["express", "express"],
47269
+ ["fastify", "fastify"],
47270
+ ["@nestjs/core", "nestjs"]
47271
+ ];
47272
+ for (const [pkgName, displayName] of order) {
47273
+ if (deps[pkgName]) {
47274
+ return {
47275
+ name: displayName,
47276
+ detectedVia: `package.json#dependencies.${pkgName}`
47277
+ };
47278
+ }
47279
+ }
47280
+ return null;
47281
+ }
47282
+ async function selectEntryPoints3(dir) {
47283
+ const pkg = readPackageJson(dir);
47284
+ if (!pkg)
47285
+ return [];
47286
+ const points = [];
47287
+ const obj = pkg;
47288
+ if (obj.bin) {
47289
+ if (typeof obj.bin === "string")
47290
+ points.push(obj.bin);
47291
+ else
47292
+ for (const v of Object.values(obj.bin))
47293
+ points.push(v);
47294
+ }
47295
+ if (obj.main)
47296
+ points.push(obj.main);
47297
+ if (obj.module && obj.module !== obj.main)
47298
+ points.push(obj.module);
47299
+ if (obj.exports && typeof obj.exports === "object") {
47300
+ const root = obj.exports["."];
47301
+ if (typeof root === "string" && !points.includes(root))
47302
+ points.push(root);
47303
+ }
47304
+ return [...new Set(points.filter((p) => p.length > 0))];
47305
+ }
47306
+ function extractImports4(_sourceFile, source) {
47307
+ const out = new Set;
47308
+ for (const re of [
47309
+ IMPORT_REGEX_ES2,
47310
+ IMPORT_REGEX_BARE,
47311
+ IMPORT_REGEX_REQUIRE2,
47312
+ IMPORT_REGEX_DYNAMIC,
47313
+ IMPORT_REGEX_REEXPORT2
47314
+ ]) {
47315
+ re.lastIndex = 0;
47316
+ let m = re.exec(source);
47317
+ while (m !== null) {
47318
+ out.add(m[1]);
47319
+ m = re.exec(source);
47320
+ }
47321
+ }
47322
+ return [...out];
47323
+ }
47324
+ async function selectBuildCommand(dir) {
47325
+ const profile = LANGUAGE_REGISTRY.get(PROFILE_ID3);
47326
+ if (!profile)
47327
+ return null;
47328
+ return defaultSelectBuildCommand(profile, dir);
47329
+ }
47330
+ async function testFilesFor(sourceFile, dir) {
47331
+ const profile = LANGUAGE_REGISTRY.get(PROFILE_ID3);
47332
+ if (!profile)
47333
+ return [];
47334
+ return defaultTestFilesFor(profile, sourceFile, dir);
47335
+ }
47336
+ function buildTypescriptBackend() {
47337
+ const profile = LANGUAGE_REGISTRY.get(PROFILE_ID3);
47338
+ if (!profile) {
47339
+ throw new Error("buildTypescriptBackend: typescript profile not in LANGUAGE_REGISTRY. " + "profiles.ts must be imported before this backend.");
47340
+ }
47341
+ return {
47342
+ ...profile,
47343
+ selectTestFramework,
47344
+ buildTestCommand,
47345
+ parseTestOutput,
47346
+ extractImports: extractImports4,
47347
+ selectBuildCommand,
47348
+ testFilesFor,
47349
+ selectFramework: selectFramework3,
47350
+ selectEntryPoints: selectEntryPoints3
47351
+ };
47352
+ }
47353
+ var PROFILE_ID3 = "typescript", IMPORT_REGEX_ES2, IMPORT_REGEX_BARE, IMPORT_REGEX_REQUIRE2, IMPORT_REGEX_DYNAMIC, IMPORT_REGEX_REEXPORT2, _internals21;
47354
+ var init_typescript = __esm(() => {
47355
+ init_default_backend();
47356
+ init_profiles();
47357
+ IMPORT_REGEX_ES2 = /import\s+[\s\S]*?\s+from\s+['"]([^'"]+)['"]/g;
47358
+ IMPORT_REGEX_BARE = /import\s+['"]([^'"]+)['"]/g;
47359
+ IMPORT_REGEX_REQUIRE2 = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
47360
+ IMPORT_REGEX_DYNAMIC = /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
47361
+ IMPORT_REGEX_REEXPORT2 = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
47362
+ _internals21 = {
47363
+ readPackageJsonRaw,
47364
+ readPackageJsonTestScript,
47365
+ frameworkFromScriptsTest
47366
+ };
47367
+ });
47368
+
47369
+ // src/lang/backends/index.ts
47370
+ function registerAllBackends() {
47371
+ if (registered)
47372
+ return;
47373
+ LANGUAGE_BACKEND_REGISTRY.register(buildTypescriptBackend());
47374
+ LANGUAGE_BACKEND_REGISTRY.register(buildPythonBackend());
47375
+ LANGUAGE_BACKEND_REGISTRY.register(buildGoBackend());
47376
+ registered = true;
47377
+ }
47378
+ var registered = false;
47379
+ var init_backends = __esm(() => {
47380
+ init_registry_backend();
47381
+ init_go();
47382
+ init_python();
47383
+ init_typescript();
47384
+ registerAllBackends();
47385
+ });
47386
+
47387
+ // src/lang/dispatch.ts
47388
+ var exports_dispatch = {};
47389
+ __export(exports_dispatch, {
47390
+ pickedProfiles: () => pickedProfiles,
47391
+ pickBackend: () => pickBackend,
47392
+ clearDispatchCache: () => clearDispatchCache,
47393
+ _internals: () => _internals22
47394
+ });
47395
+ import * as fs21 from "fs";
47396
+ import * as path38 from "path";
47397
+ function safeReaddirSet(dir) {
47398
+ try {
47399
+ return new Set(fs21.readdirSync(dir));
47400
+ } catch {
47401
+ return new Set;
47402
+ }
47403
+ }
47404
+ function manifestHash(dir) {
47405
+ const entries = safeReaddirSet(dir);
47406
+ if (entries.size === 0)
47407
+ return "";
47408
+ const parts = [];
47409
+ for (const name of MANIFEST_FILES) {
47410
+ if (!entries.has(name))
47411
+ continue;
47412
+ try {
47413
+ const stat3 = fs21.statSync(path38.join(dir, name));
47414
+ parts.push(`${name}:${stat3.size}:${stat3.mtimeMs}:${stat3.ino}`);
47415
+ } catch {}
47416
+ }
47417
+ return parts.join("|");
47418
+ }
47419
+ function findManifestRoot(start) {
47420
+ const resolved = path38.resolve(start);
47421
+ const cached3 = manifestRootCache.get(resolved);
47422
+ if (cached3 !== undefined)
47423
+ return cached3;
47424
+ let cur = resolved;
47425
+ for (let i = 0;i < 32; i++) {
47426
+ const entries = safeReaddirSet(cur);
47427
+ if (entries.size > 0) {
47428
+ for (const name of MANIFEST_FILES) {
47429
+ if (entries.has(name)) {
47430
+ manifestRootCache.set(resolved, cur);
47431
+ return cur;
47432
+ }
47433
+ }
47434
+ if (entries.has(".git")) {
47435
+ manifestRootCache.set(resolved, cur);
47436
+ return cur;
47437
+ }
47438
+ }
47439
+ const parent = path38.dirname(cur);
47440
+ if (parent === cur)
47441
+ break;
47442
+ cur = parent;
47443
+ }
47444
+ manifestRootCache.set(resolved, start);
47445
+ return start;
47446
+ }
47447
+ function evictIfNeeded() {
47448
+ if (cache.size <= _internals22.cacheCapacity)
47449
+ return;
47450
+ let oldestKey;
47451
+ let oldestOrder = Infinity;
47452
+ for (const [k, v] of cache.entries()) {
47453
+ if (v.insertOrder < oldestOrder) {
47454
+ oldestOrder = v.insertOrder;
47455
+ oldestKey = k;
47456
+ }
47457
+ }
47458
+ if (oldestKey !== undefined)
47459
+ cache.delete(oldestKey);
47460
+ }
47461
+ async function pickBackend(dir) {
47462
+ const root = findManifestRoot(dir);
47463
+ const hash3 = manifestHash(root);
47464
+ const cacheKey = root;
47465
+ const cached3 = cache.get(cacheKey);
47466
+ if (cached3 && cached3.hash === hash3) {
47467
+ return cached3.backend;
47468
+ }
47469
+ if (hash3 === "") {
47470
+ cache.set(cacheKey, {
47471
+ hash: hash3,
47472
+ backend: null,
47473
+ profiles: [],
47474
+ insertOrder: insertCounter++
47475
+ });
47476
+ evictIfNeeded();
47477
+ return null;
47478
+ }
47479
+ const profiles = await _internals22.detectProjectLanguages(root);
47480
+ if (profiles.length === 0) {
47481
+ cache.set(cacheKey, {
47482
+ hash: hash3,
47483
+ backend: null,
47484
+ profiles: [],
47485
+ insertOrder: insertCounter++
47486
+ });
47487
+ evictIfNeeded();
47488
+ return null;
47489
+ }
47490
+ const winner = profiles[0];
47491
+ const backend = LANGUAGE_BACKEND_REGISTRY.getOrDefault(winner.id) ?? null;
47492
+ cache.set(cacheKey, {
47493
+ hash: hash3,
47494
+ backend,
47495
+ profiles: profiles.map((p) => ({ id: p.id })),
47496
+ insertOrder: insertCounter++
47497
+ });
47498
+ evictIfNeeded();
47499
+ return backend;
47500
+ }
47501
+ function pickedProfiles(dir) {
47502
+ const root = findManifestRoot(dir);
47503
+ const cached3 = cache.get(root);
47504
+ return cached3?.profiles ?? [];
47505
+ }
47506
+ function clearDispatchCache() {
47507
+ cache.clear();
47508
+ manifestRootCache.clear();
47509
+ insertCounter = 0;
47510
+ }
47511
+ var _internals22, cache, insertCounter = 0, MANIFEST_FILES, MANIFEST_SET, manifestRootCache;
47512
+ var init_dispatch = __esm(() => {
47513
+ init_backends();
47514
+ init_detector();
47515
+ init_registry_backend();
47516
+ _internals22 = {
47517
+ detectProjectLanguages,
47518
+ cacheCapacity: 64
47519
+ };
47520
+ cache = new Map;
47521
+ MANIFEST_FILES = [
47522
+ "package.json",
47523
+ "tsconfig.json",
47524
+ "pyproject.toml",
47525
+ "setup.py",
47526
+ "setup.cfg",
47527
+ "requirements.txt",
47528
+ "Pipfile",
47529
+ "Cargo.toml",
47530
+ "go.mod",
47531
+ "pom.xml",
47532
+ "build.gradle",
47533
+ "build.gradle.kts",
47534
+ "build.zig",
47535
+ "CMakeLists.txt",
47536
+ "Makefile",
47537
+ "meson.build",
47538
+ "Package.swift",
47539
+ "pubspec.yaml",
47540
+ "Gemfile",
47541
+ "composer.json"
47542
+ ];
47543
+ MANIFEST_SET = new Set(MANIFEST_FILES);
47544
+ manifestRootCache = new Map;
47545
+ });
47546
+
46238
47547
  // src/tools/test-runner.ts
46239
- import * as fs17 from "fs";
46240
- import * as path34 from "path";
47548
+ import * as fs22 from "fs";
47549
+ import * as path39 from "path";
46241
47550
  function isAbsolutePath(str) {
46242
47551
  if (str.startsWith("/"))
46243
47552
  return true;
@@ -46302,19 +47611,19 @@ function hasDevDependency(devDeps, ...patterns) {
46302
47611
  return hasPackageJsonDependency(devDeps, ...patterns);
46303
47612
  }
46304
47613
  function detectGoTest(cwd) {
46305
- return fs17.existsSync(path34.join(cwd, "go.mod")) && isCommandAvailable("go");
47614
+ return fs22.existsSync(path39.join(cwd, "go.mod")) && isCommandAvailable("go");
46306
47615
  }
46307
47616
  function detectJavaMaven(cwd) {
46308
- return fs17.existsSync(path34.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
47617
+ return fs22.existsSync(path39.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
46309
47618
  }
46310
47619
  function detectGradle(cwd) {
46311
- const hasBuildFile = fs17.existsSync(path34.join(cwd, "build.gradle")) || fs17.existsSync(path34.join(cwd, "build.gradle.kts"));
46312
- const hasGradlew = fs17.existsSync(path34.join(cwd, "gradlew")) || fs17.existsSync(path34.join(cwd, "gradlew.bat"));
47620
+ const hasBuildFile = fs22.existsSync(path39.join(cwd, "build.gradle")) || fs22.existsSync(path39.join(cwd, "build.gradle.kts"));
47621
+ const hasGradlew = fs22.existsSync(path39.join(cwd, "gradlew")) || fs22.existsSync(path39.join(cwd, "gradlew.bat"));
46313
47622
  return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
46314
47623
  }
46315
47624
  function detectDotnetTest(cwd) {
46316
47625
  try {
46317
- const files = fs17.readdirSync(cwd);
47626
+ const files = fs22.readdirSync(cwd);
46318
47627
  const hasCsproj = files.some((f) => f.endsWith(".csproj"));
46319
47628
  return hasCsproj && isCommandAvailable("dotnet");
46320
47629
  } catch {
@@ -46322,32 +47631,89 @@ function detectDotnetTest(cwd) {
46322
47631
  }
46323
47632
  }
46324
47633
  function detectCTest(cwd) {
46325
- const hasSource = fs17.existsSync(path34.join(cwd, "CMakeLists.txt"));
46326
- const hasBuildCache = fs17.existsSync(path34.join(cwd, "CMakeCache.txt")) || fs17.existsSync(path34.join(cwd, "build", "CMakeCache.txt"));
47634
+ const hasSource = fs22.existsSync(path39.join(cwd, "CMakeLists.txt"));
47635
+ const hasBuildCache = fs22.existsSync(path39.join(cwd, "CMakeCache.txt")) || fs22.existsSync(path39.join(cwd, "build", "CMakeCache.txt"));
46327
47636
  return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
46328
47637
  }
46329
47638
  function detectSwiftTest(cwd) {
46330
- return fs17.existsSync(path34.join(cwd, "Package.swift")) && isCommandAvailable("swift");
47639
+ return fs22.existsSync(path39.join(cwd, "Package.swift")) && isCommandAvailable("swift");
46331
47640
  }
46332
47641
  function detectDartTest(cwd) {
46333
- return fs17.existsSync(path34.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
47642
+ return fs22.existsSync(path39.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
46334
47643
  }
46335
47644
  function detectRSpec(cwd) {
46336
- const hasRSpecFile = fs17.existsSync(path34.join(cwd, ".rspec"));
46337
- const hasGemfile = fs17.existsSync(path34.join(cwd, "Gemfile"));
46338
- const hasSpecDir = fs17.existsSync(path34.join(cwd, "spec"));
47645
+ const hasRSpecFile = fs22.existsSync(path39.join(cwd, ".rspec"));
47646
+ const hasGemfile = fs22.existsSync(path39.join(cwd, "Gemfile"));
47647
+ const hasSpecDir = fs22.existsSync(path39.join(cwd, "spec"));
46339
47648
  const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
46340
47649
  return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
46341
47650
  }
46342
47651
  function detectMinitest(cwd) {
46343
- return fs17.existsSync(path34.join(cwd, "test")) && (fs17.existsSync(path34.join(cwd, "Gemfile")) || fs17.existsSync(path34.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
47652
+ return fs22.existsSync(path39.join(cwd, "test")) && (fs22.existsSync(path39.join(cwd, "Gemfile")) || fs22.existsSync(path39.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
47653
+ }
47654
+ async function detectTestFrameworkViaDispatch(cwd) {
47655
+ try {
47656
+ const { pickBackend: pickBackend2 } = await Promise.resolve().then(() => (init_dispatch(), exports_dispatch));
47657
+ const backend = await pickBackend2(cwd);
47658
+ if (!backend?.selectTestFramework)
47659
+ return "none";
47660
+ const sel = await backend.selectTestFramework(cwd);
47661
+ if (!sel)
47662
+ return "none";
47663
+ return DISPATCH_FRAMEWORK_MAP[sel.name] ?? "none";
47664
+ } catch {
47665
+ return "none";
47666
+ }
47667
+ }
47668
+ async function buildTestCommandViaDispatch(framework, scope, files, coverage, baseDir) {
47669
+ if (framework === "none")
47670
+ return null;
47671
+ try {
47672
+ const { pickBackend: pickBackend2 } = await Promise.resolve().then(() => (init_dispatch(), exports_dispatch));
47673
+ const backend = await pickBackend2(baseDir);
47674
+ if (backend?.buildTestCommand) {
47675
+ const cmd = backend.buildTestCommand(framework, files, baseDir, {
47676
+ scope,
47677
+ coverage
47678
+ });
47679
+ if (cmd)
47680
+ return cmd;
47681
+ }
47682
+ return null;
47683
+ } catch {
47684
+ return null;
47685
+ }
47686
+ }
47687
+ async function parseTestOutputViaDispatch(framework, output, baseDir) {
47688
+ if (framework === "none")
47689
+ return null;
47690
+ try {
47691
+ const { pickBackend: pickBackend2 } = await Promise.resolve().then(() => (init_dispatch(), exports_dispatch));
47692
+ const backend = await pickBackend2(baseDir);
47693
+ if (!backend?.parseTestOutput)
47694
+ return null;
47695
+ const summary = backend.parseTestOutput(framework, output, "", 0);
47696
+ const passed = summary.passed ?? 0;
47697
+ const failed = summary.failed ?? 0;
47698
+ const skipped = summary.skipped ?? 0;
47699
+ const total = summary.total ?? passed + failed + skipped;
47700
+ const result = {
47701
+ totals: { passed, failed, skipped, total }
47702
+ };
47703
+ if (summary.coveragePercent !== undefined) {
47704
+ result.coveragePercent = summary.coveragePercent;
47705
+ }
47706
+ return result;
47707
+ } catch {
47708
+ return null;
47709
+ }
46344
47710
  }
46345
47711
  async function detectTestFramework(cwd) {
46346
47712
  const baseDir = cwd;
46347
47713
  try {
46348
- const packageJsonPath = path34.join(baseDir, "package.json");
46349
- if (fs17.existsSync(packageJsonPath)) {
46350
- const content = fs17.readFileSync(packageJsonPath, "utf-8");
47714
+ const packageJsonPath = path39.join(baseDir, "package.json");
47715
+ if (fs22.existsSync(packageJsonPath)) {
47716
+ const content = fs22.readFileSync(packageJsonPath, "utf-8");
46351
47717
  const pkg = JSON.parse(content);
46352
47718
  const _deps = pkg.dependencies || {};
46353
47719
  const devDeps = pkg.devDependencies || {};
@@ -46366,38 +47732,38 @@ async function detectTestFramework(cwd) {
46366
47732
  return "jest";
46367
47733
  if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
46368
47734
  return "mocha";
46369
- if (fs17.existsSync(path34.join(baseDir, "bun.lockb")) || fs17.existsSync(path34.join(baseDir, "bun.lock"))) {
47735
+ if (fs22.existsSync(path39.join(baseDir, "bun.lockb")) || fs22.existsSync(path39.join(baseDir, "bun.lock"))) {
46370
47736
  if (scripts.test?.includes("bun"))
46371
47737
  return "bun";
46372
47738
  }
46373
47739
  }
46374
47740
  } catch {}
46375
47741
  try {
46376
- const pyprojectTomlPath = path34.join(baseDir, "pyproject.toml");
46377
- const setupCfgPath = path34.join(baseDir, "setup.cfg");
46378
- const requirementsTxtPath = path34.join(baseDir, "requirements.txt");
46379
- if (fs17.existsSync(pyprojectTomlPath)) {
46380
- const content = fs17.readFileSync(pyprojectTomlPath, "utf-8");
47742
+ const pyprojectTomlPath = path39.join(baseDir, "pyproject.toml");
47743
+ const setupCfgPath = path39.join(baseDir, "setup.cfg");
47744
+ const requirementsTxtPath = path39.join(baseDir, "requirements.txt");
47745
+ if (fs22.existsSync(pyprojectTomlPath)) {
47746
+ const content = fs22.readFileSync(pyprojectTomlPath, "utf-8");
46381
47747
  if (content.includes("[tool.pytest"))
46382
47748
  return "pytest";
46383
47749
  if (content.includes("pytest"))
46384
47750
  return "pytest";
46385
47751
  }
46386
- if (fs17.existsSync(setupCfgPath)) {
46387
- const content = fs17.readFileSync(setupCfgPath, "utf-8");
47752
+ if (fs22.existsSync(setupCfgPath)) {
47753
+ const content = fs22.readFileSync(setupCfgPath, "utf-8");
46388
47754
  if (content.includes("[pytest]"))
46389
47755
  return "pytest";
46390
47756
  }
46391
- if (fs17.existsSync(requirementsTxtPath)) {
46392
- const content = fs17.readFileSync(requirementsTxtPath, "utf-8");
47757
+ if (fs22.existsSync(requirementsTxtPath)) {
47758
+ const content = fs22.readFileSync(requirementsTxtPath, "utf-8");
46393
47759
  if (content.includes("pytest"))
46394
47760
  return "pytest";
46395
47761
  }
46396
47762
  } catch {}
46397
47763
  try {
46398
- const cargoTomlPath = path34.join(baseDir, "Cargo.toml");
46399
- if (fs17.existsSync(cargoTomlPath)) {
46400
- const content = fs17.readFileSync(cargoTomlPath, "utf-8");
47764
+ const cargoTomlPath = path39.join(baseDir, "Cargo.toml");
47765
+ if (fs22.existsSync(cargoTomlPath)) {
47766
+ const content = fs22.readFileSync(cargoTomlPath, "utf-8");
46401
47767
  if (content.includes("[dev-dependencies]")) {
46402
47768
  if (content.includes("tokio") || content.includes("mockall") || content.includes("pretty_assertions")) {
46403
47769
  return "cargo";
@@ -46406,10 +47772,10 @@ async function detectTestFramework(cwd) {
46406
47772
  }
46407
47773
  } catch {}
46408
47774
  try {
46409
- const pesterConfigPath = path34.join(baseDir, "pester.config.ps1");
46410
- const pesterConfigJsonPath = path34.join(baseDir, "pester.config.ps1.json");
46411
- const pesterPs1Path = path34.join(baseDir, "tests.ps1");
46412
- if (fs17.existsSync(pesterConfigPath) || fs17.existsSync(pesterConfigJsonPath) || fs17.existsSync(pesterPs1Path)) {
47775
+ const pesterConfigPath = path39.join(baseDir, "pester.config.ps1");
47776
+ const pesterConfigJsonPath = path39.join(baseDir, "pester.config.ps1.json");
47777
+ const pesterPs1Path = path39.join(baseDir, "tests.ps1");
47778
+ if (fs22.existsSync(pesterConfigPath) || fs22.existsSync(pesterConfigJsonPath) || fs22.existsSync(pesterPs1Path)) {
46413
47779
  return "pester";
46414
47780
  }
46415
47781
  } catch {}
@@ -46437,12 +47803,12 @@ function isTestDirectoryPath(normalizedPath) {
46437
47803
  return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
46438
47804
  }
46439
47805
  function resolveWorkspacePath(file3, workingDir) {
46440
- return path34.isAbsolute(file3) ? path34.resolve(file3) : path34.resolve(workingDir, file3);
47806
+ return path39.isAbsolute(file3) ? path39.resolve(file3) : path39.resolve(workingDir, file3);
46441
47807
  }
46442
47808
  function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
46443
47809
  if (!preferRelative)
46444
47810
  return absolutePath;
46445
- return path34.relative(workingDir, absolutePath);
47811
+ return path39.relative(workingDir, absolutePath);
46446
47812
  }
46447
47813
  function dedupePush(target, value) {
46448
47814
  if (!target.includes(value)) {
@@ -46479,18 +47845,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
46479
47845
  }
46480
47846
  }
46481
47847
  function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
46482
- const relativeDir = path34.dirname(relativePath);
47848
+ const relativeDir = path39.dirname(relativePath);
46483
47849
  const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
46484
47850
  const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
46485
- const rootDir = path34.join(workingDir, dirName);
46486
- return nestedRelativeDir ? [rootDir, path34.join(rootDir, nestedRelativeDir)] : [rootDir];
47851
+ const rootDir = path39.join(workingDir, dirName);
47852
+ return nestedRelativeDir ? [rootDir, path39.join(rootDir, nestedRelativeDir)] : [rootDir];
46487
47853
  });
46488
47854
  const normalizedRelativePath = relativePath.replace(/\\/g, "/");
46489
47855
  if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
46490
- directories.push(path34.join(workingDir, "src/test/java", path34.dirname(normalizedRelativePath.slice("src/main/java/".length))));
47856
+ directories.push(path39.join(workingDir, "src/test/java", path39.dirname(normalizedRelativePath.slice("src/main/java/".length))));
46491
47857
  }
46492
47858
  if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
46493
- directories.push(path34.join(workingDir, "src/test/kotlin", path34.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
47859
+ directories.push(path39.join(workingDir, "src/test/kotlin", path39.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
46494
47860
  }
46495
47861
  return [...new Set(directories)];
46496
47862
  }
@@ -46498,19 +47864,19 @@ function hasCompoundTestExtension(filename) {
46498
47864
  const lower = filename.toLowerCase();
46499
47865
  return COMPOUND_TEST_EXTENSIONS.some((ext) => lower.endsWith(ext));
46500
47866
  }
46501
- function isLanguageSpecificTestFile(basename5) {
46502
- const lower = basename5.toLowerCase();
47867
+ function isLanguageSpecificTestFile(basename6) {
47868
+ const lower = basename6.toLowerCase();
46503
47869
  if (lower.endsWith("_test.go"))
46504
47870
  return true;
46505
47871
  if (lower.endsWith(".py") && (lower.startsWith("test_") || lower.endsWith("_test.py")))
46506
47872
  return true;
46507
47873
  if (lower.endsWith("_spec.rb"))
46508
47874
  return true;
46509
- if (lower.endsWith(".java") && (/^Test[A-Z]/.test(basename5) || basename5.endsWith("Test.java") || basename5.endsWith("Tests.java") || lower.endsWith("it.java")))
47875
+ if (lower.endsWith(".java") && (/^Test[A-Z]/.test(basename6) || basename6.endsWith("Test.java") || basename6.endsWith("Tests.java") || lower.endsWith("it.java")))
46510
47876
  return true;
46511
47877
  if (lower.endsWith(".cs") && (lower.endsWith("test.cs") || lower.endsWith("tests.cs")))
46512
47878
  return true;
46513
- if (lower.endsWith(".kt") && (/^Test[A-Z]/.test(basename5) || lower.endsWith("test.kt") || lower.endsWith("tests.kt")))
47879
+ if (lower.endsWith(".kt") && (/^Test[A-Z]/.test(basename6) || lower.endsWith("test.kt") || lower.endsWith("tests.kt")))
46514
47880
  return true;
46515
47881
  if (lower.endsWith(".tests.ps1"))
46516
47882
  return true;
@@ -46518,23 +47884,23 @@ function isLanguageSpecificTestFile(basename5) {
46518
47884
  }
46519
47885
  function isConventionTestFilePath(filePath) {
46520
47886
  const normalizedPath = filePath.replace(/\\/g, "/");
46521
- const basename5 = path34.basename(filePath);
46522
- return hasCompoundTestExtension(basename5) || basename5.includes(".spec.") || basename5.includes(".test.") || isLanguageSpecificTestFile(basename5) || isTestDirectoryPath(normalizedPath);
47887
+ const basename6 = path39.basename(filePath);
47888
+ return hasCompoundTestExtension(basename6) || basename6.includes(".spec.") || basename6.includes(".test.") || isLanguageSpecificTestFile(basename6) || isTestDirectoryPath(normalizedPath);
46523
47889
  }
46524
47890
  function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
46525
47891
  const testFiles = [];
46526
47892
  for (const file3 of sourceFiles) {
46527
47893
  const absoluteFile = resolveWorkspacePath(file3, workingDir);
46528
- const relativeFile = path34.relative(workingDir, absoluteFile);
46529
- const basename5 = path34.basename(absoluteFile);
46530
- const dirname16 = path34.dirname(absoluteFile);
46531
- const preferRelativeOutput = !path34.isAbsolute(file3);
47894
+ const relativeFile = path39.relative(workingDir, absoluteFile);
47895
+ const basename6 = path39.basename(absoluteFile);
47896
+ const dirname18 = path39.dirname(absoluteFile);
47897
+ const preferRelativeOutput = !path39.isAbsolute(file3);
46532
47898
  if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file3)) {
46533
47899
  dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
46534
47900
  continue;
46535
47901
  }
46536
- const nameWithoutExt = basename5.replace(/\.[^.]+$/, "");
46537
- const ext = path34.extname(basename5);
47902
+ const nameWithoutExt = basename6.replace(/\.[^.]+$/, "");
47903
+ const ext = path39.extname(basename6);
46538
47904
  const genericTestNames = [
46539
47905
  `${nameWithoutExt}.spec${ext}`,
46540
47906
  `${nameWithoutExt}.test${ext}`
@@ -46543,20 +47909,20 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
46543
47909
  const colocatedCandidates = [
46544
47910
  ...genericTestNames,
46545
47911
  ...languageSpecificTestNames
46546
- ].map((candidateName) => path34.join(dirname16, candidateName));
47912
+ ].map((candidateName) => path39.join(dirname18, candidateName));
46547
47913
  const testDirectoryNames = [
46548
- basename5,
47914
+ basename6,
46549
47915
  ...genericTestNames,
46550
47916
  ...languageSpecificTestNames
46551
47917
  ];
46552
47918
  const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
46553
47919
  const possibleTestFiles = [
46554
47920
  ...colocatedCandidates,
46555
- ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path34.join(dirname16, dirName, candidateName))),
46556
- ...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path34.join(candidateDir, candidateName)))
47921
+ ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path39.join(dirname18, dirName, candidateName))),
47922
+ ...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path39.join(candidateDir, candidateName)))
46557
47923
  ];
46558
47924
  for (const testFile of possibleTestFiles) {
46559
- if (fs17.existsSync(testFile)) {
47925
+ if (fs22.existsSync(testFile)) {
46560
47926
  dedupePush(testFiles, toWorkspaceOutputPath(testFile, workingDir, preferRelativeOutput));
46561
47927
  }
46562
47928
  }
@@ -46573,8 +47939,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
46573
47939
  for (const testFile of candidateTestFiles) {
46574
47940
  try {
46575
47941
  const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
46576
- const content = fs17.readFileSync(absoluteTestFile, "utf-8");
46577
- const testDir = path34.dirname(absoluteTestFile);
47942
+ const content = fs22.readFileSync(absoluteTestFile, "utf-8");
47943
+ const testDir = path39.dirname(absoluteTestFile);
46578
47944
  const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
46579
47945
  let match;
46580
47946
  match = importRegex.exec(content);
@@ -46582,8 +47948,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
46582
47948
  const importPath = match[1];
46583
47949
  let resolvedImport;
46584
47950
  if (importPath.startsWith(".")) {
46585
- resolvedImport = path34.resolve(testDir, importPath);
46586
- const existingExt = path34.extname(resolvedImport);
47951
+ resolvedImport = path39.resolve(testDir, importPath);
47952
+ const existingExt = path39.extname(resolvedImport);
46587
47953
  if (!existingExt) {
46588
47954
  for (const extToTry of [
46589
47955
  ".ts",
@@ -46594,7 +47960,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
46594
47960
  ".cjs"
46595
47961
  ]) {
46596
47962
  const withExt = resolvedImport + extToTry;
46597
- if (absoluteSourceFiles.includes(withExt) || fs17.existsSync(withExt)) {
47963
+ if (absoluteSourceFiles.includes(withExt) || fs22.existsSync(withExt)) {
46598
47964
  resolvedImport = withExt;
46599
47965
  break;
46600
47966
  }
@@ -46603,12 +47969,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
46603
47969
  } else {
46604
47970
  continue;
46605
47971
  }
46606
- const importBasename = path34.basename(resolvedImport, path34.extname(resolvedImport));
46607
- const importDir = path34.dirname(resolvedImport);
47972
+ const importBasename = path39.basename(resolvedImport, path39.extname(resolvedImport));
47973
+ const importDir = path39.dirname(resolvedImport);
46608
47974
  for (const sourceFile of absoluteSourceFiles) {
46609
- const sourceDir = path34.dirname(sourceFile);
46610
- const sourceBasename = path34.basename(sourceFile, path34.extname(sourceFile));
46611
- const isRelatedDir = importDir === sourceDir || importDir === path34.join(sourceDir, "__tests__") || importDir === path34.join(sourceDir, "tests") || importDir === path34.join(sourceDir, "test") || importDir === path34.join(sourceDir, "spec");
47975
+ const sourceDir = path39.dirname(sourceFile);
47976
+ const sourceBasename = path39.basename(sourceFile, path39.extname(sourceFile));
47977
+ const isRelatedDir = importDir === sourceDir || importDir === path39.join(sourceDir, "__tests__") || importDir === path39.join(sourceDir, "tests") || importDir === path39.join(sourceDir, "test") || importDir === path39.join(sourceDir, "spec");
46612
47978
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
46613
47979
  dedupePush(testFiles, testFile);
46614
47980
  break;
@@ -46621,8 +47987,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
46621
47987
  while (match !== null) {
46622
47988
  const importPath = match[1];
46623
47989
  if (importPath.startsWith(".")) {
46624
- let resolvedImport = path34.resolve(testDir, importPath);
46625
- const existingExt = path34.extname(resolvedImport);
47990
+ let resolvedImport = path39.resolve(testDir, importPath);
47991
+ const existingExt = path39.extname(resolvedImport);
46626
47992
  if (!existingExt) {
46627
47993
  for (const extToTry of [
46628
47994
  ".ts",
@@ -46633,18 +47999,18 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
46633
47999
  ".cjs"
46634
48000
  ]) {
46635
48001
  const withExt = resolvedImport + extToTry;
46636
- if (absoluteSourceFiles.includes(withExt) || fs17.existsSync(withExt)) {
48002
+ if (absoluteSourceFiles.includes(withExt) || fs22.existsSync(withExt)) {
46637
48003
  resolvedImport = withExt;
46638
48004
  break;
46639
48005
  }
46640
48006
  }
46641
48007
  }
46642
- const importDir = path34.dirname(resolvedImport);
46643
- const importBasename = path34.basename(resolvedImport, path34.extname(resolvedImport));
48008
+ const importDir = path39.dirname(resolvedImport);
48009
+ const importBasename = path39.basename(resolvedImport, path39.extname(resolvedImport));
46644
48010
  for (const sourceFile of absoluteSourceFiles) {
46645
- const sourceDir = path34.dirname(sourceFile);
46646
- const sourceBasename = path34.basename(sourceFile, path34.extname(sourceFile));
46647
- const isRelatedDir = importDir === sourceDir || importDir === path34.join(sourceDir, "__tests__") || importDir === path34.join(sourceDir, "tests") || importDir === path34.join(sourceDir, "test") || importDir === path34.join(sourceDir, "spec");
48011
+ const sourceDir = path39.dirname(sourceFile);
48012
+ const sourceBasename = path39.basename(sourceFile, path39.extname(sourceFile));
48013
+ const isRelatedDir = importDir === sourceDir || importDir === path39.join(sourceDir, "__tests__") || importDir === path39.join(sourceDir, "tests") || importDir === path39.join(sourceDir, "test") || importDir === path39.join(sourceDir, "spec");
46648
48014
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
46649
48015
  dedupePush(testFiles, testFile);
46650
48016
  break;
@@ -46677,7 +48043,7 @@ function getTargetedExecutionUnsupportedReason(framework) {
46677
48043
  return null;
46678
48044
  }
46679
48045
  }
46680
- function buildTestCommand(framework, scope, files, coverage, baseDir) {
48046
+ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
46681
48047
  switch (framework) {
46682
48048
  case "bun": {
46683
48049
  const args = ["bun", "test"];
@@ -46747,8 +48113,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
46747
48113
  return ["mvn", "test"];
46748
48114
  case "gradle": {
46749
48115
  const isWindows = process.platform === "win32";
46750
- const hasGradlewBat = fs17.existsSync(path34.join(baseDir, "gradlew.bat"));
46751
- const hasGradlew = fs17.existsSync(path34.join(baseDir, "gradlew"));
48116
+ const hasGradlewBat = fs22.existsSync(path39.join(baseDir, "gradlew.bat"));
48117
+ const hasGradlew = fs22.existsSync(path39.join(baseDir, "gradlew"));
46752
48118
  if (hasGradlewBat && isWindows)
46753
48119
  return ["gradlew.bat", "test"];
46754
48120
  if (hasGradlew)
@@ -46765,7 +48131,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
46765
48131
  "cmake-build-release",
46766
48132
  "out"
46767
48133
  ];
46768
- const actualBuildDir = buildDirCandidates.find((d) => fs17.existsSync(path34.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
48134
+ const actualBuildDir = buildDirCandidates.find((d) => fs22.existsSync(path39.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
46769
48135
  return ["ctest", "--test-dir", actualBuildDir];
46770
48136
  }
46771
48137
  case "swift-test":
@@ -46794,7 +48160,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
46794
48160
  return null;
46795
48161
  }
46796
48162
  }
46797
- function parseTestOutput(framework, output) {
48163
+ function parseTestOutput2(framework, output) {
46798
48164
  const totals = {
46799
48165
  passed: 0,
46800
48166
  failed: 0,
@@ -47057,7 +48423,8 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
47057
48423
  };
47058
48424
  }
47059
48425
  }
47060
- const command = buildTestCommand(framework, scope, files, coverage, cwd);
48426
+ const useDispatchBuild = process.env.SWARM_LANG_BACKEND !== "legacy";
48427
+ const command = useDispatchBuild ? await buildTestCommandViaDispatch(framework, scope, files, coverage, cwd) ?? buildTestCommand2(framework, scope, files, coverage, cwd) : buildTestCommand2(framework, scope, files, coverage, cwd);
47061
48428
  if (!command) {
47062
48429
  return {
47063
48430
  success: false,
@@ -47086,9 +48453,9 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
47086
48453
  stderr: "pipe",
47087
48454
  cwd
47088
48455
  });
47089
- const timeoutPromise = new Promise((resolve13) => setTimeout(() => {
48456
+ const timeoutPromise = new Promise((resolve14) => setTimeout(() => {
47090
48457
  proc.kill();
47091
- resolve13(-1);
48458
+ resolve14(-1);
47092
48459
  }, timeout_ms));
47093
48460
  const [exitCode, stdoutResult, stderrResult] = await Promise.all([
47094
48461
  Promise.race([proc.exited, timeoutPromise]),
@@ -47105,7 +48472,9 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
47105
48472
  output += `
47106
48473
  ... (output truncated at stream read limit)`;
47107
48474
  }
47108
- const { totals, coveragePercent } = parseTestOutput(framework, output);
48475
+ const useDispatchParse = process.env.SWARM_LANG_BACKEND !== "legacy";
48476
+ const parsed = useDispatchParse ? await parseTestOutputViaDispatch(framework, output, cwd) ?? parseTestOutput2(framework, output) : parseTestOutput2(framework, output);
48477
+ const { totals, coveragePercent } = parsed;
47109
48478
  const isTimeout = exitCode === -1;
47110
48479
  const testPassed = exitCode === 0 && totals.failed === 0;
47111
48480
  if (testPassed) {
@@ -47208,7 +48577,7 @@ function analyzeFailures(workingDir) {
47208
48577
  } catch {}
47209
48578
  return report;
47210
48579
  }
47211
- var MAX_OUTPUT_BYTES3 = 512000, MAX_COMMAND_LENGTH2 = 500, DEFAULT_TIMEOUT_MS = 60000, MAX_TIMEOUT_MS = 300000, MAX_SAFE_TEST_FILES = 50, POWERSHELL_METACHARACTERS, COMPOUND_TEST_EXTENSIONS, TEST_DIRECTORY_NAMES, SOURCE_EXTENSIONS, SKIP_DIRECTORIES, test_runner;
48580
+ var MAX_OUTPUT_BYTES3 = 512000, MAX_COMMAND_LENGTH2 = 500, DEFAULT_TIMEOUT_MS = 60000, MAX_TIMEOUT_MS = 300000, MAX_SAFE_TEST_FILES = 50, POWERSHELL_METACHARACTERS, DISPATCH_FRAMEWORK_MAP, COMPOUND_TEST_EXTENSIONS, TEST_DIRECTORY_NAMES, SOURCE_EXTENSIONS, SKIP_DIRECTORIES, test_runner;
47212
48581
  var init_test_runner = __esm(() => {
47213
48582
  init_zod();
47214
48583
  init_discovery();
@@ -47219,6 +48588,30 @@ var init_test_runner = __esm(() => {
47219
48588
  init_create_tool();
47220
48589
  init_resolve_working_directory();
47221
48590
  POWERSHELL_METACHARACTERS = /[|;&`$(){}[\]<>"'#*?\x00-\x1f]/;
48591
+ DISPATCH_FRAMEWORK_MAP = {
48592
+ "bun:test": "bun",
48593
+ bun: "bun",
48594
+ vitest: "vitest",
48595
+ jest: "jest",
48596
+ mocha: "mocha",
48597
+ pytest: "pytest",
48598
+ "cargo test": "cargo",
48599
+ cargo: "cargo",
48600
+ pester: "pester",
48601
+ "go test": "go-test",
48602
+ "maven-test": "maven",
48603
+ "gradle-test": "gradle",
48604
+ "gradle-test-groovy": "gradle",
48605
+ "gradle-kts": "gradle",
48606
+ "dotnet test": "dotnet-test",
48607
+ ctest: "ctest",
48608
+ "swift test": "swift-test",
48609
+ "xcodebuild-test": "swift-test",
48610
+ "flutter test": "dart-test",
48611
+ "dart test": "dart-test",
48612
+ rspec: "rspec",
48613
+ minitest: "minitest"
48614
+ };
47222
48615
  COMPOUND_TEST_EXTENSIONS = [
47223
48616
  ".test.ts",
47224
48617
  ".test.tsx",
@@ -47392,7 +48785,16 @@ var init_test_runner = __esm(() => {
47392
48785
  const _files = args.files || [];
47393
48786
  const coverage = args.coverage || false;
47394
48787
  const timeout_ms = Math.min(args.timeout_ms || DEFAULT_TIMEOUT_MS, MAX_TIMEOUT_MS);
47395
- const framework = await detectTestFramework(workingDir);
48788
+ const useDispatch = process.env.SWARM_LANG_BACKEND !== "legacy";
48789
+ let framework;
48790
+ if (useDispatch) {
48791
+ framework = await detectTestFrameworkViaDispatch(workingDir);
48792
+ if (framework === "none") {
48793
+ framework = await detectTestFramework(workingDir);
48794
+ }
48795
+ } else {
48796
+ framework = await detectTestFramework(workingDir);
48797
+ }
47396
48798
  if (framework === "none") {
47397
48799
  const result2 = {
47398
48800
  success: false,
@@ -47418,7 +48820,7 @@ var init_test_runner = __esm(() => {
47418
48820
  const sourceFiles = args.files.filter((file3) => {
47419
48821
  if (directTestFiles.includes(file3))
47420
48822
  return false;
47421
- const ext = path34.extname(file3).toLowerCase();
48823
+ const ext = path39.extname(file3).toLowerCase();
47422
48824
  return SOURCE_EXTENSIONS.has(ext);
47423
48825
  });
47424
48826
  const invalidFiles = args.files.filter((file3) => !directTestFiles.includes(file3) && !sourceFiles.includes(file3));
@@ -47453,7 +48855,7 @@ var init_test_runner = __esm(() => {
47453
48855
  if (isConventionTestFilePath(f)) {
47454
48856
  return false;
47455
48857
  }
47456
- const ext = path34.extname(f).toLowerCase();
48858
+ const ext = path39.extname(f).toLowerCase();
47457
48859
  return SOURCE_EXTENSIONS.has(ext);
47458
48860
  });
47459
48861
  if (sourceFiles.length === 0) {
@@ -47480,7 +48882,7 @@ var init_test_runner = __esm(() => {
47480
48882
  if (isConventionTestFilePath(f)) {
47481
48883
  return false;
47482
48884
  }
47483
- const ext = path34.extname(f).toLowerCase();
48885
+ const ext = path39.extname(f).toLowerCase();
47484
48886
  return SOURCE_EXTENSIONS.has(ext);
47485
48887
  });
47486
48888
  if (sourceFiles.length === 0) {
@@ -47498,8 +48900,8 @@ var init_test_runner = __esm(() => {
47498
48900
  const impactResult = await analyzeImpact(sourceFiles, workingDir);
47499
48901
  if (impactResult.impactedTests.length > 0) {
47500
48902
  testFiles = impactResult.impactedTests.map((absPath) => {
47501
- const relativePath = path34.relative(workingDir, absPath);
47502
- return path34.isAbsolute(relativePath) ? absPath : relativePath;
48903
+ const relativePath = path39.relative(workingDir, absPath);
48904
+ return path39.isAbsolute(relativePath) ? absPath : relativePath;
47503
48905
  });
47504
48906
  } else {
47505
48907
  graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
@@ -47574,8 +48976,8 @@ var init_test_runner = __esm(() => {
47574
48976
  });
47575
48977
 
47576
48978
  // src/services/preflight-service.ts
47577
- import * as fs18 from "fs";
47578
- import * as path35 from "path";
48979
+ import * as fs23 from "fs";
48980
+ import * as path40 from "path";
47579
48981
  function validateDirectoryPath(dir) {
47580
48982
  if (!dir || typeof dir !== "string") {
47581
48983
  throw new Error("Directory path is required");
@@ -47583,8 +48985,8 @@ function validateDirectoryPath(dir) {
47583
48985
  if (dir.includes("..")) {
47584
48986
  throw new Error("Directory path must not contain path traversal sequences");
47585
48987
  }
47586
- const normalized = path35.normalize(dir);
47587
- const absolutePath = path35.isAbsolute(normalized) ? normalized : path35.resolve(normalized);
48988
+ const normalized = path40.normalize(dir);
48989
+ const absolutePath = path40.isAbsolute(normalized) ? normalized : path40.resolve(normalized);
47588
48990
  return absolutePath;
47589
48991
  }
47590
48992
  function validateTimeout(timeoutMs, defaultValue) {
@@ -47607,9 +49009,9 @@ function validateTimeout(timeoutMs, defaultValue) {
47607
49009
  }
47608
49010
  function getPackageVersion(dir) {
47609
49011
  try {
47610
- const packagePath = path35.join(dir, "package.json");
47611
- if (fs18.existsSync(packagePath)) {
47612
- const content = fs18.readFileSync(packagePath, "utf-8");
49012
+ const packagePath = path40.join(dir, "package.json");
49013
+ if (fs23.existsSync(packagePath)) {
49014
+ const content = fs23.readFileSync(packagePath, "utf-8");
47613
49015
  const pkg = JSON.parse(content);
47614
49016
  return pkg.version ?? null;
47615
49017
  }
@@ -47618,9 +49020,9 @@ function getPackageVersion(dir) {
47618
49020
  }
47619
49021
  function getChangelogVersion(dir) {
47620
49022
  try {
47621
- const changelogPath = path35.join(dir, "CHANGELOG.md");
47622
- if (fs18.existsSync(changelogPath)) {
47623
- const content = fs18.readFileSync(changelogPath, "utf-8");
49023
+ const changelogPath = path40.join(dir, "CHANGELOG.md");
49024
+ if (fs23.existsSync(changelogPath)) {
49025
+ const content = fs23.readFileSync(changelogPath, "utf-8");
47624
49026
  const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
47625
49027
  if (match) {
47626
49028
  return match[1];
@@ -47632,10 +49034,10 @@ function getChangelogVersion(dir) {
47632
49034
  function getVersionFileVersion(dir) {
47633
49035
  const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
47634
49036
  for (const file3 of possibleFiles) {
47635
- const filePath = path35.join(dir, file3);
47636
- if (fs18.existsSync(filePath)) {
49037
+ const filePath = path40.join(dir, file3);
49038
+ if (fs23.existsSync(filePath)) {
47637
49039
  try {
47638
- const content = fs18.readFileSync(filePath, "utf-8").trim();
49040
+ const content = fs23.readFileSync(filePath, "utf-8").trim();
47639
49041
  const match = content.match(/(\d+\.\d+\.\d+)/);
47640
49042
  if (match) {
47641
49043
  return match[1];
@@ -47648,9 +49050,9 @@ function getVersionFileVersion(dir) {
47648
49050
  async function runVersionCheck(dir, _timeoutMs) {
47649
49051
  const startTime = Date.now();
47650
49052
  try {
47651
- const packageVersion = _internals19.getPackageVersion(dir);
47652
- const changelogVersion = _internals19.getChangelogVersion(dir);
47653
- const versionFileVersion = _internals19.getVersionFileVersion(dir);
49053
+ const packageVersion = _internals23.getPackageVersion(dir);
49054
+ const changelogVersion = _internals23.getChangelogVersion(dir);
49055
+ const versionFileVersion = _internals23.getVersionFileVersion(dir);
47654
49056
  const versions3 = [];
47655
49057
  if (packageVersion)
47656
49058
  versions3.push(`package.json: ${packageVersion}`);
@@ -47959,8 +49361,8 @@ async function runEvidenceCheck(dir) {
47959
49361
  async function runRequirementCoverageCheck(dir, currentPhase) {
47960
49362
  const startTime = Date.now();
47961
49363
  try {
47962
- const specPath = path35.join(dir, ".swarm", "spec.md");
47963
- if (!fs18.existsSync(specPath)) {
49364
+ const specPath = path40.join(dir, ".swarm", "spec.md");
49365
+ if (!fs23.existsSync(specPath)) {
47964
49366
  return {
47965
49367
  type: "req_coverage",
47966
49368
  status: "skip",
@@ -48000,7 +49402,7 @@ async function runPreflight(dir, phase, config3) {
48000
49402
  const reportId = `preflight-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
48001
49403
  let validatedDir;
48002
49404
  try {
48003
- validatedDir = _internals19.validateDirectoryPath(dir);
49405
+ validatedDir = _internals23.validateDirectoryPath(dir);
48004
49406
  } catch (error93) {
48005
49407
  return {
48006
49408
  id: reportId,
@@ -48020,7 +49422,7 @@ async function runPreflight(dir, phase, config3) {
48020
49422
  }
48021
49423
  let validatedTimeout;
48022
49424
  try {
48023
- validatedTimeout = _internals19.validateTimeout(config3?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
49425
+ validatedTimeout = _internals23.validateTimeout(config3?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
48024
49426
  } catch (error93) {
48025
49427
  return {
48026
49428
  id: reportId,
@@ -48061,12 +49463,12 @@ async function runPreflight(dir, phase, config3) {
48061
49463
  });
48062
49464
  const checks5 = [];
48063
49465
  log("[Preflight] Running lint check...");
48064
- const lintResult = await _internals19.runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
49466
+ const lintResult = await _internals23.runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
48065
49467
  checks5.push(lintResult);
48066
49468
  log(`[Preflight] Lint check: ${lintResult.status} ${lintResult.message}`);
48067
49469
  if (!cfg.skipTests) {
48068
49470
  log("[Preflight] Running tests check...");
48069
- const testsResult = await _internals19.runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
49471
+ const testsResult = await _internals23.runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
48070
49472
  checks5.push(testsResult);
48071
49473
  log(`[Preflight] Tests check: ${testsResult.status} ${testsResult.message}`);
48072
49474
  } else {
@@ -48078,7 +49480,7 @@ async function runPreflight(dir, phase, config3) {
48078
49480
  }
48079
49481
  if (!cfg.skipSecrets) {
48080
49482
  log("[Preflight] Running secrets check...");
48081
- const secretsResult = await _internals19.runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
49483
+ const secretsResult = await _internals23.runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
48082
49484
  checks5.push(secretsResult);
48083
49485
  log(`[Preflight] Secrets check: ${secretsResult.status} ${secretsResult.message}`);
48084
49486
  } else {
@@ -48090,7 +49492,7 @@ async function runPreflight(dir, phase, config3) {
48090
49492
  }
48091
49493
  if (!cfg.skipEvidence) {
48092
49494
  log("[Preflight] Running evidence check...");
48093
- const evidenceResult = await _internals19.runEvidenceCheck(validatedDir);
49495
+ const evidenceResult = await _internals23.runEvidenceCheck(validatedDir);
48094
49496
  checks5.push(evidenceResult);
48095
49497
  log(`[Preflight] Evidence check: ${evidenceResult.status} ${evidenceResult.message}`);
48096
49498
  } else {
@@ -48101,12 +49503,12 @@ async function runPreflight(dir, phase, config3) {
48101
49503
  });
48102
49504
  }
48103
49505
  log("[Preflight] Running requirement coverage check...");
48104
- const reqCoverageResult = await _internals19.runRequirementCoverageCheck(validatedDir, phase);
49506
+ const reqCoverageResult = await _internals23.runRequirementCoverageCheck(validatedDir, phase);
48105
49507
  checks5.push(reqCoverageResult);
48106
49508
  log(`[Preflight] Requirement coverage check: ${reqCoverageResult.status} ${reqCoverageResult.message}`);
48107
49509
  if (!cfg.skipVersion) {
48108
49510
  log("[Preflight] Running version check...");
48109
- const versionResult = await _internals19.runVersionCheck(validatedDir, cfg.checkTimeoutMs);
49511
+ const versionResult = await _internals23.runVersionCheck(validatedDir, cfg.checkTimeoutMs);
48110
49512
  checks5.push(versionResult);
48111
49513
  log(`[Preflight] Version check: ${versionResult.status} ${versionResult.message}`);
48112
49514
  } else {
@@ -48169,10 +49571,10 @@ function formatPreflightMarkdown(report) {
48169
49571
  async function handlePreflightCommand(directory, _args) {
48170
49572
  const plan = await loadPlan(directory);
48171
49573
  const phase = plan?.current_phase ?? 1;
48172
- const report = await _internals19.runPreflight(directory, phase);
48173
- return _internals19.formatPreflightMarkdown(report);
49574
+ const report = await _internals23.runPreflight(directory, phase);
49575
+ return _internals23.formatPreflightMarkdown(report);
48174
49576
  }
48175
- var MIN_CHECK_TIMEOUT_MS = 5000, MAX_CHECK_TIMEOUT_MS = 300000, DEFAULT_CONFIG, _internals19;
49577
+ var MIN_CHECK_TIMEOUT_MS = 5000, MAX_CHECK_TIMEOUT_MS = 300000, DEFAULT_CONFIG, _internals23;
48176
49578
  var init_preflight_service = __esm(() => {
48177
49579
  init_manager2();
48178
49580
  init_manager();
@@ -48189,7 +49591,7 @@ var init_preflight_service = __esm(() => {
48189
49591
  testScope: "convention",
48190
49592
  linter: "biome"
48191
49593
  };
48192
- _internals19 = {
49594
+ _internals23 = {
48193
49595
  runPreflight,
48194
49596
  formatPreflightMarkdown,
48195
49597
  handlePreflightCommand,
@@ -48437,13 +49839,13 @@ class CircuitBreaker {
48437
49839
  if (this.config.callTimeoutMs <= 0) {
48438
49840
  return fn();
48439
49841
  }
48440
- return new Promise((resolve14, reject) => {
49842
+ return new Promise((resolve15, reject) => {
48441
49843
  const timeout = setTimeout(() => {
48442
49844
  reject(new Error(`Call timeout after ${this.config.callTimeoutMs}ms`));
48443
49845
  }, this.config.callTimeoutMs);
48444
49846
  fn().then((result) => {
48445
49847
  clearTimeout(timeout);
48446
- resolve14(result);
49848
+ resolve15(result);
48447
49849
  }).catch((error93) => {
48448
49850
  clearTimeout(timeout);
48449
49851
  reject(error93);
@@ -48730,7 +50132,7 @@ var init_queue = __esm(() => {
48730
50132
 
48731
50133
  // src/background/worker.ts
48732
50134
  function sleep(ms) {
48733
- return new Promise((resolve14) => setTimeout(resolve14, ms));
50135
+ return new Promise((resolve15) => setTimeout(resolve15, ms));
48734
50136
  }
48735
50137
 
48736
50138
  class WorkerManager {
@@ -49075,8 +50477,8 @@ var init_manager3 = __esm(() => {
49075
50477
  });
49076
50478
 
49077
50479
  // src/commands/reset.ts
49078
- import * as fs19 from "fs";
49079
- import * as path36 from "path";
50480
+ import * as fs24 from "fs";
50481
+ import * as path41 from "path";
49080
50482
  async function handleResetCommand(directory, args) {
49081
50483
  const hasConfirm = args.includes("--confirm");
49082
50484
  if (!hasConfirm) {
@@ -49104,8 +50506,8 @@ async function handleResetCommand(directory, args) {
49104
50506
  for (const filename of filesToReset) {
49105
50507
  try {
49106
50508
  const resolvedPath = validateSwarmPath(directory, filename);
49107
- if (fs19.existsSync(resolvedPath)) {
49108
- fs19.unlinkSync(resolvedPath);
50509
+ if (fs24.existsSync(resolvedPath)) {
50510
+ fs24.unlinkSync(resolvedPath);
49109
50511
  results.push(`- \u2705 Deleted ${filename}`);
49110
50512
  } else {
49111
50513
  results.push(`- \u23ED\uFE0F ${filename} not found (skipped)`);
@@ -49116,9 +50518,9 @@ async function handleResetCommand(directory, args) {
49116
50518
  }
49117
50519
  for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
49118
50520
  try {
49119
- const rootPath = path36.join(directory, filename);
49120
- if (fs19.existsSync(rootPath)) {
49121
- fs19.unlinkSync(rootPath);
50521
+ const rootPath = path41.join(directory, filename);
50522
+ if (fs24.existsSync(rootPath)) {
50523
+ fs24.unlinkSync(rootPath);
49122
50524
  results.push(`- \u2705 Deleted ${filename} (root)`);
49123
50525
  }
49124
50526
  } catch {}
@@ -49131,8 +50533,8 @@ async function handleResetCommand(directory, args) {
49131
50533
  }
49132
50534
  try {
49133
50535
  const summariesPath = validateSwarmPath(directory, "summaries");
49134
- if (fs19.existsSync(summariesPath)) {
49135
- fs19.rmSync(summariesPath, { recursive: true, force: true });
50536
+ if (fs24.existsSync(summariesPath)) {
50537
+ fs24.rmSync(summariesPath, { recursive: true, force: true });
49136
50538
  results.push("- \u2705 Deleted summaries/ directory");
49137
50539
  } else {
49138
50540
  results.push("- \u23ED\uFE0F summaries/ not found (skipped)");
@@ -49155,14 +50557,14 @@ var init_reset = __esm(() => {
49155
50557
  });
49156
50558
 
49157
50559
  // src/commands/reset-session.ts
49158
- import * as fs20 from "fs";
49159
- import * as path37 from "path";
50560
+ import * as fs25 from "fs";
50561
+ import * as path42 from "path";
49160
50562
  async function handleResetSessionCommand(directory, _args) {
49161
50563
  const results = [];
49162
50564
  try {
49163
50565
  const statePath = validateSwarmPath(directory, "session/state.json");
49164
- if (fs20.existsSync(statePath)) {
49165
- fs20.unlinkSync(statePath);
50566
+ if (fs25.existsSync(statePath)) {
50567
+ fs25.unlinkSync(statePath);
49166
50568
  results.push("\u2705 Deleted .swarm/session/state.json");
49167
50569
  } else {
49168
50570
  results.push("\u23ED\uFE0F state.json not found (already clean)");
@@ -49171,15 +50573,15 @@ async function handleResetSessionCommand(directory, _args) {
49171
50573
  results.push("\u274C Failed to delete state.json");
49172
50574
  }
49173
50575
  try {
49174
- const sessionDir = path37.dirname(validateSwarmPath(directory, "session/state.json"));
49175
- if (fs20.existsSync(sessionDir)) {
49176
- const files = fs20.readdirSync(sessionDir);
50576
+ const sessionDir = path42.dirname(validateSwarmPath(directory, "session/state.json"));
50577
+ if (fs25.existsSync(sessionDir)) {
50578
+ const files = fs25.readdirSync(sessionDir);
49177
50579
  const otherFiles = files.filter((f) => f !== "state.json");
49178
50580
  let deletedCount = 0;
49179
50581
  for (const file3 of otherFiles) {
49180
- const filePath = path37.join(sessionDir, file3);
49181
- if (fs20.lstatSync(filePath).isFile()) {
49182
- fs20.unlinkSync(filePath);
50582
+ const filePath = path42.join(sessionDir, file3);
50583
+ if (fs25.lstatSync(filePath).isFile()) {
50584
+ fs25.unlinkSync(filePath);
49183
50585
  deletedCount++;
49184
50586
  }
49185
50587
  }
@@ -49209,7 +50611,7 @@ var init_reset_session = __esm(() => {
49209
50611
  });
49210
50612
 
49211
50613
  // src/summaries/manager.ts
49212
- import * as path38 from "path";
50614
+ import * as path43 from "path";
49213
50615
  function sanitizeSummaryId(id) {
49214
50616
  if (!id || id.length === 0) {
49215
50617
  throw new Error("Invalid summary ID: empty string");
@@ -49232,7 +50634,7 @@ function sanitizeSummaryId(id) {
49232
50634
  }
49233
50635
  async function loadFullOutput(directory, id) {
49234
50636
  const sanitizedId = sanitizeSummaryId(id);
49235
- const relativePath = path38.join("summaries", `${sanitizedId}.json`);
50637
+ const relativePath = path43.join("summaries", `${sanitizedId}.json`);
49236
50638
  validateSwarmPath(directory, relativePath);
49237
50639
  const content = await readSwarmFileAsync(directory, relativePath);
49238
50640
  if (content === null) {
@@ -49294,18 +50696,18 @@ var init_retrieve = __esm(() => {
49294
50696
  });
49295
50697
 
49296
50698
  // src/commands/rollback.ts
49297
- import * as fs21 from "fs";
49298
- import * as path39 from "path";
50699
+ import * as fs26 from "fs";
50700
+ import * as path44 from "path";
49299
50701
  async function handleRollbackCommand(directory, args) {
49300
50702
  const phaseArg = args[0];
49301
50703
  if (!phaseArg) {
49302
50704
  const manifestPath2 = validateSwarmPath(directory, "checkpoints/manifest.json");
49303
- if (!fs21.existsSync(manifestPath2)) {
50705
+ if (!fs26.existsSync(manifestPath2)) {
49304
50706
  return "No checkpoints found. Use `/swarm checkpoint` to create checkpoints.";
49305
50707
  }
49306
50708
  let manifest2;
49307
50709
  try {
49308
- manifest2 = JSON.parse(fs21.readFileSync(manifestPath2, "utf-8"));
50710
+ manifest2 = JSON.parse(fs26.readFileSync(manifestPath2, "utf-8"));
49309
50711
  } catch {
49310
50712
  return "Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.";
49311
50713
  }
@@ -49327,12 +50729,12 @@ async function handleRollbackCommand(directory, args) {
49327
50729
  return "Error: Phase number must be a positive integer.";
49328
50730
  }
49329
50731
  const manifestPath = validateSwarmPath(directory, "checkpoints/manifest.json");
49330
- if (!fs21.existsSync(manifestPath)) {
50732
+ if (!fs26.existsSync(manifestPath)) {
49331
50733
  return `Error: No checkpoints found. Cannot rollback to phase ${targetPhase}.`;
49332
50734
  }
49333
50735
  let manifest;
49334
50736
  try {
49335
- manifest = JSON.parse(fs21.readFileSync(manifestPath, "utf-8"));
50737
+ manifest = JSON.parse(fs26.readFileSync(manifestPath, "utf-8"));
49336
50738
  } catch {
49337
50739
  return `Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.`;
49338
50740
  }
@@ -49342,10 +50744,10 @@ async function handleRollbackCommand(directory, args) {
49342
50744
  return `Error: Checkpoint for phase ${targetPhase} not found. Available phases: ${available}`;
49343
50745
  }
49344
50746
  const checkpointDir = validateSwarmPath(directory, `checkpoints/phase-${targetPhase}`);
49345
- if (!fs21.existsSync(checkpointDir)) {
50747
+ if (!fs26.existsSync(checkpointDir)) {
49346
50748
  return `Error: Checkpoint directory for phase ${targetPhase} does not exist.`;
49347
50749
  }
49348
- const checkpointFiles = fs21.readdirSync(checkpointDir);
50750
+ const checkpointFiles = fs26.readdirSync(checkpointDir);
49349
50751
  if (checkpointFiles.length === 0) {
49350
50752
  return `Error: Checkpoint for phase ${targetPhase} is empty. Cannot rollback.`;
49351
50753
  }
@@ -49360,10 +50762,10 @@ async function handleRollbackCommand(directory, args) {
49360
50762
  if (EXCLUDE_FILES.has(file3) || file3.startsWith("plan-ledger.archived-")) {
49361
50763
  continue;
49362
50764
  }
49363
- const src = path39.join(checkpointDir, file3);
49364
- const dest = path39.join(swarmDir, file3);
50765
+ const src = path44.join(checkpointDir, file3);
50766
+ const dest = path44.join(swarmDir, file3);
49365
50767
  try {
49366
- fs21.cpSync(src, dest, { recursive: true, force: true });
50768
+ fs26.cpSync(src, dest, { recursive: true, force: true });
49367
50769
  successes.push(file3);
49368
50770
  } catch (error93) {
49369
50771
  failures.push({ file: file3, error: error93.message });
@@ -49380,14 +50782,14 @@ async function handleRollbackCommand(directory, args) {
49380
50782
  ].join(`
49381
50783
  `);
49382
50784
  }
49383
- const existingLedgerPath = path39.join(swarmDir, "plan-ledger.jsonl");
49384
- if (fs21.existsSync(existingLedgerPath)) {
49385
- fs21.unlinkSync(existingLedgerPath);
50785
+ const existingLedgerPath = path44.join(swarmDir, "plan-ledger.jsonl");
50786
+ if (fs26.existsSync(existingLedgerPath)) {
50787
+ fs26.unlinkSync(existingLedgerPath);
49386
50788
  }
49387
50789
  try {
49388
- const planJsonPath = path39.join(swarmDir, "plan.json");
49389
- if (fs21.existsSync(planJsonPath)) {
49390
- const planRaw = fs21.readFileSync(planJsonPath, "utf-8");
50790
+ const planJsonPath = path44.join(swarmDir, "plan.json");
50791
+ if (fs26.existsSync(planJsonPath)) {
50792
+ const planRaw = fs26.readFileSync(planJsonPath, "utf-8");
49391
50793
  const plan = PlanSchema.parse(JSON.parse(planRaw));
49392
50794
  const planId = derivePlanId(plan);
49393
50795
  const planHash = computePlanHash(plan);
@@ -49414,7 +50816,7 @@ async function handleRollbackCommand(directory, args) {
49414
50816
  timestamp: new Date().toISOString()
49415
50817
  };
49416
50818
  try {
49417
- fs21.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
50819
+ fs26.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
49418
50820
  `);
49419
50821
  } catch (error93) {
49420
50822
  console.error("Failed to write rollback event:", error93 instanceof Error ? error93.message : String(error93));
@@ -49475,11 +50877,11 @@ Ensure this is a git repository with commit history.`;
49475
50877
  const report = reportLines.filter(Boolean).join(`
49476
50878
  `);
49477
50879
  try {
49478
- const fs22 = await import("fs/promises");
49479
- const path40 = await import("path");
49480
- const reportPath = path40.join(directory, ".swarm", "simulate-report.md");
49481
- await fs22.mkdir(path40.dirname(reportPath), { recursive: true });
49482
- await fs22.writeFile(reportPath, report, "utf-8");
50880
+ const fs27 = await import("fs/promises");
50881
+ const path45 = await import("path");
50882
+ const reportPath = path45.join(directory, ".swarm", "simulate-report.md");
50883
+ await fs27.mkdir(path45.dirname(reportPath), { recursive: true });
50884
+ await fs27.writeFile(reportPath, report, "utf-8");
49483
50885
  } catch (err) {
49484
50886
  const writeErr = err instanceof Error ? err.message : String(err);
49485
50887
  warn(`simulate: failed to write report to ${directory}/.swarm/simulate-report.md`, writeErr);
@@ -49501,15 +50903,15 @@ async function handleSpecifyCommand(_directory, args) {
49501
50903
  }
49502
50904
 
49503
50905
  // src/turbo/lean/state.ts
49504
- import * as fs22 from "fs";
49505
- import * as path40 from "path";
50906
+ import * as fs27 from "fs";
50907
+ import * as path45 from "path";
49506
50908
  function nowISO2() {
49507
50909
  return new Date().toISOString();
49508
50910
  }
49509
50911
  function ensureSwarmDir2(directory) {
49510
- const swarmDir = path40.resolve(directory, ".swarm");
49511
- if (!fs22.existsSync(swarmDir)) {
49512
- fs22.mkdirSync(swarmDir, { recursive: true });
50912
+ const swarmDir = path45.resolve(directory, ".swarm");
50913
+ if (!fs27.existsSync(swarmDir)) {
50914
+ fs27.mkdirSync(swarmDir, { recursive: true });
49513
50915
  }
49514
50916
  return swarmDir;
49515
50917
  }
@@ -49551,17 +50953,17 @@ function markStateUnreadable2(directory, reason) {
49551
50953
  }
49552
50954
  function readPersisted2(directory) {
49553
50955
  try {
49554
- const filePath = path40.join(directory, ".swarm", STATE_FILE2);
49555
- if (!fs22.existsSync(filePath)) {
50956
+ const filePath = path45.join(directory, ".swarm", STATE_FILE2);
50957
+ if (!fs27.existsSync(filePath)) {
49556
50958
  const seed = emptyPersisted2();
49557
50959
  try {
49558
50960
  ensureSwarmDir2(directory);
49559
- fs22.writeFileSync(filePath, `${JSON.stringify(seed, null, 2)}
50961
+ fs27.writeFileSync(filePath, `${JSON.stringify(seed, null, 2)}
49560
50962
  `, "utf-8");
49561
50963
  } catch {}
49562
50964
  return seed;
49563
50965
  }
49564
- const raw = fs22.readFileSync(filePath, "utf-8");
50966
+ const raw = fs27.readFileSync(filePath, "utf-8");
49565
50967
  const parsed = JSON.parse(raw);
49566
50968
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed) || parsed.version !== 1 || !parsed.sessions || typeof parsed.sessions !== "object" || Array.isArray(parsed.sessions)) {
49567
50969
  markStateUnreadable2(directory, `malformed shape (version=${parsed?.version}, sessions type=${Array.isArray(parsed?.sessions) ? "array" : typeof parsed?.sessions})`);
@@ -49587,7 +50989,7 @@ function writePersisted2(directory, persisted) {
49587
50989
  let payload;
49588
50990
  try {
49589
50991
  ensureSwarmDir2(directory);
49590
- filePath = path40.join(directory, ".swarm", STATE_FILE2);
50992
+ filePath = path45.join(directory, ".swarm", STATE_FILE2);
49591
50993
  tmpPath = `${filePath}.tmp.${Date.now()}`;
49592
50994
  persisted.updatedAt = nowISO2();
49593
50995
  payload = `${JSON.stringify(persisted, null, 2)}
@@ -49598,14 +51000,14 @@ function writePersisted2(directory, persisted) {
49598
51000
  throw new Error(`Lean Turbo state persistence prepare failed: ${msg}`);
49599
51001
  }
49600
51002
  try {
49601
- fs22.writeFileSync(tmpPath, payload, "utf-8");
49602
- fs22.renameSync(tmpPath, filePath);
51003
+ fs27.writeFileSync(tmpPath, payload, "utf-8");
51004
+ fs27.renameSync(tmpPath, filePath);
49603
51005
  } catch (error93) {
49604
51006
  const msg = error93 instanceof Error ? error93.message : String(error93);
49605
51007
  error(`[turbo/lean/state] Failed to persist ${STATE_FILE2} atomically: ${msg}`);
49606
51008
  try {
49607
- if (fs22.existsSync(tmpPath)) {
49608
- fs22.unlinkSync(tmpPath);
51009
+ if (fs27.existsSync(tmpPath)) {
51010
+ fs27.unlinkSync(tmpPath);
49609
51011
  }
49610
51012
  } catch {}
49611
51013
  throw new Error(`Lean Turbo state persistence failed: ${msg}`);
@@ -49782,7 +51184,7 @@ async function getStatusData(directory, agents) {
49782
51184
  }
49783
51185
  function enrichWithLeanTurbo(status, directory) {
49784
51186
  const turboMode = hasActiveTurboMode();
49785
- const leanActive = _internals20.hasActiveLeanTurbo();
51187
+ const leanActive = _internals24.hasActiveLeanTurbo();
49786
51188
  let turboStrategy = "off";
49787
51189
  if (leanActive) {
49788
51190
  turboStrategy = "lean";
@@ -49801,7 +51203,7 @@ function enrichWithLeanTurbo(status, directory) {
49801
51203
  }
49802
51204
  }
49803
51205
  if (leanSessionID) {
49804
- const runState = _internals20.loadLeanTurboRunState(directory, leanSessionID);
51206
+ const runState = _internals24.loadLeanTurboRunState(directory, leanSessionID);
49805
51207
  if (runState) {
49806
51208
  status.leanTurboPhase = runState.phase;
49807
51209
  status.leanMaxParallelCoders = runState.maxParallelCoders;
@@ -49833,7 +51235,7 @@ function enrichWithLeanTurbo(status, directory) {
49833
51235
  }
49834
51236
  }
49835
51237
  }
49836
- status.fullAutoActive = _internals20.hasActiveFullAuto();
51238
+ status.fullAutoActive = _internals24.hasActiveFullAuto();
49837
51239
  return status;
49838
51240
  }
49839
51241
  function formatStatusMarkdown(status) {
@@ -49897,7 +51299,7 @@ async function handleStatusCommand(directory, agents) {
49897
51299
  }
49898
51300
  return formatStatusMarkdown(statusData);
49899
51301
  }
49900
- var _internals20;
51302
+ var _internals24;
49901
51303
  var init_status_service = __esm(() => {
49902
51304
  init_extractors();
49903
51305
  init_utils2();
@@ -49906,7 +51308,7 @@ var init_status_service = __esm(() => {
49906
51308
  init_state3();
49907
51309
  init_compaction_service();
49908
51310
  init_context_budget_service();
49909
- _internals20 = {
51311
+ _internals24 = {
49910
51312
  loadLeanTurboRunState,
49911
51313
  hasActiveLeanTurbo,
49912
51314
  hasActiveFullAuto
@@ -50250,8 +51652,8 @@ __export(exports_commands, {
50250
51652
  COMMAND_NAME_SET: () => COMMAND_NAME_SET,
50251
51653
  COMMAND_NAMES: () => COMMAND_NAMES
50252
51654
  });
50253
- import fs23 from "fs";
50254
- import path41 from "path";
51655
+ import fs28 from "fs";
51656
+ import path46 from "path";
50255
51657
  function buildHelpText() {
50256
51658
  const lines = ["## Swarm Commands", ""];
50257
51659
  const CATEGORIES = [
@@ -50354,11 +51756,11 @@ function createSwarmCommandHandler(directory, agents) {
50354
51756
  return;
50355
51757
  }
50356
51758
  let isFirstRun = false;
50357
- const sentinelPath = path41.join(directory, ".swarm", ".first-run-complete");
51759
+ const sentinelPath = path46.join(directory, ".swarm", ".first-run-complete");
50358
51760
  try {
50359
- const swarmDir = path41.join(directory, ".swarm");
50360
- fs23.mkdirSync(swarmDir, { recursive: true });
50361
- fs23.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
51761
+ const swarmDir = path46.join(directory, ".swarm");
51762
+ fs28.mkdirSync(swarmDir, { recursive: true });
51763
+ fs28.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
50362
51764
  `, { flag: "wx" });
50363
51765
  isFirstRun = true;
50364
51766
  } catch (_err) {}
@@ -50379,7 +51781,7 @@ function createSwarmCommandHandler(directory, agents) {
50379
51781
  const attemptedCommand = tokens[0] || "";
50380
51782
  const MAX_DISPLAY = 100;
50381
51783
  const displayCommand = attemptedCommand.length > MAX_DISPLAY ? `${attemptedCommand.slice(0, MAX_DISPLAY)}...` : attemptedCommand;
50382
- const similar = _internals21.findSimilarCommands(attemptedCommand);
51784
+ const similar = _internals25.findSimilarCommands(attemptedCommand);
50383
51785
  const header = `Command \`/swarm ${displayCommand}\` not found.`;
50384
51786
  const suggestions = similar.length > 0 ? `Did you mean:
50385
51787
  ${similar.map((cmd) => ` \u2022 /swarm ${cmd}`).join(`
@@ -50486,7 +51888,7 @@ function findSimilarCommands(query) {
50486
51888
  }
50487
51889
  const scored = VALID_COMMANDS.map((cmd) => {
50488
51890
  const cmdLower = cmd.toLowerCase();
50489
- const fullScore = _internals21.levenshteinDistance(q, cmdLower);
51891
+ const fullScore = _internals25.levenshteinDistance(q, cmdLower);
50490
51892
  let tokenScore = Infinity;
50491
51893
  if (cmd.includes(" ") || cmd.includes("-")) {
50492
51894
  const qTokens = q.split(/[\s-]+/);
@@ -50499,7 +51901,7 @@ function findSimilarCommands(query) {
50499
51901
  for (const ct of cmdTokens) {
50500
51902
  if (ct.length === 0)
50501
51903
  continue;
50502
- const dist = _internals21.levenshteinDistance(qt, ct);
51904
+ const dist = _internals25.levenshteinDistance(qt, ct);
50503
51905
  if (dist < minDist)
50504
51906
  minDist = dist;
50505
51907
  }
@@ -50509,7 +51911,7 @@ function findSimilarCommands(query) {
50509
51911
  }
50510
51912
  const dashStrippedQ = q.replace(/-/g, "");
50511
51913
  const dashStrippedCmd = cmdLower.replace(/-/g, "");
50512
- const dashScore = _internals21.levenshteinDistance(dashStrippedQ, dashStrippedCmd);
51914
+ const dashScore = _internals25.levenshteinDistance(dashStrippedQ, dashStrippedCmd);
50513
51915
  const score = Math.min(fullScore, tokenScore, dashScore);
50514
51916
  return { cmd, score };
50515
51917
  });
@@ -50541,11 +51943,11 @@ async function handleHelpCommand(ctx) {
50541
51943
  return buildHelpText2();
50542
51944
  }
50543
51945
  const tokens = targetCommand.split(/\s+/);
50544
- const resolved = _internals21.resolveCommand(tokens);
51946
+ const resolved = _internals25.resolveCommand(tokens);
50545
51947
  if (resolved) {
50546
- return _internals21.buildDetailedHelp(resolved.key, resolved.entry);
51948
+ return _internals25.buildDetailedHelp(resolved.key, resolved.entry);
50547
51949
  }
50548
- const similar = _internals21.findSimilarCommands(targetCommand);
51950
+ const similar = _internals25.findSimilarCommands(targetCommand);
50549
51951
  const { buildHelpText: fullHelp } = await Promise.resolve().then(() => (init_commands(), exports_commands));
50550
51952
  if (similar.length > 0) {
50551
51953
  return `Command '/swarm ${targetCommand}' not found.
@@ -50581,24 +51983,24 @@ function validateAliases() {
50581
51983
  }
50582
51984
  aliasTargets.get(target).push(name);
50583
51985
  const visited = new Set;
50584
- const path42 = [];
51986
+ const path47 = [];
50585
51987
  let current = target;
50586
51988
  while (current) {
50587
51989
  const currentEntry = COMMAND_REGISTRY[current];
50588
51990
  if (!currentEntry)
50589
51991
  break;
50590
51992
  if (visited.has(current)) {
50591
- const cycleStart = path42.indexOf(current);
51993
+ const cycleStart = path47.indexOf(current);
50592
51994
  const fullChain = [
50593
51995
  name,
50594
- ...path42.slice(0, cycleStart > 0 ? cycleStart : path42.length),
51996
+ ...path47.slice(0, cycleStart > 0 ? cycleStart : path47.length),
50595
51997
  current
50596
51998
  ].join(" \u2192 ");
50597
51999
  errors5.push(`Circular alias detected: ${fullChain}`);
50598
52000
  break;
50599
52001
  }
50600
52002
  visited.add(current);
50601
- path42.push(current);
52003
+ path47.push(current);
50602
52004
  current = currentEntry.aliasOf || "";
50603
52005
  }
50604
52006
  }
@@ -50639,7 +52041,7 @@ function resolveCommand(tokens) {
50639
52041
  }
50640
52042
  return null;
50641
52043
  }
50642
- var COMMAND_REGISTRY, VALID_COMMANDS, _internals21, validation;
52044
+ var COMMAND_REGISTRY, VALID_COMMANDS, _internals25, validation;
50643
52045
  var init_registry = __esm(() => {
50644
52046
  init_acknowledge_spec_drift();
50645
52047
  init_agents();
@@ -50709,7 +52111,7 @@ var init_registry = __esm(() => {
50709
52111
  clashesWithNativeCcCommand: "/agents"
50710
52112
  },
50711
52113
  help: {
50712
- handler: (ctx) => _internals21.handleHelpCommand(ctx),
52114
+ handler: (ctx) => _internals25.handleHelpCommand(ctx),
50713
52115
  description: "Show help for swarm commands",
50714
52116
  category: "core",
50715
52117
  args: "[command]",
@@ -51066,7 +52468,7 @@ var init_registry = __esm(() => {
51066
52468
  }
51067
52469
  };
51068
52470
  VALID_COMMANDS = Object.keys(COMMAND_REGISTRY);
51069
- _internals21 = {
52471
+ _internals25 = {
51070
52472
  handleHelpCommand,
51071
52473
  validateAliases,
51072
52474
  resolveCommand,
@@ -51074,7 +52476,7 @@ var init_registry = __esm(() => {
51074
52476
  findSimilarCommands,
51075
52477
  buildDetailedHelp
51076
52478
  };
51077
- validation = _internals21.validateAliases();
52479
+ validation = _internals25.validateAliases();
51078
52480
  if (!validation.valid) {
51079
52481
  throw new Error(`COMMAND_REGISTRY alias validation failed:
51080
52482
  ${validation.errors.join(`
@@ -51092,68 +52494,68 @@ init_package();
51092
52494
  init_registry();
51093
52495
  init_cache_paths();
51094
52496
  init_constants();
51095
- import * as fs24 from "fs";
52497
+ import * as fs29 from "fs";
51096
52498
  import * as os7 from "os";
51097
- import * as path42 from "path";
52499
+ import * as path47 from "path";
51098
52500
  var { version: version4 } = package_default;
51099
52501
  var CONFIG_DIR = getPluginConfigDir();
51100
- var OPENCODE_CONFIG_PATH = path42.join(CONFIG_DIR, "opencode.json");
51101
- var PLUGIN_CONFIG_PATH = path42.join(CONFIG_DIR, "opencode-swarm.json");
51102
- var PROMPTS_DIR = path42.join(CONFIG_DIR, "opencode-swarm");
52502
+ var OPENCODE_CONFIG_PATH = path47.join(CONFIG_DIR, "opencode.json");
52503
+ var PLUGIN_CONFIG_PATH = path47.join(CONFIG_DIR, "opencode-swarm.json");
52504
+ var PROMPTS_DIR = path47.join(CONFIG_DIR, "opencode-swarm");
51103
52505
  var OPENCODE_PLUGIN_CACHE_PATHS = getPluginCachePaths();
51104
52506
  var OPENCODE_PLUGIN_LOCK_FILE_PATHS = getPluginLockFilePaths();
51105
52507
  function isSafeCachePath(p) {
51106
- const resolved = path42.resolve(p);
51107
- const home = path42.resolve(os7.homedir());
52508
+ const resolved = path47.resolve(p);
52509
+ const home = path47.resolve(os7.homedir());
51108
52510
  if (resolved === "/" || resolved === home || resolved.length <= home.length) {
51109
52511
  return false;
51110
52512
  }
51111
- const segments = resolved.split(path42.sep).filter((s) => s.length > 0);
52513
+ const segments = resolved.split(path47.sep).filter((s) => s.length > 0);
51112
52514
  if (segments.length < 4) {
51113
52515
  return false;
51114
52516
  }
51115
- const leaf = path42.basename(resolved);
52517
+ const leaf = path47.basename(resolved);
51116
52518
  if (leaf !== "opencode-swarm@latest" && leaf !== "opencode-swarm") {
51117
52519
  return false;
51118
52520
  }
51119
- const parent = path42.basename(path42.dirname(resolved));
52521
+ const parent = path47.basename(path47.dirname(resolved));
51120
52522
  if (parent !== "packages" && parent !== "node_modules") {
51121
52523
  return false;
51122
52524
  }
51123
- const grandparent = path42.basename(path42.dirname(path42.dirname(resolved)));
52525
+ const grandparent = path47.basename(path47.dirname(path47.dirname(resolved)));
51124
52526
  if (grandparent !== "opencode") {
51125
52527
  return false;
51126
52528
  }
51127
52529
  return true;
51128
52530
  }
51129
52531
  function isSafeLockFilePath(p) {
51130
- const resolved = path42.resolve(p);
51131
- const home = path42.resolve(os7.homedir());
52532
+ const resolved = path47.resolve(p);
52533
+ const home = path47.resolve(os7.homedir());
51132
52534
  if (resolved === "/" || resolved === home || resolved.length <= home.length) {
51133
52535
  return false;
51134
52536
  }
51135
- const segments = resolved.split(path42.sep).filter((s) => s.length > 0);
52537
+ const segments = resolved.split(path47.sep).filter((s) => s.length > 0);
51136
52538
  if (segments.length < 4) {
51137
52539
  return false;
51138
52540
  }
51139
- const leaf = path42.basename(resolved);
52541
+ const leaf = path47.basename(resolved);
51140
52542
  if (leaf !== "bun.lock" && leaf !== "bun.lockb" && leaf !== "package-lock.json") {
51141
52543
  return false;
51142
52544
  }
51143
- const parent = path42.basename(path42.dirname(resolved));
52545
+ const parent = path47.basename(path47.dirname(resolved));
51144
52546
  if (parent !== "opencode") {
51145
52547
  return false;
51146
52548
  }
51147
52549
  return true;
51148
52550
  }
51149
52551
  function ensureDir(dir) {
51150
- if (!fs24.existsSync(dir)) {
51151
- fs24.mkdirSync(dir, { recursive: true });
52552
+ if (!fs29.existsSync(dir)) {
52553
+ fs29.mkdirSync(dir, { recursive: true });
51152
52554
  }
51153
52555
  }
51154
52556
  function loadJson(filepath) {
51155
52557
  try {
51156
- const content = fs24.readFileSync(filepath, "utf-8");
52558
+ const content = fs29.readFileSync(filepath, "utf-8");
51157
52559
  const stripped = content.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (match, comment) => comment ? "" : match).replace(/,(\s*[}\]])/g, "$1");
51158
52560
  return JSON.parse(stripped);
51159
52561
  } catch {
@@ -51161,14 +52563,14 @@ function loadJson(filepath) {
51161
52563
  }
51162
52564
  }
51163
52565
  function saveJson(filepath, data) {
51164
- fs24.writeFileSync(filepath, `${JSON.stringify(data, null, 2)}
52566
+ fs29.writeFileSync(filepath, `${JSON.stringify(data, null, 2)}
51165
52567
  `, "utf-8");
51166
52568
  }
51167
52569
  function writeProjectConfigIfMissing(cwd) {
51168
52570
  try {
51169
- const opencodeDir = path42.join(cwd, ".opencode");
51170
- const projectConfigPath = path42.join(opencodeDir, "opencode-swarm.json");
51171
- if (fs24.existsSync(projectConfigPath)) {
52571
+ const opencodeDir = path47.join(cwd, ".opencode");
52572
+ const projectConfigPath = path47.join(opencodeDir, "opencode-swarm.json");
52573
+ if (fs29.existsSync(projectConfigPath)) {
51172
52574
  return;
51173
52575
  }
51174
52576
  ensureDir(opencodeDir);
@@ -51184,7 +52586,7 @@ async function install() {
51184
52586
  `);
51185
52587
  ensureDir(CONFIG_DIR);
51186
52588
  ensureDir(PROMPTS_DIR);
51187
- const LEGACY_CONFIG_PATH = path42.join(CONFIG_DIR, "config.json");
52589
+ const LEGACY_CONFIG_PATH = path47.join(CONFIG_DIR, "config.json");
51188
52590
  let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
51189
52591
  if (!opencodeConfig) {
51190
52592
  const legacyConfig = loadJson(LEGACY_CONFIG_PATH);
@@ -51231,7 +52633,7 @@ async function install() {
51231
52633
  console.warn(`\u26A0 Could not clear opencode lock file \u2014 you may need to delete it manually:
51232
52634
  ${failed}`);
51233
52635
  }
51234
- if (!fs24.existsSync(PLUGIN_CONFIG_PATH)) {
52636
+ if (!fs29.existsSync(PLUGIN_CONFIG_PATH)) {
51235
52637
  const defaultConfig = {
51236
52638
  agents: { ...DEFAULT_AGENT_CONFIGS },
51237
52639
  max_iterations: 5
@@ -51310,14 +52712,14 @@ function evictPluginCaches() {
51310
52712
  const cleared = [];
51311
52713
  const failed = [];
51312
52714
  for (const cachePath of OPENCODE_PLUGIN_CACHE_PATHS) {
51313
- if (!fs24.existsSync(cachePath))
52715
+ if (!fs29.existsSync(cachePath))
51314
52716
  continue;
51315
52717
  if (!isSafeCachePath(cachePath)) {
51316
52718
  failed.push(`${cachePath} (refused: failed safety check)`);
51317
52719
  continue;
51318
52720
  }
51319
52721
  try {
51320
- fs24.rmSync(cachePath, { recursive: true, force: true });
52722
+ fs29.rmSync(cachePath, { recursive: true, force: true });
51321
52723
  cleared.push(cachePath);
51322
52724
  } catch (err) {
51323
52725
  failed.push(`${cachePath} (${err instanceof Error ? err.message : String(err)})`);
@@ -51329,14 +52731,14 @@ function evictLockFiles() {
51329
52731
  const cleared = [];
51330
52732
  const failed = [];
51331
52733
  for (const lockPath of OPENCODE_PLUGIN_LOCK_FILE_PATHS) {
51332
- if (!fs24.existsSync(lockPath))
52734
+ if (!fs29.existsSync(lockPath))
51333
52735
  continue;
51334
52736
  if (!isSafeLockFilePath(lockPath)) {
51335
52737
  failed.push(`${lockPath} (refused: failed safety check)`);
51336
52738
  continue;
51337
52739
  }
51338
52740
  try {
51339
- fs24.unlinkSync(lockPath);
52741
+ fs29.unlinkSync(lockPath);
51340
52742
  cleared.push(lockPath);
51341
52743
  } catch (err) {
51342
52744
  const code = err?.code;
@@ -51355,7 +52757,7 @@ async function uninstall() {
51355
52757
  `);
51356
52758
  const opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
51357
52759
  if (!opencodeConfig) {
51358
- if (fs24.existsSync(OPENCODE_CONFIG_PATH)) {
52760
+ if (fs29.existsSync(OPENCODE_CONFIG_PATH)) {
51359
52761
  console.log(`\u2717 Could not parse opencode config at: ${OPENCODE_CONFIG_PATH}`);
51360
52762
  return 1;
51361
52763
  } else {
@@ -51387,13 +52789,13 @@ async function uninstall() {
51387
52789
  console.log("\u2713 Re-enabled default OpenCode agents (explore, general)");
51388
52790
  if (process.argv.includes("--clean")) {
51389
52791
  let cleaned = false;
51390
- if (fs24.existsSync(PLUGIN_CONFIG_PATH)) {
51391
- fs24.unlinkSync(PLUGIN_CONFIG_PATH);
52792
+ if (fs29.existsSync(PLUGIN_CONFIG_PATH)) {
52793
+ fs29.unlinkSync(PLUGIN_CONFIG_PATH);
51392
52794
  console.log(`\u2713 Removed plugin config: ${PLUGIN_CONFIG_PATH}`);
51393
52795
  cleaned = true;
51394
52796
  }
51395
- if (fs24.existsSync(PROMPTS_DIR)) {
51396
- fs24.rmSync(PROMPTS_DIR, { recursive: true });
52797
+ if (fs29.existsSync(PROMPTS_DIR)) {
52798
+ fs29.rmSync(PROMPTS_DIR, { recursive: true });
51397
52799
  console.log(`\u2713 Removed custom prompts: ${PROMPTS_DIR}`);
51398
52800
  cleaned = true;
51399
52801
  }