opencode-swarm 7.37.0 → 7.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -34,7 +34,7 @@ var package_default;
34
34
  var init_package = __esm(() => {
35
35
  package_default = {
36
36
  name: "opencode-swarm",
37
- version: "7.37.0",
37
+ version: "7.38.0",
38
38
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
39
39
  main: "dist/index.js",
40
40
  types: "dist/index.d.ts",
@@ -67,6 +67,7 @@ var init_package = __esm(() => {
67
67
  files: [
68
68
  "dist",
69
69
  "dist/lang/grammars",
70
+ "tests/fixtures/memory-recall",
70
71
  "README.md",
71
72
  "LICENSE"
72
73
  ],
@@ -47418,6 +47419,332 @@ var init_gateway = __esm(() => {
47418
47419
  gitRemoteUrlCache = new Map;
47419
47420
  });
47420
47421
 
47422
+ // src/memory/evaluation.ts
47423
+ import * as fs12 from "fs/promises";
47424
+ import * as os7 from "os";
47425
+ import * as path32 from "path";
47426
+ async function evaluateMemoryRecallFixtures(options) {
47427
+ const fixtureDirectory = path32.resolve(options.fixtureDirectory);
47428
+ const providers = options.providers ?? DEFAULT_PROVIDERS;
47429
+ const modes = options.modes ?? DEFAULT_MODES;
47430
+ const generatedAt = new Date().toISOString();
47431
+ const fixtures = await loadRecallEvaluationFixtures(fixtureDirectory);
47432
+ const runs = [];
47433
+ for (const fixture of fixtures) {
47434
+ const materialized = materializeFixture(fixture);
47435
+ for (const providerName of providers) {
47436
+ const tempRoot = await fs12.realpath(await fs12.mkdtemp(path32.join(os7.tmpdir(), "swarm-memory-eval-")));
47437
+ const provider = createEvaluationProvider(providerName, tempRoot);
47438
+ try {
47439
+ await provider.initialize?.();
47440
+ for (const record3 of materialized.records) {
47441
+ await provider.upsert(record3);
47442
+ }
47443
+ for (const mode of modes) {
47444
+ const request = buildRecallRequest(fixture, mode);
47445
+ const items = await provider.recall(request);
47446
+ const retrievedIds = items.map((item) => item.record.id);
47447
+ const run = buildRun({
47448
+ fixture,
47449
+ provider: providerName,
47450
+ mode,
47451
+ k: fixture.k ?? request.maxItems,
47452
+ retrievedIds,
47453
+ materialized
47454
+ });
47455
+ runs.push(run);
47456
+ }
47457
+ } finally {
47458
+ await provider.close?.();
47459
+ if (!options.keepTempRoots) {
47460
+ await fs12.rm(tempRoot, { recursive: true, force: true });
47461
+ }
47462
+ }
47463
+ }
47464
+ }
47465
+ return {
47466
+ schema_version: 1,
47467
+ generated_at: generatedAt,
47468
+ fixture_directory: fixtureDirectory,
47469
+ providers,
47470
+ modes,
47471
+ summary: summarizeRuns(fixtures.length, runs),
47472
+ runs
47473
+ };
47474
+ }
47475
+ async function loadRecallEvaluationFixtures(fixtureDirectory) {
47476
+ const entries = await fs12.readdir(fixtureDirectory, { withFileTypes: true });
47477
+ const files = entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort((a, b) => a.localeCompare(b));
47478
+ const fixtures = [];
47479
+ for (const file3 of files) {
47480
+ const raw = await fs12.readFile(path32.join(fixtureDirectory, file3), "utf-8");
47481
+ fixtures.push(validateFixture(JSON.parse(raw), file3));
47482
+ }
47483
+ return fixtures;
47484
+ }
47485
+ function createEvaluationProvider(provider, root) {
47486
+ const config3 = {
47487
+ ...DEFAULT_MEMORY_CONFIG,
47488
+ enabled: true,
47489
+ provider
47490
+ };
47491
+ return createConfiguredMemoryProvider(root, config3);
47492
+ }
47493
+ function buildRecallRequest(fixture, mode) {
47494
+ const maxItems = fixture.maxItems ?? fixture.k ?? 5;
47495
+ const base = {
47496
+ query: fixture.query,
47497
+ task: fixture.task,
47498
+ agentRole: mode === "curator" ? "curator" : fixture.agentRole,
47499
+ mode,
47500
+ scopes: fixture.scopes,
47501
+ kinds: fixture.kinds,
47502
+ maxItems,
47503
+ tokenBudget: fixture.tokenBudget ?? 1000,
47504
+ minScore: mode === "injection" ? 0.25 : 0,
47505
+ requireQuerySignal: mode === "injection"
47506
+ };
47507
+ return base;
47508
+ }
47509
+ function materializeFixture(fixture) {
47510
+ const idsByLabel = new Map;
47511
+ const labelsById = new Map;
47512
+ const baseRecords = fixture.records.map((record3) => {
47513
+ const base = {
47514
+ scope: record3.scope,
47515
+ kind: record3.kind,
47516
+ text: record3.text
47517
+ };
47518
+ const id = createMemoryId(base);
47519
+ idsByLabel.set(record3.label, id);
47520
+ labelsById.set(id, record3.label);
47521
+ return { input: record3, id, base };
47522
+ });
47523
+ const expectedIds = new Set(fixture.expectedLabels.map((label) => {
47524
+ const id = idsByLabel.get(label);
47525
+ if (!id) {
47526
+ throw new Error(`fixture ${fixture.name} expected unknown label ${label}`);
47527
+ }
47528
+ return id;
47529
+ }));
47530
+ const allowedScopeKeys = new Set(fixture.scopes.map(stableScopeKey));
47531
+ const staleIds = new Set;
47532
+ const crossScopeIds = new Set;
47533
+ const sameScopeNoiseIds = new Set;
47534
+ const records = baseRecords.map(({ input, id, base }) => {
47535
+ const supersededBy = input.state?.supersededByLabel ? idsByLabel.get(input.state.supersededByLabel) : undefined;
47536
+ if (input.state?.supersededByLabel && !supersededBy) {
47537
+ throw new Error(`fixture ${fixture.name} record ${input.label} supersedes unknown label ${input.state.supersededByLabel}`);
47538
+ }
47539
+ const metadata = {
47540
+ ...input.metadata ?? {},
47541
+ fixture: fixture.name,
47542
+ fixtureLabel: input.label,
47543
+ ...input.state?.deleted ? { deleted: true } : {}
47544
+ };
47545
+ const record3 = {
47546
+ id,
47547
+ ...base,
47548
+ tags: input.tags ?? [],
47549
+ confidence: input.confidence ?? 0.8,
47550
+ stability: input.stability ?? "durable",
47551
+ source: input.source ?? { type: "manual", ref: fixture.name },
47552
+ createdAt: DEFAULT_TIMESTAMP,
47553
+ updatedAt: DEFAULT_TIMESTAMP,
47554
+ expiresAt: input.state?.expiresAt,
47555
+ supersededBy,
47556
+ contentHash: computeMemoryContentHash(base),
47557
+ metadata
47558
+ };
47559
+ if (record3.metadata.deleted === true || record3.supersededBy || record3.expiresAt && Date.parse(record3.expiresAt) <= Date.now()) {
47560
+ staleIds.add(record3.id);
47561
+ }
47562
+ const inScope = allowedScopeKeys.has(stableScopeKey(record3.scope));
47563
+ if (!inScope) {
47564
+ crossScopeIds.add(record3.id);
47565
+ } else if (!expectedIds.has(record3.id) && !staleIds.has(record3.id)) {
47566
+ sameScopeNoiseIds.add(record3.id);
47567
+ }
47568
+ return validateMemoryRecordRules(record3, { rejectDurableSecrets: true });
47569
+ });
47570
+ return {
47571
+ records,
47572
+ idsByLabel,
47573
+ labelsById,
47574
+ expectedIds,
47575
+ staleIds,
47576
+ crossScopeIds,
47577
+ sameScopeNoiseIds
47578
+ };
47579
+ }
47580
+ function buildRun(args) {
47581
+ const { fixture, provider, mode, k, retrievedIds, materialized } = args;
47582
+ const topK = retrievedIds.slice(0, k);
47583
+ const relevantAtK = topK.filter((id) => materialized.expectedIds.has(id)).length;
47584
+ const crossScopeLeakCount = retrievedIds.filter((id) => materialized.crossScopeIds.has(id)).length;
47585
+ const staleMemoryCount = retrievedIds.filter((id) => materialized.staleIds.has(id)).length;
47586
+ const noisyInjectionCount = mode === "injection" ? retrievedIds.filter((id) => materialized.sameScopeNoiseIds.has(id)).length : 0;
47587
+ const sameScopeNoiseCount = retrievedIds.filter((id) => materialized.sameScopeNoiseIds.has(id)).length;
47588
+ const metrics = {
47589
+ "precision@k": relevantAtK / Math.max(k, 1),
47590
+ "recall@k": relevantAtK / Math.max(materialized.expectedIds.size, 1),
47591
+ injection_count: mode === "injection" ? retrievedIds.length : 0,
47592
+ noisy_injection_count: noisyInjectionCount,
47593
+ same_scope_noise_count: sameScopeNoiseCount,
47594
+ cross_scope_leak_count: crossScopeLeakCount,
47595
+ stale_memory_count: staleMemoryCount
47596
+ };
47597
+ return {
47598
+ fixture: fixture.name,
47599
+ provider,
47600
+ mode,
47601
+ k,
47602
+ query: fixture.query,
47603
+ expected_labels: fixture.expectedLabels,
47604
+ expected_ids: fixture.expectedLabels.map((label) => materialized.idsByLabel.get(label) ?? label),
47605
+ retrieved_labels: retrievedIds.map((id) => materialized.labelsById.get(id) ?? id),
47606
+ retrieved_ids: retrievedIds,
47607
+ metrics,
47608
+ passed: metrics["recall@k"] >= 1 && metrics.noisy_injection_count === 0 && metrics.cross_scope_leak_count === 0 && metrics.stale_memory_count === 0
47609
+ };
47610
+ }
47611
+ function summarizeRuns(fixtureCount, runs) {
47612
+ const total = runs.reduce((acc, run) => {
47613
+ acc["precision@k"] += run.metrics["precision@k"];
47614
+ acc["recall@k"] += run.metrics["recall@k"];
47615
+ acc.injection_count += run.metrics.injection_count;
47616
+ acc.noisy_injection_count += run.metrics.noisy_injection_count;
47617
+ acc.same_scope_noise_count += run.metrics.same_scope_noise_count;
47618
+ acc.cross_scope_leak_count += run.metrics.cross_scope_leak_count;
47619
+ acc.stale_memory_count += run.metrics.stale_memory_count;
47620
+ if (run.passed)
47621
+ acc.passed_run_count++;
47622
+ return acc;
47623
+ }, {
47624
+ "precision@k": 0,
47625
+ "recall@k": 0,
47626
+ injection_count: 0,
47627
+ noisy_injection_count: 0,
47628
+ same_scope_noise_count: 0,
47629
+ cross_scope_leak_count: 0,
47630
+ stale_memory_count: 0,
47631
+ passed_run_count: 0
47632
+ });
47633
+ const denominator = Math.max(runs.length, 1);
47634
+ return {
47635
+ fixture_count: fixtureCount,
47636
+ run_count: runs.length,
47637
+ passed_run_count: total.passed_run_count,
47638
+ "precision@k": total["precision@k"] / denominator,
47639
+ "recall@k": total["recall@k"] / denominator,
47640
+ injection_count: total.injection_count,
47641
+ noisy_injection_count: total.noisy_injection_count,
47642
+ same_scope_noise_count: total.same_scope_noise_count,
47643
+ cross_scope_leak_count: total.cross_scope_leak_count,
47644
+ stale_memory_count: total.stale_memory_count
47645
+ };
47646
+ }
47647
+ function validateFixture(value, file3) {
47648
+ if (!value || typeof value !== "object") {
47649
+ throw new Error(`memory recall fixture ${file3} must be an object`);
47650
+ }
47651
+ const fixture = value;
47652
+ if (typeof fixture.name !== "string" || !fixture.name) {
47653
+ throw new Error(`memory recall fixture ${file3} is missing name`);
47654
+ }
47655
+ if (typeof fixture.query !== "string" || fixture.query.length < 3) {
47656
+ throw new Error(`memory recall fixture ${file3} has invalid query`);
47657
+ }
47658
+ if (!Array.isArray(fixture.scopes) || fixture.scopes.length === 0) {
47659
+ throw new Error(`memory recall fixture ${file3} must define scopes`);
47660
+ }
47661
+ const scopes = fixture.scopes.map((scope, index) => validateScope(scope, file3, `scope #${index + 1}`));
47662
+ if (!Array.isArray(fixture.expectedLabels) || fixture.expectedLabels.length === 0) {
47663
+ throw new Error(`memory recall fixture ${file3} must define expectedLabels`);
47664
+ }
47665
+ const expectedLabels = fixture.expectedLabels.map((label, index) => {
47666
+ if (typeof label !== "string" || !label) {
47667
+ throw new Error(`memory recall fixture ${file3} expectedLabels #${index + 1} must be a non-empty string`);
47668
+ }
47669
+ return label;
47670
+ });
47671
+ if (!Array.isArray(fixture.records) || fixture.records.length === 0) {
47672
+ throw new Error(`memory recall fixture ${file3} must define records`);
47673
+ }
47674
+ const records = fixture.records.map((record3, index) => validateFixtureRecord(record3, file3, index));
47675
+ return {
47676
+ ...fixture,
47677
+ name: fixture.name,
47678
+ query: fixture.query,
47679
+ scopes,
47680
+ expectedLabels,
47681
+ records
47682
+ };
47683
+ }
47684
+ function validateFixtureRecord(value, file3, index) {
47685
+ if (!value || typeof value !== "object") {
47686
+ throw new Error(`memory recall fixture ${file3} record #${index + 1} must be an object`);
47687
+ }
47688
+ const record3 = value;
47689
+ const labelForError = typeof record3.label === "string" && record3.label ? record3.label : `#${index + 1}`;
47690
+ if (typeof record3.label !== "string" || !record3.label) {
47691
+ throw new Error(`memory recall fixture ${file3} record ${labelForError} is missing label`);
47692
+ }
47693
+ const scope = validateScope(record3.scope, file3, `record ${record3.label}`);
47694
+ if (!("kind" in record3) || record3.kind === "") {
47695
+ throw new Error(`memory recall fixture ${file3} record ${record3.label} is missing kind`);
47696
+ }
47697
+ if (typeof record3.kind !== "string") {
47698
+ throw new Error(`memory recall fixture ${file3} record ${record3.label} has invalid kind`);
47699
+ }
47700
+ const parsedKind = MemoryKindSchema.safeParse(record3.kind);
47701
+ if (!parsedKind.success) {
47702
+ throw new Error(`memory recall fixture ${file3} record ${record3.label} has invalid kind`);
47703
+ }
47704
+ if (!("text" in record3) || record3.text === "") {
47705
+ throw new Error(`memory recall fixture ${file3} record ${record3.label} is missing text`);
47706
+ }
47707
+ if (typeof record3.text !== "string") {
47708
+ throw new Error(`memory recall fixture ${file3} record ${record3.label} has invalid text`);
47709
+ }
47710
+ return {
47711
+ ...record3,
47712
+ label: record3.label,
47713
+ scope,
47714
+ kind: parsedKind.data,
47715
+ text: record3.text
47716
+ };
47717
+ }
47718
+ function validateScope(value, file3, descriptor) {
47719
+ if (!value || typeof value !== "object") {
47720
+ throw new Error(`memory recall fixture ${file3} ${descriptor} is missing scope`);
47721
+ }
47722
+ const scope = value;
47723
+ if (typeof scope.type !== "string") {
47724
+ throw new Error(`memory recall fixture ${file3} ${descriptor} has invalid scope type`);
47725
+ }
47726
+ const parsed = MemoryScopeRefSchema.safeParse(scope);
47727
+ if (!parsed.success) {
47728
+ throw new Error(`memory recall fixture ${file3} ${descriptor} has invalid scope`);
47729
+ }
47730
+ return parsed.data;
47731
+ }
47732
+ var DEFAULT_PROVIDERS, DEFAULT_MODES, DEFAULT_TIMESTAMP = "2026-05-26T12:00:00.000Z";
47733
+ var init_evaluation = __esm(() => {
47734
+ init_config3();
47735
+ init_gateway();
47736
+ init_schema2();
47737
+ DEFAULT_PROVIDERS = [
47738
+ "local-jsonl",
47739
+ "sqlite"
47740
+ ];
47741
+ DEFAULT_MODES = [
47742
+ "manual",
47743
+ "injection",
47744
+ "curator"
47745
+ ];
47746
+ });
47747
+
47421
47748
  // src/agents/agent-output-schema.ts
47422
47749
  var AgentMemoryProposalSchema, AgentOutputMemorySchema, CuratorOutputMemoryDecisionSchema;
47423
47750
  var init_agent_output_schema = __esm(() => {
@@ -47472,6 +47799,7 @@ var init_injector = __esm(() => {
47472
47799
  var init_memory = __esm(() => {
47473
47800
  init_config3();
47474
47801
  init_errors6();
47802
+ init_evaluation();
47475
47803
  init_gateway();
47476
47804
  init_injector();
47477
47805
  init_jsonl_migration();
@@ -47487,6 +47815,8 @@ var init_memory = __esm(() => {
47487
47815
 
47488
47816
  // src/commands/memory.ts
47489
47817
  import { existsSync as existsSync20 } from "fs";
47818
+ import * as path33 from "path";
47819
+ import { fileURLToPath as fileURLToPath2 } from "url";
47490
47820
  async function handleMemoryCommand(_directory, _args) {
47491
47821
  return [
47492
47822
  "## Swarm Memory",
@@ -47494,7 +47824,8 @@ async function handleMemoryCommand(_directory, _args) {
47494
47824
  "- `/swarm memory status` - show provider, SQLite path, JSONL files, and last migration report",
47495
47825
  "- `/swarm memory export` - export current memory and proposals to `.swarm/memory/export/*.jsonl`",
47496
47826
  "- `/swarm memory import` - import `.swarm/memory/{memories,proposals}.jsonl` into SQLite",
47497
- "- `/swarm memory migrate` - run the one-time legacy JSONL to SQLite migration"
47827
+ "- `/swarm memory migrate` - run the one-time legacy JSONL to SQLite migration",
47828
+ "- `/swarm memory evaluate --json` - run the golden recall evaluation fixtures and emit a JSON report"
47498
47829
  ].join(`
47499
47830
  `);
47500
47831
  }
@@ -47592,10 +47923,75 @@ async function handleMemoryExportCommand(directory, _args) {
47592
47923
  await provider.close?.();
47593
47924
  }
47594
47925
  }
47926
+ async function handleMemoryEvaluateCommand(directory, args) {
47927
+ const parsed = parseEvaluateArgs(directory, args);
47928
+ if ("error" in parsed)
47929
+ return parsed.error;
47930
+ const report = await evaluateMemoryRecallFixtures({
47931
+ fixtureDirectory: parsed.fixtureDirectory
47932
+ });
47933
+ if (parsed.json)
47934
+ return `${JSON.stringify(report, null, 2)}
47935
+ `;
47936
+ return [
47937
+ "## Swarm Memory Recall Evaluation",
47938
+ "",
47939
+ `- Fixtures: \`${report.summary.fixture_count}\``,
47940
+ `- Runs: \`${report.summary.run_count}\``,
47941
+ `- Passed runs: \`${report.summary.passed_run_count}\``,
47942
+ `- Precision@k: \`${report.summary["precision@k"].toFixed(3)}\``,
47943
+ `- Recall@k: \`${report.summary["recall@k"].toFixed(3)}\``,
47944
+ `- Injection count: \`${report.summary.injection_count}\``,
47945
+ `- Noisy injections: \`${report.summary.noisy_injection_count}\``,
47946
+ `- Same-scope noise: \`${report.summary.same_scope_noise_count}\``,
47947
+ `- Cross-scope leaks: \`${report.summary.cross_scope_leak_count}\``,
47948
+ `- Stale memories: \`${report.summary.stale_memory_count}\``,
47949
+ "",
47950
+ "Use `/swarm memory evaluate --json` for the full report."
47951
+ ].join(`
47952
+ `);
47953
+ }
47595
47954
  function resolveCommandMemoryConfig(directory) {
47596
47955
  const loaded = loadPluginConfig(directory).memory;
47597
47956
  return resolveMemoryConfig(loaded ?? DEFAULT_MEMORY_CONFIG);
47598
47957
  }
47958
+ function parseEvaluateArgs(directory, args) {
47959
+ let json3 = false;
47960
+ let fixtureDirectory = path33.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall");
47961
+ for (let i = 0;i < args.length; i++) {
47962
+ const arg = args[i];
47963
+ if (arg === "--json") {
47964
+ json3 = true;
47965
+ continue;
47966
+ }
47967
+ if (arg === "--fixtures") {
47968
+ const next = args[i + 1];
47969
+ if (!next) {
47970
+ return {
47971
+ error: "Usage: /swarm memory evaluate [--json] [--fixtures <directory>]"
47972
+ };
47973
+ }
47974
+ fixtureDirectory = path33.resolve(directory, next);
47975
+ i++;
47976
+ continue;
47977
+ }
47978
+ return {
47979
+ error: "Usage: /swarm memory evaluate [--json] [--fixtures <directory>]"
47980
+ };
47981
+ }
47982
+ return { json: json3, fixtureDirectory };
47983
+ }
47984
+ function resolvePackageRootFromModule(modulePath) {
47985
+ const moduleDir = path33.dirname(modulePath);
47986
+ const leaf = path33.basename(moduleDir);
47987
+ if (leaf === "commands" || leaf === "cli") {
47988
+ return path33.resolve(moduleDir, "..", "..");
47989
+ }
47990
+ if (leaf === "dist") {
47991
+ return path33.resolve(moduleDir, "..");
47992
+ }
47993
+ return path33.resolve(moduleDir, "..");
47994
+ }
47599
47995
  function formatMigrationResult(label, report) {
47600
47996
  if (!report) {
47601
47997
  return [
@@ -47635,9 +48031,11 @@ function appendInvalidRows(lines, invalidRows) {
47635
48031
  lines.push(`- ... ${invalidRows.length - 20} more`);
47636
48032
  }
47637
48033
  }
48034
+ var PACKAGE_ROOT;
47638
48035
  var init_memory2 = __esm(() => {
47639
48036
  init_loader();
47640
48037
  init_memory();
48038
+ PACKAGE_ROOT = path33.resolve(resolvePackageRootFromModule(fileURLToPath2(import.meta.url)));
47641
48039
  });
47642
48040
 
47643
48041
  // src/services/plan-service.ts
@@ -48024,8 +48422,8 @@ function containsControlChars(str) {
48024
48422
  var init_path_security = () => {};
48025
48423
 
48026
48424
  // src/tools/lint.ts
48027
- import * as fs12 from "fs";
48028
- import * as path32 from "path";
48425
+ import * as fs13 from "fs";
48426
+ import * as path34 from "path";
48029
48427
  function validateArgs(args) {
48030
48428
  if (typeof args !== "object" || args === null)
48031
48429
  return false;
@@ -48036,9 +48434,9 @@ function validateArgs(args) {
48036
48434
  }
48037
48435
  function getLinterCommand(linter, mode, projectDir) {
48038
48436
  const isWindows = process.platform === "win32";
48039
- const binDir = path32.join(projectDir, "node_modules", ".bin");
48040
- const biomeBin = isWindows ? path32.join(binDir, "biome.EXE") : path32.join(binDir, "biome");
48041
- const eslintBin = isWindows ? path32.join(binDir, "eslint.cmd") : path32.join(binDir, "eslint");
48437
+ const binDir = path34.join(projectDir, "node_modules", ".bin");
48438
+ const biomeBin = isWindows ? path34.join(binDir, "biome.EXE") : path34.join(binDir, "biome");
48439
+ const eslintBin = isWindows ? path34.join(binDir, "eslint.cmd") : path34.join(binDir, "eslint");
48042
48440
  switch (linter) {
48043
48441
  case "biome":
48044
48442
  if (mode === "fix") {
@@ -48054,7 +48452,7 @@ function getLinterCommand(linter, mode, projectDir) {
48054
48452
  }
48055
48453
  function getAdditionalLinterCommand(linter, mode, cwd) {
48056
48454
  const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
48057
- const gradlew = fs12.existsSync(path32.join(cwd, gradlewName)) ? path32.join(cwd, gradlewName) : null;
48455
+ const gradlew = fs13.existsSync(path34.join(cwd, gradlewName)) ? path34.join(cwd, gradlewName) : null;
48058
48456
  switch (linter) {
48059
48457
  case "ruff":
48060
48458
  return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
@@ -48088,12 +48486,12 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
48088
48486
  }
48089
48487
  }
48090
48488
  function detectRuff(cwd) {
48091
- if (fs12.existsSync(path32.join(cwd, "ruff.toml")))
48489
+ if (fs13.existsSync(path34.join(cwd, "ruff.toml")))
48092
48490
  return isCommandAvailable("ruff");
48093
48491
  try {
48094
- const pyproject = path32.join(cwd, "pyproject.toml");
48095
- if (fs12.existsSync(pyproject)) {
48096
- const content = fs12.readFileSync(pyproject, "utf-8");
48492
+ const pyproject = path34.join(cwd, "pyproject.toml");
48493
+ if (fs13.existsSync(pyproject)) {
48494
+ const content = fs13.readFileSync(pyproject, "utf-8");
48097
48495
  if (content.includes("[tool.ruff]"))
48098
48496
  return isCommandAvailable("ruff");
48099
48497
  }
@@ -48101,21 +48499,21 @@ function detectRuff(cwd) {
48101
48499
  return false;
48102
48500
  }
48103
48501
  function detectClippy(cwd) {
48104
- return fs12.existsSync(path32.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
48502
+ return fs13.existsSync(path34.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
48105
48503
  }
48106
48504
  function detectGolangciLint(cwd) {
48107
- return fs12.existsSync(path32.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
48505
+ return fs13.existsSync(path34.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
48108
48506
  }
48109
48507
  function detectCheckstyle(cwd) {
48110
- const hasMaven = fs12.existsSync(path32.join(cwd, "pom.xml"));
48111
- const hasGradle = fs12.existsSync(path32.join(cwd, "build.gradle")) || fs12.existsSync(path32.join(cwd, "build.gradle.kts"));
48112
- const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs12.existsSync(path32.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
48508
+ const hasMaven = fs13.existsSync(path34.join(cwd, "pom.xml"));
48509
+ const hasGradle = fs13.existsSync(path34.join(cwd, "build.gradle")) || fs13.existsSync(path34.join(cwd, "build.gradle.kts"));
48510
+ const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs13.existsSync(path34.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
48113
48511
  return (hasMaven || hasGradle) && hasBinary;
48114
48512
  }
48115
48513
  function detectKtlint(cwd) {
48116
- const hasKotlin = fs12.existsSync(path32.join(cwd, "build.gradle.kts")) || fs12.existsSync(path32.join(cwd, "build.gradle")) || (() => {
48514
+ const hasKotlin = fs13.existsSync(path34.join(cwd, "build.gradle.kts")) || fs13.existsSync(path34.join(cwd, "build.gradle")) || (() => {
48117
48515
  try {
48118
- return fs12.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
48516
+ return fs13.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
48119
48517
  } catch {
48120
48518
  return false;
48121
48519
  }
@@ -48124,7 +48522,7 @@ function detectKtlint(cwd) {
48124
48522
  }
48125
48523
  function detectDotnetFormat(cwd) {
48126
48524
  try {
48127
- const files = fs12.readdirSync(cwd);
48525
+ const files = fs13.readdirSync(cwd);
48128
48526
  const hasCsproj = files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"));
48129
48527
  return hasCsproj && isCommandAvailable("dotnet");
48130
48528
  } catch {
@@ -48132,14 +48530,14 @@ function detectDotnetFormat(cwd) {
48132
48530
  }
48133
48531
  }
48134
48532
  function detectCppcheck(cwd) {
48135
- if (fs12.existsSync(path32.join(cwd, "CMakeLists.txt"))) {
48533
+ if (fs13.existsSync(path34.join(cwd, "CMakeLists.txt"))) {
48136
48534
  return isCommandAvailable("cppcheck");
48137
48535
  }
48138
48536
  try {
48139
- const dirsToCheck = [cwd, path32.join(cwd, "src")];
48537
+ const dirsToCheck = [cwd, path34.join(cwd, "src")];
48140
48538
  const hasCpp = dirsToCheck.some((dir) => {
48141
48539
  try {
48142
- return fs12.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
48540
+ return fs13.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
48143
48541
  } catch {
48144
48542
  return false;
48145
48543
  }
@@ -48150,13 +48548,13 @@ function detectCppcheck(cwd) {
48150
48548
  }
48151
48549
  }
48152
48550
  function detectSwiftlint(cwd) {
48153
- return fs12.existsSync(path32.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
48551
+ return fs13.existsSync(path34.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
48154
48552
  }
48155
48553
  function detectDartAnalyze(cwd) {
48156
- return fs12.existsSync(path32.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
48554
+ return fs13.existsSync(path34.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
48157
48555
  }
48158
48556
  function detectRubocop(cwd) {
48159
- return (fs12.existsSync(path32.join(cwd, "Gemfile")) || fs12.existsSync(path32.join(cwd, "gems.rb")) || fs12.existsSync(path32.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
48557
+ return (fs13.existsSync(path34.join(cwd, "Gemfile")) || fs13.existsSync(path34.join(cwd, "gems.rb")) || fs13.existsSync(path34.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
48160
48558
  }
48161
48559
  function detectAdditionalLinter(cwd) {
48162
48560
  if (detectRuff(cwd))
@@ -48184,10 +48582,10 @@ function detectAdditionalLinter(cwd) {
48184
48582
  function findBinInAncestors(startDir, binName) {
48185
48583
  let dir = startDir;
48186
48584
  while (true) {
48187
- const candidate = path32.join(dir, "node_modules", ".bin", binName);
48188
- if (fs12.existsSync(candidate))
48585
+ const candidate = path34.join(dir, "node_modules", ".bin", binName);
48586
+ if (fs13.existsSync(candidate))
48189
48587
  return candidate;
48190
- const parent = path32.dirname(dir);
48588
+ const parent = path34.dirname(dir);
48191
48589
  if (parent === dir)
48192
48590
  break;
48193
48591
  dir = parent;
@@ -48196,11 +48594,11 @@ function findBinInAncestors(startDir, binName) {
48196
48594
  }
48197
48595
  function findBinInEnvPath(binName) {
48198
48596
  const searchPath = process.env.PATH ?? "";
48199
- for (const dir of searchPath.split(path32.delimiter)) {
48597
+ for (const dir of searchPath.split(path34.delimiter)) {
48200
48598
  if (!dir)
48201
48599
  continue;
48202
- const candidate = path32.join(dir, binName);
48203
- if (fs12.existsSync(candidate))
48600
+ const candidate = path34.join(dir, binName);
48601
+ if (fs13.existsSync(candidate))
48204
48602
  return candidate;
48205
48603
  }
48206
48604
  return null;
@@ -48208,17 +48606,17 @@ function findBinInEnvPath(binName) {
48208
48606
  async function detectAvailableLinter(directory) {
48209
48607
  if (!directory)
48210
48608
  return null;
48211
- if (!fs12.existsSync(directory))
48609
+ if (!fs13.existsSync(directory))
48212
48610
  return null;
48213
48611
  const projectDir = directory;
48214
48612
  const isWindows = process.platform === "win32";
48215
- const biomeBin = isWindows ? path32.join(projectDir, "node_modules", ".bin", "biome.EXE") : path32.join(projectDir, "node_modules", ".bin", "biome");
48216
- const eslintBin = isWindows ? path32.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path32.join(projectDir, "node_modules", ".bin", "eslint");
48613
+ const biomeBin = isWindows ? path34.join(projectDir, "node_modules", ".bin", "biome.EXE") : path34.join(projectDir, "node_modules", ".bin", "biome");
48614
+ const eslintBin = isWindows ? path34.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path34.join(projectDir, "node_modules", ".bin", "eslint");
48217
48615
  const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
48218
48616
  if (localResult)
48219
48617
  return localResult;
48220
- const biomeAncestor = findBinInAncestors(path32.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
48221
- const eslintAncestor = findBinInAncestors(path32.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
48618
+ const biomeAncestor = findBinInAncestors(path34.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
48619
+ const eslintAncestor = findBinInAncestors(path34.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
48222
48620
  if (biomeAncestor || eslintAncestor) {
48223
48621
  return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
48224
48622
  }
@@ -48237,11 +48635,11 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
48237
48635
  stderr: "pipe"
48238
48636
  });
48239
48637
  const biomeExit = biomeProc.exited;
48240
- const timeout = new Promise((resolve10) => setTimeout(() => resolve10("timeout"), DETECT_TIMEOUT));
48638
+ const timeout = new Promise((resolve12) => setTimeout(() => resolve12("timeout"), DETECT_TIMEOUT));
48241
48639
  const result = await Promise.race([biomeExit, timeout]);
48242
48640
  if (result === "timeout") {
48243
48641
  biomeProc.kill();
48244
- } else if (biomeProc.exitCode === 0 && fs12.existsSync(biomeBin)) {
48642
+ } else if (biomeProc.exitCode === 0 && fs13.existsSync(biomeBin)) {
48245
48643
  return "biome";
48246
48644
  }
48247
48645
  } catch {}
@@ -48251,11 +48649,11 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
48251
48649
  stderr: "pipe"
48252
48650
  });
48253
48651
  const eslintExit = eslintProc.exited;
48254
- const timeout = new Promise((resolve10) => setTimeout(() => resolve10("timeout"), DETECT_TIMEOUT));
48652
+ const timeout = new Promise((resolve12) => setTimeout(() => resolve12("timeout"), DETECT_TIMEOUT));
48255
48653
  const result = await Promise.race([eslintExit, timeout]);
48256
48654
  if (result === "timeout") {
48257
48655
  eslintProc.kill();
48258
- } else if (eslintProc.exitCode === 0 && fs12.existsSync(eslintBin)) {
48656
+ } else if (eslintProc.exitCode === 0 && fs13.existsSync(eslintBin)) {
48259
48657
  return "eslint";
48260
48658
  }
48261
48659
  } catch {}
@@ -48440,8 +48838,8 @@ For Rust: rustup component add clippy`
48440
48838
  });
48441
48839
 
48442
48840
  // src/tools/secretscan.ts
48443
- import * as fs13 from "fs";
48444
- import * as path33 from "path";
48841
+ import * as fs14 from "fs";
48842
+ import * as path35 from "path";
48445
48843
  function calculateShannonEntropy(str) {
48446
48844
  if (str.length === 0)
48447
48845
  return 0;
@@ -48489,11 +48887,11 @@ function isGlobOrPathPattern(pattern) {
48489
48887
  return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
48490
48888
  }
48491
48889
  function loadSecretScanIgnore(scanDir) {
48492
- const ignorePath = path33.join(scanDir, ".secretscanignore");
48890
+ const ignorePath = path35.join(scanDir, ".secretscanignore");
48493
48891
  try {
48494
- if (!fs13.existsSync(ignorePath))
48892
+ if (!fs14.existsSync(ignorePath))
48495
48893
  return [];
48496
- const content = fs13.readFileSync(ignorePath, "utf8");
48894
+ const content = fs14.readFileSync(ignorePath, "utf8");
48497
48895
  const patterns = [];
48498
48896
  for (const rawLine of content.split(/\r?\n/)) {
48499
48897
  const line = rawLine.trim();
@@ -48512,7 +48910,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
48512
48910
  if (exactNames.has(entry))
48513
48911
  return true;
48514
48912
  for (const pattern of globPatterns) {
48515
- if (path33.matchesGlob(relPath, pattern))
48913
+ if (path35.matchesGlob(relPath, pattern))
48516
48914
  return true;
48517
48915
  }
48518
48916
  return false;
@@ -48533,7 +48931,7 @@ function validateDirectoryInput(dir) {
48533
48931
  return null;
48534
48932
  }
48535
48933
  function isBinaryFile(filePath, buffer) {
48536
- const ext = path33.extname(filePath).toLowerCase();
48934
+ const ext = path35.extname(filePath).toLowerCase();
48537
48935
  if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
48538
48936
  return true;
48539
48937
  }
@@ -48611,7 +49009,7 @@ function createRedactedContext(line, findings) {
48611
49009
  function scanFileForSecrets(filePath) {
48612
49010
  const findings = [];
48613
49011
  try {
48614
- const lstat = fs13.lstatSync(filePath);
49012
+ const lstat = fs14.lstatSync(filePath);
48615
49013
  if (lstat.isSymbolicLink()) {
48616
49014
  return findings;
48617
49015
  }
@@ -48620,14 +49018,14 @@ function scanFileForSecrets(filePath) {
48620
49018
  }
48621
49019
  let buffer;
48622
49020
  if (O_NOFOLLOW !== undefined) {
48623
- const fd = fs13.openSync(filePath, "r", O_NOFOLLOW);
49021
+ const fd = fs14.openSync(filePath, "r", O_NOFOLLOW);
48624
49022
  try {
48625
- buffer = fs13.readFileSync(fd);
49023
+ buffer = fs14.readFileSync(fd);
48626
49024
  } finally {
48627
- fs13.closeSync(fd);
49025
+ fs14.closeSync(fd);
48628
49026
  }
48629
49027
  } else {
48630
- buffer = fs13.readFileSync(filePath);
49028
+ buffer = fs14.readFileSync(filePath);
48631
49029
  }
48632
49030
  if (isBinaryFile(filePath, buffer)) {
48633
49031
  return findings;
@@ -48669,9 +49067,9 @@ function isSymlinkLoop(realPath, visited) {
48669
49067
  return false;
48670
49068
  }
48671
49069
  function isPathWithinScope(realPath, scanDir) {
48672
- const resolvedScanDir = path33.resolve(scanDir);
48673
- const resolvedRealPath = path33.resolve(realPath);
48674
- return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path33.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
49070
+ const resolvedScanDir = path35.resolve(scanDir);
49071
+ const resolvedRealPath = path35.resolve(realPath);
49072
+ return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path35.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
48675
49073
  }
48676
49074
  function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
48677
49075
  skippedDirs: 0,
@@ -48682,7 +49080,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
48682
49080
  const files = [];
48683
49081
  let entries;
48684
49082
  try {
48685
- entries = fs13.readdirSync(dir);
49083
+ entries = fs14.readdirSync(dir);
48686
49084
  } catch {
48687
49085
  stats.fileErrors++;
48688
49086
  return files;
@@ -48697,15 +49095,15 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
48697
49095
  return a.localeCompare(b);
48698
49096
  });
48699
49097
  for (const entry of entries) {
48700
- const fullPath = path33.join(dir, entry);
48701
- const relPath = path33.relative(scanDir, fullPath).replace(/\\/g, "/");
49098
+ const fullPath = path35.join(dir, entry);
49099
+ const relPath = path35.relative(scanDir, fullPath).replace(/\\/g, "/");
48702
49100
  if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
48703
49101
  stats.skippedDirs++;
48704
49102
  continue;
48705
49103
  }
48706
49104
  let lstat;
48707
49105
  try {
48708
- lstat = fs13.lstatSync(fullPath);
49106
+ lstat = fs14.lstatSync(fullPath);
48709
49107
  } catch {
48710
49108
  stats.fileErrors++;
48711
49109
  continue;
@@ -48717,7 +49115,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
48717
49115
  if (lstat.isDirectory()) {
48718
49116
  let realPath;
48719
49117
  try {
48720
- realPath = fs13.realpathSync(fullPath);
49118
+ realPath = fs14.realpathSync(fullPath);
48721
49119
  } catch {
48722
49120
  stats.fileErrors++;
48723
49121
  continue;
@@ -48733,7 +49131,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
48733
49131
  const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
48734
49132
  files.push(...subFiles);
48735
49133
  } else if (lstat.isFile()) {
48736
- const ext = path33.extname(fullPath).toLowerCase();
49134
+ const ext = path35.extname(fullPath).toLowerCase();
48737
49135
  if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
48738
49136
  files.push(fullPath);
48739
49137
  } else {
@@ -48936,7 +49334,7 @@ var init_secretscan = __esm(() => {
48936
49334
  redactTemplate: () => "SK[REDACTED]"
48937
49335
  }
48938
49336
  ];
48939
- O_NOFOLLOW = process.platform !== "win32" ? fs13.constants.O_NOFOLLOW : undefined;
49337
+ O_NOFOLLOW = process.platform !== "win32" ? fs14.constants.O_NOFOLLOW : undefined;
48940
49338
  secretscan = createSwarmTool({
48941
49339
  description: "Scan directory for potential secrets (API keys, tokens, passwords) using regex patterns and entropy heuristics. Returns metadata-only findings with redacted previews - NEVER returns raw secrets. Excludes common directories (node_modules, .git, dist, etc.) by default. Supports glob patterns (e.g. **/.svelte-kit/**, **/*.test.ts) and reads .secretscanignore at the scan root.",
48942
49340
  args: {
@@ -48993,15 +49391,15 @@ var init_secretscan = __esm(() => {
48993
49391
  }
48994
49392
  }
48995
49393
  try {
48996
- const _scanDirRaw = path33.resolve(directory);
49394
+ const _scanDirRaw = path35.resolve(directory);
48997
49395
  const scanDir = (() => {
48998
49396
  try {
48999
- return fs13.realpathSync(_scanDirRaw);
49397
+ return fs14.realpathSync(_scanDirRaw);
49000
49398
  } catch {
49001
49399
  return _scanDirRaw;
49002
49400
  }
49003
49401
  })();
49004
- if (!fs13.existsSync(scanDir)) {
49402
+ if (!fs14.existsSync(scanDir)) {
49005
49403
  const errorResult = {
49006
49404
  error: "directory not found",
49007
49405
  scan_dir: directory,
@@ -49012,7 +49410,7 @@ var init_secretscan = __esm(() => {
49012
49410
  };
49013
49411
  return JSON.stringify(errorResult, null, 2);
49014
49412
  }
49015
- const dirStat = fs13.statSync(scanDir);
49413
+ const dirStat = fs14.statSync(scanDir);
49016
49414
  if (!dirStat.isDirectory()) {
49017
49415
  const errorResult = {
49018
49416
  error: "target must be a directory, not a file",
@@ -49063,7 +49461,7 @@ var init_secretscan = __esm(() => {
49063
49461
  break;
49064
49462
  const fileFindings = scanFileForSecrets(filePath);
49065
49463
  try {
49066
- const stat4 = fs13.statSync(filePath);
49464
+ const stat4 = fs14.statSync(filePath);
49067
49465
  if (stat4.size > MAX_FILE_SIZE_BYTES) {
49068
49466
  skippedFiles++;
49069
49467
  continue;
@@ -49139,12 +49537,12 @@ var init_secretscan = __esm(() => {
49139
49537
  });
49140
49538
 
49141
49539
  // src/lang/default-backend.ts
49142
- import * as fs14 from "fs";
49143
- import * as path34 from "path";
49540
+ import * as fs15 from "fs";
49541
+ import * as path36 from "path";
49144
49542
  function detectFileExists(dir, pattern) {
49145
49543
  if (pattern.includes("*") || pattern.includes("?")) {
49146
49544
  try {
49147
- const files = fs14.readdirSync(dir);
49545
+ const files = fs15.readdirSync(dir);
49148
49546
  const regex = new RegExp(`^${pattern.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, ".")}$`);
49149
49547
  return files.some((f) => regex.test(f));
49150
49548
  } catch {
@@ -49152,7 +49550,7 @@ function detectFileExists(dir, pattern) {
49152
49550
  }
49153
49551
  }
49154
49552
  try {
49155
- fs14.accessSync(path34.join(dir, pattern));
49553
+ fs15.accessSync(path36.join(dir, pattern));
49156
49554
  return true;
49157
49555
  } catch {
49158
49556
  return false;
@@ -49280,8 +49678,8 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
49280
49678
  return ["mvn", "test"];
49281
49679
  case "gradle": {
49282
49680
  const isWindows = process.platform === "win32";
49283
- const hasGradlewBat = fs14.existsSync(path34.join(dir, "gradlew.bat"));
49284
- const hasGradlew = fs14.existsSync(path34.join(dir, "gradlew"));
49681
+ const hasGradlewBat = fs15.existsSync(path36.join(dir, "gradlew.bat"));
49682
+ const hasGradlew = fs15.existsSync(path36.join(dir, "gradlew"));
49285
49683
  if (hasGradlewBat && isWindows)
49286
49684
  return ["gradlew.bat", "test"];
49287
49685
  if (hasGradlew)
@@ -49298,7 +49696,7 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
49298
49696
  "cmake-build-release",
49299
49697
  "out"
49300
49698
  ];
49301
- const actualBuildDir = buildDirCandidates.find((d) => fs14.existsSync(path34.join(dir, d, "CMakeCache.txt"))) ?? "build";
49699
+ const actualBuildDir = buildDirCandidates.find((d) => fs15.existsSync(path36.join(dir, d, "CMakeCache.txt"))) ?? "build";
49302
49700
  return ["ctest", "--test-dir", actualBuildDir];
49303
49701
  }
49304
49702
  case "swift-test":
@@ -49585,23 +49983,23 @@ async function defaultSelectBuildCommand(profile, dir) {
49585
49983
  return null;
49586
49984
  }
49587
49985
  async function defaultTestFilesFor(profile, sourceFile, dir) {
49588
- const ext = path34.extname(sourceFile);
49986
+ const ext = path36.extname(sourceFile);
49589
49987
  if (!profile.extensions.includes(ext))
49590
49988
  return [];
49591
- const base = path34.basename(sourceFile, ext);
49592
- const rel = path34.relative(dir, sourceFile);
49593
- const relDir = path34.dirname(rel);
49989
+ const base = path36.basename(sourceFile, ext);
49990
+ const rel = path36.relative(dir, sourceFile);
49991
+ const relDir = path36.dirname(rel);
49594
49992
  const stripSrc = relDir.replace(/^src(\/|\\)/, "");
49595
49993
  const candidates = new Set;
49596
49994
  for (const tDir of ["tests", "test", "__tests__", "spec"]) {
49597
49995
  for (const suffix of ["", "_test", ".test", "_spec", ".spec"]) {
49598
- candidates.add(path34.join(dir, tDir, stripSrc, `${base}${suffix}${ext}`));
49996
+ candidates.add(path36.join(dir, tDir, stripSrc, `${base}${suffix}${ext}`));
49599
49997
  }
49600
49998
  }
49601
49999
  const existing = [];
49602
50000
  for (const c of candidates) {
49603
50001
  try {
49604
- fs14.accessSync(c);
50002
+ fs15.accessSync(c);
49605
50003
  existing.push(c);
49606
50004
  } catch {}
49607
50005
  }
@@ -49635,8 +50033,8 @@ var init_default_backend = __esm(() => {
49635
50033
  });
49636
50034
 
49637
50035
  // src/lang/backends/go.ts
49638
- import * as fs15 from "fs";
49639
- import * as path35 from "path";
50036
+ import * as fs16 from "fs";
50037
+ import * as path37 from "path";
49640
50038
  function extractImports(_sourceFile, source) {
49641
50039
  const out = new Set;
49642
50040
  IMPORT_REGEX_SINGLE.lastIndex = 0;
@@ -49662,7 +50060,7 @@ function extractImports(_sourceFile, source) {
49662
50060
  async function selectFramework(dir) {
49663
50061
  let content;
49664
50062
  try {
49665
- content = fs15.readFileSync(path35.join(dir, "go.mod"), "utf-8");
50063
+ content = fs16.readFileSync(path37.join(dir, "go.mod"), "utf-8");
49666
50064
  } catch {
49667
50065
  return null;
49668
50066
  }
@@ -49683,16 +50081,16 @@ async function selectFramework(dir) {
49683
50081
  async function selectEntryPoints(dir) {
49684
50082
  const points = [];
49685
50083
  try {
49686
- fs15.accessSync(path35.join(dir, "main.go"));
50084
+ fs16.accessSync(path37.join(dir, "main.go"));
49687
50085
  points.push("main.go");
49688
50086
  } catch {}
49689
50087
  try {
49690
- const cmdDir = path35.join(dir, "cmd");
49691
- const subdirs = fs15.readdirSync(cmdDir, { withFileTypes: true }).filter((d) => d.isDirectory());
50088
+ const cmdDir = path37.join(dir, "cmd");
50089
+ const subdirs = fs16.readdirSync(cmdDir, { withFileTypes: true }).filter((d) => d.isDirectory());
49692
50090
  for (const sub of subdirs) {
49693
- const main = path35.join("cmd", sub.name, "main.go");
50091
+ const main = path37.join("cmd", sub.name, "main.go");
49694
50092
  try {
49695
- fs15.accessSync(path35.join(dir, main));
50093
+ fs16.accessSync(path37.join(dir, main));
49696
50094
  points.push(main);
49697
50095
  } catch {}
49698
50096
  }
@@ -49722,8 +50120,8 @@ var init_go = __esm(() => {
49722
50120
  });
49723
50121
 
49724
50122
  // src/lang/backends/python.ts
49725
- import * as fs16 from "fs";
49726
- import * as path36 from "path";
50123
+ import * as fs17 from "fs";
50124
+ import * as path38 from "path";
49727
50125
  function parseImportTargets(rawTargets) {
49728
50126
  const cleaned = rawTargets.replace(/[()]/g, "").split(`
49729
50127
  `).map((line) => line.replace(/#.*$/, "").replace(/\\\s*$/, "")).join(" ");
@@ -49783,7 +50181,7 @@ async function selectFramework2(dir) {
49783
50181
  ];
49784
50182
  for (const candidate of ["pyproject.toml", "requirements.txt", "setup.py"]) {
49785
50183
  try {
49786
- const content = fs16.readFileSync(path36.join(dir, candidate), "utf-8");
50184
+ const content = fs17.readFileSync(path38.join(dir, candidate), "utf-8");
49787
50185
  const lower = content.toLowerCase();
49788
50186
  for (const [pkg, name] of candidates) {
49789
50187
  if (lower.includes(pkg)) {
@@ -49797,7 +50195,7 @@ async function selectFramework2(dir) {
49797
50195
  async function selectEntryPoints2(dir) {
49798
50196
  const points = new Set;
49799
50197
  try {
49800
- const content = fs16.readFileSync(path36.join(dir, "pyproject.toml"), "utf-8");
50198
+ const content = fs17.readFileSync(path38.join(dir, "pyproject.toml"), "utf-8");
49801
50199
  const scriptsBlock = content.match(/\[project\.scripts\][\s\S]*?(?=\n\[|$)/);
49802
50200
  if (scriptsBlock) {
49803
50201
  for (const line of scriptsBlock[0].split(`
@@ -49812,7 +50210,7 @@ async function selectEntryPoints2(dir) {
49812
50210
  } catch {}
49813
50211
  for (const name of ["manage.py", "main.py", "app.py", "__main__.py"]) {
49814
50212
  try {
49815
- fs16.accessSync(path36.join(dir, name));
50213
+ fs17.accessSync(path38.join(dir, name));
49816
50214
  points.add(name);
49817
50215
  } catch {}
49818
50216
  }
@@ -49840,15 +50238,15 @@ var init_python = __esm(() => {
49840
50238
  });
49841
50239
 
49842
50240
  // src/test-impact/analyzer.ts
49843
- import fs17 from "fs";
49844
- import path37 from "path";
50241
+ import fs18 from "fs";
50242
+ import path39 from "path";
49845
50243
  function normalizePath(p) {
49846
50244
  return p.replace(/\\/g, "/");
49847
50245
  }
49848
50246
  function isCacheStale(impactMap, generatedAtMs) {
49849
50247
  for (const sourcePath of Object.keys(impactMap)) {
49850
50248
  try {
49851
- const stat4 = fs17.statSync(sourcePath);
50249
+ const stat4 = fs18.statSync(sourcePath);
49852
50250
  if (stat4.mtimeMs > generatedAtMs) {
49853
50251
  return true;
49854
50252
  }
@@ -49862,15 +50260,15 @@ function resolveRelativeImport(fromDir, importPath) {
49862
50260
  if (!importPath.startsWith(".")) {
49863
50261
  return null;
49864
50262
  }
49865
- const resolved = path37.resolve(fromDir, importPath);
49866
- if (path37.extname(resolved)) {
49867
- if (fs17.existsSync(resolved) && fs17.statSync(resolved).isFile()) {
50263
+ const resolved = path39.resolve(fromDir, importPath);
50264
+ if (path39.extname(resolved)) {
50265
+ if (fs18.existsSync(resolved) && fs18.statSync(resolved).isFile()) {
49868
50266
  return normalizePath(resolved);
49869
50267
  }
49870
50268
  } else {
49871
50269
  for (const ext of EXTENSIONS_TO_TRY) {
49872
50270
  const withExt = resolved + ext;
49873
- if (fs17.existsSync(withExt) && fs17.statSync(withExt).isFile()) {
50271
+ if (fs18.existsSync(withExt) && fs18.statSync(withExt).isFile()) {
49874
50272
  return normalizePath(withExt);
49875
50273
  }
49876
50274
  }
@@ -49883,29 +50281,29 @@ function resolvePythonImport(fromDir, module) {
49883
50281
  const leadingDots = module.match(/^\.+/)?.[0].length ?? 0;
49884
50282
  let baseDir = fromDir;
49885
50283
  for (let i = 1;i < leadingDots; i++) {
49886
- baseDir = path37.dirname(baseDir);
50284
+ baseDir = path39.dirname(baseDir);
49887
50285
  }
49888
50286
  const rest = module.slice(leadingDots);
49889
50287
  if (rest.length === 0) {
49890
- const initPath = path37.join(baseDir, "__init__.py");
49891
- if (fs17.existsSync(initPath) && fs17.statSync(initPath).isFile()) {
50288
+ const initPath = path39.join(baseDir, "__init__.py");
50289
+ if (fs18.existsSync(initPath) && fs18.statSync(initPath).isFile()) {
49892
50290
  return normalizePath(initPath);
49893
50291
  }
49894
50292
  return null;
49895
50293
  }
49896
- const subpath = rest.replace(/\./g, path37.sep);
50294
+ const subpath = rest.replace(/\./g, path39.sep);
49897
50295
  const candidates = [
49898
- `${path37.join(baseDir, subpath)}.py`,
49899
- path37.join(baseDir, subpath, "__init__.py")
50296
+ `${path39.join(baseDir, subpath)}.py`,
50297
+ path39.join(baseDir, subpath, "__init__.py")
49900
50298
  ];
49901
50299
  for (const c of candidates) {
49902
- if (fs17.existsSync(c) && fs17.statSync(c).isFile())
50300
+ if (fs18.existsSync(c) && fs18.statSync(c).isFile())
49903
50301
  return normalizePath(c);
49904
50302
  }
49905
50303
  return null;
49906
50304
  }
49907
50305
  function findGoModule(fromDir) {
49908
- const resolved = path37.resolve(fromDir);
50306
+ const resolved = path39.resolve(fromDir);
49909
50307
  let cur = resolved;
49910
50308
  const walked = [];
49911
50309
  for (let i = 0;i < 16; i++) {
@@ -49917,8 +50315,8 @@ function findGoModule(fromDir) {
49917
50315
  }
49918
50316
  walked.push(cur);
49919
50317
  try {
49920
- const goMod = path37.join(cur, "go.mod");
49921
- const content = fs17.readFileSync(goMod, "utf-8");
50318
+ const goMod = path39.join(cur, "go.mod");
50319
+ const content = fs18.readFileSync(goMod, "utf-8");
49922
50320
  const moduleMatch = content.match(/^\s*module\s+"?([^"\s/]+(?:\/[^"\s]+)*)"?/m);
49923
50321
  if (moduleMatch) {
49924
50322
  const result = { moduleRoot: cur, modulePath: moduleMatch[1] };
@@ -49928,10 +50326,10 @@ function findGoModule(fromDir) {
49928
50326
  }
49929
50327
  } catch {}
49930
50328
  try {
49931
- fs17.accessSync(path37.join(cur, ".git"));
50329
+ fs18.accessSync(path39.join(cur, ".git"));
49932
50330
  break;
49933
50331
  } catch {}
49934
- const parent = path37.dirname(cur);
50332
+ const parent = path39.dirname(cur);
49935
50333
  if (parent === cur)
49936
50334
  break;
49937
50335
  cur = parent;
@@ -49943,20 +50341,20 @@ function findGoModule(fromDir) {
49943
50341
  function resolveGoImport(fromDir, importPath) {
49944
50342
  let dir = null;
49945
50343
  if (importPath.startsWith(".")) {
49946
- dir = path37.resolve(fromDir, importPath);
50344
+ dir = path39.resolve(fromDir, importPath);
49947
50345
  } else {
49948
50346
  const mod = findGoModule(fromDir);
49949
50347
  if (mod && (importPath === mod.modulePath || importPath.startsWith(`${mod.modulePath}/`))) {
49950
50348
  const subpath = importPath.slice(mod.modulePath.length);
49951
- dir = path37.join(mod.moduleRoot, subpath);
50349
+ dir = path39.join(mod.moduleRoot, subpath);
49952
50350
  }
49953
50351
  }
49954
50352
  if (dir === null)
49955
50353
  return [];
49956
- if (!fs17.existsSync(dir) || !fs17.statSync(dir).isDirectory())
50354
+ if (!fs18.existsSync(dir) || !fs18.statSync(dir).isDirectory())
49957
50355
  return [];
49958
50356
  try {
49959
- return fs17.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath(path37.join(dir, f)));
50357
+ return fs18.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath(path39.join(dir, f)));
49960
50358
  } catch {
49961
50359
  return [];
49962
50360
  }
@@ -49976,13 +50374,13 @@ function findTestFilesSync(cwd) {
49976
50374
  function walk(dir, visitedInodes) {
49977
50375
  let entries;
49978
50376
  try {
49979
- entries = fs17.readdirSync(dir, { withFileTypes: true });
50377
+ entries = fs18.readdirSync(dir, { withFileTypes: true });
49980
50378
  } catch {
49981
50379
  return;
49982
50380
  }
49983
50381
  let dirInode;
49984
50382
  try {
49985
- dirInode = fs17.statSync(dir).ino;
50383
+ dirInode = fs18.statSync(dir).ino;
49986
50384
  } catch {
49987
50385
  return;
49988
50386
  }
@@ -49995,15 +50393,15 @@ function findTestFilesSync(cwd) {
49995
50393
  for (const entry of entries) {
49996
50394
  if (entry.isDirectory()) {
49997
50395
  if (!skipDirs.has(entry.name)) {
49998
- walk(path37.join(dir, entry.name), visitedInodes);
50396
+ walk(path39.join(dir, entry.name), visitedInodes);
49999
50397
  }
50000
50398
  } else if (entry.isFile()) {
50001
50399
  const name = entry.name;
50002
50400
  const isTsTest = /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name);
50003
- const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${path37.sep}tests${path37.sep}`) && name.endsWith(".py");
50401
+ const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${path39.sep}tests${path39.sep}`) && name.endsWith(".py");
50004
50402
  const isGoTest = /.+_test\.go$/.test(name);
50005
50403
  if (isTsTest || isPyTest || isGoTest) {
50006
- testFiles.push(normalizePath(path37.join(dir, entry.name)));
50404
+ testFiles.push(normalizePath(path39.join(dir, entry.name)));
50007
50405
  }
50008
50406
  }
50009
50407
  }
@@ -50028,8 +50426,8 @@ function extractImports3(content) {
50028
50426
  ];
50029
50427
  }
50030
50428
  function addImpactEdgesForTestFile(testFile, content, impactMap) {
50031
- const ext = path37.extname(testFile).toLowerCase();
50032
- const testDir = path37.dirname(testFile);
50429
+ const ext = path39.extname(testFile).toLowerCase();
50430
+ const testDir = path39.dirname(testFile);
50033
50431
  function addEdge(source) {
50034
50432
  if (!impactMap[source])
50035
50433
  impactMap[source] = [];
@@ -50071,7 +50469,7 @@ async function buildImpactMapInternal(cwd) {
50071
50469
  for (const testFile of testFiles) {
50072
50470
  let content;
50073
50471
  try {
50074
- content = fs17.readFileSync(testFile, "utf-8");
50472
+ content = fs18.readFileSync(testFile, "utf-8");
50075
50473
  } catch {
50076
50474
  continue;
50077
50475
  }
@@ -50088,10 +50486,10 @@ async function buildImpactMap(cwd) {
50088
50486
  return impactMap;
50089
50487
  }
50090
50488
  async function loadImpactMap(cwd, options) {
50091
- const cachePath = path37.join(cwd, ".swarm", "cache", "impact-map.json");
50092
- if (fs17.existsSync(cachePath)) {
50489
+ const cachePath = path39.join(cwd, ".swarm", "cache", "impact-map.json");
50490
+ if (fs18.existsSync(cachePath)) {
50093
50491
  try {
50094
- const content = fs17.readFileSync(cachePath, "utf-8");
50492
+ const content = fs18.readFileSync(cachePath, "utf-8");
50095
50493
  const data = JSON.parse(content);
50096
50494
  if (data.map !== null && typeof data.map === "object" && !Array.isArray(data.map)) {
50097
50495
  const map3 = data.map;
@@ -50121,21 +50519,21 @@ async function loadImpactMap(cwd, options) {
50121
50519
  return _internals23.buildImpactMap(cwd);
50122
50520
  }
50123
50521
  async function saveImpactMap(cwd, impactMap) {
50124
- if (!path37.isAbsolute(cwd)) {
50522
+ if (!path39.isAbsolute(cwd)) {
50125
50523
  throw new Error(`saveImpactMap requires an absolute project root path, got: "${cwd}"`);
50126
50524
  }
50127
50525
  _internals23.validateProjectRoot(cwd);
50128
- const cacheDir2 = path37.join(cwd, ".swarm", "cache");
50129
- const cachePath = path37.join(cacheDir2, "impact-map.json");
50130
- if (!fs17.existsSync(cacheDir2)) {
50131
- fs17.mkdirSync(cacheDir2, { recursive: true });
50526
+ const cacheDir2 = path39.join(cwd, ".swarm", "cache");
50527
+ const cachePath = path39.join(cacheDir2, "impact-map.json");
50528
+ if (!fs18.existsSync(cacheDir2)) {
50529
+ fs18.mkdirSync(cacheDir2, { recursive: true });
50132
50530
  }
50133
50531
  const data = {
50134
50532
  generatedAt: new Date().toISOString(),
50135
50533
  fileCount: Object.keys(impactMap).length,
50136
50534
  map: impactMap
50137
50535
  };
50138
- fs17.writeFileSync(cachePath, JSON.stringify(data, null, 2), "utf-8");
50536
+ fs18.writeFileSync(cachePath, JSON.stringify(data, null, 2), "utf-8");
50139
50537
  }
50140
50538
  async function analyzeImpact(changedFiles, cwd, budget) {
50141
50539
  if (!Array.isArray(changedFiles)) {
@@ -50158,7 +50556,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
50158
50556
  budgetExceeded = true;
50159
50557
  break;
50160
50558
  }
50161
- const normalizedChanged = normalizePath(path37.resolve(changedFile));
50559
+ const normalizedChanged = normalizePath(path39.resolve(changedFile));
50162
50560
  const tests = impactMap[normalizedChanged];
50163
50561
  if (tests && tests.length > 0) {
50164
50562
  for (const test of tests) {
@@ -50450,16 +50848,16 @@ function detectFlakyTests(allHistory) {
50450
50848
  var FLAKY_THRESHOLD = 0.3, MIN_RUNS_FOR_QUARANTINE = 5, MAX_HISTORY_RUNS = 20;
50451
50849
 
50452
50850
  // src/test-impact/history-store.ts
50453
- import fs18 from "fs";
50454
- import path38 from "path";
50851
+ import fs19 from "fs";
50852
+ import path40 from "path";
50455
50853
  function getHistoryPath(workingDir) {
50456
50854
  if (!workingDir) {
50457
50855
  throw new Error("getHistoryPath requires a working directory \u2014 project root must be provided by the caller");
50458
50856
  }
50459
- if (!path38.isAbsolute(workingDir)) {
50857
+ if (!path40.isAbsolute(workingDir)) {
50460
50858
  throw new Error(`getHistoryPath requires an absolute project root path, got: "${workingDir}"`);
50461
50859
  }
50462
- return path38.join(workingDir, ".swarm", "cache", "test-history.jsonl");
50860
+ return path40.join(workingDir, ".swarm", "cache", "test-history.jsonl");
50463
50861
  }
50464
50862
  function sanitizeErrorMessage(errorMessage) {
50465
50863
  if (errorMessage === undefined) {
@@ -50546,10 +50944,10 @@ function batchAppendTestRuns(records, workingDir) {
50546
50944
  }
50547
50945
  }
50548
50946
  const historyPath = getHistoryPath(workingDir);
50549
- const historyDir = path38.dirname(historyPath);
50947
+ const historyDir = path40.dirname(historyPath);
50550
50948
  _internals24.validateProjectRoot(workingDir);
50551
- if (!fs18.existsSync(historyDir)) {
50552
- fs18.mkdirSync(historyDir, { recursive: true });
50949
+ if (!fs19.existsSync(historyDir)) {
50950
+ fs19.mkdirSync(historyDir, { recursive: true });
50553
50951
  }
50554
50952
  const existingRecords = readAllRecords(historyPath);
50555
50953
  const sanitizedRecords = records.map((record3) => ({
@@ -50582,24 +50980,24 @@ function batchAppendTestRuns(records, workingDir) {
50582
50980
  `)}
50583
50981
  `;
50584
50982
  const tempPath = `${historyPath}.tmp`;
50585
- fs18.writeFileSync(tempPath, content, "utf-8");
50586
- fs18.renameSync(tempPath, historyPath);
50983
+ fs19.writeFileSync(tempPath, content, "utf-8");
50984
+ fs19.renameSync(tempPath, historyPath);
50587
50985
  } catch (err) {
50588
50986
  try {
50589
50987
  const tempPath = `${historyPath}.tmp`;
50590
- if (fs18.existsSync(tempPath)) {
50591
- fs18.unlinkSync(tempPath);
50988
+ if (fs19.existsSync(tempPath)) {
50989
+ fs19.unlinkSync(tempPath);
50592
50990
  }
50593
50991
  } catch {}
50594
50992
  throw new Error(`Failed to write test history: ${err instanceof Error ? err.message : String(err)}`);
50595
50993
  }
50596
50994
  }
50597
50995
  function readAllRecords(historyPath) {
50598
- if (!fs18.existsSync(historyPath)) {
50996
+ if (!fs19.existsSync(historyPath)) {
50599
50997
  return [];
50600
50998
  }
50601
50999
  try {
50602
- const content = fs18.readFileSync(historyPath, "utf-8");
51000
+ const content = fs19.readFileSync(historyPath, "utf-8");
50603
51001
  const lines = content.split(`
50604
51002
  `);
50605
51003
  const records = [];
@@ -50641,8 +51039,8 @@ var init_history_store = __esm(() => {
50641
51039
  });
50642
51040
 
50643
51041
  // src/tools/resolve-working-directory.ts
50644
- import * as fs19 from "fs";
50645
- import * as path39 from "path";
51042
+ import * as fs20 from "fs";
51043
+ import * as path41 from "path";
50646
51044
  function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
50647
51045
  if (workingDirectory == null || workingDirectory === "") {
50648
51046
  return { success: true, directory: fallbackDirectory };
@@ -50662,18 +51060,18 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
50662
51060
  };
50663
51061
  }
50664
51062
  }
50665
- const normalizedDir = path39.normalize(workingDirectory);
50666
- const pathParts = normalizedDir.split(path39.sep);
51063
+ const normalizedDir = path41.normalize(workingDirectory);
51064
+ const pathParts = normalizedDir.split(path41.sep);
50667
51065
  if (pathParts.includes("..")) {
50668
51066
  return {
50669
51067
  success: false,
50670
51068
  message: "Invalid working_directory: path traversal sequences (..) are not allowed"
50671
51069
  };
50672
51070
  }
50673
- const resolvedDir = path39.resolve(normalizedDir);
51071
+ const resolvedDir = path41.resolve(normalizedDir);
50674
51072
  let statResult;
50675
51073
  try {
50676
- statResult = fs19.statSync(resolvedDir);
51074
+ statResult = fs20.statSync(resolvedDir);
50677
51075
  } catch {
50678
51076
  return {
50679
51077
  success: false,
@@ -50686,17 +51084,17 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
50686
51084
  message: `Invalid working_directory: path "${resolvedDir}" is not a directory`
50687
51085
  };
50688
51086
  }
50689
- const resolvedFallback = path39.resolve(fallbackDirectory);
51087
+ const resolvedFallback = path41.resolve(fallbackDirectory);
50690
51088
  let fallbackExists = false;
50691
51089
  try {
50692
- fs19.statSync(resolvedFallback);
51090
+ fs20.statSync(resolvedFallback);
50693
51091
  fallbackExists = true;
50694
51092
  } catch {
50695
51093
  fallbackExists = false;
50696
51094
  }
50697
51095
  if (workingDirectory != null && workingDirectory !== "") {
50698
51096
  if (fallbackExists) {
50699
- const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path39.sep);
51097
+ const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path41.sep);
50700
51098
  if (isSubdirectory) {
50701
51099
  return {
50702
51100
  success: false,
@@ -50750,11 +51148,11 @@ var init_registry_backend = __esm(() => {
50750
51148
  });
50751
51149
 
50752
51150
  // src/lang/backends/typescript.ts
50753
- import * as fs20 from "fs";
50754
- import * as path40 from "path";
51151
+ import * as fs21 from "fs";
51152
+ import * as path42 from "path";
50755
51153
  function readPackageJsonRaw(dir) {
50756
51154
  try {
50757
- const content = fs20.readFileSync(path40.join(dir, "package.json"), "utf-8");
51155
+ const content = fs21.readFileSync(path42.join(dir, "package.json"), "utf-8");
50758
51156
  return JSON.parse(content);
50759
51157
  } catch {
50760
51158
  return null;
@@ -50973,11 +51371,11 @@ __export(exports_dispatch, {
50973
51371
  clearDispatchCache: () => clearDispatchCache,
50974
51372
  _internals: () => _internals26
50975
51373
  });
50976
- import * as fs21 from "fs";
50977
- import * as path41 from "path";
51374
+ import * as fs22 from "fs";
51375
+ import * as path43 from "path";
50978
51376
  function safeReaddirSet(dir) {
50979
51377
  try {
50980
- return new Set(fs21.readdirSync(dir));
51378
+ return new Set(fs22.readdirSync(dir));
50981
51379
  } catch {
50982
51380
  return new Set;
50983
51381
  }
@@ -50991,14 +51389,14 @@ function manifestHash(dir) {
50991
51389
  if (!entries.has(name))
50992
51390
  continue;
50993
51391
  try {
50994
- const stat4 = fs21.statSync(path41.join(dir, name));
51392
+ const stat4 = fs22.statSync(path43.join(dir, name));
50995
51393
  parts.push(`${name}:${stat4.size}:${stat4.mtimeMs}:${stat4.ino}`);
50996
51394
  } catch {}
50997
51395
  }
50998
51396
  return parts.join("|");
50999
51397
  }
51000
51398
  function findManifestRoot(start) {
51001
- const resolved = path41.resolve(start);
51399
+ const resolved = path43.resolve(start);
51002
51400
  const cached3 = manifestRootCache.get(resolved);
51003
51401
  if (cached3 !== undefined)
51004
51402
  return cached3;
@@ -51017,7 +51415,7 @@ function findManifestRoot(start) {
51017
51415
  return cur;
51018
51416
  }
51019
51417
  }
51020
- const parent = path41.dirname(cur);
51418
+ const parent = path43.dirname(cur);
51021
51419
  if (parent === cur)
51022
51420
  break;
51023
51421
  cur = parent;
@@ -51126,14 +51524,14 @@ var init_dispatch = __esm(() => {
51126
51524
  });
51127
51525
 
51128
51526
  // src/tools/test-runner.ts
51129
- import * as fs22 from "fs";
51130
- import * as path42 from "path";
51527
+ import * as fs23 from "fs";
51528
+ import * as path44 from "path";
51131
51529
  async function estimateFanOut(sourceFiles, cwd) {
51132
51530
  try {
51133
51531
  const impactMap = await loadImpactMap(cwd, { skipRebuild: true });
51134
51532
  const uniqueTestFiles = new Set;
51135
51533
  for (const sourceFile of sourceFiles) {
51136
- const resolvedPath = path42.resolve(cwd, sourceFile);
51534
+ const resolvedPath = path44.resolve(cwd, sourceFile);
51137
51535
  const normalizedPath = resolvedPath.replace(/\\/g, "/");
51138
51536
  const testFiles = impactMap[normalizedPath];
51139
51537
  if (testFiles) {
@@ -51211,19 +51609,19 @@ function hasDevDependency(devDeps, ...patterns) {
51211
51609
  return hasPackageJsonDependency(devDeps, ...patterns);
51212
51610
  }
51213
51611
  function detectGoTest(cwd) {
51214
- return fs22.existsSync(path42.join(cwd, "go.mod")) && isCommandAvailable("go");
51612
+ return fs23.existsSync(path44.join(cwd, "go.mod")) && isCommandAvailable("go");
51215
51613
  }
51216
51614
  function detectJavaMaven(cwd) {
51217
- return fs22.existsSync(path42.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
51615
+ return fs23.existsSync(path44.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
51218
51616
  }
51219
51617
  function detectGradle(cwd) {
51220
- const hasBuildFile = fs22.existsSync(path42.join(cwd, "build.gradle")) || fs22.existsSync(path42.join(cwd, "build.gradle.kts"));
51221
- const hasGradlew = fs22.existsSync(path42.join(cwd, "gradlew")) || fs22.existsSync(path42.join(cwd, "gradlew.bat"));
51618
+ const hasBuildFile = fs23.existsSync(path44.join(cwd, "build.gradle")) || fs23.existsSync(path44.join(cwd, "build.gradle.kts"));
51619
+ const hasGradlew = fs23.existsSync(path44.join(cwd, "gradlew")) || fs23.existsSync(path44.join(cwd, "gradlew.bat"));
51222
51620
  return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
51223
51621
  }
51224
51622
  function detectDotnetTest(cwd) {
51225
51623
  try {
51226
- const files = fs22.readdirSync(cwd);
51624
+ const files = fs23.readdirSync(cwd);
51227
51625
  const hasCsproj = files.some((f) => f.endsWith(".csproj"));
51228
51626
  return hasCsproj && isCommandAvailable("dotnet");
51229
51627
  } catch {
@@ -51231,25 +51629,25 @@ function detectDotnetTest(cwd) {
51231
51629
  }
51232
51630
  }
51233
51631
  function detectCTest(cwd) {
51234
- const hasSource = fs22.existsSync(path42.join(cwd, "CMakeLists.txt"));
51235
- const hasBuildCache = fs22.existsSync(path42.join(cwd, "CMakeCache.txt")) || fs22.existsSync(path42.join(cwd, "build", "CMakeCache.txt"));
51632
+ const hasSource = fs23.existsSync(path44.join(cwd, "CMakeLists.txt"));
51633
+ const hasBuildCache = fs23.existsSync(path44.join(cwd, "CMakeCache.txt")) || fs23.existsSync(path44.join(cwd, "build", "CMakeCache.txt"));
51236
51634
  return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
51237
51635
  }
51238
51636
  function detectSwiftTest(cwd) {
51239
- return fs22.existsSync(path42.join(cwd, "Package.swift")) && isCommandAvailable("swift");
51637
+ return fs23.existsSync(path44.join(cwd, "Package.swift")) && isCommandAvailable("swift");
51240
51638
  }
51241
51639
  function detectDartTest(cwd) {
51242
- return fs22.existsSync(path42.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
51640
+ return fs23.existsSync(path44.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
51243
51641
  }
51244
51642
  function detectRSpec(cwd) {
51245
- const hasRSpecFile = fs22.existsSync(path42.join(cwd, ".rspec"));
51246
- const hasGemfile = fs22.existsSync(path42.join(cwd, "Gemfile"));
51247
- const hasSpecDir = fs22.existsSync(path42.join(cwd, "spec"));
51643
+ const hasRSpecFile = fs23.existsSync(path44.join(cwd, ".rspec"));
51644
+ const hasGemfile = fs23.existsSync(path44.join(cwd, "Gemfile"));
51645
+ const hasSpecDir = fs23.existsSync(path44.join(cwd, "spec"));
51248
51646
  const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
51249
51647
  return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
51250
51648
  }
51251
51649
  function detectMinitest(cwd) {
51252
- return fs22.existsSync(path42.join(cwd, "test")) && (fs22.existsSync(path42.join(cwd, "Gemfile")) || fs22.existsSync(path42.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
51650
+ return fs23.existsSync(path44.join(cwd, "test")) && (fs23.existsSync(path44.join(cwd, "Gemfile")) || fs23.existsSync(path44.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
51253
51651
  }
51254
51652
  async function detectTestFrameworkViaDispatch(cwd) {
51255
51653
  try {
@@ -51311,9 +51709,9 @@ async function parseTestOutputViaDispatch(framework, output, baseDir) {
51311
51709
  async function detectTestFramework(cwd) {
51312
51710
  const baseDir = cwd;
51313
51711
  try {
51314
- const packageJsonPath = path42.join(baseDir, "package.json");
51315
- if (fs22.existsSync(packageJsonPath)) {
51316
- const content = fs22.readFileSync(packageJsonPath, "utf-8");
51712
+ const packageJsonPath = path44.join(baseDir, "package.json");
51713
+ if (fs23.existsSync(packageJsonPath)) {
51714
+ const content = fs23.readFileSync(packageJsonPath, "utf-8");
51317
51715
  const pkg = JSON.parse(content);
51318
51716
  const _deps = pkg.dependencies || {};
51319
51717
  const devDeps = pkg.devDependencies || {};
@@ -51332,38 +51730,38 @@ async function detectTestFramework(cwd) {
51332
51730
  return "jest";
51333
51731
  if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
51334
51732
  return "mocha";
51335
- if (fs22.existsSync(path42.join(baseDir, "bun.lockb")) || fs22.existsSync(path42.join(baseDir, "bun.lock"))) {
51733
+ if (fs23.existsSync(path44.join(baseDir, "bun.lockb")) || fs23.existsSync(path44.join(baseDir, "bun.lock"))) {
51336
51734
  if (scripts.test?.includes("bun"))
51337
51735
  return "bun";
51338
51736
  }
51339
51737
  }
51340
51738
  } catch {}
51341
51739
  try {
51342
- const pyprojectTomlPath = path42.join(baseDir, "pyproject.toml");
51343
- const setupCfgPath = path42.join(baseDir, "setup.cfg");
51344
- const requirementsTxtPath = path42.join(baseDir, "requirements.txt");
51345
- if (fs22.existsSync(pyprojectTomlPath)) {
51346
- const content = fs22.readFileSync(pyprojectTomlPath, "utf-8");
51740
+ const pyprojectTomlPath = path44.join(baseDir, "pyproject.toml");
51741
+ const setupCfgPath = path44.join(baseDir, "setup.cfg");
51742
+ const requirementsTxtPath = path44.join(baseDir, "requirements.txt");
51743
+ if (fs23.existsSync(pyprojectTomlPath)) {
51744
+ const content = fs23.readFileSync(pyprojectTomlPath, "utf-8");
51347
51745
  if (content.includes("[tool.pytest"))
51348
51746
  return "pytest";
51349
51747
  if (content.includes("pytest"))
51350
51748
  return "pytest";
51351
51749
  }
51352
- if (fs22.existsSync(setupCfgPath)) {
51353
- const content = fs22.readFileSync(setupCfgPath, "utf-8");
51750
+ if (fs23.existsSync(setupCfgPath)) {
51751
+ const content = fs23.readFileSync(setupCfgPath, "utf-8");
51354
51752
  if (content.includes("[pytest]"))
51355
51753
  return "pytest";
51356
51754
  }
51357
- if (fs22.existsSync(requirementsTxtPath)) {
51358
- const content = fs22.readFileSync(requirementsTxtPath, "utf-8");
51755
+ if (fs23.existsSync(requirementsTxtPath)) {
51756
+ const content = fs23.readFileSync(requirementsTxtPath, "utf-8");
51359
51757
  if (content.includes("pytest"))
51360
51758
  return "pytest";
51361
51759
  }
51362
51760
  } catch {}
51363
51761
  try {
51364
- const cargoTomlPath = path42.join(baseDir, "Cargo.toml");
51365
- if (fs22.existsSync(cargoTomlPath)) {
51366
- const content = fs22.readFileSync(cargoTomlPath, "utf-8");
51762
+ const cargoTomlPath = path44.join(baseDir, "Cargo.toml");
51763
+ if (fs23.existsSync(cargoTomlPath)) {
51764
+ const content = fs23.readFileSync(cargoTomlPath, "utf-8");
51367
51765
  if (content.includes("[dev-dependencies]")) {
51368
51766
  if (content.includes("tokio") || content.includes("mockall") || content.includes("pretty_assertions")) {
51369
51767
  return "cargo";
@@ -51372,10 +51770,10 @@ async function detectTestFramework(cwd) {
51372
51770
  }
51373
51771
  } catch {}
51374
51772
  try {
51375
- const pesterConfigPath = path42.join(baseDir, "pester.config.ps1");
51376
- const pesterConfigJsonPath = path42.join(baseDir, "pester.config.ps1.json");
51377
- const pesterPs1Path = path42.join(baseDir, "tests.ps1");
51378
- if (fs22.existsSync(pesterConfigPath) || fs22.existsSync(pesterConfigJsonPath) || fs22.existsSync(pesterPs1Path)) {
51773
+ const pesterConfigPath = path44.join(baseDir, "pester.config.ps1");
51774
+ const pesterConfigJsonPath = path44.join(baseDir, "pester.config.ps1.json");
51775
+ const pesterPs1Path = path44.join(baseDir, "tests.ps1");
51776
+ if (fs23.existsSync(pesterConfigPath) || fs23.existsSync(pesterConfigJsonPath) || fs23.existsSync(pesterPs1Path)) {
51379
51777
  return "pester";
51380
51778
  }
51381
51779
  } catch {}
@@ -51403,12 +51801,12 @@ function isTestDirectoryPath(normalizedPath) {
51403
51801
  return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
51404
51802
  }
51405
51803
  function resolveWorkspacePath(file3, workingDir) {
51406
- return path42.isAbsolute(file3) ? path42.resolve(file3) : path42.resolve(workingDir, file3);
51804
+ return path44.isAbsolute(file3) ? path44.resolve(file3) : path44.resolve(workingDir, file3);
51407
51805
  }
51408
51806
  function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
51409
51807
  if (!preferRelative)
51410
51808
  return absolutePath;
51411
- return path42.relative(workingDir, absolutePath);
51809
+ return path44.relative(workingDir, absolutePath);
51412
51810
  }
51413
51811
  function dedupePush(target, value) {
51414
51812
  if (!target.includes(value)) {
@@ -51445,18 +51843,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
51445
51843
  }
51446
51844
  }
51447
51845
  function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
51448
- const relativeDir = path42.dirname(relativePath);
51846
+ const relativeDir = path44.dirname(relativePath);
51449
51847
  const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
51450
51848
  const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
51451
- const rootDir = path42.join(workingDir, dirName);
51452
- return nestedRelativeDir ? [rootDir, path42.join(rootDir, nestedRelativeDir)] : [rootDir];
51849
+ const rootDir = path44.join(workingDir, dirName);
51850
+ return nestedRelativeDir ? [rootDir, path44.join(rootDir, nestedRelativeDir)] : [rootDir];
51453
51851
  });
51454
51852
  const normalizedRelativePath = relativePath.replace(/\\/g, "/");
51455
51853
  if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
51456
- directories.push(path42.join(workingDir, "src/test/java", path42.dirname(normalizedRelativePath.slice("src/main/java/".length))));
51854
+ directories.push(path44.join(workingDir, "src/test/java", path44.dirname(normalizedRelativePath.slice("src/main/java/".length))));
51457
51855
  }
51458
51856
  if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
51459
- directories.push(path42.join(workingDir, "src/test/kotlin", path42.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
51857
+ directories.push(path44.join(workingDir, "src/test/kotlin", path44.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
51460
51858
  }
51461
51859
  return [...new Set(directories)];
51462
51860
  }
@@ -51464,19 +51862,19 @@ function hasCompoundTestExtension(filename) {
51464
51862
  const lower = filename.toLowerCase();
51465
51863
  return COMPOUND_TEST_EXTENSIONS.some((ext) => lower.endsWith(ext));
51466
51864
  }
51467
- function isLanguageSpecificTestFile(basename6) {
51468
- const lower = basename6.toLowerCase();
51865
+ function isLanguageSpecificTestFile(basename7) {
51866
+ const lower = basename7.toLowerCase();
51469
51867
  if (lower.endsWith("_test.go"))
51470
51868
  return true;
51471
51869
  if (lower.endsWith(".py") && (lower.startsWith("test_") || lower.endsWith("_test.py")))
51472
51870
  return true;
51473
51871
  if (lower.endsWith("_spec.rb"))
51474
51872
  return true;
51475
- if (lower.endsWith(".java") && (/^Test[A-Z]/.test(basename6) || basename6.endsWith("Test.java") || basename6.endsWith("Tests.java") || lower.endsWith("it.java")))
51873
+ if (lower.endsWith(".java") && (/^Test[A-Z]/.test(basename7) || basename7.endsWith("Test.java") || basename7.endsWith("Tests.java") || lower.endsWith("it.java")))
51476
51874
  return true;
51477
51875
  if (lower.endsWith(".cs") && (lower.endsWith("test.cs") || lower.endsWith("tests.cs")))
51478
51876
  return true;
51479
- if (lower.endsWith(".kt") && (/^Test[A-Z]/.test(basename6) || lower.endsWith("test.kt") || lower.endsWith("tests.kt")))
51877
+ if (lower.endsWith(".kt") && (/^Test[A-Z]/.test(basename7) || lower.endsWith("test.kt") || lower.endsWith("tests.kt")))
51480
51878
  return true;
51481
51879
  if (lower.endsWith(".tests.ps1"))
51482
51880
  return true;
@@ -51484,23 +51882,23 @@ function isLanguageSpecificTestFile(basename6) {
51484
51882
  }
51485
51883
  function isConventionTestFilePath(filePath) {
51486
51884
  const normalizedPath = filePath.replace(/\\/g, "/");
51487
- const basename6 = path42.basename(filePath);
51488
- return hasCompoundTestExtension(basename6) || basename6.includes(".spec.") || basename6.includes(".test.") || isLanguageSpecificTestFile(basename6) || isTestDirectoryPath(normalizedPath);
51885
+ const basename7 = path44.basename(filePath);
51886
+ return hasCompoundTestExtension(basename7) || basename7.includes(".spec.") || basename7.includes(".test.") || isLanguageSpecificTestFile(basename7) || isTestDirectoryPath(normalizedPath);
51489
51887
  }
51490
51888
  function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
51491
51889
  const testFiles = [];
51492
51890
  for (const file3 of sourceFiles) {
51493
51891
  const absoluteFile = resolveWorkspacePath(file3, workingDir);
51494
- const relativeFile = path42.relative(workingDir, absoluteFile);
51495
- const basename6 = path42.basename(absoluteFile);
51496
- const dirname20 = path42.dirname(absoluteFile);
51497
- const preferRelativeOutput = !path42.isAbsolute(file3);
51892
+ const relativeFile = path44.relative(workingDir, absoluteFile);
51893
+ const basename7 = path44.basename(absoluteFile);
51894
+ const dirname21 = path44.dirname(absoluteFile);
51895
+ const preferRelativeOutput = !path44.isAbsolute(file3);
51498
51896
  if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file3)) {
51499
51897
  dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
51500
51898
  continue;
51501
51899
  }
51502
- const nameWithoutExt = basename6.replace(/\.[^.]+$/, "");
51503
- const ext = path42.extname(basename6);
51900
+ const nameWithoutExt = basename7.replace(/\.[^.]+$/, "");
51901
+ const ext = path44.extname(basename7);
51504
51902
  const genericTestNames = [
51505
51903
  `${nameWithoutExt}.spec${ext}`,
51506
51904
  `${nameWithoutExt}.test${ext}`
@@ -51509,20 +51907,20 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
51509
51907
  const colocatedCandidates = [
51510
51908
  ...genericTestNames,
51511
51909
  ...languageSpecificTestNames
51512
- ].map((candidateName) => path42.join(dirname20, candidateName));
51910
+ ].map((candidateName) => path44.join(dirname21, candidateName));
51513
51911
  const testDirectoryNames = [
51514
- basename6,
51912
+ basename7,
51515
51913
  ...genericTestNames,
51516
51914
  ...languageSpecificTestNames
51517
51915
  ];
51518
51916
  const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
51519
51917
  const possibleTestFiles = [
51520
51918
  ...colocatedCandidates,
51521
- ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path42.join(dirname20, dirName, candidateName))),
51522
- ...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path42.join(candidateDir, candidateName)))
51919
+ ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path44.join(dirname21, dirName, candidateName))),
51920
+ ...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path44.join(candidateDir, candidateName)))
51523
51921
  ];
51524
51922
  for (const testFile of possibleTestFiles) {
51525
- if (fs22.existsSync(testFile)) {
51923
+ if (fs23.existsSync(testFile)) {
51526
51924
  dedupePush(testFiles, toWorkspaceOutputPath(testFile, workingDir, preferRelativeOutput));
51527
51925
  }
51528
51926
  }
@@ -51539,8 +51937,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
51539
51937
  for (const testFile of candidateTestFiles) {
51540
51938
  try {
51541
51939
  const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
51542
- const content = fs22.readFileSync(absoluteTestFile, "utf-8");
51543
- const testDir = path42.dirname(absoluteTestFile);
51940
+ const content = fs23.readFileSync(absoluteTestFile, "utf-8");
51941
+ const testDir = path44.dirname(absoluteTestFile);
51544
51942
  const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
51545
51943
  let match;
51546
51944
  match = importRegex.exec(content);
@@ -51548,8 +51946,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
51548
51946
  const importPath = match[1];
51549
51947
  let resolvedImport;
51550
51948
  if (importPath.startsWith(".")) {
51551
- resolvedImport = path42.resolve(testDir, importPath);
51552
- const existingExt = path42.extname(resolvedImport);
51949
+ resolvedImport = path44.resolve(testDir, importPath);
51950
+ const existingExt = path44.extname(resolvedImport);
51553
51951
  if (!existingExt) {
51554
51952
  for (const extToTry of [
51555
51953
  ".ts",
@@ -51560,7 +51958,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
51560
51958
  ".cjs"
51561
51959
  ]) {
51562
51960
  const withExt = resolvedImport + extToTry;
51563
- if (absoluteSourceFiles.includes(withExt) || fs22.existsSync(withExt)) {
51961
+ if (absoluteSourceFiles.includes(withExt) || fs23.existsSync(withExt)) {
51564
51962
  resolvedImport = withExt;
51565
51963
  break;
51566
51964
  }
@@ -51569,12 +51967,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
51569
51967
  } else {
51570
51968
  continue;
51571
51969
  }
51572
- const importBasename = path42.basename(resolvedImport, path42.extname(resolvedImport));
51573
- const importDir = path42.dirname(resolvedImport);
51970
+ const importBasename = path44.basename(resolvedImport, path44.extname(resolvedImport));
51971
+ const importDir = path44.dirname(resolvedImport);
51574
51972
  for (const sourceFile of absoluteSourceFiles) {
51575
- const sourceDir = path42.dirname(sourceFile);
51576
- const sourceBasename = path42.basename(sourceFile, path42.extname(sourceFile));
51577
- const isRelatedDir = importDir === sourceDir || importDir === path42.join(sourceDir, "__tests__") || importDir === path42.join(sourceDir, "tests") || importDir === path42.join(sourceDir, "test") || importDir === path42.join(sourceDir, "spec");
51973
+ const sourceDir = path44.dirname(sourceFile);
51974
+ const sourceBasename = path44.basename(sourceFile, path44.extname(sourceFile));
51975
+ const isRelatedDir = importDir === sourceDir || importDir === path44.join(sourceDir, "__tests__") || importDir === path44.join(sourceDir, "tests") || importDir === path44.join(sourceDir, "test") || importDir === path44.join(sourceDir, "spec");
51578
51976
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
51579
51977
  dedupePush(testFiles, testFile);
51580
51978
  break;
@@ -51587,8 +51985,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
51587
51985
  while (match !== null) {
51588
51986
  const importPath = match[1];
51589
51987
  if (importPath.startsWith(".")) {
51590
- let resolvedImport = path42.resolve(testDir, importPath);
51591
- const existingExt = path42.extname(resolvedImport);
51988
+ let resolvedImport = path44.resolve(testDir, importPath);
51989
+ const existingExt = path44.extname(resolvedImport);
51592
51990
  if (!existingExt) {
51593
51991
  for (const extToTry of [
51594
51992
  ".ts",
@@ -51599,18 +51997,18 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
51599
51997
  ".cjs"
51600
51998
  ]) {
51601
51999
  const withExt = resolvedImport + extToTry;
51602
- if (absoluteSourceFiles.includes(withExt) || fs22.existsSync(withExt)) {
52000
+ if (absoluteSourceFiles.includes(withExt) || fs23.existsSync(withExt)) {
51603
52001
  resolvedImport = withExt;
51604
52002
  break;
51605
52003
  }
51606
52004
  }
51607
52005
  }
51608
- const importDir = path42.dirname(resolvedImport);
51609
- const importBasename = path42.basename(resolvedImport, path42.extname(resolvedImport));
52006
+ const importDir = path44.dirname(resolvedImport);
52007
+ const importBasename = path44.basename(resolvedImport, path44.extname(resolvedImport));
51610
52008
  for (const sourceFile of absoluteSourceFiles) {
51611
- const sourceDir = path42.dirname(sourceFile);
51612
- const sourceBasename = path42.basename(sourceFile, path42.extname(sourceFile));
51613
- const isRelatedDir = importDir === sourceDir || importDir === path42.join(sourceDir, "__tests__") || importDir === path42.join(sourceDir, "tests") || importDir === path42.join(sourceDir, "test") || importDir === path42.join(sourceDir, "spec");
52009
+ const sourceDir = path44.dirname(sourceFile);
52010
+ const sourceBasename = path44.basename(sourceFile, path44.extname(sourceFile));
52011
+ const isRelatedDir = importDir === sourceDir || importDir === path44.join(sourceDir, "__tests__") || importDir === path44.join(sourceDir, "tests") || importDir === path44.join(sourceDir, "test") || importDir === path44.join(sourceDir, "spec");
51614
52012
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
51615
52013
  dedupePush(testFiles, testFile);
51616
52014
  break;
@@ -51720,8 +52118,8 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
51720
52118
  return ["mvn", "test"];
51721
52119
  case "gradle": {
51722
52120
  const isWindows = process.platform === "win32";
51723
- const hasGradlewBat = fs22.existsSync(path42.join(baseDir, "gradlew.bat"));
51724
- const hasGradlew = fs22.existsSync(path42.join(baseDir, "gradlew"));
52121
+ const hasGradlewBat = fs23.existsSync(path44.join(baseDir, "gradlew.bat"));
52122
+ const hasGradlew = fs23.existsSync(path44.join(baseDir, "gradlew"));
51725
52123
  if (hasGradlewBat && isWindows)
51726
52124
  return ["gradlew.bat", "test"];
51727
52125
  if (hasGradlew)
@@ -51738,7 +52136,7 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
51738
52136
  "cmake-build-release",
51739
52137
  "out"
51740
52138
  ];
51741
- const actualBuildDir = buildDirCandidates.find((d) => fs22.existsSync(path42.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
52139
+ const actualBuildDir = buildDirCandidates.find((d) => fs23.existsSync(path44.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
51742
52140
  return ["ctest", "--test-dir", actualBuildDir];
51743
52141
  }
51744
52142
  case "swift-test":
@@ -52170,13 +52568,13 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
52170
52568
  };
52171
52569
  }
52172
52570
  const startTime = Date.now();
52173
- const vitestJsonOutputPath = framework === "vitest" ? path42.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
52571
+ const vitestJsonOutputPath = framework === "vitest" ? path44.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
52174
52572
  try {
52175
52573
  if (vitestJsonOutputPath) {
52176
52574
  try {
52177
- fs22.mkdirSync(path42.dirname(vitestJsonOutputPath), { recursive: true });
52178
- if (fs22.existsSync(vitestJsonOutputPath)) {
52179
- fs22.unlinkSync(vitestJsonOutputPath);
52575
+ fs23.mkdirSync(path44.dirname(vitestJsonOutputPath), { recursive: true });
52576
+ if (fs23.existsSync(vitestJsonOutputPath)) {
52577
+ fs23.unlinkSync(vitestJsonOutputPath);
52180
52578
  }
52181
52579
  } catch {}
52182
52580
  }
@@ -52185,9 +52583,9 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
52185
52583
  stderr: "pipe",
52186
52584
  cwd
52187
52585
  });
52188
- const timeoutPromise = new Promise((resolve14) => setTimeout(() => {
52586
+ const timeoutPromise = new Promise((resolve16) => setTimeout(() => {
52189
52587
  proc.kill();
52190
- resolve14(-1);
52588
+ resolve16(-1);
52191
52589
  }, timeout_ms));
52192
52590
  const [exitCode, stdoutResult, stderrResult] = await Promise.all([
52193
52591
  Promise.race([proc.exited, timeoutPromise]),
@@ -52202,8 +52600,8 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
52202
52600
  }
52203
52601
  if (vitestJsonOutputPath) {
52204
52602
  try {
52205
- if (fs22.existsSync(vitestJsonOutputPath)) {
52206
- const vitestJsonOutput = fs22.readFileSync(vitestJsonOutputPath, "utf-8");
52603
+ if (fs23.existsSync(vitestJsonOutputPath)) {
52604
+ const vitestJsonOutput = fs23.readFileSync(vitestJsonOutputPath, "utf-8");
52207
52605
  if (vitestJsonOutput.trim().length > 0) {
52208
52606
  output += (output ? `
52209
52607
  ` : "") + vitestJsonOutput;
@@ -52290,10 +52688,10 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
52290
52688
  }
52291
52689
  function normalizeHistoryTestFile(testFile, workingDir) {
52292
52690
  const normalized = testFile.replace(/\\/g, "/");
52293
- if (!path42.isAbsolute(testFile))
52691
+ if (!path44.isAbsolute(testFile))
52294
52692
  return normalized;
52295
- const relative9 = path42.relative(workingDir, testFile);
52296
- if (relative9.startsWith("..") || path42.isAbsolute(relative9)) {
52693
+ const relative9 = path44.relative(workingDir, testFile);
52694
+ if (relative9.startsWith("..") || path44.isAbsolute(relative9)) {
52297
52695
  return normalized;
52298
52696
  }
52299
52697
  return relative9.replace(/\\/g, "/");
@@ -52631,7 +53029,7 @@ var init_test_runner = __esm(() => {
52631
53029
  const sourceFiles = args.files.filter((file3) => {
52632
53030
  if (directTestFiles.includes(file3))
52633
53031
  return false;
52634
- const ext = path42.extname(file3).toLowerCase();
53032
+ const ext = path44.extname(file3).toLowerCase();
52635
53033
  return SOURCE_EXTENSIONS.has(ext);
52636
53034
  });
52637
53035
  const invalidFiles = args.files.filter((file3) => !directTestFiles.includes(file3) && !sourceFiles.includes(file3));
@@ -52677,7 +53075,7 @@ var init_test_runner = __esm(() => {
52677
53075
  if (isConventionTestFilePath(f)) {
52678
53076
  return false;
52679
53077
  }
52680
- const ext = path42.extname(f).toLowerCase();
53078
+ const ext = path44.extname(f).toLowerCase();
52681
53079
  return SOURCE_EXTENSIONS.has(ext);
52682
53080
  });
52683
53081
  if (sourceFiles.length === 0) {
@@ -52727,7 +53125,7 @@ var init_test_runner = __esm(() => {
52727
53125
  if (isConventionTestFilePath(f)) {
52728
53126
  return false;
52729
53127
  }
52730
- const ext = path42.extname(f).toLowerCase();
53128
+ const ext = path44.extname(f).toLowerCase();
52731
53129
  return SOURCE_EXTENSIONS.has(ext);
52732
53130
  });
52733
53131
  if (sourceFiles.length === 0) {
@@ -52779,8 +53177,8 @@ var init_test_runner = __esm(() => {
52779
53177
  }
52780
53178
  if (impactResult.impactedTests.length > 0) {
52781
53179
  testFiles = impactResult.impactedTests.map((absPath) => {
52782
- const relativePath = path42.relative(workingDir, absPath);
52783
- return path42.isAbsolute(relativePath) ? absPath : relativePath;
53180
+ const relativePath = path44.relative(workingDir, absPath);
53181
+ return path44.isAbsolute(relativePath) ? absPath : relativePath;
52784
53182
  });
52785
53183
  } else {
52786
53184
  graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
@@ -52855,8 +53253,8 @@ var init_test_runner = __esm(() => {
52855
53253
  });
52856
53254
 
52857
53255
  // src/services/preflight-service.ts
52858
- import * as fs23 from "fs";
52859
- import * as path43 from "path";
53256
+ import * as fs24 from "fs";
53257
+ import * as path45 from "path";
52860
53258
  function validateDirectoryPath(dir) {
52861
53259
  if (!dir || typeof dir !== "string") {
52862
53260
  throw new Error("Directory path is required");
@@ -52864,8 +53262,8 @@ function validateDirectoryPath(dir) {
52864
53262
  if (dir.includes("..")) {
52865
53263
  throw new Error("Directory path must not contain path traversal sequences");
52866
53264
  }
52867
- const normalized = path43.normalize(dir);
52868
- const absolutePath = path43.isAbsolute(normalized) ? normalized : path43.resolve(normalized);
53265
+ const normalized = path45.normalize(dir);
53266
+ const absolutePath = path45.isAbsolute(normalized) ? normalized : path45.resolve(normalized);
52869
53267
  return absolutePath;
52870
53268
  }
52871
53269
  function validateTimeout(timeoutMs, defaultValue) {
@@ -52888,9 +53286,9 @@ function validateTimeout(timeoutMs, defaultValue) {
52888
53286
  }
52889
53287
  function getPackageVersion(dir) {
52890
53288
  try {
52891
- const packagePath = path43.join(dir, "package.json");
52892
- if (fs23.existsSync(packagePath)) {
52893
- const content = fs23.readFileSync(packagePath, "utf-8");
53289
+ const packagePath = path45.join(dir, "package.json");
53290
+ if (fs24.existsSync(packagePath)) {
53291
+ const content = fs24.readFileSync(packagePath, "utf-8");
52894
53292
  const pkg = JSON.parse(content);
52895
53293
  return pkg.version ?? null;
52896
53294
  }
@@ -52899,9 +53297,9 @@ function getPackageVersion(dir) {
52899
53297
  }
52900
53298
  function getChangelogVersion(dir) {
52901
53299
  try {
52902
- const changelogPath = path43.join(dir, "CHANGELOG.md");
52903
- if (fs23.existsSync(changelogPath)) {
52904
- const content = fs23.readFileSync(changelogPath, "utf-8");
53300
+ const changelogPath = path45.join(dir, "CHANGELOG.md");
53301
+ if (fs24.existsSync(changelogPath)) {
53302
+ const content = fs24.readFileSync(changelogPath, "utf-8");
52905
53303
  const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
52906
53304
  if (match) {
52907
53305
  return match[1];
@@ -52913,10 +53311,10 @@ function getChangelogVersion(dir) {
52913
53311
  function getVersionFileVersion(dir) {
52914
53312
  const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
52915
53313
  for (const file3 of possibleFiles) {
52916
- const filePath = path43.join(dir, file3);
52917
- if (fs23.existsSync(filePath)) {
53314
+ const filePath = path45.join(dir, file3);
53315
+ if (fs24.existsSync(filePath)) {
52918
53316
  try {
52919
- const content = fs23.readFileSync(filePath, "utf-8").trim();
53317
+ const content = fs24.readFileSync(filePath, "utf-8").trim();
52920
53318
  const match = content.match(/(\d+\.\d+\.\d+)/);
52921
53319
  if (match) {
52922
53320
  return match[1];
@@ -53255,8 +53653,8 @@ async function runEvidenceCheck(dir) {
53255
53653
  async function runRequirementCoverageCheck(dir, currentPhase) {
53256
53654
  const startTime = Date.now();
53257
53655
  try {
53258
- const specPath = path43.join(dir, ".swarm", "spec.md");
53259
- if (!fs23.existsSync(specPath)) {
53656
+ const specPath = path45.join(dir, ".swarm", "spec.md");
53657
+ if (!fs24.existsSync(specPath)) {
53260
53658
  return {
53261
53659
  type: "req_coverage",
53262
53660
  status: "skip",
@@ -53734,13 +54132,13 @@ class CircuitBreaker {
53734
54132
  if (this.config.callTimeoutMs <= 0) {
53735
54133
  return fn();
53736
54134
  }
53737
- return new Promise((resolve15, reject) => {
54135
+ return new Promise((resolve17, reject) => {
53738
54136
  const timeout = setTimeout(() => {
53739
54137
  reject(new Error(`Call timeout after ${this.config.callTimeoutMs}ms`));
53740
54138
  }, this.config.callTimeoutMs);
53741
54139
  fn().then((result) => {
53742
54140
  clearTimeout(timeout);
53743
- resolve15(result);
54141
+ resolve17(result);
53744
54142
  }).catch((error93) => {
53745
54143
  clearTimeout(timeout);
53746
54144
  reject(error93);
@@ -54027,7 +54425,7 @@ var init_queue = __esm(() => {
54027
54425
 
54028
54426
  // src/background/worker.ts
54029
54427
  function sleep(ms) {
54030
- return new Promise((resolve15) => setTimeout(resolve15, ms));
54428
+ return new Promise((resolve17) => setTimeout(resolve17, ms));
54031
54429
  }
54032
54430
 
54033
54431
  class WorkerManager {
@@ -54372,8 +54770,8 @@ var init_manager3 = __esm(() => {
54372
54770
  });
54373
54771
 
54374
54772
  // src/commands/reset.ts
54375
- import * as fs24 from "fs";
54376
- import * as path44 from "path";
54773
+ import * as fs25 from "fs";
54774
+ import * as path46 from "path";
54377
54775
  async function handleResetCommand(directory, args) {
54378
54776
  const hasConfirm = args.includes("--confirm");
54379
54777
  if (!hasConfirm) {
@@ -54401,8 +54799,8 @@ async function handleResetCommand(directory, args) {
54401
54799
  for (const filename of filesToReset) {
54402
54800
  try {
54403
54801
  const resolvedPath = validateSwarmPath(directory, filename);
54404
- if (fs24.existsSync(resolvedPath)) {
54405
- fs24.unlinkSync(resolvedPath);
54802
+ if (fs25.existsSync(resolvedPath)) {
54803
+ fs25.unlinkSync(resolvedPath);
54406
54804
  results.push(`- \u2705 Deleted ${filename}`);
54407
54805
  } else {
54408
54806
  results.push(`- \u23ED\uFE0F ${filename} not found (skipped)`);
@@ -54413,9 +54811,9 @@ async function handleResetCommand(directory, args) {
54413
54811
  }
54414
54812
  for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
54415
54813
  try {
54416
- const rootPath = path44.join(directory, filename);
54417
- if (fs24.existsSync(rootPath)) {
54418
- fs24.unlinkSync(rootPath);
54814
+ const rootPath = path46.join(directory, filename);
54815
+ if (fs25.existsSync(rootPath)) {
54816
+ fs25.unlinkSync(rootPath);
54419
54817
  results.push(`- \u2705 Deleted ${filename} (root)`);
54420
54818
  }
54421
54819
  } catch {}
@@ -54428,8 +54826,8 @@ async function handleResetCommand(directory, args) {
54428
54826
  }
54429
54827
  try {
54430
54828
  const summariesPath = validateSwarmPath(directory, "summaries");
54431
- if (fs24.existsSync(summariesPath)) {
54432
- fs24.rmSync(summariesPath, { recursive: true, force: true });
54829
+ if (fs25.existsSync(summariesPath)) {
54830
+ fs25.rmSync(summariesPath, { recursive: true, force: true });
54433
54831
  results.push("- \u2705 Deleted summaries/ directory");
54434
54832
  } else {
54435
54833
  results.push("- \u23ED\uFE0F summaries/ not found (skipped)");
@@ -54452,14 +54850,14 @@ var init_reset = __esm(() => {
54452
54850
  });
54453
54851
 
54454
54852
  // src/commands/reset-session.ts
54455
- import * as fs25 from "fs";
54456
- import * as path45 from "path";
54853
+ import * as fs26 from "fs";
54854
+ import * as path47 from "path";
54457
54855
  async function handleResetSessionCommand(directory, _args) {
54458
54856
  const results = [];
54459
54857
  try {
54460
54858
  const statePath = validateSwarmPath(directory, "session/state.json");
54461
- if (fs25.existsSync(statePath)) {
54462
- fs25.unlinkSync(statePath);
54859
+ if (fs26.existsSync(statePath)) {
54860
+ fs26.unlinkSync(statePath);
54463
54861
  results.push("\u2705 Deleted .swarm/session/state.json");
54464
54862
  } else {
54465
54863
  results.push("\u23ED\uFE0F state.json not found (already clean)");
@@ -54468,15 +54866,15 @@ async function handleResetSessionCommand(directory, _args) {
54468
54866
  results.push("\u274C Failed to delete state.json");
54469
54867
  }
54470
54868
  try {
54471
- const sessionDir = path45.dirname(validateSwarmPath(directory, "session/state.json"));
54472
- if (fs25.existsSync(sessionDir)) {
54473
- const files = fs25.readdirSync(sessionDir);
54869
+ const sessionDir = path47.dirname(validateSwarmPath(directory, "session/state.json"));
54870
+ if (fs26.existsSync(sessionDir)) {
54871
+ const files = fs26.readdirSync(sessionDir);
54474
54872
  const otherFiles = files.filter((f) => f !== "state.json");
54475
54873
  let deletedCount = 0;
54476
54874
  for (const file3 of otherFiles) {
54477
- const filePath = path45.join(sessionDir, file3);
54478
- if (fs25.lstatSync(filePath).isFile()) {
54479
- fs25.unlinkSync(filePath);
54875
+ const filePath = path47.join(sessionDir, file3);
54876
+ if (fs26.lstatSync(filePath).isFile()) {
54877
+ fs26.unlinkSync(filePath);
54480
54878
  deletedCount++;
54481
54879
  }
54482
54880
  }
@@ -54506,7 +54904,7 @@ var init_reset_session = __esm(() => {
54506
54904
  });
54507
54905
 
54508
54906
  // src/summaries/manager.ts
54509
- import * as path46 from "path";
54907
+ import * as path48 from "path";
54510
54908
  function sanitizeSummaryId(id) {
54511
54909
  if (!id || id.length === 0) {
54512
54910
  throw new Error("Invalid summary ID: empty string");
@@ -54529,7 +54927,7 @@ function sanitizeSummaryId(id) {
54529
54927
  }
54530
54928
  async function loadFullOutput(directory, id) {
54531
54929
  const sanitizedId = sanitizeSummaryId(id);
54532
- const relativePath = path46.join("summaries", `${sanitizedId}.json`);
54930
+ const relativePath = path48.join("summaries", `${sanitizedId}.json`);
54533
54931
  validateSwarmPath(directory, relativePath);
54534
54932
  const content = await readSwarmFileAsync(directory, relativePath);
54535
54933
  if (content === null) {
@@ -54591,18 +54989,18 @@ var init_retrieve = __esm(() => {
54591
54989
  });
54592
54990
 
54593
54991
  // src/commands/rollback.ts
54594
- import * as fs26 from "fs";
54595
- import * as path47 from "path";
54992
+ import * as fs27 from "fs";
54993
+ import * as path49 from "path";
54596
54994
  async function handleRollbackCommand(directory, args) {
54597
54995
  const phaseArg = args[0];
54598
54996
  if (!phaseArg) {
54599
54997
  const manifestPath2 = validateSwarmPath(directory, "checkpoints/manifest.json");
54600
- if (!fs26.existsSync(manifestPath2)) {
54998
+ if (!fs27.existsSync(manifestPath2)) {
54601
54999
  return "No checkpoints found. Use `/swarm checkpoint` to create checkpoints.";
54602
55000
  }
54603
55001
  let manifest2;
54604
55002
  try {
54605
- manifest2 = JSON.parse(fs26.readFileSync(manifestPath2, "utf-8"));
55003
+ manifest2 = JSON.parse(fs27.readFileSync(manifestPath2, "utf-8"));
54606
55004
  } catch {
54607
55005
  return "Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.";
54608
55006
  }
@@ -54624,12 +55022,12 @@ async function handleRollbackCommand(directory, args) {
54624
55022
  return "Error: Phase number must be a positive integer.";
54625
55023
  }
54626
55024
  const manifestPath = validateSwarmPath(directory, "checkpoints/manifest.json");
54627
- if (!fs26.existsSync(manifestPath)) {
55025
+ if (!fs27.existsSync(manifestPath)) {
54628
55026
  return `Error: No checkpoints found. Cannot rollback to phase ${targetPhase}.`;
54629
55027
  }
54630
55028
  let manifest;
54631
55029
  try {
54632
- manifest = JSON.parse(fs26.readFileSync(manifestPath, "utf-8"));
55030
+ manifest = JSON.parse(fs27.readFileSync(manifestPath, "utf-8"));
54633
55031
  } catch {
54634
55032
  return `Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.`;
54635
55033
  }
@@ -54639,10 +55037,10 @@ async function handleRollbackCommand(directory, args) {
54639
55037
  return `Error: Checkpoint for phase ${targetPhase} not found. Available phases: ${available}`;
54640
55038
  }
54641
55039
  const checkpointDir = validateSwarmPath(directory, `checkpoints/phase-${targetPhase}`);
54642
- if (!fs26.existsSync(checkpointDir)) {
55040
+ if (!fs27.existsSync(checkpointDir)) {
54643
55041
  return `Error: Checkpoint directory for phase ${targetPhase} does not exist.`;
54644
55042
  }
54645
- const checkpointFiles = fs26.readdirSync(checkpointDir);
55043
+ const checkpointFiles = fs27.readdirSync(checkpointDir);
54646
55044
  if (checkpointFiles.length === 0) {
54647
55045
  return `Error: Checkpoint for phase ${targetPhase} is empty. Cannot rollback.`;
54648
55046
  }
@@ -54657,10 +55055,10 @@ async function handleRollbackCommand(directory, args) {
54657
55055
  if (EXCLUDE_FILES.has(file3) || file3.startsWith("plan-ledger.archived-")) {
54658
55056
  continue;
54659
55057
  }
54660
- const src = path47.join(checkpointDir, file3);
54661
- const dest = path47.join(swarmDir, file3);
55058
+ const src = path49.join(checkpointDir, file3);
55059
+ const dest = path49.join(swarmDir, file3);
54662
55060
  try {
54663
- fs26.cpSync(src, dest, { recursive: true, force: true });
55061
+ fs27.cpSync(src, dest, { recursive: true, force: true });
54664
55062
  successes.push(file3);
54665
55063
  } catch (error93) {
54666
55064
  failures.push({ file: file3, error: error93.message });
@@ -54677,14 +55075,14 @@ async function handleRollbackCommand(directory, args) {
54677
55075
  ].join(`
54678
55076
  `);
54679
55077
  }
54680
- const existingLedgerPath = path47.join(swarmDir, "plan-ledger.jsonl");
54681
- if (fs26.existsSync(existingLedgerPath)) {
54682
- fs26.unlinkSync(existingLedgerPath);
55078
+ const existingLedgerPath = path49.join(swarmDir, "plan-ledger.jsonl");
55079
+ if (fs27.existsSync(existingLedgerPath)) {
55080
+ fs27.unlinkSync(existingLedgerPath);
54683
55081
  }
54684
55082
  try {
54685
- const planJsonPath = path47.join(swarmDir, "plan.json");
54686
- if (fs26.existsSync(planJsonPath)) {
54687
- const planRaw = fs26.readFileSync(planJsonPath, "utf-8");
55083
+ const planJsonPath = path49.join(swarmDir, "plan.json");
55084
+ if (fs27.existsSync(planJsonPath)) {
55085
+ const planRaw = fs27.readFileSync(planJsonPath, "utf-8");
54688
55086
  const plan = PlanSchema.parse(JSON.parse(planRaw));
54689
55087
  const planId = derivePlanId(plan);
54690
55088
  const planHash = computePlanHash(plan);
@@ -54711,7 +55109,7 @@ async function handleRollbackCommand(directory, args) {
54711
55109
  timestamp: new Date().toISOString()
54712
55110
  };
54713
55111
  try {
54714
- fs26.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
55112
+ fs27.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
54715
55113
  `);
54716
55114
  } catch (error93) {
54717
55115
  console.error("Failed to write rollback event:", error93 instanceof Error ? error93.message : String(error93));
@@ -54772,11 +55170,11 @@ Ensure this is a git repository with commit history.`;
54772
55170
  const report = reportLines.filter(Boolean).join(`
54773
55171
  `);
54774
55172
  try {
54775
- const fs27 = await import("fs/promises");
54776
- const path48 = await import("path");
54777
- const reportPath = path48.join(directory, ".swarm", "simulate-report.md");
54778
- await fs27.mkdir(path48.dirname(reportPath), { recursive: true });
54779
- await fs27.writeFile(reportPath, report, "utf-8");
55173
+ const fs28 = await import("fs/promises");
55174
+ const path50 = await import("path");
55175
+ const reportPath = path50.join(directory, ".swarm", "simulate-report.md");
55176
+ await fs28.mkdir(path50.dirname(reportPath), { recursive: true });
55177
+ await fs28.writeFile(reportPath, report, "utf-8");
54780
55178
  } catch (err) {
54781
55179
  const writeErr = err instanceof Error ? err.message : String(err);
54782
55180
  warn(`simulate: failed to write report to ${directory}/.swarm/simulate-report.md`, writeErr);
@@ -54798,15 +55196,15 @@ async function handleSpecifyCommand(_directory, args) {
54798
55196
  }
54799
55197
 
54800
55198
  // src/turbo/lean/state.ts
54801
- import * as fs27 from "fs";
54802
- import * as path48 from "path";
55199
+ import * as fs28 from "fs";
55200
+ import * as path50 from "path";
54803
55201
  function nowISO2() {
54804
55202
  return new Date().toISOString();
54805
55203
  }
54806
55204
  function ensureSwarmDir2(directory) {
54807
- const swarmDir = path48.resolve(directory, ".swarm");
54808
- if (!fs27.existsSync(swarmDir)) {
54809
- fs27.mkdirSync(swarmDir, { recursive: true });
55205
+ const swarmDir = path50.resolve(directory, ".swarm");
55206
+ if (!fs28.existsSync(swarmDir)) {
55207
+ fs28.mkdirSync(swarmDir, { recursive: true });
54810
55208
  }
54811
55209
  return swarmDir;
54812
55210
  }
@@ -54848,17 +55246,17 @@ function markStateUnreadable2(directory, reason) {
54848
55246
  }
54849
55247
  function readPersisted2(directory) {
54850
55248
  try {
54851
- const filePath = path48.join(directory, ".swarm", STATE_FILE2);
54852
- if (!fs27.existsSync(filePath)) {
55249
+ const filePath = path50.join(directory, ".swarm", STATE_FILE2);
55250
+ if (!fs28.existsSync(filePath)) {
54853
55251
  const seed = emptyPersisted2();
54854
55252
  try {
54855
55253
  ensureSwarmDir2(directory);
54856
- fs27.writeFileSync(filePath, `${JSON.stringify(seed, null, 2)}
55254
+ fs28.writeFileSync(filePath, `${JSON.stringify(seed, null, 2)}
54857
55255
  `, "utf-8");
54858
55256
  } catch {}
54859
55257
  return seed;
54860
55258
  }
54861
- const raw = fs27.readFileSync(filePath, "utf-8");
55259
+ const raw = fs28.readFileSync(filePath, "utf-8");
54862
55260
  const parsed = JSON.parse(raw);
54863
55261
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed) || parsed.version !== 1 || !parsed.sessions || typeof parsed.sessions !== "object" || Array.isArray(parsed.sessions)) {
54864
55262
  markStateUnreadable2(directory, `malformed shape (version=${parsed?.version}, sessions type=${Array.isArray(parsed?.sessions) ? "array" : typeof parsed?.sessions})`);
@@ -54884,7 +55282,7 @@ function writePersisted2(directory, persisted) {
54884
55282
  let payload;
54885
55283
  try {
54886
55284
  ensureSwarmDir2(directory);
54887
- filePath = path48.join(directory, ".swarm", STATE_FILE2);
55285
+ filePath = path50.join(directory, ".swarm", STATE_FILE2);
54888
55286
  tmpPath = `${filePath}.tmp.${Date.now()}`;
54889
55287
  persisted.updatedAt = nowISO2();
54890
55288
  payload = `${JSON.stringify(persisted, null, 2)}
@@ -54895,14 +55293,14 @@ function writePersisted2(directory, persisted) {
54895
55293
  throw new Error(`Lean Turbo state persistence prepare failed: ${msg}`);
54896
55294
  }
54897
55295
  try {
54898
- fs27.writeFileSync(tmpPath, payload, "utf-8");
54899
- fs27.renameSync(tmpPath, filePath);
55296
+ fs28.writeFileSync(tmpPath, payload, "utf-8");
55297
+ fs28.renameSync(tmpPath, filePath);
54900
55298
  } catch (error93) {
54901
55299
  const msg = error93 instanceof Error ? error93.message : String(error93);
54902
55300
  error(`[turbo/lean/state] Failed to persist ${STATE_FILE2} atomically: ${msg}`);
54903
55301
  try {
54904
- if (fs27.existsSync(tmpPath)) {
54905
- fs27.unlinkSync(tmpPath);
55302
+ if (fs28.existsSync(tmpPath)) {
55303
+ fs28.unlinkSync(tmpPath);
54906
55304
  }
54907
55305
  } catch {}
54908
55306
  throw new Error(`Lean Turbo state persistence failed: ${msg}`);
@@ -55011,10 +55409,10 @@ var init_context_budget_service = __esm(() => {
55011
55409
 
55012
55410
  // src/services/status-service.ts
55013
55411
  import * as fsSync2 from "fs";
55014
- import * as path49 from "path";
55412
+ import * as path51 from "path";
55015
55413
  function readSpecStalenessSnapshot(directory) {
55016
55414
  try {
55017
- const p = path49.join(directory, ".swarm", "spec-staleness.json");
55415
+ const p = path51.join(directory, ".swarm", "spec-staleness.json");
55018
55416
  if (!fsSync2.existsSync(p))
55019
55417
  return { stale: false };
55020
55418
  const raw = fsSync2.readFileSync(p, "utf-8");
@@ -55539,8 +55937,8 @@ var init_write_retro2 = __esm(() => {
55539
55937
  });
55540
55938
 
55541
55939
  // src/commands/command-dispatch.ts
55542
- import fs28 from "fs";
55543
- import path50 from "path";
55940
+ import fs29 from "fs";
55941
+ import path52 from "path";
55544
55942
  function normalizeSwarmCommandInput(command, argumentText) {
55545
55943
  if (command !== "swarm" && !command.startsWith("swarm-")) {
55546
55944
  return { isSwarmCommand: false, tokens: [] };
@@ -55576,11 +55974,11 @@ ${similar.map((cmd) => ` - /swarm ${cmd}`).join(`
55576
55974
  `);
55577
55975
  }
55578
55976
  function maybeMarkFirstRun(directory) {
55579
- const sentinelPath = path50.join(directory, ".swarm", ".first-run-complete");
55977
+ const sentinelPath = path52.join(directory, ".swarm", ".first-run-complete");
55580
55978
  try {
55581
- const swarmDir = path50.join(directory, ".swarm");
55582
- fs28.mkdirSync(swarmDir, { recursive: true });
55583
- fs28.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
55979
+ const swarmDir = path52.join(directory, ".swarm");
55980
+ fs29.mkdirSync(swarmDir, { recursive: true });
55981
+ fs29.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
55584
55982
  `, { flag: "wx" });
55585
55983
  return true;
55586
55984
  } catch {
@@ -55692,7 +56090,17 @@ function classifySwarmCommandToolUse(resolved) {
55692
56090
  return { allowed: true };
55693
56091
  return {
55694
56092
  allowed: false,
55695
- message: "Use `/swarm memory status` or `/swarm memory export` through swarm_command. Memory import and migrate are intentionally excluded from chat-tool execution."
56093
+ message: "Use `/swarm memory status`, `/swarm memory export`, or `/swarm memory evaluate --json` through swarm_command. Memory import and migrate are intentionally excluded from chat-tool execution."
56094
+ };
56095
+ }
56096
+ if (canonicalKey === "memory evaluate") {
56097
+ if (args.length === 0)
56098
+ return { allowed: true };
56099
+ if (args.length === 1 && args[0] === "--json")
56100
+ return { allowed: true };
56101
+ return {
56102
+ allowed: false,
56103
+ message: "Usage through swarm_command: `/swarm memory evaluate --json`. Custom fixture directories are only available through direct user command execution."
55696
56104
  };
55697
56105
  }
55698
56106
  if (canonicalKey === "retrieve") {
@@ -55780,6 +56188,7 @@ var init_tool_policy = __esm(() => {
55780
56188
  "memory",
55781
56189
  "memory status",
55782
56190
  "memory export",
56191
+ "memory evaluate",
55783
56192
  "memory import",
55784
56193
  "memory migrate",
55785
56194
  "sync-plan",
@@ -55805,6 +56214,7 @@ var init_tool_policy = __esm(() => {
55805
56214
  "memory",
55806
56215
  "memory status",
55807
56216
  "memory export",
56217
+ "memory evaluate",
55808
56218
  "sync-plan",
55809
56219
  "export"
55810
56220
  ]);
@@ -55868,6 +56278,7 @@ __export(exports_commands, {
55868
56278
  handleMemoryMigrateCommand: () => handleMemoryMigrateCommand,
55869
56279
  handleMemoryImportCommand: () => handleMemoryImportCommand,
55870
56280
  handleMemoryExportCommand: () => handleMemoryExportCommand,
56281
+ handleMemoryEvaluateCommand: () => handleMemoryEvaluateCommand,
55871
56282
  handleMemoryCommand: () => handleMemoryCommand,
55872
56283
  handleKnowledgeRestoreCommand: () => handleKnowledgeRestoreCommand,
55873
56284
  handleKnowledgeQuarantineCommand: () => handleKnowledgeQuarantineCommand,
@@ -56287,24 +56698,24 @@ function validateAliases() {
56287
56698
  }
56288
56699
  aliasTargets.get(target).push(name);
56289
56700
  const visited = new Set;
56290
- const path51 = [];
56701
+ const path53 = [];
56291
56702
  let current = target;
56292
56703
  while (current) {
56293
56704
  const currentEntry = COMMAND_REGISTRY[current];
56294
56705
  if (!currentEntry)
56295
56706
  break;
56296
56707
  if (visited.has(current)) {
56297
- const cycleStart = path51.indexOf(current);
56708
+ const cycleStart = path53.indexOf(current);
56298
56709
  const fullChain = [
56299
56710
  name,
56300
- ...path51.slice(0, cycleStart > 0 ? cycleStart : path51.length),
56711
+ ...path53.slice(0, cycleStart > 0 ? cycleStart : path53.length),
56301
56712
  current
56302
56713
  ].join(" \u2192 ");
56303
56714
  errors5.push(`Circular alias detected: ${fullChain}`);
56304
56715
  break;
56305
56716
  }
56306
56717
  visited.add(current);
56307
- path51.push(current);
56718
+ path53.push(current);
56308
56719
  current = currentEntry.aliasOf || "";
56309
56720
  }
56310
56721
  }
@@ -56797,6 +57208,13 @@ Subcommands:
56797
57208
  args: "",
56798
57209
  category: "utility"
56799
57210
  },
57211
+ "memory evaluate": {
57212
+ handler: (ctx) => handleMemoryEvaluateCommand(ctx.directory, ctx.args),
57213
+ description: "Run golden Swarm memory recall evaluation fixtures",
57214
+ subcommandOf: "memory",
57215
+ args: "--json, --fixtures <directory>",
57216
+ category: "diagnostics"
57217
+ },
56800
57218
  "memory import": {
56801
57219
  handler: (ctx) => handleMemoryImportCommand(ctx.directory, ctx.args),
56802
57220
  description: "Import legacy JSONL memory into SQLite",
@@ -56847,68 +57265,68 @@ init_package();
56847
57265
  init_registry();
56848
57266
  init_cache_paths();
56849
57267
  init_constants();
56850
- import * as fs29 from "fs";
56851
- import * as os7 from "os";
56852
- import * as path51 from "path";
57268
+ import * as fs30 from "fs";
57269
+ import * as os8 from "os";
57270
+ import * as path53 from "path";
56853
57271
  var { version: version4 } = package_default;
56854
57272
  var CONFIG_DIR = getPluginConfigDir();
56855
- var OPENCODE_CONFIG_PATH = path51.join(CONFIG_DIR, "opencode.json");
56856
- var PLUGIN_CONFIG_PATH = path51.join(CONFIG_DIR, "opencode-swarm.json");
56857
- var PROMPTS_DIR = path51.join(CONFIG_DIR, "opencode-swarm");
57273
+ var OPENCODE_CONFIG_PATH = path53.join(CONFIG_DIR, "opencode.json");
57274
+ var PLUGIN_CONFIG_PATH = path53.join(CONFIG_DIR, "opencode-swarm.json");
57275
+ var PROMPTS_DIR = path53.join(CONFIG_DIR, "opencode-swarm");
56858
57276
  var OPENCODE_PLUGIN_CACHE_PATHS = getPluginCachePaths();
56859
57277
  var OPENCODE_PLUGIN_LOCK_FILE_PATHS = getPluginLockFilePaths();
56860
57278
  function isSafeCachePath(p) {
56861
- const resolved = path51.resolve(p);
56862
- const home = path51.resolve(os7.homedir());
57279
+ const resolved = path53.resolve(p);
57280
+ const home = path53.resolve(os8.homedir());
56863
57281
  if (resolved === "/" || resolved === home || resolved.length <= home.length) {
56864
57282
  return false;
56865
57283
  }
56866
- const segments = resolved.split(path51.sep).filter((s) => s.length > 0);
57284
+ const segments = resolved.split(path53.sep).filter((s) => s.length > 0);
56867
57285
  if (segments.length < 4) {
56868
57286
  return false;
56869
57287
  }
56870
- const leaf = path51.basename(resolved);
57288
+ const leaf = path53.basename(resolved);
56871
57289
  if (leaf !== "opencode-swarm@latest" && leaf !== "opencode-swarm") {
56872
57290
  return false;
56873
57291
  }
56874
- const parent = path51.basename(path51.dirname(resolved));
57292
+ const parent = path53.basename(path53.dirname(resolved));
56875
57293
  if (parent !== "packages" && parent !== "node_modules") {
56876
57294
  return false;
56877
57295
  }
56878
- const grandparent = path51.basename(path51.dirname(path51.dirname(resolved)));
57296
+ const grandparent = path53.basename(path53.dirname(path53.dirname(resolved)));
56879
57297
  if (grandparent !== "opencode") {
56880
57298
  return false;
56881
57299
  }
56882
57300
  return true;
56883
57301
  }
56884
57302
  function isSafeLockFilePath(p) {
56885
- const resolved = path51.resolve(p);
56886
- const home = path51.resolve(os7.homedir());
57303
+ const resolved = path53.resolve(p);
57304
+ const home = path53.resolve(os8.homedir());
56887
57305
  if (resolved === "/" || resolved === home || resolved.length <= home.length) {
56888
57306
  return false;
56889
57307
  }
56890
- const segments = resolved.split(path51.sep).filter((s) => s.length > 0);
57308
+ const segments = resolved.split(path53.sep).filter((s) => s.length > 0);
56891
57309
  if (segments.length < 4) {
56892
57310
  return false;
56893
57311
  }
56894
- const leaf = path51.basename(resolved);
57312
+ const leaf = path53.basename(resolved);
56895
57313
  if (leaf !== "bun.lock" && leaf !== "bun.lockb" && leaf !== "package-lock.json") {
56896
57314
  return false;
56897
57315
  }
56898
- const parent = path51.basename(path51.dirname(resolved));
57316
+ const parent = path53.basename(path53.dirname(resolved));
56899
57317
  if (parent !== "opencode") {
56900
57318
  return false;
56901
57319
  }
56902
57320
  return true;
56903
57321
  }
56904
57322
  function ensureDir(dir) {
56905
- if (!fs29.existsSync(dir)) {
56906
- fs29.mkdirSync(dir, { recursive: true });
57323
+ if (!fs30.existsSync(dir)) {
57324
+ fs30.mkdirSync(dir, { recursive: true });
56907
57325
  }
56908
57326
  }
56909
57327
  function loadJson(filepath) {
56910
57328
  try {
56911
- const content = fs29.readFileSync(filepath, "utf-8");
57329
+ const content = fs30.readFileSync(filepath, "utf-8");
56912
57330
  const stripped = content.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (match, comment) => comment ? "" : match).replace(/,(\s*[}\]])/g, "$1");
56913
57331
  return JSON.parse(stripped);
56914
57332
  } catch {
@@ -56916,14 +57334,14 @@ function loadJson(filepath) {
56916
57334
  }
56917
57335
  }
56918
57336
  function saveJson(filepath, data) {
56919
- fs29.writeFileSync(filepath, `${JSON.stringify(data, null, 2)}
57337
+ fs30.writeFileSync(filepath, `${JSON.stringify(data, null, 2)}
56920
57338
  `, "utf-8");
56921
57339
  }
56922
57340
  function writeProjectConfigIfMissing(cwd) {
56923
57341
  try {
56924
- const opencodeDir = path51.join(cwd, ".opencode");
56925
- const projectConfigPath = path51.join(opencodeDir, "opencode-swarm.json");
56926
- if (fs29.existsSync(projectConfigPath)) {
57342
+ const opencodeDir = path53.join(cwd, ".opencode");
57343
+ const projectConfigPath = path53.join(opencodeDir, "opencode-swarm.json");
57344
+ if (fs30.existsSync(projectConfigPath)) {
56927
57345
  return;
56928
57346
  }
56929
57347
  ensureDir(opencodeDir);
@@ -56939,7 +57357,7 @@ async function install() {
56939
57357
  `);
56940
57358
  ensureDir(CONFIG_DIR);
56941
57359
  ensureDir(PROMPTS_DIR);
56942
- const LEGACY_CONFIG_PATH = path51.join(CONFIG_DIR, "config.json");
57360
+ const LEGACY_CONFIG_PATH = path53.join(CONFIG_DIR, "config.json");
56943
57361
  let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
56944
57362
  if (!opencodeConfig) {
56945
57363
  const legacyConfig = loadJson(LEGACY_CONFIG_PATH);
@@ -56986,7 +57404,7 @@ async function install() {
56986
57404
  console.warn(`\u26A0 Could not clear opencode lock file \u2014 you may need to delete it manually:
56987
57405
  ${failed}`);
56988
57406
  }
56989
- if (!fs29.existsSync(PLUGIN_CONFIG_PATH)) {
57407
+ if (!fs30.existsSync(PLUGIN_CONFIG_PATH)) {
56990
57408
  const defaultConfig = {
56991
57409
  agents: { ...DEFAULT_AGENT_CONFIGS },
56992
57410
  max_iterations: 5
@@ -57065,14 +57483,14 @@ function evictPluginCaches() {
57065
57483
  const cleared = [];
57066
57484
  const failed = [];
57067
57485
  for (const cachePath of OPENCODE_PLUGIN_CACHE_PATHS) {
57068
- if (!fs29.existsSync(cachePath))
57486
+ if (!fs30.existsSync(cachePath))
57069
57487
  continue;
57070
57488
  if (!isSafeCachePath(cachePath)) {
57071
57489
  failed.push(`${cachePath} (refused: failed safety check)`);
57072
57490
  continue;
57073
57491
  }
57074
57492
  try {
57075
- fs29.rmSync(cachePath, { recursive: true, force: true });
57493
+ fs30.rmSync(cachePath, { recursive: true, force: true });
57076
57494
  cleared.push(cachePath);
57077
57495
  } catch (err) {
57078
57496
  failed.push(`${cachePath} (${err instanceof Error ? err.message : String(err)})`);
@@ -57084,14 +57502,14 @@ function evictLockFiles() {
57084
57502
  const cleared = [];
57085
57503
  const failed = [];
57086
57504
  for (const lockPath of OPENCODE_PLUGIN_LOCK_FILE_PATHS) {
57087
- if (!fs29.existsSync(lockPath))
57505
+ if (!fs30.existsSync(lockPath))
57088
57506
  continue;
57089
57507
  if (!isSafeLockFilePath(lockPath)) {
57090
57508
  failed.push(`${lockPath} (refused: failed safety check)`);
57091
57509
  continue;
57092
57510
  }
57093
57511
  try {
57094
- fs29.unlinkSync(lockPath);
57512
+ fs30.unlinkSync(lockPath);
57095
57513
  cleared.push(lockPath);
57096
57514
  } catch (err) {
57097
57515
  const code = err?.code;
@@ -57110,7 +57528,7 @@ async function uninstall() {
57110
57528
  `);
57111
57529
  const opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
57112
57530
  if (!opencodeConfig) {
57113
- if (fs29.existsSync(OPENCODE_CONFIG_PATH)) {
57531
+ if (fs30.existsSync(OPENCODE_CONFIG_PATH)) {
57114
57532
  console.log(`\u2717 Could not parse opencode config at: ${OPENCODE_CONFIG_PATH}`);
57115
57533
  return 1;
57116
57534
  } else {
@@ -57142,13 +57560,13 @@ async function uninstall() {
57142
57560
  console.log("\u2713 Re-enabled default OpenCode agents (explore, general)");
57143
57561
  if (process.argv.includes("--clean")) {
57144
57562
  let cleaned = false;
57145
- if (fs29.existsSync(PLUGIN_CONFIG_PATH)) {
57146
- fs29.unlinkSync(PLUGIN_CONFIG_PATH);
57563
+ if (fs30.existsSync(PLUGIN_CONFIG_PATH)) {
57564
+ fs30.unlinkSync(PLUGIN_CONFIG_PATH);
57147
57565
  console.log(`\u2713 Removed plugin config: ${PLUGIN_CONFIG_PATH}`);
57148
57566
  cleaned = true;
57149
57567
  }
57150
- if (fs29.existsSync(PROMPTS_DIR)) {
57151
- fs29.rmSync(PROMPTS_DIR, { recursive: true });
57568
+ if (fs30.existsSync(PROMPTS_DIR)) {
57569
+ fs30.rmSync(PROMPTS_DIR, { recursive: true });
57152
57570
  console.log(`\u2713 Removed custom prompts: ${PROMPTS_DIR}`);
57153
57571
  cleaned = true;
57154
57572
  }