opencode-swarm 7.37.0 → 7.39.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.39.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
  ],
@@ -38859,6 +38860,110 @@ var init_close = __esm(() => {
38859
38860
  ];
38860
38861
  });
38861
38862
 
38863
+ // src/commands/concurrency.ts
38864
+ async function handleConcurrencyCommand(directory, args, sessionID) {
38865
+ if (!sessionID || sessionID.trim() === "") {
38866
+ return "Error: No active session context. Concurrency requires an active session. Use /swarm concurrency from within an OpenCode session, or start a session first.";
38867
+ }
38868
+ const session = getAgentSession(sessionID);
38869
+ if (!session) {
38870
+ return "Error: No active session. Concurrency requires an active session to operate.";
38871
+ }
38872
+ const arg0 = args[0]?.toLowerCase();
38873
+ const arg1 = args[1];
38874
+ const plan = await loadPlanJsonOnly(directory).catch(() => null);
38875
+ const hasPlan = plan !== null && plan !== undefined;
38876
+ if (arg0 === undefined) {
38877
+ return [
38878
+ "Concurrency commands:",
38879
+ " /swarm concurrency set <N|preset> \u2014 Set session concurrency override (1-64 or min/medium/max)",
38880
+ " /swarm concurrency status \u2014 Show effective concurrency",
38881
+ " /swarm concurrency reset \u2014 Clear the override"
38882
+ ].join(`
38883
+ `);
38884
+ }
38885
+ if (arg0 === "status") {
38886
+ return buildStatusMessage(session, plan);
38887
+ }
38888
+ if (!hasPlan) {
38889
+ if (arg0 === "set") {
38890
+ return "No active plan. Concurrency override requires an active plan.";
38891
+ }
38892
+ }
38893
+ if (arg0 === "reset") {
38894
+ session.maxConcurrencyOverride = undefined;
38895
+ return "Concurrency override cleared";
38896
+ }
38897
+ if (arg0 === "set") {
38898
+ if (arg1 === undefined) {
38899
+ return "Error: /swarm concurrency set requires a value. Usage: /swarm concurrency set <N|preset>";
38900
+ }
38901
+ return handleSetCommand(session, arg1);
38902
+ }
38903
+ return [
38904
+ `Unknown concurrency subcommand: ${arg0}`,
38905
+ "Usage: /swarm concurrency <set|status|reset>"
38906
+ ].join(`
38907
+ `);
38908
+ }
38909
+ function handleSetCommand(session, value) {
38910
+ const normalizedValue = value.toLowerCase();
38911
+ if (normalizedValue in PRESETS) {
38912
+ const presetConcurrency = PRESETS[normalizedValue];
38913
+ session.maxConcurrencyOverride = presetConcurrency;
38914
+ return `Concurrency override set to ${presetConcurrency} (${normalizedValue})`;
38915
+ }
38916
+ const numericValue = Number(value);
38917
+ if (Number.isNaN(numericValue)) {
38918
+ return `Invalid concurrency value: ${value}. Must be a number (1-64) or a preset (min, medium, max).`;
38919
+ }
38920
+ if (!Number.isInteger(numericValue)) {
38921
+ return `Invalid concurrency value: ${value}. Must be a number (1-64) or a preset (min, medium, max).`;
38922
+ }
38923
+ if (numericValue < MIN_CONCURRENCY || numericValue > MAX_CONCURRENCY) {
38924
+ return `Concurrency value ${value} is out of range. Must be between ${MIN_CONCURRENCY} and ${MAX_CONCURRENCY}.`;
38925
+ }
38926
+ session.maxConcurrencyOverride = numericValue;
38927
+ return `Concurrency override set to ${numericValue}`;
38928
+ }
38929
+ function buildStatusMessage(session, plan) {
38930
+ const overrideActive = session.maxConcurrencyOverride !== undefined;
38931
+ const configuredOverride = session.maxConcurrencyOverride ?? "absent";
38932
+ const hasPlan = plan !== null && plan !== undefined;
38933
+ const planBaseline = hasPlan ? plan.execution_profile?.max_concurrent_tasks ?? 1 : 1;
38934
+ const parallelizationEnabled = hasPlan ? plan.execution_profile?.parallelization_enabled ?? false : false;
38935
+ const operationalEffective = !parallelizationEnabled ? 1 : session.maxConcurrencyOverride ?? planBaseline;
38936
+ let description;
38937
+ if (!hasPlan) {
38938
+ description = "No active plan";
38939
+ } else if (!parallelizationEnabled) {
38940
+ description = "Parallelization disabled (always 1)";
38941
+ } else if (overrideActive) {
38942
+ description = `Override active (${session.maxConcurrencyOverride})`;
38943
+ } else {
38944
+ description = `Plan baseline (${planBaseline})`;
38945
+ }
38946
+ return [
38947
+ `Concurrency: ${description}`,
38948
+ ` override_active: ${overrideActive}`,
38949
+ ` configured_override: ${configuredOverride}`,
38950
+ ` plan_baseline: ${planBaseline}`,
38951
+ ` operational_effective: ${operationalEffective}`,
38952
+ ` parallelization_enabled: ${parallelizationEnabled}`
38953
+ ].join(`
38954
+ `);
38955
+ }
38956
+ var PRESETS, MIN_CONCURRENCY = 1, MAX_CONCURRENCY = 64;
38957
+ var init_concurrency = __esm(() => {
38958
+ init_manager();
38959
+ init_state();
38960
+ PRESETS = {
38961
+ min: 1,
38962
+ medium: 3,
38963
+ max: 8
38964
+ };
38965
+ });
38966
+
38862
38967
  // src/commands/config.ts
38863
38968
  import * as os4 from "os";
38864
38969
  import * as path17 from "path";
@@ -44427,7 +44532,10 @@ function serializeAgentSession(s) {
44427
44532
  fullAutoDeadlockCount: s.fullAutoDeadlockCount ?? 0,
44428
44533
  fullAutoLastQuestionHash: s.fullAutoLastQuestionHash ?? null,
44429
44534
  sessionRehydratedAt: s.sessionRehydratedAt ?? 0,
44430
- ...Object.keys(stageBCompletion).length > 0 && { stageBCompletion }
44535
+ ...Object.keys(stageBCompletion).length > 0 && { stageBCompletion },
44536
+ ...s.maxConcurrencyOverride !== undefined && {
44537
+ maxConcurrencyOverride: s.maxConcurrencyOverride
44538
+ }
44431
44539
  };
44432
44540
  }
44433
44541
  async function writeSnapshot(directory, state) {
@@ -47418,6 +47526,332 @@ var init_gateway = __esm(() => {
47418
47526
  gitRemoteUrlCache = new Map;
47419
47527
  });
47420
47528
 
47529
+ // src/memory/evaluation.ts
47530
+ import * as fs12 from "fs/promises";
47531
+ import * as os7 from "os";
47532
+ import * as path32 from "path";
47533
+ async function evaluateMemoryRecallFixtures(options) {
47534
+ const fixtureDirectory = path32.resolve(options.fixtureDirectory);
47535
+ const providers = options.providers ?? DEFAULT_PROVIDERS;
47536
+ const modes = options.modes ?? DEFAULT_MODES;
47537
+ const generatedAt = new Date().toISOString();
47538
+ const fixtures = await loadRecallEvaluationFixtures(fixtureDirectory);
47539
+ const runs = [];
47540
+ for (const fixture of fixtures) {
47541
+ const materialized = materializeFixture(fixture);
47542
+ for (const providerName of providers) {
47543
+ const tempRoot = await fs12.realpath(await fs12.mkdtemp(path32.join(os7.tmpdir(), "swarm-memory-eval-")));
47544
+ const provider = createEvaluationProvider(providerName, tempRoot);
47545
+ try {
47546
+ await provider.initialize?.();
47547
+ for (const record3 of materialized.records) {
47548
+ await provider.upsert(record3);
47549
+ }
47550
+ for (const mode of modes) {
47551
+ const request = buildRecallRequest(fixture, mode);
47552
+ const items = await provider.recall(request);
47553
+ const retrievedIds = items.map((item) => item.record.id);
47554
+ const run = buildRun({
47555
+ fixture,
47556
+ provider: providerName,
47557
+ mode,
47558
+ k: fixture.k ?? request.maxItems,
47559
+ retrievedIds,
47560
+ materialized
47561
+ });
47562
+ runs.push(run);
47563
+ }
47564
+ } finally {
47565
+ await provider.close?.();
47566
+ if (!options.keepTempRoots) {
47567
+ await fs12.rm(tempRoot, { recursive: true, force: true });
47568
+ }
47569
+ }
47570
+ }
47571
+ }
47572
+ return {
47573
+ schema_version: 1,
47574
+ generated_at: generatedAt,
47575
+ fixture_directory: fixtureDirectory,
47576
+ providers,
47577
+ modes,
47578
+ summary: summarizeRuns(fixtures.length, runs),
47579
+ runs
47580
+ };
47581
+ }
47582
+ async function loadRecallEvaluationFixtures(fixtureDirectory) {
47583
+ const entries = await fs12.readdir(fixtureDirectory, { withFileTypes: true });
47584
+ const files = entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort((a, b) => a.localeCompare(b));
47585
+ const fixtures = [];
47586
+ for (const file3 of files) {
47587
+ const raw = await fs12.readFile(path32.join(fixtureDirectory, file3), "utf-8");
47588
+ fixtures.push(validateFixture(JSON.parse(raw), file3));
47589
+ }
47590
+ return fixtures;
47591
+ }
47592
+ function createEvaluationProvider(provider, root) {
47593
+ const config3 = {
47594
+ ...DEFAULT_MEMORY_CONFIG,
47595
+ enabled: true,
47596
+ provider
47597
+ };
47598
+ return createConfiguredMemoryProvider(root, config3);
47599
+ }
47600
+ function buildRecallRequest(fixture, mode) {
47601
+ const maxItems = fixture.maxItems ?? fixture.k ?? 5;
47602
+ const base = {
47603
+ query: fixture.query,
47604
+ task: fixture.task,
47605
+ agentRole: mode === "curator" ? "curator" : fixture.agentRole,
47606
+ mode,
47607
+ scopes: fixture.scopes,
47608
+ kinds: fixture.kinds,
47609
+ maxItems,
47610
+ tokenBudget: fixture.tokenBudget ?? 1000,
47611
+ minScore: mode === "injection" ? 0.25 : 0,
47612
+ requireQuerySignal: mode === "injection"
47613
+ };
47614
+ return base;
47615
+ }
47616
+ function materializeFixture(fixture) {
47617
+ const idsByLabel = new Map;
47618
+ const labelsById = new Map;
47619
+ const baseRecords = fixture.records.map((record3) => {
47620
+ const base = {
47621
+ scope: record3.scope,
47622
+ kind: record3.kind,
47623
+ text: record3.text
47624
+ };
47625
+ const id = createMemoryId(base);
47626
+ idsByLabel.set(record3.label, id);
47627
+ labelsById.set(id, record3.label);
47628
+ return { input: record3, id, base };
47629
+ });
47630
+ const expectedIds = new Set(fixture.expectedLabels.map((label) => {
47631
+ const id = idsByLabel.get(label);
47632
+ if (!id) {
47633
+ throw new Error(`fixture ${fixture.name} expected unknown label ${label}`);
47634
+ }
47635
+ return id;
47636
+ }));
47637
+ const allowedScopeKeys = new Set(fixture.scopes.map(stableScopeKey));
47638
+ const staleIds = new Set;
47639
+ const crossScopeIds = new Set;
47640
+ const sameScopeNoiseIds = new Set;
47641
+ const records = baseRecords.map(({ input, id, base }) => {
47642
+ const supersededBy = input.state?.supersededByLabel ? idsByLabel.get(input.state.supersededByLabel) : undefined;
47643
+ if (input.state?.supersededByLabel && !supersededBy) {
47644
+ throw new Error(`fixture ${fixture.name} record ${input.label} supersedes unknown label ${input.state.supersededByLabel}`);
47645
+ }
47646
+ const metadata = {
47647
+ ...input.metadata ?? {},
47648
+ fixture: fixture.name,
47649
+ fixtureLabel: input.label,
47650
+ ...input.state?.deleted ? { deleted: true } : {}
47651
+ };
47652
+ const record3 = {
47653
+ id,
47654
+ ...base,
47655
+ tags: input.tags ?? [],
47656
+ confidence: input.confidence ?? 0.8,
47657
+ stability: input.stability ?? "durable",
47658
+ source: input.source ?? { type: "manual", ref: fixture.name },
47659
+ createdAt: DEFAULT_TIMESTAMP,
47660
+ updatedAt: DEFAULT_TIMESTAMP,
47661
+ expiresAt: input.state?.expiresAt,
47662
+ supersededBy,
47663
+ contentHash: computeMemoryContentHash(base),
47664
+ metadata
47665
+ };
47666
+ if (record3.metadata.deleted === true || record3.supersededBy || record3.expiresAt && Date.parse(record3.expiresAt) <= Date.now()) {
47667
+ staleIds.add(record3.id);
47668
+ }
47669
+ const inScope = allowedScopeKeys.has(stableScopeKey(record3.scope));
47670
+ if (!inScope) {
47671
+ crossScopeIds.add(record3.id);
47672
+ } else if (!expectedIds.has(record3.id) && !staleIds.has(record3.id)) {
47673
+ sameScopeNoiseIds.add(record3.id);
47674
+ }
47675
+ return validateMemoryRecordRules(record3, { rejectDurableSecrets: true });
47676
+ });
47677
+ return {
47678
+ records,
47679
+ idsByLabel,
47680
+ labelsById,
47681
+ expectedIds,
47682
+ staleIds,
47683
+ crossScopeIds,
47684
+ sameScopeNoiseIds
47685
+ };
47686
+ }
47687
+ function buildRun(args) {
47688
+ const { fixture, provider, mode, k, retrievedIds, materialized } = args;
47689
+ const topK = retrievedIds.slice(0, k);
47690
+ const relevantAtK = topK.filter((id) => materialized.expectedIds.has(id)).length;
47691
+ const crossScopeLeakCount = retrievedIds.filter((id) => materialized.crossScopeIds.has(id)).length;
47692
+ const staleMemoryCount = retrievedIds.filter((id) => materialized.staleIds.has(id)).length;
47693
+ const noisyInjectionCount = mode === "injection" ? retrievedIds.filter((id) => materialized.sameScopeNoiseIds.has(id)).length : 0;
47694
+ const sameScopeNoiseCount = retrievedIds.filter((id) => materialized.sameScopeNoiseIds.has(id)).length;
47695
+ const metrics = {
47696
+ "precision@k": relevantAtK / Math.max(k, 1),
47697
+ "recall@k": relevantAtK / Math.max(materialized.expectedIds.size, 1),
47698
+ injection_count: mode === "injection" ? retrievedIds.length : 0,
47699
+ noisy_injection_count: noisyInjectionCount,
47700
+ same_scope_noise_count: sameScopeNoiseCount,
47701
+ cross_scope_leak_count: crossScopeLeakCount,
47702
+ stale_memory_count: staleMemoryCount
47703
+ };
47704
+ return {
47705
+ fixture: fixture.name,
47706
+ provider,
47707
+ mode,
47708
+ k,
47709
+ query: fixture.query,
47710
+ expected_labels: fixture.expectedLabels,
47711
+ expected_ids: fixture.expectedLabels.map((label) => materialized.idsByLabel.get(label) ?? label),
47712
+ retrieved_labels: retrievedIds.map((id) => materialized.labelsById.get(id) ?? id),
47713
+ retrieved_ids: retrievedIds,
47714
+ metrics,
47715
+ passed: metrics["recall@k"] >= 1 && metrics.noisy_injection_count === 0 && metrics.cross_scope_leak_count === 0 && metrics.stale_memory_count === 0
47716
+ };
47717
+ }
47718
+ function summarizeRuns(fixtureCount, runs) {
47719
+ const total = runs.reduce((acc, run) => {
47720
+ acc["precision@k"] += run.metrics["precision@k"];
47721
+ acc["recall@k"] += run.metrics["recall@k"];
47722
+ acc.injection_count += run.metrics.injection_count;
47723
+ acc.noisy_injection_count += run.metrics.noisy_injection_count;
47724
+ acc.same_scope_noise_count += run.metrics.same_scope_noise_count;
47725
+ acc.cross_scope_leak_count += run.metrics.cross_scope_leak_count;
47726
+ acc.stale_memory_count += run.metrics.stale_memory_count;
47727
+ if (run.passed)
47728
+ acc.passed_run_count++;
47729
+ return acc;
47730
+ }, {
47731
+ "precision@k": 0,
47732
+ "recall@k": 0,
47733
+ injection_count: 0,
47734
+ noisy_injection_count: 0,
47735
+ same_scope_noise_count: 0,
47736
+ cross_scope_leak_count: 0,
47737
+ stale_memory_count: 0,
47738
+ passed_run_count: 0
47739
+ });
47740
+ const denominator = Math.max(runs.length, 1);
47741
+ return {
47742
+ fixture_count: fixtureCount,
47743
+ run_count: runs.length,
47744
+ passed_run_count: total.passed_run_count,
47745
+ "precision@k": total["precision@k"] / denominator,
47746
+ "recall@k": total["recall@k"] / denominator,
47747
+ injection_count: total.injection_count,
47748
+ noisy_injection_count: total.noisy_injection_count,
47749
+ same_scope_noise_count: total.same_scope_noise_count,
47750
+ cross_scope_leak_count: total.cross_scope_leak_count,
47751
+ stale_memory_count: total.stale_memory_count
47752
+ };
47753
+ }
47754
+ function validateFixture(value, file3) {
47755
+ if (!value || typeof value !== "object") {
47756
+ throw new Error(`memory recall fixture ${file3} must be an object`);
47757
+ }
47758
+ const fixture = value;
47759
+ if (typeof fixture.name !== "string" || !fixture.name) {
47760
+ throw new Error(`memory recall fixture ${file3} is missing name`);
47761
+ }
47762
+ if (typeof fixture.query !== "string" || fixture.query.length < 3) {
47763
+ throw new Error(`memory recall fixture ${file3} has invalid query`);
47764
+ }
47765
+ if (!Array.isArray(fixture.scopes) || fixture.scopes.length === 0) {
47766
+ throw new Error(`memory recall fixture ${file3} must define scopes`);
47767
+ }
47768
+ const scopes = fixture.scopes.map((scope, index) => validateScope(scope, file3, `scope #${index + 1}`));
47769
+ if (!Array.isArray(fixture.expectedLabels) || fixture.expectedLabels.length === 0) {
47770
+ throw new Error(`memory recall fixture ${file3} must define expectedLabels`);
47771
+ }
47772
+ const expectedLabels = fixture.expectedLabels.map((label, index) => {
47773
+ if (typeof label !== "string" || !label) {
47774
+ throw new Error(`memory recall fixture ${file3} expectedLabels #${index + 1} must be a non-empty string`);
47775
+ }
47776
+ return label;
47777
+ });
47778
+ if (!Array.isArray(fixture.records) || fixture.records.length === 0) {
47779
+ throw new Error(`memory recall fixture ${file3} must define records`);
47780
+ }
47781
+ const records = fixture.records.map((record3, index) => validateFixtureRecord(record3, file3, index));
47782
+ return {
47783
+ ...fixture,
47784
+ name: fixture.name,
47785
+ query: fixture.query,
47786
+ scopes,
47787
+ expectedLabels,
47788
+ records
47789
+ };
47790
+ }
47791
+ function validateFixtureRecord(value, file3, index) {
47792
+ if (!value || typeof value !== "object") {
47793
+ throw new Error(`memory recall fixture ${file3} record #${index + 1} must be an object`);
47794
+ }
47795
+ const record3 = value;
47796
+ const labelForError = typeof record3.label === "string" && record3.label ? record3.label : `#${index + 1}`;
47797
+ if (typeof record3.label !== "string" || !record3.label) {
47798
+ throw new Error(`memory recall fixture ${file3} record ${labelForError} is missing label`);
47799
+ }
47800
+ const scope = validateScope(record3.scope, file3, `record ${record3.label}`);
47801
+ if (!("kind" in record3) || record3.kind === "") {
47802
+ throw new Error(`memory recall fixture ${file3} record ${record3.label} is missing kind`);
47803
+ }
47804
+ if (typeof record3.kind !== "string") {
47805
+ throw new Error(`memory recall fixture ${file3} record ${record3.label} has invalid kind`);
47806
+ }
47807
+ const parsedKind = MemoryKindSchema.safeParse(record3.kind);
47808
+ if (!parsedKind.success) {
47809
+ throw new Error(`memory recall fixture ${file3} record ${record3.label} has invalid kind`);
47810
+ }
47811
+ if (!("text" in record3) || record3.text === "") {
47812
+ throw new Error(`memory recall fixture ${file3} record ${record3.label} is missing text`);
47813
+ }
47814
+ if (typeof record3.text !== "string") {
47815
+ throw new Error(`memory recall fixture ${file3} record ${record3.label} has invalid text`);
47816
+ }
47817
+ return {
47818
+ ...record3,
47819
+ label: record3.label,
47820
+ scope,
47821
+ kind: parsedKind.data,
47822
+ text: record3.text
47823
+ };
47824
+ }
47825
+ function validateScope(value, file3, descriptor) {
47826
+ if (!value || typeof value !== "object") {
47827
+ throw new Error(`memory recall fixture ${file3} ${descriptor} is missing scope`);
47828
+ }
47829
+ const scope = value;
47830
+ if (typeof scope.type !== "string") {
47831
+ throw new Error(`memory recall fixture ${file3} ${descriptor} has invalid scope type`);
47832
+ }
47833
+ const parsed = MemoryScopeRefSchema.safeParse(scope);
47834
+ if (!parsed.success) {
47835
+ throw new Error(`memory recall fixture ${file3} ${descriptor} has invalid scope`);
47836
+ }
47837
+ return parsed.data;
47838
+ }
47839
+ var DEFAULT_PROVIDERS, DEFAULT_MODES, DEFAULT_TIMESTAMP = "2026-05-26T12:00:00.000Z";
47840
+ var init_evaluation = __esm(() => {
47841
+ init_config3();
47842
+ init_gateway();
47843
+ init_schema2();
47844
+ DEFAULT_PROVIDERS = [
47845
+ "local-jsonl",
47846
+ "sqlite"
47847
+ ];
47848
+ DEFAULT_MODES = [
47849
+ "manual",
47850
+ "injection",
47851
+ "curator"
47852
+ ];
47853
+ });
47854
+
47421
47855
  // src/agents/agent-output-schema.ts
47422
47856
  var AgentMemoryProposalSchema, AgentOutputMemorySchema, CuratorOutputMemoryDecisionSchema;
47423
47857
  var init_agent_output_schema = __esm(() => {
@@ -47472,6 +47906,7 @@ var init_injector = __esm(() => {
47472
47906
  var init_memory = __esm(() => {
47473
47907
  init_config3();
47474
47908
  init_errors6();
47909
+ init_evaluation();
47475
47910
  init_gateway();
47476
47911
  init_injector();
47477
47912
  init_jsonl_migration();
@@ -47487,6 +47922,8 @@ var init_memory = __esm(() => {
47487
47922
 
47488
47923
  // src/commands/memory.ts
47489
47924
  import { existsSync as existsSync20 } from "fs";
47925
+ import * as path33 from "path";
47926
+ import { fileURLToPath as fileURLToPath2 } from "url";
47490
47927
  async function handleMemoryCommand(_directory, _args) {
47491
47928
  return [
47492
47929
  "## Swarm Memory",
@@ -47494,7 +47931,8 @@ async function handleMemoryCommand(_directory, _args) {
47494
47931
  "- `/swarm memory status` - show provider, SQLite path, JSONL files, and last migration report",
47495
47932
  "- `/swarm memory export` - export current memory and proposals to `.swarm/memory/export/*.jsonl`",
47496
47933
  "- `/swarm memory import` - import `.swarm/memory/{memories,proposals}.jsonl` into SQLite",
47497
- "- `/swarm memory migrate` - run the one-time legacy JSONL to SQLite migration"
47934
+ "- `/swarm memory migrate` - run the one-time legacy JSONL to SQLite migration",
47935
+ "- `/swarm memory evaluate --json` - run the golden recall evaluation fixtures and emit a JSON report"
47498
47936
  ].join(`
47499
47937
  `);
47500
47938
  }
@@ -47592,10 +48030,75 @@ async function handleMemoryExportCommand(directory, _args) {
47592
48030
  await provider.close?.();
47593
48031
  }
47594
48032
  }
48033
+ async function handleMemoryEvaluateCommand(directory, args) {
48034
+ const parsed = parseEvaluateArgs(directory, args);
48035
+ if ("error" in parsed)
48036
+ return parsed.error;
48037
+ const report = await evaluateMemoryRecallFixtures({
48038
+ fixtureDirectory: parsed.fixtureDirectory
48039
+ });
48040
+ if (parsed.json)
48041
+ return `${JSON.stringify(report, null, 2)}
48042
+ `;
48043
+ return [
48044
+ "## Swarm Memory Recall Evaluation",
48045
+ "",
48046
+ `- Fixtures: \`${report.summary.fixture_count}\``,
48047
+ `- Runs: \`${report.summary.run_count}\``,
48048
+ `- Passed runs: \`${report.summary.passed_run_count}\``,
48049
+ `- Precision@k: \`${report.summary["precision@k"].toFixed(3)}\``,
48050
+ `- Recall@k: \`${report.summary["recall@k"].toFixed(3)}\``,
48051
+ `- Injection count: \`${report.summary.injection_count}\``,
48052
+ `- Noisy injections: \`${report.summary.noisy_injection_count}\``,
48053
+ `- Same-scope noise: \`${report.summary.same_scope_noise_count}\``,
48054
+ `- Cross-scope leaks: \`${report.summary.cross_scope_leak_count}\``,
48055
+ `- Stale memories: \`${report.summary.stale_memory_count}\``,
48056
+ "",
48057
+ "Use `/swarm memory evaluate --json` for the full report."
48058
+ ].join(`
48059
+ `);
48060
+ }
47595
48061
  function resolveCommandMemoryConfig(directory) {
47596
48062
  const loaded = loadPluginConfig(directory).memory;
47597
48063
  return resolveMemoryConfig(loaded ?? DEFAULT_MEMORY_CONFIG);
47598
48064
  }
48065
+ function parseEvaluateArgs(directory, args) {
48066
+ let json3 = false;
48067
+ let fixtureDirectory = path33.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall");
48068
+ for (let i = 0;i < args.length; i++) {
48069
+ const arg = args[i];
48070
+ if (arg === "--json") {
48071
+ json3 = true;
48072
+ continue;
48073
+ }
48074
+ if (arg === "--fixtures") {
48075
+ const next = args[i + 1];
48076
+ if (!next) {
48077
+ return {
48078
+ error: "Usage: /swarm memory evaluate [--json] [--fixtures <directory>]"
48079
+ };
48080
+ }
48081
+ fixtureDirectory = path33.resolve(directory, next);
48082
+ i++;
48083
+ continue;
48084
+ }
48085
+ return {
48086
+ error: "Usage: /swarm memory evaluate [--json] [--fixtures <directory>]"
48087
+ };
48088
+ }
48089
+ return { json: json3, fixtureDirectory };
48090
+ }
48091
+ function resolvePackageRootFromModule(modulePath) {
48092
+ const moduleDir = path33.dirname(modulePath);
48093
+ const leaf = path33.basename(moduleDir);
48094
+ if (leaf === "commands" || leaf === "cli") {
48095
+ return path33.resolve(moduleDir, "..", "..");
48096
+ }
48097
+ if (leaf === "dist") {
48098
+ return path33.resolve(moduleDir, "..");
48099
+ }
48100
+ return path33.resolve(moduleDir, "..");
48101
+ }
47599
48102
  function formatMigrationResult(label, report) {
47600
48103
  if (!report) {
47601
48104
  return [
@@ -47635,9 +48138,11 @@ function appendInvalidRows(lines, invalidRows) {
47635
48138
  lines.push(`- ... ${invalidRows.length - 20} more`);
47636
48139
  }
47637
48140
  }
48141
+ var PACKAGE_ROOT;
47638
48142
  var init_memory2 = __esm(() => {
47639
48143
  init_loader();
47640
48144
  init_memory();
48145
+ PACKAGE_ROOT = path33.resolve(resolvePackageRootFromModule(fileURLToPath2(import.meta.url)));
47641
48146
  });
47642
48147
 
47643
48148
  // src/services/plan-service.ts
@@ -48024,8 +48529,8 @@ function containsControlChars(str) {
48024
48529
  var init_path_security = () => {};
48025
48530
 
48026
48531
  // src/tools/lint.ts
48027
- import * as fs12 from "fs";
48028
- import * as path32 from "path";
48532
+ import * as fs13 from "fs";
48533
+ import * as path34 from "path";
48029
48534
  function validateArgs(args) {
48030
48535
  if (typeof args !== "object" || args === null)
48031
48536
  return false;
@@ -48036,9 +48541,9 @@ function validateArgs(args) {
48036
48541
  }
48037
48542
  function getLinterCommand(linter, mode, projectDir) {
48038
48543
  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");
48544
+ const binDir = path34.join(projectDir, "node_modules", ".bin");
48545
+ const biomeBin = isWindows ? path34.join(binDir, "biome.EXE") : path34.join(binDir, "biome");
48546
+ const eslintBin = isWindows ? path34.join(binDir, "eslint.cmd") : path34.join(binDir, "eslint");
48042
48547
  switch (linter) {
48043
48548
  case "biome":
48044
48549
  if (mode === "fix") {
@@ -48054,7 +48559,7 @@ function getLinterCommand(linter, mode, projectDir) {
48054
48559
  }
48055
48560
  function getAdditionalLinterCommand(linter, mode, cwd) {
48056
48561
  const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
48057
- const gradlew = fs12.existsSync(path32.join(cwd, gradlewName)) ? path32.join(cwd, gradlewName) : null;
48562
+ const gradlew = fs13.existsSync(path34.join(cwd, gradlewName)) ? path34.join(cwd, gradlewName) : null;
48058
48563
  switch (linter) {
48059
48564
  case "ruff":
48060
48565
  return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
@@ -48088,12 +48593,12 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
48088
48593
  }
48089
48594
  }
48090
48595
  function detectRuff(cwd) {
48091
- if (fs12.existsSync(path32.join(cwd, "ruff.toml")))
48596
+ if (fs13.existsSync(path34.join(cwd, "ruff.toml")))
48092
48597
  return isCommandAvailable("ruff");
48093
48598
  try {
48094
- const pyproject = path32.join(cwd, "pyproject.toml");
48095
- if (fs12.existsSync(pyproject)) {
48096
- const content = fs12.readFileSync(pyproject, "utf-8");
48599
+ const pyproject = path34.join(cwd, "pyproject.toml");
48600
+ if (fs13.existsSync(pyproject)) {
48601
+ const content = fs13.readFileSync(pyproject, "utf-8");
48097
48602
  if (content.includes("[tool.ruff]"))
48098
48603
  return isCommandAvailable("ruff");
48099
48604
  }
@@ -48101,21 +48606,21 @@ function detectRuff(cwd) {
48101
48606
  return false;
48102
48607
  }
48103
48608
  function detectClippy(cwd) {
48104
- return fs12.existsSync(path32.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
48609
+ return fs13.existsSync(path34.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
48105
48610
  }
48106
48611
  function detectGolangciLint(cwd) {
48107
- return fs12.existsSync(path32.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
48612
+ return fs13.existsSync(path34.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
48108
48613
  }
48109
48614
  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"));
48615
+ const hasMaven = fs13.existsSync(path34.join(cwd, "pom.xml"));
48616
+ const hasGradle = fs13.existsSync(path34.join(cwd, "build.gradle")) || fs13.existsSync(path34.join(cwd, "build.gradle.kts"));
48617
+ const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs13.existsSync(path34.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
48113
48618
  return (hasMaven || hasGradle) && hasBinary;
48114
48619
  }
48115
48620
  function detectKtlint(cwd) {
48116
- const hasKotlin = fs12.existsSync(path32.join(cwd, "build.gradle.kts")) || fs12.existsSync(path32.join(cwd, "build.gradle")) || (() => {
48621
+ const hasKotlin = fs13.existsSync(path34.join(cwd, "build.gradle.kts")) || fs13.existsSync(path34.join(cwd, "build.gradle")) || (() => {
48117
48622
  try {
48118
- return fs12.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
48623
+ return fs13.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
48119
48624
  } catch {
48120
48625
  return false;
48121
48626
  }
@@ -48124,7 +48629,7 @@ function detectKtlint(cwd) {
48124
48629
  }
48125
48630
  function detectDotnetFormat(cwd) {
48126
48631
  try {
48127
- const files = fs12.readdirSync(cwd);
48632
+ const files = fs13.readdirSync(cwd);
48128
48633
  const hasCsproj = files.some((f) => f.endsWith(".csproj") || f.endsWith(".sln"));
48129
48634
  return hasCsproj && isCommandAvailable("dotnet");
48130
48635
  } catch {
@@ -48132,14 +48637,14 @@ function detectDotnetFormat(cwd) {
48132
48637
  }
48133
48638
  }
48134
48639
  function detectCppcheck(cwd) {
48135
- if (fs12.existsSync(path32.join(cwd, "CMakeLists.txt"))) {
48640
+ if (fs13.existsSync(path34.join(cwd, "CMakeLists.txt"))) {
48136
48641
  return isCommandAvailable("cppcheck");
48137
48642
  }
48138
48643
  try {
48139
- const dirsToCheck = [cwd, path32.join(cwd, "src")];
48644
+ const dirsToCheck = [cwd, path34.join(cwd, "src")];
48140
48645
  const hasCpp = dirsToCheck.some((dir) => {
48141
48646
  try {
48142
- return fs12.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
48647
+ return fs13.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
48143
48648
  } catch {
48144
48649
  return false;
48145
48650
  }
@@ -48150,13 +48655,13 @@ function detectCppcheck(cwd) {
48150
48655
  }
48151
48656
  }
48152
48657
  function detectSwiftlint(cwd) {
48153
- return fs12.existsSync(path32.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
48658
+ return fs13.existsSync(path34.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
48154
48659
  }
48155
48660
  function detectDartAnalyze(cwd) {
48156
- return fs12.existsSync(path32.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
48661
+ return fs13.existsSync(path34.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
48157
48662
  }
48158
48663
  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"));
48664
+ 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
48665
  }
48161
48666
  function detectAdditionalLinter(cwd) {
48162
48667
  if (detectRuff(cwd))
@@ -48184,10 +48689,10 @@ function detectAdditionalLinter(cwd) {
48184
48689
  function findBinInAncestors(startDir, binName) {
48185
48690
  let dir = startDir;
48186
48691
  while (true) {
48187
- const candidate = path32.join(dir, "node_modules", ".bin", binName);
48188
- if (fs12.existsSync(candidate))
48692
+ const candidate = path34.join(dir, "node_modules", ".bin", binName);
48693
+ if (fs13.existsSync(candidate))
48189
48694
  return candidate;
48190
- const parent = path32.dirname(dir);
48695
+ const parent = path34.dirname(dir);
48191
48696
  if (parent === dir)
48192
48697
  break;
48193
48698
  dir = parent;
@@ -48196,11 +48701,11 @@ function findBinInAncestors(startDir, binName) {
48196
48701
  }
48197
48702
  function findBinInEnvPath(binName) {
48198
48703
  const searchPath = process.env.PATH ?? "";
48199
- for (const dir of searchPath.split(path32.delimiter)) {
48704
+ for (const dir of searchPath.split(path34.delimiter)) {
48200
48705
  if (!dir)
48201
48706
  continue;
48202
- const candidate = path32.join(dir, binName);
48203
- if (fs12.existsSync(candidate))
48707
+ const candidate = path34.join(dir, binName);
48708
+ if (fs13.existsSync(candidate))
48204
48709
  return candidate;
48205
48710
  }
48206
48711
  return null;
@@ -48208,17 +48713,17 @@ function findBinInEnvPath(binName) {
48208
48713
  async function detectAvailableLinter(directory) {
48209
48714
  if (!directory)
48210
48715
  return null;
48211
- if (!fs12.existsSync(directory))
48716
+ if (!fs13.existsSync(directory))
48212
48717
  return null;
48213
48718
  const projectDir = directory;
48214
48719
  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");
48720
+ const biomeBin = isWindows ? path34.join(projectDir, "node_modules", ".bin", "biome.EXE") : path34.join(projectDir, "node_modules", ".bin", "biome");
48721
+ const eslintBin = isWindows ? path34.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path34.join(projectDir, "node_modules", ".bin", "eslint");
48217
48722
  const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
48218
48723
  if (localResult)
48219
48724
  return localResult;
48220
- const biomeAncestor = findBinInAncestors(path32.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
48221
- const eslintAncestor = findBinInAncestors(path32.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
48725
+ const biomeAncestor = findBinInAncestors(path34.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
48726
+ const eslintAncestor = findBinInAncestors(path34.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
48222
48727
  if (biomeAncestor || eslintAncestor) {
48223
48728
  return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
48224
48729
  }
@@ -48237,11 +48742,11 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
48237
48742
  stderr: "pipe"
48238
48743
  });
48239
48744
  const biomeExit = biomeProc.exited;
48240
- const timeout = new Promise((resolve10) => setTimeout(() => resolve10("timeout"), DETECT_TIMEOUT));
48745
+ const timeout = new Promise((resolve12) => setTimeout(() => resolve12("timeout"), DETECT_TIMEOUT));
48241
48746
  const result = await Promise.race([biomeExit, timeout]);
48242
48747
  if (result === "timeout") {
48243
48748
  biomeProc.kill();
48244
- } else if (biomeProc.exitCode === 0 && fs12.existsSync(biomeBin)) {
48749
+ } else if (biomeProc.exitCode === 0 && fs13.existsSync(biomeBin)) {
48245
48750
  return "biome";
48246
48751
  }
48247
48752
  } catch {}
@@ -48251,11 +48756,11 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
48251
48756
  stderr: "pipe"
48252
48757
  });
48253
48758
  const eslintExit = eslintProc.exited;
48254
- const timeout = new Promise((resolve10) => setTimeout(() => resolve10("timeout"), DETECT_TIMEOUT));
48759
+ const timeout = new Promise((resolve12) => setTimeout(() => resolve12("timeout"), DETECT_TIMEOUT));
48255
48760
  const result = await Promise.race([eslintExit, timeout]);
48256
48761
  if (result === "timeout") {
48257
48762
  eslintProc.kill();
48258
- } else if (eslintProc.exitCode === 0 && fs12.existsSync(eslintBin)) {
48763
+ } else if (eslintProc.exitCode === 0 && fs13.existsSync(eslintBin)) {
48259
48764
  return "eslint";
48260
48765
  }
48261
48766
  } catch {}
@@ -48440,8 +48945,8 @@ For Rust: rustup component add clippy`
48440
48945
  });
48441
48946
 
48442
48947
  // src/tools/secretscan.ts
48443
- import * as fs13 from "fs";
48444
- import * as path33 from "path";
48948
+ import * as fs14 from "fs";
48949
+ import * as path35 from "path";
48445
48950
  function calculateShannonEntropy(str) {
48446
48951
  if (str.length === 0)
48447
48952
  return 0;
@@ -48489,11 +48994,11 @@ function isGlobOrPathPattern(pattern) {
48489
48994
  return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
48490
48995
  }
48491
48996
  function loadSecretScanIgnore(scanDir) {
48492
- const ignorePath = path33.join(scanDir, ".secretscanignore");
48997
+ const ignorePath = path35.join(scanDir, ".secretscanignore");
48493
48998
  try {
48494
- if (!fs13.existsSync(ignorePath))
48999
+ if (!fs14.existsSync(ignorePath))
48495
49000
  return [];
48496
- const content = fs13.readFileSync(ignorePath, "utf8");
49001
+ const content = fs14.readFileSync(ignorePath, "utf8");
48497
49002
  const patterns = [];
48498
49003
  for (const rawLine of content.split(/\r?\n/)) {
48499
49004
  const line = rawLine.trim();
@@ -48512,7 +49017,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
48512
49017
  if (exactNames.has(entry))
48513
49018
  return true;
48514
49019
  for (const pattern of globPatterns) {
48515
- if (path33.matchesGlob(relPath, pattern))
49020
+ if (path35.matchesGlob(relPath, pattern))
48516
49021
  return true;
48517
49022
  }
48518
49023
  return false;
@@ -48533,7 +49038,7 @@ function validateDirectoryInput(dir) {
48533
49038
  return null;
48534
49039
  }
48535
49040
  function isBinaryFile(filePath, buffer) {
48536
- const ext = path33.extname(filePath).toLowerCase();
49041
+ const ext = path35.extname(filePath).toLowerCase();
48537
49042
  if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
48538
49043
  return true;
48539
49044
  }
@@ -48611,7 +49116,7 @@ function createRedactedContext(line, findings) {
48611
49116
  function scanFileForSecrets(filePath) {
48612
49117
  const findings = [];
48613
49118
  try {
48614
- const lstat = fs13.lstatSync(filePath);
49119
+ const lstat = fs14.lstatSync(filePath);
48615
49120
  if (lstat.isSymbolicLink()) {
48616
49121
  return findings;
48617
49122
  }
@@ -48620,14 +49125,14 @@ function scanFileForSecrets(filePath) {
48620
49125
  }
48621
49126
  let buffer;
48622
49127
  if (O_NOFOLLOW !== undefined) {
48623
- const fd = fs13.openSync(filePath, "r", O_NOFOLLOW);
49128
+ const fd = fs14.openSync(filePath, "r", O_NOFOLLOW);
48624
49129
  try {
48625
- buffer = fs13.readFileSync(fd);
49130
+ buffer = fs14.readFileSync(fd);
48626
49131
  } finally {
48627
- fs13.closeSync(fd);
49132
+ fs14.closeSync(fd);
48628
49133
  }
48629
49134
  } else {
48630
- buffer = fs13.readFileSync(filePath);
49135
+ buffer = fs14.readFileSync(filePath);
48631
49136
  }
48632
49137
  if (isBinaryFile(filePath, buffer)) {
48633
49138
  return findings;
@@ -48669,9 +49174,9 @@ function isSymlinkLoop(realPath, visited) {
48669
49174
  return false;
48670
49175
  }
48671
49176
  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}\\`);
49177
+ const resolvedScanDir = path35.resolve(scanDir);
49178
+ const resolvedRealPath = path35.resolve(realPath);
49179
+ return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path35.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
48675
49180
  }
48676
49181
  function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
48677
49182
  skippedDirs: 0,
@@ -48682,7 +49187,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
48682
49187
  const files = [];
48683
49188
  let entries;
48684
49189
  try {
48685
- entries = fs13.readdirSync(dir);
49190
+ entries = fs14.readdirSync(dir);
48686
49191
  } catch {
48687
49192
  stats.fileErrors++;
48688
49193
  return files;
@@ -48697,15 +49202,15 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
48697
49202
  return a.localeCompare(b);
48698
49203
  });
48699
49204
  for (const entry of entries) {
48700
- const fullPath = path33.join(dir, entry);
48701
- const relPath = path33.relative(scanDir, fullPath).replace(/\\/g, "/");
49205
+ const fullPath = path35.join(dir, entry);
49206
+ const relPath = path35.relative(scanDir, fullPath).replace(/\\/g, "/");
48702
49207
  if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
48703
49208
  stats.skippedDirs++;
48704
49209
  continue;
48705
49210
  }
48706
49211
  let lstat;
48707
49212
  try {
48708
- lstat = fs13.lstatSync(fullPath);
49213
+ lstat = fs14.lstatSync(fullPath);
48709
49214
  } catch {
48710
49215
  stats.fileErrors++;
48711
49216
  continue;
@@ -48717,7 +49222,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
48717
49222
  if (lstat.isDirectory()) {
48718
49223
  let realPath;
48719
49224
  try {
48720
- realPath = fs13.realpathSync(fullPath);
49225
+ realPath = fs14.realpathSync(fullPath);
48721
49226
  } catch {
48722
49227
  stats.fileErrors++;
48723
49228
  continue;
@@ -48733,7 +49238,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
48733
49238
  const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
48734
49239
  files.push(...subFiles);
48735
49240
  } else if (lstat.isFile()) {
48736
- const ext = path33.extname(fullPath).toLowerCase();
49241
+ const ext = path35.extname(fullPath).toLowerCase();
48737
49242
  if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
48738
49243
  files.push(fullPath);
48739
49244
  } else {
@@ -48936,7 +49441,7 @@ var init_secretscan = __esm(() => {
48936
49441
  redactTemplate: () => "SK[REDACTED]"
48937
49442
  }
48938
49443
  ];
48939
- O_NOFOLLOW = process.platform !== "win32" ? fs13.constants.O_NOFOLLOW : undefined;
49444
+ O_NOFOLLOW = process.platform !== "win32" ? fs14.constants.O_NOFOLLOW : undefined;
48940
49445
  secretscan = createSwarmTool({
48941
49446
  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
49447
  args: {
@@ -48993,15 +49498,15 @@ var init_secretscan = __esm(() => {
48993
49498
  }
48994
49499
  }
48995
49500
  try {
48996
- const _scanDirRaw = path33.resolve(directory);
49501
+ const _scanDirRaw = path35.resolve(directory);
48997
49502
  const scanDir = (() => {
48998
49503
  try {
48999
- return fs13.realpathSync(_scanDirRaw);
49504
+ return fs14.realpathSync(_scanDirRaw);
49000
49505
  } catch {
49001
49506
  return _scanDirRaw;
49002
49507
  }
49003
49508
  })();
49004
- if (!fs13.existsSync(scanDir)) {
49509
+ if (!fs14.existsSync(scanDir)) {
49005
49510
  const errorResult = {
49006
49511
  error: "directory not found",
49007
49512
  scan_dir: directory,
@@ -49012,7 +49517,7 @@ var init_secretscan = __esm(() => {
49012
49517
  };
49013
49518
  return JSON.stringify(errorResult, null, 2);
49014
49519
  }
49015
- const dirStat = fs13.statSync(scanDir);
49520
+ const dirStat = fs14.statSync(scanDir);
49016
49521
  if (!dirStat.isDirectory()) {
49017
49522
  const errorResult = {
49018
49523
  error: "target must be a directory, not a file",
@@ -49063,7 +49568,7 @@ var init_secretscan = __esm(() => {
49063
49568
  break;
49064
49569
  const fileFindings = scanFileForSecrets(filePath);
49065
49570
  try {
49066
- const stat4 = fs13.statSync(filePath);
49571
+ const stat4 = fs14.statSync(filePath);
49067
49572
  if (stat4.size > MAX_FILE_SIZE_BYTES) {
49068
49573
  skippedFiles++;
49069
49574
  continue;
@@ -49139,12 +49644,12 @@ var init_secretscan = __esm(() => {
49139
49644
  });
49140
49645
 
49141
49646
  // src/lang/default-backend.ts
49142
- import * as fs14 from "fs";
49143
- import * as path34 from "path";
49647
+ import * as fs15 from "fs";
49648
+ import * as path36 from "path";
49144
49649
  function detectFileExists(dir, pattern) {
49145
49650
  if (pattern.includes("*") || pattern.includes("?")) {
49146
49651
  try {
49147
- const files = fs14.readdirSync(dir);
49652
+ const files = fs15.readdirSync(dir);
49148
49653
  const regex = new RegExp(`^${pattern.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, ".")}$`);
49149
49654
  return files.some((f) => regex.test(f));
49150
49655
  } catch {
@@ -49152,7 +49657,7 @@ function detectFileExists(dir, pattern) {
49152
49657
  }
49153
49658
  }
49154
49659
  try {
49155
- fs14.accessSync(path34.join(dir, pattern));
49660
+ fs15.accessSync(path36.join(dir, pattern));
49156
49661
  return true;
49157
49662
  } catch {
49158
49663
  return false;
@@ -49280,8 +49785,8 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
49280
49785
  return ["mvn", "test"];
49281
49786
  case "gradle": {
49282
49787
  const isWindows = process.platform === "win32";
49283
- const hasGradlewBat = fs14.existsSync(path34.join(dir, "gradlew.bat"));
49284
- const hasGradlew = fs14.existsSync(path34.join(dir, "gradlew"));
49788
+ const hasGradlewBat = fs15.existsSync(path36.join(dir, "gradlew.bat"));
49789
+ const hasGradlew = fs15.existsSync(path36.join(dir, "gradlew"));
49285
49790
  if (hasGradlewBat && isWindows)
49286
49791
  return ["gradlew.bat", "test"];
49287
49792
  if (hasGradlew)
@@ -49298,7 +49803,7 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
49298
49803
  "cmake-build-release",
49299
49804
  "out"
49300
49805
  ];
49301
- const actualBuildDir = buildDirCandidates.find((d) => fs14.existsSync(path34.join(dir, d, "CMakeCache.txt"))) ?? "build";
49806
+ const actualBuildDir = buildDirCandidates.find((d) => fs15.existsSync(path36.join(dir, d, "CMakeCache.txt"))) ?? "build";
49302
49807
  return ["ctest", "--test-dir", actualBuildDir];
49303
49808
  }
49304
49809
  case "swift-test":
@@ -49585,23 +50090,23 @@ async function defaultSelectBuildCommand(profile, dir) {
49585
50090
  return null;
49586
50091
  }
49587
50092
  async function defaultTestFilesFor(profile, sourceFile, dir) {
49588
- const ext = path34.extname(sourceFile);
50093
+ const ext = path36.extname(sourceFile);
49589
50094
  if (!profile.extensions.includes(ext))
49590
50095
  return [];
49591
- const base = path34.basename(sourceFile, ext);
49592
- const rel = path34.relative(dir, sourceFile);
49593
- const relDir = path34.dirname(rel);
50096
+ const base = path36.basename(sourceFile, ext);
50097
+ const rel = path36.relative(dir, sourceFile);
50098
+ const relDir = path36.dirname(rel);
49594
50099
  const stripSrc = relDir.replace(/^src(\/|\\)/, "");
49595
50100
  const candidates = new Set;
49596
50101
  for (const tDir of ["tests", "test", "__tests__", "spec"]) {
49597
50102
  for (const suffix of ["", "_test", ".test", "_spec", ".spec"]) {
49598
- candidates.add(path34.join(dir, tDir, stripSrc, `${base}${suffix}${ext}`));
50103
+ candidates.add(path36.join(dir, tDir, stripSrc, `${base}${suffix}${ext}`));
49599
50104
  }
49600
50105
  }
49601
50106
  const existing = [];
49602
50107
  for (const c of candidates) {
49603
50108
  try {
49604
- fs14.accessSync(c);
50109
+ fs15.accessSync(c);
49605
50110
  existing.push(c);
49606
50111
  } catch {}
49607
50112
  }
@@ -49635,8 +50140,8 @@ var init_default_backend = __esm(() => {
49635
50140
  });
49636
50141
 
49637
50142
  // src/lang/backends/go.ts
49638
- import * as fs15 from "fs";
49639
- import * as path35 from "path";
50143
+ import * as fs16 from "fs";
50144
+ import * as path37 from "path";
49640
50145
  function extractImports(_sourceFile, source) {
49641
50146
  const out = new Set;
49642
50147
  IMPORT_REGEX_SINGLE.lastIndex = 0;
@@ -49662,7 +50167,7 @@ function extractImports(_sourceFile, source) {
49662
50167
  async function selectFramework(dir) {
49663
50168
  let content;
49664
50169
  try {
49665
- content = fs15.readFileSync(path35.join(dir, "go.mod"), "utf-8");
50170
+ content = fs16.readFileSync(path37.join(dir, "go.mod"), "utf-8");
49666
50171
  } catch {
49667
50172
  return null;
49668
50173
  }
@@ -49683,16 +50188,16 @@ async function selectFramework(dir) {
49683
50188
  async function selectEntryPoints(dir) {
49684
50189
  const points = [];
49685
50190
  try {
49686
- fs15.accessSync(path35.join(dir, "main.go"));
50191
+ fs16.accessSync(path37.join(dir, "main.go"));
49687
50192
  points.push("main.go");
49688
50193
  } catch {}
49689
50194
  try {
49690
- const cmdDir = path35.join(dir, "cmd");
49691
- const subdirs = fs15.readdirSync(cmdDir, { withFileTypes: true }).filter((d) => d.isDirectory());
50195
+ const cmdDir = path37.join(dir, "cmd");
50196
+ const subdirs = fs16.readdirSync(cmdDir, { withFileTypes: true }).filter((d) => d.isDirectory());
49692
50197
  for (const sub of subdirs) {
49693
- const main = path35.join("cmd", sub.name, "main.go");
50198
+ const main = path37.join("cmd", sub.name, "main.go");
49694
50199
  try {
49695
- fs15.accessSync(path35.join(dir, main));
50200
+ fs16.accessSync(path37.join(dir, main));
49696
50201
  points.push(main);
49697
50202
  } catch {}
49698
50203
  }
@@ -49722,8 +50227,8 @@ var init_go = __esm(() => {
49722
50227
  });
49723
50228
 
49724
50229
  // src/lang/backends/python.ts
49725
- import * as fs16 from "fs";
49726
- import * as path36 from "path";
50230
+ import * as fs17 from "fs";
50231
+ import * as path38 from "path";
49727
50232
  function parseImportTargets(rawTargets) {
49728
50233
  const cleaned = rawTargets.replace(/[()]/g, "").split(`
49729
50234
  `).map((line) => line.replace(/#.*$/, "").replace(/\\\s*$/, "")).join(" ");
@@ -49783,7 +50288,7 @@ async function selectFramework2(dir) {
49783
50288
  ];
49784
50289
  for (const candidate of ["pyproject.toml", "requirements.txt", "setup.py"]) {
49785
50290
  try {
49786
- const content = fs16.readFileSync(path36.join(dir, candidate), "utf-8");
50291
+ const content = fs17.readFileSync(path38.join(dir, candidate), "utf-8");
49787
50292
  const lower = content.toLowerCase();
49788
50293
  for (const [pkg, name] of candidates) {
49789
50294
  if (lower.includes(pkg)) {
@@ -49797,7 +50302,7 @@ async function selectFramework2(dir) {
49797
50302
  async function selectEntryPoints2(dir) {
49798
50303
  const points = new Set;
49799
50304
  try {
49800
- const content = fs16.readFileSync(path36.join(dir, "pyproject.toml"), "utf-8");
50305
+ const content = fs17.readFileSync(path38.join(dir, "pyproject.toml"), "utf-8");
49801
50306
  const scriptsBlock = content.match(/\[project\.scripts\][\s\S]*?(?=\n\[|$)/);
49802
50307
  if (scriptsBlock) {
49803
50308
  for (const line of scriptsBlock[0].split(`
@@ -49812,7 +50317,7 @@ async function selectEntryPoints2(dir) {
49812
50317
  } catch {}
49813
50318
  for (const name of ["manage.py", "main.py", "app.py", "__main__.py"]) {
49814
50319
  try {
49815
- fs16.accessSync(path36.join(dir, name));
50320
+ fs17.accessSync(path38.join(dir, name));
49816
50321
  points.add(name);
49817
50322
  } catch {}
49818
50323
  }
@@ -49840,15 +50345,15 @@ var init_python = __esm(() => {
49840
50345
  });
49841
50346
 
49842
50347
  // src/test-impact/analyzer.ts
49843
- import fs17 from "fs";
49844
- import path37 from "path";
50348
+ import fs18 from "fs";
50349
+ import path39 from "path";
49845
50350
  function normalizePath(p) {
49846
50351
  return p.replace(/\\/g, "/");
49847
50352
  }
49848
50353
  function isCacheStale(impactMap, generatedAtMs) {
49849
50354
  for (const sourcePath of Object.keys(impactMap)) {
49850
50355
  try {
49851
- const stat4 = fs17.statSync(sourcePath);
50356
+ const stat4 = fs18.statSync(sourcePath);
49852
50357
  if (stat4.mtimeMs > generatedAtMs) {
49853
50358
  return true;
49854
50359
  }
@@ -49862,15 +50367,15 @@ function resolveRelativeImport(fromDir, importPath) {
49862
50367
  if (!importPath.startsWith(".")) {
49863
50368
  return null;
49864
50369
  }
49865
- const resolved = path37.resolve(fromDir, importPath);
49866
- if (path37.extname(resolved)) {
49867
- if (fs17.existsSync(resolved) && fs17.statSync(resolved).isFile()) {
50370
+ const resolved = path39.resolve(fromDir, importPath);
50371
+ if (path39.extname(resolved)) {
50372
+ if (fs18.existsSync(resolved) && fs18.statSync(resolved).isFile()) {
49868
50373
  return normalizePath(resolved);
49869
50374
  }
49870
50375
  } else {
49871
50376
  for (const ext of EXTENSIONS_TO_TRY) {
49872
50377
  const withExt = resolved + ext;
49873
- if (fs17.existsSync(withExt) && fs17.statSync(withExt).isFile()) {
50378
+ if (fs18.existsSync(withExt) && fs18.statSync(withExt).isFile()) {
49874
50379
  return normalizePath(withExt);
49875
50380
  }
49876
50381
  }
@@ -49883,29 +50388,29 @@ function resolvePythonImport(fromDir, module) {
49883
50388
  const leadingDots = module.match(/^\.+/)?.[0].length ?? 0;
49884
50389
  let baseDir = fromDir;
49885
50390
  for (let i = 1;i < leadingDots; i++) {
49886
- baseDir = path37.dirname(baseDir);
50391
+ baseDir = path39.dirname(baseDir);
49887
50392
  }
49888
50393
  const rest = module.slice(leadingDots);
49889
50394
  if (rest.length === 0) {
49890
- const initPath = path37.join(baseDir, "__init__.py");
49891
- if (fs17.existsSync(initPath) && fs17.statSync(initPath).isFile()) {
50395
+ const initPath = path39.join(baseDir, "__init__.py");
50396
+ if (fs18.existsSync(initPath) && fs18.statSync(initPath).isFile()) {
49892
50397
  return normalizePath(initPath);
49893
50398
  }
49894
50399
  return null;
49895
50400
  }
49896
- const subpath = rest.replace(/\./g, path37.sep);
50401
+ const subpath = rest.replace(/\./g, path39.sep);
49897
50402
  const candidates = [
49898
- `${path37.join(baseDir, subpath)}.py`,
49899
- path37.join(baseDir, subpath, "__init__.py")
50403
+ `${path39.join(baseDir, subpath)}.py`,
50404
+ path39.join(baseDir, subpath, "__init__.py")
49900
50405
  ];
49901
50406
  for (const c of candidates) {
49902
- if (fs17.existsSync(c) && fs17.statSync(c).isFile())
50407
+ if (fs18.existsSync(c) && fs18.statSync(c).isFile())
49903
50408
  return normalizePath(c);
49904
50409
  }
49905
50410
  return null;
49906
50411
  }
49907
50412
  function findGoModule(fromDir) {
49908
- const resolved = path37.resolve(fromDir);
50413
+ const resolved = path39.resolve(fromDir);
49909
50414
  let cur = resolved;
49910
50415
  const walked = [];
49911
50416
  for (let i = 0;i < 16; i++) {
@@ -49917,8 +50422,8 @@ function findGoModule(fromDir) {
49917
50422
  }
49918
50423
  walked.push(cur);
49919
50424
  try {
49920
- const goMod = path37.join(cur, "go.mod");
49921
- const content = fs17.readFileSync(goMod, "utf-8");
50425
+ const goMod = path39.join(cur, "go.mod");
50426
+ const content = fs18.readFileSync(goMod, "utf-8");
49922
50427
  const moduleMatch = content.match(/^\s*module\s+"?([^"\s/]+(?:\/[^"\s]+)*)"?/m);
49923
50428
  if (moduleMatch) {
49924
50429
  const result = { moduleRoot: cur, modulePath: moduleMatch[1] };
@@ -49928,10 +50433,10 @@ function findGoModule(fromDir) {
49928
50433
  }
49929
50434
  } catch {}
49930
50435
  try {
49931
- fs17.accessSync(path37.join(cur, ".git"));
50436
+ fs18.accessSync(path39.join(cur, ".git"));
49932
50437
  break;
49933
50438
  } catch {}
49934
- const parent = path37.dirname(cur);
50439
+ const parent = path39.dirname(cur);
49935
50440
  if (parent === cur)
49936
50441
  break;
49937
50442
  cur = parent;
@@ -49943,20 +50448,20 @@ function findGoModule(fromDir) {
49943
50448
  function resolveGoImport(fromDir, importPath) {
49944
50449
  let dir = null;
49945
50450
  if (importPath.startsWith(".")) {
49946
- dir = path37.resolve(fromDir, importPath);
50451
+ dir = path39.resolve(fromDir, importPath);
49947
50452
  } else {
49948
50453
  const mod = findGoModule(fromDir);
49949
50454
  if (mod && (importPath === mod.modulePath || importPath.startsWith(`${mod.modulePath}/`))) {
49950
50455
  const subpath = importPath.slice(mod.modulePath.length);
49951
- dir = path37.join(mod.moduleRoot, subpath);
50456
+ dir = path39.join(mod.moduleRoot, subpath);
49952
50457
  }
49953
50458
  }
49954
50459
  if (dir === null)
49955
50460
  return [];
49956
- if (!fs17.existsSync(dir) || !fs17.statSync(dir).isDirectory())
50461
+ if (!fs18.existsSync(dir) || !fs18.statSync(dir).isDirectory())
49957
50462
  return [];
49958
50463
  try {
49959
- return fs17.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath(path37.join(dir, f)));
50464
+ return fs18.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath(path39.join(dir, f)));
49960
50465
  } catch {
49961
50466
  return [];
49962
50467
  }
@@ -49976,13 +50481,13 @@ function findTestFilesSync(cwd) {
49976
50481
  function walk(dir, visitedInodes) {
49977
50482
  let entries;
49978
50483
  try {
49979
- entries = fs17.readdirSync(dir, { withFileTypes: true });
50484
+ entries = fs18.readdirSync(dir, { withFileTypes: true });
49980
50485
  } catch {
49981
50486
  return;
49982
50487
  }
49983
50488
  let dirInode;
49984
50489
  try {
49985
- dirInode = fs17.statSync(dir).ino;
50490
+ dirInode = fs18.statSync(dir).ino;
49986
50491
  } catch {
49987
50492
  return;
49988
50493
  }
@@ -49995,15 +50500,15 @@ function findTestFilesSync(cwd) {
49995
50500
  for (const entry of entries) {
49996
50501
  if (entry.isDirectory()) {
49997
50502
  if (!skipDirs.has(entry.name)) {
49998
- walk(path37.join(dir, entry.name), visitedInodes);
50503
+ walk(path39.join(dir, entry.name), visitedInodes);
49999
50504
  }
50000
50505
  } else if (entry.isFile()) {
50001
50506
  const name = entry.name;
50002
50507
  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");
50508
+ const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${path39.sep}tests${path39.sep}`) && name.endsWith(".py");
50004
50509
  const isGoTest = /.+_test\.go$/.test(name);
50005
50510
  if (isTsTest || isPyTest || isGoTest) {
50006
- testFiles.push(normalizePath(path37.join(dir, entry.name)));
50511
+ testFiles.push(normalizePath(path39.join(dir, entry.name)));
50007
50512
  }
50008
50513
  }
50009
50514
  }
@@ -50028,8 +50533,8 @@ function extractImports3(content) {
50028
50533
  ];
50029
50534
  }
50030
50535
  function addImpactEdgesForTestFile(testFile, content, impactMap) {
50031
- const ext = path37.extname(testFile).toLowerCase();
50032
- const testDir = path37.dirname(testFile);
50536
+ const ext = path39.extname(testFile).toLowerCase();
50537
+ const testDir = path39.dirname(testFile);
50033
50538
  function addEdge(source) {
50034
50539
  if (!impactMap[source])
50035
50540
  impactMap[source] = [];
@@ -50071,7 +50576,7 @@ async function buildImpactMapInternal(cwd) {
50071
50576
  for (const testFile of testFiles) {
50072
50577
  let content;
50073
50578
  try {
50074
- content = fs17.readFileSync(testFile, "utf-8");
50579
+ content = fs18.readFileSync(testFile, "utf-8");
50075
50580
  } catch {
50076
50581
  continue;
50077
50582
  }
@@ -50088,10 +50593,10 @@ async function buildImpactMap(cwd) {
50088
50593
  return impactMap;
50089
50594
  }
50090
50595
  async function loadImpactMap(cwd, options) {
50091
- const cachePath = path37.join(cwd, ".swarm", "cache", "impact-map.json");
50092
- if (fs17.existsSync(cachePath)) {
50596
+ const cachePath = path39.join(cwd, ".swarm", "cache", "impact-map.json");
50597
+ if (fs18.existsSync(cachePath)) {
50093
50598
  try {
50094
- const content = fs17.readFileSync(cachePath, "utf-8");
50599
+ const content = fs18.readFileSync(cachePath, "utf-8");
50095
50600
  const data = JSON.parse(content);
50096
50601
  if (data.map !== null && typeof data.map === "object" && !Array.isArray(data.map)) {
50097
50602
  const map3 = data.map;
@@ -50121,21 +50626,21 @@ async function loadImpactMap(cwd, options) {
50121
50626
  return _internals23.buildImpactMap(cwd);
50122
50627
  }
50123
50628
  async function saveImpactMap(cwd, impactMap) {
50124
- if (!path37.isAbsolute(cwd)) {
50629
+ if (!path39.isAbsolute(cwd)) {
50125
50630
  throw new Error(`saveImpactMap requires an absolute project root path, got: "${cwd}"`);
50126
50631
  }
50127
50632
  _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 });
50633
+ const cacheDir2 = path39.join(cwd, ".swarm", "cache");
50634
+ const cachePath = path39.join(cacheDir2, "impact-map.json");
50635
+ if (!fs18.existsSync(cacheDir2)) {
50636
+ fs18.mkdirSync(cacheDir2, { recursive: true });
50132
50637
  }
50133
50638
  const data = {
50134
50639
  generatedAt: new Date().toISOString(),
50135
50640
  fileCount: Object.keys(impactMap).length,
50136
50641
  map: impactMap
50137
50642
  };
50138
- fs17.writeFileSync(cachePath, JSON.stringify(data, null, 2), "utf-8");
50643
+ fs18.writeFileSync(cachePath, JSON.stringify(data, null, 2), "utf-8");
50139
50644
  }
50140
50645
  async function analyzeImpact(changedFiles, cwd, budget) {
50141
50646
  if (!Array.isArray(changedFiles)) {
@@ -50158,7 +50663,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
50158
50663
  budgetExceeded = true;
50159
50664
  break;
50160
50665
  }
50161
- const normalizedChanged = normalizePath(path37.resolve(changedFile));
50666
+ const normalizedChanged = normalizePath(path39.resolve(changedFile));
50162
50667
  const tests = impactMap[normalizedChanged];
50163
50668
  if (tests && tests.length > 0) {
50164
50669
  for (const test of tests) {
@@ -50450,16 +50955,16 @@ function detectFlakyTests(allHistory) {
50450
50955
  var FLAKY_THRESHOLD = 0.3, MIN_RUNS_FOR_QUARANTINE = 5, MAX_HISTORY_RUNS = 20;
50451
50956
 
50452
50957
  // src/test-impact/history-store.ts
50453
- import fs18 from "fs";
50454
- import path38 from "path";
50958
+ import fs19 from "fs";
50959
+ import path40 from "path";
50455
50960
  function getHistoryPath(workingDir) {
50456
50961
  if (!workingDir) {
50457
50962
  throw new Error("getHistoryPath requires a working directory \u2014 project root must be provided by the caller");
50458
50963
  }
50459
- if (!path38.isAbsolute(workingDir)) {
50964
+ if (!path40.isAbsolute(workingDir)) {
50460
50965
  throw new Error(`getHistoryPath requires an absolute project root path, got: "${workingDir}"`);
50461
50966
  }
50462
- return path38.join(workingDir, ".swarm", "cache", "test-history.jsonl");
50967
+ return path40.join(workingDir, ".swarm", "cache", "test-history.jsonl");
50463
50968
  }
50464
50969
  function sanitizeErrorMessage(errorMessage) {
50465
50970
  if (errorMessage === undefined) {
@@ -50546,10 +51051,10 @@ function batchAppendTestRuns(records, workingDir) {
50546
51051
  }
50547
51052
  }
50548
51053
  const historyPath = getHistoryPath(workingDir);
50549
- const historyDir = path38.dirname(historyPath);
51054
+ const historyDir = path40.dirname(historyPath);
50550
51055
  _internals24.validateProjectRoot(workingDir);
50551
- if (!fs18.existsSync(historyDir)) {
50552
- fs18.mkdirSync(historyDir, { recursive: true });
51056
+ if (!fs19.existsSync(historyDir)) {
51057
+ fs19.mkdirSync(historyDir, { recursive: true });
50553
51058
  }
50554
51059
  const existingRecords = readAllRecords(historyPath);
50555
51060
  const sanitizedRecords = records.map((record3) => ({
@@ -50582,24 +51087,24 @@ function batchAppendTestRuns(records, workingDir) {
50582
51087
  `)}
50583
51088
  `;
50584
51089
  const tempPath = `${historyPath}.tmp`;
50585
- fs18.writeFileSync(tempPath, content, "utf-8");
50586
- fs18.renameSync(tempPath, historyPath);
51090
+ fs19.writeFileSync(tempPath, content, "utf-8");
51091
+ fs19.renameSync(tempPath, historyPath);
50587
51092
  } catch (err) {
50588
51093
  try {
50589
51094
  const tempPath = `${historyPath}.tmp`;
50590
- if (fs18.existsSync(tempPath)) {
50591
- fs18.unlinkSync(tempPath);
51095
+ if (fs19.existsSync(tempPath)) {
51096
+ fs19.unlinkSync(tempPath);
50592
51097
  }
50593
51098
  } catch {}
50594
51099
  throw new Error(`Failed to write test history: ${err instanceof Error ? err.message : String(err)}`);
50595
51100
  }
50596
51101
  }
50597
51102
  function readAllRecords(historyPath) {
50598
- if (!fs18.existsSync(historyPath)) {
51103
+ if (!fs19.existsSync(historyPath)) {
50599
51104
  return [];
50600
51105
  }
50601
51106
  try {
50602
- const content = fs18.readFileSync(historyPath, "utf-8");
51107
+ const content = fs19.readFileSync(historyPath, "utf-8");
50603
51108
  const lines = content.split(`
50604
51109
  `);
50605
51110
  const records = [];
@@ -50641,8 +51146,8 @@ var init_history_store = __esm(() => {
50641
51146
  });
50642
51147
 
50643
51148
  // src/tools/resolve-working-directory.ts
50644
- import * as fs19 from "fs";
50645
- import * as path39 from "path";
51149
+ import * as fs20 from "fs";
51150
+ import * as path41 from "path";
50646
51151
  function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
50647
51152
  if (workingDirectory == null || workingDirectory === "") {
50648
51153
  return { success: true, directory: fallbackDirectory };
@@ -50662,18 +51167,18 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
50662
51167
  };
50663
51168
  }
50664
51169
  }
50665
- const normalizedDir = path39.normalize(workingDirectory);
50666
- const pathParts = normalizedDir.split(path39.sep);
51170
+ const normalizedDir = path41.normalize(workingDirectory);
51171
+ const pathParts = normalizedDir.split(path41.sep);
50667
51172
  if (pathParts.includes("..")) {
50668
51173
  return {
50669
51174
  success: false,
50670
51175
  message: "Invalid working_directory: path traversal sequences (..) are not allowed"
50671
51176
  };
50672
51177
  }
50673
- const resolvedDir = path39.resolve(normalizedDir);
51178
+ const resolvedDir = path41.resolve(normalizedDir);
50674
51179
  let statResult;
50675
51180
  try {
50676
- statResult = fs19.statSync(resolvedDir);
51181
+ statResult = fs20.statSync(resolvedDir);
50677
51182
  } catch {
50678
51183
  return {
50679
51184
  success: false,
@@ -50686,17 +51191,17 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
50686
51191
  message: `Invalid working_directory: path "${resolvedDir}" is not a directory`
50687
51192
  };
50688
51193
  }
50689
- const resolvedFallback = path39.resolve(fallbackDirectory);
51194
+ const resolvedFallback = path41.resolve(fallbackDirectory);
50690
51195
  let fallbackExists = false;
50691
51196
  try {
50692
- fs19.statSync(resolvedFallback);
51197
+ fs20.statSync(resolvedFallback);
50693
51198
  fallbackExists = true;
50694
51199
  } catch {
50695
51200
  fallbackExists = false;
50696
51201
  }
50697
51202
  if (workingDirectory != null && workingDirectory !== "") {
50698
51203
  if (fallbackExists) {
50699
- const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path39.sep);
51204
+ const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path41.sep);
50700
51205
  if (isSubdirectory) {
50701
51206
  return {
50702
51207
  success: false,
@@ -50750,11 +51255,11 @@ var init_registry_backend = __esm(() => {
50750
51255
  });
50751
51256
 
50752
51257
  // src/lang/backends/typescript.ts
50753
- import * as fs20 from "fs";
50754
- import * as path40 from "path";
51258
+ import * as fs21 from "fs";
51259
+ import * as path42 from "path";
50755
51260
  function readPackageJsonRaw(dir) {
50756
51261
  try {
50757
- const content = fs20.readFileSync(path40.join(dir, "package.json"), "utf-8");
51262
+ const content = fs21.readFileSync(path42.join(dir, "package.json"), "utf-8");
50758
51263
  return JSON.parse(content);
50759
51264
  } catch {
50760
51265
  return null;
@@ -50973,11 +51478,11 @@ __export(exports_dispatch, {
50973
51478
  clearDispatchCache: () => clearDispatchCache,
50974
51479
  _internals: () => _internals26
50975
51480
  });
50976
- import * as fs21 from "fs";
50977
- import * as path41 from "path";
51481
+ import * as fs22 from "fs";
51482
+ import * as path43 from "path";
50978
51483
  function safeReaddirSet(dir) {
50979
51484
  try {
50980
- return new Set(fs21.readdirSync(dir));
51485
+ return new Set(fs22.readdirSync(dir));
50981
51486
  } catch {
50982
51487
  return new Set;
50983
51488
  }
@@ -50991,14 +51496,14 @@ function manifestHash(dir) {
50991
51496
  if (!entries.has(name))
50992
51497
  continue;
50993
51498
  try {
50994
- const stat4 = fs21.statSync(path41.join(dir, name));
51499
+ const stat4 = fs22.statSync(path43.join(dir, name));
50995
51500
  parts.push(`${name}:${stat4.size}:${stat4.mtimeMs}:${stat4.ino}`);
50996
51501
  } catch {}
50997
51502
  }
50998
51503
  return parts.join("|");
50999
51504
  }
51000
51505
  function findManifestRoot(start) {
51001
- const resolved = path41.resolve(start);
51506
+ const resolved = path43.resolve(start);
51002
51507
  const cached3 = manifestRootCache.get(resolved);
51003
51508
  if (cached3 !== undefined)
51004
51509
  return cached3;
@@ -51017,7 +51522,7 @@ function findManifestRoot(start) {
51017
51522
  return cur;
51018
51523
  }
51019
51524
  }
51020
- const parent = path41.dirname(cur);
51525
+ const parent = path43.dirname(cur);
51021
51526
  if (parent === cur)
51022
51527
  break;
51023
51528
  cur = parent;
@@ -51126,14 +51631,14 @@ var init_dispatch = __esm(() => {
51126
51631
  });
51127
51632
 
51128
51633
  // src/tools/test-runner.ts
51129
- import * as fs22 from "fs";
51130
- import * as path42 from "path";
51634
+ import * as fs23 from "fs";
51635
+ import * as path44 from "path";
51131
51636
  async function estimateFanOut(sourceFiles, cwd) {
51132
51637
  try {
51133
51638
  const impactMap = await loadImpactMap(cwd, { skipRebuild: true });
51134
51639
  const uniqueTestFiles = new Set;
51135
51640
  for (const sourceFile of sourceFiles) {
51136
- const resolvedPath = path42.resolve(cwd, sourceFile);
51641
+ const resolvedPath = path44.resolve(cwd, sourceFile);
51137
51642
  const normalizedPath = resolvedPath.replace(/\\/g, "/");
51138
51643
  const testFiles = impactMap[normalizedPath];
51139
51644
  if (testFiles) {
@@ -51211,19 +51716,19 @@ function hasDevDependency(devDeps, ...patterns) {
51211
51716
  return hasPackageJsonDependency(devDeps, ...patterns);
51212
51717
  }
51213
51718
  function detectGoTest(cwd) {
51214
- return fs22.existsSync(path42.join(cwd, "go.mod")) && isCommandAvailable("go");
51719
+ return fs23.existsSync(path44.join(cwd, "go.mod")) && isCommandAvailable("go");
51215
51720
  }
51216
51721
  function detectJavaMaven(cwd) {
51217
- return fs22.existsSync(path42.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
51722
+ return fs23.existsSync(path44.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
51218
51723
  }
51219
51724
  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"));
51725
+ const hasBuildFile = fs23.existsSync(path44.join(cwd, "build.gradle")) || fs23.existsSync(path44.join(cwd, "build.gradle.kts"));
51726
+ const hasGradlew = fs23.existsSync(path44.join(cwd, "gradlew")) || fs23.existsSync(path44.join(cwd, "gradlew.bat"));
51222
51727
  return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
51223
51728
  }
51224
51729
  function detectDotnetTest(cwd) {
51225
51730
  try {
51226
- const files = fs22.readdirSync(cwd);
51731
+ const files = fs23.readdirSync(cwd);
51227
51732
  const hasCsproj = files.some((f) => f.endsWith(".csproj"));
51228
51733
  return hasCsproj && isCommandAvailable("dotnet");
51229
51734
  } catch {
@@ -51231,25 +51736,25 @@ function detectDotnetTest(cwd) {
51231
51736
  }
51232
51737
  }
51233
51738
  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"));
51739
+ const hasSource = fs23.existsSync(path44.join(cwd, "CMakeLists.txt"));
51740
+ const hasBuildCache = fs23.existsSync(path44.join(cwd, "CMakeCache.txt")) || fs23.existsSync(path44.join(cwd, "build", "CMakeCache.txt"));
51236
51741
  return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
51237
51742
  }
51238
51743
  function detectSwiftTest(cwd) {
51239
- return fs22.existsSync(path42.join(cwd, "Package.swift")) && isCommandAvailable("swift");
51744
+ return fs23.existsSync(path44.join(cwd, "Package.swift")) && isCommandAvailable("swift");
51240
51745
  }
51241
51746
  function detectDartTest(cwd) {
51242
- return fs22.existsSync(path42.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
51747
+ return fs23.existsSync(path44.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
51243
51748
  }
51244
51749
  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"));
51750
+ const hasRSpecFile = fs23.existsSync(path44.join(cwd, ".rspec"));
51751
+ const hasGemfile = fs23.existsSync(path44.join(cwd, "Gemfile"));
51752
+ const hasSpecDir = fs23.existsSync(path44.join(cwd, "spec"));
51248
51753
  const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
51249
51754
  return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
51250
51755
  }
51251
51756
  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");
51757
+ return fs23.existsSync(path44.join(cwd, "test")) && (fs23.existsSync(path44.join(cwd, "Gemfile")) || fs23.existsSync(path44.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
51253
51758
  }
51254
51759
  async function detectTestFrameworkViaDispatch(cwd) {
51255
51760
  try {
@@ -51311,9 +51816,9 @@ async function parseTestOutputViaDispatch(framework, output, baseDir) {
51311
51816
  async function detectTestFramework(cwd) {
51312
51817
  const baseDir = cwd;
51313
51818
  try {
51314
- const packageJsonPath = path42.join(baseDir, "package.json");
51315
- if (fs22.existsSync(packageJsonPath)) {
51316
- const content = fs22.readFileSync(packageJsonPath, "utf-8");
51819
+ const packageJsonPath = path44.join(baseDir, "package.json");
51820
+ if (fs23.existsSync(packageJsonPath)) {
51821
+ const content = fs23.readFileSync(packageJsonPath, "utf-8");
51317
51822
  const pkg = JSON.parse(content);
51318
51823
  const _deps = pkg.dependencies || {};
51319
51824
  const devDeps = pkg.devDependencies || {};
@@ -51332,38 +51837,38 @@ async function detectTestFramework(cwd) {
51332
51837
  return "jest";
51333
51838
  if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
51334
51839
  return "mocha";
51335
- if (fs22.existsSync(path42.join(baseDir, "bun.lockb")) || fs22.existsSync(path42.join(baseDir, "bun.lock"))) {
51840
+ if (fs23.existsSync(path44.join(baseDir, "bun.lockb")) || fs23.existsSync(path44.join(baseDir, "bun.lock"))) {
51336
51841
  if (scripts.test?.includes("bun"))
51337
51842
  return "bun";
51338
51843
  }
51339
51844
  }
51340
51845
  } catch {}
51341
51846
  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");
51847
+ const pyprojectTomlPath = path44.join(baseDir, "pyproject.toml");
51848
+ const setupCfgPath = path44.join(baseDir, "setup.cfg");
51849
+ const requirementsTxtPath = path44.join(baseDir, "requirements.txt");
51850
+ if (fs23.existsSync(pyprojectTomlPath)) {
51851
+ const content = fs23.readFileSync(pyprojectTomlPath, "utf-8");
51347
51852
  if (content.includes("[tool.pytest"))
51348
51853
  return "pytest";
51349
51854
  if (content.includes("pytest"))
51350
51855
  return "pytest";
51351
51856
  }
51352
- if (fs22.existsSync(setupCfgPath)) {
51353
- const content = fs22.readFileSync(setupCfgPath, "utf-8");
51857
+ if (fs23.existsSync(setupCfgPath)) {
51858
+ const content = fs23.readFileSync(setupCfgPath, "utf-8");
51354
51859
  if (content.includes("[pytest]"))
51355
51860
  return "pytest";
51356
51861
  }
51357
- if (fs22.existsSync(requirementsTxtPath)) {
51358
- const content = fs22.readFileSync(requirementsTxtPath, "utf-8");
51862
+ if (fs23.existsSync(requirementsTxtPath)) {
51863
+ const content = fs23.readFileSync(requirementsTxtPath, "utf-8");
51359
51864
  if (content.includes("pytest"))
51360
51865
  return "pytest";
51361
51866
  }
51362
51867
  } catch {}
51363
51868
  try {
51364
- const cargoTomlPath = path42.join(baseDir, "Cargo.toml");
51365
- if (fs22.existsSync(cargoTomlPath)) {
51366
- const content = fs22.readFileSync(cargoTomlPath, "utf-8");
51869
+ const cargoTomlPath = path44.join(baseDir, "Cargo.toml");
51870
+ if (fs23.existsSync(cargoTomlPath)) {
51871
+ const content = fs23.readFileSync(cargoTomlPath, "utf-8");
51367
51872
  if (content.includes("[dev-dependencies]")) {
51368
51873
  if (content.includes("tokio") || content.includes("mockall") || content.includes("pretty_assertions")) {
51369
51874
  return "cargo";
@@ -51372,10 +51877,10 @@ async function detectTestFramework(cwd) {
51372
51877
  }
51373
51878
  } catch {}
51374
51879
  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)) {
51880
+ const pesterConfigPath = path44.join(baseDir, "pester.config.ps1");
51881
+ const pesterConfigJsonPath = path44.join(baseDir, "pester.config.ps1.json");
51882
+ const pesterPs1Path = path44.join(baseDir, "tests.ps1");
51883
+ if (fs23.existsSync(pesterConfigPath) || fs23.existsSync(pesterConfigJsonPath) || fs23.existsSync(pesterPs1Path)) {
51379
51884
  return "pester";
51380
51885
  }
51381
51886
  } catch {}
@@ -51403,12 +51908,12 @@ function isTestDirectoryPath(normalizedPath) {
51403
51908
  return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
51404
51909
  }
51405
51910
  function resolveWorkspacePath(file3, workingDir) {
51406
- return path42.isAbsolute(file3) ? path42.resolve(file3) : path42.resolve(workingDir, file3);
51911
+ return path44.isAbsolute(file3) ? path44.resolve(file3) : path44.resolve(workingDir, file3);
51407
51912
  }
51408
51913
  function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
51409
51914
  if (!preferRelative)
51410
51915
  return absolutePath;
51411
- return path42.relative(workingDir, absolutePath);
51916
+ return path44.relative(workingDir, absolutePath);
51412
51917
  }
51413
51918
  function dedupePush(target, value) {
51414
51919
  if (!target.includes(value)) {
@@ -51445,18 +51950,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
51445
51950
  }
51446
51951
  }
51447
51952
  function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
51448
- const relativeDir = path42.dirname(relativePath);
51953
+ const relativeDir = path44.dirname(relativePath);
51449
51954
  const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
51450
51955
  const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
51451
- const rootDir = path42.join(workingDir, dirName);
51452
- return nestedRelativeDir ? [rootDir, path42.join(rootDir, nestedRelativeDir)] : [rootDir];
51956
+ const rootDir = path44.join(workingDir, dirName);
51957
+ return nestedRelativeDir ? [rootDir, path44.join(rootDir, nestedRelativeDir)] : [rootDir];
51453
51958
  });
51454
51959
  const normalizedRelativePath = relativePath.replace(/\\/g, "/");
51455
51960
  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))));
51961
+ directories.push(path44.join(workingDir, "src/test/java", path44.dirname(normalizedRelativePath.slice("src/main/java/".length))));
51457
51962
  }
51458
51963
  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))));
51964
+ directories.push(path44.join(workingDir, "src/test/kotlin", path44.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
51460
51965
  }
51461
51966
  return [...new Set(directories)];
51462
51967
  }
@@ -51464,19 +51969,19 @@ function hasCompoundTestExtension(filename) {
51464
51969
  const lower = filename.toLowerCase();
51465
51970
  return COMPOUND_TEST_EXTENSIONS.some((ext) => lower.endsWith(ext));
51466
51971
  }
51467
- function isLanguageSpecificTestFile(basename6) {
51468
- const lower = basename6.toLowerCase();
51972
+ function isLanguageSpecificTestFile(basename7) {
51973
+ const lower = basename7.toLowerCase();
51469
51974
  if (lower.endsWith("_test.go"))
51470
51975
  return true;
51471
51976
  if (lower.endsWith(".py") && (lower.startsWith("test_") || lower.endsWith("_test.py")))
51472
51977
  return true;
51473
51978
  if (lower.endsWith("_spec.rb"))
51474
51979
  return true;
51475
- if (lower.endsWith(".java") && (/^Test[A-Z]/.test(basename6) || basename6.endsWith("Test.java") || basename6.endsWith("Tests.java") || lower.endsWith("it.java")))
51980
+ if (lower.endsWith(".java") && (/^Test[A-Z]/.test(basename7) || basename7.endsWith("Test.java") || basename7.endsWith("Tests.java") || lower.endsWith("it.java")))
51476
51981
  return true;
51477
51982
  if (lower.endsWith(".cs") && (lower.endsWith("test.cs") || lower.endsWith("tests.cs")))
51478
51983
  return true;
51479
- if (lower.endsWith(".kt") && (/^Test[A-Z]/.test(basename6) || lower.endsWith("test.kt") || lower.endsWith("tests.kt")))
51984
+ if (lower.endsWith(".kt") && (/^Test[A-Z]/.test(basename7) || lower.endsWith("test.kt") || lower.endsWith("tests.kt")))
51480
51985
  return true;
51481
51986
  if (lower.endsWith(".tests.ps1"))
51482
51987
  return true;
@@ -51484,23 +51989,23 @@ function isLanguageSpecificTestFile(basename6) {
51484
51989
  }
51485
51990
  function isConventionTestFilePath(filePath) {
51486
51991
  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);
51992
+ const basename7 = path44.basename(filePath);
51993
+ return hasCompoundTestExtension(basename7) || basename7.includes(".spec.") || basename7.includes(".test.") || isLanguageSpecificTestFile(basename7) || isTestDirectoryPath(normalizedPath);
51489
51994
  }
51490
51995
  function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
51491
51996
  const testFiles = [];
51492
51997
  for (const file3 of sourceFiles) {
51493
51998
  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);
51999
+ const relativeFile = path44.relative(workingDir, absoluteFile);
52000
+ const basename7 = path44.basename(absoluteFile);
52001
+ const dirname21 = path44.dirname(absoluteFile);
52002
+ const preferRelativeOutput = !path44.isAbsolute(file3);
51498
52003
  if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file3)) {
51499
52004
  dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
51500
52005
  continue;
51501
52006
  }
51502
- const nameWithoutExt = basename6.replace(/\.[^.]+$/, "");
51503
- const ext = path42.extname(basename6);
52007
+ const nameWithoutExt = basename7.replace(/\.[^.]+$/, "");
52008
+ const ext = path44.extname(basename7);
51504
52009
  const genericTestNames = [
51505
52010
  `${nameWithoutExt}.spec${ext}`,
51506
52011
  `${nameWithoutExt}.test${ext}`
@@ -51509,20 +52014,20 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
51509
52014
  const colocatedCandidates = [
51510
52015
  ...genericTestNames,
51511
52016
  ...languageSpecificTestNames
51512
- ].map((candidateName) => path42.join(dirname20, candidateName));
52017
+ ].map((candidateName) => path44.join(dirname21, candidateName));
51513
52018
  const testDirectoryNames = [
51514
- basename6,
52019
+ basename7,
51515
52020
  ...genericTestNames,
51516
52021
  ...languageSpecificTestNames
51517
52022
  ];
51518
52023
  const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
51519
52024
  const possibleTestFiles = [
51520
52025
  ...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)))
52026
+ ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path44.join(dirname21, dirName, candidateName))),
52027
+ ...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path44.join(candidateDir, candidateName)))
51523
52028
  ];
51524
52029
  for (const testFile of possibleTestFiles) {
51525
- if (fs22.existsSync(testFile)) {
52030
+ if (fs23.existsSync(testFile)) {
51526
52031
  dedupePush(testFiles, toWorkspaceOutputPath(testFile, workingDir, preferRelativeOutput));
51527
52032
  }
51528
52033
  }
@@ -51539,8 +52044,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
51539
52044
  for (const testFile of candidateTestFiles) {
51540
52045
  try {
51541
52046
  const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
51542
- const content = fs22.readFileSync(absoluteTestFile, "utf-8");
51543
- const testDir = path42.dirname(absoluteTestFile);
52047
+ const content = fs23.readFileSync(absoluteTestFile, "utf-8");
52048
+ const testDir = path44.dirname(absoluteTestFile);
51544
52049
  const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
51545
52050
  let match;
51546
52051
  match = importRegex.exec(content);
@@ -51548,8 +52053,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
51548
52053
  const importPath = match[1];
51549
52054
  let resolvedImport;
51550
52055
  if (importPath.startsWith(".")) {
51551
- resolvedImport = path42.resolve(testDir, importPath);
51552
- const existingExt = path42.extname(resolvedImport);
52056
+ resolvedImport = path44.resolve(testDir, importPath);
52057
+ const existingExt = path44.extname(resolvedImport);
51553
52058
  if (!existingExt) {
51554
52059
  for (const extToTry of [
51555
52060
  ".ts",
@@ -51560,7 +52065,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
51560
52065
  ".cjs"
51561
52066
  ]) {
51562
52067
  const withExt = resolvedImport + extToTry;
51563
- if (absoluteSourceFiles.includes(withExt) || fs22.existsSync(withExt)) {
52068
+ if (absoluteSourceFiles.includes(withExt) || fs23.existsSync(withExt)) {
51564
52069
  resolvedImport = withExt;
51565
52070
  break;
51566
52071
  }
@@ -51569,12 +52074,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
51569
52074
  } else {
51570
52075
  continue;
51571
52076
  }
51572
- const importBasename = path42.basename(resolvedImport, path42.extname(resolvedImport));
51573
- const importDir = path42.dirname(resolvedImport);
52077
+ const importBasename = path44.basename(resolvedImport, path44.extname(resolvedImport));
52078
+ const importDir = path44.dirname(resolvedImport);
51574
52079
  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");
52080
+ const sourceDir = path44.dirname(sourceFile);
52081
+ const sourceBasename = path44.basename(sourceFile, path44.extname(sourceFile));
52082
+ 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
52083
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
51579
52084
  dedupePush(testFiles, testFile);
51580
52085
  break;
@@ -51587,8 +52092,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
51587
52092
  while (match !== null) {
51588
52093
  const importPath = match[1];
51589
52094
  if (importPath.startsWith(".")) {
51590
- let resolvedImport = path42.resolve(testDir, importPath);
51591
- const existingExt = path42.extname(resolvedImport);
52095
+ let resolvedImport = path44.resolve(testDir, importPath);
52096
+ const existingExt = path44.extname(resolvedImport);
51592
52097
  if (!existingExt) {
51593
52098
  for (const extToTry of [
51594
52099
  ".ts",
@@ -51599,18 +52104,18 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
51599
52104
  ".cjs"
51600
52105
  ]) {
51601
52106
  const withExt = resolvedImport + extToTry;
51602
- if (absoluteSourceFiles.includes(withExt) || fs22.existsSync(withExt)) {
52107
+ if (absoluteSourceFiles.includes(withExt) || fs23.existsSync(withExt)) {
51603
52108
  resolvedImport = withExt;
51604
52109
  break;
51605
52110
  }
51606
52111
  }
51607
52112
  }
51608
- const importDir = path42.dirname(resolvedImport);
51609
- const importBasename = path42.basename(resolvedImport, path42.extname(resolvedImport));
52113
+ const importDir = path44.dirname(resolvedImport);
52114
+ const importBasename = path44.basename(resolvedImport, path44.extname(resolvedImport));
51610
52115
  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");
52116
+ const sourceDir = path44.dirname(sourceFile);
52117
+ const sourceBasename = path44.basename(sourceFile, path44.extname(sourceFile));
52118
+ 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
52119
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
51615
52120
  dedupePush(testFiles, testFile);
51616
52121
  break;
@@ -51720,8 +52225,8 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
51720
52225
  return ["mvn", "test"];
51721
52226
  case "gradle": {
51722
52227
  const isWindows = process.platform === "win32";
51723
- const hasGradlewBat = fs22.existsSync(path42.join(baseDir, "gradlew.bat"));
51724
- const hasGradlew = fs22.existsSync(path42.join(baseDir, "gradlew"));
52228
+ const hasGradlewBat = fs23.existsSync(path44.join(baseDir, "gradlew.bat"));
52229
+ const hasGradlew = fs23.existsSync(path44.join(baseDir, "gradlew"));
51725
52230
  if (hasGradlewBat && isWindows)
51726
52231
  return ["gradlew.bat", "test"];
51727
52232
  if (hasGradlew)
@@ -51738,7 +52243,7 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
51738
52243
  "cmake-build-release",
51739
52244
  "out"
51740
52245
  ];
51741
- const actualBuildDir = buildDirCandidates.find((d) => fs22.existsSync(path42.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
52246
+ const actualBuildDir = buildDirCandidates.find((d) => fs23.existsSync(path44.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
51742
52247
  return ["ctest", "--test-dir", actualBuildDir];
51743
52248
  }
51744
52249
  case "swift-test":
@@ -52170,13 +52675,13 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
52170
52675
  };
52171
52676
  }
52172
52677
  const startTime = Date.now();
52173
- const vitestJsonOutputPath = framework === "vitest" ? path42.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
52678
+ const vitestJsonOutputPath = framework === "vitest" ? path44.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
52174
52679
  try {
52175
52680
  if (vitestJsonOutputPath) {
52176
52681
  try {
52177
- fs22.mkdirSync(path42.dirname(vitestJsonOutputPath), { recursive: true });
52178
- if (fs22.existsSync(vitestJsonOutputPath)) {
52179
- fs22.unlinkSync(vitestJsonOutputPath);
52682
+ fs23.mkdirSync(path44.dirname(vitestJsonOutputPath), { recursive: true });
52683
+ if (fs23.existsSync(vitestJsonOutputPath)) {
52684
+ fs23.unlinkSync(vitestJsonOutputPath);
52180
52685
  }
52181
52686
  } catch {}
52182
52687
  }
@@ -52185,9 +52690,9 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
52185
52690
  stderr: "pipe",
52186
52691
  cwd
52187
52692
  });
52188
- const timeoutPromise = new Promise((resolve14) => setTimeout(() => {
52693
+ const timeoutPromise = new Promise((resolve16) => setTimeout(() => {
52189
52694
  proc.kill();
52190
- resolve14(-1);
52695
+ resolve16(-1);
52191
52696
  }, timeout_ms));
52192
52697
  const [exitCode, stdoutResult, stderrResult] = await Promise.all([
52193
52698
  Promise.race([proc.exited, timeoutPromise]),
@@ -52202,8 +52707,8 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
52202
52707
  }
52203
52708
  if (vitestJsonOutputPath) {
52204
52709
  try {
52205
- if (fs22.existsSync(vitestJsonOutputPath)) {
52206
- const vitestJsonOutput = fs22.readFileSync(vitestJsonOutputPath, "utf-8");
52710
+ if (fs23.existsSync(vitestJsonOutputPath)) {
52711
+ const vitestJsonOutput = fs23.readFileSync(vitestJsonOutputPath, "utf-8");
52207
52712
  if (vitestJsonOutput.trim().length > 0) {
52208
52713
  output += (output ? `
52209
52714
  ` : "") + vitestJsonOutput;
@@ -52290,10 +52795,10 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
52290
52795
  }
52291
52796
  function normalizeHistoryTestFile(testFile, workingDir) {
52292
52797
  const normalized = testFile.replace(/\\/g, "/");
52293
- if (!path42.isAbsolute(testFile))
52798
+ if (!path44.isAbsolute(testFile))
52294
52799
  return normalized;
52295
- const relative9 = path42.relative(workingDir, testFile);
52296
- if (relative9.startsWith("..") || path42.isAbsolute(relative9)) {
52800
+ const relative9 = path44.relative(workingDir, testFile);
52801
+ if (relative9.startsWith("..") || path44.isAbsolute(relative9)) {
52297
52802
  return normalized;
52298
52803
  }
52299
52804
  return relative9.replace(/\\/g, "/");
@@ -52631,7 +53136,7 @@ var init_test_runner = __esm(() => {
52631
53136
  const sourceFiles = args.files.filter((file3) => {
52632
53137
  if (directTestFiles.includes(file3))
52633
53138
  return false;
52634
- const ext = path42.extname(file3).toLowerCase();
53139
+ const ext = path44.extname(file3).toLowerCase();
52635
53140
  return SOURCE_EXTENSIONS.has(ext);
52636
53141
  });
52637
53142
  const invalidFiles = args.files.filter((file3) => !directTestFiles.includes(file3) && !sourceFiles.includes(file3));
@@ -52677,7 +53182,7 @@ var init_test_runner = __esm(() => {
52677
53182
  if (isConventionTestFilePath(f)) {
52678
53183
  return false;
52679
53184
  }
52680
- const ext = path42.extname(f).toLowerCase();
53185
+ const ext = path44.extname(f).toLowerCase();
52681
53186
  return SOURCE_EXTENSIONS.has(ext);
52682
53187
  });
52683
53188
  if (sourceFiles.length === 0) {
@@ -52727,7 +53232,7 @@ var init_test_runner = __esm(() => {
52727
53232
  if (isConventionTestFilePath(f)) {
52728
53233
  return false;
52729
53234
  }
52730
- const ext = path42.extname(f).toLowerCase();
53235
+ const ext = path44.extname(f).toLowerCase();
52731
53236
  return SOURCE_EXTENSIONS.has(ext);
52732
53237
  });
52733
53238
  if (sourceFiles.length === 0) {
@@ -52779,8 +53284,8 @@ var init_test_runner = __esm(() => {
52779
53284
  }
52780
53285
  if (impactResult.impactedTests.length > 0) {
52781
53286
  testFiles = impactResult.impactedTests.map((absPath) => {
52782
- const relativePath = path42.relative(workingDir, absPath);
52783
- return path42.isAbsolute(relativePath) ? absPath : relativePath;
53287
+ const relativePath = path44.relative(workingDir, absPath);
53288
+ return path44.isAbsolute(relativePath) ? absPath : relativePath;
52784
53289
  });
52785
53290
  } else {
52786
53291
  graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
@@ -52855,8 +53360,8 @@ var init_test_runner = __esm(() => {
52855
53360
  });
52856
53361
 
52857
53362
  // src/services/preflight-service.ts
52858
- import * as fs23 from "fs";
52859
- import * as path43 from "path";
53363
+ import * as fs24 from "fs";
53364
+ import * as path45 from "path";
52860
53365
  function validateDirectoryPath(dir) {
52861
53366
  if (!dir || typeof dir !== "string") {
52862
53367
  throw new Error("Directory path is required");
@@ -52864,8 +53369,8 @@ function validateDirectoryPath(dir) {
52864
53369
  if (dir.includes("..")) {
52865
53370
  throw new Error("Directory path must not contain path traversal sequences");
52866
53371
  }
52867
- const normalized = path43.normalize(dir);
52868
- const absolutePath = path43.isAbsolute(normalized) ? normalized : path43.resolve(normalized);
53372
+ const normalized = path45.normalize(dir);
53373
+ const absolutePath = path45.isAbsolute(normalized) ? normalized : path45.resolve(normalized);
52869
53374
  return absolutePath;
52870
53375
  }
52871
53376
  function validateTimeout(timeoutMs, defaultValue) {
@@ -52888,9 +53393,9 @@ function validateTimeout(timeoutMs, defaultValue) {
52888
53393
  }
52889
53394
  function getPackageVersion(dir) {
52890
53395
  try {
52891
- const packagePath = path43.join(dir, "package.json");
52892
- if (fs23.existsSync(packagePath)) {
52893
- const content = fs23.readFileSync(packagePath, "utf-8");
53396
+ const packagePath = path45.join(dir, "package.json");
53397
+ if (fs24.existsSync(packagePath)) {
53398
+ const content = fs24.readFileSync(packagePath, "utf-8");
52894
53399
  const pkg = JSON.parse(content);
52895
53400
  return pkg.version ?? null;
52896
53401
  }
@@ -52899,9 +53404,9 @@ function getPackageVersion(dir) {
52899
53404
  }
52900
53405
  function getChangelogVersion(dir) {
52901
53406
  try {
52902
- const changelogPath = path43.join(dir, "CHANGELOG.md");
52903
- if (fs23.existsSync(changelogPath)) {
52904
- const content = fs23.readFileSync(changelogPath, "utf-8");
53407
+ const changelogPath = path45.join(dir, "CHANGELOG.md");
53408
+ if (fs24.existsSync(changelogPath)) {
53409
+ const content = fs24.readFileSync(changelogPath, "utf-8");
52905
53410
  const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
52906
53411
  if (match) {
52907
53412
  return match[1];
@@ -52913,10 +53418,10 @@ function getChangelogVersion(dir) {
52913
53418
  function getVersionFileVersion(dir) {
52914
53419
  const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
52915
53420
  for (const file3 of possibleFiles) {
52916
- const filePath = path43.join(dir, file3);
52917
- if (fs23.existsSync(filePath)) {
53421
+ const filePath = path45.join(dir, file3);
53422
+ if (fs24.existsSync(filePath)) {
52918
53423
  try {
52919
- const content = fs23.readFileSync(filePath, "utf-8").trim();
53424
+ const content = fs24.readFileSync(filePath, "utf-8").trim();
52920
53425
  const match = content.match(/(\d+\.\d+\.\d+)/);
52921
53426
  if (match) {
52922
53427
  return match[1];
@@ -53255,8 +53760,8 @@ async function runEvidenceCheck(dir) {
53255
53760
  async function runRequirementCoverageCheck(dir, currentPhase) {
53256
53761
  const startTime = Date.now();
53257
53762
  try {
53258
- const specPath = path43.join(dir, ".swarm", "spec.md");
53259
- if (!fs23.existsSync(specPath)) {
53763
+ const specPath = path45.join(dir, ".swarm", "spec.md");
53764
+ if (!fs24.existsSync(specPath)) {
53260
53765
  return {
53261
53766
  type: "req_coverage",
53262
53767
  status: "skip",
@@ -53734,13 +54239,13 @@ class CircuitBreaker {
53734
54239
  if (this.config.callTimeoutMs <= 0) {
53735
54240
  return fn();
53736
54241
  }
53737
- return new Promise((resolve15, reject) => {
54242
+ return new Promise((resolve17, reject) => {
53738
54243
  const timeout = setTimeout(() => {
53739
54244
  reject(new Error(`Call timeout after ${this.config.callTimeoutMs}ms`));
53740
54245
  }, this.config.callTimeoutMs);
53741
54246
  fn().then((result) => {
53742
54247
  clearTimeout(timeout);
53743
- resolve15(result);
54248
+ resolve17(result);
53744
54249
  }).catch((error93) => {
53745
54250
  clearTimeout(timeout);
53746
54251
  reject(error93);
@@ -54027,7 +54532,7 @@ var init_queue = __esm(() => {
54027
54532
 
54028
54533
  // src/background/worker.ts
54029
54534
  function sleep(ms) {
54030
- return new Promise((resolve15) => setTimeout(resolve15, ms));
54535
+ return new Promise((resolve17) => setTimeout(resolve17, ms));
54031
54536
  }
54032
54537
 
54033
54538
  class WorkerManager {
@@ -54372,8 +54877,8 @@ var init_manager3 = __esm(() => {
54372
54877
  });
54373
54878
 
54374
54879
  // src/commands/reset.ts
54375
- import * as fs24 from "fs";
54376
- import * as path44 from "path";
54880
+ import * as fs25 from "fs";
54881
+ import * as path46 from "path";
54377
54882
  async function handleResetCommand(directory, args) {
54378
54883
  const hasConfirm = args.includes("--confirm");
54379
54884
  if (!hasConfirm) {
@@ -54401,8 +54906,8 @@ async function handleResetCommand(directory, args) {
54401
54906
  for (const filename of filesToReset) {
54402
54907
  try {
54403
54908
  const resolvedPath = validateSwarmPath(directory, filename);
54404
- if (fs24.existsSync(resolvedPath)) {
54405
- fs24.unlinkSync(resolvedPath);
54909
+ if (fs25.existsSync(resolvedPath)) {
54910
+ fs25.unlinkSync(resolvedPath);
54406
54911
  results.push(`- \u2705 Deleted ${filename}`);
54407
54912
  } else {
54408
54913
  results.push(`- \u23ED\uFE0F ${filename} not found (skipped)`);
@@ -54413,9 +54918,9 @@ async function handleResetCommand(directory, args) {
54413
54918
  }
54414
54919
  for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
54415
54920
  try {
54416
- const rootPath = path44.join(directory, filename);
54417
- if (fs24.existsSync(rootPath)) {
54418
- fs24.unlinkSync(rootPath);
54921
+ const rootPath = path46.join(directory, filename);
54922
+ if (fs25.existsSync(rootPath)) {
54923
+ fs25.unlinkSync(rootPath);
54419
54924
  results.push(`- \u2705 Deleted ${filename} (root)`);
54420
54925
  }
54421
54926
  } catch {}
@@ -54428,8 +54933,8 @@ async function handleResetCommand(directory, args) {
54428
54933
  }
54429
54934
  try {
54430
54935
  const summariesPath = validateSwarmPath(directory, "summaries");
54431
- if (fs24.existsSync(summariesPath)) {
54432
- fs24.rmSync(summariesPath, { recursive: true, force: true });
54936
+ if (fs25.existsSync(summariesPath)) {
54937
+ fs25.rmSync(summariesPath, { recursive: true, force: true });
54433
54938
  results.push("- \u2705 Deleted summaries/ directory");
54434
54939
  } else {
54435
54940
  results.push("- \u23ED\uFE0F summaries/ not found (skipped)");
@@ -54452,14 +54957,14 @@ var init_reset = __esm(() => {
54452
54957
  });
54453
54958
 
54454
54959
  // src/commands/reset-session.ts
54455
- import * as fs25 from "fs";
54456
- import * as path45 from "path";
54960
+ import * as fs26 from "fs";
54961
+ import * as path47 from "path";
54457
54962
  async function handleResetSessionCommand(directory, _args) {
54458
54963
  const results = [];
54459
54964
  try {
54460
54965
  const statePath = validateSwarmPath(directory, "session/state.json");
54461
- if (fs25.existsSync(statePath)) {
54462
- fs25.unlinkSync(statePath);
54966
+ if (fs26.existsSync(statePath)) {
54967
+ fs26.unlinkSync(statePath);
54463
54968
  results.push("\u2705 Deleted .swarm/session/state.json");
54464
54969
  } else {
54465
54970
  results.push("\u23ED\uFE0F state.json not found (already clean)");
@@ -54468,15 +54973,15 @@ async function handleResetSessionCommand(directory, _args) {
54468
54973
  results.push("\u274C Failed to delete state.json");
54469
54974
  }
54470
54975
  try {
54471
- const sessionDir = path45.dirname(validateSwarmPath(directory, "session/state.json"));
54472
- if (fs25.existsSync(sessionDir)) {
54473
- const files = fs25.readdirSync(sessionDir);
54976
+ const sessionDir = path47.dirname(validateSwarmPath(directory, "session/state.json"));
54977
+ if (fs26.existsSync(sessionDir)) {
54978
+ const files = fs26.readdirSync(sessionDir);
54474
54979
  const otherFiles = files.filter((f) => f !== "state.json");
54475
54980
  let deletedCount = 0;
54476
54981
  for (const file3 of otherFiles) {
54477
- const filePath = path45.join(sessionDir, file3);
54478
- if (fs25.lstatSync(filePath).isFile()) {
54479
- fs25.unlinkSync(filePath);
54982
+ const filePath = path47.join(sessionDir, file3);
54983
+ if (fs26.lstatSync(filePath).isFile()) {
54984
+ fs26.unlinkSync(filePath);
54480
54985
  deletedCount++;
54481
54986
  }
54482
54987
  }
@@ -54506,7 +55011,7 @@ var init_reset_session = __esm(() => {
54506
55011
  });
54507
55012
 
54508
55013
  // src/summaries/manager.ts
54509
- import * as path46 from "path";
55014
+ import * as path48 from "path";
54510
55015
  function sanitizeSummaryId(id) {
54511
55016
  if (!id || id.length === 0) {
54512
55017
  throw new Error("Invalid summary ID: empty string");
@@ -54529,7 +55034,7 @@ function sanitizeSummaryId(id) {
54529
55034
  }
54530
55035
  async function loadFullOutput(directory, id) {
54531
55036
  const sanitizedId = sanitizeSummaryId(id);
54532
- const relativePath = path46.join("summaries", `${sanitizedId}.json`);
55037
+ const relativePath = path48.join("summaries", `${sanitizedId}.json`);
54533
55038
  validateSwarmPath(directory, relativePath);
54534
55039
  const content = await readSwarmFileAsync(directory, relativePath);
54535
55040
  if (content === null) {
@@ -54591,18 +55096,18 @@ var init_retrieve = __esm(() => {
54591
55096
  });
54592
55097
 
54593
55098
  // src/commands/rollback.ts
54594
- import * as fs26 from "fs";
54595
- import * as path47 from "path";
55099
+ import * as fs27 from "fs";
55100
+ import * as path49 from "path";
54596
55101
  async function handleRollbackCommand(directory, args) {
54597
55102
  const phaseArg = args[0];
54598
55103
  if (!phaseArg) {
54599
55104
  const manifestPath2 = validateSwarmPath(directory, "checkpoints/manifest.json");
54600
- if (!fs26.existsSync(manifestPath2)) {
55105
+ if (!fs27.existsSync(manifestPath2)) {
54601
55106
  return "No checkpoints found. Use `/swarm checkpoint` to create checkpoints.";
54602
55107
  }
54603
55108
  let manifest2;
54604
55109
  try {
54605
- manifest2 = JSON.parse(fs26.readFileSync(manifestPath2, "utf-8"));
55110
+ manifest2 = JSON.parse(fs27.readFileSync(manifestPath2, "utf-8"));
54606
55111
  } catch {
54607
55112
  return "Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.";
54608
55113
  }
@@ -54624,12 +55129,12 @@ async function handleRollbackCommand(directory, args) {
54624
55129
  return "Error: Phase number must be a positive integer.";
54625
55130
  }
54626
55131
  const manifestPath = validateSwarmPath(directory, "checkpoints/manifest.json");
54627
- if (!fs26.existsSync(manifestPath)) {
55132
+ if (!fs27.existsSync(manifestPath)) {
54628
55133
  return `Error: No checkpoints found. Cannot rollback to phase ${targetPhase}.`;
54629
55134
  }
54630
55135
  let manifest;
54631
55136
  try {
54632
- manifest = JSON.parse(fs26.readFileSync(manifestPath, "utf-8"));
55137
+ manifest = JSON.parse(fs27.readFileSync(manifestPath, "utf-8"));
54633
55138
  } catch {
54634
55139
  return `Error: Checkpoint manifest is corrupted. Delete .swarm/checkpoints/manifest.json and re-checkpoint.`;
54635
55140
  }
@@ -54639,10 +55144,10 @@ async function handleRollbackCommand(directory, args) {
54639
55144
  return `Error: Checkpoint for phase ${targetPhase} not found. Available phases: ${available}`;
54640
55145
  }
54641
55146
  const checkpointDir = validateSwarmPath(directory, `checkpoints/phase-${targetPhase}`);
54642
- if (!fs26.existsSync(checkpointDir)) {
55147
+ if (!fs27.existsSync(checkpointDir)) {
54643
55148
  return `Error: Checkpoint directory for phase ${targetPhase} does not exist.`;
54644
55149
  }
54645
- const checkpointFiles = fs26.readdirSync(checkpointDir);
55150
+ const checkpointFiles = fs27.readdirSync(checkpointDir);
54646
55151
  if (checkpointFiles.length === 0) {
54647
55152
  return `Error: Checkpoint for phase ${targetPhase} is empty. Cannot rollback.`;
54648
55153
  }
@@ -54657,10 +55162,10 @@ async function handleRollbackCommand(directory, args) {
54657
55162
  if (EXCLUDE_FILES.has(file3) || file3.startsWith("plan-ledger.archived-")) {
54658
55163
  continue;
54659
55164
  }
54660
- const src = path47.join(checkpointDir, file3);
54661
- const dest = path47.join(swarmDir, file3);
55165
+ const src = path49.join(checkpointDir, file3);
55166
+ const dest = path49.join(swarmDir, file3);
54662
55167
  try {
54663
- fs26.cpSync(src, dest, { recursive: true, force: true });
55168
+ fs27.cpSync(src, dest, { recursive: true, force: true });
54664
55169
  successes.push(file3);
54665
55170
  } catch (error93) {
54666
55171
  failures.push({ file: file3, error: error93.message });
@@ -54677,14 +55182,14 @@ async function handleRollbackCommand(directory, args) {
54677
55182
  ].join(`
54678
55183
  `);
54679
55184
  }
54680
- const existingLedgerPath = path47.join(swarmDir, "plan-ledger.jsonl");
54681
- if (fs26.existsSync(existingLedgerPath)) {
54682
- fs26.unlinkSync(existingLedgerPath);
55185
+ const existingLedgerPath = path49.join(swarmDir, "plan-ledger.jsonl");
55186
+ if (fs27.existsSync(existingLedgerPath)) {
55187
+ fs27.unlinkSync(existingLedgerPath);
54683
55188
  }
54684
55189
  try {
54685
- const planJsonPath = path47.join(swarmDir, "plan.json");
54686
- if (fs26.existsSync(planJsonPath)) {
54687
- const planRaw = fs26.readFileSync(planJsonPath, "utf-8");
55190
+ const planJsonPath = path49.join(swarmDir, "plan.json");
55191
+ if (fs27.existsSync(planJsonPath)) {
55192
+ const planRaw = fs27.readFileSync(planJsonPath, "utf-8");
54688
55193
  const plan = PlanSchema.parse(JSON.parse(planRaw));
54689
55194
  const planId = derivePlanId(plan);
54690
55195
  const planHash = computePlanHash(plan);
@@ -54711,7 +55216,7 @@ async function handleRollbackCommand(directory, args) {
54711
55216
  timestamp: new Date().toISOString()
54712
55217
  };
54713
55218
  try {
54714
- fs26.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
55219
+ fs27.appendFileSync(eventsPath, `${JSON.stringify(rollbackEvent)}
54715
55220
  `);
54716
55221
  } catch (error93) {
54717
55222
  console.error("Failed to write rollback event:", error93 instanceof Error ? error93.message : String(error93));
@@ -54772,11 +55277,11 @@ Ensure this is a git repository with commit history.`;
54772
55277
  const report = reportLines.filter(Boolean).join(`
54773
55278
  `);
54774
55279
  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");
55280
+ const fs28 = await import("fs/promises");
55281
+ const path50 = await import("path");
55282
+ const reportPath = path50.join(directory, ".swarm", "simulate-report.md");
55283
+ await fs28.mkdir(path50.dirname(reportPath), { recursive: true });
55284
+ await fs28.writeFile(reportPath, report, "utf-8");
54780
55285
  } catch (err) {
54781
55286
  const writeErr = err instanceof Error ? err.message : String(err);
54782
55287
  warn(`simulate: failed to write report to ${directory}/.swarm/simulate-report.md`, writeErr);
@@ -54798,15 +55303,15 @@ async function handleSpecifyCommand(_directory, args) {
54798
55303
  }
54799
55304
 
54800
55305
  // src/turbo/lean/state.ts
54801
- import * as fs27 from "fs";
54802
- import * as path48 from "path";
55306
+ import * as fs28 from "fs";
55307
+ import * as path50 from "path";
54803
55308
  function nowISO2() {
54804
55309
  return new Date().toISOString();
54805
55310
  }
54806
55311
  function ensureSwarmDir2(directory) {
54807
- const swarmDir = path48.resolve(directory, ".swarm");
54808
- if (!fs27.existsSync(swarmDir)) {
54809
- fs27.mkdirSync(swarmDir, { recursive: true });
55312
+ const swarmDir = path50.resolve(directory, ".swarm");
55313
+ if (!fs28.existsSync(swarmDir)) {
55314
+ fs28.mkdirSync(swarmDir, { recursive: true });
54810
55315
  }
54811
55316
  return swarmDir;
54812
55317
  }
@@ -54848,17 +55353,17 @@ function markStateUnreadable2(directory, reason) {
54848
55353
  }
54849
55354
  function readPersisted2(directory) {
54850
55355
  try {
54851
- const filePath = path48.join(directory, ".swarm", STATE_FILE2);
54852
- if (!fs27.existsSync(filePath)) {
55356
+ const filePath = path50.join(directory, ".swarm", STATE_FILE2);
55357
+ if (!fs28.existsSync(filePath)) {
54853
55358
  const seed = emptyPersisted2();
54854
55359
  try {
54855
55360
  ensureSwarmDir2(directory);
54856
- fs27.writeFileSync(filePath, `${JSON.stringify(seed, null, 2)}
55361
+ fs28.writeFileSync(filePath, `${JSON.stringify(seed, null, 2)}
54857
55362
  `, "utf-8");
54858
55363
  } catch {}
54859
55364
  return seed;
54860
55365
  }
54861
- const raw = fs27.readFileSync(filePath, "utf-8");
55366
+ const raw = fs28.readFileSync(filePath, "utf-8");
54862
55367
  const parsed = JSON.parse(raw);
54863
55368
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed) || parsed.version !== 1 || !parsed.sessions || typeof parsed.sessions !== "object" || Array.isArray(parsed.sessions)) {
54864
55369
  markStateUnreadable2(directory, `malformed shape (version=${parsed?.version}, sessions type=${Array.isArray(parsed?.sessions) ? "array" : typeof parsed?.sessions})`);
@@ -54884,7 +55389,7 @@ function writePersisted2(directory, persisted) {
54884
55389
  let payload;
54885
55390
  try {
54886
55391
  ensureSwarmDir2(directory);
54887
- filePath = path48.join(directory, ".swarm", STATE_FILE2);
55392
+ filePath = path50.join(directory, ".swarm", STATE_FILE2);
54888
55393
  tmpPath = `${filePath}.tmp.${Date.now()}`;
54889
55394
  persisted.updatedAt = nowISO2();
54890
55395
  payload = `${JSON.stringify(persisted, null, 2)}
@@ -54895,14 +55400,14 @@ function writePersisted2(directory, persisted) {
54895
55400
  throw new Error(`Lean Turbo state persistence prepare failed: ${msg}`);
54896
55401
  }
54897
55402
  try {
54898
- fs27.writeFileSync(tmpPath, payload, "utf-8");
54899
- fs27.renameSync(tmpPath, filePath);
55403
+ fs28.writeFileSync(tmpPath, payload, "utf-8");
55404
+ fs28.renameSync(tmpPath, filePath);
54900
55405
  } catch (error93) {
54901
55406
  const msg = error93 instanceof Error ? error93.message : String(error93);
54902
55407
  error(`[turbo/lean/state] Failed to persist ${STATE_FILE2} atomically: ${msg}`);
54903
55408
  try {
54904
- if (fs27.existsSync(tmpPath)) {
54905
- fs27.unlinkSync(tmpPath);
55409
+ if (fs28.existsSync(tmpPath)) {
55410
+ fs28.unlinkSync(tmpPath);
54906
55411
  }
54907
55412
  } catch {}
54908
55413
  throw new Error(`Lean Turbo state persistence failed: ${msg}`);
@@ -55011,10 +55516,10 @@ var init_context_budget_service = __esm(() => {
55011
55516
 
55012
55517
  // src/services/status-service.ts
55013
55518
  import * as fsSync2 from "fs";
55014
- import * as path49 from "path";
55519
+ import * as path51 from "path";
55015
55520
  function readSpecStalenessSnapshot(directory) {
55016
55521
  try {
55017
- const p = path49.join(directory, ".swarm", "spec-staleness.json");
55522
+ const p = path51.join(directory, ".swarm", "spec-staleness.json");
55018
55523
  if (!fsSync2.existsSync(p))
55019
55524
  return { stale: false };
55020
55525
  const raw = fsSync2.readFileSync(p, "utf-8");
@@ -55301,7 +55806,7 @@ async function handleTurboCommand(directory, args, sessionID) {
55301
55806
  const arg0 = args[0]?.toLowerCase();
55302
55807
  const arg1 = args[1]?.toLowerCase();
55303
55808
  if (arg0 === "status") {
55304
- return buildStatusMessage(session, directory, sessionID);
55809
+ return buildStatusMessage2(session, directory, sessionID);
55305
55810
  }
55306
55811
  const isTurboOn = session.turboMode;
55307
55812
  const isLeanActive = session.leanTurboActive === true;
@@ -55432,7 +55937,7 @@ function enableLeanTurbo(session, directory, sessionID) {
55432
55937
  `Full-Auto: ${fullAutoActive ? "active" : "inactive"})`
55433
55938
  ].join(" ");
55434
55939
  }
55435
- function buildStatusMessage(session, directory, sessionID) {
55940
+ function buildStatusMessage2(session, directory, sessionID) {
55436
55941
  if (!session.turboMode) {
55437
55942
  return "Turbo: off";
55438
55943
  }
@@ -55539,8 +56044,8 @@ var init_write_retro2 = __esm(() => {
55539
56044
  });
55540
56045
 
55541
56046
  // src/commands/command-dispatch.ts
55542
- import fs28 from "fs";
55543
- import path50 from "path";
56047
+ import fs29 from "fs";
56048
+ import path52 from "path";
55544
56049
  function normalizeSwarmCommandInput(command, argumentText) {
55545
56050
  if (command !== "swarm" && !command.startsWith("swarm-")) {
55546
56051
  return { isSwarmCommand: false, tokens: [] };
@@ -55576,11 +56081,11 @@ ${similar.map((cmd) => ` - /swarm ${cmd}`).join(`
55576
56081
  `);
55577
56082
  }
55578
56083
  function maybeMarkFirstRun(directory) {
55579
- const sentinelPath = path50.join(directory, ".swarm", ".first-run-complete");
56084
+ const sentinelPath = path52.join(directory, ".swarm", ".first-run-complete");
55580
56085
  try {
55581
- const swarmDir = path50.join(directory, ".swarm");
55582
- fs28.mkdirSync(swarmDir, { recursive: true });
55583
- fs28.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
56086
+ const swarmDir = path52.join(directory, ".swarm");
56087
+ fs29.mkdirSync(swarmDir, { recursive: true });
56088
+ fs29.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
55584
56089
  `, { flag: "wx" });
55585
56090
  return true;
55586
56091
  } catch {
@@ -55692,7 +56197,17 @@ function classifySwarmCommandToolUse(resolved) {
55692
56197
  return { allowed: true };
55693
56198
  return {
55694
56199
  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."
56200
+ 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."
56201
+ };
56202
+ }
56203
+ if (canonicalKey === "memory evaluate") {
56204
+ if (args.length === 0)
56205
+ return { allowed: true };
56206
+ if (args.length === 1 && args[0] === "--json")
56207
+ return { allowed: true };
56208
+ return {
56209
+ allowed: false,
56210
+ message: "Usage through swarm_command: `/swarm memory evaluate --json`. Custom fixture directories are only available through direct user command execution."
55696
56211
  };
55697
56212
  }
55698
56213
  if (canonicalKey === "retrieve") {
@@ -55780,6 +56295,7 @@ var init_tool_policy = __esm(() => {
55780
56295
  "memory",
55781
56296
  "memory status",
55782
56297
  "memory export",
56298
+ "memory evaluate",
55783
56299
  "memory import",
55784
56300
  "memory migrate",
55785
56301
  "sync-plan",
@@ -55805,6 +56321,7 @@ var init_tool_policy = __esm(() => {
55805
56321
  "memory",
55806
56322
  "memory status",
55807
56323
  "memory export",
56324
+ "memory evaluate",
55808
56325
  "sync-plan",
55809
56326
  "export"
55810
56327
  ]);
@@ -55887,6 +56404,7 @@ __export(exports_commands, {
55887
56404
  handleCurateCommand: () => handleCurateCommand,
55888
56405
  handleCouncilCommand: () => handleCouncilCommand,
55889
56406
  handleConfigCommand: () => handleConfigCommand,
56407
+ handleConcurrencyCommand: () => handleConcurrencyCommand,
55890
56408
  handleCloseCommand: () => handleCloseCommand,
55891
56409
  handleClarifyCommand: () => handleClarifyCommand,
55892
56410
  handleCheckpointCommand: () => handleCheckpointCommand,
@@ -56133,6 +56651,7 @@ var init_commands = __esm(() => {
56133
56651
  init_close();
56134
56652
  init_command_dispatch();
56135
56653
  init_command_names();
56654
+ init_concurrency();
56136
56655
  init_config2();
56137
56656
  init_council();
56138
56657
  init_curate();
@@ -56287,24 +56806,24 @@ function validateAliases() {
56287
56806
  }
56288
56807
  aliasTargets.get(target).push(name);
56289
56808
  const visited = new Set;
56290
- const path51 = [];
56809
+ const path53 = [];
56291
56810
  let current = target;
56292
56811
  while (current) {
56293
56812
  const currentEntry = COMMAND_REGISTRY[current];
56294
56813
  if (!currentEntry)
56295
56814
  break;
56296
56815
  if (visited.has(current)) {
56297
- const cycleStart = path51.indexOf(current);
56816
+ const cycleStart = path53.indexOf(current);
56298
56817
  const fullChain = [
56299
56818
  name,
56300
- ...path51.slice(0, cycleStart > 0 ? cycleStart : path51.length),
56819
+ ...path53.slice(0, cycleStart > 0 ? cycleStart : path53.length),
56301
56820
  current
56302
56821
  ].join(" \u2192 ");
56303
56822
  errors5.push(`Circular alias detected: ${fullChain}`);
56304
56823
  break;
56305
56824
  }
56306
56825
  visited.add(current);
56307
- path51.push(current);
56826
+ path53.push(current);
56308
56827
  current = currentEntry.aliasOf || "";
56309
56828
  }
56310
56829
  }
@@ -56353,6 +56872,7 @@ var init_registry = __esm(() => {
56353
56872
  init_benchmark();
56354
56873
  init_checkpoint2();
56355
56874
  init_close();
56875
+ init_concurrency();
56356
56876
  init_config2();
56357
56877
  init_council();
56358
56878
  init_curate();
@@ -56597,6 +57117,23 @@ var init_registry = __esm(() => {
56597
57117
  aliasOf: "finalize",
56598
57118
  deprecated: true
56599
57119
  },
57120
+ concurrency: {
57121
+ handler: (ctx) => handleConcurrencyCommand(ctx.directory, ctx.args, ctx.sessionID),
57122
+ description: "Manage runtime concurrency override for plan execution [set|status|reset]",
57123
+ args: "set <N|preset>, status, reset",
57124
+ details: `Sets, queries, or clears a session-scoped concurrency override for max_concurrent_tasks during plan execution.
57125
+ When set, the override takes precedence over the plan's locked execution_profile.max_concurrent_tasks.
57126
+ ` + `The override is session-scoped \u2014 it does not modify the plan and is cleared on session reset.
57127
+ ` + `
57128
+ Subcommands:
57129
+ ` + ` concurrency set <N> \u2014 Set session concurrency to N (1-64)
57130
+ ` + ` concurrency set <preset> \u2014 Set to preset: min (1), medium (3), max (8)
57131
+ ` + ` concurrency status \u2014 Show effective concurrency (override, plan baseline, operational effective)
57132
+ ` + ` concurrency reset \u2014 Clear the session concurrency override
57133
+ ` + `
57134
+ ` + "Session-scoped \u2014 resets on new session.",
57135
+ category: "utility"
57136
+ },
56600
57137
  simulate: {
56601
57138
  handler: (ctx) => handleSimulateCommand(ctx.directory, ctx.args),
56602
57139
  description: "Dry-run hidden coupling analysis with configurable thresholds",
@@ -56797,6 +57334,13 @@ Subcommands:
56797
57334
  args: "",
56798
57335
  category: "utility"
56799
57336
  },
57337
+ "memory evaluate": {
57338
+ handler: (ctx) => handleMemoryEvaluateCommand(ctx.directory, ctx.args),
57339
+ description: "Run golden Swarm memory recall evaluation fixtures",
57340
+ subcommandOf: "memory",
57341
+ args: "--json, --fixtures <directory>",
57342
+ category: "diagnostics"
57343
+ },
56800
57344
  "memory import": {
56801
57345
  handler: (ctx) => handleMemoryImportCommand(ctx.directory, ctx.args),
56802
57346
  description: "Import legacy JSONL memory into SQLite",
@@ -56847,68 +57391,68 @@ init_package();
56847
57391
  init_registry();
56848
57392
  init_cache_paths();
56849
57393
  init_constants();
56850
- import * as fs29 from "fs";
56851
- import * as os7 from "os";
56852
- import * as path51 from "path";
57394
+ import * as fs30 from "fs";
57395
+ import * as os8 from "os";
57396
+ import * as path53 from "path";
56853
57397
  var { version: version4 } = package_default;
56854
57398
  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");
57399
+ var OPENCODE_CONFIG_PATH = path53.join(CONFIG_DIR, "opencode.json");
57400
+ var PLUGIN_CONFIG_PATH = path53.join(CONFIG_DIR, "opencode-swarm.json");
57401
+ var PROMPTS_DIR = path53.join(CONFIG_DIR, "opencode-swarm");
56858
57402
  var OPENCODE_PLUGIN_CACHE_PATHS = getPluginCachePaths();
56859
57403
  var OPENCODE_PLUGIN_LOCK_FILE_PATHS = getPluginLockFilePaths();
56860
57404
  function isSafeCachePath(p) {
56861
- const resolved = path51.resolve(p);
56862
- const home = path51.resolve(os7.homedir());
57405
+ const resolved = path53.resolve(p);
57406
+ const home = path53.resolve(os8.homedir());
56863
57407
  if (resolved === "/" || resolved === home || resolved.length <= home.length) {
56864
57408
  return false;
56865
57409
  }
56866
- const segments = resolved.split(path51.sep).filter((s) => s.length > 0);
57410
+ const segments = resolved.split(path53.sep).filter((s) => s.length > 0);
56867
57411
  if (segments.length < 4) {
56868
57412
  return false;
56869
57413
  }
56870
- const leaf = path51.basename(resolved);
57414
+ const leaf = path53.basename(resolved);
56871
57415
  if (leaf !== "opencode-swarm@latest" && leaf !== "opencode-swarm") {
56872
57416
  return false;
56873
57417
  }
56874
- const parent = path51.basename(path51.dirname(resolved));
57418
+ const parent = path53.basename(path53.dirname(resolved));
56875
57419
  if (parent !== "packages" && parent !== "node_modules") {
56876
57420
  return false;
56877
57421
  }
56878
- const grandparent = path51.basename(path51.dirname(path51.dirname(resolved)));
57422
+ const grandparent = path53.basename(path53.dirname(path53.dirname(resolved)));
56879
57423
  if (grandparent !== "opencode") {
56880
57424
  return false;
56881
57425
  }
56882
57426
  return true;
56883
57427
  }
56884
57428
  function isSafeLockFilePath(p) {
56885
- const resolved = path51.resolve(p);
56886
- const home = path51.resolve(os7.homedir());
57429
+ const resolved = path53.resolve(p);
57430
+ const home = path53.resolve(os8.homedir());
56887
57431
  if (resolved === "/" || resolved === home || resolved.length <= home.length) {
56888
57432
  return false;
56889
57433
  }
56890
- const segments = resolved.split(path51.sep).filter((s) => s.length > 0);
57434
+ const segments = resolved.split(path53.sep).filter((s) => s.length > 0);
56891
57435
  if (segments.length < 4) {
56892
57436
  return false;
56893
57437
  }
56894
- const leaf = path51.basename(resolved);
57438
+ const leaf = path53.basename(resolved);
56895
57439
  if (leaf !== "bun.lock" && leaf !== "bun.lockb" && leaf !== "package-lock.json") {
56896
57440
  return false;
56897
57441
  }
56898
- const parent = path51.basename(path51.dirname(resolved));
57442
+ const parent = path53.basename(path53.dirname(resolved));
56899
57443
  if (parent !== "opencode") {
56900
57444
  return false;
56901
57445
  }
56902
57446
  return true;
56903
57447
  }
56904
57448
  function ensureDir(dir) {
56905
- if (!fs29.existsSync(dir)) {
56906
- fs29.mkdirSync(dir, { recursive: true });
57449
+ if (!fs30.existsSync(dir)) {
57450
+ fs30.mkdirSync(dir, { recursive: true });
56907
57451
  }
56908
57452
  }
56909
57453
  function loadJson(filepath) {
56910
57454
  try {
56911
- const content = fs29.readFileSync(filepath, "utf-8");
57455
+ const content = fs30.readFileSync(filepath, "utf-8");
56912
57456
  const stripped = content.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (match, comment) => comment ? "" : match).replace(/,(\s*[}\]])/g, "$1");
56913
57457
  return JSON.parse(stripped);
56914
57458
  } catch {
@@ -56916,14 +57460,14 @@ function loadJson(filepath) {
56916
57460
  }
56917
57461
  }
56918
57462
  function saveJson(filepath, data) {
56919
- fs29.writeFileSync(filepath, `${JSON.stringify(data, null, 2)}
57463
+ fs30.writeFileSync(filepath, `${JSON.stringify(data, null, 2)}
56920
57464
  `, "utf-8");
56921
57465
  }
56922
57466
  function writeProjectConfigIfMissing(cwd) {
56923
57467
  try {
56924
- const opencodeDir = path51.join(cwd, ".opencode");
56925
- const projectConfigPath = path51.join(opencodeDir, "opencode-swarm.json");
56926
- if (fs29.existsSync(projectConfigPath)) {
57468
+ const opencodeDir = path53.join(cwd, ".opencode");
57469
+ const projectConfigPath = path53.join(opencodeDir, "opencode-swarm.json");
57470
+ if (fs30.existsSync(projectConfigPath)) {
56927
57471
  return;
56928
57472
  }
56929
57473
  ensureDir(opencodeDir);
@@ -56939,7 +57483,7 @@ async function install() {
56939
57483
  `);
56940
57484
  ensureDir(CONFIG_DIR);
56941
57485
  ensureDir(PROMPTS_DIR);
56942
- const LEGACY_CONFIG_PATH = path51.join(CONFIG_DIR, "config.json");
57486
+ const LEGACY_CONFIG_PATH = path53.join(CONFIG_DIR, "config.json");
56943
57487
  let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
56944
57488
  if (!opencodeConfig) {
56945
57489
  const legacyConfig = loadJson(LEGACY_CONFIG_PATH);
@@ -56986,7 +57530,7 @@ async function install() {
56986
57530
  console.warn(`\u26A0 Could not clear opencode lock file \u2014 you may need to delete it manually:
56987
57531
  ${failed}`);
56988
57532
  }
56989
- if (!fs29.existsSync(PLUGIN_CONFIG_PATH)) {
57533
+ if (!fs30.existsSync(PLUGIN_CONFIG_PATH)) {
56990
57534
  const defaultConfig = {
56991
57535
  agents: { ...DEFAULT_AGENT_CONFIGS },
56992
57536
  max_iterations: 5
@@ -57065,14 +57609,14 @@ function evictPluginCaches() {
57065
57609
  const cleared = [];
57066
57610
  const failed = [];
57067
57611
  for (const cachePath of OPENCODE_PLUGIN_CACHE_PATHS) {
57068
- if (!fs29.existsSync(cachePath))
57612
+ if (!fs30.existsSync(cachePath))
57069
57613
  continue;
57070
57614
  if (!isSafeCachePath(cachePath)) {
57071
57615
  failed.push(`${cachePath} (refused: failed safety check)`);
57072
57616
  continue;
57073
57617
  }
57074
57618
  try {
57075
- fs29.rmSync(cachePath, { recursive: true, force: true });
57619
+ fs30.rmSync(cachePath, { recursive: true, force: true });
57076
57620
  cleared.push(cachePath);
57077
57621
  } catch (err) {
57078
57622
  failed.push(`${cachePath} (${err instanceof Error ? err.message : String(err)})`);
@@ -57084,14 +57628,14 @@ function evictLockFiles() {
57084
57628
  const cleared = [];
57085
57629
  const failed = [];
57086
57630
  for (const lockPath of OPENCODE_PLUGIN_LOCK_FILE_PATHS) {
57087
- if (!fs29.existsSync(lockPath))
57631
+ if (!fs30.existsSync(lockPath))
57088
57632
  continue;
57089
57633
  if (!isSafeLockFilePath(lockPath)) {
57090
57634
  failed.push(`${lockPath} (refused: failed safety check)`);
57091
57635
  continue;
57092
57636
  }
57093
57637
  try {
57094
- fs29.unlinkSync(lockPath);
57638
+ fs30.unlinkSync(lockPath);
57095
57639
  cleared.push(lockPath);
57096
57640
  } catch (err) {
57097
57641
  const code = err?.code;
@@ -57110,7 +57654,7 @@ async function uninstall() {
57110
57654
  `);
57111
57655
  const opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
57112
57656
  if (!opencodeConfig) {
57113
- if (fs29.existsSync(OPENCODE_CONFIG_PATH)) {
57657
+ if (fs30.existsSync(OPENCODE_CONFIG_PATH)) {
57114
57658
  console.log(`\u2717 Could not parse opencode config at: ${OPENCODE_CONFIG_PATH}`);
57115
57659
  return 1;
57116
57660
  } else {
@@ -57142,13 +57686,13 @@ async function uninstall() {
57142
57686
  console.log("\u2713 Re-enabled default OpenCode agents (explore, general)");
57143
57687
  if (process.argv.includes("--clean")) {
57144
57688
  let cleaned = false;
57145
- if (fs29.existsSync(PLUGIN_CONFIG_PATH)) {
57146
- fs29.unlinkSync(PLUGIN_CONFIG_PATH);
57689
+ if (fs30.existsSync(PLUGIN_CONFIG_PATH)) {
57690
+ fs30.unlinkSync(PLUGIN_CONFIG_PATH);
57147
57691
  console.log(`\u2713 Removed plugin config: ${PLUGIN_CONFIG_PATH}`);
57148
57692
  cleaned = true;
57149
57693
  }
57150
- if (fs29.existsSync(PROMPTS_DIR)) {
57151
- fs29.rmSync(PROMPTS_DIR, { recursive: true });
57694
+ if (fs30.existsSync(PROMPTS_DIR)) {
57695
+ fs30.rmSync(PROMPTS_DIR, { recursive: true });
57152
57696
  console.log(`\u2713 Removed custom prompts: ${PROMPTS_DIR}`);
57153
57697
  cleaned = true;
57154
57698
  }