opencode-swarm 7.16.0 → 7.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/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.1",
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",
@@ -15935,7 +15935,6 @@ async function handleAcknowledgeSpecDriftCommand(directory, _args) {
15935
15935
  return "Spec staleness file was corrupted. It has been removed.";
15936
15936
  }
15937
15937
  const { planTitle, phase } = stalenessData;
15938
- await fsPromises3.unlink(specStalenessPath);
15939
15938
  let currentHash = null;
15940
15939
  let planUpdateSkipped = false;
15941
15940
  try {
@@ -15949,6 +15948,9 @@ async function handleAcknowledgeSpecDriftCommand(directory, _args) {
15949
15948
  console.error("[acknowledge-spec-drift] Failed to update plan specHash:", planError instanceof Error ? planError.message : String(planError));
15950
15949
  planUpdateSkipped = true;
15951
15950
  }
15951
+ if (!planUpdateSkipped) {
15952
+ await fsPromises3.unlink(specStalenessPath);
15953
+ }
15952
15954
  const eventsPath = validateSwarmPath(directory, "events.jsonl");
15953
15955
  const acknowledgmentEvent = {
15954
15956
  type: "spec_drift_acknowledged",
@@ -35412,6 +35414,8 @@ async function quarantineEntry(directory, entryId, reason, reportedBy) {
35412
35414
  const remaining = entries.filter((e) => e.id !== entryId);
35413
35415
  const quarantined = {
35414
35416
  ...entry,
35417
+ status: "quarantined",
35418
+ original_status: entry.status,
35415
35419
  quarantine_reason: sanitizedReason,
35416
35420
  quarantined_at: new Date().toISOString(),
35417
35421
  reported_by: reportedBy
@@ -35470,7 +35474,24 @@ async function restoreEntry(directory, entryId) {
35470
35474
  return;
35471
35475
  }
35472
35476
  const remaining = quarantinedEntries.filter((e) => e.id !== entryId);
35473
- const { quarantine_reason, quarantined_at, reported_by, ...original } = entryToRestore;
35477
+ const {
35478
+ quarantine_reason,
35479
+ quarantined_at,
35480
+ reported_by,
35481
+ original_status,
35482
+ status: _quarantineStatus,
35483
+ ...rest
35484
+ } = entryToRestore;
35485
+ const original = { ...rest, status: original_status ?? "candidate" };
35486
+ const validation = validateLesson(original.lesson, [], {
35487
+ category: original.category,
35488
+ scope: original.scope,
35489
+ confidence: original.confidence
35490
+ });
35491
+ if (!validation.valid) {
35492
+ warn(`[knowledge-validator] restoreEntry: entry ${entryId} failed re-validation: ${validation.reason}`);
35493
+ return;
35494
+ }
35474
35495
  const jsonlContent = remaining.length > 0 ? `${remaining.map((e) => JSON.stringify(e)).join(`
35475
35496
  `)}
35476
35497
  ` : "";
@@ -40347,11 +40368,34 @@ class LanguageRegistry {
40347
40368
  this.profiles = new Map;
40348
40369
  this.extensionIndex = new Map;
40349
40370
  }
40371
+ unregister(id) {
40372
+ const profile = this.profiles.get(id);
40373
+ if (!profile)
40374
+ return;
40375
+ this.profiles.delete(id);
40376
+ if (!profile.parserOnly) {
40377
+ for (const ext of profile.extensions) {
40378
+ if (this.extensionIndex.get(ext) === id) {
40379
+ this.extensionIndex.delete(ext);
40380
+ }
40381
+ }
40382
+ }
40383
+ }
40350
40384
  register(profile) {
40351
- this.profiles.set(profile.id, profile);
40352
- for (const ext of profile.extensions) {
40353
- this.extensionIndex.set(ext, profile.id);
40385
+ const existing = this.profiles.get(profile.id);
40386
+ if (existing && existing !== profile) {
40387
+ throw new Error(`LanguageRegistry: profile id "${profile.id}" registered twice. ` + `Each LanguageProfile.id must be unique. ` + `Got: ${profile.displayName} vs existing ${existing.displayName}.`);
40354
40388
  }
40389
+ if (!profile.parserOnly) {
40390
+ for (const ext of profile.extensions) {
40391
+ const claimedBy = this.extensionIndex.get(ext);
40392
+ if (claimedBy && claimedBy !== profile.id) {
40393
+ 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.`);
40394
+ }
40395
+ this.extensionIndex.set(ext, profile.id);
40396
+ }
40397
+ }
40398
+ this.profiles.set(profile.id, profile);
40355
40399
  }
40356
40400
  get(id) {
40357
40401
  return this.profiles.get(id);
@@ -40383,7 +40427,8 @@ var init_profiles = __esm(() => {
40383
40427
  extensions: [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"],
40384
40428
  treeSitter: {
40385
40429
  grammarId: "typescript",
40386
- wasmFile: "tree-sitter-typescript.wasm"
40430
+ wasmFile: "tree-sitter-typescript.wasm",
40431
+ commentNodes: ["comment", "line_comment", "block_comment"]
40387
40432
  },
40388
40433
  build: {
40389
40434
  detectFiles: ["package.json"],
@@ -40409,7 +40454,13 @@ var init_profiles = __esm(() => {
40409
40454
  ]
40410
40455
  },
40411
40456
  test: {
40412
- detectFiles: ["package.json", "vitest.config.ts", "jest.config.js"],
40457
+ detectFiles: [
40458
+ "package.json",
40459
+ "vitest.config.ts",
40460
+ "jest.config.js",
40461
+ ".mocharc.js",
40462
+ ".mocharc.json"
40463
+ ],
40413
40464
  frameworks: [
40414
40465
  {
40415
40466
  name: "vitest",
@@ -40420,9 +40471,15 @@ var init_profiles = __esm(() => {
40420
40471
  { name: "jest", detect: "jest.config.js", cmd: "npx jest", priority: 9 },
40421
40472
  {
40422
40473
  name: "bun:test",
40423
- detect: "package.json",
40474
+ detect: "bun.lock",
40424
40475
  cmd: "bun test",
40425
40476
  priority: 8
40477
+ },
40478
+ {
40479
+ name: "mocha",
40480
+ detect: ".mocharc.json",
40481
+ cmd: "npx mocha",
40482
+ priority: 7
40426
40483
  }
40427
40484
  ]
40428
40485
  },
@@ -40476,7 +40533,11 @@ var init_profiles = __esm(() => {
40476
40533
  displayName: "Python",
40477
40534
  tier: 1,
40478
40535
  extensions: [".py", ".pyw"],
40479
- treeSitter: { grammarId: "python", wasmFile: "tree-sitter-python.wasm" },
40536
+ treeSitter: {
40537
+ grammarId: "python",
40538
+ wasmFile: "tree-sitter-python.wasm",
40539
+ commentNodes: ["comment"]
40540
+ },
40480
40541
  build: {
40481
40542
  detectFiles: ["setup.py", "pyproject.toml", "setup.cfg"],
40482
40543
  commands: [
@@ -40546,7 +40607,11 @@ var init_profiles = __esm(() => {
40546
40607
  displayName: "Rust",
40547
40608
  tier: 1,
40548
40609
  extensions: [".rs"],
40549
- treeSitter: { grammarId: "rust", wasmFile: "tree-sitter-rust.wasm" },
40610
+ treeSitter: {
40611
+ grammarId: "rust",
40612
+ wasmFile: "tree-sitter-rust.wasm",
40613
+ commentNodes: ["line_comment", "block_comment"]
40614
+ },
40550
40615
  build: {
40551
40616
  detectFiles: ["Cargo.toml"],
40552
40617
  commands: [
@@ -40615,7 +40680,11 @@ var init_profiles = __esm(() => {
40615
40680
  displayName: "Go",
40616
40681
  tier: 1,
40617
40682
  extensions: [".go"],
40618
- treeSitter: { grammarId: "go", wasmFile: "tree-sitter-go.wasm" },
40683
+ treeSitter: {
40684
+ grammarId: "go",
40685
+ wasmFile: "tree-sitter-go.wasm",
40686
+ commentNodes: ["comment"]
40687
+ },
40619
40688
  build: {
40620
40689
  detectFiles: ["go.mod"],
40621
40690
  commands: [
@@ -40679,7 +40748,11 @@ var init_profiles = __esm(() => {
40679
40748
  displayName: "Java",
40680
40749
  tier: 2,
40681
40750
  extensions: [".java"],
40682
- treeSitter: { grammarId: "java", wasmFile: "tree-sitter-java.wasm" },
40751
+ treeSitter: {
40752
+ grammarId: "java",
40753
+ wasmFile: "tree-sitter-java.wasm",
40754
+ commentNodes: ["line_comment", "block_comment"]
40755
+ },
40683
40756
  build: {
40684
40757
  detectFiles: ["pom.xml", "build.gradle", "build.gradle.kts"],
40685
40758
  commands: [
@@ -40759,7 +40832,11 @@ var init_profiles = __esm(() => {
40759
40832
  displayName: "Kotlin",
40760
40833
  tier: 2,
40761
40834
  extensions: [".kt", ".kts"],
40762
- treeSitter: { grammarId: "kotlin", wasmFile: "tree-sitter-kotlin.wasm" },
40835
+ treeSitter: {
40836
+ grammarId: "kotlin",
40837
+ wasmFile: "tree-sitter-kotlin.wasm",
40838
+ commentNodes: ["line_comment", "multiline_comment"]
40839
+ },
40763
40840
  build: {
40764
40841
  detectFiles: ["build.gradle.kts", "build.gradle", "pom.xml"],
40765
40842
  commands: [
@@ -40839,7 +40916,11 @@ var init_profiles = __esm(() => {
40839
40916
  displayName: "C# / .NET",
40840
40917
  tier: 2,
40841
40918
  extensions: [".cs", ".csx"],
40842
- treeSitter: { grammarId: "csharp", wasmFile: "tree-sitter-c-sharp.wasm" },
40919
+ treeSitter: {
40920
+ grammarId: "csharp",
40921
+ wasmFile: "tree-sitter-c-sharp.wasm",
40922
+ commentNodes: ["comment"]
40923
+ },
40843
40924
  build: {
40844
40925
  detectFiles: ["*.csproj", "*.sln", "Directory.Build.props"],
40845
40926
  commands: [
@@ -40907,7 +40988,11 @@ var init_profiles = __esm(() => {
40907
40988
  displayName: "C / C++",
40908
40989
  tier: 2,
40909
40990
  extensions: [".c", ".h", ".cpp", ".hpp", ".cc", ".cxx"],
40910
- treeSitter: { grammarId: "cpp", wasmFile: "tree-sitter-cpp.wasm" },
40991
+ treeSitter: {
40992
+ grammarId: "cpp",
40993
+ wasmFile: "tree-sitter-cpp.wasm",
40994
+ commentNodes: ["comment"]
40995
+ },
40911
40996
  build: {
40912
40997
  detectFiles: ["CMakeLists.txt", "Makefile", "meson.build"],
40913
40998
  commands: [
@@ -40982,7 +41067,11 @@ var init_profiles = __esm(() => {
40982
41067
  displayName: "Swift",
40983
41068
  tier: 2,
40984
41069
  extensions: [".swift"],
40985
- treeSitter: { grammarId: "swift", wasmFile: "tree-sitter-swift.wasm" },
41070
+ treeSitter: {
41071
+ grammarId: "swift",
41072
+ wasmFile: "tree-sitter-swift.wasm",
41073
+ commentNodes: ["comment", "multiline_comment"]
41074
+ },
40986
41075
  build: {
40987
41076
  detectFiles: ["Package.swift", "*.xcodeproj", "*.xcworkspace"],
40988
41077
  commands: [
@@ -41056,7 +41145,11 @@ var init_profiles = __esm(() => {
41056
41145
  displayName: "Dart / Flutter",
41057
41146
  tier: 3,
41058
41147
  extensions: [".dart"],
41059
- treeSitter: { grammarId: "dart", wasmFile: "tree-sitter-dart.wasm" },
41148
+ treeSitter: {
41149
+ grammarId: "dart",
41150
+ wasmFile: "tree-sitter-dart.wasm",
41151
+ commentNodes: ["comment", "documentation_comment"]
41152
+ },
41060
41153
  build: {
41061
41154
  detectFiles: ["pubspec.yaml"],
41062
41155
  commands: [
@@ -41130,7 +41223,11 @@ var init_profiles = __esm(() => {
41130
41223
  displayName: "Ruby",
41131
41224
  tier: 3,
41132
41225
  extensions: [".rb", ".rake", ".gemspec"],
41133
- treeSitter: { grammarId: "ruby", wasmFile: "tree-sitter-ruby.wasm" },
41226
+ treeSitter: {
41227
+ grammarId: "ruby",
41228
+ wasmFile: "tree-sitter-ruby.wasm",
41229
+ commentNodes: ["comment"]
41230
+ },
41134
41231
  build: {
41135
41232
  detectFiles: ["Gemfile", "Rakefile"],
41136
41233
  commands: [
@@ -41199,7 +41296,11 @@ var init_profiles = __esm(() => {
41199
41296
  displayName: "PHP",
41200
41297
  tier: 3,
41201
41298
  extensions: [".php", ".phtml", ".blade.php"],
41202
- treeSitter: { grammarId: "php", wasmFile: "tree-sitter-php.wasm" },
41299
+ treeSitter: {
41300
+ grammarId: "php",
41301
+ wasmFile: "tree-sitter-php.wasm",
41302
+ commentNodes: ["comment"]
41303
+ },
41203
41304
  build: {
41204
41305
  detectFiles: ["composer.json"],
41205
41306
  commands: [
@@ -41207,7 +41308,7 @@ var init_profiles = __esm(() => {
41207
41308
  name: "Composer Install",
41208
41309
  cmd: "composer install --no-interaction --prefer-dist",
41209
41310
  detectFile: "composer.json",
41210
- priority: 1
41311
+ priority: 10
41211
41312
  }
41212
41313
  ]
41213
41314
  },
@@ -41218,19 +41319,19 @@ var init_profiles = __esm(() => {
41218
41319
  name: "Pest",
41219
41320
  detect: "Pest.php",
41220
41321
  cmd: "vendor/bin/pest",
41221
- priority: 1
41322
+ priority: 10
41222
41323
  },
41223
41324
  {
41224
41325
  name: "PHPUnit",
41225
41326
  detect: "phpunit.xml",
41226
41327
  cmd: "vendor/bin/phpunit",
41227
- priority: 3
41328
+ priority: 8
41228
41329
  },
41229
41330
  {
41230
41331
  name: "PHPUnit",
41231
41332
  detect: "phpunit.xml.dist",
41232
41333
  cmd: "vendor/bin/phpunit",
41233
- priority: 4
41334
+ priority: 7
41234
41335
  }
41235
41336
  ]
41236
41337
  },
@@ -41247,25 +41348,25 @@ var init_profiles = __esm(() => {
41247
41348
  name: "PHPStan",
41248
41349
  detect: "phpstan.neon",
41249
41350
  cmd: "vendor/bin/phpstan analyse",
41250
- priority: 1
41351
+ priority: 10
41251
41352
  },
41252
41353
  {
41253
41354
  name: "PHPStan",
41254
41355
  detect: "phpstan.neon.dist",
41255
41356
  cmd: "vendor/bin/phpstan analyse",
41256
- priority: 2
41357
+ priority: 9
41257
41358
  },
41258
41359
  {
41259
41360
  name: "Pint",
41260
41361
  detect: "pint.json",
41261
41362
  cmd: "vendor/bin/pint --test",
41262
- priority: 3
41363
+ priority: 8
41263
41364
  },
41264
41365
  {
41265
41366
  name: "PHP-CS-Fixer",
41266
41367
  detect: ".php-cs-fixer.php",
41267
41368
  cmd: "vendor/bin/php-cs-fixer fix --dry-run --diff",
41268
- priority: 4
41369
+ priority: 7
41269
41370
  }
41270
41371
  ]
41271
41372
  },
@@ -41370,9 +41471,12 @@ function isCommandAvailable(command) {
41370
41471
  const isWindows = process.platform === "win32";
41371
41472
  const cmd = isWindows ? `${command}.exe` : command;
41372
41473
  try {
41373
- const result = bunSpawnSync(isWindows ? ["where", cmd] : ["which", cmd], {
41374
- stdout: "pipe",
41375
- stderr: "pipe"
41474
+ const result = _internals11.spawnSyncImpl(isWindows ? ["where", cmd] : ["which", cmd], {
41475
+ cwd: process.cwd(),
41476
+ stdin: "ignore",
41477
+ stdout: "ignore",
41478
+ stderr: "ignore",
41479
+ timeout: IS_COMMAND_AVAILABLE_TIMEOUT_MS
41376
41480
  });
41377
41481
  const available = result.success;
41378
41482
  toolchainCache.set(command, available);
@@ -41580,7 +41684,7 @@ function clearToolchainCache() {
41580
41684
  function getEcosystems() {
41581
41685
  return ECOSYSTEMS.map((e) => e.ecosystem);
41582
41686
  }
41583
- var ECOSYSTEMS, PROFILE_TO_ECOSYSTEM_NAMES, toolchainCache, _internals11, build_discovery;
41687
+ var ECOSYSTEMS, PROFILE_TO_ECOSYSTEM_NAMES, toolchainCache, IS_COMMAND_AVAILABLE_TIMEOUT_MS = 3000, _internals11, build_discovery;
41584
41688
  var init_discovery = __esm(() => {
41585
41689
  init_dist();
41586
41690
  init_detector();
@@ -41703,7 +41807,8 @@ var init_discovery = __esm(() => {
41703
41807
  discoverBuildCommandsFromProfiles,
41704
41808
  discoverBuildCommands,
41705
41809
  clearToolchainCache,
41706
- getEcosystems
41810
+ getEcosystems,
41811
+ spawnSyncImpl: bunSpawnSync
41707
41812
  };
41708
41813
  build_discovery = tool({
41709
41814
  description: "Discover build commands for various ecosystems in a project directory",
@@ -45582,16 +45687,710 @@ var init_secretscan = __esm(() => {
45582
45687
  };
45583
45688
  });
45584
45689
 
45690
+ // src/lang/default-backend.ts
45691
+ import * as fs14 from "fs";
45692
+ import * as path31 from "path";
45693
+ function detectFileExists(dir, pattern) {
45694
+ if (pattern.includes("*") || pattern.includes("?")) {
45695
+ try {
45696
+ const files = fs14.readdirSync(dir);
45697
+ const regex = new RegExp(`^${pattern.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, ".")}$`);
45698
+ return files.some((f) => regex.test(f));
45699
+ } catch {
45700
+ return false;
45701
+ }
45702
+ }
45703
+ try {
45704
+ fs14.accessSync(path31.join(dir, pattern));
45705
+ return true;
45706
+ } catch {
45707
+ return false;
45708
+ }
45709
+ }
45710
+ function tokenizeCommand(cmd) {
45711
+ const out = [];
45712
+ let buf = "";
45713
+ let quote = null;
45714
+ for (const ch of cmd) {
45715
+ if (quote) {
45716
+ if (ch === quote) {
45717
+ quote = null;
45718
+ } else {
45719
+ buf += ch;
45720
+ }
45721
+ continue;
45722
+ }
45723
+ if (ch === '"' || ch === "'") {
45724
+ quote = ch;
45725
+ continue;
45726
+ }
45727
+ if (ch === " " || ch === "\t") {
45728
+ if (buf.length > 0) {
45729
+ out.push(buf);
45730
+ buf = "";
45731
+ }
45732
+ continue;
45733
+ }
45734
+ buf += ch;
45735
+ }
45736
+ if (buf.length > 0)
45737
+ out.push(buf);
45738
+ return out;
45739
+ }
45740
+ async function defaultSelectTestFramework(profile, dir) {
45741
+ const sorted = [...profile.test.frameworks].sort((a, b) => b.priority - a.priority);
45742
+ for (const fw of sorted) {
45743
+ if (!detectFileExists(dir, fw.detect))
45744
+ continue;
45745
+ const argv = tokenizeCommand(fw.cmd);
45746
+ if (argv.length === 0)
45747
+ continue;
45748
+ if (!isCommandAvailable(argv[0]))
45749
+ continue;
45750
+ return {
45751
+ name: fw.name,
45752
+ cmd: argv,
45753
+ cwd: dir,
45754
+ detectedVia: fw.detect,
45755
+ filesIgnored: false
45756
+ };
45757
+ }
45758
+ return null;
45759
+ }
45760
+ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}) {
45761
+ const scope = opts.scope ?? "all";
45762
+ const coverage = opts.coverage ?? false;
45763
+ switch (framework) {
45764
+ case "bun": {
45765
+ const args = ["bun", "test"];
45766
+ if (coverage)
45767
+ args.push("--coverage");
45768
+ if (scope !== "all" && files.length > 0)
45769
+ args.push(...files);
45770
+ return args;
45771
+ }
45772
+ case "vitest": {
45773
+ const args = ["npx", "vitest", "run"];
45774
+ if (coverage)
45775
+ args.push("--coverage");
45776
+ if (scope !== "all" && files.length > 0)
45777
+ args.push(...files);
45778
+ return args;
45779
+ }
45780
+ case "jest": {
45781
+ const args = ["npx", "jest"];
45782
+ if (coverage)
45783
+ args.push("--coverage");
45784
+ if (scope !== "all" && files.length > 0)
45785
+ args.push(...files);
45786
+ return args;
45787
+ }
45788
+ case "mocha": {
45789
+ const args = ["npx", "mocha"];
45790
+ if (scope !== "all" && files.length > 0)
45791
+ args.push(...files);
45792
+ return args;
45793
+ }
45794
+ case "pytest": {
45795
+ const isWindows = process.platform === "win32";
45796
+ const args = isWindows ? ["python", "-m", "pytest"] : ["python3", "-m", "pytest"];
45797
+ if (coverage)
45798
+ args.push("--cov=.", "--cov-report=term-missing");
45799
+ if (scope !== "all" && files.length > 0)
45800
+ args.push(...files);
45801
+ return args;
45802
+ }
45803
+ case "cargo": {
45804
+ const args = ["cargo", "test"];
45805
+ if (scope !== "all" && files.length > 0)
45806
+ args.push(...files);
45807
+ return args;
45808
+ }
45809
+ case "pester": {
45810
+ if (scope !== "all" && files.length > 0) {
45811
+ const escapedFiles = files.map((f) => f.replace(/'/g, "''").replace(/`/g, "``").replace(/\$/g, "`$"));
45812
+ const psCommand = `Invoke-Pester -Path @('${escapedFiles.join("','")}')`;
45813
+ const utf16Bytes = Buffer.from(psCommand, "utf16le");
45814
+ const base64Command = utf16Bytes.toString("base64");
45815
+ return ["pwsh", "-EncodedCommand", base64Command];
45816
+ }
45817
+ return ["pwsh", "-Command", "Invoke-Pester"];
45818
+ }
45819
+ case "go-test":
45820
+ return ["go", "test", "./..."];
45821
+ case "maven":
45822
+ return ["mvn", "test"];
45823
+ case "gradle": {
45824
+ const isWindows = process.platform === "win32";
45825
+ const hasGradlewBat = fs14.existsSync(path31.join(dir, "gradlew.bat"));
45826
+ const hasGradlew = fs14.existsSync(path31.join(dir, "gradlew"));
45827
+ if (hasGradlewBat && isWindows)
45828
+ return ["gradlew.bat", "test"];
45829
+ if (hasGradlew)
45830
+ return ["./gradlew", "test"];
45831
+ return ["gradle", "test"];
45832
+ }
45833
+ case "dotnet-test":
45834
+ return ["dotnet", "test"];
45835
+ case "ctest": {
45836
+ const buildDirCandidates = [
45837
+ "build",
45838
+ "_build",
45839
+ "cmake-build-debug",
45840
+ "cmake-build-release",
45841
+ "out"
45842
+ ];
45843
+ const actualBuildDir = buildDirCandidates.find((d) => fs14.existsSync(path31.join(dir, d, "CMakeCache.txt"))) ?? "build";
45844
+ return ["ctest", "--test-dir", actualBuildDir];
45845
+ }
45846
+ case "swift-test":
45847
+ return ["swift", "test"];
45848
+ case "dart-test":
45849
+ return isCommandAvailable("flutter") ? ["flutter", "test", ...files] : ["dart", "test", ...files];
45850
+ case "rspec": {
45851
+ const args = isCommandAvailable("bundle") ? ["bundle", "exec", "rspec"] : ["rspec"];
45852
+ if (scope !== "all" && files.length > 0)
45853
+ args.push(...files);
45854
+ return args;
45855
+ }
45856
+ case "minitest":
45857
+ if (scope !== "all" && files.length > 0) {
45858
+ const requires = files.map((f) => `require_relative '${f.replace(/\\/g, "/").replace(/'/g, "\\'")}'`).join("; ");
45859
+ return ["ruby", "-Itest", "-e", requires];
45860
+ }
45861
+ return [
45862
+ "ruby",
45863
+ "-Itest",
45864
+ "-e",
45865
+ 'Dir.glob("test/**/*_test.rb").sort.each { |f| require_relative f }'
45866
+ ];
45867
+ default: {
45868
+ const fw = profile.test.frameworks.find((f) => f.name === framework);
45869
+ if (!fw)
45870
+ return null;
45871
+ const argv = tokenizeCommand(fw.cmd);
45872
+ if (argv.length === 0)
45873
+ return null;
45874
+ if (files.length === 0)
45875
+ return argv;
45876
+ return [...argv, ...files];
45877
+ }
45878
+ }
45879
+ }
45880
+ function defaultParseTestOutput(framework, stdout, stderr, exitCode) {
45881
+ const output = stdout && stderr ? `${stdout}
45882
+ ${stderr}` : stdout || stderr || "";
45883
+ let passed = 0;
45884
+ let failed = 0;
45885
+ let skipped = 0;
45886
+ let total;
45887
+ let coveragePercent;
45888
+ switch (framework) {
45889
+ case "vitest":
45890
+ case "jest":
45891
+ case "bun": {
45892
+ const jsonMatch = output.match(/\{[\s\S]*"testResults"[\s\S]*\}/);
45893
+ if (jsonMatch) {
45894
+ try {
45895
+ const parsed = JSON.parse(jsonMatch[0]);
45896
+ if (parsed.numTotalTests !== undefined) {
45897
+ passed = parsed.numPassedTests || 0;
45898
+ failed = parsed.numFailedTests || 0;
45899
+ skipped = parsed.numPendingTests || 0;
45900
+ total = parsed.numTotalTests || 0;
45901
+ }
45902
+ if (parsed.coverage !== undefined) {
45903
+ coveragePercent = parsed.coverage;
45904
+ }
45905
+ } catch {}
45906
+ }
45907
+ if (total === undefined || total === 0) {
45908
+ const passMatch = output.match(/(\d+)\s+pass(ing|ed)?/);
45909
+ const failMatch = output.match(/(\d+)\s+fail(ing|ed)?/);
45910
+ const skipMatch = output.match(/(\d+)\s+skip(ping|ped)?/);
45911
+ if (passMatch)
45912
+ passed = parseInt(passMatch[1], 10);
45913
+ if (failMatch)
45914
+ failed = parseInt(failMatch[1], 10);
45915
+ if (skipMatch)
45916
+ skipped = parseInt(skipMatch[1], 10);
45917
+ total = passed + failed + skipped;
45918
+ }
45919
+ const coverageMatch = output.match(/All files[^\d]*(\d+\.?\d*)\s*%/);
45920
+ if (coveragePercent === undefined && coverageMatch) {
45921
+ coveragePercent = parseFloat(coverageMatch[1]);
45922
+ }
45923
+ break;
45924
+ }
45925
+ case "mocha": {
45926
+ const passMatch = output.match(/(\d+)\s+passing/);
45927
+ const failMatch = output.match(/(\d+)\s+failing/);
45928
+ const pendingMatch = output.match(/(\d+)\s+pending/);
45929
+ if (passMatch)
45930
+ passed = parseInt(passMatch[1], 10);
45931
+ if (failMatch)
45932
+ failed = parseInt(failMatch[1], 10);
45933
+ if (pendingMatch)
45934
+ skipped = parseInt(pendingMatch[1], 10);
45935
+ total = passed + failed + skipped;
45936
+ break;
45937
+ }
45938
+ case "pytest": {
45939
+ const passMatch = output.match(/(\d+)\s+passed/);
45940
+ const failMatch = output.match(/(\d+)\s+failed/);
45941
+ const skipMatch = output.match(/(\d+)\s+skipped/);
45942
+ if (passMatch)
45943
+ passed = parseInt(passMatch[1], 10);
45944
+ if (failMatch)
45945
+ failed = parseInt(failMatch[1], 10);
45946
+ if (skipMatch)
45947
+ skipped = parseInt(skipMatch[1], 10);
45948
+ total = passed + failed + skipped;
45949
+ const coverageMatch = output.match(/TOTAL\s+(\d+\.?\d*)\s*%/);
45950
+ if (coverageMatch)
45951
+ coveragePercent = parseFloat(coverageMatch[1]);
45952
+ break;
45953
+ }
45954
+ case "cargo": {
45955
+ const passMatch = output.match(/test result: ok\. (\d+) passed/);
45956
+ const failMatch = output.match(/test result: FAILED\. (\d+) passed; (\d+) failed/);
45957
+ if (failMatch) {
45958
+ passed = parseInt(failMatch[1], 10);
45959
+ failed = parseInt(failMatch[2], 10);
45960
+ } else if (passMatch) {
45961
+ passed = parseInt(passMatch[1], 10);
45962
+ }
45963
+ total = passed + failed;
45964
+ break;
45965
+ }
45966
+ case "pester": {
45967
+ const passMatch = output.match(/Passed:\s*(\d+)/);
45968
+ const failMatch = output.match(/Failed:\s*(\d+)/);
45969
+ const skipMatch = output.match(/Skipped:\s*(\d+)/);
45970
+ if (passMatch)
45971
+ passed = parseInt(passMatch[1], 10);
45972
+ if (failMatch)
45973
+ failed = parseInt(failMatch[1], 10);
45974
+ if (skipMatch)
45975
+ skipped = parseInt(skipMatch[1], 10);
45976
+ total = passed + failed + skipped;
45977
+ break;
45978
+ }
45979
+ case "go-test": {
45980
+ const passMatches = [...output.matchAll(/--- PASS:/g)];
45981
+ const failMatches = [...output.matchAll(/--- FAIL:/g)];
45982
+ const skipMatches = [...output.matchAll(/--- SKIP:/g)];
45983
+ passed = passMatches.length;
45984
+ failed = failMatches.length;
45985
+ skipped = skipMatches.length;
45986
+ total = passed + failed + skipped;
45987
+ const covMatch = output.match(/coverage:\s*(\d+\.?\d*)\s*%/);
45988
+ if (covMatch)
45989
+ coveragePercent = parseFloat(covMatch[1]);
45990
+ break;
45991
+ }
45992
+ case "maven": {
45993
+ const mavenMatch = output.match(/Tests run:\s*(\d+),\s*Failures:\s*(\d+),\s*Errors:\s*(\d+),\s*Skipped:\s*(\d+)/);
45994
+ if (mavenMatch) {
45995
+ const tot = parseInt(mavenMatch[1], 10);
45996
+ const failures = parseInt(mavenMatch[2], 10);
45997
+ const errors5 = parseInt(mavenMatch[3], 10);
45998
+ const sk = parseInt(mavenMatch[4], 10);
45999
+ failed = failures + errors5;
46000
+ skipped = sk;
46001
+ passed = tot - failed - sk;
46002
+ total = tot;
46003
+ }
46004
+ break;
46005
+ }
46006
+ case "gradle": {
46007
+ const gradleMatch = output.match(/(\d+) tests? completed(?:,\s*(\d+) failed)?(?:,\s*(\d+) skipped)?/);
46008
+ if (gradleMatch) {
46009
+ total = parseInt(gradleMatch[1], 10);
46010
+ failed = gradleMatch[2] ? parseInt(gradleMatch[2], 10) : 0;
46011
+ skipped = gradleMatch[3] ? parseInt(gradleMatch[3], 10) : 0;
46012
+ passed = total - failed - skipped;
46013
+ }
46014
+ break;
46015
+ }
46016
+ case "dotnet-test": {
46017
+ const passMatch = output.match(/Passed[!:]?\s*(\d+)/i);
46018
+ const failMatch = output.match(/Failed[!:]?\s*(\d+)/i);
46019
+ const skipMatch = output.match(/Skipped[!:]?\s*(\d+)/i);
46020
+ if (passMatch)
46021
+ passed = parseInt(passMatch[1], 10);
46022
+ if (failMatch)
46023
+ failed = parseInt(failMatch[1], 10);
46024
+ if (skipMatch)
46025
+ skipped = parseInt(skipMatch[1], 10);
46026
+ total = passed + failed + skipped;
46027
+ break;
46028
+ }
46029
+ case "ctest": {
46030
+ const ctestMatch = output.match(/(\d+) tests? failed out of (\d+)/);
46031
+ if (ctestMatch) {
46032
+ failed = parseInt(ctestMatch[1], 10);
46033
+ total = parseInt(ctestMatch[2], 10);
46034
+ passed = total - failed;
46035
+ } else {
46036
+ const allPassMatch = output.match(/100% tests passed.*?(\d+) tests?/);
46037
+ if (allPassMatch) {
46038
+ total = parseInt(allPassMatch[1], 10);
46039
+ passed = total;
46040
+ }
46041
+ }
46042
+ break;
46043
+ }
46044
+ case "swift-test": {
46045
+ const swiftMatch = output.match(/Executed (\d+) tests?,\s*with (\d+) failures?/);
46046
+ if (swiftMatch) {
46047
+ total = parseInt(swiftMatch[1], 10);
46048
+ failed = parseInt(swiftMatch[2], 10);
46049
+ passed = total - failed;
46050
+ }
46051
+ break;
46052
+ }
46053
+ case "dart-test": {
46054
+ const dartPassMatch = output.match(/\+(\d+):\s*All tests passed/);
46055
+ const dartMixMatch = output.match(/\+(\d+)\s+-(\d+):/);
46056
+ if (dartPassMatch) {
46057
+ passed = parseInt(dartPassMatch[1], 10);
46058
+ total = passed;
46059
+ } else if (dartMixMatch) {
46060
+ passed = parseInt(dartMixMatch[1], 10);
46061
+ failed = parseInt(dartMixMatch[2], 10);
46062
+ total = passed + failed;
46063
+ }
46064
+ break;
46065
+ }
46066
+ case "rspec": {
46067
+ const rspecMatch = output.match(/(\d+) examples?,\s*(\d+) failures?(?:,\s*(\d+) pending)?/);
46068
+ if (rspecMatch) {
46069
+ total = parseInt(rspecMatch[1], 10);
46070
+ failed = parseInt(rspecMatch[2], 10);
46071
+ skipped = rspecMatch[3] ? parseInt(rspecMatch[3], 10) : 0;
46072
+ passed = total - failed - skipped;
46073
+ }
46074
+ break;
46075
+ }
46076
+ case "minitest": {
46077
+ const minitestMatch = output.match(/(\d+) runs?,\s*\d+ assertions?,\s*(\d+) failures?,\s*(\d+) errors?,\s*(\d+) skips?/);
46078
+ if (minitestMatch) {
46079
+ total = parseInt(minitestMatch[1], 10);
46080
+ const failures = parseInt(minitestMatch[2], 10);
46081
+ const errors5 = parseInt(minitestMatch[3], 10);
46082
+ skipped = parseInt(minitestMatch[4], 10);
46083
+ failed = failures + errors5;
46084
+ passed = total - failed - skipped;
46085
+ }
46086
+ break;
46087
+ }
46088
+ default:
46089
+ break;
46090
+ }
46091
+ if (total === undefined)
46092
+ total = passed + failed + skipped;
46093
+ return {
46094
+ ok: exitCode === 0,
46095
+ raw: { stdout, stderr, exitCode },
46096
+ passed,
46097
+ failed,
46098
+ skipped,
46099
+ total,
46100
+ ...coveragePercent !== undefined ? { coveragePercent } : {}
46101
+ };
46102
+ }
46103
+ async function defaultDetectProject(profile, dir) {
46104
+ for (const f of profile.build.detectFiles) {
46105
+ if (detectFileExists(dir, f))
46106
+ return true;
46107
+ }
46108
+ return false;
46109
+ }
46110
+ async function defaultSelectBuildCommand(profile, dir) {
46111
+ const sorted = [...profile.build.commands].sort((a, b) => b.priority - a.priority);
46112
+ for (const cmd of sorted) {
46113
+ if (cmd.detectFile && !detectFileExists(dir, cmd.detectFile))
46114
+ continue;
46115
+ const argv = tokenizeCommand(cmd.cmd);
46116
+ if (argv.length === 0)
46117
+ continue;
46118
+ if (!isCommandAvailable(argv[0]))
46119
+ continue;
46120
+ return {
46121
+ name: cmd.name,
46122
+ cmd: argv,
46123
+ cwd: dir,
46124
+ detectedVia: cmd.detectFile ?? `${profile.id} default`
46125
+ };
46126
+ }
46127
+ return null;
46128
+ }
46129
+ async function defaultTestFilesFor(profile, sourceFile, dir) {
46130
+ const ext = path31.extname(sourceFile);
46131
+ if (!profile.extensions.includes(ext))
46132
+ return [];
46133
+ const base = path31.basename(sourceFile, ext);
46134
+ const rel = path31.relative(dir, sourceFile);
46135
+ const relDir = path31.dirname(rel);
46136
+ const stripSrc = relDir.replace(/^src(\/|\\)/, "");
46137
+ const candidates = new Set;
46138
+ for (const tDir of ["tests", "test", "__tests__", "spec"]) {
46139
+ for (const suffix of ["", "_test", ".test", "_spec", ".spec"]) {
46140
+ candidates.add(path31.join(dir, tDir, stripSrc, `${base}${suffix}${ext}`));
46141
+ }
46142
+ }
46143
+ const existing = [];
46144
+ for (const c of candidates) {
46145
+ try {
46146
+ fs14.accessSync(c);
46147
+ existing.push(c);
46148
+ } catch {}
46149
+ }
46150
+ return existing;
46151
+ }
46152
+ function defaultExtractImports() {
46153
+ return [];
46154
+ }
46155
+ async function defaultSelectFramework() {
46156
+ return null;
46157
+ }
46158
+ async function defaultSelectEntryPoints() {
46159
+ return [];
46160
+ }
46161
+ function defaultBackendFor(profile) {
46162
+ return {
46163
+ ...profile,
46164
+ detectProject: (dir) => defaultDetectProject(profile, dir),
46165
+ selectTestFramework: (dir) => defaultSelectTestFramework(profile, dir),
46166
+ buildTestCommand: (framework, files, dir, opts) => defaultBuildTestCommand(profile, framework, files, dir, opts),
46167
+ parseTestOutput: (framework, stdout, stderr, exitCode) => defaultParseTestOutput(framework, stdout, stderr, exitCode),
46168
+ testFilesFor: (sourceFile, dir) => defaultTestFilesFor(profile, sourceFile, dir),
46169
+ extractImports: () => defaultExtractImports(),
46170
+ selectBuildCommand: (dir) => defaultSelectBuildCommand(profile, dir),
46171
+ selectFramework: () => defaultSelectFramework(),
46172
+ selectEntryPoints: () => defaultSelectEntryPoints()
46173
+ };
46174
+ }
46175
+ var init_default_backend = __esm(() => {
46176
+ init_discovery();
46177
+ });
46178
+
46179
+ // src/lang/backends/go.ts
46180
+ import * as fs15 from "fs";
46181
+ import * as path32 from "path";
46182
+ function extractImports(_sourceFile, source) {
46183
+ const out = new Set;
46184
+ IMPORT_REGEX_SINGLE.lastIndex = 0;
46185
+ let m = IMPORT_REGEX_SINGLE.exec(source);
46186
+ while (m !== null) {
46187
+ out.add(m[1]);
46188
+ m = IMPORT_REGEX_SINGLE.exec(source);
46189
+ }
46190
+ IMPORT_REGEX_GROUP.lastIndex = 0;
46191
+ m = IMPORT_REGEX_GROUP.exec(source);
46192
+ while (m !== null) {
46193
+ const block = m[1];
46194
+ IMPORT_REGEX_GROUP_LINE.lastIndex = 0;
46195
+ let inner = IMPORT_REGEX_GROUP_LINE.exec(block);
46196
+ while (inner !== null) {
46197
+ out.add(inner[1]);
46198
+ inner = IMPORT_REGEX_GROUP_LINE.exec(block);
46199
+ }
46200
+ m = IMPORT_REGEX_GROUP.exec(source);
46201
+ }
46202
+ return [...out];
46203
+ }
46204
+ async function selectFramework(dir) {
46205
+ let content;
46206
+ try {
46207
+ content = fs15.readFileSync(path32.join(dir, "go.mod"), "utf-8");
46208
+ } catch {
46209
+ return null;
46210
+ }
46211
+ const candidates = [
46212
+ ["github.com/gin-gonic/gin", "gin"],
46213
+ ["github.com/labstack/echo", "echo"],
46214
+ ["github.com/gofiber/fiber", "fiber"],
46215
+ ["github.com/gorilla/mux", "gorilla"],
46216
+ ["github.com/go-chi/chi", "chi"]
46217
+ ];
46218
+ for (const [pkg, name] of candidates) {
46219
+ if (content.includes(pkg)) {
46220
+ return { name, detectedVia: `go.mod require ${pkg}` };
46221
+ }
46222
+ }
46223
+ return null;
46224
+ }
46225
+ async function selectEntryPoints(dir) {
46226
+ const points = [];
46227
+ try {
46228
+ fs15.accessSync(path32.join(dir, "main.go"));
46229
+ points.push("main.go");
46230
+ } catch {}
46231
+ try {
46232
+ const cmdDir = path32.join(dir, "cmd");
46233
+ const subdirs = fs15.readdirSync(cmdDir, { withFileTypes: true }).filter((d) => d.isDirectory());
46234
+ for (const sub of subdirs) {
46235
+ const main = path32.join("cmd", sub.name, "main.go");
46236
+ try {
46237
+ fs15.accessSync(path32.join(dir, main));
46238
+ points.push(main);
46239
+ } catch {}
46240
+ }
46241
+ } catch {}
46242
+ return points;
46243
+ }
46244
+ function buildGoBackend() {
46245
+ const profile = LANGUAGE_REGISTRY.get(PROFILE_ID);
46246
+ if (!profile) {
46247
+ throw new Error("buildGoBackend: go profile not in LANGUAGE_REGISTRY. " + "profiles.ts must be imported before this backend.");
46248
+ }
46249
+ return {
46250
+ ...defaultBackendFor(profile),
46251
+ extractImports,
46252
+ selectFramework,
46253
+ selectEntryPoints
46254
+ };
46255
+ }
46256
+ var PROFILE_ID = "go", IMPORT_REGEX_SINGLE, IMPORT_REGEX_GROUP, IMPORT_REGEX_GROUP_LINE, _internals18;
46257
+ var init_go = __esm(() => {
46258
+ init_default_backend();
46259
+ init_profiles();
46260
+ IMPORT_REGEX_SINGLE = /^\s*import\s+(?:[a-zA-Z_.][a-zA-Z0-9_]*\s+)?"([^"]+)"/gm;
46261
+ IMPORT_REGEX_GROUP = /^\s*import\s*\(([\s\S]*?)\)/gm;
46262
+ IMPORT_REGEX_GROUP_LINE = /(?:[a-zA-Z_.][a-zA-Z0-9_]*\s+)?"([^"]+)"/g;
46263
+ _internals18 = { extractImports };
46264
+ });
46265
+
46266
+ // src/lang/backends/python.ts
46267
+ import * as fs16 from "fs";
46268
+ import * as path33 from "path";
46269
+ function parseImportTargets(rawTargets) {
46270
+ const cleaned = rawTargets.replace(/[()]/g, "").split(`
46271
+ `).map((line) => line.replace(/#.*$/, "").replace(/\\\s*$/, "")).join(" ");
46272
+ const out = [];
46273
+ for (const seg of cleaned.split(",")) {
46274
+ const trimmed = seg.trim();
46275
+ if (trimmed.length === 0)
46276
+ continue;
46277
+ const name = trimmed.split(/\s+as\s+/)[0].trim();
46278
+ if (/^[\w]+$/.test(name))
46279
+ out.push(name);
46280
+ }
46281
+ return out;
46282
+ }
46283
+ function extractImports2(_sourceFile, source) {
46284
+ const out = new Set;
46285
+ source = source.replace(/\\\r?\n[ \t]*/g, " ");
46286
+ IMPORT_REGEX_FROM_WITH_TARGETS.lastIndex = 0;
46287
+ let m = IMPORT_REGEX_FROM_WITH_TARGETS.exec(source);
46288
+ while (m !== null) {
46289
+ const fromClause = m[1];
46290
+ const targets = parseImportTargets(m[2]);
46291
+ const isPurelyRelative = fromClause.length > 0 && /^\.+$/.test(fromClause);
46292
+ if (isPurelyRelative && targets.length > 0) {
46293
+ for (const t of targets)
46294
+ out.add(`${fromClause}${t}`);
46295
+ } else if (fromClause.length > 0) {
46296
+ out.add(fromClause);
46297
+ }
46298
+ m = IMPORT_REGEX_FROM_WITH_TARGETS.exec(source);
46299
+ }
46300
+ IMPORT_REGEX_IMPORT.lastIndex = 0;
46301
+ m = IMPORT_REGEX_IMPORT.exec(source);
46302
+ while (m !== null) {
46303
+ const segments = m[1].split(",");
46304
+ for (const seg of segments) {
46305
+ const trimmed = seg.trim();
46306
+ if (trimmed.length === 0)
46307
+ continue;
46308
+ const mod = trimmed.split(/\s+as\s+/)[0].trim();
46309
+ if (/^[\w.]+$/.test(mod))
46310
+ out.add(mod);
46311
+ }
46312
+ m = IMPORT_REGEX_IMPORT.exec(source);
46313
+ }
46314
+ return [...out];
46315
+ }
46316
+ async function selectFramework2(dir) {
46317
+ const candidates = [
46318
+ ["django", "django"],
46319
+ ["flask", "flask"],
46320
+ ["fastapi", "fastapi"],
46321
+ ["starlette", "starlette"],
46322
+ ["tornado", "tornado"],
46323
+ ["aiohttp", "aiohttp"],
46324
+ ["bottle", "bottle"]
46325
+ ];
46326
+ for (const candidate of ["pyproject.toml", "requirements.txt", "setup.py"]) {
46327
+ try {
46328
+ const content = fs16.readFileSync(path33.join(dir, candidate), "utf-8");
46329
+ const lower = content.toLowerCase();
46330
+ for (const [pkg, name] of candidates) {
46331
+ if (lower.includes(pkg)) {
46332
+ return { name, detectedVia: candidate };
46333
+ }
46334
+ }
46335
+ } catch {}
46336
+ }
46337
+ return null;
46338
+ }
46339
+ async function selectEntryPoints2(dir) {
46340
+ const points = new Set;
46341
+ try {
46342
+ const content = fs16.readFileSync(path33.join(dir, "pyproject.toml"), "utf-8");
46343
+ const scriptsBlock = content.match(/\[project\.scripts\][\s\S]*?(?=\n\[|$)/);
46344
+ if (scriptsBlock) {
46345
+ for (const line of scriptsBlock[0].split(`
46346
+ `)) {
46347
+ const m = line.match(/=\s*['"]([^'":]+)/);
46348
+ if (m) {
46349
+ const modPath = `${m[1].replace(/\./g, "/")}.py`;
46350
+ points.add(modPath);
46351
+ }
46352
+ }
46353
+ }
46354
+ } catch {}
46355
+ for (const name of ["manage.py", "main.py", "app.py", "__main__.py"]) {
46356
+ try {
46357
+ fs16.accessSync(path33.join(dir, name));
46358
+ points.add(name);
46359
+ } catch {}
46360
+ }
46361
+ return [...points];
46362
+ }
46363
+ function buildPythonBackend() {
46364
+ const profile = LANGUAGE_REGISTRY.get(PROFILE_ID2);
46365
+ if (!profile) {
46366
+ throw new Error("buildPythonBackend: python profile not in LANGUAGE_REGISTRY. " + "profiles.ts must be imported before this backend.");
46367
+ }
46368
+ return {
46369
+ ...defaultBackendFor(profile),
46370
+ extractImports: extractImports2,
46371
+ selectFramework: selectFramework2,
46372
+ selectEntryPoints: selectEntryPoints2
46373
+ };
46374
+ }
46375
+ var PROFILE_ID2 = "python", IMPORT_REGEX_FROM_WITH_TARGETS, IMPORT_REGEX_IMPORT, _internals19;
46376
+ var init_python = __esm(() => {
46377
+ init_default_backend();
46378
+ init_profiles();
46379
+ IMPORT_REGEX_FROM_WITH_TARGETS = /^\s*from\s+(\.*[\w.]*)\s+import\s+(\([^)]*\)|[^\n#]+)/gm;
46380
+ IMPORT_REGEX_IMPORT = /^\s*import\s+([^\n#]+)/gm;
46381
+ _internals19 = { extractImports: extractImports2 };
46382
+ });
46383
+
45585
46384
  // src/test-impact/analyzer.ts
45586
- import fs14 from "fs";
45587
- import path31 from "path";
46385
+ import fs17 from "fs";
46386
+ import path34 from "path";
45588
46387
  function normalizePath(p) {
45589
46388
  return p.replace(/\\/g, "/");
45590
46389
  }
45591
46390
  function isCacheStale(impactMap, generatedAtMs) {
45592
46391
  for (const sourcePath of Object.keys(impactMap)) {
45593
46392
  try {
45594
- const stat3 = fs14.statSync(sourcePath);
46393
+ const stat3 = fs17.statSync(sourcePath);
45595
46394
  if (stat3.mtimeMs > generatedAtMs) {
45596
46395
  return true;
45597
46396
  }
@@ -45605,21 +46404,108 @@ function resolveRelativeImport(fromDir, importPath) {
45605
46404
  if (!importPath.startsWith(".")) {
45606
46405
  return null;
45607
46406
  }
45608
- const resolved = path31.resolve(fromDir, importPath);
45609
- if (path31.extname(resolved)) {
45610
- if (fs14.existsSync(resolved) && fs14.statSync(resolved).isFile()) {
46407
+ const resolved = path34.resolve(fromDir, importPath);
46408
+ if (path34.extname(resolved)) {
46409
+ if (fs17.existsSync(resolved) && fs17.statSync(resolved).isFile()) {
45611
46410
  return normalizePath(resolved);
45612
46411
  }
45613
46412
  } else {
45614
46413
  for (const ext of EXTENSIONS_TO_TRY) {
45615
46414
  const withExt = resolved + ext;
45616
- if (fs14.existsSync(withExt) && fs14.statSync(withExt).isFile()) {
46415
+ if (fs17.existsSync(withExt) && fs17.statSync(withExt).isFile()) {
45617
46416
  return normalizePath(withExt);
45618
46417
  }
45619
46418
  }
45620
46419
  }
45621
46420
  return null;
45622
46421
  }
46422
+ function resolvePythonImport(fromDir, module) {
46423
+ if (!module.startsWith("."))
46424
+ return null;
46425
+ const leadingDots = module.match(/^\.+/)?.[0].length ?? 0;
46426
+ let baseDir = fromDir;
46427
+ for (let i = 1;i < leadingDots; i++) {
46428
+ baseDir = path34.dirname(baseDir);
46429
+ }
46430
+ const rest = module.slice(leadingDots);
46431
+ if (rest.length === 0) {
46432
+ const initPath = path34.join(baseDir, "__init__.py");
46433
+ if (fs17.existsSync(initPath) && fs17.statSync(initPath).isFile()) {
46434
+ return normalizePath(initPath);
46435
+ }
46436
+ return null;
46437
+ }
46438
+ const subpath = rest.replace(/\./g, path34.sep);
46439
+ const candidates = [
46440
+ `${path34.join(baseDir, subpath)}.py`,
46441
+ path34.join(baseDir, subpath, "__init__.py")
46442
+ ];
46443
+ for (const c of candidates) {
46444
+ if (fs17.existsSync(c) && fs17.statSync(c).isFile())
46445
+ return normalizePath(c);
46446
+ }
46447
+ return null;
46448
+ }
46449
+ function findGoModule(fromDir) {
46450
+ const resolved = path34.resolve(fromDir);
46451
+ let cur = resolved;
46452
+ const walked = [];
46453
+ for (let i = 0;i < 16; i++) {
46454
+ const cached3 = goModuleCache.get(cur);
46455
+ if (cached3 !== undefined) {
46456
+ for (const d of walked)
46457
+ goModuleCache.set(d, cached3);
46458
+ return cached3;
46459
+ }
46460
+ walked.push(cur);
46461
+ try {
46462
+ const goMod = path34.join(cur, "go.mod");
46463
+ const content = fs17.readFileSync(goMod, "utf-8");
46464
+ const moduleMatch = content.match(/^\s*module\s+"?([^"\s/]+(?:\/[^"\s]+)*)"?/m);
46465
+ if (moduleMatch) {
46466
+ const result = { moduleRoot: cur, modulePath: moduleMatch[1] };
46467
+ for (const d of walked)
46468
+ goModuleCache.set(d, result);
46469
+ return result;
46470
+ }
46471
+ } catch {}
46472
+ try {
46473
+ fs17.accessSync(path34.join(cur, ".git"));
46474
+ break;
46475
+ } catch {}
46476
+ const parent = path34.dirname(cur);
46477
+ if (parent === cur)
46478
+ break;
46479
+ cur = parent;
46480
+ }
46481
+ for (const d of walked)
46482
+ goModuleCache.set(d, null);
46483
+ return null;
46484
+ }
46485
+ function resolveGoImport(fromDir, importPath) {
46486
+ let dir = null;
46487
+ if (importPath.startsWith(".")) {
46488
+ dir = path34.resolve(fromDir, importPath);
46489
+ } else {
46490
+ const mod = findGoModule(fromDir);
46491
+ if (mod && (importPath === mod.modulePath || importPath.startsWith(`${mod.modulePath}/`))) {
46492
+ const subpath = importPath.slice(mod.modulePath.length);
46493
+ dir = path34.join(mod.moduleRoot, subpath);
46494
+ }
46495
+ }
46496
+ if (dir === null)
46497
+ return [];
46498
+ if (!fs17.existsSync(dir) || !fs17.statSync(dir).isDirectory())
46499
+ return [];
46500
+ try {
46501
+ return fs17.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath(path34.join(dir, f)));
46502
+ } catch {
46503
+ return [];
46504
+ }
46505
+ }
46506
+ function _clearGoModuleCache() {
46507
+ goModuleCache.clear();
46508
+ }
45623
46509
  function findTestFilesSync(cwd) {
45624
46510
  const testFiles = [];
45625
46511
  const skipDirs = new Set([
@@ -45632,13 +46518,13 @@ function findTestFilesSync(cwd) {
45632
46518
  function walk(dir, visitedInodes) {
45633
46519
  let entries;
45634
46520
  try {
45635
- entries = fs14.readdirSync(dir, { withFileTypes: true });
46521
+ entries = fs17.readdirSync(dir, { withFileTypes: true });
45636
46522
  } catch {
45637
46523
  return;
45638
46524
  }
45639
46525
  let dirInode;
45640
46526
  try {
45641
- dirInode = fs14.statSync(dir).ino;
46527
+ dirInode = fs17.statSync(dir).ino;
45642
46528
  } catch {
45643
46529
  return;
45644
46530
  }
@@ -45651,12 +46537,15 @@ function findTestFilesSync(cwd) {
45651
46537
  for (const entry of entries) {
45652
46538
  if (entry.isDirectory()) {
45653
46539
  if (!skipDirs.has(entry.name)) {
45654
- walk(path31.join(dir, entry.name), visitedInodes);
46540
+ walk(path34.join(dir, entry.name), visitedInodes);
45655
46541
  }
45656
46542
  } else if (entry.isFile()) {
45657
46543
  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)));
46544
+ const isTsTest = /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name);
46545
+ const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${path34.sep}tests${path34.sep}`) && name.endsWith(".py");
46546
+ const isGoTest = /.+_test\.go$/.test(name);
46547
+ if (isTsTest || isPyTest || isGoTest) {
46548
+ testFiles.push(normalizePath(path34.join(dir, entry.name)));
45660
46549
  }
45661
46550
  }
45662
46551
  }
@@ -45664,7 +46553,7 @@ function findTestFilesSync(cwd) {
45664
46553
  walk(cwd, new Set);
45665
46554
  return [...new Set(testFiles)];
45666
46555
  }
45667
- function extractImports(content) {
46556
+ function extractImports3(content) {
45668
46557
  function execRegex(regex, content2) {
45669
46558
  const results = [];
45670
46559
  regex.lastIndex = 0;
@@ -45680,68 +46569,93 @@ function extractImports(content) {
45680
46569
  ...execRegex(IMPORT_REGEX_REEXPORT, content)
45681
46570
  ];
45682
46571
  }
46572
+ function addImpactEdgesForTestFile(testFile, content, impactMap) {
46573
+ const ext = path34.extname(testFile).toLowerCase();
46574
+ const testDir = path34.dirname(testFile);
46575
+ function addEdge(source) {
46576
+ if (!impactMap[source])
46577
+ impactMap[source] = [];
46578
+ if (!impactMap[source].includes(testFile)) {
46579
+ impactMap[source].push(testFile);
46580
+ }
46581
+ }
46582
+ if (TS_EXTENSIONS.has(ext)) {
46583
+ const imports = extractImports3(content);
46584
+ for (const importPath of imports) {
46585
+ const resolved = resolveRelativeImport(testDir, importPath);
46586
+ if (resolved !== null)
46587
+ addEdge(resolved);
46588
+ }
46589
+ return;
46590
+ }
46591
+ if (PYTHON_EXTENSIONS.has(ext)) {
46592
+ const modules = _internals19.extractImports(testFile, content);
46593
+ for (const mod of modules) {
46594
+ const resolved = resolvePythonImport(testDir, mod);
46595
+ if (resolved !== null)
46596
+ addEdge(resolved);
46597
+ }
46598
+ return;
46599
+ }
46600
+ if (GO_EXTENSIONS.has(ext)) {
46601
+ const imports = _internals18.extractImports(testFile, content);
46602
+ for (const importPath of imports) {
46603
+ const sourceFiles = resolveGoImport(testDir, importPath);
46604
+ for (const source of sourceFiles)
46605
+ addEdge(source);
46606
+ }
46607
+ return;
46608
+ }
46609
+ }
45683
46610
  async function buildImpactMapInternal(cwd) {
45684
46611
  const testFiles = findTestFilesSync(cwd);
45685
46612
  const impactMap = {};
45686
46613
  for (const testFile of testFiles) {
45687
46614
  let content;
45688
46615
  try {
45689
- content = fs14.readFileSync(testFile, "utf-8");
46616
+ content = fs17.readFileSync(testFile, "utf-8");
45690
46617
  } catch {
45691
46618
  continue;
45692
46619
  }
45693
46620
  if (content.substring(0, 8192).includes("\x00")) {
45694
46621
  continue;
45695
46622
  }
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
- }
46623
+ addImpactEdgesForTestFile(testFile, content, impactMap);
45710
46624
  }
45711
46625
  return impactMap;
45712
46626
  }
45713
46627
  async function buildImpactMap(cwd) {
45714
- const impactMap = await _internals18.buildImpactMapInternal(cwd);
45715
- await _internals18.saveImpactMap(cwd, impactMap);
46628
+ const impactMap = await _internals20.buildImpactMapInternal(cwd);
46629
+ await _internals20.saveImpactMap(cwd, impactMap);
45716
46630
  return impactMap;
45717
46631
  }
45718
46632
  async function loadImpactMap(cwd) {
45719
- const cachePath = path31.join(cwd, ".swarm", "cache", "impact-map.json");
45720
- if (fs14.existsSync(cachePath)) {
46633
+ const cachePath = path34.join(cwd, ".swarm", "cache", "impact-map.json");
46634
+ if (fs17.existsSync(cachePath)) {
45721
46635
  try {
45722
- const content = fs14.readFileSync(cachePath, "utf-8");
46636
+ const content = fs17.readFileSync(cachePath, "utf-8");
45723
46637
  const data = JSON.parse(content);
45724
46638
  const map3 = data.map;
45725
46639
  const generatedAt = new Date(data.generatedAt).getTime();
45726
- if (!_internals18.isCacheStale(map3, generatedAt)) {
46640
+ if (!_internals20.isCacheStale(map3, generatedAt)) {
45727
46641
  return map3;
45728
46642
  }
45729
46643
  } catch {}
45730
46644
  }
45731
- return _internals18.buildImpactMap(cwd);
46645
+ return _internals20.buildImpactMap(cwd);
45732
46646
  }
45733
46647
  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 });
46648
+ const cacheDir2 = path34.join(cwd, ".swarm", "cache");
46649
+ const cachePath = path34.join(cacheDir2, "impact-map.json");
46650
+ if (!fs17.existsSync(cacheDir2)) {
46651
+ fs17.mkdirSync(cacheDir2, { recursive: true });
45738
46652
  }
45739
46653
  const data = {
45740
46654
  generatedAt: new Date().toISOString(),
45741
46655
  fileCount: Object.keys(impactMap).length,
45742
46656
  map: impactMap
45743
46657
  };
45744
- fs14.writeFileSync(cachePath, JSON.stringify(data, null, 2), "utf-8");
46658
+ fs17.writeFileSync(cachePath, JSON.stringify(data, null, 2), "utf-8");
45745
46659
  }
45746
46660
  async function analyzeImpact(changedFiles, cwd) {
45747
46661
  if (!Array.isArray(changedFiles)) {
@@ -45754,11 +46668,11 @@ async function analyzeImpact(changedFiles, cwd) {
45754
46668
  };
45755
46669
  }
45756
46670
  const validFiles = changedFiles.filter((f) => typeof f === "string" && f.length > 0 && !f.includes("\x00"));
45757
- const impactMap = await _internals18.loadImpactMap(cwd);
46671
+ const impactMap = await _internals20.loadImpactMap(cwd);
45758
46672
  const impactedTestsSet = new Set;
45759
46673
  const untestedFiles = [];
45760
46674
  for (const changedFile of validFiles) {
45761
- const normalizedChanged = normalizePath(path31.resolve(changedFile));
46675
+ const normalizedChanged = normalizePath(path34.resolve(changedFile));
45762
46676
  const tests = impactMap[normalizedChanged];
45763
46677
  if (tests && tests.length > 0) {
45764
46678
  for (const test of tests) {
@@ -45795,23 +46709,30 @@ async function analyzeImpact(changedFiles, cwd) {
45795
46709
  impactMap
45796
46710
  };
45797
46711
  }
45798
- var IMPORT_REGEX_ES, IMPORT_REGEX_REQUIRE, IMPORT_REGEX_REEXPORT, EXTENSIONS_TO_TRY, _internals18;
46712
+ var IMPORT_REGEX_ES, IMPORT_REGEX_REQUIRE, IMPORT_REGEX_REEXPORT, TS_EXTENSIONS, PYTHON_EXTENSIONS, GO_EXTENSIONS, EXTENSIONS_TO_TRY, goModuleCache, _internals20;
45799
46713
  var init_analyzer = __esm(() => {
45800
- IMPORT_REGEX_ES = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
46714
+ init_go();
46715
+ init_python();
46716
+ IMPORT_REGEX_ES = /import\s+[\s\S]*?\s+from\s+['"]([^'"]+)['"]/g;
45801
46717
  IMPORT_REGEX_REQUIRE = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
45802
46718
  IMPORT_REGEX_REEXPORT = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
46719
+ TS_EXTENSIONS = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"]);
46720
+ PYTHON_EXTENSIONS = new Set([".py"]);
46721
+ GO_EXTENSIONS = new Set([".go"]);
45803
46722
  EXTENSIONS_TO_TRY = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
45804
- _internals18 = {
46723
+ goModuleCache = new Map;
46724
+ _internals20 = {
45805
46725
  normalizePath,
45806
46726
  isCacheStale,
45807
46727
  resolveRelativeImport,
45808
46728
  findTestFilesSync,
45809
- extractImports,
46729
+ extractImports: extractImports3,
45810
46730
  buildImpactMapInternal,
45811
46731
  buildImpactMap,
45812
46732
  loadImpactMap,
45813
46733
  saveImpactMap,
45814
- analyzeImpact
46734
+ analyzeImpact,
46735
+ _clearGoModuleCache
45815
46736
  };
45816
46737
  });
45817
46738
 
@@ -46021,10 +46942,10 @@ function detectFlakyTests(allHistory) {
46021
46942
  var FLAKY_THRESHOLD = 0.3, MIN_RUNS_FOR_QUARANTINE = 5, MAX_HISTORY_RUNS = 20;
46022
46943
 
46023
46944
  // src/test-impact/history-store.ts
46024
- import fs15 from "fs";
46025
- import path32 from "path";
46945
+ import fs18 from "fs";
46946
+ import path35 from "path";
46026
46947
  function getHistoryPath(workingDir) {
46027
- return path32.join(workingDir || process.cwd(), ".swarm", "cache", "test-history.jsonl");
46948
+ return path35.join(workingDir || process.cwd(), ".swarm", "cache", "test-history.jsonl");
46028
46949
  }
46029
46950
  function sanitizeErrorMessage(errorMessage) {
46030
46951
  if (errorMessage === undefined) {
@@ -46079,9 +47000,9 @@ function appendTestRun(record3, workingDir) {
46079
47000
  changedFiles: sanitizeChangedFiles(record3.changedFiles || [])
46080
47001
  };
46081
47002
  const historyPath = getHistoryPath(workingDir);
46082
- const historyDir = path32.dirname(historyPath);
46083
- if (!fs15.existsSync(historyDir)) {
46084
- fs15.mkdirSync(historyDir, { recursive: true });
47003
+ const historyDir = path35.dirname(historyPath);
47004
+ if (!fs18.existsSync(historyDir)) {
47005
+ fs18.mkdirSync(historyDir, { recursive: true });
46085
47006
  }
46086
47007
  const existingRecords = readAllRecords(historyPath);
46087
47008
  existingRecords.push(sanitizedRecord);
@@ -46106,24 +47027,24 @@ function appendTestRun(record3, workingDir) {
46106
47027
  `)}
46107
47028
  `;
46108
47029
  const tempPath = `${historyPath}.tmp`;
46109
- fs15.writeFileSync(tempPath, content, "utf-8");
46110
- fs15.renameSync(tempPath, historyPath);
47030
+ fs18.writeFileSync(tempPath, content, "utf-8");
47031
+ fs18.renameSync(tempPath, historyPath);
46111
47032
  } catch (err) {
46112
47033
  try {
46113
47034
  const tempPath = `${historyPath}.tmp`;
46114
- if (fs15.existsSync(tempPath)) {
46115
- fs15.unlinkSync(tempPath);
47035
+ if (fs18.existsSync(tempPath)) {
47036
+ fs18.unlinkSync(tempPath);
46116
47037
  }
46117
47038
  } catch {}
46118
47039
  throw new Error(`Failed to write test history: ${err instanceof Error ? err.message : String(err)}`);
46119
47040
  }
46120
47041
  }
46121
47042
  function readAllRecords(historyPath) {
46122
- if (!fs15.existsSync(historyPath)) {
47043
+ if (!fs18.existsSync(historyPath)) {
46123
47044
  return [];
46124
47045
  }
46125
47046
  try {
46126
- const content = fs15.readFileSync(historyPath, "utf-8");
47047
+ const content = fs18.readFileSync(historyPath, "utf-8");
46127
47048
  const lines = content.split(`
46128
47049
  `);
46129
47050
  const records = [];
@@ -46160,8 +47081,8 @@ var init_history_store = __esm(() => {
46160
47081
  });
46161
47082
 
46162
47083
  // src/tools/resolve-working-directory.ts
46163
- import * as fs16 from "fs";
46164
- import * as path33 from "path";
47084
+ import * as fs19 from "fs";
47085
+ import * as path36 from "path";
46165
47086
  function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
46166
47087
  if (workingDirectory == null || workingDirectory === "") {
46167
47088
  return { success: true, directory: fallbackDirectory };
@@ -46181,18 +47102,18 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
46181
47102
  };
46182
47103
  }
46183
47104
  }
46184
- const normalizedDir = path33.normalize(workingDirectory);
46185
- const pathParts = normalizedDir.split(path33.sep);
47105
+ const normalizedDir = path36.normalize(workingDirectory);
47106
+ const pathParts = normalizedDir.split(path36.sep);
46186
47107
  if (pathParts.includes("..")) {
46187
47108
  return {
46188
47109
  success: false,
46189
47110
  message: "Invalid working_directory: path traversal sequences (..) are not allowed"
46190
47111
  };
46191
47112
  }
46192
- const resolvedDir = path33.resolve(normalizedDir);
47113
+ const resolvedDir = path36.resolve(normalizedDir);
46193
47114
  let statResult;
46194
47115
  try {
46195
- statResult = fs16.statSync(resolvedDir);
47116
+ statResult = fs19.statSync(resolvedDir);
46196
47117
  } catch {
46197
47118
  return {
46198
47119
  success: false,
@@ -46205,17 +47126,17 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
46205
47126
  message: `Invalid working_directory: path "${resolvedDir}" is not a directory`
46206
47127
  };
46207
47128
  }
46208
- const resolvedFallback = path33.resolve(fallbackDirectory);
47129
+ const resolvedFallback = path36.resolve(fallbackDirectory);
46209
47130
  let fallbackExists = false;
46210
47131
  try {
46211
- fs16.statSync(resolvedFallback);
47132
+ fs19.statSync(resolvedFallback);
46212
47133
  fallbackExists = true;
46213
47134
  } catch {
46214
47135
  fallbackExists = false;
46215
47136
  }
46216
47137
  if (workingDirectory != null && workingDirectory !== "") {
46217
47138
  if (fallbackExists) {
46218
- const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path33.sep);
47139
+ const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path36.sep);
46219
47140
  if (isSubdirectory) {
46220
47141
  return {
46221
47142
  success: false,
@@ -46235,9 +47156,418 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
46235
47156
  }
46236
47157
  var init_resolve_working_directory = () => {};
46237
47158
 
47159
+ // src/lang/registry-backend.ts
47160
+ class LanguageBackendRegistry {
47161
+ backends = new Map;
47162
+ register(backend) {
47163
+ const existing = this.backends.get(backend.id);
47164
+ if (existing && existing !== backend) {
47165
+ throw new Error(`LanguageBackendRegistry: backend id "${backend.id}" registered twice. ` + `Each LanguageBackend.id must be unique.`);
47166
+ }
47167
+ this.backends.set(backend.id, backend);
47168
+ }
47169
+ get(id) {
47170
+ return this.backends.get(id);
47171
+ }
47172
+ getOrDefault(id) {
47173
+ const registered = this.backends.get(id);
47174
+ if (registered)
47175
+ return registered;
47176
+ const profile = LANGUAGE_REGISTRY.get(id);
47177
+ if (!profile)
47178
+ return;
47179
+ return defaultBackendFor(profile);
47180
+ }
47181
+ unregister(id) {
47182
+ this.backends.delete(id);
47183
+ }
47184
+ }
47185
+ var LANGUAGE_BACKEND_REGISTRY;
47186
+ var init_registry_backend = __esm(() => {
47187
+ init_default_backend();
47188
+ init_profiles();
47189
+ LANGUAGE_BACKEND_REGISTRY = new LanguageBackendRegistry;
47190
+ });
47191
+
47192
+ // src/lang/backends/typescript.ts
47193
+ import * as fs20 from "fs";
47194
+ import * as path37 from "path";
47195
+ function readPackageJsonRaw(dir) {
47196
+ try {
47197
+ const content = fs20.readFileSync(path37.join(dir, "package.json"), "utf-8");
47198
+ return JSON.parse(content);
47199
+ } catch {
47200
+ return null;
47201
+ }
47202
+ }
47203
+ function readPackageJson(dir) {
47204
+ return _internals21.readPackageJsonRaw(dir);
47205
+ }
47206
+ function readPackageJsonTestScript(dir) {
47207
+ return readPackageJson(dir)?.scripts?.test ?? null;
47208
+ }
47209
+ function frameworkFromScriptsTest(script) {
47210
+ if (script.includes("vitest"))
47211
+ return "vitest";
47212
+ if (script.includes("jest"))
47213
+ return "jest";
47214
+ if (script.includes("mocha"))
47215
+ return "mocha";
47216
+ if (script.includes("bun test"))
47217
+ return "bun:test";
47218
+ return null;
47219
+ }
47220
+ function frameworkFromDevDeps(devDeps) {
47221
+ if (!devDeps)
47222
+ return null;
47223
+ if (devDeps.vitest || devDeps["@vitest/ui"])
47224
+ return "vitest";
47225
+ if (devDeps.jest || devDeps["@types/jest"])
47226
+ return "jest";
47227
+ if (devDeps.mocha || devDeps["@types/mocha"])
47228
+ return "mocha";
47229
+ return null;
47230
+ }
47231
+ function selectionFromFramework(profile, fwName, dir, detectedVia) {
47232
+ const fw = profile.test.frameworks.find((f) => f.name === fwName);
47233
+ if (!fw)
47234
+ return null;
47235
+ const argv = tokenizeCommand(fw.cmd);
47236
+ if (argv.length === 0)
47237
+ return null;
47238
+ return {
47239
+ name: fw.name,
47240
+ cmd: argv,
47241
+ cwd: dir,
47242
+ detectedVia,
47243
+ filesIgnored: false
47244
+ };
47245
+ }
47246
+ async function selectTestFramework(dir) {
47247
+ const profile = LANGUAGE_REGISTRY.get(PROFILE_ID3);
47248
+ if (!profile)
47249
+ return null;
47250
+ const pkg = readPackageJson(dir);
47251
+ const script = pkg?.scripts?.test;
47252
+ if (script) {
47253
+ const fwName = frameworkFromScriptsTest(script);
47254
+ if (fwName) {
47255
+ const sel = selectionFromFramework(profile, fwName, dir, "package.json#scripts.test");
47256
+ if (sel)
47257
+ return sel;
47258
+ }
47259
+ }
47260
+ const devDepsFw = frameworkFromDevDeps(pkg?.devDependencies);
47261
+ if (devDepsFw) {
47262
+ const sel = selectionFromFramework(profile, devDepsFw, dir, "package.json#devDependencies");
47263
+ if (sel)
47264
+ return sel;
47265
+ }
47266
+ return defaultSelectTestFramework(profile, dir);
47267
+ }
47268
+ function buildTestCommand(framework, files, dir, opts) {
47269
+ const profile = LANGUAGE_REGISTRY.get(PROFILE_ID3);
47270
+ if (!profile)
47271
+ return null;
47272
+ return defaultBuildTestCommand(profile, framework, files, dir, opts);
47273
+ }
47274
+ function parseTestOutput(framework, stdout, stderr, exitCode) {
47275
+ return defaultParseTestOutput(framework, stdout, stderr, exitCode);
47276
+ }
47277
+ async function selectFramework3(dir) {
47278
+ const pkg = readPackageJson(dir);
47279
+ if (!pkg)
47280
+ return null;
47281
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
47282
+ const order = [
47283
+ ["next", "next"],
47284
+ ["nuxt", "nuxt"],
47285
+ ["@angular/core", "angular"],
47286
+ ["svelte", "svelte"],
47287
+ ["react", "react"],
47288
+ ["vue", "vue"],
47289
+ ["express", "express"],
47290
+ ["fastify", "fastify"],
47291
+ ["@nestjs/core", "nestjs"]
47292
+ ];
47293
+ for (const [pkgName, displayName] of order) {
47294
+ if (deps[pkgName]) {
47295
+ return {
47296
+ name: displayName,
47297
+ detectedVia: `package.json#dependencies.${pkgName}`
47298
+ };
47299
+ }
47300
+ }
47301
+ return null;
47302
+ }
47303
+ async function selectEntryPoints3(dir) {
47304
+ const pkg = readPackageJson(dir);
47305
+ if (!pkg)
47306
+ return [];
47307
+ const points = [];
47308
+ const obj = pkg;
47309
+ if (obj.bin) {
47310
+ if (typeof obj.bin === "string")
47311
+ points.push(obj.bin);
47312
+ else
47313
+ for (const v of Object.values(obj.bin))
47314
+ points.push(v);
47315
+ }
47316
+ if (obj.main)
47317
+ points.push(obj.main);
47318
+ if (obj.module && obj.module !== obj.main)
47319
+ points.push(obj.module);
47320
+ if (obj.exports && typeof obj.exports === "object") {
47321
+ const root = obj.exports["."];
47322
+ if (typeof root === "string" && !points.includes(root))
47323
+ points.push(root);
47324
+ }
47325
+ return [...new Set(points.filter((p) => p.length > 0))];
47326
+ }
47327
+ function extractImports4(_sourceFile, source) {
47328
+ const out = new Set;
47329
+ for (const re of [
47330
+ IMPORT_REGEX_ES2,
47331
+ IMPORT_REGEX_BARE,
47332
+ IMPORT_REGEX_REQUIRE2,
47333
+ IMPORT_REGEX_DYNAMIC,
47334
+ IMPORT_REGEX_REEXPORT2
47335
+ ]) {
47336
+ re.lastIndex = 0;
47337
+ let m = re.exec(source);
47338
+ while (m !== null) {
47339
+ out.add(m[1]);
47340
+ m = re.exec(source);
47341
+ }
47342
+ }
47343
+ return [...out];
47344
+ }
47345
+ async function selectBuildCommand(dir) {
47346
+ const profile = LANGUAGE_REGISTRY.get(PROFILE_ID3);
47347
+ if (!profile)
47348
+ return null;
47349
+ return defaultSelectBuildCommand(profile, dir);
47350
+ }
47351
+ async function testFilesFor(sourceFile, dir) {
47352
+ const profile = LANGUAGE_REGISTRY.get(PROFILE_ID3);
47353
+ if (!profile)
47354
+ return [];
47355
+ return defaultTestFilesFor(profile, sourceFile, dir);
47356
+ }
47357
+ function buildTypescriptBackend() {
47358
+ const profile = LANGUAGE_REGISTRY.get(PROFILE_ID3);
47359
+ if (!profile) {
47360
+ throw new Error("buildTypescriptBackend: typescript profile not in LANGUAGE_REGISTRY. " + "profiles.ts must be imported before this backend.");
47361
+ }
47362
+ return {
47363
+ ...profile,
47364
+ selectTestFramework,
47365
+ buildTestCommand,
47366
+ parseTestOutput,
47367
+ extractImports: extractImports4,
47368
+ selectBuildCommand,
47369
+ testFilesFor,
47370
+ selectFramework: selectFramework3,
47371
+ selectEntryPoints: selectEntryPoints3
47372
+ };
47373
+ }
47374
+ var PROFILE_ID3 = "typescript", IMPORT_REGEX_ES2, IMPORT_REGEX_BARE, IMPORT_REGEX_REQUIRE2, IMPORT_REGEX_DYNAMIC, IMPORT_REGEX_REEXPORT2, _internals21;
47375
+ var init_typescript = __esm(() => {
47376
+ init_default_backend();
47377
+ init_profiles();
47378
+ IMPORT_REGEX_ES2 = /import\s+[\s\S]*?\s+from\s+['"]([^'"]+)['"]/g;
47379
+ IMPORT_REGEX_BARE = /import\s+['"]([^'"]+)['"]/g;
47380
+ IMPORT_REGEX_REQUIRE2 = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
47381
+ IMPORT_REGEX_DYNAMIC = /import\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
47382
+ IMPORT_REGEX_REEXPORT2 = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
47383
+ _internals21 = {
47384
+ readPackageJsonRaw,
47385
+ readPackageJsonTestScript,
47386
+ frameworkFromScriptsTest
47387
+ };
47388
+ });
47389
+
47390
+ // src/lang/backends/index.ts
47391
+ function registerAllBackends() {
47392
+ if (registered)
47393
+ return;
47394
+ LANGUAGE_BACKEND_REGISTRY.register(buildTypescriptBackend());
47395
+ LANGUAGE_BACKEND_REGISTRY.register(buildPythonBackend());
47396
+ LANGUAGE_BACKEND_REGISTRY.register(buildGoBackend());
47397
+ registered = true;
47398
+ }
47399
+ var registered = false;
47400
+ var init_backends = __esm(() => {
47401
+ init_registry_backend();
47402
+ init_go();
47403
+ init_python();
47404
+ init_typescript();
47405
+ registerAllBackends();
47406
+ });
47407
+
47408
+ // src/lang/dispatch.ts
47409
+ var exports_dispatch = {};
47410
+ __export(exports_dispatch, {
47411
+ pickedProfiles: () => pickedProfiles,
47412
+ pickBackend: () => pickBackend,
47413
+ clearDispatchCache: () => clearDispatchCache,
47414
+ _internals: () => _internals22
47415
+ });
47416
+ import * as fs21 from "fs";
47417
+ import * as path38 from "path";
47418
+ function safeReaddirSet(dir) {
47419
+ try {
47420
+ return new Set(fs21.readdirSync(dir));
47421
+ } catch {
47422
+ return new Set;
47423
+ }
47424
+ }
47425
+ function manifestHash(dir) {
47426
+ const entries = safeReaddirSet(dir);
47427
+ if (entries.size === 0)
47428
+ return "";
47429
+ const parts = [];
47430
+ for (const name of MANIFEST_FILES) {
47431
+ if (!entries.has(name))
47432
+ continue;
47433
+ try {
47434
+ const stat3 = fs21.statSync(path38.join(dir, name));
47435
+ parts.push(`${name}:${stat3.size}:${stat3.mtimeMs}:${stat3.ino}`);
47436
+ } catch {}
47437
+ }
47438
+ return parts.join("|");
47439
+ }
47440
+ function findManifestRoot(start) {
47441
+ const resolved = path38.resolve(start);
47442
+ const cached3 = manifestRootCache.get(resolved);
47443
+ if (cached3 !== undefined)
47444
+ return cached3;
47445
+ let cur = resolved;
47446
+ for (let i = 0;i < 32; i++) {
47447
+ const entries = safeReaddirSet(cur);
47448
+ if (entries.size > 0) {
47449
+ for (const name of MANIFEST_FILES) {
47450
+ if (entries.has(name)) {
47451
+ manifestRootCache.set(resolved, cur);
47452
+ return cur;
47453
+ }
47454
+ }
47455
+ if (entries.has(".git")) {
47456
+ manifestRootCache.set(resolved, cur);
47457
+ return cur;
47458
+ }
47459
+ }
47460
+ const parent = path38.dirname(cur);
47461
+ if (parent === cur)
47462
+ break;
47463
+ cur = parent;
47464
+ }
47465
+ manifestRootCache.set(resolved, start);
47466
+ return start;
47467
+ }
47468
+ function evictIfNeeded() {
47469
+ if (cache.size <= _internals22.cacheCapacity)
47470
+ return;
47471
+ let oldestKey;
47472
+ let oldestOrder = Infinity;
47473
+ for (const [k, v] of cache.entries()) {
47474
+ if (v.insertOrder < oldestOrder) {
47475
+ oldestOrder = v.insertOrder;
47476
+ oldestKey = k;
47477
+ }
47478
+ }
47479
+ if (oldestKey !== undefined)
47480
+ cache.delete(oldestKey);
47481
+ }
47482
+ async function pickBackend(dir) {
47483
+ const root = findManifestRoot(dir);
47484
+ const hash3 = manifestHash(root);
47485
+ const cacheKey = root;
47486
+ const cached3 = cache.get(cacheKey);
47487
+ if (cached3 && cached3.hash === hash3) {
47488
+ return cached3.backend;
47489
+ }
47490
+ if (hash3 === "") {
47491
+ cache.set(cacheKey, {
47492
+ hash: hash3,
47493
+ backend: null,
47494
+ profiles: [],
47495
+ insertOrder: insertCounter++
47496
+ });
47497
+ evictIfNeeded();
47498
+ return null;
47499
+ }
47500
+ const profiles = await _internals22.detectProjectLanguages(root);
47501
+ if (profiles.length === 0) {
47502
+ cache.set(cacheKey, {
47503
+ hash: hash3,
47504
+ backend: null,
47505
+ profiles: [],
47506
+ insertOrder: insertCounter++
47507
+ });
47508
+ evictIfNeeded();
47509
+ return null;
47510
+ }
47511
+ const winner = profiles[0];
47512
+ const backend = LANGUAGE_BACKEND_REGISTRY.getOrDefault(winner.id) ?? null;
47513
+ cache.set(cacheKey, {
47514
+ hash: hash3,
47515
+ backend,
47516
+ profiles: profiles.map((p) => ({ id: p.id })),
47517
+ insertOrder: insertCounter++
47518
+ });
47519
+ evictIfNeeded();
47520
+ return backend;
47521
+ }
47522
+ function pickedProfiles(dir) {
47523
+ const root = findManifestRoot(dir);
47524
+ const cached3 = cache.get(root);
47525
+ return cached3?.profiles ?? [];
47526
+ }
47527
+ function clearDispatchCache() {
47528
+ cache.clear();
47529
+ manifestRootCache.clear();
47530
+ insertCounter = 0;
47531
+ }
47532
+ var _internals22, cache, insertCounter = 0, MANIFEST_FILES, _MANIFEST_SET, manifestRootCache;
47533
+ var init_dispatch = __esm(() => {
47534
+ init_backends();
47535
+ init_detector();
47536
+ init_registry_backend();
47537
+ _internals22 = {
47538
+ detectProjectLanguages,
47539
+ cacheCapacity: 64
47540
+ };
47541
+ cache = new Map;
47542
+ MANIFEST_FILES = [
47543
+ "package.json",
47544
+ "tsconfig.json",
47545
+ "pyproject.toml",
47546
+ "setup.py",
47547
+ "setup.cfg",
47548
+ "requirements.txt",
47549
+ "Pipfile",
47550
+ "Cargo.toml",
47551
+ "go.mod",
47552
+ "pom.xml",
47553
+ "build.gradle",
47554
+ "build.gradle.kts",
47555
+ "build.zig",
47556
+ "CMakeLists.txt",
47557
+ "Makefile",
47558
+ "meson.build",
47559
+ "Package.swift",
47560
+ "pubspec.yaml",
47561
+ "Gemfile",
47562
+ "composer.json"
47563
+ ];
47564
+ _MANIFEST_SET = new Set(MANIFEST_FILES);
47565
+ manifestRootCache = new Map;
47566
+ });
47567
+
46238
47568
  // src/tools/test-runner.ts
46239
- import * as fs17 from "fs";
46240
- import * as path34 from "path";
47569
+ import * as fs22 from "fs";
47570
+ import * as path39 from "path";
46241
47571
  function isAbsolutePath(str) {
46242
47572
  if (str.startsWith("/"))
46243
47573
  return true;
@@ -46302,19 +47632,19 @@ function hasDevDependency(devDeps, ...patterns) {
46302
47632
  return hasPackageJsonDependency(devDeps, ...patterns);
46303
47633
  }
46304
47634
  function detectGoTest(cwd) {
46305
- return fs17.existsSync(path34.join(cwd, "go.mod")) && isCommandAvailable("go");
47635
+ return fs22.existsSync(path39.join(cwd, "go.mod")) && isCommandAvailable("go");
46306
47636
  }
46307
47637
  function detectJavaMaven(cwd) {
46308
- return fs17.existsSync(path34.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
47638
+ return fs22.existsSync(path39.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
46309
47639
  }
46310
47640
  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"));
47641
+ const hasBuildFile = fs22.existsSync(path39.join(cwd, "build.gradle")) || fs22.existsSync(path39.join(cwd, "build.gradle.kts"));
47642
+ const hasGradlew = fs22.existsSync(path39.join(cwd, "gradlew")) || fs22.existsSync(path39.join(cwd, "gradlew.bat"));
46313
47643
  return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
46314
47644
  }
46315
47645
  function detectDotnetTest(cwd) {
46316
47646
  try {
46317
- const files = fs17.readdirSync(cwd);
47647
+ const files = fs22.readdirSync(cwd);
46318
47648
  const hasCsproj = files.some((f) => f.endsWith(".csproj"));
46319
47649
  return hasCsproj && isCommandAvailable("dotnet");
46320
47650
  } catch {
@@ -46322,32 +47652,89 @@ function detectDotnetTest(cwd) {
46322
47652
  }
46323
47653
  }
46324
47654
  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"));
47655
+ const hasSource = fs22.existsSync(path39.join(cwd, "CMakeLists.txt"));
47656
+ const hasBuildCache = fs22.existsSync(path39.join(cwd, "CMakeCache.txt")) || fs22.existsSync(path39.join(cwd, "build", "CMakeCache.txt"));
46327
47657
  return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
46328
47658
  }
46329
47659
  function detectSwiftTest(cwd) {
46330
- return fs17.existsSync(path34.join(cwd, "Package.swift")) && isCommandAvailable("swift");
47660
+ return fs22.existsSync(path39.join(cwd, "Package.swift")) && isCommandAvailable("swift");
46331
47661
  }
46332
47662
  function detectDartTest(cwd) {
46333
- return fs17.existsSync(path34.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
47663
+ return fs22.existsSync(path39.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
46334
47664
  }
46335
47665
  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"));
47666
+ const hasRSpecFile = fs22.existsSync(path39.join(cwd, ".rspec"));
47667
+ const hasGemfile = fs22.existsSync(path39.join(cwd, "Gemfile"));
47668
+ const hasSpecDir = fs22.existsSync(path39.join(cwd, "spec"));
46339
47669
  const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
46340
47670
  return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
46341
47671
  }
46342
47672
  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");
47673
+ return fs22.existsSync(path39.join(cwd, "test")) && (fs22.existsSync(path39.join(cwd, "Gemfile")) || fs22.existsSync(path39.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
47674
+ }
47675
+ async function detectTestFrameworkViaDispatch(cwd) {
47676
+ try {
47677
+ const { pickBackend: pickBackend2 } = await Promise.resolve().then(() => (init_dispatch(), exports_dispatch));
47678
+ const backend = await pickBackend2(cwd);
47679
+ if (!backend?.selectTestFramework)
47680
+ return "none";
47681
+ const sel = await backend.selectTestFramework(cwd);
47682
+ if (!sel)
47683
+ return "none";
47684
+ return DISPATCH_FRAMEWORK_MAP[sel.name] ?? "none";
47685
+ } catch {
47686
+ return "none";
47687
+ }
47688
+ }
47689
+ async function buildTestCommandViaDispatch(framework, scope, files, coverage, baseDir) {
47690
+ if (framework === "none")
47691
+ return null;
47692
+ try {
47693
+ const { pickBackend: pickBackend2 } = await Promise.resolve().then(() => (init_dispatch(), exports_dispatch));
47694
+ const backend = await pickBackend2(baseDir);
47695
+ if (backend?.buildTestCommand) {
47696
+ const cmd = backend.buildTestCommand(framework, files, baseDir, {
47697
+ scope,
47698
+ coverage
47699
+ });
47700
+ if (cmd)
47701
+ return cmd;
47702
+ }
47703
+ return null;
47704
+ } catch {
47705
+ return null;
47706
+ }
47707
+ }
47708
+ async function parseTestOutputViaDispatch(framework, output, baseDir) {
47709
+ if (framework === "none")
47710
+ return null;
47711
+ try {
47712
+ const { pickBackend: pickBackend2 } = await Promise.resolve().then(() => (init_dispatch(), exports_dispatch));
47713
+ const backend = await pickBackend2(baseDir);
47714
+ if (!backend?.parseTestOutput)
47715
+ return null;
47716
+ const summary = backend.parseTestOutput(framework, output, "", 0);
47717
+ const passed = summary.passed ?? 0;
47718
+ const failed = summary.failed ?? 0;
47719
+ const skipped = summary.skipped ?? 0;
47720
+ const total = summary.total ?? passed + failed + skipped;
47721
+ const result = {
47722
+ totals: { passed, failed, skipped, total }
47723
+ };
47724
+ if (summary.coveragePercent !== undefined) {
47725
+ result.coveragePercent = summary.coveragePercent;
47726
+ }
47727
+ return result;
47728
+ } catch {
47729
+ return null;
47730
+ }
46344
47731
  }
46345
47732
  async function detectTestFramework(cwd) {
46346
47733
  const baseDir = cwd;
46347
47734
  try {
46348
- const packageJsonPath = path34.join(baseDir, "package.json");
46349
- if (fs17.existsSync(packageJsonPath)) {
46350
- const content = fs17.readFileSync(packageJsonPath, "utf-8");
47735
+ const packageJsonPath = path39.join(baseDir, "package.json");
47736
+ if (fs22.existsSync(packageJsonPath)) {
47737
+ const content = fs22.readFileSync(packageJsonPath, "utf-8");
46351
47738
  const pkg = JSON.parse(content);
46352
47739
  const _deps = pkg.dependencies || {};
46353
47740
  const devDeps = pkg.devDependencies || {};
@@ -46366,38 +47753,38 @@ async function detectTestFramework(cwd) {
46366
47753
  return "jest";
46367
47754
  if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
46368
47755
  return "mocha";
46369
- if (fs17.existsSync(path34.join(baseDir, "bun.lockb")) || fs17.existsSync(path34.join(baseDir, "bun.lock"))) {
47756
+ if (fs22.existsSync(path39.join(baseDir, "bun.lockb")) || fs22.existsSync(path39.join(baseDir, "bun.lock"))) {
46370
47757
  if (scripts.test?.includes("bun"))
46371
47758
  return "bun";
46372
47759
  }
46373
47760
  }
46374
47761
  } catch {}
46375
47762
  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");
47763
+ const pyprojectTomlPath = path39.join(baseDir, "pyproject.toml");
47764
+ const setupCfgPath = path39.join(baseDir, "setup.cfg");
47765
+ const requirementsTxtPath = path39.join(baseDir, "requirements.txt");
47766
+ if (fs22.existsSync(pyprojectTomlPath)) {
47767
+ const content = fs22.readFileSync(pyprojectTomlPath, "utf-8");
46381
47768
  if (content.includes("[tool.pytest"))
46382
47769
  return "pytest";
46383
47770
  if (content.includes("pytest"))
46384
47771
  return "pytest";
46385
47772
  }
46386
- if (fs17.existsSync(setupCfgPath)) {
46387
- const content = fs17.readFileSync(setupCfgPath, "utf-8");
47773
+ if (fs22.existsSync(setupCfgPath)) {
47774
+ const content = fs22.readFileSync(setupCfgPath, "utf-8");
46388
47775
  if (content.includes("[pytest]"))
46389
47776
  return "pytest";
46390
47777
  }
46391
- if (fs17.existsSync(requirementsTxtPath)) {
46392
- const content = fs17.readFileSync(requirementsTxtPath, "utf-8");
47778
+ if (fs22.existsSync(requirementsTxtPath)) {
47779
+ const content = fs22.readFileSync(requirementsTxtPath, "utf-8");
46393
47780
  if (content.includes("pytest"))
46394
47781
  return "pytest";
46395
47782
  }
46396
47783
  } catch {}
46397
47784
  try {
46398
- const cargoTomlPath = path34.join(baseDir, "Cargo.toml");
46399
- if (fs17.existsSync(cargoTomlPath)) {
46400
- const content = fs17.readFileSync(cargoTomlPath, "utf-8");
47785
+ const cargoTomlPath = path39.join(baseDir, "Cargo.toml");
47786
+ if (fs22.existsSync(cargoTomlPath)) {
47787
+ const content = fs22.readFileSync(cargoTomlPath, "utf-8");
46401
47788
  if (content.includes("[dev-dependencies]")) {
46402
47789
  if (content.includes("tokio") || content.includes("mockall") || content.includes("pretty_assertions")) {
46403
47790
  return "cargo";
@@ -46406,10 +47793,10 @@ async function detectTestFramework(cwd) {
46406
47793
  }
46407
47794
  } catch {}
46408
47795
  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)) {
47796
+ const pesterConfigPath = path39.join(baseDir, "pester.config.ps1");
47797
+ const pesterConfigJsonPath = path39.join(baseDir, "pester.config.ps1.json");
47798
+ const pesterPs1Path = path39.join(baseDir, "tests.ps1");
47799
+ if (fs22.existsSync(pesterConfigPath) || fs22.existsSync(pesterConfigJsonPath) || fs22.existsSync(pesterPs1Path)) {
46413
47800
  return "pester";
46414
47801
  }
46415
47802
  } catch {}
@@ -46437,12 +47824,12 @@ function isTestDirectoryPath(normalizedPath) {
46437
47824
  return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
46438
47825
  }
46439
47826
  function resolveWorkspacePath(file3, workingDir) {
46440
- return path34.isAbsolute(file3) ? path34.resolve(file3) : path34.resolve(workingDir, file3);
47827
+ return path39.isAbsolute(file3) ? path39.resolve(file3) : path39.resolve(workingDir, file3);
46441
47828
  }
46442
47829
  function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
46443
47830
  if (!preferRelative)
46444
47831
  return absolutePath;
46445
- return path34.relative(workingDir, absolutePath);
47832
+ return path39.relative(workingDir, absolutePath);
46446
47833
  }
46447
47834
  function dedupePush(target, value) {
46448
47835
  if (!target.includes(value)) {
@@ -46479,18 +47866,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
46479
47866
  }
46480
47867
  }
46481
47868
  function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
46482
- const relativeDir = path34.dirname(relativePath);
47869
+ const relativeDir = path39.dirname(relativePath);
46483
47870
  const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
46484
47871
  const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
46485
- const rootDir = path34.join(workingDir, dirName);
46486
- return nestedRelativeDir ? [rootDir, path34.join(rootDir, nestedRelativeDir)] : [rootDir];
47872
+ const rootDir = path39.join(workingDir, dirName);
47873
+ return nestedRelativeDir ? [rootDir, path39.join(rootDir, nestedRelativeDir)] : [rootDir];
46487
47874
  });
46488
47875
  const normalizedRelativePath = relativePath.replace(/\\/g, "/");
46489
47876
  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))));
47877
+ directories.push(path39.join(workingDir, "src/test/java", path39.dirname(normalizedRelativePath.slice("src/main/java/".length))));
46491
47878
  }
46492
47879
  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))));
47880
+ directories.push(path39.join(workingDir, "src/test/kotlin", path39.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
46494
47881
  }
46495
47882
  return [...new Set(directories)];
46496
47883
  }
@@ -46498,19 +47885,19 @@ function hasCompoundTestExtension(filename) {
46498
47885
  const lower = filename.toLowerCase();
46499
47886
  return COMPOUND_TEST_EXTENSIONS.some((ext) => lower.endsWith(ext));
46500
47887
  }
46501
- function isLanguageSpecificTestFile(basename5) {
46502
- const lower = basename5.toLowerCase();
47888
+ function isLanguageSpecificTestFile(basename6) {
47889
+ const lower = basename6.toLowerCase();
46503
47890
  if (lower.endsWith("_test.go"))
46504
47891
  return true;
46505
47892
  if (lower.endsWith(".py") && (lower.startsWith("test_") || lower.endsWith("_test.py")))
46506
47893
  return true;
46507
47894
  if (lower.endsWith("_spec.rb"))
46508
47895
  return true;
46509
- if (lower.endsWith(".java") && (/^Test[A-Z]/.test(basename5) || basename5.endsWith("Test.java") || basename5.endsWith("Tests.java") || lower.endsWith("it.java")))
47896
+ if (lower.endsWith(".java") && (/^Test[A-Z]/.test(basename6) || basename6.endsWith("Test.java") || basename6.endsWith("Tests.java") || lower.endsWith("it.java")))
46510
47897
  return true;
46511
47898
  if (lower.endsWith(".cs") && (lower.endsWith("test.cs") || lower.endsWith("tests.cs")))
46512
47899
  return true;
46513
- if (lower.endsWith(".kt") && (/^Test[A-Z]/.test(basename5) || lower.endsWith("test.kt") || lower.endsWith("tests.kt")))
47900
+ if (lower.endsWith(".kt") && (/^Test[A-Z]/.test(basename6) || lower.endsWith("test.kt") || lower.endsWith("tests.kt")))
46514
47901
  return true;
46515
47902
  if (lower.endsWith(".tests.ps1"))
46516
47903
  return true;
@@ -46518,23 +47905,23 @@ function isLanguageSpecificTestFile(basename5) {
46518
47905
  }
46519
47906
  function isConventionTestFilePath(filePath) {
46520
47907
  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);
47908
+ const basename6 = path39.basename(filePath);
47909
+ return hasCompoundTestExtension(basename6) || basename6.includes(".spec.") || basename6.includes(".test.") || isLanguageSpecificTestFile(basename6) || isTestDirectoryPath(normalizedPath);
46523
47910
  }
46524
47911
  function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
46525
47912
  const testFiles = [];
46526
47913
  for (const file3 of sourceFiles) {
46527
47914
  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);
47915
+ const relativeFile = path39.relative(workingDir, absoluteFile);
47916
+ const basename6 = path39.basename(absoluteFile);
47917
+ const dirname18 = path39.dirname(absoluteFile);
47918
+ const preferRelativeOutput = !path39.isAbsolute(file3);
46532
47919
  if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file3)) {
46533
47920
  dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
46534
47921
  continue;
46535
47922
  }
46536
- const nameWithoutExt = basename5.replace(/\.[^.]+$/, "");
46537
- const ext = path34.extname(basename5);
47923
+ const nameWithoutExt = basename6.replace(/\.[^.]+$/, "");
47924
+ const ext = path39.extname(basename6);
46538
47925
  const genericTestNames = [
46539
47926
  `${nameWithoutExt}.spec${ext}`,
46540
47927
  `${nameWithoutExt}.test${ext}`
@@ -46543,20 +47930,20 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
46543
47930
  const colocatedCandidates = [
46544
47931
  ...genericTestNames,
46545
47932
  ...languageSpecificTestNames
46546
- ].map((candidateName) => path34.join(dirname16, candidateName));
47933
+ ].map((candidateName) => path39.join(dirname18, candidateName));
46547
47934
  const testDirectoryNames = [
46548
- basename5,
47935
+ basename6,
46549
47936
  ...genericTestNames,
46550
47937
  ...languageSpecificTestNames
46551
47938
  ];
46552
47939
  const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
46553
47940
  const possibleTestFiles = [
46554
47941
  ...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)))
47942
+ ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path39.join(dirname18, dirName, candidateName))),
47943
+ ...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path39.join(candidateDir, candidateName)))
46557
47944
  ];
46558
47945
  for (const testFile of possibleTestFiles) {
46559
- if (fs17.existsSync(testFile)) {
47946
+ if (fs22.existsSync(testFile)) {
46560
47947
  dedupePush(testFiles, toWorkspaceOutputPath(testFile, workingDir, preferRelativeOutput));
46561
47948
  }
46562
47949
  }
@@ -46573,8 +47960,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
46573
47960
  for (const testFile of candidateTestFiles) {
46574
47961
  try {
46575
47962
  const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
46576
- const content = fs17.readFileSync(absoluteTestFile, "utf-8");
46577
- const testDir = path34.dirname(absoluteTestFile);
47963
+ const content = fs22.readFileSync(absoluteTestFile, "utf-8");
47964
+ const testDir = path39.dirname(absoluteTestFile);
46578
47965
  const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
46579
47966
  let match;
46580
47967
  match = importRegex.exec(content);
@@ -46582,8 +47969,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
46582
47969
  const importPath = match[1];
46583
47970
  let resolvedImport;
46584
47971
  if (importPath.startsWith(".")) {
46585
- resolvedImport = path34.resolve(testDir, importPath);
46586
- const existingExt = path34.extname(resolvedImport);
47972
+ resolvedImport = path39.resolve(testDir, importPath);
47973
+ const existingExt = path39.extname(resolvedImport);
46587
47974
  if (!existingExt) {
46588
47975
  for (const extToTry of [
46589
47976
  ".ts",
@@ -46594,7 +47981,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
46594
47981
  ".cjs"
46595
47982
  ]) {
46596
47983
  const withExt = resolvedImport + extToTry;
46597
- if (absoluteSourceFiles.includes(withExt) || fs17.existsSync(withExt)) {
47984
+ if (absoluteSourceFiles.includes(withExt) || fs22.existsSync(withExt)) {
46598
47985
  resolvedImport = withExt;
46599
47986
  break;
46600
47987
  }
@@ -46603,12 +47990,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
46603
47990
  } else {
46604
47991
  continue;
46605
47992
  }
46606
- const importBasename = path34.basename(resolvedImport, path34.extname(resolvedImport));
46607
- const importDir = path34.dirname(resolvedImport);
47993
+ const importBasename = path39.basename(resolvedImport, path39.extname(resolvedImport));
47994
+ const importDir = path39.dirname(resolvedImport);
46608
47995
  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");
47996
+ const sourceDir = path39.dirname(sourceFile);
47997
+ const sourceBasename = path39.basename(sourceFile, path39.extname(sourceFile));
47998
+ 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
47999
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
46613
48000
  dedupePush(testFiles, testFile);
46614
48001
  break;
@@ -46621,8 +48008,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
46621
48008
  while (match !== null) {
46622
48009
  const importPath = match[1];
46623
48010
  if (importPath.startsWith(".")) {
46624
- let resolvedImport = path34.resolve(testDir, importPath);
46625
- const existingExt = path34.extname(resolvedImport);
48011
+ let resolvedImport = path39.resolve(testDir, importPath);
48012
+ const existingExt = path39.extname(resolvedImport);
46626
48013
  if (!existingExt) {
46627
48014
  for (const extToTry of [
46628
48015
  ".ts",
@@ -46633,18 +48020,18 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
46633
48020
  ".cjs"
46634
48021
  ]) {
46635
48022
  const withExt = resolvedImport + extToTry;
46636
- if (absoluteSourceFiles.includes(withExt) || fs17.existsSync(withExt)) {
48023
+ if (absoluteSourceFiles.includes(withExt) || fs22.existsSync(withExt)) {
46637
48024
  resolvedImport = withExt;
46638
48025
  break;
46639
48026
  }
46640
48027
  }
46641
48028
  }
46642
- const importDir = path34.dirname(resolvedImport);
46643
- const importBasename = path34.basename(resolvedImport, path34.extname(resolvedImport));
48029
+ const importDir = path39.dirname(resolvedImport);
48030
+ const importBasename = path39.basename(resolvedImport, path39.extname(resolvedImport));
46644
48031
  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");
48032
+ const sourceDir = path39.dirname(sourceFile);
48033
+ const sourceBasename = path39.basename(sourceFile, path39.extname(sourceFile));
48034
+ 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
48035
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
46649
48036
  dedupePush(testFiles, testFile);
46650
48037
  break;
@@ -46677,7 +48064,7 @@ function getTargetedExecutionUnsupportedReason(framework) {
46677
48064
  return null;
46678
48065
  }
46679
48066
  }
46680
- function buildTestCommand(framework, scope, files, coverage, baseDir) {
48067
+ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
46681
48068
  switch (framework) {
46682
48069
  case "bun": {
46683
48070
  const args = ["bun", "test"];
@@ -46747,8 +48134,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
46747
48134
  return ["mvn", "test"];
46748
48135
  case "gradle": {
46749
48136
  const isWindows = process.platform === "win32";
46750
- const hasGradlewBat = fs17.existsSync(path34.join(baseDir, "gradlew.bat"));
46751
- const hasGradlew = fs17.existsSync(path34.join(baseDir, "gradlew"));
48137
+ const hasGradlewBat = fs22.existsSync(path39.join(baseDir, "gradlew.bat"));
48138
+ const hasGradlew = fs22.existsSync(path39.join(baseDir, "gradlew"));
46752
48139
  if (hasGradlewBat && isWindows)
46753
48140
  return ["gradlew.bat", "test"];
46754
48141
  if (hasGradlew)
@@ -46765,7 +48152,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
46765
48152
  "cmake-build-release",
46766
48153
  "out"
46767
48154
  ];
46768
- const actualBuildDir = buildDirCandidates.find((d) => fs17.existsSync(path34.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
48155
+ const actualBuildDir = buildDirCandidates.find((d) => fs22.existsSync(path39.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
46769
48156
  return ["ctest", "--test-dir", actualBuildDir];
46770
48157
  }
46771
48158
  case "swift-test":
@@ -46794,7 +48181,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir) {
46794
48181
  return null;
46795
48182
  }
46796
48183
  }
46797
- function parseTestOutput(framework, output) {
48184
+ function parseTestOutput2(framework, output) {
46798
48185
  const totals = {
46799
48186
  passed: 0,
46800
48187
  failed: 0,
@@ -47057,7 +48444,8 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
47057
48444
  };
47058
48445
  }
47059
48446
  }
47060
- const command = buildTestCommand(framework, scope, files, coverage, cwd);
48447
+ const useDispatchBuild = process.env.SWARM_LANG_BACKEND !== "legacy";
48448
+ const command = useDispatchBuild ? await buildTestCommandViaDispatch(framework, scope, files, coverage, cwd) ?? buildTestCommand2(framework, scope, files, coverage, cwd) : buildTestCommand2(framework, scope, files, coverage, cwd);
47061
48449
  if (!command) {
47062
48450
  return {
47063
48451
  success: false,
@@ -47086,9 +48474,9 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
47086
48474
  stderr: "pipe",
47087
48475
  cwd
47088
48476
  });
47089
- const timeoutPromise = new Promise((resolve13) => setTimeout(() => {
48477
+ const timeoutPromise = new Promise((resolve14) => setTimeout(() => {
47090
48478
  proc.kill();
47091
- resolve13(-1);
48479
+ resolve14(-1);
47092
48480
  }, timeout_ms));
47093
48481
  const [exitCode, stdoutResult, stderrResult] = await Promise.all([
47094
48482
  Promise.race([proc.exited, timeoutPromise]),
@@ -47105,7 +48493,9 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
47105
48493
  output += `
47106
48494
  ... (output truncated at stream read limit)`;
47107
48495
  }
47108
- const { totals, coveragePercent } = parseTestOutput(framework, output);
48496
+ const useDispatchParse = process.env.SWARM_LANG_BACKEND !== "legacy";
48497
+ const parsed = useDispatchParse ? await parseTestOutputViaDispatch(framework, output, cwd) ?? parseTestOutput2(framework, output) : parseTestOutput2(framework, output);
48498
+ const { totals, coveragePercent } = parsed;
47109
48499
  const isTimeout = exitCode === -1;
47110
48500
  const testPassed = exitCode === 0 && totals.failed === 0;
47111
48501
  if (testPassed) {
@@ -47208,7 +48598,7 @@ function analyzeFailures(workingDir) {
47208
48598
  } catch {}
47209
48599
  return report;
47210
48600
  }
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;
48601
+ 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
48602
  var init_test_runner = __esm(() => {
47213
48603
  init_zod();
47214
48604
  init_discovery();
@@ -47219,6 +48609,30 @@ var init_test_runner = __esm(() => {
47219
48609
  init_create_tool();
47220
48610
  init_resolve_working_directory();
47221
48611
  POWERSHELL_METACHARACTERS = /[|;&`$(){}[\]<>"'#*?\x00-\x1f]/;
48612
+ DISPATCH_FRAMEWORK_MAP = {
48613
+ "bun:test": "bun",
48614
+ bun: "bun",
48615
+ vitest: "vitest",
48616
+ jest: "jest",
48617
+ mocha: "mocha",
48618
+ pytest: "pytest",
48619
+ "cargo test": "cargo",
48620
+ cargo: "cargo",
48621
+ pester: "pester",
48622
+ "go test": "go-test",
48623
+ "maven-test": "maven",
48624
+ "gradle-test": "gradle",
48625
+ "gradle-test-groovy": "gradle",
48626
+ "gradle-kts": "gradle",
48627
+ "dotnet test": "dotnet-test",
48628
+ ctest: "ctest",
48629
+ "swift test": "swift-test",
48630
+ "xcodebuild-test": "swift-test",
48631
+ "flutter test": "dart-test",
48632
+ "dart test": "dart-test",
48633
+ rspec: "rspec",
48634
+ minitest: "minitest"
48635
+ };
47222
48636
  COMPOUND_TEST_EXTENSIONS = [
47223
48637
  ".test.ts",
47224
48638
  ".test.tsx",
@@ -47392,7 +48806,16 @@ var init_test_runner = __esm(() => {
47392
48806
  const _files = args.files || [];
47393
48807
  const coverage = args.coverage || false;
47394
48808
  const timeout_ms = Math.min(args.timeout_ms || DEFAULT_TIMEOUT_MS, MAX_TIMEOUT_MS);
47395
- const framework = await detectTestFramework(workingDir);
48809
+ const useDispatch = process.env.SWARM_LANG_BACKEND !== "legacy";
48810
+ let framework;
48811
+ if (useDispatch) {
48812
+ framework = await detectTestFrameworkViaDispatch(workingDir);
48813
+ if (framework === "none") {
48814
+ framework = await detectTestFramework(workingDir);
48815
+ }
48816
+ } else {
48817
+ framework = await detectTestFramework(workingDir);
48818
+ }
47396
48819
  if (framework === "none") {
47397
48820
  const result2 = {
47398
48821
  success: false,
@@ -47418,7 +48841,7 @@ var init_test_runner = __esm(() => {
47418
48841
  const sourceFiles = args.files.filter((file3) => {
47419
48842
  if (directTestFiles.includes(file3))
47420
48843
  return false;
47421
- const ext = path34.extname(file3).toLowerCase();
48844
+ const ext = path39.extname(file3).toLowerCase();
47422
48845
  return SOURCE_EXTENSIONS.has(ext);
47423
48846
  });
47424
48847
  const invalidFiles = args.files.filter((file3) => !directTestFiles.includes(file3) && !sourceFiles.includes(file3));
@@ -47453,7 +48876,7 @@ var init_test_runner = __esm(() => {
47453
48876
  if (isConventionTestFilePath(f)) {
47454
48877
  return false;
47455
48878
  }
47456
- const ext = path34.extname(f).toLowerCase();
48879
+ const ext = path39.extname(f).toLowerCase();
47457
48880
  return SOURCE_EXTENSIONS.has(ext);
47458
48881
  });
47459
48882
  if (sourceFiles.length === 0) {
@@ -47480,7 +48903,7 @@ var init_test_runner = __esm(() => {
47480
48903
  if (isConventionTestFilePath(f)) {
47481
48904
  return false;
47482
48905
  }
47483
- const ext = path34.extname(f).toLowerCase();
48906
+ const ext = path39.extname(f).toLowerCase();
47484
48907
  return SOURCE_EXTENSIONS.has(ext);
47485
48908
  });
47486
48909
  if (sourceFiles.length === 0) {
@@ -47498,8 +48921,8 @@ var init_test_runner = __esm(() => {
47498
48921
  const impactResult = await analyzeImpact(sourceFiles, workingDir);
47499
48922
  if (impactResult.impactedTests.length > 0) {
47500
48923
  testFiles = impactResult.impactedTests.map((absPath) => {
47501
- const relativePath = path34.relative(workingDir, absPath);
47502
- return path34.isAbsolute(relativePath) ? absPath : relativePath;
48924
+ const relativePath = path39.relative(workingDir, absPath);
48925
+ return path39.isAbsolute(relativePath) ? absPath : relativePath;
47503
48926
  });
47504
48927
  } else {
47505
48928
  graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
@@ -47574,8 +48997,8 @@ var init_test_runner = __esm(() => {
47574
48997
  });
47575
48998
 
47576
48999
  // src/services/preflight-service.ts
47577
- import * as fs18 from "fs";
47578
- import * as path35 from "path";
49000
+ import * as fs23 from "fs";
49001
+ import * as path40 from "path";
47579
49002
  function validateDirectoryPath(dir) {
47580
49003
  if (!dir || typeof dir !== "string") {
47581
49004
  throw new Error("Directory path is required");
@@ -47583,8 +49006,8 @@ function validateDirectoryPath(dir) {
47583
49006
  if (dir.includes("..")) {
47584
49007
  throw new Error("Directory path must not contain path traversal sequences");
47585
49008
  }
47586
- const normalized = path35.normalize(dir);
47587
- const absolutePath = path35.isAbsolute(normalized) ? normalized : path35.resolve(normalized);
49009
+ const normalized = path40.normalize(dir);
49010
+ const absolutePath = path40.isAbsolute(normalized) ? normalized : path40.resolve(normalized);
47588
49011
  return absolutePath;
47589
49012
  }
47590
49013
  function validateTimeout(timeoutMs, defaultValue) {
@@ -47607,9 +49030,9 @@ function validateTimeout(timeoutMs, defaultValue) {
47607
49030
  }
47608
49031
  function getPackageVersion(dir) {
47609
49032
  try {
47610
- const packagePath = path35.join(dir, "package.json");
47611
- if (fs18.existsSync(packagePath)) {
47612
- const content = fs18.readFileSync(packagePath, "utf-8");
49033
+ const packagePath = path40.join(dir, "package.json");
49034
+ if (fs23.existsSync(packagePath)) {
49035
+ const content = fs23.readFileSync(packagePath, "utf-8");
47613
49036
  const pkg = JSON.parse(content);
47614
49037
  return pkg.version ?? null;
47615
49038
  }
@@ -47618,9 +49041,9 @@ function getPackageVersion(dir) {
47618
49041
  }
47619
49042
  function getChangelogVersion(dir) {
47620
49043
  try {
47621
- const changelogPath = path35.join(dir, "CHANGELOG.md");
47622
- if (fs18.existsSync(changelogPath)) {
47623
- const content = fs18.readFileSync(changelogPath, "utf-8");
49044
+ const changelogPath = path40.join(dir, "CHANGELOG.md");
49045
+ if (fs23.existsSync(changelogPath)) {
49046
+ const content = fs23.readFileSync(changelogPath, "utf-8");
47624
49047
  const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
47625
49048
  if (match) {
47626
49049
  return match[1];
@@ -47632,10 +49055,10 @@ function getChangelogVersion(dir) {
47632
49055
  function getVersionFileVersion(dir) {
47633
49056
  const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
47634
49057
  for (const file3 of possibleFiles) {
47635
- const filePath = path35.join(dir, file3);
47636
- if (fs18.existsSync(filePath)) {
49058
+ const filePath = path40.join(dir, file3);
49059
+ if (fs23.existsSync(filePath)) {
47637
49060
  try {
47638
- const content = fs18.readFileSync(filePath, "utf-8").trim();
49061
+ const content = fs23.readFileSync(filePath, "utf-8").trim();
47639
49062
  const match = content.match(/(\d+\.\d+\.\d+)/);
47640
49063
  if (match) {
47641
49064
  return match[1];
@@ -47648,9 +49071,9 @@ function getVersionFileVersion(dir) {
47648
49071
  async function runVersionCheck(dir, _timeoutMs) {
47649
49072
  const startTime = Date.now();
47650
49073
  try {
47651
- const packageVersion = _internals19.getPackageVersion(dir);
47652
- const changelogVersion = _internals19.getChangelogVersion(dir);
47653
- const versionFileVersion = _internals19.getVersionFileVersion(dir);
49074
+ const packageVersion = _internals23.getPackageVersion(dir);
49075
+ const changelogVersion = _internals23.getChangelogVersion(dir);
49076
+ const versionFileVersion = _internals23.getVersionFileVersion(dir);
47654
49077
  const versions3 = [];
47655
49078
  if (packageVersion)
47656
49079
  versions3.push(`package.json: ${packageVersion}`);
@@ -47959,8 +49382,8 @@ async function runEvidenceCheck(dir) {
47959
49382
  async function runRequirementCoverageCheck(dir, currentPhase) {
47960
49383
  const startTime = Date.now();
47961
49384
  try {
47962
- const specPath = path35.join(dir, ".swarm", "spec.md");
47963
- if (!fs18.existsSync(specPath)) {
49385
+ const specPath = path40.join(dir, ".swarm", "spec.md");
49386
+ if (!fs23.existsSync(specPath)) {
47964
49387
  return {
47965
49388
  type: "req_coverage",
47966
49389
  status: "skip",
@@ -48000,7 +49423,7 @@ async function runPreflight(dir, phase, config3) {
48000
49423
  const reportId = `preflight-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
48001
49424
  let validatedDir;
48002
49425
  try {
48003
- validatedDir = _internals19.validateDirectoryPath(dir);
49426
+ validatedDir = _internals23.validateDirectoryPath(dir);
48004
49427
  } catch (error93) {
48005
49428
  return {
48006
49429
  id: reportId,
@@ -48020,7 +49443,7 @@ async function runPreflight(dir, phase, config3) {
48020
49443
  }
48021
49444
  let validatedTimeout;
48022
49445
  try {
48023
- validatedTimeout = _internals19.validateTimeout(config3?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
49446
+ validatedTimeout = _internals23.validateTimeout(config3?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
48024
49447
  } catch (error93) {
48025
49448
  return {
48026
49449
  id: reportId,
@@ -48061,12 +49484,12 @@ async function runPreflight(dir, phase, config3) {
48061
49484
  });
48062
49485
  const checks5 = [];
48063
49486
  log("[Preflight] Running lint check...");
48064
- const lintResult = await _internals19.runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
49487
+ const lintResult = await _internals23.runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
48065
49488
  checks5.push(lintResult);
48066
49489
  log(`[Preflight] Lint check: ${lintResult.status} ${lintResult.message}`);
48067
49490
  if (!cfg.skipTests) {
48068
49491
  log("[Preflight] Running tests check...");
48069
- const testsResult = await _internals19.runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
49492
+ const testsResult = await _internals23.runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
48070
49493
  checks5.push(testsResult);
48071
49494
  log(`[Preflight] Tests check: ${testsResult.status} ${testsResult.message}`);
48072
49495
  } else {
@@ -48078,7 +49501,7 @@ async function runPreflight(dir, phase, config3) {
48078
49501
  }
48079
49502
  if (!cfg.skipSecrets) {
48080
49503
  log("[Preflight] Running secrets check...");
48081
- const secretsResult = await _internals19.runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
49504
+ const secretsResult = await _internals23.runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
48082
49505
  checks5.push(secretsResult);
48083
49506
  log(`[Preflight] Secrets check: ${secretsResult.status} ${secretsResult.message}`);
48084
49507
  } else {
@@ -48090,7 +49513,7 @@ async function runPreflight(dir, phase, config3) {
48090
49513
  }
48091
49514
  if (!cfg.skipEvidence) {
48092
49515
  log("[Preflight] Running evidence check...");
48093
- const evidenceResult = await _internals19.runEvidenceCheck(validatedDir);
49516
+ const evidenceResult = await _internals23.runEvidenceCheck(validatedDir);
48094
49517
  checks5.push(evidenceResult);
48095
49518
  log(`[Preflight] Evidence check: ${evidenceResult.status} ${evidenceResult.message}`);
48096
49519
  } else {
@@ -48101,12 +49524,12 @@ async function runPreflight(dir, phase, config3) {
48101
49524
  });
48102
49525
  }
48103
49526
  log("[Preflight] Running requirement coverage check...");
48104
- const reqCoverageResult = await _internals19.runRequirementCoverageCheck(validatedDir, phase);
49527
+ const reqCoverageResult = await _internals23.runRequirementCoverageCheck(validatedDir, phase);
48105
49528
  checks5.push(reqCoverageResult);
48106
49529
  log(`[Preflight] Requirement coverage check: ${reqCoverageResult.status} ${reqCoverageResult.message}`);
48107
49530
  if (!cfg.skipVersion) {
48108
49531
  log("[Preflight] Running version check...");
48109
- const versionResult = await _internals19.runVersionCheck(validatedDir, cfg.checkTimeoutMs);
49532
+ const versionResult = await _internals23.runVersionCheck(validatedDir, cfg.checkTimeoutMs);
48110
49533
  checks5.push(versionResult);
48111
49534
  log(`[Preflight] Version check: ${versionResult.status} ${versionResult.message}`);
48112
49535
  } else {
@@ -48169,10 +49592,10 @@ function formatPreflightMarkdown(report) {
48169
49592
  async function handlePreflightCommand(directory, _args) {
48170
49593
  const plan = await loadPlan(directory);
48171
49594
  const phase = plan?.current_phase ?? 1;
48172
- const report = await _internals19.runPreflight(directory, phase);
48173
- return _internals19.formatPreflightMarkdown(report);
49595
+ const report = await _internals23.runPreflight(directory, phase);
49596
+ return _internals23.formatPreflightMarkdown(report);
48174
49597
  }
48175
- var MIN_CHECK_TIMEOUT_MS = 5000, MAX_CHECK_TIMEOUT_MS = 300000, DEFAULT_CONFIG, _internals19;
49598
+ var MIN_CHECK_TIMEOUT_MS = 5000, MAX_CHECK_TIMEOUT_MS = 300000, DEFAULT_CONFIG, _internals23;
48176
49599
  var init_preflight_service = __esm(() => {
48177
49600
  init_manager2();
48178
49601
  init_manager();
@@ -48189,7 +49612,7 @@ var init_preflight_service = __esm(() => {
48189
49612
  testScope: "convention",
48190
49613
  linter: "biome"
48191
49614
  };
48192
- _internals19 = {
49615
+ _internals23 = {
48193
49616
  runPreflight,
48194
49617
  formatPreflightMarkdown,
48195
49618
  handlePreflightCommand,
@@ -48437,13 +49860,13 @@ class CircuitBreaker {
48437
49860
  if (this.config.callTimeoutMs <= 0) {
48438
49861
  return fn();
48439
49862
  }
48440
- return new Promise((resolve14, reject) => {
49863
+ return new Promise((resolve15, reject) => {
48441
49864
  const timeout = setTimeout(() => {
48442
49865
  reject(new Error(`Call timeout after ${this.config.callTimeoutMs}ms`));
48443
49866
  }, this.config.callTimeoutMs);
48444
49867
  fn().then((result) => {
48445
49868
  clearTimeout(timeout);
48446
- resolve14(result);
49869
+ resolve15(result);
48447
49870
  }).catch((error93) => {
48448
49871
  clearTimeout(timeout);
48449
49872
  reject(error93);
@@ -48730,7 +50153,7 @@ var init_queue = __esm(() => {
48730
50153
 
48731
50154
  // src/background/worker.ts
48732
50155
  function sleep(ms) {
48733
- return new Promise((resolve14) => setTimeout(resolve14, ms));
50156
+ return new Promise((resolve15) => setTimeout(resolve15, ms));
48734
50157
  }
48735
50158
 
48736
50159
  class WorkerManager {
@@ -49075,8 +50498,8 @@ var init_manager3 = __esm(() => {
49075
50498
  });
49076
50499
 
49077
50500
  // src/commands/reset.ts
49078
- import * as fs19 from "fs";
49079
- import * as path36 from "path";
50501
+ import * as fs24 from "fs";
50502
+ import * as path41 from "path";
49080
50503
  async function handleResetCommand(directory, args) {
49081
50504
  const hasConfirm = args.includes("--confirm");
49082
50505
  if (!hasConfirm) {
@@ -49104,8 +50527,8 @@ async function handleResetCommand(directory, args) {
49104
50527
  for (const filename of filesToReset) {
49105
50528
  try {
49106
50529
  const resolvedPath = validateSwarmPath(directory, filename);
49107
- if (fs19.existsSync(resolvedPath)) {
49108
- fs19.unlinkSync(resolvedPath);
50530
+ if (fs24.existsSync(resolvedPath)) {
50531
+ fs24.unlinkSync(resolvedPath);
49109
50532
  results.push(`- \u2705 Deleted ${filename}`);
49110
50533
  } else {
49111
50534
  results.push(`- \u23ED\uFE0F ${filename} not found (skipped)`);
@@ -49116,9 +50539,9 @@ async function handleResetCommand(directory, args) {
49116
50539
  }
49117
50540
  for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
49118
50541
  try {
49119
- const rootPath = path36.join(directory, filename);
49120
- if (fs19.existsSync(rootPath)) {
49121
- fs19.unlinkSync(rootPath);
50542
+ const rootPath = path41.join(directory, filename);
50543
+ if (fs24.existsSync(rootPath)) {
50544
+ fs24.unlinkSync(rootPath);
49122
50545
  results.push(`- \u2705 Deleted ${filename} (root)`);
49123
50546
  }
49124
50547
  } catch {}
@@ -49131,8 +50554,8 @@ async function handleResetCommand(directory, args) {
49131
50554
  }
49132
50555
  try {
49133
50556
  const summariesPath = validateSwarmPath(directory, "summaries");
49134
- if (fs19.existsSync(summariesPath)) {
49135
- fs19.rmSync(summariesPath, { recursive: true, force: true });
50557
+ if (fs24.existsSync(summariesPath)) {
50558
+ fs24.rmSync(summariesPath, { recursive: true, force: true });
49136
50559
  results.push("- \u2705 Deleted summaries/ directory");
49137
50560
  } else {
49138
50561
  results.push("- \u23ED\uFE0F summaries/ not found (skipped)");
@@ -49155,14 +50578,14 @@ var init_reset = __esm(() => {
49155
50578
  });
49156
50579
 
49157
50580
  // src/commands/reset-session.ts
49158
- import * as fs20 from "fs";
49159
- import * as path37 from "path";
50581
+ import * as fs25 from "fs";
50582
+ import * as path42 from "path";
49160
50583
  async function handleResetSessionCommand(directory, _args) {
49161
50584
  const results = [];
49162
50585
  try {
49163
50586
  const statePath = validateSwarmPath(directory, "session/state.json");
49164
- if (fs20.existsSync(statePath)) {
49165
- fs20.unlinkSync(statePath);
50587
+ if (fs25.existsSync(statePath)) {
50588
+ fs25.unlinkSync(statePath);
49166
50589
  results.push("\u2705 Deleted .swarm/session/state.json");
49167
50590
  } else {
49168
50591
  results.push("\u23ED\uFE0F state.json not found (already clean)");
@@ -49171,15 +50594,15 @@ async function handleResetSessionCommand(directory, _args) {
49171
50594
  results.push("\u274C Failed to delete state.json");
49172
50595
  }
49173
50596
  try {
49174
- const sessionDir = path37.dirname(validateSwarmPath(directory, "session/state.json"));
49175
- if (fs20.existsSync(sessionDir)) {
49176
- const files = fs20.readdirSync(sessionDir);
50597
+ const sessionDir = path42.dirname(validateSwarmPath(directory, "session/state.json"));
50598
+ if (fs25.existsSync(sessionDir)) {
50599
+ const files = fs25.readdirSync(sessionDir);
49177
50600
  const otherFiles = files.filter((f) => f !== "state.json");
49178
50601
  let deletedCount = 0;
49179
50602
  for (const file3 of otherFiles) {
49180
- const filePath = path37.join(sessionDir, file3);
49181
- if (fs20.lstatSync(filePath).isFile()) {
49182
- fs20.unlinkSync(filePath);
50603
+ const filePath = path42.join(sessionDir, file3);
50604
+ if (fs25.lstatSync(filePath).isFile()) {
50605
+ fs25.unlinkSync(filePath);
49183
50606
  deletedCount++;
49184
50607
  }
49185
50608
  }
@@ -49209,7 +50632,7 @@ var init_reset_session = __esm(() => {
49209
50632
  });
49210
50633
 
49211
50634
  // src/summaries/manager.ts
49212
- import * as path38 from "path";
50635
+ import * as path43 from "path";
49213
50636
  function sanitizeSummaryId(id) {
49214
50637
  if (!id || id.length === 0) {
49215
50638
  throw new Error("Invalid summary ID: empty string");
@@ -49232,7 +50655,7 @@ function sanitizeSummaryId(id) {
49232
50655
  }
49233
50656
  async function loadFullOutput(directory, id) {
49234
50657
  const sanitizedId = sanitizeSummaryId(id);
49235
- const relativePath = path38.join("summaries", `${sanitizedId}.json`);
50658
+ const relativePath = path43.join("summaries", `${sanitizedId}.json`);
49236
50659
  validateSwarmPath(directory, relativePath);
49237
50660
  const content = await readSwarmFileAsync(directory, relativePath);
49238
50661
  if (content === null) {
@@ -49294,18 +50717,18 @@ var init_retrieve = __esm(() => {
49294
50717
  });
49295
50718
 
49296
50719
  // src/commands/rollback.ts
49297
- import * as fs21 from "fs";
49298
- import * as path39 from "path";
50720
+ import * as fs26 from "fs";
50721
+ import * as path44 from "path";
49299
50722
  async function handleRollbackCommand(directory, args) {
49300
50723
  const phaseArg = args[0];
49301
50724
  if (!phaseArg) {
49302
50725
  const manifestPath2 = validateSwarmPath(directory, "checkpoints/manifest.json");
49303
- if (!fs21.existsSync(manifestPath2)) {
50726
+ if (!fs26.existsSync(manifestPath2)) {
49304
50727
  return "No checkpoints found. Use `/swarm checkpoint` to create checkpoints.";
49305
50728
  }
49306
50729
  let manifest2;
49307
50730
  try {
49308
- manifest2 = JSON.parse(fs21.readFileSync(manifestPath2, "utf-8"));
50731
+ manifest2 = JSON.parse(fs26.readFileSync(manifestPath2, "utf-8"));
49309
50732
  } catch {
49310
50733
  return "Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.";
49311
50734
  }
@@ -49327,12 +50750,12 @@ async function handleRollbackCommand(directory, args) {
49327
50750
  return "Error: Phase number must be a positive integer.";
49328
50751
  }
49329
50752
  const manifestPath = validateSwarmPath(directory, "checkpoints/manifest.json");
49330
- if (!fs21.existsSync(manifestPath)) {
50753
+ if (!fs26.existsSync(manifestPath)) {
49331
50754
  return `Error: No checkpoints found. Cannot rollback to phase ${targetPhase}.`;
49332
50755
  }
49333
50756
  let manifest;
49334
50757
  try {
49335
- manifest = JSON.parse(fs21.readFileSync(manifestPath, "utf-8"));
50758
+ manifest = JSON.parse(fs26.readFileSync(manifestPath, "utf-8"));
49336
50759
  } catch {
49337
50760
  return `Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.`;
49338
50761
  }
@@ -49342,10 +50765,10 @@ async function handleRollbackCommand(directory, args) {
49342
50765
  return `Error: Checkpoint for phase ${targetPhase} not found. Available phases: ${available}`;
49343
50766
  }
49344
50767
  const checkpointDir = validateSwarmPath(directory, `checkpoints/phase-${targetPhase}`);
49345
- if (!fs21.existsSync(checkpointDir)) {
50768
+ if (!fs26.existsSync(checkpointDir)) {
49346
50769
  return `Error: Checkpoint directory for phase ${targetPhase} does not exist.`;
49347
50770
  }
49348
- const checkpointFiles = fs21.readdirSync(checkpointDir);
50771
+ const checkpointFiles = fs26.readdirSync(checkpointDir);
49349
50772
  if (checkpointFiles.length === 0) {
49350
50773
  return `Error: Checkpoint for phase ${targetPhase} is empty. Cannot rollback.`;
49351
50774
  }
@@ -49360,10 +50783,10 @@ async function handleRollbackCommand(directory, args) {
49360
50783
  if (EXCLUDE_FILES.has(file3) || file3.startsWith("plan-ledger.archived-")) {
49361
50784
  continue;
49362
50785
  }
49363
- const src = path39.join(checkpointDir, file3);
49364
- const dest = path39.join(swarmDir, file3);
50786
+ const src = path44.join(checkpointDir, file3);
50787
+ const dest = path44.join(swarmDir, file3);
49365
50788
  try {
49366
- fs21.cpSync(src, dest, { recursive: true, force: true });
50789
+ fs26.cpSync(src, dest, { recursive: true, force: true });
49367
50790
  successes.push(file3);
49368
50791
  } catch (error93) {
49369
50792
  failures.push({ file: file3, error: error93.message });
@@ -49380,14 +50803,14 @@ async function handleRollbackCommand(directory, args) {
49380
50803
  ].join(`
49381
50804
  `);
49382
50805
  }
49383
- const existingLedgerPath = path39.join(swarmDir, "plan-ledger.jsonl");
49384
- if (fs21.existsSync(existingLedgerPath)) {
49385
- fs21.unlinkSync(existingLedgerPath);
50806
+ const existingLedgerPath = path44.join(swarmDir, "plan-ledger.jsonl");
50807
+ if (fs26.existsSync(existingLedgerPath)) {
50808
+ fs26.unlinkSync(existingLedgerPath);
49386
50809
  }
49387
50810
  try {
49388
- const planJsonPath = path39.join(swarmDir, "plan.json");
49389
- if (fs21.existsSync(planJsonPath)) {
49390
- const planRaw = fs21.readFileSync(planJsonPath, "utf-8");
50811
+ const planJsonPath = path44.join(swarmDir, "plan.json");
50812
+ if (fs26.existsSync(planJsonPath)) {
50813
+ const planRaw = fs26.readFileSync(planJsonPath, "utf-8");
49391
50814
  const plan = PlanSchema.parse(JSON.parse(planRaw));
49392
50815
  const planId = derivePlanId(plan);
49393
50816
  const planHash = computePlanHash(plan);
@@ -49414,7 +50837,7 @@ async function handleRollbackCommand(directory, args) {
49414
50837
  timestamp: new Date().toISOString()
49415
50838
  };
49416
50839
  try {
49417
- fs21.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
50840
+ fs26.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
49418
50841
  `);
49419
50842
  } catch (error93) {
49420
50843
  console.error("Failed to write rollback event:", error93 instanceof Error ? error93.message : String(error93));
@@ -49475,11 +50898,11 @@ Ensure this is a git repository with commit history.`;
49475
50898
  const report = reportLines.filter(Boolean).join(`
49476
50899
  `);
49477
50900
  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");
50901
+ const fs27 = await import("fs/promises");
50902
+ const path45 = await import("path");
50903
+ const reportPath = path45.join(directory, ".swarm", "simulate-report.md");
50904
+ await fs27.mkdir(path45.dirname(reportPath), { recursive: true });
50905
+ await fs27.writeFile(reportPath, report, "utf-8");
49483
50906
  } catch (err) {
49484
50907
  const writeErr = err instanceof Error ? err.message : String(err);
49485
50908
  warn(`simulate: failed to write report to ${directory}/.swarm/simulate-report.md`, writeErr);
@@ -49501,15 +50924,15 @@ async function handleSpecifyCommand(_directory, args) {
49501
50924
  }
49502
50925
 
49503
50926
  // src/turbo/lean/state.ts
49504
- import * as fs22 from "fs";
49505
- import * as path40 from "path";
50927
+ import * as fs27 from "fs";
50928
+ import * as path45 from "path";
49506
50929
  function nowISO2() {
49507
50930
  return new Date().toISOString();
49508
50931
  }
49509
50932
  function ensureSwarmDir2(directory) {
49510
- const swarmDir = path40.resolve(directory, ".swarm");
49511
- if (!fs22.existsSync(swarmDir)) {
49512
- fs22.mkdirSync(swarmDir, { recursive: true });
50933
+ const swarmDir = path45.resolve(directory, ".swarm");
50934
+ if (!fs27.existsSync(swarmDir)) {
50935
+ fs27.mkdirSync(swarmDir, { recursive: true });
49513
50936
  }
49514
50937
  return swarmDir;
49515
50938
  }
@@ -49551,17 +50974,17 @@ function markStateUnreadable2(directory, reason) {
49551
50974
  }
49552
50975
  function readPersisted2(directory) {
49553
50976
  try {
49554
- const filePath = path40.join(directory, ".swarm", STATE_FILE2);
49555
- if (!fs22.existsSync(filePath)) {
50977
+ const filePath = path45.join(directory, ".swarm", STATE_FILE2);
50978
+ if (!fs27.existsSync(filePath)) {
49556
50979
  const seed = emptyPersisted2();
49557
50980
  try {
49558
50981
  ensureSwarmDir2(directory);
49559
- fs22.writeFileSync(filePath, `${JSON.stringify(seed, null, 2)}
50982
+ fs27.writeFileSync(filePath, `${JSON.stringify(seed, null, 2)}
49560
50983
  `, "utf-8");
49561
50984
  } catch {}
49562
50985
  return seed;
49563
50986
  }
49564
- const raw = fs22.readFileSync(filePath, "utf-8");
50987
+ const raw = fs27.readFileSync(filePath, "utf-8");
49565
50988
  const parsed = JSON.parse(raw);
49566
50989
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed) || parsed.version !== 1 || !parsed.sessions || typeof parsed.sessions !== "object" || Array.isArray(parsed.sessions)) {
49567
50990
  markStateUnreadable2(directory, `malformed shape (version=${parsed?.version}, sessions type=${Array.isArray(parsed?.sessions) ? "array" : typeof parsed?.sessions})`);
@@ -49587,7 +51010,7 @@ function writePersisted2(directory, persisted) {
49587
51010
  let payload;
49588
51011
  try {
49589
51012
  ensureSwarmDir2(directory);
49590
- filePath = path40.join(directory, ".swarm", STATE_FILE2);
51013
+ filePath = path45.join(directory, ".swarm", STATE_FILE2);
49591
51014
  tmpPath = `${filePath}.tmp.${Date.now()}`;
49592
51015
  persisted.updatedAt = nowISO2();
49593
51016
  payload = `${JSON.stringify(persisted, null, 2)}
@@ -49598,14 +51021,14 @@ function writePersisted2(directory, persisted) {
49598
51021
  throw new Error(`Lean Turbo state persistence prepare failed: ${msg}`);
49599
51022
  }
49600
51023
  try {
49601
- fs22.writeFileSync(tmpPath, payload, "utf-8");
49602
- fs22.renameSync(tmpPath, filePath);
51024
+ fs27.writeFileSync(tmpPath, payload, "utf-8");
51025
+ fs27.renameSync(tmpPath, filePath);
49603
51026
  } catch (error93) {
49604
51027
  const msg = error93 instanceof Error ? error93.message : String(error93);
49605
51028
  error(`[turbo/lean/state] Failed to persist ${STATE_FILE2} atomically: ${msg}`);
49606
51029
  try {
49607
- if (fs22.existsSync(tmpPath)) {
49608
- fs22.unlinkSync(tmpPath);
51030
+ if (fs27.existsSync(tmpPath)) {
51031
+ fs27.unlinkSync(tmpPath);
49609
51032
  }
49610
51033
  } catch {}
49611
51034
  throw new Error(`Lean Turbo state persistence failed: ${msg}`);
@@ -49782,7 +51205,7 @@ async function getStatusData(directory, agents) {
49782
51205
  }
49783
51206
  function enrichWithLeanTurbo(status, directory) {
49784
51207
  const turboMode = hasActiveTurboMode();
49785
- const leanActive = _internals20.hasActiveLeanTurbo();
51208
+ const leanActive = _internals24.hasActiveLeanTurbo();
49786
51209
  let turboStrategy = "off";
49787
51210
  if (leanActive) {
49788
51211
  turboStrategy = "lean";
@@ -49801,7 +51224,7 @@ function enrichWithLeanTurbo(status, directory) {
49801
51224
  }
49802
51225
  }
49803
51226
  if (leanSessionID) {
49804
- const runState = _internals20.loadLeanTurboRunState(directory, leanSessionID);
51227
+ const runState = _internals24.loadLeanTurboRunState(directory, leanSessionID);
49805
51228
  if (runState) {
49806
51229
  status.leanTurboPhase = runState.phase;
49807
51230
  status.leanMaxParallelCoders = runState.maxParallelCoders;
@@ -49833,7 +51256,7 @@ function enrichWithLeanTurbo(status, directory) {
49833
51256
  }
49834
51257
  }
49835
51258
  }
49836
- status.fullAutoActive = _internals20.hasActiveFullAuto();
51259
+ status.fullAutoActive = _internals24.hasActiveFullAuto();
49837
51260
  return status;
49838
51261
  }
49839
51262
  function formatStatusMarkdown(status) {
@@ -49897,7 +51320,7 @@ async function handleStatusCommand(directory, agents) {
49897
51320
  }
49898
51321
  return formatStatusMarkdown(statusData);
49899
51322
  }
49900
- var _internals20;
51323
+ var _internals24;
49901
51324
  var init_status_service = __esm(() => {
49902
51325
  init_extractors();
49903
51326
  init_utils2();
@@ -49906,7 +51329,7 @@ var init_status_service = __esm(() => {
49906
51329
  init_state3();
49907
51330
  init_compaction_service();
49908
51331
  init_context_budget_service();
49909
- _internals20 = {
51332
+ _internals24 = {
49910
51333
  loadLeanTurboRunState,
49911
51334
  hasActiveLeanTurbo,
49912
51335
  hasActiveFullAuto
@@ -50250,8 +51673,8 @@ __export(exports_commands, {
50250
51673
  COMMAND_NAME_SET: () => COMMAND_NAME_SET,
50251
51674
  COMMAND_NAMES: () => COMMAND_NAMES
50252
51675
  });
50253
- import fs23 from "fs";
50254
- import path41 from "path";
51676
+ import fs28 from "fs";
51677
+ import path46 from "path";
50255
51678
  function buildHelpText() {
50256
51679
  const lines = ["## Swarm Commands", ""];
50257
51680
  const CATEGORIES = [
@@ -50354,11 +51777,11 @@ function createSwarmCommandHandler(directory, agents) {
50354
51777
  return;
50355
51778
  }
50356
51779
  let isFirstRun = false;
50357
- const sentinelPath = path41.join(directory, ".swarm", ".first-run-complete");
51780
+ const sentinelPath = path46.join(directory, ".swarm", ".first-run-complete");
50358
51781
  try {
50359
- const swarmDir = path41.join(directory, ".swarm");
50360
- fs23.mkdirSync(swarmDir, { recursive: true });
50361
- fs23.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
51782
+ const swarmDir = path46.join(directory, ".swarm");
51783
+ fs28.mkdirSync(swarmDir, { recursive: true });
51784
+ fs28.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
50362
51785
  `, { flag: "wx" });
50363
51786
  isFirstRun = true;
50364
51787
  } catch (_err) {}
@@ -50379,7 +51802,7 @@ function createSwarmCommandHandler(directory, agents) {
50379
51802
  const attemptedCommand = tokens[0] || "";
50380
51803
  const MAX_DISPLAY = 100;
50381
51804
  const displayCommand = attemptedCommand.length > MAX_DISPLAY ? `${attemptedCommand.slice(0, MAX_DISPLAY)}...` : attemptedCommand;
50382
- const similar = _internals21.findSimilarCommands(attemptedCommand);
51805
+ const similar = _internals25.findSimilarCommands(attemptedCommand);
50383
51806
  const header = `Command \`/swarm ${displayCommand}\` not found.`;
50384
51807
  const suggestions = similar.length > 0 ? `Did you mean:
50385
51808
  ${similar.map((cmd) => ` \u2022 /swarm ${cmd}`).join(`
@@ -50486,7 +51909,7 @@ function findSimilarCommands(query) {
50486
51909
  }
50487
51910
  const scored = VALID_COMMANDS.map((cmd) => {
50488
51911
  const cmdLower = cmd.toLowerCase();
50489
- const fullScore = _internals21.levenshteinDistance(q, cmdLower);
51912
+ const fullScore = _internals25.levenshteinDistance(q, cmdLower);
50490
51913
  let tokenScore = Infinity;
50491
51914
  if (cmd.includes(" ") || cmd.includes("-")) {
50492
51915
  const qTokens = q.split(/[\s-]+/);
@@ -50499,7 +51922,7 @@ function findSimilarCommands(query) {
50499
51922
  for (const ct of cmdTokens) {
50500
51923
  if (ct.length === 0)
50501
51924
  continue;
50502
- const dist = _internals21.levenshteinDistance(qt, ct);
51925
+ const dist = _internals25.levenshteinDistance(qt, ct);
50503
51926
  if (dist < minDist)
50504
51927
  minDist = dist;
50505
51928
  }
@@ -50509,7 +51932,7 @@ function findSimilarCommands(query) {
50509
51932
  }
50510
51933
  const dashStrippedQ = q.replace(/-/g, "");
50511
51934
  const dashStrippedCmd = cmdLower.replace(/-/g, "");
50512
- const dashScore = _internals21.levenshteinDistance(dashStrippedQ, dashStrippedCmd);
51935
+ const dashScore = _internals25.levenshteinDistance(dashStrippedQ, dashStrippedCmd);
50513
51936
  const score = Math.min(fullScore, tokenScore, dashScore);
50514
51937
  return { cmd, score };
50515
51938
  });
@@ -50541,11 +51964,11 @@ async function handleHelpCommand(ctx) {
50541
51964
  return buildHelpText2();
50542
51965
  }
50543
51966
  const tokens = targetCommand.split(/\s+/);
50544
- const resolved = _internals21.resolveCommand(tokens);
51967
+ const resolved = _internals25.resolveCommand(tokens);
50545
51968
  if (resolved) {
50546
- return _internals21.buildDetailedHelp(resolved.key, resolved.entry);
51969
+ return _internals25.buildDetailedHelp(resolved.key, resolved.entry);
50547
51970
  }
50548
- const similar = _internals21.findSimilarCommands(targetCommand);
51971
+ const similar = _internals25.findSimilarCommands(targetCommand);
50549
51972
  const { buildHelpText: fullHelp } = await Promise.resolve().then(() => (init_commands(), exports_commands));
50550
51973
  if (similar.length > 0) {
50551
51974
  return `Command '/swarm ${targetCommand}' not found.
@@ -50581,24 +52004,24 @@ function validateAliases() {
50581
52004
  }
50582
52005
  aliasTargets.get(target).push(name);
50583
52006
  const visited = new Set;
50584
- const path42 = [];
52007
+ const path47 = [];
50585
52008
  let current = target;
50586
52009
  while (current) {
50587
52010
  const currentEntry = COMMAND_REGISTRY[current];
50588
52011
  if (!currentEntry)
50589
52012
  break;
50590
52013
  if (visited.has(current)) {
50591
- const cycleStart = path42.indexOf(current);
52014
+ const cycleStart = path47.indexOf(current);
50592
52015
  const fullChain = [
50593
52016
  name,
50594
- ...path42.slice(0, cycleStart > 0 ? cycleStart : path42.length),
52017
+ ...path47.slice(0, cycleStart > 0 ? cycleStart : path47.length),
50595
52018
  current
50596
52019
  ].join(" \u2192 ");
50597
52020
  errors5.push(`Circular alias detected: ${fullChain}`);
50598
52021
  break;
50599
52022
  }
50600
52023
  visited.add(current);
50601
- path42.push(current);
52024
+ path47.push(current);
50602
52025
  current = currentEntry.aliasOf || "";
50603
52026
  }
50604
52027
  }
@@ -50639,7 +52062,7 @@ function resolveCommand(tokens) {
50639
52062
  }
50640
52063
  return null;
50641
52064
  }
50642
- var COMMAND_REGISTRY, VALID_COMMANDS, _internals21, validation;
52065
+ var COMMAND_REGISTRY, VALID_COMMANDS, _internals25, validation;
50643
52066
  var init_registry = __esm(() => {
50644
52067
  init_acknowledge_spec_drift();
50645
52068
  init_agents();
@@ -50709,7 +52132,7 @@ var init_registry = __esm(() => {
50709
52132
  clashesWithNativeCcCommand: "/agents"
50710
52133
  },
50711
52134
  help: {
50712
- handler: (ctx) => _internals21.handleHelpCommand(ctx),
52135
+ handler: (ctx) => _internals25.handleHelpCommand(ctx),
50713
52136
  description: "Show help for swarm commands",
50714
52137
  category: "core",
50715
52138
  args: "[command]",
@@ -51066,7 +52489,7 @@ var init_registry = __esm(() => {
51066
52489
  }
51067
52490
  };
51068
52491
  VALID_COMMANDS = Object.keys(COMMAND_REGISTRY);
51069
- _internals21 = {
52492
+ _internals25 = {
51070
52493
  handleHelpCommand,
51071
52494
  validateAliases,
51072
52495
  resolveCommand,
@@ -51074,7 +52497,7 @@ var init_registry = __esm(() => {
51074
52497
  findSimilarCommands,
51075
52498
  buildDetailedHelp
51076
52499
  };
51077
- validation = _internals21.validateAliases();
52500
+ validation = _internals25.validateAliases();
51078
52501
  if (!validation.valid) {
51079
52502
  throw new Error(`COMMAND_REGISTRY alias validation failed:
51080
52503
  ${validation.errors.join(`
@@ -51092,68 +52515,68 @@ init_package();
51092
52515
  init_registry();
51093
52516
  init_cache_paths();
51094
52517
  init_constants();
51095
- import * as fs24 from "fs";
52518
+ import * as fs29 from "fs";
51096
52519
  import * as os7 from "os";
51097
- import * as path42 from "path";
52520
+ import * as path47 from "path";
51098
52521
  var { version: version4 } = package_default;
51099
52522
  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");
52523
+ var OPENCODE_CONFIG_PATH = path47.join(CONFIG_DIR, "opencode.json");
52524
+ var PLUGIN_CONFIG_PATH = path47.join(CONFIG_DIR, "opencode-swarm.json");
52525
+ var PROMPTS_DIR = path47.join(CONFIG_DIR, "opencode-swarm");
51103
52526
  var OPENCODE_PLUGIN_CACHE_PATHS = getPluginCachePaths();
51104
52527
  var OPENCODE_PLUGIN_LOCK_FILE_PATHS = getPluginLockFilePaths();
51105
52528
  function isSafeCachePath(p) {
51106
- const resolved = path42.resolve(p);
51107
- const home = path42.resolve(os7.homedir());
52529
+ const resolved = path47.resolve(p);
52530
+ const home = path47.resolve(os7.homedir());
51108
52531
  if (resolved === "/" || resolved === home || resolved.length <= home.length) {
51109
52532
  return false;
51110
52533
  }
51111
- const segments = resolved.split(path42.sep).filter((s) => s.length > 0);
52534
+ const segments = resolved.split(path47.sep).filter((s) => s.length > 0);
51112
52535
  if (segments.length < 4) {
51113
52536
  return false;
51114
52537
  }
51115
- const leaf = path42.basename(resolved);
52538
+ const leaf = path47.basename(resolved);
51116
52539
  if (leaf !== "opencode-swarm@latest" && leaf !== "opencode-swarm") {
51117
52540
  return false;
51118
52541
  }
51119
- const parent = path42.basename(path42.dirname(resolved));
52542
+ const parent = path47.basename(path47.dirname(resolved));
51120
52543
  if (parent !== "packages" && parent !== "node_modules") {
51121
52544
  return false;
51122
52545
  }
51123
- const grandparent = path42.basename(path42.dirname(path42.dirname(resolved)));
52546
+ const grandparent = path47.basename(path47.dirname(path47.dirname(resolved)));
51124
52547
  if (grandparent !== "opencode") {
51125
52548
  return false;
51126
52549
  }
51127
52550
  return true;
51128
52551
  }
51129
52552
  function isSafeLockFilePath(p) {
51130
- const resolved = path42.resolve(p);
51131
- const home = path42.resolve(os7.homedir());
52553
+ const resolved = path47.resolve(p);
52554
+ const home = path47.resolve(os7.homedir());
51132
52555
  if (resolved === "/" || resolved === home || resolved.length <= home.length) {
51133
52556
  return false;
51134
52557
  }
51135
- const segments = resolved.split(path42.sep).filter((s) => s.length > 0);
52558
+ const segments = resolved.split(path47.sep).filter((s) => s.length > 0);
51136
52559
  if (segments.length < 4) {
51137
52560
  return false;
51138
52561
  }
51139
- const leaf = path42.basename(resolved);
52562
+ const leaf = path47.basename(resolved);
51140
52563
  if (leaf !== "bun.lock" && leaf !== "bun.lockb" && leaf !== "package-lock.json") {
51141
52564
  return false;
51142
52565
  }
51143
- const parent = path42.basename(path42.dirname(resolved));
52566
+ const parent = path47.basename(path47.dirname(resolved));
51144
52567
  if (parent !== "opencode") {
51145
52568
  return false;
51146
52569
  }
51147
52570
  return true;
51148
52571
  }
51149
52572
  function ensureDir(dir) {
51150
- if (!fs24.existsSync(dir)) {
51151
- fs24.mkdirSync(dir, { recursive: true });
52573
+ if (!fs29.existsSync(dir)) {
52574
+ fs29.mkdirSync(dir, { recursive: true });
51152
52575
  }
51153
52576
  }
51154
52577
  function loadJson(filepath) {
51155
52578
  try {
51156
- const content = fs24.readFileSync(filepath, "utf-8");
52579
+ const content = fs29.readFileSync(filepath, "utf-8");
51157
52580
  const stripped = content.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (match, comment) => comment ? "" : match).replace(/,(\s*[}\]])/g, "$1");
51158
52581
  return JSON.parse(stripped);
51159
52582
  } catch {
@@ -51161,14 +52584,14 @@ function loadJson(filepath) {
51161
52584
  }
51162
52585
  }
51163
52586
  function saveJson(filepath, data) {
51164
- fs24.writeFileSync(filepath, `${JSON.stringify(data, null, 2)}
52587
+ fs29.writeFileSync(filepath, `${JSON.stringify(data, null, 2)}
51165
52588
  `, "utf-8");
51166
52589
  }
51167
52590
  function writeProjectConfigIfMissing(cwd) {
51168
52591
  try {
51169
- const opencodeDir = path42.join(cwd, ".opencode");
51170
- const projectConfigPath = path42.join(opencodeDir, "opencode-swarm.json");
51171
- if (fs24.existsSync(projectConfigPath)) {
52592
+ const opencodeDir = path47.join(cwd, ".opencode");
52593
+ const projectConfigPath = path47.join(opencodeDir, "opencode-swarm.json");
52594
+ if (fs29.existsSync(projectConfigPath)) {
51172
52595
  return;
51173
52596
  }
51174
52597
  ensureDir(opencodeDir);
@@ -51184,7 +52607,7 @@ async function install() {
51184
52607
  `);
51185
52608
  ensureDir(CONFIG_DIR);
51186
52609
  ensureDir(PROMPTS_DIR);
51187
- const LEGACY_CONFIG_PATH = path42.join(CONFIG_DIR, "config.json");
52610
+ const LEGACY_CONFIG_PATH = path47.join(CONFIG_DIR, "config.json");
51188
52611
  let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
51189
52612
  if (!opencodeConfig) {
51190
52613
  const legacyConfig = loadJson(LEGACY_CONFIG_PATH);
@@ -51231,7 +52654,7 @@ async function install() {
51231
52654
  console.warn(`\u26A0 Could not clear opencode lock file \u2014 you may need to delete it manually:
51232
52655
  ${failed}`);
51233
52656
  }
51234
- if (!fs24.existsSync(PLUGIN_CONFIG_PATH)) {
52657
+ if (!fs29.existsSync(PLUGIN_CONFIG_PATH)) {
51235
52658
  const defaultConfig = {
51236
52659
  agents: { ...DEFAULT_AGENT_CONFIGS },
51237
52660
  max_iterations: 5
@@ -51310,14 +52733,14 @@ function evictPluginCaches() {
51310
52733
  const cleared = [];
51311
52734
  const failed = [];
51312
52735
  for (const cachePath of OPENCODE_PLUGIN_CACHE_PATHS) {
51313
- if (!fs24.existsSync(cachePath))
52736
+ if (!fs29.existsSync(cachePath))
51314
52737
  continue;
51315
52738
  if (!isSafeCachePath(cachePath)) {
51316
52739
  failed.push(`${cachePath} (refused: failed safety check)`);
51317
52740
  continue;
51318
52741
  }
51319
52742
  try {
51320
- fs24.rmSync(cachePath, { recursive: true, force: true });
52743
+ fs29.rmSync(cachePath, { recursive: true, force: true });
51321
52744
  cleared.push(cachePath);
51322
52745
  } catch (err) {
51323
52746
  failed.push(`${cachePath} (${err instanceof Error ? err.message : String(err)})`);
@@ -51329,14 +52752,14 @@ function evictLockFiles() {
51329
52752
  const cleared = [];
51330
52753
  const failed = [];
51331
52754
  for (const lockPath of OPENCODE_PLUGIN_LOCK_FILE_PATHS) {
51332
- if (!fs24.existsSync(lockPath))
52755
+ if (!fs29.existsSync(lockPath))
51333
52756
  continue;
51334
52757
  if (!isSafeLockFilePath(lockPath)) {
51335
52758
  failed.push(`${lockPath} (refused: failed safety check)`);
51336
52759
  continue;
51337
52760
  }
51338
52761
  try {
51339
- fs24.unlinkSync(lockPath);
52762
+ fs29.unlinkSync(lockPath);
51340
52763
  cleared.push(lockPath);
51341
52764
  } catch (err) {
51342
52765
  const code = err?.code;
@@ -51355,7 +52778,7 @@ async function uninstall() {
51355
52778
  `);
51356
52779
  const opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
51357
52780
  if (!opencodeConfig) {
51358
- if (fs24.existsSync(OPENCODE_CONFIG_PATH)) {
52781
+ if (fs29.existsSync(OPENCODE_CONFIG_PATH)) {
51359
52782
  console.log(`\u2717 Could not parse opencode config at: ${OPENCODE_CONFIG_PATH}`);
51360
52783
  return 1;
51361
52784
  } else {
@@ -51387,13 +52810,13 @@ async function uninstall() {
51387
52810
  console.log("\u2713 Re-enabled default OpenCode agents (explore, general)");
51388
52811
  if (process.argv.includes("--clean")) {
51389
52812
  let cleaned = false;
51390
- if (fs24.existsSync(PLUGIN_CONFIG_PATH)) {
51391
- fs24.unlinkSync(PLUGIN_CONFIG_PATH);
52813
+ if (fs29.existsSync(PLUGIN_CONFIG_PATH)) {
52814
+ fs29.unlinkSync(PLUGIN_CONFIG_PATH);
51392
52815
  console.log(`\u2713 Removed plugin config: ${PLUGIN_CONFIG_PATH}`);
51393
52816
  cleaned = true;
51394
52817
  }
51395
- if (fs24.existsSync(PROMPTS_DIR)) {
51396
- fs24.rmSync(PROMPTS_DIR, { recursive: true });
52818
+ if (fs29.existsSync(PROMPTS_DIR)) {
52819
+ fs29.rmSync(PROMPTS_DIR, { recursive: true });
51397
52820
  console.log(`\u2713 Removed custom prompts: ${PROMPTS_DIR}`);
51398
52821
  cleaned = true;
51399
52822
  }