opencode-swarm 7.99.7 → 7.100.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.
Files changed (26) hide show
  1. package/dist/cli/{config-doctor-1j77p1jy.js → config-doctor-g29kxhek.js} +2 -2
  2. package/dist/cli/{guardrail-explain-dkh5f7nf.js → guardrail-explain-q8pj9691.js} +5 -5
  3. package/dist/cli/{guardrail-log-ya49kpwn.js → guardrail-log-ywajkn46.js} +3 -3
  4. package/dist/cli/{index-h9ptj4b1.js → index-5bstvpct.js} +1 -1
  5. package/dist/cli/{index-sz3kw59p.js → index-jg6m72g7.js} +6 -6
  6. package/dist/cli/{index-7hnwnw5g.js → index-m0qshbr6.js} +41 -1
  7. package/dist/cli/{index-xsswhy6k.js → index-pj3a5fbt.js} +1 -1
  8. package/dist/cli/{index-wpnam1jh.js → index-q5cae5d7.js} +1029 -311
  9. package/dist/cli/{index-0d3pmjf9.js → index-rpb763g8.js} +1 -1
  10. package/dist/cli/{index-zyhd4mnn.js → index-tj0jek4p.js} +2 -2
  11. package/dist/cli/index.js +4 -4
  12. package/dist/cli/{schema-nz638xc3.js → schema-n7pd65qq.js} +1 -1
  13. package/dist/config/schema.d.ts +40 -0
  14. package/dist/index.js +2199 -1429
  15. package/dist/memory/config.d.ts +38 -0
  16. package/dist/memory/embeddings/cache.d.ts +25 -0
  17. package/dist/memory/embeddings/fusion.d.ts +56 -0
  18. package/dist/memory/embeddings/local-provider.d.ts +57 -0
  19. package/dist/memory/embeddings/reranker.d.ts +42 -0
  20. package/dist/memory/embeddings/types.d.ts +27 -0
  21. package/dist/memory/scoring.d.ts +1 -0
  22. package/dist/memory/sqlite-provider.d.ts +19 -0
  23. package/package.json +1 -1
  24. package/tests/fixtures/memory-recall/paraphrase-auth.json +64 -0
  25. package/tests/fixtures/memory-recall/paraphrase-concurrency.json +64 -0
  26. package/tests/fixtures/memory-recall/paraphrase-deployment.json +64 -0
@@ -57,7 +57,7 @@ import {
57
57
  readDoctorArtifact,
58
58
  removeStraySwarmDir,
59
59
  runConfigDoctor
60
- } from "./index-0d3pmjf9.js";
60
+ } from "./index-rpb763g8.js";
61
61
  import {
62
62
  AGENT_TOOL_MAP,
63
63
  ALL_SUBAGENT_NAMES,
@@ -70,7 +70,7 @@ import {
70
70
  TOOL_NAME_SET,
71
71
  resolveExternalSkillsConfig,
72
72
  stripKnownSwarmPrefix
73
- } from "./index-7hnwnw5g.js";
73
+ } from "./index-m0qshbr6.js";
74
74
  import {
75
75
  MAX_TRANSIENT_RETRIES,
76
76
  PlanSchema,
@@ -909,7 +909,7 @@ var init_executor = __esm(() => {
909
909
  // package.json
910
910
  var package_default = {
911
911
  name: "opencode-swarm",
912
- version: "7.99.7",
912
+ version: "7.100.0",
913
913
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
914
914
  main: "dist/index.js",
915
915
  types: "dist/index.d.ts",
@@ -13362,7 +13362,7 @@ async function runFinalizeStage(ctx) {
13362
13362
  }
13363
13363
  }
13364
13364
  try {
13365
- const { CuratorConfigSchema: CCS } = await import("./schema-nz638xc3.js");
13365
+ const { CuratorConfigSchema: CCS } = await import("./schema-n7pd65qq.js");
13366
13366
  const { config: pmLoadedConfig } = _internals20.loadPluginConfigWithMeta(ctx.directory);
13367
13367
  const curatorCfg = CCS.parse(pmLoadedConfig.curator ?? {});
13368
13368
  if (curatorCfg.enabled && curatorCfg.postmortem_enabled) {
@@ -17154,7 +17154,7 @@ async function handleDoctorCommand(directory, args) {
17154
17154
  const result = runConfigDoctor(config, directory);
17155
17155
  let output;
17156
17156
  if (enableAutoFix && result.hasAutoFixableIssues) {
17157
- const { runConfigDoctorWithFixes } = await import("./config-doctor-1j77p1jy.js");
17157
+ const { runConfigDoctorWithFixes } = await import("./config-doctor-g29kxhek.js");
17158
17158
  const fixResult = await runConfigDoctorWithFixes(directory, config, true);
17159
17159
  output = formatDoctorMarkdown(fixResult.result);
17160
17160
  } else {
@@ -20521,7 +20521,7 @@ ${USAGE7}`;
20521
20521
 
20522
20522
  // src/commands/memory.ts
20523
20523
  import { existsSync as existsSync27 } from "fs";
20524
- import * as path48 from "path";
20524
+ import * as path50 from "path";
20525
20525
  import { fileURLToPath as fileURLToPath2 } from "url";
20526
20526
 
20527
20527
  // src/memory/config.ts
@@ -20556,6 +20556,24 @@ var DEFAULT_CONSOLIDATION_CONFIG = {
20556
20556
  autoApplyMinConfidence: 0.6,
20557
20557
  decayHalfLifeDays: { ...DEFAULT_DECAY_HALF_LIFE_DAYS }
20558
20558
  };
20559
+ var DEFAULT_EMBEDDINGS_CONFIG = {
20560
+ enabled: false,
20561
+ model: "Xenova/all-MiniLM-L6-v2",
20562
+ dimension: 384,
20563
+ cacheSize: 256
20564
+ };
20565
+ var DEFAULT_RETRIEVAL_CONFIG = {
20566
+ rrfK: 60,
20567
+ weights: {
20568
+ lexical: 0.5,
20569
+ dense: 0.4,
20570
+ metadata: 0.1
20571
+ },
20572
+ rerank: {
20573
+ enabled: false
20574
+ },
20575
+ latencyBudgetMs: 250
20576
+ };
20559
20577
  var DEFAULT_MEMORY_CONFIG = {
20560
20578
  enabled: false,
20561
20579
  provider: "sqlite",
@@ -20592,6 +20610,8 @@ var DEFAULT_MEMORY_CONFIG = {
20592
20610
  ...DEFAULT_CONSOLIDATION_CONFIG,
20593
20611
  decayHalfLifeDays: { ...DEFAULT_DECAY_HALF_LIFE_DAYS }
20594
20612
  },
20613
+ embeddings: { ...DEFAULT_EMBEDDINGS_CONFIG },
20614
+ retrieval: { ...DEFAULT_RETRIEVAL_CONFIG },
20595
20615
  hardDelete: false
20596
20616
  };
20597
20617
  var DURABLE_MEMORY_KINDS = new Set([
@@ -20648,6 +20668,22 @@ function resolveMemoryConfig(input) {
20648
20668
  ...DEFAULT_MEMORY_CONFIG.consolidation.decayHalfLifeDays,
20649
20669
  ...input?.consolidation?.decayHalfLifeDays ?? {}
20650
20670
  }
20671
+ },
20672
+ embeddings: {
20673
+ ...DEFAULT_MEMORY_CONFIG.embeddings,
20674
+ ...input?.embeddings ?? {}
20675
+ },
20676
+ retrieval: {
20677
+ ...DEFAULT_MEMORY_CONFIG.retrieval,
20678
+ ...input?.retrieval ?? {},
20679
+ weights: {
20680
+ ...DEFAULT_MEMORY_CONFIG.retrieval.weights,
20681
+ ...input?.retrieval?.weights ?? {}
20682
+ },
20683
+ rerank: {
20684
+ ...DEFAULT_MEMORY_CONFIG.retrieval.rerank,
20685
+ ...input?.retrieval?.rerank ?? {}
20686
+ }
20651
20687
  }
20652
20688
  };
20653
20689
  }
@@ -20662,8 +20698,8 @@ class MemoryValidationError extends Error {
20662
20698
  }
20663
20699
  // src/memory/evaluation.ts
20664
20700
  import * as fs19 from "fs/promises";
20665
- import * as os10 from "os";
20666
- import * as path46 from "path";
20701
+ import * as os12 from "os";
20702
+ import * as path48 from "path";
20667
20703
 
20668
20704
  // src/memory/local-jsonl-provider.ts
20669
20705
  import { randomUUID as randomUUID5 } from "crypto";
@@ -21935,18 +21971,372 @@ async function writeJsonlAtomic(filePath, values) {
21935
21971
 
21936
21972
  // src/memory/provider-pool.ts
21937
21973
  import { realpathSync as realpathSync2 } from "fs";
21938
- import * as path45 from "path";
21974
+ import * as path47 from "path";
21939
21975
 
21940
21976
  // src/memory/sqlite-provider.ts
21941
21977
  import { randomUUID as randomUUID6 } from "crypto";
21978
+ import { mkdirSync as mkdirSync17 } from "fs";
21979
+ import { createRequire as createRequire4 } from "module";
21980
+ import * as path46 from "path";
21981
+
21982
+ // src/memory/embeddings/cache.ts
21983
+ var DEFAULT_CACHE_SIZE = 256;
21984
+ function normalizeQuery(query) {
21985
+ return query.toLowerCase().trim();
21986
+ }
21987
+ function compositeKey(modelVersion, normalizedQuery) {
21988
+ return `${modelVersion}\x00${normalizedQuery}`;
21989
+ }
21990
+
21991
+ class EmbeddingCache {
21992
+ cache;
21993
+ maxSize;
21994
+ constructor(maxSize = DEFAULT_CACHE_SIZE) {
21995
+ this.maxSize = maxSize;
21996
+ this.cache = new Map;
21997
+ }
21998
+ get size() {
21999
+ return this.cache.size;
22000
+ }
22001
+ get(modelVersion, query) {
22002
+ const key = compositeKey(modelVersion, normalizeQuery(query));
22003
+ const entry = this.cache.get(key);
22004
+ if (entry !== undefined) {
22005
+ this.cache.delete(key);
22006
+ this.cache.set(key, entry);
22007
+ }
22008
+ return entry;
22009
+ }
22010
+ set(modelVersion, query, entry) {
22011
+ const key = compositeKey(modelVersion, normalizeQuery(query));
22012
+ if (this.cache.has(key)) {
22013
+ this.cache.delete(key);
22014
+ } else if (this.cache.size >= this.maxSize) {
22015
+ const oldestKey = this.cache.keys().next().value;
22016
+ if (oldestKey !== undefined) {
22017
+ this.cache.delete(oldestKey);
22018
+ }
22019
+ }
22020
+ if (this.cache.size < this.maxSize) {
22021
+ this.cache.set(key, entry);
22022
+ }
22023
+ }
22024
+ has(modelVersion, query) {
22025
+ const key = compositeKey(modelVersion, normalizeQuery(query));
22026
+ return this.cache.has(key);
22027
+ }
22028
+ clear() {
22029
+ this.cache.clear();
22030
+ }
22031
+ }
22032
+
22033
+ // src/memory/embeddings/fusion.ts
22034
+ function fuseRankings(lexicalRankedIds, denseRankedIds, metadataRankedIds, weights, rrfK) {
22035
+ const lexicalRanks = buildRankMap(lexicalRankedIds);
22036
+ const denseRanks = buildRankMap(denseRankedIds);
22037
+ const metadataRanks = buildRankMap(metadataRankedIds);
22038
+ const allIds = new Set;
22039
+ for (const id of lexicalRankedIds)
22040
+ allIds.add(id);
22041
+ for (const id of denseRankedIds)
22042
+ allIds.add(id);
22043
+ for (const id of metadataRankedIds)
22044
+ allIds.add(id);
22045
+ const candidates = [];
22046
+ for (const id of allIds) {
22047
+ const lexicalRank = lexicalRanks.get(id) ?? null;
22048
+ const denseRank = denseRanks.get(id) ?? null;
22049
+ const metadataRank = metadataRanks.get(id) ?? null;
22050
+ const rawScore = (lexicalRank !== null ? weights.lexical * rrfTerm(lexicalRank, rrfK) : 0) + (denseRank !== null ? weights.dense * rrfTerm(denseRank, rrfK) : 0) + (metadataRank !== null ? weights.metadata * rrfTerm(metadataRank, rrfK) : 0);
22051
+ candidates.push({
22052
+ id,
22053
+ fusedScore: rawScore,
22054
+ lexicalRank,
22055
+ denseRank,
22056
+ metadataRank
22057
+ });
22058
+ }
22059
+ return minMaxNormalise(candidates);
22060
+ }
22061
+ function buildRankMap(rankedIds) {
22062
+ const map = new Map;
22063
+ for (let i = 0;i < rankedIds.length; i++) {
22064
+ map.set(rankedIds[i], i + 1);
22065
+ }
22066
+ return map;
22067
+ }
22068
+ function rrfTerm(rank, rrfK) {
22069
+ return 1 / (rrfK + rank);
22070
+ }
22071
+ function minMaxNormalise(candidates) {
22072
+ if (candidates.length === 0)
22073
+ return candidates;
22074
+ let min = Infinity;
22075
+ let max = -Infinity;
22076
+ for (const c of candidates) {
22077
+ if (c.fusedScore < min)
22078
+ min = c.fusedScore;
22079
+ if (c.fusedScore > max)
22080
+ max = c.fusedScore;
22081
+ }
22082
+ const range = max - min;
22083
+ const normalised = [];
22084
+ for (const c of candidates) {
22085
+ const normalisedScore = range === 0 ? 1 : (c.fusedScore - min) / range;
22086
+ normalised.push({
22087
+ ...c,
22088
+ fusedScore: normalisedScore
22089
+ });
22090
+ }
22091
+ normalised.sort((a, b) => b.fusedScore - a.fusedScore || a.id.localeCompare(b.id));
22092
+ return normalised;
22093
+ }
22094
+
22095
+ // src/memory/embeddings/local-provider.ts
21942
22096
  import { mkdirSync as mkdirSync15 } from "fs";
21943
22097
  import { createRequire as createRequire2 } from "module";
22098
+ import * as os10 from "os";
22099
+ import * as path43 from "path";
22100
+
22101
+ // src/memory/embeddings/types.ts
22102
+ class EmbeddingUnavailableError extends Error {
22103
+ constructor(message) {
22104
+ super(message ?? "Embedding provider is unavailable (dependency not installed or model failed to load)");
22105
+ this.name = "EmbeddingUnavailableError";
22106
+ }
22107
+ }
22108
+
22109
+ class EmbeddingVersionMismatchError extends Error {
22110
+ queryVersion;
22111
+ storedVersion;
22112
+ constructor(queryVersion, storedVersion) {
22113
+ super(`Embedding version mismatch: query uses ${queryVersion} but stored vectors are ${storedVersion}. Rebuild the index or pin the model version.`);
22114
+ this.name = "EmbeddingVersionMismatchError";
22115
+ this.queryVersion = queryVersion;
22116
+ this.storedVersion = storedVersion;
22117
+ }
22118
+ }
22119
+
22120
+ // src/memory/embeddings/local-provider.ts
22121
+ var _internals33 = {
22122
+ resolveEmbeddingCacheDir() {
22123
+ let base;
22124
+ if (process.platform === "win32") {
22125
+ base = process.env.LOCALAPPDATA || path43.join(os10.homedir(), "AppData", "Local");
22126
+ } else if (process.platform === "darwin") {
22127
+ base = path43.join(os10.homedir(), "Library", "Caches");
22128
+ } else {
22129
+ base = process.env.XDG_CACHE_HOME || path43.join(os10.homedir(), ".cache");
22130
+ }
22131
+ const resolved = path43.join(base, "opencode", "embeddings");
22132
+ const segments = resolved.split(path43.sep);
22133
+ if (segments.includes(".swarm")) {
22134
+ const safeDefault = process.platform === "win32" ? path43.join(os10.homedir(), "AppData", "Local", "opencode", "embeddings") : process.platform === "darwin" ? path43.join(os10.homedir(), "Library", "Caches", "opencode", "embeddings") : path43.join(os10.homedir(), ".cache", "opencode", "embeddings");
22135
+ warn("Embedding cache dir resolved under .swarm/ \u2014 falling back to safe default");
22136
+ return safeDefault;
22137
+ }
22138
+ return resolved;
22139
+ }
22140
+ };
22141
+ function resolveEmbeddingCacheDir() {
22142
+ return _internals33.resolveEmbeddingCacheDir();
22143
+ }
22144
+
22145
+ class LocalEmbeddingProvider {
22146
+ modelName;
22147
+ dimension;
22148
+ modelVersion;
22149
+ _available = false;
22150
+ loadFailed = false;
22151
+ pipeline = null;
22152
+ static downloadNoticePrinted = false;
22153
+ constructor(config) {
22154
+ this.modelName = config.model;
22155
+ this.dimension = config.dimension;
22156
+ this.modelVersion = config.version ?? `${config.model}:${config.dimension}`;
22157
+ }
22158
+ get available() {
22159
+ return this._available;
22160
+ }
22161
+ async ensurePipeline() {
22162
+ if (this.loadFailed) {
22163
+ return null;
22164
+ }
22165
+ if (this.pipeline)
22166
+ return this.pipeline;
22167
+ try {
22168
+ const req = createRequire2(import.meta.url);
22169
+ const transformers = req("@xenova/transformers");
22170
+ if (!LocalEmbeddingProvider.downloadNoticePrinted) {
22171
+ LocalEmbeddingProvider.downloadNoticePrinted = true;
22172
+ console.log(`[opencode-swarm] Downloading embedding model "${this.modelName}" (~25 MB) \u2014 this happens once per process.`);
22173
+ }
22174
+ const cacheDir2 = resolveEmbeddingCacheDir();
22175
+ mkdirSync15(cacheDir2, { recursive: true });
22176
+ this.pipeline = await transformers.pipeline("feature-extraction", this.modelName, { cache_dir: cacheDir2 });
22177
+ this._available = true;
22178
+ return this.pipeline;
22179
+ } catch (err) {
22180
+ this.loadFailed = true;
22181
+ this._available = false;
22182
+ warn("Local embedding provider unavailable \u2014 falling back to lexical-only", {
22183
+ reason: err instanceof Error ? err.message : String(err)
22184
+ });
22185
+ return null;
22186
+ }
22187
+ }
22188
+ async embed(text) {
22189
+ const pipeline = await this.ensurePipeline();
22190
+ if (!pipeline) {
22191
+ throw new EmbeddingUnavailableError("Embedding provider is unavailable (dependency not installed or model failed to load)");
22192
+ }
22193
+ const result = await pipeline(text, {
22194
+ pooling: "mean",
22195
+ normalize: true
22196
+ });
22197
+ return this.tensorToFloat32Array(result);
22198
+ }
22199
+ async embedBatch(texts) {
22200
+ if (texts.length === 0)
22201
+ return [];
22202
+ const pipeline = await this.ensurePipeline();
22203
+ if (!pipeline) {
22204
+ throw new EmbeddingUnavailableError("Embedding provider is unavailable (dependency not installed or model failed to load)");
22205
+ }
22206
+ const result = await pipeline(texts, {
22207
+ pooling: "mean",
22208
+ normalize: true
22209
+ });
22210
+ if (Array.isArray(result)) {
22211
+ return result.map((t) => this.tensorToFloat32Array(t));
22212
+ }
22213
+ return this.tensorToFloat32ArrayBatch(result);
22214
+ }
22215
+ tensorToFloat32Array(tensor) {
22216
+ if (tensor instanceof Float32Array)
22217
+ return tensor;
22218
+ const obj = tensor;
22219
+ if (obj?.data && obj.data instanceof Float32Array) {
22220
+ return obj.data;
22221
+ }
22222
+ const entries = Object.entries(tensor);
22223
+ for (const [, value] of entries) {
22224
+ if (value instanceof Float32Array)
22225
+ return value;
22226
+ }
22227
+ throw new Error(`Unexpected embedding tensor shape: ${JSON.stringify(tensor)}`);
22228
+ }
22229
+ tensorToFloat32ArrayBatch(tensor) {
22230
+ const obj = tensor;
22231
+ if (obj?.data && obj.data instanceof Float32Array && obj.dims && obj.dims.length >= 2) {
22232
+ const batchSize = obj.dims[0];
22233
+ const dim = obj.dims[1];
22234
+ const result = [];
22235
+ for (let i = 0;i < batchSize; i++) {
22236
+ const offset = i * dim;
22237
+ result.push(obj.data.slice(offset, offset + dim));
22238
+ }
22239
+ return result;
22240
+ }
22241
+ if (Array.isArray(tensor)) {
22242
+ return tensor.map((t) => this.tensorToFloat32Array(t));
22243
+ }
22244
+ throw new Error(`Unexpected batch embedding tensor shape: ${JSON.stringify(tensor)}`);
22245
+ }
22246
+ }
22247
+
22248
+ // src/memory/embeddings/reranker.ts
22249
+ import { mkdirSync as mkdirSync16 } from "fs";
22250
+ import { createRequire as createRequire3 } from "module";
22251
+ import * as os11 from "os";
21944
22252
  import * as path44 from "path";
22253
+ function shouldRerank(previousRecallElapsedMs, latencyBudgetMs) {
22254
+ return previousRecallElapsedMs <= latencyBudgetMs;
22255
+ }
22256
+
22257
+ class CrossEncoderReranker {
22258
+ options;
22259
+ loadFailed = false;
22260
+ _available = false;
22261
+ pipeline = null;
22262
+ constructor(options) {
22263
+ this.options = options;
22264
+ }
22265
+ get available() {
22266
+ return this._available;
22267
+ }
22268
+ async ensurePipeline() {
22269
+ if (this.loadFailed)
22270
+ return null;
22271
+ if (this.pipeline)
22272
+ return this.pipeline;
22273
+ try {
22274
+ const req = createRequire3(import.meta.url);
22275
+ const transformers = req("@xenova/transformers");
22276
+ const modelName = this.options.model ?? "Xenova/ms-marco-MiniLM-L-6-v2";
22277
+ const cacheDir2 = resolveRerankerCacheDir();
22278
+ mkdirSync16(cacheDir2, { recursive: true });
22279
+ this.pipeline = await transformers.pipeline("text-classification", modelName, { cache_dir: cacheDir2 });
22280
+ this._available = true;
22281
+ return this.pipeline;
22282
+ } catch (err) {
22283
+ this.loadFailed = true;
22284
+ this._available = false;
22285
+ warn("Cross-encoder reranker unavailable \u2014 skipping rerank", {
22286
+ reason: err instanceof Error ? err.message : String(err)
22287
+ });
22288
+ return null;
22289
+ }
22290
+ }
22291
+ async rerank(candidates, query, topN) {
22292
+ if (candidates.length === 0)
22293
+ return candidates;
22294
+ const pipeline = await this.ensurePipeline();
22295
+ if (!pipeline)
22296
+ return candidates;
22297
+ try {
22298
+ const inputs = candidates.map((c) => [query, c.text]);
22299
+ const results = await pipeline(inputs, { truncation: true });
22300
+ const scored = candidates.map((c, idx) => ({
22301
+ ...c,
22302
+ score: results[idx]?.score ?? 0
22303
+ }));
22304
+ scored.sort((a, b) => (b.score ?? 0) - (a.score ?? 0));
22305
+ if (typeof topN === "number" && topN > 0) {
22306
+ return scored.slice(0, topN);
22307
+ }
22308
+ return scored;
22309
+ } catch (err) {
22310
+ warn("Rerank scoring failed \u2014 returning original order", {
22311
+ reason: err instanceof Error ? err.message : String(err)
22312
+ });
22313
+ return candidates;
22314
+ }
22315
+ }
22316
+ }
22317
+ function resolveRerankerCacheDir() {
22318
+ let base;
22319
+ if (process.platform === "win32") {
22320
+ base = process.env.LOCALAPPDATA || path44.join(os11.homedir(), "AppData", "Local");
22321
+ } else if (process.platform === "darwin") {
22322
+ base = path44.join(os11.homedir(), "Library", "Caches");
22323
+ } else {
22324
+ base = process.env.XDG_CACHE_HOME || path44.join(os11.homedir(), ".cache");
22325
+ }
22326
+ const resolved = path44.join(base, "opencode", "embeddings");
22327
+ const segments = resolved.split(path44.sep);
22328
+ if (segments.includes(".swarm")) {
22329
+ const safeDefault = process.platform === "win32" ? path44.join(os11.homedir(), "AppData", "Local", "opencode", "embeddings") : process.platform === "darwin" ? path44.join(os11.homedir(), "Library", "Caches", "opencode", "embeddings") : path44.join(os11.homedir(), ".cache", "opencode", "embeddings");
22330
+ warn("Reranker cache dir resolved under .swarm/ \u2014 falling back to safe default");
22331
+ return safeDefault;
22332
+ }
22333
+ return resolved;
22334
+ }
21945
22335
 
21946
22336
  // src/memory/jsonl-migration.ts
21947
22337
  import { existsSync as existsSync26, renameSync as renameSync10, unlinkSync as unlinkSync7 } from "fs";
21948
22338
  import { copyFile as copyFile2, mkdir as mkdir11, readFile as readFile13, stat as stat5, writeFile as writeFile11 } from "fs/promises";
21949
- import * as path43 from "path";
22339
+ import * as path45 from "path";
21950
22340
  var LEGACY_JSONL_MIGRATION_VERSION = 2;
21951
22341
  var LEGACY_JSONL_MIGRATION_NAME = "legacy_jsonl_import_complete";
21952
22342
  function resolveMemoryStorageDir(rootDirectory, config = {}) {
@@ -21962,8 +22352,8 @@ function resolveSqliteDatabasePath(rootDirectory, config = {}) {
21962
22352
  async function readLegacyJsonl(rootDirectory, config = {}) {
21963
22353
  const resolved = resolveConfig(config);
21964
22354
  const storageDir = resolveMemoryStorageDir(rootDirectory, resolved);
21965
- const memoryLoad = await readMemoryJsonl(path43.join(storageDir, "memories.jsonl"), resolved);
21966
- const proposalLoad = await readProposalJsonl(path43.join(storageDir, "proposals.jsonl"), resolved);
22355
+ const memoryLoad = await readMemoryJsonl(path45.join(storageDir, "memories.jsonl"), resolved);
22356
+ const proposalLoad = await readProposalJsonl(path45.join(storageDir, "proposals.jsonl"), resolved);
21967
22357
  return {
21968
22358
  memories: memoryLoad.records,
21969
22359
  proposals: proposalLoad.records,
@@ -21973,14 +22363,14 @@ async function readLegacyJsonl(rootDirectory, config = {}) {
21973
22363
  }
21974
22364
  async function backupLegacyJsonl(rootDirectory, config = {}) {
21975
22365
  const storageDir = resolveMemoryStorageDir(rootDirectory, config);
21976
- const backupDir = path43.join(storageDir, "backups");
22366
+ const backupDir = path45.join(storageDir, "backups");
21977
22367
  await mkdir11(backupDir, { recursive: true });
21978
22368
  const results = [];
21979
22369
  for (const filename of ["memories.jsonl", "proposals.jsonl"]) {
21980
- const source = path43.join(storageDir, filename);
22370
+ const source = path45.join(storageDir, filename);
21981
22371
  if (!existsSync26(source))
21982
22372
  continue;
21983
- const backup = path43.join(backupDir, `${filename}.pre-sqlite-migration`);
22373
+ const backup = path45.join(backupDir, `${filename}.pre-sqlite-migration`);
21984
22374
  if (existsSync26(backup)) {
21985
22375
  results.push({ source, backup, created: false });
21986
22376
  continue;
@@ -21991,11 +22381,11 @@ async function backupLegacyJsonl(rootDirectory, config = {}) {
21991
22381
  return results;
21992
22382
  }
21993
22383
  async function writeJsonlExport(rootDirectory, config, memories, proposals) {
21994
- const exportDir = path43.join(resolveMemoryStorageDir(rootDirectory, config), "export");
22384
+ const exportDir = path45.join(resolveMemoryStorageDir(rootDirectory, config), "export");
21995
22385
  await mkdir11(exportDir, { recursive: true });
21996
- const memoriesPath = path43.join(exportDir, "memories.jsonl");
21997
- const proposalsPath = path43.join(exportDir, "proposals.jsonl");
21998
- const memoriesTempPath = path43.join(path43.dirname(memoriesPath), `${path43.basename(memoriesPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
22386
+ const memoriesPath = path45.join(exportDir, "memories.jsonl");
22387
+ const proposalsPath = path45.join(exportDir, "proposals.jsonl");
22388
+ const memoriesTempPath = path45.join(path45.dirname(memoriesPath), `${path45.basename(memoriesPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
21999
22389
  try {
22000
22390
  await writeFile11(memoriesTempPath, toJsonl(memories), "utf-8");
22001
22391
  renameSync10(memoriesTempPath, memoriesPath);
@@ -22005,7 +22395,7 @@ async function writeJsonlExport(rootDirectory, config, memories, proposals) {
22005
22395
  } catch {}
22006
22396
  throw err;
22007
22397
  }
22008
- const proposalsTempPath = path43.join(path43.dirname(proposalsPath), `${path43.basename(proposalsPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
22398
+ const proposalsTempPath = path45.join(path45.dirname(proposalsPath), `${path45.basename(proposalsPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
22009
22399
  try {
22010
22400
  await writeFile11(proposalsTempPath, toJsonl(proposals), "utf-8");
22011
22401
  renameSync10(proposalsTempPath, proposalsPath);
@@ -22018,9 +22408,9 @@ async function writeJsonlExport(rootDirectory, config, memories, proposals) {
22018
22408
  return { directory: exportDir, memoriesPath, proposalsPath };
22019
22409
  }
22020
22410
  async function writeMigrationReport(rootDirectory, report, config = {}) {
22021
- const reportPath = path43.join(resolveMemoryStorageDir(rootDirectory, config), "migration-report.json");
22022
- await mkdir11(path43.dirname(reportPath), { recursive: true });
22023
- const reportTempPath = path43.join(path43.dirname(reportPath), `${path43.basename(reportPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
22411
+ const reportPath = path45.join(resolveMemoryStorageDir(rootDirectory, config), "migration-report.json");
22412
+ await mkdir11(path45.dirname(reportPath), { recursive: true });
22413
+ const reportTempPath = path45.join(path45.dirname(reportPath), `${path45.basename(reportPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
22024
22414
  try {
22025
22415
  await writeFile11(reportTempPath, `${JSON.stringify(report, null, 2)}
22026
22416
  `, "utf-8");
@@ -22034,7 +22424,7 @@ async function writeMigrationReport(rootDirectory, report, config = {}) {
22034
22424
  return reportPath;
22035
22425
  }
22036
22426
  async function readMigrationReport(rootDirectory, config = {}) {
22037
- const reportPath = path43.join(resolveMemoryStorageDir(rootDirectory, config), "migration-report.json");
22427
+ const reportPath = path45.join(resolveMemoryStorageDir(rootDirectory, config), "migration-report.json");
22038
22428
  if (!existsSync26(reportPath))
22039
22429
  return null;
22040
22430
  try {
@@ -22047,7 +22437,7 @@ async function getLegacyJsonlFileStatus(rootDirectory, config = {}) {
22047
22437
  const storageDir = resolveMemoryStorageDir(rootDirectory, config);
22048
22438
  const statuses = [];
22049
22439
  for (const file of ["memories.jsonl", "proposals.jsonl"]) {
22050
- const filePath = path43.join(storageDir, file);
22440
+ const filePath = path45.join(storageDir, file);
22051
22441
  let sizeBytes = 0;
22052
22442
  if (existsSync26(filePath)) {
22053
22443
  sizeBytes = (await stat5(filePath)).size;
@@ -22171,7 +22561,7 @@ var _DatabaseCtor2 = null;
22171
22561
  function loadDatabaseCtor2() {
22172
22562
  if (_DatabaseCtor2)
22173
22563
  return _DatabaseCtor2;
22174
- const req = createRequire2(import.meta.url);
22564
+ const req = createRequire4(import.meta.url);
22175
22565
  _DatabaseCtor2 = req("bun:sqlite").Database;
22176
22566
  return _DatabaseCtor2;
22177
22567
  }
@@ -22291,6 +22681,16 @@ var MIGRATIONS2 = [
22291
22681
  CREATE INDEX IF NOT EXISTS idx_memory_recall_usage_timestamp
22292
22682
  ON memory_recall_usage(timestamp DESC);
22293
22683
  `
22684
+ },
22685
+ {
22686
+ version: 6,
22687
+ name: "create_embedding_config_table",
22688
+ sql: `
22689
+ CREATE TABLE IF NOT EXISTS embedding_config (
22690
+ key TEXT PRIMARY KEY,
22691
+ value TEXT
22692
+ );
22693
+ `
22294
22694
  }
22295
22695
  ];
22296
22696
 
@@ -22302,6 +22702,10 @@ class SQLiteMemoryProvider {
22302
22702
  initPromise = null;
22303
22703
  db = null;
22304
22704
  ftsAvailable = false;
22705
+ vecAvailable = false;
22706
+ embeddingProvider = null;
22707
+ embeddingCache = null;
22708
+ reranker = null;
22305
22709
  memories = new Map;
22306
22710
  proposals = new Map;
22307
22711
  lastAutomaticJsonlMigration = null;
@@ -22355,7 +22759,7 @@ class SQLiteMemoryProvider {
22355
22759
  }
22356
22760
  async doInitialize() {
22357
22761
  const dbPath = this.databasePath();
22358
- mkdirSync15(path44.dirname(dbPath), { recursive: true });
22762
+ mkdirSync17(path46.dirname(dbPath), { recursive: true });
22359
22763
  const Db = loadDatabaseCtor2();
22360
22764
  this.db = new Db(dbPath);
22361
22765
  this.db.run("PRAGMA journal_mode = WAL;");
@@ -22366,6 +22770,29 @@ class SQLiteMemoryProvider {
22366
22770
  this.runMigrations();
22367
22771
  this.backfillScopeKeys();
22368
22772
  this.ftsAvailable = this.initializeFtsIndex();
22773
+ this.initializeVecExtension();
22774
+ if (this.config.embeddings.enabled && !this.embeddingProvider) {
22775
+ try {
22776
+ this.embeddingProvider = new LocalEmbeddingProvider({
22777
+ model: this.config.embeddings.model,
22778
+ dimension: this.config.embeddings.dimension,
22779
+ version: this.config.embeddings.version
22780
+ });
22781
+ } catch (err) {
22782
+ this.embeddingProvider = null;
22783
+ warn("Failed to construct embedding provider \u2014 dense retrieval disabled", {
22784
+ reason: err instanceof Error ? err.message : String(err)
22785
+ });
22786
+ }
22787
+ try {
22788
+ this.embeddingCache = new EmbeddingCache(this.config.embeddings.cacheSize);
22789
+ } catch (err) {
22790
+ this.embeddingCache = null;
22791
+ warn("Failed to construct embedding cache \u2014 recall works without cache", {
22792
+ reason: err instanceof Error ? err.message : String(err)
22793
+ });
22794
+ }
22795
+ }
22369
22796
  this.lastAutomaticJsonlMigration = null;
22370
22797
  await this.migrateLegacyJsonlIfNeeded();
22371
22798
  const memoryLoad = this.loadMemories();
@@ -22392,6 +22819,7 @@ class SQLiteMemoryProvider {
22392
22819
  }, { rejectDurableSecrets: this.config.redaction.rejectDurableSecrets });
22393
22820
  this.memories.set(next.id, next);
22394
22821
  this.writeMemory(next);
22822
+ await this.writeMemoryVec(next);
22395
22823
  await this.event("upsert", next.id);
22396
22824
  return next;
22397
22825
  }
@@ -22408,6 +22836,7 @@ class SQLiteMemoryProvider {
22408
22836
  this.memories.delete(id);
22409
22837
  this.requireDb().run("DELETE FROM memory_items WHERE id = ?", [id]);
22410
22838
  this.deleteMemoryFts(id);
22839
+ this.deleteMemoryVec(id);
22411
22840
  } else {
22412
22841
  const tombstone = {
22413
22842
  ...existing,
@@ -22424,20 +22853,139 @@ class SQLiteMemoryProvider {
22424
22853
  }
22425
22854
  async recallWithDiagnostics(request) {
22426
22855
  await this.initialize();
22856
+ if (!this.config.embeddings.enabled || !this.vecAvailable || !this.embeddingProvider) {
22857
+ const scopedRecords2 = await this.list({
22858
+ scopes: request.scopes,
22859
+ kinds: request.kinds,
22860
+ includeExpired: request.includeExpired,
22861
+ limit: RECALL_CANDIDATE_LIMIT
22862
+ });
22863
+ const candidates = this.selectRecallCandidates(request, scopedRecords2);
22864
+ const result = scoreMemoryRecordsWithDiagnostics(candidates.records, request);
22865
+ const reranked = candidates.ftsOrder ? rerankWithFts(result.items, candidates.ftsOrder) : result.items;
22866
+ return {
22867
+ items: reranked.slice(0, request.maxItems),
22868
+ diagnostics: {
22869
+ ...result.diagnostics,
22870
+ returnedCount: Math.min(reranked.length, request.maxItems)
22871
+ }
22872
+ };
22873
+ }
22874
+ const recallElapsedStart = Date.now();
22427
22875
  const scopedRecords = await this.list({
22428
22876
  scopes: request.scopes,
22429
22877
  kinds: request.kinds,
22430
22878
  includeExpired: request.includeExpired,
22431
22879
  limit: RECALL_CANDIDATE_LIMIT
22432
22880
  });
22433
- const candidates = this.selectRecallCandidates(request, scopedRecords);
22434
- const result = scoreMemoryRecordsWithDiagnostics(candidates.records, request);
22435
- const reranked = candidates.ftsOrder ? rerankWithFts(result.items, candidates.ftsOrder) : result.items;
22881
+ const lexicalCandidates = this.selectRecallCandidates(request, scopedRecords);
22882
+ const lexicalResult = scoreMemoryRecordsWithDiagnostics(lexicalCandidates.records, request);
22883
+ const lexicalReranked = lexicalCandidates.ftsOrder ? rerankWithFts(lexicalResult.items, lexicalCandidates.ftsOrder) : lexicalResult.items;
22884
+ const lexicalIds = lexicalReranked.map((item) => item.record.id);
22885
+ let denseIds = [];
22886
+ try {
22887
+ const modelVersion = this.embeddingProvider.modelVersion;
22888
+ const normalizedQuery = normalizeMemoryText(request.query).toLowerCase();
22889
+ let queryEmbedding = this.embeddingCache?.get(modelVersion, normalizedQuery)?.vector ?? null;
22890
+ if (queryEmbedding === null) {
22891
+ queryEmbedding = await this.embeddingProvider.embed(normalizedQuery);
22892
+ this.embeddingCache?.set(modelVersion, normalizedQuery, {
22893
+ vector: queryEmbedding,
22894
+ modelVersion,
22895
+ queryHash: normalizedQuery
22896
+ });
22897
+ }
22898
+ const denseRecords = await this.selectDenseCandidates(request, queryEmbedding);
22899
+ denseIds = denseRecords.map((record) => record.id);
22900
+ } catch (err) {
22901
+ if (err instanceof EmbeddingVersionMismatchError || err instanceof EmbeddingUnavailableError) {
22902
+ warn("Dense retrieval failed \u2014 falling back to lexical-only", {
22903
+ reason: err instanceof Error ? err.message : String(err)
22904
+ });
22905
+ } else {
22906
+ warn("Dense retrieval failed \u2014 falling back to lexical-only", {
22907
+ reason: err instanceof Error ? err.message : String(err)
22908
+ });
22909
+ }
22910
+ return {
22911
+ items: lexicalReranked.slice(0, request.maxItems),
22912
+ diagnostics: {
22913
+ ...lexicalResult.diagnostics,
22914
+ returnedCount: Math.min(lexicalReranked.length, request.maxItems)
22915
+ }
22916
+ };
22917
+ }
22918
+ const metadataIds = buildMetadataRankedIds(lexicalReranked, request);
22919
+ const weights = this.config.retrieval.weights;
22920
+ const rrfK = this.config.retrieval.rrfK;
22921
+ const fused = fuseRankings(lexicalIds, denseIds, metadataIds, weights, rrfK);
22922
+ const lexicalItemMap = new Map(lexicalReranked.map((item) => [item.record.id, item]));
22923
+ const minScore = request.minScore ?? this.config.recall.minScore;
22924
+ const fusedItems = [];
22925
+ for (const candidate of fused) {
22926
+ if (candidate.fusedScore < minScore)
22927
+ continue;
22928
+ const lexicalItem = lexicalItemMap.get(candidate.id);
22929
+ if (lexicalItem) {
22930
+ fusedItems.push({
22931
+ record: lexicalItem.record,
22932
+ score: candidate.fusedScore,
22933
+ reason: `${lexicalItem.reason}, rrf_fused=${candidate.fusedScore.toFixed(4)}`,
22934
+ signals: lexicalItem.signals
22935
+ });
22936
+ } else {
22937
+ const record = this.memories.get(candidate.id);
22938
+ if (record) {
22939
+ fusedItems.push({
22940
+ record,
22941
+ score: candidate.fusedScore,
22942
+ reason: `rrf_fused=${candidate.fusedScore.toFixed(4)}`,
22943
+ signals: {
22944
+ textOverlap: 0,
22945
+ tagOverlap: 0,
22946
+ fileOverlap: 0,
22947
+ symbolOverlap: 0,
22948
+ kindMatch: false,
22949
+ scopeMatch: false
22950
+ }
22951
+ });
22952
+ }
22953
+ }
22954
+ }
22955
+ const previousRecallElapsedMs = Date.now() - recallElapsedStart;
22956
+ let rerankedItems = fusedItems;
22957
+ if (this.config.retrieval.rerank.enabled && shouldRerank(previousRecallElapsedMs, this.config.retrieval.latencyBudgetMs)) {
22958
+ try {
22959
+ if (!this.reranker) {
22960
+ this.reranker = new CrossEncoderReranker({
22961
+ model: this.config.retrieval.rerank.model
22962
+ });
22963
+ }
22964
+ const topN = Math.min(20, fusedItems.length);
22965
+ const rerankCandidates = fusedItems.slice(0, topN).map((item) => ({
22966
+ id: item.record.id,
22967
+ text: item.record.text,
22968
+ score: item.score
22969
+ }));
22970
+ const rerankResult = await this.reranker.rerank(rerankCandidates, request.query, topN);
22971
+ const topNPrefix = fusedItems.slice(0, topN);
22972
+ const tail = fusedItems.slice(topN);
22973
+ const rerankOrder = new Map(rerankResult.map((c, idx) => [c.id, idx]));
22974
+ const reorderedTopN = [...topNPrefix].sort((a, b) => (rerankOrder.get(a.record.id) ?? 0) - (rerankOrder.get(b.record.id) ?? 0));
22975
+ rerankedItems = [...reorderedTopN, ...tail];
22976
+ } catch (err) {
22977
+ warn("Rerank failed \u2014 returning fused order", {
22978
+ reason: err instanceof Error ? err.message : String(err)
22979
+ });
22980
+ rerankedItems = fusedItems;
22981
+ }
22982
+ }
22436
22983
  return {
22437
- items: reranked.slice(0, request.maxItems),
22984
+ items: rerankedItems.slice(0, request.maxItems),
22438
22985
  diagnostics: {
22439
- ...result.diagnostics,
22440
- returnedCount: Math.min(reranked.length, request.maxItems)
22986
+ ...lexicalResult.diagnostics,
22987
+ returnedCount: Math.min(rerankedItems.length, request.maxItems),
22988
+ fusionActive: true
22441
22989
  }
22442
22990
  };
22443
22991
  }
@@ -22594,6 +23142,11 @@ class SQLiteMemoryProvider {
22594
23142
  for (const memory of result.memories) {
22595
23143
  this.memories.set(memory.id, memory);
22596
23144
  }
23145
+ for (const memory of result.memories) {
23146
+ if (memory.metadata.deleted !== true) {
23147
+ await this.writeMemoryVec(memory);
23148
+ }
23149
+ }
22597
23150
  return result.change;
22598
23151
  }
22599
23152
  close() {
@@ -22606,6 +23159,46 @@ class SQLiteMemoryProvider {
22606
23159
  this.initPromise = null;
22607
23160
  this.lastAutomaticJsonlMigration = null;
22608
23161
  }
23162
+ async rebuildEmbeddingIndex() {
23163
+ await this.initialize();
23164
+ if (!this.vecAvailable || !this.embeddingProvider) {
23165
+ warn("rebuildEmbeddingIndex skipped \u2014 sqlite-vec or embedding provider not available");
23166
+ return;
23167
+ }
23168
+ const currentVersion = this.embeddingProvider.modelVersion;
23169
+ const durableRecords = Array.from(this.memories.values()).filter((record) => DURABLE_MEMORY_KINDS.has(record.kind) && record.metadata.deleted !== true && record.supersededBy === undefined && record.stability !== "ephemeral");
23170
+ let successCount = 0;
23171
+ let failureCount = 0;
23172
+ const db = this.requireDb();
23173
+ for (const record of durableRecords) {
23174
+ try {
23175
+ const normalizedText = normalizeMemoryText(record.text).toLowerCase();
23176
+ if (normalizedText.length === 0)
23177
+ continue;
23178
+ const vector = await this.embeddingProvider.embed(normalizedText);
23179
+ db.run("INSERT OR REPLACE INTO memory_items_vec (id, embedding) VALUES (?, ?)", [record.id, vector]);
23180
+ successCount++;
23181
+ } catch (err) {
23182
+ const reason = err instanceof Error ? err.message : String(err);
23183
+ warn("rebuildEmbeddingIndex: failed to embed record", {
23184
+ id: record.id,
23185
+ reason
23186
+ });
23187
+ failureCount++;
23188
+ }
23189
+ }
23190
+ if (failureCount === 0) {
23191
+ db.run("INSERT OR REPLACE INTO embedding_config (key, value) VALUES (?, ?)", ["model_version", currentVersion]);
23192
+ }
23193
+ this.embeddingCache?.clear();
23194
+ if (failureCount > 0) {
23195
+ warn("rebuildEmbeddingIndex completed with failures", {
23196
+ successCount,
23197
+ failureCount,
23198
+ total: durableRecords.length
23199
+ });
23200
+ }
23201
+ }
22609
23202
  async importJsonl() {
22610
23203
  const wasInitialized = this.initialized;
22611
23204
  await this.initialize();
@@ -22664,6 +23257,7 @@ class SQLiteMemoryProvider {
22664
23257
  for (const id of removeIds) {
22665
23258
  db.run("DELETE FROM memory_items WHERE id = ?", [id]);
22666
23259
  this.deleteMemoryFts(id);
23260
+ this.deleteMemoryVec(id);
22667
23261
  }
22668
23262
  this.insertEvent("compact", "memory_items", "removed deleted, superseded, and expired scratch memories", JSON.stringify(result));
22669
23263
  });
@@ -22710,6 +23304,52 @@ class SQLiteMemoryProvider {
22710
23304
  return { records: scopedRecords, usedFts: false };
22711
23305
  }
22712
23306
  }
23307
+ getStoredModelVersion() {
23308
+ const row = this.requireDb().query(`SELECT value FROM embedding_config WHERE key = 'model_version' LIMIT 1`).get("model_version");
23309
+ return row?.value ?? null;
23310
+ }
23311
+ async selectDenseCandidates(request, queryEmbedding) {
23312
+ if (!this.config.embeddings.enabled || !this.vecAvailable || !this.embeddingProvider) {
23313
+ return [];
23314
+ }
23315
+ const storedVersion = this.getStoredModelVersion();
23316
+ const queryVersion = this.embeddingProvider.modelVersion;
23317
+ if (storedVersion !== null && storedVersion !== queryVersion) {
23318
+ throw new EmbeddingVersionMismatchError(queryVersion, storedVersion);
23319
+ }
23320
+ const k = Math.max(100, request.maxItems * 20);
23321
+ const rows = this.requireDb().query(`SELECT id, distance FROM memory_items_vec WHERE embedding MATCH ? ORDER BY distance LIMIT ?`).all(queryEmbedding, k);
23322
+ const scopeKeys = request.scopes?.map((s) => stableScopeKey(s)) ?? [];
23323
+ const kinds = request.kinds ?? [];
23324
+ const includeInactive = false;
23325
+ const includeExpired = request.includeExpired ?? false;
23326
+ const allowedIds = new Set;
23327
+ for (const record of this.memories.values()) {
23328
+ if (scopeKeys.length > 0 && !scopeKeys.includes(stableScopeKey(record.scope)))
23329
+ continue;
23330
+ if (kinds.length > 0 && !kinds.includes(record.kind))
23331
+ continue;
23332
+ if (!includeInactive && record.supersededBy)
23333
+ continue;
23334
+ if (!includeInactive && record.metadata.deleted === true)
23335
+ continue;
23336
+ if (!includeExpired && record.expiresAt) {
23337
+ const expires = Date.parse(record.expiresAt);
23338
+ if (Number.isFinite(expires) && expires <= Date.now())
23339
+ continue;
23340
+ }
23341
+ allowedIds.add(record.id);
23342
+ }
23343
+ const results = [];
23344
+ for (const row of rows) {
23345
+ if (!allowedIds.has(row.id))
23346
+ continue;
23347
+ const record = this.memories.get(row.id);
23348
+ if (record)
23349
+ results.push(record);
23350
+ }
23351
+ return results;
23352
+ }
22713
23353
  runMigrations() {
22714
23354
  const db = this.requireDb();
22715
23355
  db.run(`CREATE TABLE IF NOT EXISTS schema_migrations (
@@ -22782,6 +23422,26 @@ class SQLiteMemoryProvider {
22782
23422
  return false;
22783
23423
  }
22784
23424
  }
23425
+ initializeVecExtension() {
23426
+ const db = this.requireDb();
23427
+ try {
23428
+ const dimension = Math.max(1, Math.trunc(this.config.embeddings.dimension ?? 384));
23429
+ const req = createRequire4(import.meta.url);
23430
+ const pkgDir = path46.dirname(req.resolve("@sqlite/sqlite-vec/package.json"));
23431
+ const ext = process.platform === "win32" ? ".dll" : process.platform === "darwin" ? ".dylib" : ".so";
23432
+ const vec0Path = path46.join(pkgDir, `vec0${ext}`);
23433
+ db.loadExtension(vec0Path);
23434
+ db.run(`CREATE VIRTUAL TABLE IF NOT EXISTS memory_items_vec USING vec0(
23435
+ id TEXT PRIMARY KEY, embedding FLOAT[${dimension}]
23436
+ )`);
23437
+ const modelVersion = this.config.embeddings.version ?? `${this.config.embeddings.model}:${dimension}`;
23438
+ db.run("INSERT OR IGNORE INTO embedding_config (key, value) VALUES (?, ?)", ["model_version", modelVersion]);
23439
+ this.vecAvailable = true;
23440
+ } catch (err) {
23441
+ this.vecAvailable = false;
23442
+ warn("sqlite-vec extension not available \u2014 dense retrieval disabled", err);
23443
+ }
23444
+ }
22785
23445
  recreateFtsIndex() {
22786
23446
  const db = this.requireDb();
22787
23447
  const recreate = db.transaction(() => {
@@ -22893,6 +23553,34 @@ class SQLiteMemoryProvider {
22893
23553
  this.ftsAvailable = false;
22894
23554
  }
22895
23555
  }
23556
+ async writeMemoryVec(record) {
23557
+ if (!this.config.embeddings.enabled)
23558
+ return;
23559
+ if (!this.vecAvailable)
23560
+ return;
23561
+ if (!this.embeddingProvider)
23562
+ return;
23563
+ if (!DURABLE_MEMORY_KINDS.has(record.kind))
23564
+ return;
23565
+ if (record.stability === "ephemeral")
23566
+ return;
23567
+ const normalizedText = normalizeMemoryText(record.text).toLowerCase();
23568
+ if (normalizedText.length === 0)
23569
+ return;
23570
+ try {
23571
+ const vector = await this.embeddingProvider.embed(normalizedText);
23572
+ this.requireDb().run("INSERT OR REPLACE INTO memory_items_vec (id, embedding) VALUES (?, ?)", [record.id, vector]);
23573
+ } catch (err) {
23574
+ const reason = err instanceof Error ? err.message : String(err);
23575
+ if (err instanceof EmbeddingUnavailableError) {
23576
+ warn("Embedding provider unavailable during write \u2014 skipping vector", {
23577
+ reason
23578
+ });
23579
+ } else {
23580
+ warn("Embedding computation failed \u2014 skipping vector", { reason });
23581
+ }
23582
+ }
23583
+ }
22896
23584
  deleteMemoryFts(id) {
22897
23585
  if (!this.ftsAvailable)
22898
23586
  return;
@@ -22902,6 +23590,13 @@ class SQLiteMemoryProvider {
22902
23590
  this.ftsAvailable = false;
22903
23591
  }
22904
23592
  }
23593
+ deleteMemoryVec(id) {
23594
+ if (!this.vecAvailable)
23595
+ return;
23596
+ try {
23597
+ this.requireDb().run("DELETE FROM memory_items_vec WHERE id = ?", [id]);
23598
+ } catch {}
23599
+ }
22905
23600
  writeProposal(proposal) {
22906
23601
  this.requireDb().run(`INSERT OR REPLACE INTO memory_proposals (
22907
23602
  id,
@@ -23245,6 +23940,29 @@ function rerankWithFts(items, ftsOrder) {
23245
23940
  };
23246
23941
  }).sort((a, b) => b.score - a.score || a.record.id.localeCompare(b.record.id));
23247
23942
  }
23943
+ function buildMetadataRankedIds(lexicalItems, request) {
23944
+ const scopeKeys = request.scopes?.map((s) => stableScopeKey(s)) ?? [];
23945
+ const kinds = new Set(request.kinds ?? []);
23946
+ const hasScopeFilter = scopeKeys.length > 0;
23947
+ const hasKindFilter = kinds.size > 0;
23948
+ const both = [];
23949
+ const scopeOnly = [];
23950
+ const kindOnly = [];
23951
+ const neither = [];
23952
+ for (const item of lexicalItems) {
23953
+ const scopeMatch = !hasScopeFilter || scopeKeys.includes(stableScopeKey(item.record.scope));
23954
+ const kindMatch = !hasKindFilter || kinds.has(item.record.kind);
23955
+ if (scopeMatch && kindMatch)
23956
+ both.push(item.record.id);
23957
+ else if (scopeMatch)
23958
+ scopeOnly.push(item.record.id);
23959
+ else if (kindMatch)
23960
+ kindOnly.push(item.record.id);
23961
+ else
23962
+ neither.push(item.record.id);
23963
+ }
23964
+ return [...both, ...scopeOnly, ...kindOnly, ...neither];
23965
+ }
23248
23966
 
23249
23967
  // src/memory/provider-pool.ts
23250
23968
  var MAX_POOL_SIZE = 16;
@@ -23384,7 +24102,7 @@ function resolvePoolKey(directory) {
23384
24102
  try {
23385
24103
  return realpathSync2(directory);
23386
24104
  } catch {
23387
- return path45.resolve(directory);
24105
+ return path47.resolve(directory);
23388
24106
  }
23389
24107
  }
23390
24108
 
@@ -23456,7 +24174,7 @@ var DEFAULT_MODES = [
23456
24174
  ];
23457
24175
  var DEFAULT_TIMESTAMP = "2026-05-26T12:00:00.000Z";
23458
24176
  async function evaluateMemoryRecallFixtures(options) {
23459
- const fixtureDirectory = path46.resolve(options.fixtureDirectory);
24177
+ const fixtureDirectory = path48.resolve(options.fixtureDirectory);
23460
24178
  const providers = options.providers ?? DEFAULT_PROVIDERS;
23461
24179
  const modes = options.modes ?? DEFAULT_MODES;
23462
24180
  const generatedAt = new Date().toISOString();
@@ -23465,7 +24183,7 @@ async function evaluateMemoryRecallFixtures(options) {
23465
24183
  for (const fixture of fixtures) {
23466
24184
  const materialized = materializeFixture(fixture);
23467
24185
  for (const providerName of providers) {
23468
- const tempRoot = await fs19.realpath(await fs19.mkdtemp(path46.join(os10.tmpdir(), "swarm-memory-eval-")));
24186
+ const tempRoot = await fs19.realpath(await fs19.mkdtemp(path48.join(os12.tmpdir(), "swarm-memory-eval-")));
23469
24187
  const provider = createEvaluationProvider(providerName, tempRoot);
23470
24188
  try {
23471
24189
  await provider.initialize?.();
@@ -23509,7 +24227,7 @@ async function loadRecallEvaluationFixtures(fixtureDirectory) {
23509
24227
  const files = entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort((a, b) => a.localeCompare(b));
23510
24228
  const fixtures = [];
23511
24229
  for (const file of files) {
23512
- const raw = await fs19.readFile(path46.join(fixtureDirectory, file), "utf-8");
24230
+ const raw = await fs19.readFile(path48.join(fixtureDirectory, file), "utf-8");
23513
24231
  fixtures.push(validateFixture(JSON.parse(raw), file));
23514
24232
  }
23515
24233
  return fixtures;
@@ -23786,8 +24504,8 @@ var CuratorOutputMemoryDecisionSchema = exports_external.object({
23786
24504
  }).passthrough();
23787
24505
  // src/memory/consolidation-log.ts
23788
24506
  import { appendFile as appendFile4, mkdir as mkdir12, readFile as readFile15 } from "fs/promises";
23789
- import * as path47 from "path";
23790
- var LOG_RELATIVE_PATH = path47.join("memory", "consolidation-log.jsonl");
24507
+ import * as path49 from "path";
24508
+ var LOG_RELATIVE_PATH = path49.join("memory", "consolidation-log.jsonl");
23791
24509
  async function readConsolidationLog(directory) {
23792
24510
  const filePath = validateSwarmPath(directory, LOG_RELATIVE_PATH);
23793
24511
  let raw;
@@ -23810,7 +24528,7 @@ async function readConsolidationLog(directory) {
23810
24528
  }
23811
24529
 
23812
24530
  // src/commands/memory.ts
23813
- var PACKAGE_ROOT = path48.resolve(resolvePackageRootFromModule(fileURLToPath2(import.meta.url)));
24531
+ var PACKAGE_ROOT = path50.resolve(resolvePackageRootFromModule(fileURLToPath2(import.meta.url)));
23814
24532
  async function handleMemoryCommand(_directory, _args) {
23815
24533
  return [
23816
24534
  "## Swarm Memory",
@@ -24108,7 +24826,7 @@ function resolveCommandMemoryConfig(directory) {
24108
24826
  }
24109
24827
  function parseEvaluateArgs(directory, args) {
24110
24828
  let json = false;
24111
- let fixtureDirectory = path48.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall");
24829
+ let fixtureDirectory = path50.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall");
24112
24830
  for (let i = 0;i < args.length; i++) {
24113
24831
  const arg = args[i];
24114
24832
  if (arg === "--json") {
@@ -24122,10 +24840,10 @@ function parseEvaluateArgs(directory, args) {
24122
24840
  error: "Usage: /swarm memory evaluate [--json] [--fixtures <directory>]"
24123
24841
  };
24124
24842
  }
24125
- const resolvedFixtures = path48.resolve(directory, next);
24126
- const canonical = path48.normalize(resolvedFixtures) + path48.sep;
24127
- const allowedRootA = path48.normalize(directory) + path48.sep;
24128
- const allowedRootB = path48.normalize(path48.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall")) + path48.sep;
24843
+ const resolvedFixtures = path50.resolve(directory, next);
24844
+ const canonical = path50.normalize(resolvedFixtures) + path50.sep;
24845
+ const allowedRootA = path50.normalize(directory) + path50.sep;
24846
+ const allowedRootB = path50.normalize(path50.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall")) + path50.sep;
24129
24847
  if (!canonical.startsWith(allowedRootA) && !canonical.startsWith(allowedRootB)) {
24130
24848
  return {
24131
24849
  error: "--fixtures <directory> must resolve under the project directory or the bundled tests/fixtures/memory-recall directory"
@@ -24164,15 +24882,15 @@ function parseMaintenanceArgs(args, options) {
24164
24882
  return { limit, confirm };
24165
24883
  }
24166
24884
  function resolvePackageRootFromModule(modulePath) {
24167
- const moduleDir = path48.dirname(modulePath);
24168
- const leaf = path48.basename(moduleDir);
24885
+ const moduleDir = path50.dirname(modulePath);
24886
+ const leaf = path50.basename(moduleDir);
24169
24887
  if (leaf === "commands" || leaf === "cli") {
24170
- return path48.resolve(moduleDir, "..", "..");
24888
+ return path50.resolve(moduleDir, "..", "..");
24171
24889
  }
24172
24890
  if (leaf === "dist") {
24173
- return path48.resolve(moduleDir, "..");
24891
+ return path50.resolve(moduleDir, "..");
24174
24892
  }
24175
- return path48.resolve(moduleDir, "..");
24893
+ return path50.resolve(moduleDir, "..");
24176
24894
  }
24177
24895
  function formatMigrationResult(label, report) {
24178
24896
  if (!report) {
@@ -24289,15 +25007,15 @@ function truncate(value, maxLength) {
24289
25007
  }
24290
25008
 
24291
25009
  // src/services/plan-service.ts
24292
- var _internals33 = {
25010
+ var _internals34 = {
24293
25011
  loadPlanJsonOnly,
24294
25012
  derivePlanMarkdown,
24295
25013
  readSwarmFileAsync
24296
25014
  };
24297
25015
  async function getPlanData(directory, phaseArg) {
24298
- const plan = await _internals33.loadPlanJsonOnly(directory);
25016
+ const plan = await _internals34.loadPlanJsonOnly(directory);
24299
25017
  if (plan) {
24300
- const fullMarkdown = _internals33.derivePlanMarkdown(plan);
25018
+ const fullMarkdown = _internals34.derivePlanMarkdown(plan);
24301
25019
  if (phaseArg === undefined || phaseArg === null || phaseArg === "") {
24302
25020
  return {
24303
25021
  hasPlan: true,
@@ -24340,7 +25058,7 @@ async function getPlanData(directory, phaseArg) {
24340
25058
  isLegacy: false
24341
25059
  };
24342
25060
  }
24343
- const planContent = await _internals33.readSwarmFileAsync(directory, "plan.md");
25061
+ const planContent = await _internals34.readSwarmFileAsync(directory, "plan.md");
24344
25062
  if (!planContent) {
24345
25063
  return {
24346
25064
  hasPlan: false,
@@ -24437,7 +25155,7 @@ async function handlePlanCommand(directory, args) {
24437
25155
  return formatPlanMarkdown(planData);
24438
25156
  }
24439
25157
  // src/commands/post-mortem.ts
24440
- var _internals34 = {
25158
+ var _internals35 = {
24441
25159
  createCuratorLLMDelegate,
24442
25160
  runCuratorPostMortem
24443
25161
  };
@@ -24449,10 +25167,10 @@ async function handlePostMortemCommand(directory, args, options) {
24449
25167
  };
24450
25168
  if (options?.sessionID) {
24451
25169
  try {
24452
- pmOptions.llmDelegate = _internals34.createCuratorLLMDelegate(directory, "postmortem", options.sessionID);
25170
+ pmOptions.llmDelegate = _internals35.createCuratorLLMDelegate(directory, "postmortem", options.sessionID);
24453
25171
  } catch {}
24454
25172
  }
24455
- const result = await _internals34.runCuratorPostMortem(directory, pmOptions);
25173
+ const result = await _internals35.runCuratorPostMortem(directory, pmOptions);
24456
25174
  const lines = [];
24457
25175
  if (result.success) {
24458
25176
  lines.push("## Post-Mortem Report Generated");
@@ -24607,12 +25325,12 @@ function formatRelativeTime(epochMs) {
24607
25325
  const diffDays = Math.floor(diffHours / 24);
24608
25326
  return `${diffDays} day${diffDays === 1 ? "" : "s"} ago`;
24609
25327
  }
24610
- var _internals35 = {
25328
+ var _internals36 = {
24611
25329
  formatRelativeTime,
24612
25330
  listActive
24613
25331
  };
24614
25332
  async function handlePrMonitorStatusCommand(directory, _args, sessionID, source) {
24615
- const allActive = await _internals35.listActive(directory);
25333
+ const allActive = await _internals36.listActive(directory);
24616
25334
  const allSessions = source === "cli";
24617
25335
  const subs = allSessions ? allActive : allActive.filter((record) => record.sessionID === sessionID);
24618
25336
  if (subs.length === 0) {
@@ -24750,7 +25468,7 @@ async function handlePrSubscribeCommand(directory, args, sessionID) {
24750
25468
  const repoFullName = `${prInfo.owner}/${prInfo.repo}`;
24751
25469
  const prUrl = `https://github.com/${prInfo.owner}/${prInfo.repo}/pull/${prInfo.number}`;
24752
25470
  try {
24753
- const config = _internals36.loadPluginConfig(directory);
25471
+ const config = _internals37.loadPluginConfig(directory);
24754
25472
  const prMonitorConfig = config.pr_monitor;
24755
25473
  if (!prMonitorConfig?.enabled) {
24756
25474
  return [
@@ -24760,7 +25478,7 @@ async function handlePrSubscribeCommand(directory, args, sessionID) {
24760
25478
  ].join(`
24761
25479
  `);
24762
25480
  }
24763
- await _internals36.subscribe(directory, {
25481
+ await _internals37.subscribe(directory, {
24764
25482
  sessionID,
24765
25483
  prNumber: prInfo.number,
24766
25484
  repoFullName,
@@ -24784,7 +25502,7 @@ async function handlePrSubscribeCommand(directory, args, sessionID) {
24784
25502
  `);
24785
25503
  }
24786
25504
  }
24787
- var _internals36 = {
25505
+ var _internals37 = {
24788
25506
  loadPluginConfig,
24789
25507
  subscribe
24790
25508
  };
@@ -24807,9 +25525,9 @@ async function handlePrUnsubscribeCommand(directory, args, sessionID) {
24807
25525
  `);
24808
25526
  }
24809
25527
  const refToken = rest[0];
24810
- const prInfo = _internals37.parsePrRef(refToken, directory);
25528
+ const prInfo = _internals38.parsePrRef(refToken, directory);
24811
25529
  if (!prInfo) {
24812
- if (_internals37.looksLikePrRef(refToken)) {
25530
+ if (_internals38.looksLikePrRef(refToken)) {
24813
25531
  return [
24814
25532
  `Error: Could not resolve PR reference from "${refToken}".`,
24815
25533
  "",
@@ -24830,8 +25548,8 @@ async function handlePrUnsubscribeCommand(directory, args, sessionID) {
24830
25548
  const repoFullName = `${prInfo.owner}/${prInfo.repo}`;
24831
25549
  const prUrl = `https://github.com/${prInfo.owner}/${prInfo.repo}/pull/${prInfo.number}`;
24832
25550
  try {
24833
- const correlationId = _internals37.buildCorrelationId(sessionID, repoFullName, prInfo.number);
24834
- const result = await _internals37.unsubscribe(directory, correlationId);
25551
+ const correlationId = _internals38.buildCorrelationId(sessionID, repoFullName, prInfo.number);
25552
+ const result = await _internals38.unsubscribe(directory, correlationId);
24835
25553
  if (!result) {
24836
25554
  return [
24837
25555
  `Not subscribed to ${prUrl}`,
@@ -24858,7 +25576,7 @@ async function handlePrUnsubscribeCommand(directory, args, sessionID) {
24858
25576
  `);
24859
25577
  }
24860
25578
  }
24861
- var _internals37 = {
25579
+ var _internals38 = {
24862
25580
  unsubscribe,
24863
25581
  buildCorrelationId,
24864
25582
  parsePrRef,
@@ -24867,11 +25585,11 @@ var _internals37 = {
24867
25585
 
24868
25586
  // src/services/preflight-service.ts
24869
25587
  import * as fs26 from "fs";
24870
- import * as path55 from "path";
25588
+ import * as path57 from "path";
24871
25589
 
24872
25590
  // src/tools/lint.ts
24873
25591
  import * as fs20 from "fs";
24874
- import * as path49 from "path";
25592
+ import * as path51 from "path";
24875
25593
 
24876
25594
  // src/utils/path-security.ts
24877
25595
  function containsPathTraversal(str) {
@@ -24927,9 +25645,9 @@ function validateArgs(args) {
24927
25645
  }
24928
25646
  function getLinterCommand(linter, mode, projectDir) {
24929
25647
  const isWindows = process.platform === "win32";
24930
- const binDir = path49.join(projectDir, "node_modules", ".bin");
24931
- const biomeBin = isWindows ? path49.join(binDir, "biome.EXE") : path49.join(binDir, "biome");
24932
- const eslintBin = isWindows ? path49.join(binDir, "eslint.cmd") : path49.join(binDir, "eslint");
25648
+ const binDir = path51.join(projectDir, "node_modules", ".bin");
25649
+ const biomeBin = isWindows ? path51.join(binDir, "biome.EXE") : path51.join(binDir, "biome");
25650
+ const eslintBin = isWindows ? path51.join(binDir, "eslint.cmd") : path51.join(binDir, "eslint");
24933
25651
  switch (linter) {
24934
25652
  case "biome":
24935
25653
  if (mode === "fix") {
@@ -24945,7 +25663,7 @@ function getLinterCommand(linter, mode, projectDir) {
24945
25663
  }
24946
25664
  function getAdditionalLinterCommand(linter, mode, cwd) {
24947
25665
  const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
24948
- const gradlew = fs20.existsSync(path49.join(cwd, gradlewName)) ? path49.join(cwd, gradlewName) : null;
25666
+ const gradlew = fs20.existsSync(path51.join(cwd, gradlewName)) ? path51.join(cwd, gradlewName) : null;
24949
25667
  switch (linter) {
24950
25668
  case "ruff":
24951
25669
  return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
@@ -24979,10 +25697,10 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
24979
25697
  }
24980
25698
  }
24981
25699
  function detectRuff(cwd) {
24982
- if (fs20.existsSync(path49.join(cwd, "ruff.toml")))
25700
+ if (fs20.existsSync(path51.join(cwd, "ruff.toml")))
24983
25701
  return isCommandAvailable("ruff");
24984
25702
  try {
24985
- const pyproject = path49.join(cwd, "pyproject.toml");
25703
+ const pyproject = path51.join(cwd, "pyproject.toml");
24986
25704
  if (fs20.existsSync(pyproject)) {
24987
25705
  const content = fs20.readFileSync(pyproject, "utf-8");
24988
25706
  if (content.includes("[tool.ruff]"))
@@ -24992,19 +25710,19 @@ function detectRuff(cwd) {
24992
25710
  return false;
24993
25711
  }
24994
25712
  function detectClippy(cwd) {
24995
- return fs20.existsSync(path49.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
25713
+ return fs20.existsSync(path51.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
24996
25714
  }
24997
25715
  function detectGolangciLint(cwd) {
24998
- return fs20.existsSync(path49.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
25716
+ return fs20.existsSync(path51.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
24999
25717
  }
25000
25718
  function detectCheckstyle(cwd) {
25001
- const hasMaven = fs20.existsSync(path49.join(cwd, "pom.xml"));
25002
- const hasGradle = fs20.existsSync(path49.join(cwd, "build.gradle")) || fs20.existsSync(path49.join(cwd, "build.gradle.kts"));
25003
- const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs20.existsSync(path49.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
25719
+ const hasMaven = fs20.existsSync(path51.join(cwd, "pom.xml"));
25720
+ const hasGradle = fs20.existsSync(path51.join(cwd, "build.gradle")) || fs20.existsSync(path51.join(cwd, "build.gradle.kts"));
25721
+ const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs20.existsSync(path51.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
25004
25722
  return (hasMaven || hasGradle) && hasBinary;
25005
25723
  }
25006
25724
  function detectKtlint(cwd) {
25007
- const hasKotlin = fs20.existsSync(path49.join(cwd, "build.gradle.kts")) || fs20.existsSync(path49.join(cwd, "build.gradle")) || (() => {
25725
+ const hasKotlin = fs20.existsSync(path51.join(cwd, "build.gradle.kts")) || fs20.existsSync(path51.join(cwd, "build.gradle")) || (() => {
25008
25726
  try {
25009
25727
  return fs20.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
25010
25728
  } catch {
@@ -25023,11 +25741,11 @@ function detectDotnetFormat(cwd) {
25023
25741
  }
25024
25742
  }
25025
25743
  function detectCppcheck(cwd) {
25026
- if (fs20.existsSync(path49.join(cwd, "CMakeLists.txt"))) {
25744
+ if (fs20.existsSync(path51.join(cwd, "CMakeLists.txt"))) {
25027
25745
  return isCommandAvailable("cppcheck");
25028
25746
  }
25029
25747
  try {
25030
- const dirsToCheck = [cwd, path49.join(cwd, "src")];
25748
+ const dirsToCheck = [cwd, path51.join(cwd, "src")];
25031
25749
  const hasCpp = dirsToCheck.some((dir) => {
25032
25750
  try {
25033
25751
  return fs20.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
@@ -25041,13 +25759,13 @@ function detectCppcheck(cwd) {
25041
25759
  }
25042
25760
  }
25043
25761
  function detectSwiftlint(cwd) {
25044
- return fs20.existsSync(path49.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
25762
+ return fs20.existsSync(path51.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
25045
25763
  }
25046
25764
  function detectDartAnalyze(cwd) {
25047
- return fs20.existsSync(path49.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
25765
+ return fs20.existsSync(path51.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
25048
25766
  }
25049
25767
  function detectRubocop(cwd) {
25050
- return (fs20.existsSync(path49.join(cwd, "Gemfile")) || fs20.existsSync(path49.join(cwd, "gems.rb")) || fs20.existsSync(path49.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
25768
+ return (fs20.existsSync(path51.join(cwd, "Gemfile")) || fs20.existsSync(path51.join(cwd, "gems.rb")) || fs20.existsSync(path51.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
25051
25769
  }
25052
25770
  function detectAdditionalLinter(cwd) {
25053
25771
  if (detectRuff(cwd))
@@ -25075,10 +25793,10 @@ function detectAdditionalLinter(cwd) {
25075
25793
  function findBinInAncestors(startDir, binName) {
25076
25794
  let dir = startDir;
25077
25795
  while (true) {
25078
- const candidate = path49.join(dir, "node_modules", ".bin", binName);
25796
+ const candidate = path51.join(dir, "node_modules", ".bin", binName);
25079
25797
  if (fs20.existsSync(candidate))
25080
25798
  return candidate;
25081
- const parent = path49.dirname(dir);
25799
+ const parent = path51.dirname(dir);
25082
25800
  if (parent === dir)
25083
25801
  break;
25084
25802
  dir = parent;
@@ -25087,10 +25805,10 @@ function findBinInAncestors(startDir, binName) {
25087
25805
  }
25088
25806
  function findBinInEnvPath(binName) {
25089
25807
  const searchPath = process.env.PATH ?? "";
25090
- for (const dir of searchPath.split(path49.delimiter)) {
25808
+ for (const dir of searchPath.split(path51.delimiter)) {
25091
25809
  if (!dir)
25092
25810
  continue;
25093
- const candidate = path49.join(dir, binName);
25811
+ const candidate = path51.join(dir, binName);
25094
25812
  if (fs20.existsSync(candidate))
25095
25813
  return candidate;
25096
25814
  }
@@ -25103,13 +25821,13 @@ async function detectAvailableLinter(directory) {
25103
25821
  return null;
25104
25822
  const projectDir = directory;
25105
25823
  const isWindows = process.platform === "win32";
25106
- const biomeBin = isWindows ? path49.join(projectDir, "node_modules", ".bin", "biome.EXE") : path49.join(projectDir, "node_modules", ".bin", "biome");
25107
- const eslintBin = isWindows ? path49.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path49.join(projectDir, "node_modules", ".bin", "eslint");
25824
+ const biomeBin = isWindows ? path51.join(projectDir, "node_modules", ".bin", "biome.EXE") : path51.join(projectDir, "node_modules", ".bin", "biome");
25825
+ const eslintBin = isWindows ? path51.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path51.join(projectDir, "node_modules", ".bin", "eslint");
25108
25826
  const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
25109
25827
  if (localResult)
25110
25828
  return localResult;
25111
- const biomeAncestor = findBinInAncestors(path49.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
25112
- const eslintAncestor = findBinInAncestors(path49.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
25829
+ const biomeAncestor = findBinInAncestors(path51.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
25830
+ const eslintAncestor = findBinInAncestors(path51.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
25113
25831
  if (biomeAncestor || eslintAncestor) {
25114
25832
  return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
25115
25833
  }
@@ -25292,15 +26010,15 @@ var lint = createSwarmTool({
25292
26010
  }
25293
26011
  const { mode } = args;
25294
26012
  const cwd = directory;
25295
- const linter = await _internals38.detectAvailableLinter(directory);
26013
+ const linter = await _internals39.detectAvailableLinter(directory);
25296
26014
  if (linter) {
25297
- const result = await _internals38.runLint(linter, mode, directory);
26015
+ const result = await _internals39.runLint(linter, mode, directory);
25298
26016
  return JSON.stringify(result, null, 2);
25299
26017
  }
25300
- const additionalLinter = _internals38.detectAdditionalLinter(cwd);
26018
+ const additionalLinter = _internals39.detectAdditionalLinter(cwd);
25301
26019
  if (additionalLinter) {
25302
26020
  warn(`[lint] Using ${additionalLinter} linter for this project`);
25303
- const result = await _internals38.runAdditionalLint(additionalLinter, mode, cwd);
26021
+ const result = await _internals39.runAdditionalLint(additionalLinter, mode, cwd);
25304
26022
  return JSON.stringify(result, null, 2);
25305
26023
  }
25306
26024
  const errorResult = {
@@ -25314,7 +26032,7 @@ For Rust: rustup component add clippy`
25314
26032
  return JSON.stringify(errorResult, null, 2);
25315
26033
  }
25316
26034
  });
25317
- var _internals38 = {
26035
+ var _internals39 = {
25318
26036
  detectAvailableLinter,
25319
26037
  runLint,
25320
26038
  detectAdditionalLinter,
@@ -25323,7 +26041,7 @@ var _internals38 = {
25323
26041
 
25324
26042
  // src/tools/secretscan.ts
25325
26043
  import * as fs21 from "fs";
25326
- import * as path50 from "path";
26044
+ import * as path52 from "path";
25327
26045
  var MAX_FILE_PATH_LENGTH = 500;
25328
26046
  var MAX_FILE_SIZE_BYTES = 512 * 1024;
25329
26047
  var MAX_FILES_SCANNED = 1000;
@@ -25550,7 +26268,7 @@ function isGlobOrPathPattern(pattern) {
25550
26268
  return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
25551
26269
  }
25552
26270
  function loadSecretScanIgnore(scanDir) {
25553
- const ignorePath = path50.join(scanDir, ".secretscanignore");
26271
+ const ignorePath = path52.join(scanDir, ".secretscanignore");
25554
26272
  try {
25555
26273
  if (!fs21.existsSync(ignorePath))
25556
26274
  return [];
@@ -25573,7 +26291,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
25573
26291
  if (exactNames.has(entry))
25574
26292
  return true;
25575
26293
  for (const pattern of globPatterns) {
25576
- if (path50.matchesGlob(relPath, pattern))
26294
+ if (path52.matchesGlob(relPath, pattern))
25577
26295
  return true;
25578
26296
  }
25579
26297
  return false;
@@ -25594,7 +26312,7 @@ function validateDirectoryInput(dir) {
25594
26312
  return null;
25595
26313
  }
25596
26314
  function isBinaryFile(filePath, buffer) {
25597
- const ext = path50.extname(filePath).toLowerCase();
26315
+ const ext = path52.extname(filePath).toLowerCase();
25598
26316
  if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
25599
26317
  return true;
25600
26318
  }
@@ -25731,9 +26449,9 @@ function isSymlinkLoop(realPath, visited) {
25731
26449
  return false;
25732
26450
  }
25733
26451
  function isPathWithinScope(realPath, scanDir) {
25734
- const resolvedScanDir = path50.resolve(scanDir);
25735
- const resolvedRealPath = path50.resolve(realPath);
25736
- return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path50.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
26452
+ const resolvedScanDir = path52.resolve(scanDir);
26453
+ const resolvedRealPath = path52.resolve(realPath);
26454
+ return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path52.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
25737
26455
  }
25738
26456
  function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
25739
26457
  skippedDirs: 0,
@@ -25759,8 +26477,8 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
25759
26477
  return a.localeCompare(b);
25760
26478
  });
25761
26479
  for (const entry of entries) {
25762
- const fullPath = path50.join(dir, entry);
25763
- const relPath = path50.relative(scanDir, fullPath).replace(/\\/g, "/");
26480
+ const fullPath = path52.join(dir, entry);
26481
+ const relPath = path52.relative(scanDir, fullPath).replace(/\\/g, "/");
25764
26482
  if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
25765
26483
  stats.skippedDirs++;
25766
26484
  continue;
@@ -25795,7 +26513,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
25795
26513
  const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
25796
26514
  files.push(...subFiles);
25797
26515
  } else if (lstat2.isFile()) {
25798
- const ext = path50.extname(fullPath).toLowerCase();
26516
+ const ext = path52.extname(fullPath).toLowerCase();
25799
26517
  if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
25800
26518
  files.push(fullPath);
25801
26519
  } else {
@@ -25861,7 +26579,7 @@ var secretscan = createSwarmTool({
25861
26579
  }
25862
26580
  }
25863
26581
  try {
25864
- const _scanDirRaw = path50.resolve(directory);
26582
+ const _scanDirRaw = path52.resolve(directory);
25865
26583
  const scanDir = (() => {
25866
26584
  try {
25867
26585
  return fs21.realpathSync(_scanDirRaw);
@@ -26002,7 +26720,7 @@ var secretscan = createSwarmTool({
26002
26720
  });
26003
26721
  async function runSecretscan(directory) {
26004
26722
  try {
26005
- const result = await _internals39.secretscan.execute({ directory }, {});
26723
+ const result = await _internals40.secretscan.execute({ directory }, {});
26006
26724
  const jsonStr = typeof result === "string" ? result : result.output;
26007
26725
  return JSON.parse(jsonStr);
26008
26726
  } catch (e) {
@@ -26017,18 +26735,18 @@ async function runSecretscan(directory) {
26017
26735
  return errorResult;
26018
26736
  }
26019
26737
  }
26020
- var _internals39 = {
26738
+ var _internals40 = {
26021
26739
  secretscan,
26022
26740
  runSecretscan
26023
26741
  };
26024
26742
 
26025
26743
  // src/tools/test-runner.ts
26026
26744
  import * as fs25 from "fs";
26027
- import * as path54 from "path";
26745
+ import * as path56 from "path";
26028
26746
 
26029
26747
  // src/test-impact/analyzer.ts
26030
26748
  import fs22 from "fs";
26031
- import path51 from "path";
26749
+ import path53 from "path";
26032
26750
  var IMPORT_REGEX_ES = /import\s+[\s\S]*?\s+from\s+['"]([^'"]+)['"]/g;
26033
26751
  var IMPORT_REGEX_REQUIRE = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
26034
26752
  var IMPORT_REGEX_REEXPORT = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
@@ -26069,8 +26787,8 @@ function resolveRelativeImport(fromDir, importPath) {
26069
26787
  if (!importPath.startsWith(".")) {
26070
26788
  return null;
26071
26789
  }
26072
- const resolved = path51.resolve(fromDir, importPath);
26073
- if (path51.extname(resolved)) {
26790
+ const resolved = path53.resolve(fromDir, importPath);
26791
+ if (path53.extname(resolved)) {
26074
26792
  if (fs22.existsSync(resolved) && fs22.statSync(resolved).isFile()) {
26075
26793
  return normalizePath2(resolved);
26076
26794
  }
@@ -26090,20 +26808,20 @@ function resolvePythonImport(fromDir, module) {
26090
26808
  const leadingDots = module.match(/^\.+/)?.[0].length ?? 0;
26091
26809
  let baseDir = fromDir;
26092
26810
  for (let i = 1;i < leadingDots; i++) {
26093
- baseDir = path51.dirname(baseDir);
26811
+ baseDir = path53.dirname(baseDir);
26094
26812
  }
26095
26813
  const rest = module.slice(leadingDots);
26096
26814
  if (rest.length === 0) {
26097
- const initPath = path51.join(baseDir, "__init__.py");
26815
+ const initPath = path53.join(baseDir, "__init__.py");
26098
26816
  if (fs22.existsSync(initPath) && fs22.statSync(initPath).isFile()) {
26099
26817
  return normalizePath2(initPath);
26100
26818
  }
26101
26819
  return null;
26102
26820
  }
26103
- const subpath = rest.replace(/\./g, path51.sep);
26821
+ const subpath = rest.replace(/\./g, path53.sep);
26104
26822
  const candidates = [
26105
- `${path51.join(baseDir, subpath)}.py`,
26106
- path51.join(baseDir, subpath, "__init__.py")
26823
+ `${path53.join(baseDir, subpath)}.py`,
26824
+ path53.join(baseDir, subpath, "__init__.py")
26107
26825
  ];
26108
26826
  for (const c of candidates) {
26109
26827
  if (fs22.existsSync(c) && fs22.statSync(c).isFile())
@@ -26113,7 +26831,7 @@ function resolvePythonImport(fromDir, module) {
26113
26831
  }
26114
26832
  var goModuleCache = new Map;
26115
26833
  function findGoModule(fromDir) {
26116
- const resolved = path51.resolve(fromDir);
26834
+ const resolved = path53.resolve(fromDir);
26117
26835
  let cur = resolved;
26118
26836
  const walked = [];
26119
26837
  for (let i = 0;i < 16; i++) {
@@ -26125,7 +26843,7 @@ function findGoModule(fromDir) {
26125
26843
  }
26126
26844
  walked.push(cur);
26127
26845
  try {
26128
- const goMod = path51.join(cur, "go.mod");
26846
+ const goMod = path53.join(cur, "go.mod");
26129
26847
  const content = fs22.readFileSync(goMod, "utf-8");
26130
26848
  const moduleMatch = content.match(/^\s*module\s+"?([^"\s/]+(?:\/[^"\s]+)*)"?/m);
26131
26849
  if (moduleMatch) {
@@ -26136,10 +26854,10 @@ function findGoModule(fromDir) {
26136
26854
  }
26137
26855
  } catch {}
26138
26856
  try {
26139
- fs22.accessSync(path51.join(cur, ".git"));
26857
+ fs22.accessSync(path53.join(cur, ".git"));
26140
26858
  break;
26141
26859
  } catch {}
26142
- const parent = path51.dirname(cur);
26860
+ const parent = path53.dirname(cur);
26143
26861
  if (parent === cur)
26144
26862
  break;
26145
26863
  cur = parent;
@@ -26151,12 +26869,12 @@ function findGoModule(fromDir) {
26151
26869
  function resolveGoImport(fromDir, importPath) {
26152
26870
  let dir = null;
26153
26871
  if (importPath.startsWith(".")) {
26154
- dir = path51.resolve(fromDir, importPath);
26872
+ dir = path53.resolve(fromDir, importPath);
26155
26873
  } else {
26156
26874
  const mod = findGoModule(fromDir);
26157
26875
  if (mod && (importPath === mod.modulePath || importPath.startsWith(`${mod.modulePath}/`))) {
26158
26876
  const subpath = importPath.slice(mod.modulePath.length);
26159
- dir = path51.join(mod.moduleRoot, subpath);
26877
+ dir = path53.join(mod.moduleRoot, subpath);
26160
26878
  }
26161
26879
  }
26162
26880
  if (dir === null)
@@ -26164,7 +26882,7 @@ function resolveGoImport(fromDir, importPath) {
26164
26882
  if (!fs22.existsSync(dir) || !fs22.statSync(dir).isDirectory())
26165
26883
  return [];
26166
26884
  try {
26167
- return fs22.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath2(path51.join(dir, f)));
26885
+ return fs22.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath2(path53.join(dir, f)));
26168
26886
  } catch {
26169
26887
  return [];
26170
26888
  }
@@ -26203,15 +26921,15 @@ function findTestFilesSync(cwd) {
26203
26921
  for (const entry of entries) {
26204
26922
  if (entry.isDirectory()) {
26205
26923
  if (!skipDirs.has(entry.name)) {
26206
- walk(path51.join(dir, entry.name), visitedInodes);
26924
+ walk(path53.join(dir, entry.name), visitedInodes);
26207
26925
  }
26208
26926
  } else if (entry.isFile()) {
26209
26927
  const name = entry.name;
26210
26928
  const isTsTest = /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name);
26211
- const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${path51.sep}tests${path51.sep}`) && name.endsWith(".py");
26929
+ const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${path53.sep}tests${path53.sep}`) && name.endsWith(".py");
26212
26930
  const isGoTest = /.+_test\.go$/.test(name);
26213
26931
  if (isTsTest || isPyTest || isGoTest) {
26214
- testFiles.push(normalizePath2(path51.join(dir, entry.name)));
26932
+ testFiles.push(normalizePath2(path53.join(dir, entry.name)));
26215
26933
  }
26216
26934
  }
26217
26935
  }
@@ -26236,8 +26954,8 @@ function extractImports(content) {
26236
26954
  ];
26237
26955
  }
26238
26956
  function addImpactEdgesForTestFile(testFile, content, impactMap) {
26239
- const ext = path51.extname(testFile).toLowerCase();
26240
- const testDir = path51.dirname(testFile);
26957
+ const ext = path53.extname(testFile).toLowerCase();
26958
+ const testDir = path53.dirname(testFile);
26241
26959
  function addEdge(source) {
26242
26960
  if (!impactMap[source])
26243
26961
  impactMap[source] = [];
@@ -26290,7 +27008,7 @@ async function buildImpactMapInternal(cwd) {
26290
27008
  }
26291
27009
  return impactMap;
26292
27010
  }
26293
- var _internals40 = {
27011
+ var _internals41 = {
26294
27012
  validateProjectRoot,
26295
27013
  normalizePath: normalizePath2,
26296
27014
  isCacheStale,
@@ -26305,12 +27023,12 @@ var _internals40 = {
26305
27023
  _clearGoModuleCache
26306
27024
  };
26307
27025
  async function buildImpactMap(cwd) {
26308
- const impactMap = await _internals40.buildImpactMapInternal(cwd);
26309
- await _internals40.saveImpactMap(cwd, impactMap);
27026
+ const impactMap = await _internals41.buildImpactMapInternal(cwd);
27027
+ await _internals41.saveImpactMap(cwd, impactMap);
26310
27028
  return impactMap;
26311
27029
  }
26312
27030
  async function loadImpactMap(cwd, options) {
26313
- const cachePath = path51.join(cwd, ".swarm", "cache", "impact-map.json");
27031
+ const cachePath = path53.join(cwd, ".swarm", "cache", "impact-map.json");
26314
27032
  if (fs22.existsSync(cachePath)) {
26315
27033
  try {
26316
27034
  const content = fs22.readFileSync(cachePath, "utf-8");
@@ -26320,7 +27038,7 @@ async function loadImpactMap(cwd, options) {
26320
27038
  const hasValidValues = Object.values(map).every((v) => Array.isArray(v) && v.every((item) => typeof item === "string"));
26321
27039
  if (hasValidValues) {
26322
27040
  const generatedAt = new Date(data.generatedAt).getTime();
26323
- if (!_internals40.isCacheStale(map, generatedAt)) {
27041
+ if (!_internals41.isCacheStale(map, generatedAt)) {
26324
27042
  return map;
26325
27043
  }
26326
27044
  if (options?.skipRebuild) {
@@ -26340,15 +27058,15 @@ async function loadImpactMap(cwd, options) {
26340
27058
  if (options?.skipRebuild) {
26341
27059
  return {};
26342
27060
  }
26343
- return _internals40.buildImpactMap(cwd);
27061
+ return _internals41.buildImpactMap(cwd);
26344
27062
  }
26345
27063
  async function saveImpactMap(cwd, impactMap) {
26346
- if (!path51.isAbsolute(cwd)) {
27064
+ if (!path53.isAbsolute(cwd)) {
26347
27065
  throw new Error(`saveImpactMap requires an absolute project root path, got: "${cwd}"`);
26348
27066
  }
26349
- _internals40.validateProjectRoot(cwd);
26350
- const cacheDir2 = path51.join(cwd, ".swarm", "cache");
26351
- const cachePath = path51.join(cacheDir2, "impact-map.json");
27067
+ _internals41.validateProjectRoot(cwd);
27068
+ const cacheDir2 = path53.join(cwd, ".swarm", "cache");
27069
+ const cachePath = path53.join(cacheDir2, "impact-map.json");
26352
27070
  if (!fs22.existsSync(cacheDir2)) {
26353
27071
  fs22.mkdirSync(cacheDir2, { recursive: true });
26354
27072
  }
@@ -26370,7 +27088,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
26370
27088
  };
26371
27089
  }
26372
27090
  const validFiles = changedFiles.filter((f) => typeof f === "string" && f.length > 0 && !f.includes("\x00"));
26373
- const impactMap = await _internals40.loadImpactMap(cwd);
27091
+ const impactMap = await _internals41.loadImpactMap(cwd);
26374
27092
  const impactedTestsSet = new Set;
26375
27093
  const untestedFiles = [];
26376
27094
  let visitedCount = 0;
@@ -26380,7 +27098,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
26380
27098
  budgetExceeded = true;
26381
27099
  break;
26382
27100
  }
26383
- const normalizedChanged = normalizePath2(path51.resolve(changedFile));
27101
+ const normalizedChanged = normalizePath2(path53.resolve(changedFile));
26384
27102
  const tests = impactMap[normalizedChanged];
26385
27103
  if (tests && tests.length > 0) {
26386
27104
  for (const test of tests) {
@@ -26394,13 +27112,13 @@ async function analyzeImpact(changedFiles, cwd, budget) {
26394
27112
  if (budgetExceeded)
26395
27113
  break;
26396
27114
  } else {
26397
- const changedDir = normalizePath2(path51.dirname(normalizedChanged));
26398
- const changedInputDir = normalizePath2(path51.dirname(changedFile));
27115
+ const changedDir = normalizePath2(path53.dirname(normalizedChanged));
27116
+ const changedInputDir = normalizePath2(path53.dirname(changedFile));
26399
27117
  const suffixMatches = Object.entries(impactMap).filter(([sourcePath]) => {
26400
27118
  return sourcePath.endsWith(changedFile) || changedFile.endsWith(sourcePath) || sourcePath.endsWith(normalizedChanged) || normalizedChanged.endsWith(sourcePath);
26401
27119
  }).sort(([sourceA], [sourceB]) => {
26402
- const sourceDirA = normalizePath2(path51.dirname(sourceA));
26403
- const sourceDirB = normalizePath2(path51.dirname(sourceB));
27120
+ const sourceDirA = normalizePath2(path53.dirname(sourceA));
27121
+ const sourceDirB = normalizePath2(path53.dirname(sourceB));
26404
27122
  const exactA = sourceDirA === changedDir || changedInputDir !== "." && (sourceDirA === changedInputDir || sourceDirA.endsWith(`/${changedInputDir}`));
26405
27123
  const exactB = sourceDirB === changedDir || changedInputDir !== "." && (sourceDirB === changedInputDir || sourceDirB.endsWith(`/${changedInputDir}`));
26406
27124
  if (exactA !== exactB)
@@ -26727,7 +27445,7 @@ function detectFlakyTests(allHistory) {
26727
27445
 
26728
27446
  // src/test-impact/history-store.ts
26729
27447
  import fs23 from "fs";
26730
- import path52 from "path";
27448
+ import path54 from "path";
26731
27449
  var MAX_HISTORY_PER_TEST = 20;
26732
27450
  var MAX_ERROR_LENGTH = 500;
26733
27451
  var MAX_STACK_LENGTH = 200;
@@ -26739,10 +27457,10 @@ function getHistoryPath(workingDir) {
26739
27457
  if (!workingDir) {
26740
27458
  throw new Error("getHistoryPath requires a working directory \u2014 project root must be provided by the caller");
26741
27459
  }
26742
- if (!path52.isAbsolute(workingDir)) {
27460
+ if (!path54.isAbsolute(workingDir)) {
26743
27461
  throw new Error(`getHistoryPath requires an absolute project root path, got: "${workingDir}"`);
26744
27462
  }
26745
- return path52.join(workingDir, ".swarm", "cache", "test-history.jsonl");
27463
+ return path54.join(workingDir, ".swarm", "cache", "test-history.jsonl");
26746
27464
  }
26747
27465
  function sanitizeErrorMessage(errorMessage) {
26748
27466
  if (errorMessage === undefined) {
@@ -26834,8 +27552,8 @@ function batchAppendTestRuns(records, workingDir) {
26834
27552
  }
26835
27553
  }
26836
27554
  const historyPath = getHistoryPath(workingDir);
26837
- const historyDir = path52.dirname(historyPath);
26838
- _internals41.validateProjectRoot(workingDir);
27555
+ const historyDir = path54.dirname(historyPath);
27556
+ _internals42.validateProjectRoot(workingDir);
26839
27557
  if (!fs23.existsSync(historyDir)) {
26840
27558
  fs23.mkdirSync(historyDir, { recursive: true });
26841
27559
  }
@@ -26958,13 +27676,13 @@ function getAllHistory(workingDir) {
26958
27676
  records.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
26959
27677
  return records;
26960
27678
  }
26961
- var _internals41 = {
27679
+ var _internals42 = {
26962
27680
  validateProjectRoot
26963
27681
  };
26964
27682
 
26965
27683
  // src/tools/resolve-working-directory.ts
26966
27684
  import * as fs24 from "fs";
26967
- import * as path53 from "path";
27685
+ import * as path55 from "path";
26968
27686
  function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
26969
27687
  if (workingDirectory == null || workingDirectory === "") {
26970
27688
  if (typeof fallbackDirectory !== "string" || fallbackDirectory === "") {
@@ -27003,8 +27721,8 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
27003
27721
  message: "Invalid working_directory: path traversal sequences (..) are not allowed"
27004
27722
  };
27005
27723
  }
27006
- const normalizedDir = path53.normalize(workingDirectory);
27007
- const resolvedDir = path53.resolve(normalizedDir);
27724
+ const normalizedDir = path55.normalize(workingDirectory);
27725
+ const resolvedDir = path55.resolve(normalizedDir);
27008
27726
  let statResult;
27009
27727
  try {
27010
27728
  statResult = fs24.statSync(resolvedDir);
@@ -27023,7 +27741,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
27023
27741
  if (typeof fallbackDirectory !== "string" || fallbackDirectory === "") {
27024
27742
  return { success: true, directory: resolvedDir };
27025
27743
  }
27026
- const resolvedFallback = path53.resolve(fallbackDirectory);
27744
+ const resolvedFallback = path55.resolve(fallbackDirectory);
27027
27745
  let fallbackExists = false;
27028
27746
  try {
27029
27747
  fs24.statSync(resolvedFallback);
@@ -27032,7 +27750,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
27032
27750
  fallbackExists = false;
27033
27751
  }
27034
27752
  if (fallbackExists) {
27035
- const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path53.sep);
27753
+ const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path55.sep);
27036
27754
  if (isSubdirectory) {
27037
27755
  return {
27038
27756
  success: false,
@@ -27055,7 +27773,7 @@ async function estimateFanOut(sourceFiles, cwd) {
27055
27773
  const impactMap = await loadImpactMap(cwd, { skipRebuild: true });
27056
27774
  const uniqueTestFiles = new Set;
27057
27775
  for (const sourceFile of sourceFiles) {
27058
- const resolvedPath = path54.resolve(cwd, sourceFile);
27776
+ const resolvedPath = path56.resolve(cwd, sourceFile);
27059
27777
  const normalizedPath = resolvedPath.replace(/\\/g, "/");
27060
27778
  const testFiles = impactMap[normalizedPath];
27061
27779
  if (testFiles) {
@@ -27140,14 +27858,14 @@ function hasDevDependency(devDeps, ...patterns) {
27140
27858
  return hasPackageJsonDependency(devDeps, ...patterns);
27141
27859
  }
27142
27860
  function detectGoTest(cwd) {
27143
- return fs25.existsSync(path54.join(cwd, "go.mod")) && isCommandAvailable("go");
27861
+ return fs25.existsSync(path56.join(cwd, "go.mod")) && isCommandAvailable("go");
27144
27862
  }
27145
27863
  function detectJavaMaven(cwd) {
27146
- return fs25.existsSync(path54.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
27864
+ return fs25.existsSync(path56.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
27147
27865
  }
27148
27866
  function detectGradle(cwd) {
27149
- const hasBuildFile = fs25.existsSync(path54.join(cwd, "build.gradle")) || fs25.existsSync(path54.join(cwd, "build.gradle.kts"));
27150
- const hasGradlew = fs25.existsSync(path54.join(cwd, "gradlew")) || fs25.existsSync(path54.join(cwd, "gradlew.bat"));
27867
+ const hasBuildFile = fs25.existsSync(path56.join(cwd, "build.gradle")) || fs25.existsSync(path56.join(cwd, "build.gradle.kts"));
27868
+ const hasGradlew = fs25.existsSync(path56.join(cwd, "gradlew")) || fs25.existsSync(path56.join(cwd, "gradlew.bat"));
27151
27869
  return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
27152
27870
  }
27153
27871
  function detectDotnetTest(cwd) {
@@ -27160,25 +27878,25 @@ function detectDotnetTest(cwd) {
27160
27878
  }
27161
27879
  }
27162
27880
  function detectCTest(cwd) {
27163
- const hasSource = fs25.existsSync(path54.join(cwd, "CMakeLists.txt"));
27164
- const hasBuildCache = fs25.existsSync(path54.join(cwd, "CMakeCache.txt")) || fs25.existsSync(path54.join(cwd, "build", "CMakeCache.txt"));
27881
+ const hasSource = fs25.existsSync(path56.join(cwd, "CMakeLists.txt"));
27882
+ const hasBuildCache = fs25.existsSync(path56.join(cwd, "CMakeCache.txt")) || fs25.existsSync(path56.join(cwd, "build", "CMakeCache.txt"));
27165
27883
  return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
27166
27884
  }
27167
27885
  function detectSwiftTest(cwd) {
27168
- return fs25.existsSync(path54.join(cwd, "Package.swift")) && isCommandAvailable("swift");
27886
+ return fs25.existsSync(path56.join(cwd, "Package.swift")) && isCommandAvailable("swift");
27169
27887
  }
27170
27888
  function detectDartTest(cwd) {
27171
- return fs25.existsSync(path54.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
27889
+ return fs25.existsSync(path56.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
27172
27890
  }
27173
27891
  function detectRSpec(cwd) {
27174
- const hasRSpecFile = fs25.existsSync(path54.join(cwd, ".rspec"));
27175
- const hasGemfile = fs25.existsSync(path54.join(cwd, "Gemfile"));
27176
- const hasSpecDir = fs25.existsSync(path54.join(cwd, "spec"));
27892
+ const hasRSpecFile = fs25.existsSync(path56.join(cwd, ".rspec"));
27893
+ const hasGemfile = fs25.existsSync(path56.join(cwd, "Gemfile"));
27894
+ const hasSpecDir = fs25.existsSync(path56.join(cwd, "spec"));
27177
27895
  const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
27178
27896
  return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
27179
27897
  }
27180
27898
  function detectMinitest(cwd) {
27181
- return fs25.existsSync(path54.join(cwd, "test")) && (fs25.existsSync(path54.join(cwd, "Gemfile")) || fs25.existsSync(path54.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
27899
+ return fs25.existsSync(path56.join(cwd, "test")) && (fs25.existsSync(path56.join(cwd, "Gemfile")) || fs25.existsSync(path56.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
27182
27900
  }
27183
27901
  var DISPATCH_FRAMEWORK_MAP = {
27184
27902
  bun: "bun",
@@ -27263,7 +27981,7 @@ async function parseTestOutputViaDispatch(framework, output, baseDir) {
27263
27981
  async function detectTestFramework(cwd) {
27264
27982
  const baseDir = cwd;
27265
27983
  try {
27266
- const packageJsonPath = path54.join(baseDir, "package.json");
27984
+ const packageJsonPath = path56.join(baseDir, "package.json");
27267
27985
  if (fs25.existsSync(packageJsonPath)) {
27268
27986
  const content = fs25.readFileSync(packageJsonPath, "utf-8");
27269
27987
  const pkg = JSON.parse(content);
@@ -27284,16 +28002,16 @@ async function detectTestFramework(cwd) {
27284
28002
  return "jest";
27285
28003
  if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
27286
28004
  return "mocha";
27287
- if (fs25.existsSync(path54.join(baseDir, "bun.lockb")) || fs25.existsSync(path54.join(baseDir, "bun.lock"))) {
28005
+ if (fs25.existsSync(path56.join(baseDir, "bun.lockb")) || fs25.existsSync(path56.join(baseDir, "bun.lock"))) {
27288
28006
  if (scripts.test?.includes("bun"))
27289
28007
  return "bun";
27290
28008
  }
27291
28009
  }
27292
28010
  } catch {}
27293
28011
  try {
27294
- const pyprojectTomlPath = path54.join(baseDir, "pyproject.toml");
27295
- const setupCfgPath = path54.join(baseDir, "setup.cfg");
27296
- const requirementsTxtPath = path54.join(baseDir, "requirements.txt");
28012
+ const pyprojectTomlPath = path56.join(baseDir, "pyproject.toml");
28013
+ const setupCfgPath = path56.join(baseDir, "setup.cfg");
28014
+ const requirementsTxtPath = path56.join(baseDir, "requirements.txt");
27297
28015
  if (fs25.existsSync(pyprojectTomlPath)) {
27298
28016
  const content = fs25.readFileSync(pyprojectTomlPath, "utf-8");
27299
28017
  if (content.includes("[tool.pytest"))
@@ -27313,7 +28031,7 @@ async function detectTestFramework(cwd) {
27313
28031
  }
27314
28032
  } catch {}
27315
28033
  try {
27316
- const cargoTomlPath = path54.join(baseDir, "Cargo.toml");
28034
+ const cargoTomlPath = path56.join(baseDir, "Cargo.toml");
27317
28035
  if (fs25.existsSync(cargoTomlPath)) {
27318
28036
  const content = fs25.readFileSync(cargoTomlPath, "utf-8");
27319
28037
  if (content.includes("[dev-dependencies]")) {
@@ -27324,9 +28042,9 @@ async function detectTestFramework(cwd) {
27324
28042
  }
27325
28043
  } catch {}
27326
28044
  try {
27327
- const pesterConfigPath = path54.join(baseDir, "pester.config.ps1");
27328
- const pesterConfigJsonPath = path54.join(baseDir, "pester.config.ps1.json");
27329
- const pesterPs1Path = path54.join(baseDir, "tests.ps1");
28045
+ const pesterConfigPath = path56.join(baseDir, "pester.config.ps1");
28046
+ const pesterConfigJsonPath = path56.join(baseDir, "pester.config.ps1.json");
28047
+ const pesterPs1Path = path56.join(baseDir, "tests.ps1");
27330
28048
  if (fs25.existsSync(pesterConfigPath) || fs25.existsSync(pesterConfigJsonPath) || fs25.existsSync(pesterPs1Path)) {
27331
28049
  return "pester";
27332
28050
  }
@@ -27369,12 +28087,12 @@ function isTestDirectoryPath(normalizedPath) {
27369
28087
  return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
27370
28088
  }
27371
28089
  function resolveWorkspacePath(file, workingDir) {
27372
- return path54.isAbsolute(file) ? path54.resolve(file) : path54.resolve(workingDir, file);
28090
+ return path56.isAbsolute(file) ? path56.resolve(file) : path56.resolve(workingDir, file);
27373
28091
  }
27374
28092
  function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
27375
28093
  if (!preferRelative)
27376
28094
  return absolutePath;
27377
- return path54.relative(workingDir, absolutePath);
28095
+ return path56.relative(workingDir, absolutePath);
27378
28096
  }
27379
28097
  function dedupePush(target, value) {
27380
28098
  if (!target.includes(value)) {
@@ -27411,18 +28129,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
27411
28129
  }
27412
28130
  }
27413
28131
  function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
27414
- const relativeDir = path54.dirname(relativePath);
28132
+ const relativeDir = path56.dirname(relativePath);
27415
28133
  const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
27416
28134
  const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
27417
- const rootDir = path54.join(workingDir, dirName);
27418
- return nestedRelativeDir ? [rootDir, path54.join(rootDir, nestedRelativeDir)] : [rootDir];
28135
+ const rootDir = path56.join(workingDir, dirName);
28136
+ return nestedRelativeDir ? [rootDir, path56.join(rootDir, nestedRelativeDir)] : [rootDir];
27419
28137
  });
27420
28138
  const normalizedRelativePath = relativePath.replace(/\\/g, "/");
27421
28139
  if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
27422
- directories.push(path54.join(workingDir, "src/test/java", path54.dirname(normalizedRelativePath.slice("src/main/java/".length))));
28140
+ directories.push(path56.join(workingDir, "src/test/java", path56.dirname(normalizedRelativePath.slice("src/main/java/".length))));
27423
28141
  }
27424
28142
  if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
27425
- directories.push(path54.join(workingDir, "src/test/kotlin", path54.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
28143
+ directories.push(path56.join(workingDir, "src/test/kotlin", path56.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
27426
28144
  }
27427
28145
  return [...new Set(directories)];
27428
28146
  }
@@ -27450,23 +28168,23 @@ function isLanguageSpecificTestFile(basename10) {
27450
28168
  }
27451
28169
  function isConventionTestFilePath(filePath) {
27452
28170
  const normalizedPath = filePath.replace(/\\/g, "/");
27453
- const basename10 = path54.basename(filePath);
28171
+ const basename10 = path56.basename(filePath);
27454
28172
  return hasCompoundTestExtension(basename10) || basename10.includes(".spec.") || basename10.includes(".test.") || isLanguageSpecificTestFile(basename10) || isTestDirectoryPath(normalizedPath);
27455
28173
  }
27456
28174
  function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
27457
28175
  const testFiles = [];
27458
28176
  for (const file of sourceFiles) {
27459
28177
  const absoluteFile = resolveWorkspacePath(file, workingDir);
27460
- const relativeFile = path54.relative(workingDir, absoluteFile);
27461
- const basename10 = path54.basename(absoluteFile);
27462
- const dirname25 = path54.dirname(absoluteFile);
27463
- const preferRelativeOutput = !path54.isAbsolute(file);
28178
+ const relativeFile = path56.relative(workingDir, absoluteFile);
28179
+ const basename10 = path56.basename(absoluteFile);
28180
+ const dirname25 = path56.dirname(absoluteFile);
28181
+ const preferRelativeOutput = !path56.isAbsolute(file);
27464
28182
  if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file)) {
27465
28183
  dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
27466
28184
  continue;
27467
28185
  }
27468
28186
  const nameWithoutExt = basename10.replace(/\.[^.]+$/, "");
27469
- const ext = path54.extname(basename10);
28187
+ const ext = path56.extname(basename10);
27470
28188
  const genericTestNames = [
27471
28189
  `${nameWithoutExt}.spec${ext}`,
27472
28190
  `${nameWithoutExt}.test${ext}`
@@ -27475,7 +28193,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
27475
28193
  const colocatedCandidates = [
27476
28194
  ...genericTestNames,
27477
28195
  ...languageSpecificTestNames
27478
- ].map((candidateName) => path54.join(dirname25, candidateName));
28196
+ ].map((candidateName) => path56.join(dirname25, candidateName));
27479
28197
  const testDirectoryNames = [
27480
28198
  basename10,
27481
28199
  ...genericTestNames,
@@ -27484,8 +28202,8 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
27484
28202
  const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
27485
28203
  const possibleTestFiles = [
27486
28204
  ...colocatedCandidates,
27487
- ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path54.join(dirname25, dirName, candidateName))),
27488
- ...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path54.join(candidateDir, candidateName)))
28205
+ ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path56.join(dirname25, dirName, candidateName))),
28206
+ ...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path56.join(candidateDir, candidateName)))
27489
28207
  ];
27490
28208
  for (const testFile of possibleTestFiles) {
27491
28209
  if (fs25.existsSync(testFile)) {
@@ -27506,7 +28224,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
27506
28224
  try {
27507
28225
  const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
27508
28226
  const content = fs25.readFileSync(absoluteTestFile, "utf-8");
27509
- const testDir = path54.dirname(absoluteTestFile);
28227
+ const testDir = path56.dirname(absoluteTestFile);
27510
28228
  const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
27511
28229
  let match;
27512
28230
  match = importRegex.exec(content);
@@ -27514,8 +28232,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
27514
28232
  const importPath = match[1];
27515
28233
  let resolvedImport;
27516
28234
  if (importPath.startsWith(".")) {
27517
- resolvedImport = path54.resolve(testDir, importPath);
27518
- const existingExt = path54.extname(resolvedImport);
28235
+ resolvedImport = path56.resolve(testDir, importPath);
28236
+ const existingExt = path56.extname(resolvedImport);
27519
28237
  if (!existingExt) {
27520
28238
  for (const extToTry of [
27521
28239
  ".ts",
@@ -27535,12 +28253,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
27535
28253
  } else {
27536
28254
  continue;
27537
28255
  }
27538
- const importBasename = path54.basename(resolvedImport, path54.extname(resolvedImport));
27539
- const importDir = path54.dirname(resolvedImport);
28256
+ const importBasename = path56.basename(resolvedImport, path56.extname(resolvedImport));
28257
+ const importDir = path56.dirname(resolvedImport);
27540
28258
  for (const sourceFile of absoluteSourceFiles) {
27541
- const sourceDir = path54.dirname(sourceFile);
27542
- const sourceBasename = path54.basename(sourceFile, path54.extname(sourceFile));
27543
- const isRelatedDir = importDir === sourceDir || importDir === path54.join(sourceDir, "__tests__") || importDir === path54.join(sourceDir, "tests") || importDir === path54.join(sourceDir, "test") || importDir === path54.join(sourceDir, "spec");
28259
+ const sourceDir = path56.dirname(sourceFile);
28260
+ const sourceBasename = path56.basename(sourceFile, path56.extname(sourceFile));
28261
+ const isRelatedDir = importDir === sourceDir || importDir === path56.join(sourceDir, "__tests__") || importDir === path56.join(sourceDir, "tests") || importDir === path56.join(sourceDir, "test") || importDir === path56.join(sourceDir, "spec");
27544
28262
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
27545
28263
  dedupePush(testFiles, testFile);
27546
28264
  break;
@@ -27553,8 +28271,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
27553
28271
  while (match !== null) {
27554
28272
  const importPath = match[1];
27555
28273
  if (importPath.startsWith(".")) {
27556
- let resolvedImport = path54.resolve(testDir, importPath);
27557
- const existingExt = path54.extname(resolvedImport);
28274
+ let resolvedImport = path56.resolve(testDir, importPath);
28275
+ const existingExt = path56.extname(resolvedImport);
27558
28276
  if (!existingExt) {
27559
28277
  for (const extToTry of [
27560
28278
  ".ts",
@@ -27571,12 +28289,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
27571
28289
  }
27572
28290
  }
27573
28291
  }
27574
- const importDir = path54.dirname(resolvedImport);
27575
- const importBasename = path54.basename(resolvedImport, path54.extname(resolvedImport));
28292
+ const importDir = path56.dirname(resolvedImport);
28293
+ const importBasename = path56.basename(resolvedImport, path56.extname(resolvedImport));
27576
28294
  for (const sourceFile of absoluteSourceFiles) {
27577
- const sourceDir = path54.dirname(sourceFile);
27578
- const sourceBasename = path54.basename(sourceFile, path54.extname(sourceFile));
27579
- const isRelatedDir = importDir === sourceDir || importDir === path54.join(sourceDir, "__tests__") || importDir === path54.join(sourceDir, "tests") || importDir === path54.join(sourceDir, "test") || importDir === path54.join(sourceDir, "spec");
28295
+ const sourceDir = path56.dirname(sourceFile);
28296
+ const sourceBasename = path56.basename(sourceFile, path56.extname(sourceFile));
28297
+ const isRelatedDir = importDir === sourceDir || importDir === path56.join(sourceDir, "__tests__") || importDir === path56.join(sourceDir, "tests") || importDir === path56.join(sourceDir, "test") || importDir === path56.join(sourceDir, "spec");
27580
28298
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
27581
28299
  dedupePush(testFiles, testFile);
27582
28300
  break;
@@ -27696,8 +28414,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
27696
28414
  return ["mvn", "test"];
27697
28415
  case "gradle": {
27698
28416
  const isWindows = process.platform === "win32";
27699
- const hasGradlewBat = fs25.existsSync(path54.join(baseDir, "gradlew.bat"));
27700
- const hasGradlew = fs25.existsSync(path54.join(baseDir, "gradlew"));
28417
+ const hasGradlewBat = fs25.existsSync(path56.join(baseDir, "gradlew.bat"));
28418
+ const hasGradlew = fs25.existsSync(path56.join(baseDir, "gradlew"));
27701
28419
  if (hasGradlewBat && isWindows)
27702
28420
  return ["gradlew.bat", "test"];
27703
28421
  if (hasGradlew)
@@ -27714,7 +28432,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
27714
28432
  "cmake-build-release",
27715
28433
  "out"
27716
28434
  ];
27717
- const actualBuildDir = buildDirCandidates.find((d) => fs25.existsSync(path54.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
28435
+ const actualBuildDir = buildDirCandidates.find((d) => fs25.existsSync(path56.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
27718
28436
  return ["ctest", "--test-dir", actualBuildDir];
27719
28437
  }
27720
28438
  case "swift-test":
@@ -28148,11 +28866,11 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd, bail
28148
28866
  };
28149
28867
  }
28150
28868
  const startTime = Date.now();
28151
- const vitestJsonOutputPath = framework === "vitest" ? path54.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
28869
+ const vitestJsonOutputPath = framework === "vitest" ? path56.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
28152
28870
  try {
28153
28871
  if (vitestJsonOutputPath) {
28154
28872
  try {
28155
- fs25.mkdirSync(path54.dirname(vitestJsonOutputPath), { recursive: true });
28873
+ fs25.mkdirSync(path56.dirname(vitestJsonOutputPath), { recursive: true });
28156
28874
  if (fs25.existsSync(vitestJsonOutputPath)) {
28157
28875
  fs25.unlinkSync(vitestJsonOutputPath);
28158
28876
  }
@@ -28320,10 +29038,10 @@ var SKIP_DIRECTORIES = new Set([
28320
29038
  ]);
28321
29039
  function normalizeHistoryTestFile(testFile, workingDir) {
28322
29040
  const normalized = testFile.replace(/\\/g, "/");
28323
- if (!path54.isAbsolute(testFile))
29041
+ if (!path56.isAbsolute(testFile))
28324
29042
  return normalized;
28325
- const relative8 = path54.relative(workingDir, testFile);
28326
- if (relative8.startsWith("..") || path54.isAbsolute(relative8)) {
29043
+ const relative8 = path56.relative(workingDir, testFile);
29044
+ if (relative8.startsWith("..") || path56.isAbsolute(relative8)) {
28327
29045
  return normalized;
28328
29046
  }
28329
29047
  return relative8.replace(/\\/g, "/");
@@ -28562,7 +29280,7 @@ var test_runner = createSwarmTool({
28562
29280
  const sourceFiles = args.files.filter((file) => {
28563
29281
  if (directTestFiles.includes(file))
28564
29282
  return false;
28565
- const ext = path54.extname(file).toLowerCase();
29283
+ const ext = path56.extname(file).toLowerCase();
28566
29284
  return SOURCE_EXTENSIONS.has(ext);
28567
29285
  });
28568
29286
  const invalidFiles = args.files.filter((file) => !directTestFiles.includes(file) && !sourceFiles.includes(file));
@@ -28608,7 +29326,7 @@ var test_runner = createSwarmTool({
28608
29326
  if (isConventionTestFilePath(f)) {
28609
29327
  return false;
28610
29328
  }
28611
- const ext = path54.extname(f).toLowerCase();
29329
+ const ext = path56.extname(f).toLowerCase();
28612
29330
  return SOURCE_EXTENSIONS.has(ext);
28613
29331
  });
28614
29332
  if (sourceFiles.length === 0) {
@@ -28658,7 +29376,7 @@ var test_runner = createSwarmTool({
28658
29376
  if (isConventionTestFilePath(f)) {
28659
29377
  return false;
28660
29378
  }
28661
- const ext = path54.extname(f).toLowerCase();
29379
+ const ext = path56.extname(f).toLowerCase();
28662
29380
  return SOURCE_EXTENSIONS.has(ext);
28663
29381
  });
28664
29382
  if (sourceFiles.length === 0) {
@@ -28710,8 +29428,8 @@ var test_runner = createSwarmTool({
28710
29428
  }
28711
29429
  if (impactResult.impactedTests.length > 0) {
28712
29430
  testFiles = impactResult.impactedTests.map((absPath) => {
28713
- const relativePath = path54.relative(workingDir, absPath);
28714
- return path54.isAbsolute(relativePath) ? absPath : relativePath;
29431
+ const relativePath = path56.relative(workingDir, absPath);
29432
+ return path56.isAbsolute(relativePath) ? absPath : relativePath;
28715
29433
  });
28716
29434
  } else {
28717
29435
  graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
@@ -28806,8 +29524,8 @@ function validateDirectoryPath(dir) {
28806
29524
  if (dir.includes("..")) {
28807
29525
  throw new Error("Directory path must not contain path traversal sequences");
28808
29526
  }
28809
- const normalized = path55.normalize(dir);
28810
- const absolutePath = path55.isAbsolute(normalized) ? normalized : path55.resolve(normalized);
29527
+ const normalized = path57.normalize(dir);
29528
+ const absolutePath = path57.isAbsolute(normalized) ? normalized : path57.resolve(normalized);
28811
29529
  return absolutePath;
28812
29530
  }
28813
29531
  function validateTimeout(timeoutMs, defaultValue) {
@@ -28830,7 +29548,7 @@ function validateTimeout(timeoutMs, defaultValue) {
28830
29548
  }
28831
29549
  function getPackageVersion(dir) {
28832
29550
  try {
28833
- const packagePath = path55.join(dir, "package.json");
29551
+ const packagePath = path57.join(dir, "package.json");
28834
29552
  if (fs26.existsSync(packagePath)) {
28835
29553
  const content = fs26.readFileSync(packagePath, "utf-8");
28836
29554
  const pkg = JSON.parse(content);
@@ -28841,7 +29559,7 @@ function getPackageVersion(dir) {
28841
29559
  }
28842
29560
  function getChangelogVersion(dir) {
28843
29561
  try {
28844
- const changelogPath = path55.join(dir, "CHANGELOG.md");
29562
+ const changelogPath = path57.join(dir, "CHANGELOG.md");
28845
29563
  if (fs26.existsSync(changelogPath)) {
28846
29564
  const content = fs26.readFileSync(changelogPath, "utf-8");
28847
29565
  const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
@@ -28855,7 +29573,7 @@ function getChangelogVersion(dir) {
28855
29573
  function getVersionFileVersion(dir) {
28856
29574
  const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
28857
29575
  for (const file of possibleFiles) {
28858
- const filePath = path55.join(dir, file);
29576
+ const filePath = path57.join(dir, file);
28859
29577
  if (fs26.existsSync(filePath)) {
28860
29578
  try {
28861
29579
  const content = fs26.readFileSync(filePath, "utf-8").trim();
@@ -28871,9 +29589,9 @@ function getVersionFileVersion(dir) {
28871
29589
  async function runVersionCheck(dir, _timeoutMs) {
28872
29590
  const startTime = Date.now();
28873
29591
  try {
28874
- const packageVersion = _internals42.getPackageVersion(dir);
28875
- const changelogVersion = _internals42.getChangelogVersion(dir);
28876
- const versionFileVersion = _internals42.getVersionFileVersion(dir);
29592
+ const packageVersion = _internals43.getPackageVersion(dir);
29593
+ const changelogVersion = _internals43.getChangelogVersion(dir);
29594
+ const versionFileVersion = _internals43.getVersionFileVersion(dir);
28877
29595
  const versions = [];
28878
29596
  if (packageVersion)
28879
29597
  versions.push(`package.json: ${packageVersion}`);
@@ -29237,7 +29955,7 @@ async function runPreflight(dir, phase, config) {
29237
29955
  const reportId = `preflight-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
29238
29956
  let validatedDir;
29239
29957
  try {
29240
- validatedDir = _internals42.validateDirectoryPath(dir);
29958
+ validatedDir = _internals43.validateDirectoryPath(dir);
29241
29959
  } catch (error2) {
29242
29960
  return {
29243
29961
  id: reportId,
@@ -29257,7 +29975,7 @@ async function runPreflight(dir, phase, config) {
29257
29975
  }
29258
29976
  let validatedTimeout;
29259
29977
  try {
29260
- validatedTimeout = _internals42.validateTimeout(config?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
29978
+ validatedTimeout = _internals43.validateTimeout(config?.checkTimeoutMs, DEFAULT_CONFIG.checkTimeoutMs);
29261
29979
  } catch (error2) {
29262
29980
  return {
29263
29981
  id: reportId,
@@ -29298,12 +30016,12 @@ async function runPreflight(dir, phase, config) {
29298
30016
  });
29299
30017
  const checks = [];
29300
30018
  log("[Preflight] Running lint check...");
29301
- const lintResult = await _internals42.runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
30019
+ const lintResult = await _internals43.runLintCheck(validatedDir, cfg.linter, cfg.checkTimeoutMs);
29302
30020
  checks.push(lintResult);
29303
30021
  log(`[Preflight] Lint check: ${lintResult.status} ${lintResult.message}`);
29304
30022
  if (!cfg.skipTests) {
29305
30023
  log("[Preflight] Running tests check...");
29306
- const testsResult = await _internals42.runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
30024
+ const testsResult = await _internals43.runTestsCheck(validatedDir, cfg.testScope, cfg.checkTimeoutMs);
29307
30025
  checks.push(testsResult);
29308
30026
  log(`[Preflight] Tests check: ${testsResult.status} ${testsResult.message}`);
29309
30027
  } else {
@@ -29315,7 +30033,7 @@ async function runPreflight(dir, phase, config) {
29315
30033
  }
29316
30034
  if (!cfg.skipSecrets) {
29317
30035
  log("[Preflight] Running secrets check...");
29318
- const secretsResult = await _internals42.runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
30036
+ const secretsResult = await _internals43.runSecretsCheck(validatedDir, cfg.checkTimeoutMs);
29319
30037
  checks.push(secretsResult);
29320
30038
  log(`[Preflight] Secrets check: ${secretsResult.status} ${secretsResult.message}`);
29321
30039
  } else {
@@ -29327,7 +30045,7 @@ async function runPreflight(dir, phase, config) {
29327
30045
  }
29328
30046
  if (!cfg.skipEvidence) {
29329
30047
  log("[Preflight] Running evidence check...");
29330
- const evidenceResult = await _internals42.runEvidenceCheck(validatedDir);
30048
+ const evidenceResult = await _internals43.runEvidenceCheck(validatedDir);
29331
30049
  checks.push(evidenceResult);
29332
30050
  log(`[Preflight] Evidence check: ${evidenceResult.status} ${evidenceResult.message}`);
29333
30051
  } else {
@@ -29338,12 +30056,12 @@ async function runPreflight(dir, phase, config) {
29338
30056
  });
29339
30057
  }
29340
30058
  log("[Preflight] Running requirement coverage check...");
29341
- const reqCoverageResult = await _internals42.runRequirementCoverageCheck(validatedDir, phase);
30059
+ const reqCoverageResult = await _internals43.runRequirementCoverageCheck(validatedDir, phase);
29342
30060
  checks.push(reqCoverageResult);
29343
30061
  log(`[Preflight] Requirement coverage check: ${reqCoverageResult.status} ${reqCoverageResult.message}`);
29344
30062
  if (!cfg.skipVersion) {
29345
30063
  log("[Preflight] Running version check...");
29346
- const versionResult = await _internals42.runVersionCheck(validatedDir, cfg.checkTimeoutMs);
30064
+ const versionResult = await _internals43.runVersionCheck(validatedDir, cfg.checkTimeoutMs);
29347
30065
  checks.push(versionResult);
29348
30066
  log(`[Preflight] Version check: ${versionResult.status} ${versionResult.message}`);
29349
30067
  } else {
@@ -29406,10 +30124,10 @@ function formatPreflightMarkdown(report) {
29406
30124
  async function handlePreflightCommand(directory, _args) {
29407
30125
  const plan = await loadPlan(directory);
29408
30126
  const phase = plan?.current_phase ?? 1;
29409
- const report = await _internals42.runPreflight(directory, phase);
29410
- return _internals42.formatPreflightMarkdown(report);
30127
+ const report = await _internals43.runPreflight(directory, phase);
30128
+ return _internals43.formatPreflightMarkdown(report);
29411
30129
  }
29412
- var _internals42 = {
30130
+ var _internals43 = {
29413
30131
  runPreflight,
29414
30132
  formatPreflightMarkdown,
29415
30133
  handlePreflightCommand,
@@ -29593,7 +30311,7 @@ async function handleQaGatesCommand(directory, args, sessionID) {
29593
30311
 
29594
30312
  // src/commands/reset.ts
29595
30313
  import * as fs27 from "fs";
29596
- import * as path56 from "path";
30314
+ import * as path58 from "path";
29597
30315
 
29598
30316
  // src/background/circuit-breaker.ts
29599
30317
  class CircuitBreaker {
@@ -30312,7 +31030,7 @@ async function handleResetCommand(directory, args) {
30312
31030
  }
30313
31031
  for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
30314
31032
  try {
30315
- const rootPath = path56.join(directory, filename);
31033
+ const rootPath = path58.join(directory, filename);
30316
31034
  if (fs27.existsSync(rootPath)) {
30317
31035
  fs27.unlinkSync(rootPath);
30318
31036
  results.push(`- \u2705 Deleted ${filename} (root)`);
@@ -30350,7 +31068,7 @@ async function handleResetCommand(directory, args) {
30350
31068
 
30351
31069
  // src/commands/reset-session.ts
30352
31070
  import * as fs29 from "fs";
30353
- import * as path58 from "path";
31071
+ import * as path60 from "path";
30354
31072
 
30355
31073
  // src/hooks/trajectory-logger.ts
30356
31074
  var callStartTimes = new Map;
@@ -30757,16 +31475,16 @@ function detectPatterns(trajectory, config, lastProcessedStep = 0) {
30757
31475
  }
30758
31476
  // src/prm/replay.ts
30759
31477
  import { promises as fs28 } from "fs";
30760
- import path57 from "path";
31478
+ import path59 from "path";
30761
31479
  function isPathSafe(targetPath, basePath) {
30762
- const resolvedTarget = path57.resolve(targetPath);
30763
- const resolvedBase = path57.resolve(basePath);
30764
- const rel = path57.relative(resolvedBase, resolvedTarget);
30765
- return !rel.startsWith("..") && !path57.isAbsolute(rel);
31480
+ const resolvedTarget = path59.resolve(targetPath);
31481
+ const resolvedBase = path59.resolve(basePath);
31482
+ const rel = path59.relative(resolvedBase, resolvedTarget);
31483
+ return !rel.startsWith("..") && !path59.isAbsolute(rel);
30766
31484
  }
30767
31485
  function isWithinReplaysDir(targetPath) {
30768
- const resolved = path57.resolve(targetPath);
30769
- const parts = resolved.split(path57.sep);
31486
+ const resolved = path59.resolve(targetPath);
31487
+ const parts = resolved.split(path59.sep);
30770
31488
  for (let i = 0;i < parts.length - 1; i++) {
30771
31489
  if (parts[i] === ".swarm" && parts[i + 1] === "replays") {
30772
31490
  return true;
@@ -30779,10 +31497,10 @@ function sanitizeFilename(input) {
30779
31497
  }
30780
31498
  async function startReplayRecording(sessionID, directory) {
30781
31499
  try {
30782
- const replayDir = path57.join(directory, ".swarm", "replays");
31500
+ const replayDir = path59.join(directory, ".swarm", "replays");
30783
31501
  const safeSessionID = sanitizeFilename(sessionID);
30784
31502
  const filename = `${safeSessionID}-${Date.now()}.jsonl`;
30785
- const filepath = path57.join(replayDir, filename);
31503
+ const filepath = path59.join(replayDir, filename);
30786
31504
  if (!isPathSafe(filepath, replayDir)) {
30787
31505
  console.warn(`[replay] Invalid path detected - path traversal attempt blocked for session ${sessionID}`);
30788
31506
  return null;
@@ -30814,7 +31532,7 @@ async function recordReplayEntry(artifactPath, sessionID, entry) {
30814
31532
  }
30815
31533
 
30816
31534
  // src/prm/index.ts
30817
- var _internals43 = {
31535
+ var _internals44 = {
30818
31536
  getAgentSession,
30819
31537
  readTrajectory,
30820
31538
  getInMemoryTrajectory,
@@ -30837,7 +31555,7 @@ function resetPrmSessionState(session, sessionId) {
30837
31555
  session.prmTrajectoryStep = 0;
30838
31556
  session.replayArtifactPath = null;
30839
31557
  if (sessionId) {
30840
- _internals43.clearTrajectoryCache(sessionId);
31558
+ _internals44.clearTrajectoryCache(sessionId);
30841
31559
  }
30842
31560
  }
30843
31561
 
@@ -30860,7 +31578,7 @@ async function handleResetSessionCommand(directory, _args) {
30860
31578
  } catch {
30861
31579
  results.push("\u274C Failed to delete state.json");
30862
31580
  }
30863
- const sessionDir = path58.dirname(validateSwarmPath(directory, "session/state.json"));
31581
+ const sessionDir = path60.dirname(validateSwarmPath(directory, "session/state.json"));
30864
31582
  let sessionFiles = [];
30865
31583
  if (fs29.existsSync(sessionDir)) {
30866
31584
  try {
@@ -30872,7 +31590,7 @@ async function handleResetSessionCommand(directory, _args) {
30872
31590
  for (const file of sessionFiles) {
30873
31591
  if (file === "state.json")
30874
31592
  continue;
30875
- const filePath = path58.join(sessionDir, file);
31593
+ const filePath = path60.join(sessionDir, file);
30876
31594
  try {
30877
31595
  if (!fs29.existsSync(filePath))
30878
31596
  continue;
@@ -30907,7 +31625,7 @@ async function handleResetSessionCommand(directory, _args) {
30907
31625
  }
30908
31626
 
30909
31627
  // src/summaries/manager.ts
30910
- import * as path59 from "path";
31628
+ import * as path61 from "path";
30911
31629
  var SUMMARY_ID_REGEX = /^S\d+$/;
30912
31630
  function sanitizeSummaryId(id) {
30913
31631
  if (!id || id.length === 0) {
@@ -30931,7 +31649,7 @@ function sanitizeSummaryId(id) {
30931
31649
  }
30932
31650
  async function loadFullOutput(directory, id) {
30933
31651
  const sanitizedId = sanitizeSummaryId(id);
30934
- const relativePath = path59.join("summaries", `${sanitizedId}.json`);
31652
+ const relativePath = path61.join("summaries", `${sanitizedId}.json`);
30935
31653
  validateSwarmPath(directory, relativePath);
30936
31654
  const content = await readSwarmFileAsync(directory, relativePath);
30937
31655
  if (content === null) {
@@ -30984,7 +31702,7 @@ ${error2 instanceof Error ? error2.message : String(error2)}`;
30984
31702
 
30985
31703
  // src/commands/rollback.ts
30986
31704
  import * as fs30 from "fs";
30987
- import * as path60 from "path";
31705
+ import * as path62 from "path";
30988
31706
  async function handleRollbackCommand(directory, args) {
30989
31707
  const phaseArg = args[0];
30990
31708
  if (!phaseArg) {
@@ -31050,8 +31768,8 @@ async function handleRollbackCommand(directory, args) {
31050
31768
  if (EXCLUDE_FILES.has(file) || file.startsWith("plan-ledger.archived-")) {
31051
31769
  continue;
31052
31770
  }
31053
- const src = path60.join(checkpointDir, file);
31054
- const dest = path60.join(swarmDir, file);
31771
+ const src = path62.join(checkpointDir, file);
31772
+ const dest = path62.join(swarmDir, file);
31055
31773
  try {
31056
31774
  fs30.cpSync(src, dest, { recursive: true, force: true });
31057
31775
  successes.push(file);
@@ -31070,7 +31788,7 @@ async function handleRollbackCommand(directory, args) {
31070
31788
  ].join(`
31071
31789
  `);
31072
31790
  }
31073
- const existingLedgerPath = path60.join(swarmDir, "plan-ledger.jsonl");
31791
+ const existingLedgerPath = path62.join(swarmDir, "plan-ledger.jsonl");
31074
31792
  let ledgerDeletionFailed = false;
31075
31793
  if (fs30.existsSync(existingLedgerPath)) {
31076
31794
  try {
@@ -31083,7 +31801,7 @@ async function handleRollbackCommand(directory, args) {
31083
31801
  }
31084
31802
  if (!ledgerDeletionFailed) {
31085
31803
  try {
31086
- const planJsonPath = path60.join(swarmDir, "plan.json");
31804
+ const planJsonPath = path62.join(swarmDir, "plan.json");
31087
31805
  if (fs30.existsSync(planJsonPath)) {
31088
31806
  const planRaw = fs30.readFileSync(planJsonPath, "utf-8");
31089
31807
  const plan = PlanSchema.parse(JSON.parse(planRaw));
@@ -31344,10 +32062,10 @@ Ensure this is a git repository with commit history.`;
31344
32062
  `);
31345
32063
  try {
31346
32064
  const fs31 = await import("fs/promises");
31347
- const path61 = await import("path");
31348
- const reportPath = path61.join(directory, ".swarm", "simulate-report.md");
31349
- await fs31.mkdir(path61.dirname(reportPath), { recursive: true });
31350
- const reportTempPath = path61.join(path61.dirname(reportPath), `${path61.basename(reportPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
32065
+ const path63 = await import("path");
32066
+ const reportPath = path63.join(directory, ".swarm", "simulate-report.md");
32067
+ await fs31.mkdir(path63.dirname(reportPath), { recursive: true });
32068
+ const reportTempPath = path63.join(path63.dirname(reportPath), `${path63.basename(reportPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
31351
32069
  try {
31352
32070
  await fs31.writeFile(reportTempPath, report, "utf-8");
31353
32071
  renameSync11(reportTempPath, reportPath);
@@ -31376,18 +32094,18 @@ async function handleSpecifyCommand(_directory, args) {
31376
32094
  // src/services/status-service.ts
31377
32095
  import * as fsSync3 from "fs";
31378
32096
  import { readFile as readFile16 } from "fs/promises";
31379
- import * as path62 from "path";
32097
+ import * as path64 from "path";
31380
32098
 
31381
32099
  // src/turbo/lean/state.ts
31382
32100
  init_logger();
31383
32101
  import * as fs31 from "fs";
31384
- import * as path61 from "path";
32102
+ import * as path63 from "path";
31385
32103
  var STATE_FILE3 = "turbo-state.json";
31386
32104
  function nowISO3() {
31387
32105
  return new Date().toISOString();
31388
32106
  }
31389
32107
  function ensureSwarmDir2(directory) {
31390
- const swarmDir = path61.resolve(directory, ".swarm");
32108
+ const swarmDir = path63.resolve(directory, ".swarm");
31391
32109
  if (!fs31.existsSync(swarmDir)) {
31392
32110
  fs31.mkdirSync(swarmDir, { recursive: true });
31393
32111
  }
@@ -31432,7 +32150,7 @@ function markStateUnreadable2(directory, reason) {
31432
32150
  }
31433
32151
  function readPersisted2(directory) {
31434
32152
  try {
31435
- const filePath = path61.join(directory, ".swarm", STATE_FILE3);
32153
+ const filePath = path63.join(directory, ".swarm", STATE_FILE3);
31436
32154
  if (!fs31.existsSync(filePath)) {
31437
32155
  const seed = emptyPersisted2();
31438
32156
  try {
@@ -31468,7 +32186,7 @@ function writePersisted2(directory, persisted) {
31468
32186
  let payload;
31469
32187
  try {
31470
32188
  ensureSwarmDir2(directory);
31471
- filePath = path61.join(directory, ".swarm", STATE_FILE3);
32189
+ filePath = path63.join(directory, ".swarm", STATE_FILE3);
31472
32190
  tmpPath = `${filePath}.tmp.${Date.now()}`;
31473
32191
  persisted.updatedAt = nowISO3();
31474
32192
  payload = `${JSON.stringify(persisted, null, 2)}
@@ -31579,14 +32297,14 @@ var DEFAULT_CONTEXT_BUDGET_CONFIG = {
31579
32297
  };
31580
32298
 
31581
32299
  // src/services/status-service.ts
31582
- var _internals44 = {
32300
+ var _internals45 = {
31583
32301
  loadLeanTurboRunState,
31584
32302
  hasActiveLeanTurbo,
31585
32303
  hasActiveFullAuto
31586
32304
  };
31587
32305
  function readSpecStalenessSnapshot(directory) {
31588
32306
  try {
31589
- const p = path62.join(directory, ".swarm", "spec-staleness.json");
32307
+ const p = path64.join(directory, ".swarm", "spec-staleness.json");
31590
32308
  if (!fsSync3.existsSync(p))
31591
32309
  return { stale: false };
31592
32310
  const raw = fsSync3.readFileSync(p, "utf-8");
@@ -31684,7 +32402,7 @@ async function getStatusData(directory, agents) {
31684
32402
  }
31685
32403
  function enrichWithLeanTurbo(status, directory) {
31686
32404
  const turboMode = hasActiveTurboMode();
31687
- const leanActive = _internals44.hasActiveLeanTurbo();
32405
+ const leanActive = _internals45.hasActiveLeanTurbo();
31688
32406
  let turboStrategy = "off";
31689
32407
  if (leanActive) {
31690
32408
  turboStrategy = "lean";
@@ -31703,7 +32421,7 @@ function enrichWithLeanTurbo(status, directory) {
31703
32421
  }
31704
32422
  }
31705
32423
  if (leanSessionID) {
31706
- const runState = _internals44.loadLeanTurboRunState(directory, leanSessionID);
32424
+ const runState = _internals45.loadLeanTurboRunState(directory, leanSessionID);
31707
32425
  if (runState) {
31708
32426
  status.leanTurboPhase = runState.phase;
31709
32427
  status.leanMaxParallelCoders = runState.maxParallelCoders;
@@ -31735,7 +32453,7 @@ function enrichWithLeanTurbo(status, directory) {
31735
32453
  }
31736
32454
  }
31737
32455
  }
31738
- status.fullAutoActive = _internals44.hasActiveFullAuto();
32456
+ status.fullAutoActive = _internals45.hasActiveFullAuto();
31739
32457
  return status;
31740
32458
  }
31741
32459
  function formatStatusMarkdown(status) {
@@ -31889,7 +32607,7 @@ No active swarm plan found. Nothing to sync.`;
31889
32607
 
31890
32608
  // src/commands/turbo.ts
31891
32609
  init_logger();
31892
- var _internals45 = {
32610
+ var _internals46 = {
31893
32611
  loadPluginConfigWithMeta
31894
32612
  };
31895
32613
  async function handleTurboCommand(directory, args, sessionID) {
@@ -31949,7 +32667,7 @@ async function handleTurboCommand(directory, args, sessionID) {
31949
32667
  if (arg0 === "on") {
31950
32668
  let strategy = "standard";
31951
32669
  try {
31952
- const { config } = _internals45.loadPluginConfigWithMeta(directory);
32670
+ const { config } = _internals46.loadPluginConfigWithMeta(directory);
31953
32671
  if (config.turbo?.strategy === "lean") {
31954
32672
  strategy = "lean";
31955
32673
  }
@@ -32046,7 +32764,7 @@ function enableLeanTurbo(session, directory, sessionID) {
32046
32764
  let maxParallelCoders = 4;
32047
32765
  let conflictPolicy = "serialize";
32048
32766
  try {
32049
- const { config } = _internals45.loadPluginConfigWithMeta(directory);
32767
+ const { config } = _internals46.loadPluginConfigWithMeta(directory);
32050
32768
  const leanConfig = config.turbo?.lean;
32051
32769
  if (leanConfig) {
32052
32770
  maxParallelCoders = leanConfig.max_parallel_coders ?? 4;
@@ -32119,11 +32837,11 @@ function buildStatusMessage2(session, directory, sessionID) {
32119
32837
 
32120
32838
  // src/commands/unlink.ts
32121
32839
  import { existsSync as existsSync37 } from "fs";
32122
- import * as path63 from "path";
32840
+ import * as path65 from "path";
32123
32841
  var DEDUP_THRESHOLD2 = 0.6;
32124
32842
  async function copySharedKnowledgeToLocal(linkDir, localSwarmDir) {
32125
- const sharedPath = path63.join(linkDir, "knowledge.jsonl");
32126
- const localPath = path63.join(localSwarmDir, "knowledge.jsonl");
32843
+ const sharedPath = path65.join(linkDir, "knowledge.jsonl");
32844
+ const localPath = path65.join(localSwarmDir, "knowledge.jsonl");
32127
32845
  if (!existsSync37(sharedPath))
32128
32846
  return 0;
32129
32847
  const sharedEntries = await readKnowledge(sharedPath);
@@ -32158,7 +32876,7 @@ async function handleUnlinkCommand(directory, args) {
32158
32876
  let copied = 0;
32159
32877
  if (copyBack) {
32160
32878
  try {
32161
- copied = await copySharedKnowledgeToLocal(linkDir, path63.join(directory, ".swarm"));
32879
+ copied = await copySharedKnowledgeToLocal(linkDir, path65.join(directory, ".swarm"));
32162
32880
  } catch (error2) {
32163
32881
  return `\u274C Failed to copy shared knowledge back to local: ${error2 instanceof Error ? error2.message : String(error2)}`;
32164
32882
  }
@@ -32262,7 +32980,7 @@ function findSimilarCommands(query) {
32262
32980
  }
32263
32981
  const scored = VALID_COMMANDS.map((cmd) => {
32264
32982
  const cmdLower = cmd.toLowerCase();
32265
- const fullScore = _internals46.levenshteinDistance(q, cmdLower);
32983
+ const fullScore = _internals47.levenshteinDistance(q, cmdLower);
32266
32984
  let tokenScore = Infinity;
32267
32985
  if (cmd.includes(" ") || cmd.includes("-")) {
32268
32986
  const qTokens = q.split(/[\s-]+/);
@@ -32275,7 +32993,7 @@ function findSimilarCommands(query) {
32275
32993
  for (const ct of cmdTokens) {
32276
32994
  if (ct.length === 0)
32277
32995
  continue;
32278
- const dist = _internals46.levenshteinDistance(qt, ct);
32996
+ const dist = _internals47.levenshteinDistance(qt, ct);
32279
32997
  if (dist < minDist)
32280
32998
  minDist = dist;
32281
32999
  }
@@ -32285,7 +33003,7 @@ function findSimilarCommands(query) {
32285
33003
  }
32286
33004
  const dashStrippedQ = q.replace(/-/g, "");
32287
33005
  const dashStrippedCmd = cmdLower.replace(/-/g, "");
32288
- const dashScore = _internals46.levenshteinDistance(dashStrippedQ, dashStrippedCmd);
33006
+ const dashScore = _internals47.levenshteinDistance(dashStrippedQ, dashStrippedCmd);
32289
33007
  const score = Math.min(fullScore, tokenScore, dashScore);
32290
33008
  return { cmd, score };
32291
33009
  });
@@ -32320,16 +33038,16 @@ function buildDetailedHelp(commandName, entry) {
32320
33038
  async function handleHelpCommand(ctx) {
32321
33039
  const targetCommand = ctx.args.join(" ");
32322
33040
  if (!targetCommand) {
32323
- const { buildHelpText } = await import("./index-sz3kw59p.js");
33041
+ const { buildHelpText } = await import("./index-jg6m72g7.js");
32324
33042
  return buildHelpText();
32325
33043
  }
32326
33044
  const tokens = targetCommand.split(/\s+/);
32327
- const resolved = _internals46.resolveCommand(tokens);
33045
+ const resolved = _internals47.resolveCommand(tokens);
32328
33046
  if (resolved) {
32329
- return _internals46.buildDetailedHelp(resolved.key, resolved.entry);
33047
+ return _internals47.buildDetailedHelp(resolved.key, resolved.entry);
32330
33048
  }
32331
- const similar = _internals46.findSimilarCommands(targetCommand);
32332
- const { buildHelpText: fullHelp } = await import("./index-sz3kw59p.js");
33049
+ const similar = _internals47.findSimilarCommands(targetCommand);
33050
+ const { buildHelpText: fullHelp } = await import("./index-jg6m72g7.js");
32333
33051
  if (similar.length > 0) {
32334
33052
  return `Command '/swarm ${targetCommand}' not found.
32335
33053
 
@@ -32393,7 +33111,7 @@ var COMMAND_REGISTRY = {
32393
33111
  toolNoArgs: true
32394
33112
  },
32395
33113
  help: {
32396
- handler: (ctx) => _internals46.handleHelpCommand(ctx),
33114
+ handler: (ctx) => _internals47.handleHelpCommand(ctx),
32397
33115
  description: "Show help for swarm commands",
32398
33116
  category: "core",
32399
33117
  args: "[command]",
@@ -32462,7 +33180,7 @@ var COMMAND_REGISTRY = {
32462
33180
  },
32463
33181
  "guardrail explain": {
32464
33182
  handler: async (ctx) => {
32465
- const { handleGuardrailExplain } = await import("./guardrail-explain-dkh5f7nf.js");
33183
+ const { handleGuardrailExplain } = await import("./guardrail-explain-q8pj9691.js");
32466
33184
  return handleGuardrailExplain(ctx.directory, ctx.args);
32467
33185
  },
32468
33186
  description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
@@ -32472,7 +33190,7 @@ var COMMAND_REGISTRY = {
32472
33190
  },
32473
33191
  "guardrail-log": {
32474
33192
  handler: async (ctx) => {
32475
- const { handleGuardrailLog } = await import("./guardrail-log-ya49kpwn.js");
33193
+ const { handleGuardrailLog } = await import("./guardrail-log-ywajkn46.js");
32476
33194
  return handleGuardrailLog(ctx.directory, ctx.args);
32477
33195
  },
32478
33196
  description: "Read the guardrail decision log (use --blocks-only for blocks)",
@@ -33235,24 +33953,24 @@ function validateAliases() {
33235
33953
  continue;
33236
33954
  }
33237
33955
  const visited = new Set;
33238
- const path64 = [];
33956
+ const path66 = [];
33239
33957
  let current = target;
33240
33958
  while (current) {
33241
33959
  const currentEntry = COMMAND_REGISTRY[current];
33242
33960
  if (!currentEntry)
33243
33961
  break;
33244
33962
  if (visited.has(current)) {
33245
- const cycleStart = path64.indexOf(current);
33963
+ const cycleStart = path66.indexOf(current);
33246
33964
  const fullChain = [
33247
33965
  name,
33248
- ...path64.slice(0, cycleStart > 0 ? cycleStart : path64.length),
33966
+ ...path66.slice(0, cycleStart > 0 ? cycleStart : path66.length),
33249
33967
  current
33250
33968
  ].join(" \u2192 ");
33251
33969
  errors.push(`Circular alias detected: ${fullChain}`);
33252
33970
  break;
33253
33971
  }
33254
33972
  visited.add(current);
33255
- path64.push(current);
33973
+ path66.push(current);
33256
33974
  current = currentEntry.aliasOf || "";
33257
33975
  }
33258
33976
  }
@@ -33271,7 +33989,7 @@ function validateToolPolicy() {
33271
33989
  }
33272
33990
  return { valid: warnings.length === 0, warnings };
33273
33991
  }
33274
- var _internals46 = {
33992
+ var _internals47 = {
33275
33993
  handleHelpCommand,
33276
33994
  validateAliases,
33277
33995
  validateToolPolicy,
@@ -33281,16 +33999,16 @@ var _internals46 = {
33281
33999
  findSimilarCommands,
33282
34000
  buildDetailedHelp
33283
34001
  };
33284
- var validation = _internals46.validateAliases();
34002
+ var validation = _internals47.validateAliases();
33285
34003
  if (!validation.valid) {
33286
34004
  throw new Error(`COMMAND_REGISTRY alias validation failed:
33287
34005
  ${validation.errors.join(`
33288
34006
  `)}`);
33289
34007
  }
33290
- _internals46.emitValidationWarnings("COMMAND_REGISTRY alias warnings", validation.warnings);
34008
+ _internals47.emitValidationWarnings("COMMAND_REGISTRY alias warnings", validation.warnings);
33291
34009
  try {
33292
- const toolPolicyValidation = _internals46.validateToolPolicy();
33293
- _internals46.emitValidationWarnings("COMMAND_REGISTRY toolPolicy warnings", toolPolicyValidation.warnings);
34010
+ const toolPolicyValidation = _internals47.validateToolPolicy();
34011
+ _internals47.emitValidationWarnings("COMMAND_REGISTRY toolPolicy warnings", toolPolicyValidation.warnings);
33294
34012
  } catch (e) {
33295
34013
  warn(`COMMAND_REGISTRY toolPolicy validation failed (non-fatal): ${e.message}`);
33296
34014
  }
@@ -33349,7 +34067,7 @@ function formatCommandNotFound(tokens) {
33349
34067
  const attemptedCommand = tokens[0] || "";
33350
34068
  const MAX_DISPLAY = 100;
33351
34069
  const displayCommand = attemptedCommand.length > MAX_DISPLAY ? `${attemptedCommand.slice(0, MAX_DISPLAY)}...` : attemptedCommand;
33352
- const similar = _internals46.findSimilarCommands(attemptedCommand);
34070
+ const similar = _internals47.findSimilarCommands(attemptedCommand);
33353
34071
  const header = `Command \`/swarm ${displayCommand}\` not found.`;
33354
34072
  const suggestions = similar.length > 0 ? `Did you mean:
33355
34073
  ${similar.map((cmd) => ` - /swarm ${cmd}`).join(`
@@ -33406,4 +34124,4 @@ ${text}`;
33406
34124
  };
33407
34125
  }
33408
34126
 
33409
- export { package_default, handleAcknowledgeSpecDriftCommand, handleAgentsCommand, handleAnalyzeCommand, handleArchiveCommand, DC_SAFE_TARGETS, dcNormalizeCommand, dcUnwrapWrappers, dcSplitSegments, dcValidateTargets, dcCheckJunctionCreation, dcExtractWindowsCmdTargets, dcExtractPowerShellTargets, normalizeSwarmCommandInput, canonicalCommandKey, formatCommandNotFound, executeSwarmCommand, SWARM_COMMAND_TOOL_COMMANDS, SWARM_COMMAND_TOOL_ALLOWLIST, HUMAN_ONLY_SWARM_COMMANDS, classifySwarmCommandToolUse, classifySwarmCommandChatFallbackUse, detectPosixWrites, detectWindowsWrites, resolveWriteTargets, handleAutoProceedCommand, handleBenchmarkCommand, handleBrainstormCommand, handleCheckpointCommand, handleClarifyCommand, handleCloseCommand, handleCodebaseReviewCommand, handleConcurrencyCommand, handleConfigCommand, handleConsolidateCommand, handleCostsCommand, handleCouncilCommand, handleCurateCommand, handleDarkMatterCommand, handleDeepDiveCommand, handleDeepResearchCommand, getPluginConfigDir, getPluginCachePaths, getPluginLockFilePaths, handleDiagnoseCommand, handleDoctorCommand, handleEvidenceCommand, handleEvidenceSummaryCommand, handleExportCommand, handleFullAutoCommand, handleHandoffCommand, handleHistoryCommand, handleKnowledgeQuarantineCommand, handleKnowledgeRestoreCommand, handleKnowledgeMigrateCommand, handleKnowledgeListCommand, handleKnowledgeUnactionableCommand, handleKnowledgeRetryHardeningCommand, handleLearningCommand, handleLinkCommand, handleMemoryCommand, handleMemoryStatusCommand, handleMemoryMigrateCommand, handleMemoryImportCommand, handleMemoryExportCommand, handlePlanCommand, handlePreflightCommand, handlePromoteCommand, handleQaGatesCommand, handleResetCommand, handleResetSessionCommand, handleRetrieveCommand, handleRollbackCommand, handleSddStatusCommand, handleSddValidateCommand, handleSddProjectCommand, handleSddCommand, handleSimulateCommand, handleSpecifyCommand, handleStatusCommand, handleSyncPlanCommand, handleTurboCommand, handleUnlinkCommand, handleWriteRetroCommand, handleHelpCommand, COMMAND_REGISTRY, VALID_COMMANDS, _internals46 as _internals, resolveCommand };
34127
+ export { package_default, handleAcknowledgeSpecDriftCommand, handleAgentsCommand, handleAnalyzeCommand, handleArchiveCommand, DC_SAFE_TARGETS, dcNormalizeCommand, dcUnwrapWrappers, dcSplitSegments, dcValidateTargets, dcCheckJunctionCreation, dcExtractWindowsCmdTargets, dcExtractPowerShellTargets, normalizeSwarmCommandInput, canonicalCommandKey, formatCommandNotFound, executeSwarmCommand, SWARM_COMMAND_TOOL_COMMANDS, SWARM_COMMAND_TOOL_ALLOWLIST, HUMAN_ONLY_SWARM_COMMANDS, classifySwarmCommandToolUse, classifySwarmCommandChatFallbackUse, detectPosixWrites, detectWindowsWrites, resolveWriteTargets, handleAutoProceedCommand, handleBenchmarkCommand, handleBrainstormCommand, handleCheckpointCommand, handleClarifyCommand, handleCloseCommand, handleCodebaseReviewCommand, handleConcurrencyCommand, handleConfigCommand, handleConsolidateCommand, handleCostsCommand, handleCouncilCommand, handleCurateCommand, handleDarkMatterCommand, handleDeepDiveCommand, handleDeepResearchCommand, getPluginConfigDir, getPluginCachePaths, getPluginLockFilePaths, handleDiagnoseCommand, handleDoctorCommand, handleEvidenceCommand, handleEvidenceSummaryCommand, handleExportCommand, handleFullAutoCommand, handleHandoffCommand, handleHistoryCommand, handleKnowledgeQuarantineCommand, handleKnowledgeRestoreCommand, handleKnowledgeMigrateCommand, handleKnowledgeListCommand, handleKnowledgeUnactionableCommand, handleKnowledgeRetryHardeningCommand, handleLearningCommand, handleLinkCommand, handleMemoryCommand, handleMemoryStatusCommand, handleMemoryMigrateCommand, handleMemoryImportCommand, handleMemoryExportCommand, handlePlanCommand, handlePreflightCommand, handlePromoteCommand, handleQaGatesCommand, handleResetCommand, handleResetSessionCommand, handleRetrieveCommand, handleRollbackCommand, handleSddStatusCommand, handleSddValidateCommand, handleSddProjectCommand, handleSddCommand, handleSimulateCommand, handleSpecifyCommand, handleStatusCommand, handleSyncPlanCommand, handleTurboCommand, handleUnlinkCommand, handleWriteRetroCommand, handleHelpCommand, COMMAND_REGISTRY, VALID_COMMANDS, _internals47 as _internals, resolveCommand };