opencode-swarm 7.87.3 → 7.88.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/.opencode/skills/brainstorm/SKILL.md +2 -1
  2. package/.opencode/skills/clarify/SKILL.md +7 -1
  3. package/.opencode/skills/clarify-spec/SKILL.md +1 -1
  4. package/.opencode/skills/issue-ingest/SKILL.md +3 -2
  5. package/.opencode/skills/plan/SKILL.md +7 -1
  6. package/.opencode/skills/specify/SKILL.md +3 -2
  7. package/.opencode/skills/swarm-pr-review/SKILL.md +304 -9
  8. package/README.md +1 -0
  9. package/dist/background/candidate-parser.d.ts +189 -0
  10. package/dist/background/candidate-sidecar-store.d.ts +56 -0
  11. package/dist/cli/{config-doctor-6h64pn8n.js → config-doctor-jzbgpbdh.js} +2 -2
  12. package/dist/cli/{guardrail-explain-2q9myk7c.js → guardrail-explain-995zavv8.js} +5 -5
  13. package/dist/cli/{guardrail-log-eegabqcp.js → guardrail-log-c7egm5km.js} +3 -3
  14. package/dist/cli/{index-q9h0wb04.js → index-0asbrmdx.js} +4 -0
  15. package/dist/cli/{index-kz1bmebr.js → index-4td9ef53.js} +523 -229
  16. package/dist/cli/{index-1cb4wxnm.js → index-819xp49y.js} +1 -1
  17. package/dist/cli/{index-5hvbw5xh.js → index-g00qm2gf.js} +1 -1
  18. package/dist/cli/{index-r3f47swm.js → index-sr7g2msm.js} +6 -6
  19. package/dist/cli/{index-amwa268r.js → index-tt5aehrb.js} +2 -2
  20. package/dist/cli/{index-5vpe6vq9.js → index-vjsr9bqt.js} +1 -1
  21. package/dist/cli/index.js +4 -4
  22. package/dist/cli/{schema-84146tvk.js → schema-vb6jkxgg.js} +1 -1
  23. package/dist/index.js +2114 -991
  24. package/dist/memory/config.d.ts +1 -0
  25. package/dist/memory/gateway.d.ts +1 -0
  26. package/dist/memory/provider-pool.d.ts +50 -0
  27. package/dist/memory/sqlite-provider.d.ts +3 -0
  28. package/dist/tools/index.d.ts +1 -0
  29. package/dist/tools/manifest.d.ts +1 -0
  30. package/dist/tools/parse-lane-candidates.d.ts +2 -0
  31. package/dist/tools/tool-metadata.d.ts +4 -0
  32. package/package.json +1 -1
@@ -47,7 +47,7 @@ import {
47
47
  readDoctorArtifact,
48
48
  removeStraySwarmDir,
49
49
  runConfigDoctor
50
- } from "./index-1cb4wxnm.js";
50
+ } from "./index-819xp49y.js";
51
51
  import {
52
52
  AGENT_TOOL_MAP,
53
53
  ALL_SUBAGENT_NAMES,
@@ -60,7 +60,7 @@ import {
60
60
  TOOL_NAME_SET,
61
61
  resolveExternalSkillsConfig,
62
62
  stripKnownSwarmPrefix
63
- } from "./index-q9h0wb04.js";
63
+ } from "./index-0asbrmdx.js";
64
64
  import {
65
65
  MAX_TRANSIENT_RETRIES,
66
66
  PlanSchema,
@@ -899,7 +899,7 @@ var init_executor = __esm(() => {
899
899
  // package.json
900
900
  var package_default = {
901
901
  name: "opencode-swarm",
902
- version: "7.87.3",
902
+ version: "7.88.1",
903
903
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
904
904
  main: "dist/index.js",
905
905
  types: "dist/index.d.ts",
@@ -11539,7 +11539,7 @@ async function runFinalizeStage(ctx) {
11539
11539
  }
11540
11540
  }
11541
11541
  try {
11542
- const { CuratorConfigSchema: CCS } = await import("./schema-84146tvk.js");
11542
+ const { CuratorConfigSchema: CCS } = await import("./schema-vb6jkxgg.js");
11543
11543
  const { config: pmLoadedConfig } = _internals20.loadPluginConfigWithMeta(ctx.directory);
11544
11544
  const curatorCfg = CCS.parse(pmLoadedConfig.curator ?? {});
11545
11545
  if (curatorCfg.enabled && curatorCfg.postmortem_enabled) {
@@ -15220,7 +15220,7 @@ async function handleDoctorCommand(directory, args) {
15220
15220
  const result = runConfigDoctor(config, directory);
15221
15221
  let output;
15222
15222
  if (enableAutoFix && result.hasAutoFixableIssues) {
15223
- const { runConfigDoctorWithFixes } = await import("./config-doctor-6h64pn8n.js");
15223
+ const { runConfigDoctorWithFixes } = await import("./config-doctor-jzbgpbdh.js");
15224
15224
  const fixResult = await runConfigDoctorWithFixes(directory, config, true);
15225
15225
  output = formatDoctorMarkdown(fixResult.result);
15226
15226
  } else {
@@ -18335,7 +18335,7 @@ ${USAGE7}`;
18335
18335
 
18336
18336
  // src/commands/memory.ts
18337
18337
  import { existsSync as existsSync25 } from "fs";
18338
- import * as path42 from "path";
18338
+ import * as path43 from "path";
18339
18339
  import { fileURLToPath as fileURLToPath2 } from "url";
18340
18340
 
18341
18341
  // src/memory/config.ts
@@ -18367,7 +18367,8 @@ var DEFAULT_MEMORY_CONFIG = {
18367
18367
  },
18368
18368
  maintenance: {
18369
18369
  lowUtilityMaxConfidence: 0.45,
18370
- lowUtilityMinAgeDays: 30
18370
+ lowUtilityMinAgeDays: 30,
18371
+ autoCompactEveryNRecalls: 50
18371
18372
  },
18372
18373
  hardDelete: false
18373
18374
  };
@@ -18428,7 +18429,7 @@ class MemoryValidationError extends Error {
18428
18429
  // src/memory/evaluation.ts
18429
18430
  import * as fs17 from "fs/promises";
18430
18431
  import * as os9 from "os";
18431
- import * as path41 from "path";
18432
+ import * as path42 from "path";
18432
18433
 
18433
18434
  // src/memory/local-jsonl-provider.ts
18434
18435
  import { randomUUID as randomUUID5 } from "crypto";
@@ -19669,6 +19670,10 @@ async function writeJsonlAtomic(filePath, values) {
19669
19670
  await rename5(tmp, filePath);
19670
19671
  }
19671
19672
 
19673
+ // src/memory/provider-pool.ts
19674
+ import { realpathSync as realpathSync2 } from "fs";
19675
+ import * as path41 from "path";
19676
+
19672
19677
  // src/memory/sqlite-provider.ts
19673
19678
  import { randomUUID as randomUUID6 } from "crypto";
19674
19679
  import { mkdirSync as mkdirSync15 } from "fs";
@@ -19907,6 +19912,7 @@ function loadDatabaseCtor2() {
19907
19912
  _DatabaseCtor2 = req("bun:sqlite").Database;
19908
19913
  return _DatabaseCtor2;
19909
19914
  }
19915
+ var RECALL_CANDIDATE_LIMIT = 1000;
19910
19916
  var FTS_SCHEMA_MIGRATION_NAME = "create_memory_fts5_shadow_index";
19911
19917
  var FTS_TABLE_NAME = "memory_items_fts";
19912
19918
  var FTS_INDEX_COLUMNS = [
@@ -20004,6 +20010,24 @@ var MIGRATIONS2 = [
20004
20010
  ${ftsCreateColumnsSql()}
20005
20011
  );
20006
20012
  `
20013
+ },
20014
+ {
20015
+ version: 4,
20016
+ name: "create_meta_table",
20017
+ sql: `
20018
+ CREATE TABLE IF NOT EXISTS _meta (
20019
+ key TEXT PRIMARY KEY,
20020
+ value TEXT NOT NULL
20021
+ );
20022
+ `
20023
+ },
20024
+ {
20025
+ version: 5,
20026
+ name: "create_recall_usage_timestamp_index",
20027
+ sql: `
20028
+ CREATE INDEX IF NOT EXISTS idx_memory_recall_usage_timestamp
20029
+ ON memory_recall_usage(timestamp DESC);
20030
+ `
20007
20031
  }
20008
20032
  ];
20009
20033
 
@@ -20018,6 +20042,8 @@ class SQLiteMemoryProvider {
20018
20042
  memories = new Map;
20019
20043
  proposals = new Map;
20020
20044
  lastAutomaticJsonlMigration = null;
20045
+ recallCountSinceLastCompaction = 0;
20046
+ isCompacting = false;
20021
20047
  constructor(rootDirectory, config = {}) {
20022
20048
  this.rootDirectory = rootDirectory;
20023
20049
  this.config = {
@@ -20075,6 +20101,7 @@ class SQLiteMemoryProvider {
20075
20101
  this.db.run(`PRAGMA busy_timeout = ${busyTimeoutMs};`);
20076
20102
  this.db.run("PRAGMA foreign_keys = ON;");
20077
20103
  this.runMigrations();
20104
+ this.backfillScopeKeys();
20078
20105
  this.ftsAvailable = this.initializeFtsIndex();
20079
20106
  this.lastAutomaticJsonlMigration = null;
20080
20107
  await this.migrateLegacyJsonlIfNeeded();
@@ -20137,7 +20164,8 @@ class SQLiteMemoryProvider {
20137
20164
  const scopedRecords = await this.list({
20138
20165
  scopes: request.scopes,
20139
20166
  kinds: request.kinds,
20140
- includeExpired: request.includeExpired
20167
+ includeExpired: request.includeExpired,
20168
+ limit: RECALL_CANDIDATE_LIMIT
20141
20169
  });
20142
20170
  const candidates = this.selectRecallCandidates(request, scopedRecords);
20143
20171
  const result = scoreMemoryRecordsWithDiagnostics(candidates.records, request);
@@ -20158,7 +20186,29 @@ class SQLiteMemoryProvider {
20158
20186
  timestamp,
20159
20187
  usage_json
20160
20188
  ) VALUES (?, ?, ?, ?)`, [randomUUID6(), event.bundleId, event.timestamp, JSON.stringify(event)]);
20161
- await this.event("recall", event.bundleId, JSON.stringify(event));
20189
+ this.recallCountSinceLastCompaction++;
20190
+ const threshold = this.config.maintenance?.autoCompactEveryNRecalls ?? 50;
20191
+ if (threshold > 0 && this.recallCountSinceLastCompaction >= threshold && !this.isCompacting) {
20192
+ this.recallCountSinceLastCompaction = 0;
20193
+ this.isCompacting = true;
20194
+ this.compactMaintenance({ dryRun: false }).then((result) => {
20195
+ const rowsInspected = result.remaining + result.removedDeleted + result.removedSuperseded + result.removedExpiredScratch;
20196
+ const rowsPurged = result.removedDeleted + result.removedSuperseded + result.removedExpiredScratch;
20197
+ return this.insertEvent("compact_triggered", "memory_items", "auto compaction triggered", JSON.stringify({
20198
+ trigger: "auto",
20199
+ threshold,
20200
+ rowsInspected,
20201
+ rowsPurged,
20202
+ timestamp: new Date().toISOString()
20203
+ }));
20204
+ }).catch((err) => {
20205
+ if (process.env.OPENCODE_SWARM_DEBUG === "1") {
20206
+ console.debug(`[memory] auto-compaction failed: ${err}`);
20207
+ }
20208
+ }).finally(() => {
20209
+ this.isCompacting = false;
20210
+ });
20211
+ }
20162
20212
  }
20163
20213
  async listRecallUsage(filter = {}) {
20164
20214
  await this.initialize();
@@ -20182,12 +20232,46 @@ class SQLiteMemoryProvider {
20182
20232
  }
20183
20233
  async list(filter = {}) {
20184
20234
  await this.initialize();
20185
- let records = Array.from(this.memories.values());
20235
+ const db = this.requireDb();
20236
+ const conditions = [];
20237
+ const params = [];
20186
20238
  if (filter.scopes && filter.scopes.length > 0) {
20187
- records = records.filter((record) => scopeAllowed(record.scope, filter.scopes ?? []));
20239
+ const scopeKeys = filter.scopes.map((scope) => stableScopeKey(scope));
20240
+ const placeholders = scopeKeys.map(() => "?").join(", ");
20241
+ conditions.push(`scope_key IN (${placeholders})`);
20242
+ params.push(...scopeKeys);
20188
20243
  }
20189
20244
  if (filter.kinds && filter.kinds.length > 0) {
20190
- records = records.filter((record) => filter.kinds?.includes(record.kind));
20245
+ if (filter.kinds.length === 1) {
20246
+ conditions.push("kind = ?");
20247
+ params.push(filter.kinds[0]);
20248
+ } else {
20249
+ const placeholders = filter.kinds.map(() => "?").join(", ");
20250
+ conditions.push(`kind IN (${placeholders})`);
20251
+ params.push(...filter.kinds);
20252
+ }
20253
+ }
20254
+ if (!filter.includeInactive) {
20255
+ conditions.push("superseded_by IS NULL");
20256
+ conditions.push("deleted = 0");
20257
+ }
20258
+ if (!filter.includeExpired) {
20259
+ const nowIso = new Date().toISOString();
20260
+ conditions.push("(expires_at IS NULL OR expires_at > ?)");
20261
+ params.push(nowIso);
20262
+ }
20263
+ const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
20264
+ let sql = `SELECT id, record_json FROM memory_items ${whereClause} ORDER BY updated_at DESC`;
20265
+ if (typeof filter.limit === "number") {
20266
+ sql += " LIMIT ?";
20267
+ params.push(Math.trunc(filter.limit));
20268
+ }
20269
+ const rows = db.query(sql).all(...params);
20270
+ let records = [];
20271
+ for (const row of rows) {
20272
+ const parsed = this.parseMemoryRow(row);
20273
+ if (parsed)
20274
+ records.push(parsed);
20191
20275
  }
20192
20276
  if (!filter.includeExpired) {
20193
20277
  const now = Date.now();
@@ -20198,11 +20282,7 @@ class SQLiteMemoryProvider {
20198
20282
  return !Number.isFinite(expires) || expires > now;
20199
20283
  });
20200
20284
  }
20201
- if (!filter.includeInactive) {
20202
- records = records.filter((record) => !record.supersededBy && record.metadata.deleted !== true);
20203
- }
20204
- records.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
20205
- return records.slice(0, filter.limit ?? records.length);
20285
+ return records;
20206
20286
  }
20207
20287
  async createProposal(proposal) {
20208
20288
  await this.initialize();
@@ -20392,6 +20472,31 @@ class SQLiteMemoryProvider {
20392
20472
  apply();
20393
20473
  }
20394
20474
  }
20475
+ backfillScopeKeys() {
20476
+ const db = this.requireDb();
20477
+ const metaRow = db.query("SELECT value FROM _meta WHERE key = 'scope_key_backfilled'").get("scope_key_backfilled");
20478
+ if (metaRow?.value === "1")
20479
+ return;
20480
+ const rows = db.query("SELECT id, record_json, scope_key FROM memory_items").all();
20481
+ let backfillCount = 0;
20482
+ for (const row of rows) {
20483
+ try {
20484
+ const record = JSON.parse(row.record_json);
20485
+ const canonicalKey = stableScopeKey(record.scope);
20486
+ if (row.scope_key !== canonicalKey) {
20487
+ db.run("UPDATE memory_items SET scope_key = ? WHERE id = ?", [
20488
+ canonicalKey,
20489
+ row.id
20490
+ ]);
20491
+ backfillCount++;
20492
+ }
20493
+ } catch {}
20494
+ }
20495
+ if (backfillCount > 0) {
20496
+ this.insertEvent("migration", "backfill_scope_keys", `${backfillCount} memory item(s) scope_key backfilled to canonical form`);
20497
+ }
20498
+ db.run("INSERT OR REPLACE INTO _meta (key, value) VALUES ('scope_key_backfilled', '1')");
20499
+ }
20395
20500
  initializeFtsIndex() {
20396
20501
  const db = this.requireDb();
20397
20502
  try {
@@ -20502,7 +20607,7 @@ class SQLiteMemoryProvider {
20502
20607
  record_json
20503
20608
  ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, [
20504
20609
  record.id,
20505
- JSON.stringify(record.scope),
20610
+ stableScopeKey(record.scope),
20506
20611
  record.kind,
20507
20612
  record.updatedAt,
20508
20613
  record.expiresAt ?? null,
@@ -20878,14 +20983,203 @@ function rerankWithFts(items, ftsOrder) {
20878
20983
  }).sort((a, b) => b.score - a.score || a.record.id.localeCompare(b.record.id));
20879
20984
  }
20880
20985
 
20986
+ // src/memory/provider-pool.ts
20987
+ var MAX_POOL_SIZE = 16;
20988
+ var POOLED_MARKER = Symbol("opencode-swarm-pooled-provider");
20989
+ var REAL_CLOSE = Symbol("opencode-swarm-real-close");
20990
+ var head = null;
20991
+ var tail = null;
20992
+ var entriesByKey = new Map;
20993
+ var deferredEntries = new Set;
20994
+ function markAsPooled(provider) {
20995
+ const originalClose = provider.close;
20996
+ provider.close = () => {
20997
+ releaseProvider(provider);
20998
+ return Promise.resolve();
20999
+ };
21000
+ provider[POOLED_MARKER] = true;
21001
+ if (originalClose) {
21002
+ provider[REAL_CLOSE] = originalClose;
21003
+ }
21004
+ }
21005
+ function callRealClose(provider) {
21006
+ const realClose = provider[REAL_CLOSE];
21007
+ try {
21008
+ realClose?.call(provider);
21009
+ } catch (err) {
21010
+ const msg = err instanceof Error ? err.message : String(err);
21011
+ if (process.env.OPENCODE_SWARM_DEBUG === "1") {
21012
+ console.debug(`[provider-pool] real close failed: ${msg}`);
21013
+ }
21014
+ }
21015
+ }
21016
+ function isPooledProvider(provider) {
21017
+ return POOLED_MARKER in provider;
21018
+ }
21019
+ function getOrCreateProvider(directory, config) {
21020
+ const key = resolvePoolKey(directory);
21021
+ const existing = entriesByKey.get(key);
21022
+ if (existing) {
21023
+ moveToHead(existing);
21024
+ existing.refCount++;
21025
+ return existing.provider;
21026
+ }
21027
+ for (const deferred of deferredEntries) {
21028
+ if (deferred.key === key) {
21029
+ deferredEntries.delete(deferred);
21030
+ if (entriesByKey.size >= MAX_POOL_SIZE) {
21031
+ evictLru();
21032
+ }
21033
+ deferred.prev = null;
21034
+ deferred.next = head;
21035
+ if (head)
21036
+ head.prev = deferred;
21037
+ head = deferred;
21038
+ if (!tail)
21039
+ tail = deferred;
21040
+ entriesByKey.set(key, deferred);
21041
+ deferred.refCount++;
21042
+ return deferred.provider;
21043
+ }
21044
+ }
21045
+ const provider = new SQLiteMemoryProvider(directory, config);
21046
+ markAsPooled(provider);
21047
+ if (entriesByKey.size >= MAX_POOL_SIZE) {
21048
+ evictLru();
21049
+ }
21050
+ const entry = {
21051
+ key,
21052
+ provider,
21053
+ refCount: 1,
21054
+ prev: null,
21055
+ next: head
21056
+ };
21057
+ if (head)
21058
+ head.prev = entry;
21059
+ head = entry;
21060
+ if (!tail)
21061
+ tail = entry;
21062
+ entriesByKey.set(key, entry);
21063
+ return provider;
21064
+ }
21065
+ function releaseProvider(provider) {
21066
+ for (const [_key, entry] of entriesByKey) {
21067
+ if (entry.provider === provider) {
21068
+ entry.refCount = Math.max(0, entry.refCount - 1);
21069
+ return;
21070
+ }
21071
+ }
21072
+ for (const entry of deferredEntries) {
21073
+ if (entry.provider === provider) {
21074
+ entry.refCount--;
21075
+ if (entry.refCount <= 0) {
21076
+ deferredEntries.delete(entry);
21077
+ callRealClose(provider);
21078
+ }
21079
+ return;
21080
+ }
21081
+ }
21082
+ if (isPooledProvider(provider)) {
21083
+ callRealClose(provider);
21084
+ }
21085
+ }
21086
+ function evictLru() {
21087
+ if (!tail)
21088
+ return;
21089
+ const evicted = tail;
21090
+ entriesByKey.delete(evicted.key);
21091
+ unlinkEntry(evicted);
21092
+ if (evicted.refCount > 0) {
21093
+ deferredEntries.add(evicted);
21094
+ } else {
21095
+ callRealClose(evicted.provider);
21096
+ }
21097
+ }
21098
+ function moveToHead(entry) {
21099
+ if (head === entry)
21100
+ return;
21101
+ unlinkEntry(entry);
21102
+ entry.prev = null;
21103
+ entry.next = head;
21104
+ if (head)
21105
+ head.prev = entry;
21106
+ head = entry;
21107
+ if (!tail)
21108
+ tail = entry;
21109
+ }
21110
+ function unlinkEntry(entry) {
21111
+ if (entry.prev)
21112
+ entry.prev.next = entry.next;
21113
+ if (entry.next)
21114
+ entry.next.prev = entry.prev;
21115
+ if (head === entry)
21116
+ head = entry.next;
21117
+ if (tail === entry)
21118
+ tail = entry.prev;
21119
+ }
21120
+ function resolvePoolKey(directory) {
21121
+ try {
21122
+ return realpathSync2(directory);
21123
+ } catch {
21124
+ return path41.resolve(directory);
21125
+ }
21126
+ }
21127
+
20881
21128
  // src/memory/gateway.ts
20882
21129
  function createConfiguredMemoryProvider(directory, config) {
20883
21130
  if (config.provider === "sqlite") {
20884
- return new SQLiteMemoryProvider(directory, config);
21131
+ return getOrCreateProvider(directory, config);
20885
21132
  }
20886
21133
  return new LocalJsonlMemoryProvider(directory, config);
20887
21134
  }
20888
21135
  var gitRemoteUrlCache = new Map;
21136
+ var RESERVED_IDENTIFIERS = new Set([
21137
+ "const",
21138
+ "let",
21139
+ "var",
21140
+ "function",
21141
+ "class",
21142
+ "interface",
21143
+ "type",
21144
+ "async",
21145
+ "await",
21146
+ "return",
21147
+ "if",
21148
+ "else",
21149
+ "for",
21150
+ "while",
21151
+ "do",
21152
+ "switch",
21153
+ "case",
21154
+ "break",
21155
+ "continue",
21156
+ "new",
21157
+ "this",
21158
+ "super",
21159
+ "extends",
21160
+ "implements",
21161
+ "import",
21162
+ "export",
21163
+ "from",
21164
+ "default",
21165
+ "try",
21166
+ "catch",
21167
+ "finally",
21168
+ "throw",
21169
+ "typeof",
21170
+ "instanceof",
21171
+ "in",
21172
+ "of",
21173
+ "as",
21174
+ "yield",
21175
+ "static",
21176
+ "get",
21177
+ "set",
21178
+ "readonly",
21179
+ "public",
21180
+ "private",
21181
+ "protected"
21182
+ ]);
20889
21183
 
20890
21184
  // src/memory/evaluation.ts
20891
21185
  var DEFAULT_PROVIDERS = [
@@ -20899,7 +21193,7 @@ var DEFAULT_MODES = [
20899
21193
  ];
20900
21194
  var DEFAULT_TIMESTAMP = "2026-05-26T12:00:00.000Z";
20901
21195
  async function evaluateMemoryRecallFixtures(options) {
20902
- const fixtureDirectory = path41.resolve(options.fixtureDirectory);
21196
+ const fixtureDirectory = path42.resolve(options.fixtureDirectory);
20903
21197
  const providers = options.providers ?? DEFAULT_PROVIDERS;
20904
21198
  const modes = options.modes ?? DEFAULT_MODES;
20905
21199
  const generatedAt = new Date().toISOString();
@@ -20908,7 +21202,7 @@ async function evaluateMemoryRecallFixtures(options) {
20908
21202
  for (const fixture of fixtures) {
20909
21203
  const materialized = materializeFixture(fixture);
20910
21204
  for (const providerName of providers) {
20911
- const tempRoot = await fs17.realpath(await fs17.mkdtemp(path41.join(os9.tmpdir(), "swarm-memory-eval-")));
21205
+ const tempRoot = await fs17.realpath(await fs17.mkdtemp(path42.join(os9.tmpdir(), "swarm-memory-eval-")));
20912
21206
  const provider = createEvaluationProvider(providerName, tempRoot);
20913
21207
  try {
20914
21208
  await provider.initialize?.();
@@ -20952,7 +21246,7 @@ async function loadRecallEvaluationFixtures(fixtureDirectory) {
20952
21246
  const files = entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort((a, b) => a.localeCompare(b));
20953
21247
  const fixtures = [];
20954
21248
  for (const file of files) {
20955
- const raw = await fs17.readFile(path41.join(fixtureDirectory, file), "utf-8");
21249
+ const raw = await fs17.readFile(path42.join(fixtureDirectory, file), "utf-8");
20956
21250
  fixtures.push(validateFixture(JSON.parse(raw), file));
20957
21251
  }
20958
21252
  return fixtures;
@@ -21228,7 +21522,7 @@ var CuratorOutputMemoryDecisionSchema = exports_external.object({
21228
21522
  curatorMemoryDecisions: exports_external.array(CuratorMemoryDecisionSchema).max(20).optional()
21229
21523
  }).passthrough();
21230
21524
  // src/commands/memory.ts
21231
- var PACKAGE_ROOT = path42.resolve(resolvePackageRootFromModule(fileURLToPath2(import.meta.url)));
21525
+ var PACKAGE_ROOT = path43.resolve(resolvePackageRootFromModule(fileURLToPath2(import.meta.url)));
21232
21526
  async function handleMemoryCommand(_directory, _args) {
21233
21527
  return [
21234
21528
  "## Swarm Memory",
@@ -21497,7 +21791,7 @@ function resolveCommandMemoryConfig(directory) {
21497
21791
  }
21498
21792
  function parseEvaluateArgs(directory, args) {
21499
21793
  let json = false;
21500
- let fixtureDirectory = path42.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall");
21794
+ let fixtureDirectory = path43.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall");
21501
21795
  for (let i = 0;i < args.length; i++) {
21502
21796
  const arg = args[i];
21503
21797
  if (arg === "--json") {
@@ -21511,10 +21805,10 @@ function parseEvaluateArgs(directory, args) {
21511
21805
  error: "Usage: /swarm memory evaluate [--json] [--fixtures <directory>]"
21512
21806
  };
21513
21807
  }
21514
- const resolvedFixtures = path42.resolve(directory, next);
21515
- const canonical = path42.normalize(resolvedFixtures) + path42.sep;
21516
- const allowedRootA = path42.normalize(directory) + path42.sep;
21517
- const allowedRootB = path42.normalize(path42.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall")) + path42.sep;
21808
+ const resolvedFixtures = path43.resolve(directory, next);
21809
+ const canonical = path43.normalize(resolvedFixtures) + path43.sep;
21810
+ const allowedRootA = path43.normalize(directory) + path43.sep;
21811
+ const allowedRootB = path43.normalize(path43.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall")) + path43.sep;
21518
21812
  if (!canonical.startsWith(allowedRootA) && !canonical.startsWith(allowedRootB)) {
21519
21813
  return {
21520
21814
  error: "--fixtures <directory> must resolve under the project directory or the bundled tests/fixtures/memory-recall directory"
@@ -21553,15 +21847,15 @@ function parseMaintenanceArgs(args, options) {
21553
21847
  return { limit, confirm };
21554
21848
  }
21555
21849
  function resolvePackageRootFromModule(modulePath) {
21556
- const moduleDir = path42.dirname(modulePath);
21557
- const leaf = path42.basename(moduleDir);
21850
+ const moduleDir = path43.dirname(modulePath);
21851
+ const leaf = path43.basename(moduleDir);
21558
21852
  if (leaf === "commands" || leaf === "cli") {
21559
- return path42.resolve(moduleDir, "..", "..");
21853
+ return path43.resolve(moduleDir, "..", "..");
21560
21854
  }
21561
21855
  if (leaf === "dist") {
21562
- return path42.resolve(moduleDir, "..");
21856
+ return path43.resolve(moduleDir, "..");
21563
21857
  }
21564
- return path42.resolve(moduleDir, "..");
21858
+ return path43.resolve(moduleDir, "..");
21565
21859
  }
21566
21860
  function formatMigrationResult(label, report) {
21567
21861
  if (!report) {
@@ -22243,11 +22537,11 @@ var _internals36 = {
22243
22537
 
22244
22538
  // src/services/preflight-service.ts
22245
22539
  import * as fs24 from "fs";
22246
- import * as path49 from "path";
22540
+ import * as path50 from "path";
22247
22541
 
22248
22542
  // src/tools/lint.ts
22249
22543
  import * as fs18 from "fs";
22250
- import * as path43 from "path";
22544
+ import * as path44 from "path";
22251
22545
 
22252
22546
  // src/utils/path-security.ts
22253
22547
  function containsPathTraversal(str) {
@@ -22303,9 +22597,9 @@ function validateArgs(args) {
22303
22597
  }
22304
22598
  function getLinterCommand(linter, mode, projectDir) {
22305
22599
  const isWindows = process.platform === "win32";
22306
- const binDir = path43.join(projectDir, "node_modules", ".bin");
22307
- const biomeBin = isWindows ? path43.join(binDir, "biome.EXE") : path43.join(binDir, "biome");
22308
- const eslintBin = isWindows ? path43.join(binDir, "eslint.cmd") : path43.join(binDir, "eslint");
22600
+ const binDir = path44.join(projectDir, "node_modules", ".bin");
22601
+ const biomeBin = isWindows ? path44.join(binDir, "biome.EXE") : path44.join(binDir, "biome");
22602
+ const eslintBin = isWindows ? path44.join(binDir, "eslint.cmd") : path44.join(binDir, "eslint");
22309
22603
  switch (linter) {
22310
22604
  case "biome":
22311
22605
  if (mode === "fix") {
@@ -22321,7 +22615,7 @@ function getLinterCommand(linter, mode, projectDir) {
22321
22615
  }
22322
22616
  function getAdditionalLinterCommand(linter, mode, cwd) {
22323
22617
  const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
22324
- const gradlew = fs18.existsSync(path43.join(cwd, gradlewName)) ? path43.join(cwd, gradlewName) : null;
22618
+ const gradlew = fs18.existsSync(path44.join(cwd, gradlewName)) ? path44.join(cwd, gradlewName) : null;
22325
22619
  switch (linter) {
22326
22620
  case "ruff":
22327
22621
  return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
@@ -22355,10 +22649,10 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
22355
22649
  }
22356
22650
  }
22357
22651
  function detectRuff(cwd) {
22358
- if (fs18.existsSync(path43.join(cwd, "ruff.toml")))
22652
+ if (fs18.existsSync(path44.join(cwd, "ruff.toml")))
22359
22653
  return isCommandAvailable("ruff");
22360
22654
  try {
22361
- const pyproject = path43.join(cwd, "pyproject.toml");
22655
+ const pyproject = path44.join(cwd, "pyproject.toml");
22362
22656
  if (fs18.existsSync(pyproject)) {
22363
22657
  const content = fs18.readFileSync(pyproject, "utf-8");
22364
22658
  if (content.includes("[tool.ruff]"))
@@ -22368,19 +22662,19 @@ function detectRuff(cwd) {
22368
22662
  return false;
22369
22663
  }
22370
22664
  function detectClippy(cwd) {
22371
- return fs18.existsSync(path43.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
22665
+ return fs18.existsSync(path44.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
22372
22666
  }
22373
22667
  function detectGolangciLint(cwd) {
22374
- return fs18.existsSync(path43.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
22668
+ return fs18.existsSync(path44.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
22375
22669
  }
22376
22670
  function detectCheckstyle(cwd) {
22377
- const hasMaven = fs18.existsSync(path43.join(cwd, "pom.xml"));
22378
- const hasGradle = fs18.existsSync(path43.join(cwd, "build.gradle")) || fs18.existsSync(path43.join(cwd, "build.gradle.kts"));
22379
- const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs18.existsSync(path43.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
22671
+ const hasMaven = fs18.existsSync(path44.join(cwd, "pom.xml"));
22672
+ const hasGradle = fs18.existsSync(path44.join(cwd, "build.gradle")) || fs18.existsSync(path44.join(cwd, "build.gradle.kts"));
22673
+ const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs18.existsSync(path44.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
22380
22674
  return (hasMaven || hasGradle) && hasBinary;
22381
22675
  }
22382
22676
  function detectKtlint(cwd) {
22383
- const hasKotlin = fs18.existsSync(path43.join(cwd, "build.gradle.kts")) || fs18.existsSync(path43.join(cwd, "build.gradle")) || (() => {
22677
+ const hasKotlin = fs18.existsSync(path44.join(cwd, "build.gradle.kts")) || fs18.existsSync(path44.join(cwd, "build.gradle")) || (() => {
22384
22678
  try {
22385
22679
  return fs18.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
22386
22680
  } catch {
@@ -22399,11 +22693,11 @@ function detectDotnetFormat(cwd) {
22399
22693
  }
22400
22694
  }
22401
22695
  function detectCppcheck(cwd) {
22402
- if (fs18.existsSync(path43.join(cwd, "CMakeLists.txt"))) {
22696
+ if (fs18.existsSync(path44.join(cwd, "CMakeLists.txt"))) {
22403
22697
  return isCommandAvailable("cppcheck");
22404
22698
  }
22405
22699
  try {
22406
- const dirsToCheck = [cwd, path43.join(cwd, "src")];
22700
+ const dirsToCheck = [cwd, path44.join(cwd, "src")];
22407
22701
  const hasCpp = dirsToCheck.some((dir) => {
22408
22702
  try {
22409
22703
  return fs18.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
@@ -22417,13 +22711,13 @@ function detectCppcheck(cwd) {
22417
22711
  }
22418
22712
  }
22419
22713
  function detectSwiftlint(cwd) {
22420
- return fs18.existsSync(path43.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
22714
+ return fs18.existsSync(path44.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
22421
22715
  }
22422
22716
  function detectDartAnalyze(cwd) {
22423
- return fs18.existsSync(path43.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
22717
+ return fs18.existsSync(path44.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
22424
22718
  }
22425
22719
  function detectRubocop(cwd) {
22426
- return (fs18.existsSync(path43.join(cwd, "Gemfile")) || fs18.existsSync(path43.join(cwd, "gems.rb")) || fs18.existsSync(path43.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
22720
+ return (fs18.existsSync(path44.join(cwd, "Gemfile")) || fs18.existsSync(path44.join(cwd, "gems.rb")) || fs18.existsSync(path44.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
22427
22721
  }
22428
22722
  function detectAdditionalLinter(cwd) {
22429
22723
  if (detectRuff(cwd))
@@ -22451,10 +22745,10 @@ function detectAdditionalLinter(cwd) {
22451
22745
  function findBinInAncestors(startDir, binName) {
22452
22746
  let dir = startDir;
22453
22747
  while (true) {
22454
- const candidate = path43.join(dir, "node_modules", ".bin", binName);
22748
+ const candidate = path44.join(dir, "node_modules", ".bin", binName);
22455
22749
  if (fs18.existsSync(candidate))
22456
22750
  return candidate;
22457
- const parent = path43.dirname(dir);
22751
+ const parent = path44.dirname(dir);
22458
22752
  if (parent === dir)
22459
22753
  break;
22460
22754
  dir = parent;
@@ -22463,10 +22757,10 @@ function findBinInAncestors(startDir, binName) {
22463
22757
  }
22464
22758
  function findBinInEnvPath(binName) {
22465
22759
  const searchPath = process.env.PATH ?? "";
22466
- for (const dir of searchPath.split(path43.delimiter)) {
22760
+ for (const dir of searchPath.split(path44.delimiter)) {
22467
22761
  if (!dir)
22468
22762
  continue;
22469
- const candidate = path43.join(dir, binName);
22763
+ const candidate = path44.join(dir, binName);
22470
22764
  if (fs18.existsSync(candidate))
22471
22765
  return candidate;
22472
22766
  }
@@ -22479,13 +22773,13 @@ async function detectAvailableLinter(directory) {
22479
22773
  return null;
22480
22774
  const projectDir = directory;
22481
22775
  const isWindows = process.platform === "win32";
22482
- const biomeBin = isWindows ? path43.join(projectDir, "node_modules", ".bin", "biome.EXE") : path43.join(projectDir, "node_modules", ".bin", "biome");
22483
- const eslintBin = isWindows ? path43.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path43.join(projectDir, "node_modules", ".bin", "eslint");
22776
+ const biomeBin = isWindows ? path44.join(projectDir, "node_modules", ".bin", "biome.EXE") : path44.join(projectDir, "node_modules", ".bin", "biome");
22777
+ const eslintBin = isWindows ? path44.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path44.join(projectDir, "node_modules", ".bin", "eslint");
22484
22778
  const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
22485
22779
  if (localResult)
22486
22780
  return localResult;
22487
- const biomeAncestor = findBinInAncestors(path43.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
22488
- const eslintAncestor = findBinInAncestors(path43.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
22781
+ const biomeAncestor = findBinInAncestors(path44.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
22782
+ const eslintAncestor = findBinInAncestors(path44.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
22489
22783
  if (biomeAncestor || eslintAncestor) {
22490
22784
  return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
22491
22785
  }
@@ -22504,7 +22798,7 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
22504
22798
  stderr: "pipe"
22505
22799
  });
22506
22800
  const biomeExit = biomeProc.exited;
22507
- const timeout = new Promise((resolve12) => setTimeout(() => resolve12("timeout"), DETECT_TIMEOUT));
22801
+ const timeout = new Promise((resolve13) => setTimeout(() => resolve13("timeout"), DETECT_TIMEOUT));
22508
22802
  const result = await Promise.race([biomeExit, timeout]);
22509
22803
  if (result === "timeout") {
22510
22804
  biomeProc.kill();
@@ -22518,7 +22812,7 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
22518
22812
  stderr: "pipe"
22519
22813
  });
22520
22814
  const eslintExit = eslintProc.exited;
22521
- const timeout = new Promise((resolve12) => setTimeout(() => resolve12("timeout"), DETECT_TIMEOUT));
22815
+ const timeout = new Promise((resolve13) => setTimeout(() => resolve13("timeout"), DETECT_TIMEOUT));
22522
22816
  const result = await Promise.race([eslintExit, timeout]);
22523
22817
  if (result === "timeout") {
22524
22818
  eslintProc.kill();
@@ -22699,7 +22993,7 @@ var _internals37 = {
22699
22993
 
22700
22994
  // src/tools/secretscan.ts
22701
22995
  import * as fs19 from "fs";
22702
- import * as path44 from "path";
22996
+ import * as path45 from "path";
22703
22997
  var MAX_FILE_PATH_LENGTH = 500;
22704
22998
  var MAX_FILE_SIZE_BYTES = 512 * 1024;
22705
22999
  var MAX_FILES_SCANNED = 1000;
@@ -22926,7 +23220,7 @@ function isGlobOrPathPattern(pattern) {
22926
23220
  return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
22927
23221
  }
22928
23222
  function loadSecretScanIgnore(scanDir) {
22929
- const ignorePath = path44.join(scanDir, ".secretscanignore");
23223
+ const ignorePath = path45.join(scanDir, ".secretscanignore");
22930
23224
  try {
22931
23225
  if (!fs19.existsSync(ignorePath))
22932
23226
  return [];
@@ -22949,7 +23243,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
22949
23243
  if (exactNames.has(entry))
22950
23244
  return true;
22951
23245
  for (const pattern of globPatterns) {
22952
- if (path44.matchesGlob(relPath, pattern))
23246
+ if (path45.matchesGlob(relPath, pattern))
22953
23247
  return true;
22954
23248
  }
22955
23249
  return false;
@@ -22970,7 +23264,7 @@ function validateDirectoryInput(dir) {
22970
23264
  return null;
22971
23265
  }
22972
23266
  function isBinaryFile(filePath, buffer) {
22973
- const ext = path44.extname(filePath).toLowerCase();
23267
+ const ext = path45.extname(filePath).toLowerCase();
22974
23268
  if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
22975
23269
  return true;
22976
23270
  }
@@ -23107,9 +23401,9 @@ function isSymlinkLoop(realPath, visited) {
23107
23401
  return false;
23108
23402
  }
23109
23403
  function isPathWithinScope(realPath, scanDir) {
23110
- const resolvedScanDir = path44.resolve(scanDir);
23111
- const resolvedRealPath = path44.resolve(realPath);
23112
- return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path44.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
23404
+ const resolvedScanDir = path45.resolve(scanDir);
23405
+ const resolvedRealPath = path45.resolve(realPath);
23406
+ return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path45.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
23113
23407
  }
23114
23408
  function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
23115
23409
  skippedDirs: 0,
@@ -23135,8 +23429,8 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
23135
23429
  return a.localeCompare(b);
23136
23430
  });
23137
23431
  for (const entry of entries) {
23138
- const fullPath = path44.join(dir, entry);
23139
- const relPath = path44.relative(scanDir, fullPath).replace(/\\/g, "/");
23432
+ const fullPath = path45.join(dir, entry);
23433
+ const relPath = path45.relative(scanDir, fullPath).replace(/\\/g, "/");
23140
23434
  if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
23141
23435
  stats.skippedDirs++;
23142
23436
  continue;
@@ -23171,7 +23465,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
23171
23465
  const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
23172
23466
  files.push(...subFiles);
23173
23467
  } else if (lstat2.isFile()) {
23174
- const ext = path44.extname(fullPath).toLowerCase();
23468
+ const ext = path45.extname(fullPath).toLowerCase();
23175
23469
  if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
23176
23470
  files.push(fullPath);
23177
23471
  } else {
@@ -23237,7 +23531,7 @@ var secretscan = createSwarmTool({
23237
23531
  }
23238
23532
  }
23239
23533
  try {
23240
- const _scanDirRaw = path44.resolve(directory);
23534
+ const _scanDirRaw = path45.resolve(directory);
23241
23535
  const scanDir = (() => {
23242
23536
  try {
23243
23537
  return fs19.realpathSync(_scanDirRaw);
@@ -23400,11 +23694,11 @@ var _internals38 = {
23400
23694
 
23401
23695
  // src/tools/test-runner.ts
23402
23696
  import * as fs23 from "fs";
23403
- import * as path48 from "path";
23697
+ import * as path49 from "path";
23404
23698
 
23405
23699
  // src/test-impact/analyzer.ts
23406
23700
  import fs20 from "fs";
23407
- import path45 from "path";
23701
+ import path46 from "path";
23408
23702
  var IMPORT_REGEX_ES = /import\s+[\s\S]*?\s+from\s+['"]([^'"]+)['"]/g;
23409
23703
  var IMPORT_REGEX_REQUIRE = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
23410
23704
  var IMPORT_REGEX_REEXPORT = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
@@ -23445,8 +23739,8 @@ function resolveRelativeImport(fromDir, importPath) {
23445
23739
  if (!importPath.startsWith(".")) {
23446
23740
  return null;
23447
23741
  }
23448
- const resolved = path45.resolve(fromDir, importPath);
23449
- if (path45.extname(resolved)) {
23742
+ const resolved = path46.resolve(fromDir, importPath);
23743
+ if (path46.extname(resolved)) {
23450
23744
  if (fs20.existsSync(resolved) && fs20.statSync(resolved).isFile()) {
23451
23745
  return normalizePath2(resolved);
23452
23746
  }
@@ -23466,20 +23760,20 @@ function resolvePythonImport(fromDir, module) {
23466
23760
  const leadingDots = module.match(/^\.+/)?.[0].length ?? 0;
23467
23761
  let baseDir = fromDir;
23468
23762
  for (let i = 1;i < leadingDots; i++) {
23469
- baseDir = path45.dirname(baseDir);
23763
+ baseDir = path46.dirname(baseDir);
23470
23764
  }
23471
23765
  const rest = module.slice(leadingDots);
23472
23766
  if (rest.length === 0) {
23473
- const initPath = path45.join(baseDir, "__init__.py");
23767
+ const initPath = path46.join(baseDir, "__init__.py");
23474
23768
  if (fs20.existsSync(initPath) && fs20.statSync(initPath).isFile()) {
23475
23769
  return normalizePath2(initPath);
23476
23770
  }
23477
23771
  return null;
23478
23772
  }
23479
- const subpath = rest.replace(/\./g, path45.sep);
23773
+ const subpath = rest.replace(/\./g, path46.sep);
23480
23774
  const candidates = [
23481
- `${path45.join(baseDir, subpath)}.py`,
23482
- path45.join(baseDir, subpath, "__init__.py")
23775
+ `${path46.join(baseDir, subpath)}.py`,
23776
+ path46.join(baseDir, subpath, "__init__.py")
23483
23777
  ];
23484
23778
  for (const c of candidates) {
23485
23779
  if (fs20.existsSync(c) && fs20.statSync(c).isFile())
@@ -23489,7 +23783,7 @@ function resolvePythonImport(fromDir, module) {
23489
23783
  }
23490
23784
  var goModuleCache = new Map;
23491
23785
  function findGoModule(fromDir) {
23492
- const resolved = path45.resolve(fromDir);
23786
+ const resolved = path46.resolve(fromDir);
23493
23787
  let cur = resolved;
23494
23788
  const walked = [];
23495
23789
  for (let i = 0;i < 16; i++) {
@@ -23501,7 +23795,7 @@ function findGoModule(fromDir) {
23501
23795
  }
23502
23796
  walked.push(cur);
23503
23797
  try {
23504
- const goMod = path45.join(cur, "go.mod");
23798
+ const goMod = path46.join(cur, "go.mod");
23505
23799
  const content = fs20.readFileSync(goMod, "utf-8");
23506
23800
  const moduleMatch = content.match(/^\s*module\s+"?([^"\s/]+(?:\/[^"\s]+)*)"?/m);
23507
23801
  if (moduleMatch) {
@@ -23512,10 +23806,10 @@ function findGoModule(fromDir) {
23512
23806
  }
23513
23807
  } catch {}
23514
23808
  try {
23515
- fs20.accessSync(path45.join(cur, ".git"));
23809
+ fs20.accessSync(path46.join(cur, ".git"));
23516
23810
  break;
23517
23811
  } catch {}
23518
- const parent = path45.dirname(cur);
23812
+ const parent = path46.dirname(cur);
23519
23813
  if (parent === cur)
23520
23814
  break;
23521
23815
  cur = parent;
@@ -23527,12 +23821,12 @@ function findGoModule(fromDir) {
23527
23821
  function resolveGoImport(fromDir, importPath) {
23528
23822
  let dir = null;
23529
23823
  if (importPath.startsWith(".")) {
23530
- dir = path45.resolve(fromDir, importPath);
23824
+ dir = path46.resolve(fromDir, importPath);
23531
23825
  } else {
23532
23826
  const mod = findGoModule(fromDir);
23533
23827
  if (mod && (importPath === mod.modulePath || importPath.startsWith(`${mod.modulePath}/`))) {
23534
23828
  const subpath = importPath.slice(mod.modulePath.length);
23535
- dir = path45.join(mod.moduleRoot, subpath);
23829
+ dir = path46.join(mod.moduleRoot, subpath);
23536
23830
  }
23537
23831
  }
23538
23832
  if (dir === null)
@@ -23540,7 +23834,7 @@ function resolveGoImport(fromDir, importPath) {
23540
23834
  if (!fs20.existsSync(dir) || !fs20.statSync(dir).isDirectory())
23541
23835
  return [];
23542
23836
  try {
23543
- return fs20.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath2(path45.join(dir, f)));
23837
+ return fs20.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath2(path46.join(dir, f)));
23544
23838
  } catch {
23545
23839
  return [];
23546
23840
  }
@@ -23579,15 +23873,15 @@ function findTestFilesSync(cwd) {
23579
23873
  for (const entry of entries) {
23580
23874
  if (entry.isDirectory()) {
23581
23875
  if (!skipDirs.has(entry.name)) {
23582
- walk(path45.join(dir, entry.name), visitedInodes);
23876
+ walk(path46.join(dir, entry.name), visitedInodes);
23583
23877
  }
23584
23878
  } else if (entry.isFile()) {
23585
23879
  const name = entry.name;
23586
23880
  const isTsTest = /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name);
23587
- const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${path45.sep}tests${path45.sep}`) && name.endsWith(".py");
23881
+ const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${path46.sep}tests${path46.sep}`) && name.endsWith(".py");
23588
23882
  const isGoTest = /.+_test\.go$/.test(name);
23589
23883
  if (isTsTest || isPyTest || isGoTest) {
23590
- testFiles.push(normalizePath2(path45.join(dir, entry.name)));
23884
+ testFiles.push(normalizePath2(path46.join(dir, entry.name)));
23591
23885
  }
23592
23886
  }
23593
23887
  }
@@ -23612,8 +23906,8 @@ function extractImports(content) {
23612
23906
  ];
23613
23907
  }
23614
23908
  function addImpactEdgesForTestFile(testFile, content, impactMap) {
23615
- const ext = path45.extname(testFile).toLowerCase();
23616
- const testDir = path45.dirname(testFile);
23909
+ const ext = path46.extname(testFile).toLowerCase();
23910
+ const testDir = path46.dirname(testFile);
23617
23911
  function addEdge(source) {
23618
23912
  if (!impactMap[source])
23619
23913
  impactMap[source] = [];
@@ -23686,7 +23980,7 @@ async function buildImpactMap(cwd) {
23686
23980
  return impactMap;
23687
23981
  }
23688
23982
  async function loadImpactMap(cwd, options) {
23689
- const cachePath = path45.join(cwd, ".swarm", "cache", "impact-map.json");
23983
+ const cachePath = path46.join(cwd, ".swarm", "cache", "impact-map.json");
23690
23984
  if (fs20.existsSync(cachePath)) {
23691
23985
  try {
23692
23986
  const content = fs20.readFileSync(cachePath, "utf-8");
@@ -23719,12 +24013,12 @@ async function loadImpactMap(cwd, options) {
23719
24013
  return _internals39.buildImpactMap(cwd);
23720
24014
  }
23721
24015
  async function saveImpactMap(cwd, impactMap) {
23722
- if (!path45.isAbsolute(cwd)) {
24016
+ if (!path46.isAbsolute(cwd)) {
23723
24017
  throw new Error(`saveImpactMap requires an absolute project root path, got: "${cwd}"`);
23724
24018
  }
23725
24019
  _internals39.validateProjectRoot(cwd);
23726
- const cacheDir2 = path45.join(cwd, ".swarm", "cache");
23727
- const cachePath = path45.join(cacheDir2, "impact-map.json");
24020
+ const cacheDir2 = path46.join(cwd, ".swarm", "cache");
24021
+ const cachePath = path46.join(cacheDir2, "impact-map.json");
23728
24022
  if (!fs20.existsSync(cacheDir2)) {
23729
24023
  fs20.mkdirSync(cacheDir2, { recursive: true });
23730
24024
  }
@@ -23756,7 +24050,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
23756
24050
  budgetExceeded = true;
23757
24051
  break;
23758
24052
  }
23759
- const normalizedChanged = normalizePath2(path45.resolve(changedFile));
24053
+ const normalizedChanged = normalizePath2(path46.resolve(changedFile));
23760
24054
  const tests = impactMap[normalizedChanged];
23761
24055
  if (tests && tests.length > 0) {
23762
24056
  for (const test of tests) {
@@ -23770,13 +24064,13 @@ async function analyzeImpact(changedFiles, cwd, budget) {
23770
24064
  if (budgetExceeded)
23771
24065
  break;
23772
24066
  } else {
23773
- const changedDir = normalizePath2(path45.dirname(normalizedChanged));
23774
- const changedInputDir = normalizePath2(path45.dirname(changedFile));
24067
+ const changedDir = normalizePath2(path46.dirname(normalizedChanged));
24068
+ const changedInputDir = normalizePath2(path46.dirname(changedFile));
23775
24069
  const suffixMatches = Object.entries(impactMap).filter(([sourcePath]) => {
23776
24070
  return sourcePath.endsWith(changedFile) || changedFile.endsWith(sourcePath) || sourcePath.endsWith(normalizedChanged) || normalizedChanged.endsWith(sourcePath);
23777
24071
  }).sort(([sourceA], [sourceB]) => {
23778
- const sourceDirA = normalizePath2(path45.dirname(sourceA));
23779
- const sourceDirB = normalizePath2(path45.dirname(sourceB));
24072
+ const sourceDirA = normalizePath2(path46.dirname(sourceA));
24073
+ const sourceDirB = normalizePath2(path46.dirname(sourceB));
23780
24074
  const exactA = sourceDirA === changedDir || changedInputDir !== "." && (sourceDirA === changedInputDir || sourceDirA.endsWith(`/${changedInputDir}`));
23781
24075
  const exactB = sourceDirB === changedDir || changedInputDir !== "." && (sourceDirB === changedInputDir || sourceDirB.endsWith(`/${changedInputDir}`));
23782
24076
  if (exactA !== exactB)
@@ -24103,7 +24397,7 @@ function detectFlakyTests(allHistory) {
24103
24397
 
24104
24398
  // src/test-impact/history-store.ts
24105
24399
  import fs21 from "fs";
24106
- import path46 from "path";
24400
+ import path47 from "path";
24107
24401
  var MAX_HISTORY_PER_TEST = 20;
24108
24402
  var MAX_ERROR_LENGTH = 500;
24109
24403
  var MAX_STACK_LENGTH = 200;
@@ -24115,10 +24409,10 @@ function getHistoryPath(workingDir) {
24115
24409
  if (!workingDir) {
24116
24410
  throw new Error("getHistoryPath requires a working directory \u2014 project root must be provided by the caller");
24117
24411
  }
24118
- if (!path46.isAbsolute(workingDir)) {
24412
+ if (!path47.isAbsolute(workingDir)) {
24119
24413
  throw new Error(`getHistoryPath requires an absolute project root path, got: "${workingDir}"`);
24120
24414
  }
24121
- return path46.join(workingDir, ".swarm", "cache", "test-history.jsonl");
24415
+ return path47.join(workingDir, ".swarm", "cache", "test-history.jsonl");
24122
24416
  }
24123
24417
  function sanitizeErrorMessage(errorMessage) {
24124
24418
  if (errorMessage === undefined) {
@@ -24210,7 +24504,7 @@ function batchAppendTestRuns(records, workingDir) {
24210
24504
  }
24211
24505
  }
24212
24506
  const historyPath = getHistoryPath(workingDir);
24213
- const historyDir = path46.dirname(historyPath);
24507
+ const historyDir = path47.dirname(historyPath);
24214
24508
  _internals40.validateProjectRoot(workingDir);
24215
24509
  if (!fs21.existsSync(historyDir)) {
24216
24510
  fs21.mkdirSync(historyDir, { recursive: true });
@@ -24340,7 +24634,7 @@ var _internals40 = {
24340
24634
 
24341
24635
  // src/tools/resolve-working-directory.ts
24342
24636
  import * as fs22 from "fs";
24343
- import * as path47 from "path";
24637
+ import * as path48 from "path";
24344
24638
  function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
24345
24639
  if (workingDirectory == null || workingDirectory === "") {
24346
24640
  if (typeof fallbackDirectory !== "string" || fallbackDirectory === "") {
@@ -24372,15 +24666,15 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
24372
24666
  };
24373
24667
  }
24374
24668
  }
24375
- const rawPathParts = workingDirectory.split(path47.sep);
24669
+ const rawPathParts = workingDirectory.split(path48.sep);
24376
24670
  if (rawPathParts.includes("..")) {
24377
24671
  return {
24378
24672
  success: false,
24379
24673
  message: "Invalid working_directory: path traversal sequences (..) are not allowed"
24380
24674
  };
24381
24675
  }
24382
- const normalizedDir = path47.normalize(workingDirectory);
24383
- const resolvedDir = path47.resolve(normalizedDir);
24676
+ const normalizedDir = path48.normalize(workingDirectory);
24677
+ const resolvedDir = path48.resolve(normalizedDir);
24384
24678
  let statResult;
24385
24679
  try {
24386
24680
  statResult = fs22.statSync(resolvedDir);
@@ -24399,7 +24693,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
24399
24693
  if (typeof fallbackDirectory !== "string" || fallbackDirectory === "") {
24400
24694
  return { success: true, directory: resolvedDir };
24401
24695
  }
24402
- const resolvedFallback = path47.resolve(fallbackDirectory);
24696
+ const resolvedFallback = path48.resolve(fallbackDirectory);
24403
24697
  let fallbackExists = false;
24404
24698
  try {
24405
24699
  fs22.statSync(resolvedFallback);
@@ -24408,7 +24702,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
24408
24702
  fallbackExists = false;
24409
24703
  }
24410
24704
  if (fallbackExists) {
24411
- const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path47.sep);
24705
+ const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path48.sep);
24412
24706
  if (isSubdirectory) {
24413
24707
  return {
24414
24708
  success: false,
@@ -24431,7 +24725,7 @@ async function estimateFanOut(sourceFiles, cwd) {
24431
24725
  const impactMap = await loadImpactMap(cwd, { skipRebuild: true });
24432
24726
  const uniqueTestFiles = new Set;
24433
24727
  for (const sourceFile of sourceFiles) {
24434
- const resolvedPath = path48.resolve(cwd, sourceFile);
24728
+ const resolvedPath = path49.resolve(cwd, sourceFile);
24435
24729
  const normalizedPath = resolvedPath.replace(/\\/g, "/");
24436
24730
  const testFiles = impactMap[normalizedPath];
24437
24731
  if (testFiles) {
@@ -24516,14 +24810,14 @@ function hasDevDependency(devDeps, ...patterns) {
24516
24810
  return hasPackageJsonDependency(devDeps, ...patterns);
24517
24811
  }
24518
24812
  function detectGoTest(cwd) {
24519
- return fs23.existsSync(path48.join(cwd, "go.mod")) && isCommandAvailable("go");
24813
+ return fs23.existsSync(path49.join(cwd, "go.mod")) && isCommandAvailable("go");
24520
24814
  }
24521
24815
  function detectJavaMaven(cwd) {
24522
- return fs23.existsSync(path48.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
24816
+ return fs23.existsSync(path49.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
24523
24817
  }
24524
24818
  function detectGradle(cwd) {
24525
- const hasBuildFile = fs23.existsSync(path48.join(cwd, "build.gradle")) || fs23.existsSync(path48.join(cwd, "build.gradle.kts"));
24526
- const hasGradlew = fs23.existsSync(path48.join(cwd, "gradlew")) || fs23.existsSync(path48.join(cwd, "gradlew.bat"));
24819
+ const hasBuildFile = fs23.existsSync(path49.join(cwd, "build.gradle")) || fs23.existsSync(path49.join(cwd, "build.gradle.kts"));
24820
+ const hasGradlew = fs23.existsSync(path49.join(cwd, "gradlew")) || fs23.existsSync(path49.join(cwd, "gradlew.bat"));
24527
24821
  return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
24528
24822
  }
24529
24823
  function detectDotnetTest(cwd) {
@@ -24536,25 +24830,25 @@ function detectDotnetTest(cwd) {
24536
24830
  }
24537
24831
  }
24538
24832
  function detectCTest(cwd) {
24539
- const hasSource = fs23.existsSync(path48.join(cwd, "CMakeLists.txt"));
24540
- const hasBuildCache = fs23.existsSync(path48.join(cwd, "CMakeCache.txt")) || fs23.existsSync(path48.join(cwd, "build", "CMakeCache.txt"));
24833
+ const hasSource = fs23.existsSync(path49.join(cwd, "CMakeLists.txt"));
24834
+ const hasBuildCache = fs23.existsSync(path49.join(cwd, "CMakeCache.txt")) || fs23.existsSync(path49.join(cwd, "build", "CMakeCache.txt"));
24541
24835
  return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
24542
24836
  }
24543
24837
  function detectSwiftTest(cwd) {
24544
- return fs23.existsSync(path48.join(cwd, "Package.swift")) && isCommandAvailable("swift");
24838
+ return fs23.existsSync(path49.join(cwd, "Package.swift")) && isCommandAvailable("swift");
24545
24839
  }
24546
24840
  function detectDartTest(cwd) {
24547
- return fs23.existsSync(path48.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
24841
+ return fs23.existsSync(path49.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
24548
24842
  }
24549
24843
  function detectRSpec(cwd) {
24550
- const hasRSpecFile = fs23.existsSync(path48.join(cwd, ".rspec"));
24551
- const hasGemfile = fs23.existsSync(path48.join(cwd, "Gemfile"));
24552
- const hasSpecDir = fs23.existsSync(path48.join(cwd, "spec"));
24844
+ const hasRSpecFile = fs23.existsSync(path49.join(cwd, ".rspec"));
24845
+ const hasGemfile = fs23.existsSync(path49.join(cwd, "Gemfile"));
24846
+ const hasSpecDir = fs23.existsSync(path49.join(cwd, "spec"));
24553
24847
  const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
24554
24848
  return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
24555
24849
  }
24556
24850
  function detectMinitest(cwd) {
24557
- return fs23.existsSync(path48.join(cwd, "test")) && (fs23.existsSync(path48.join(cwd, "Gemfile")) || fs23.existsSync(path48.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
24851
+ return fs23.existsSync(path49.join(cwd, "test")) && (fs23.existsSync(path49.join(cwd, "Gemfile")) || fs23.existsSync(path49.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
24558
24852
  }
24559
24853
  var DISPATCH_FRAMEWORK_MAP = {
24560
24854
  bun: "bun",
@@ -24639,7 +24933,7 @@ async function parseTestOutputViaDispatch(framework, output, baseDir) {
24639
24933
  async function detectTestFramework(cwd) {
24640
24934
  const baseDir = cwd;
24641
24935
  try {
24642
- const packageJsonPath = path48.join(baseDir, "package.json");
24936
+ const packageJsonPath = path49.join(baseDir, "package.json");
24643
24937
  if (fs23.existsSync(packageJsonPath)) {
24644
24938
  const content = fs23.readFileSync(packageJsonPath, "utf-8");
24645
24939
  const pkg = JSON.parse(content);
@@ -24660,16 +24954,16 @@ async function detectTestFramework(cwd) {
24660
24954
  return "jest";
24661
24955
  if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
24662
24956
  return "mocha";
24663
- if (fs23.existsSync(path48.join(baseDir, "bun.lockb")) || fs23.existsSync(path48.join(baseDir, "bun.lock"))) {
24957
+ if (fs23.existsSync(path49.join(baseDir, "bun.lockb")) || fs23.existsSync(path49.join(baseDir, "bun.lock"))) {
24664
24958
  if (scripts.test?.includes("bun"))
24665
24959
  return "bun";
24666
24960
  }
24667
24961
  }
24668
24962
  } catch {}
24669
24963
  try {
24670
- const pyprojectTomlPath = path48.join(baseDir, "pyproject.toml");
24671
- const setupCfgPath = path48.join(baseDir, "setup.cfg");
24672
- const requirementsTxtPath = path48.join(baseDir, "requirements.txt");
24964
+ const pyprojectTomlPath = path49.join(baseDir, "pyproject.toml");
24965
+ const setupCfgPath = path49.join(baseDir, "setup.cfg");
24966
+ const requirementsTxtPath = path49.join(baseDir, "requirements.txt");
24673
24967
  if (fs23.existsSync(pyprojectTomlPath)) {
24674
24968
  const content = fs23.readFileSync(pyprojectTomlPath, "utf-8");
24675
24969
  if (content.includes("[tool.pytest"))
@@ -24689,7 +24983,7 @@ async function detectTestFramework(cwd) {
24689
24983
  }
24690
24984
  } catch {}
24691
24985
  try {
24692
- const cargoTomlPath = path48.join(baseDir, "Cargo.toml");
24986
+ const cargoTomlPath = path49.join(baseDir, "Cargo.toml");
24693
24987
  if (fs23.existsSync(cargoTomlPath)) {
24694
24988
  const content = fs23.readFileSync(cargoTomlPath, "utf-8");
24695
24989
  if (content.includes("[dev-dependencies]")) {
@@ -24700,9 +24994,9 @@ async function detectTestFramework(cwd) {
24700
24994
  }
24701
24995
  } catch {}
24702
24996
  try {
24703
- const pesterConfigPath = path48.join(baseDir, "pester.config.ps1");
24704
- const pesterConfigJsonPath = path48.join(baseDir, "pester.config.ps1.json");
24705
- const pesterPs1Path = path48.join(baseDir, "tests.ps1");
24997
+ const pesterConfigPath = path49.join(baseDir, "pester.config.ps1");
24998
+ const pesterConfigJsonPath = path49.join(baseDir, "pester.config.ps1.json");
24999
+ const pesterPs1Path = path49.join(baseDir, "tests.ps1");
24706
25000
  if (fs23.existsSync(pesterConfigPath) || fs23.existsSync(pesterConfigJsonPath) || fs23.existsSync(pesterPs1Path)) {
24707
25001
  return "pester";
24708
25002
  }
@@ -24745,12 +25039,12 @@ function isTestDirectoryPath(normalizedPath) {
24745
25039
  return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
24746
25040
  }
24747
25041
  function resolveWorkspacePath(file, workingDir) {
24748
- return path48.isAbsolute(file) ? path48.resolve(file) : path48.resolve(workingDir, file);
25042
+ return path49.isAbsolute(file) ? path49.resolve(file) : path49.resolve(workingDir, file);
24749
25043
  }
24750
25044
  function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
24751
25045
  if (!preferRelative)
24752
25046
  return absolutePath;
24753
- return path48.relative(workingDir, absolutePath);
25047
+ return path49.relative(workingDir, absolutePath);
24754
25048
  }
24755
25049
  function dedupePush(target, value) {
24756
25050
  if (!target.includes(value)) {
@@ -24787,18 +25081,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
24787
25081
  }
24788
25082
  }
24789
25083
  function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
24790
- const relativeDir = path48.dirname(relativePath);
25084
+ const relativeDir = path49.dirname(relativePath);
24791
25085
  const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
24792
25086
  const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
24793
- const rootDir = path48.join(workingDir, dirName);
24794
- return nestedRelativeDir ? [rootDir, path48.join(rootDir, nestedRelativeDir)] : [rootDir];
25087
+ const rootDir = path49.join(workingDir, dirName);
25088
+ return nestedRelativeDir ? [rootDir, path49.join(rootDir, nestedRelativeDir)] : [rootDir];
24795
25089
  });
24796
25090
  const normalizedRelativePath = relativePath.replace(/\\/g, "/");
24797
25091
  if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
24798
- directories.push(path48.join(workingDir, "src/test/java", path48.dirname(normalizedRelativePath.slice("src/main/java/".length))));
25092
+ directories.push(path49.join(workingDir, "src/test/java", path49.dirname(normalizedRelativePath.slice("src/main/java/".length))));
24799
25093
  }
24800
25094
  if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
24801
- directories.push(path48.join(workingDir, "src/test/kotlin", path48.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
25095
+ directories.push(path49.join(workingDir, "src/test/kotlin", path49.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
24802
25096
  }
24803
25097
  return [...new Set(directories)];
24804
25098
  }
@@ -24826,23 +25120,23 @@ function isLanguageSpecificTestFile(basename9) {
24826
25120
  }
24827
25121
  function isConventionTestFilePath(filePath) {
24828
25122
  const normalizedPath = filePath.replace(/\\/g, "/");
24829
- const basename9 = path48.basename(filePath);
25123
+ const basename9 = path49.basename(filePath);
24830
25124
  return hasCompoundTestExtension(basename9) || basename9.includes(".spec.") || basename9.includes(".test.") || isLanguageSpecificTestFile(basename9) || isTestDirectoryPath(normalizedPath);
24831
25125
  }
24832
25126
  function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
24833
25127
  const testFiles = [];
24834
25128
  for (const file of sourceFiles) {
24835
25129
  const absoluteFile = resolveWorkspacePath(file, workingDir);
24836
- const relativeFile = path48.relative(workingDir, absoluteFile);
24837
- const basename9 = path48.basename(absoluteFile);
24838
- const dirname23 = path48.dirname(absoluteFile);
24839
- const preferRelativeOutput = !path48.isAbsolute(file);
25130
+ const relativeFile = path49.relative(workingDir, absoluteFile);
25131
+ const basename9 = path49.basename(absoluteFile);
25132
+ const dirname23 = path49.dirname(absoluteFile);
25133
+ const preferRelativeOutput = !path49.isAbsolute(file);
24840
25134
  if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file)) {
24841
25135
  dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
24842
25136
  continue;
24843
25137
  }
24844
25138
  const nameWithoutExt = basename9.replace(/\.[^.]+$/, "");
24845
- const ext = path48.extname(basename9);
25139
+ const ext = path49.extname(basename9);
24846
25140
  const genericTestNames = [
24847
25141
  `${nameWithoutExt}.spec${ext}`,
24848
25142
  `${nameWithoutExt}.test${ext}`
@@ -24851,7 +25145,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
24851
25145
  const colocatedCandidates = [
24852
25146
  ...genericTestNames,
24853
25147
  ...languageSpecificTestNames
24854
- ].map((candidateName) => path48.join(dirname23, candidateName));
25148
+ ].map((candidateName) => path49.join(dirname23, candidateName));
24855
25149
  const testDirectoryNames = [
24856
25150
  basename9,
24857
25151
  ...genericTestNames,
@@ -24860,8 +25154,8 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
24860
25154
  const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
24861
25155
  const possibleTestFiles = [
24862
25156
  ...colocatedCandidates,
24863
- ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path48.join(dirname23, dirName, candidateName))),
24864
- ...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path48.join(candidateDir, candidateName)))
25157
+ ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path49.join(dirname23, dirName, candidateName))),
25158
+ ...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path49.join(candidateDir, candidateName)))
24865
25159
  ];
24866
25160
  for (const testFile of possibleTestFiles) {
24867
25161
  if (fs23.existsSync(testFile)) {
@@ -24882,7 +25176,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
24882
25176
  try {
24883
25177
  const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
24884
25178
  const content = fs23.readFileSync(absoluteTestFile, "utf-8");
24885
- const testDir = path48.dirname(absoluteTestFile);
25179
+ const testDir = path49.dirname(absoluteTestFile);
24886
25180
  const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
24887
25181
  let match;
24888
25182
  match = importRegex.exec(content);
@@ -24890,8 +25184,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
24890
25184
  const importPath = match[1];
24891
25185
  let resolvedImport;
24892
25186
  if (importPath.startsWith(".")) {
24893
- resolvedImport = path48.resolve(testDir, importPath);
24894
- const existingExt = path48.extname(resolvedImport);
25187
+ resolvedImport = path49.resolve(testDir, importPath);
25188
+ const existingExt = path49.extname(resolvedImport);
24895
25189
  if (!existingExt) {
24896
25190
  for (const extToTry of [
24897
25191
  ".ts",
@@ -24911,12 +25205,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
24911
25205
  } else {
24912
25206
  continue;
24913
25207
  }
24914
- const importBasename = path48.basename(resolvedImport, path48.extname(resolvedImport));
24915
- const importDir = path48.dirname(resolvedImport);
25208
+ const importBasename = path49.basename(resolvedImport, path49.extname(resolvedImport));
25209
+ const importDir = path49.dirname(resolvedImport);
24916
25210
  for (const sourceFile of absoluteSourceFiles) {
24917
- const sourceDir = path48.dirname(sourceFile);
24918
- const sourceBasename = path48.basename(sourceFile, path48.extname(sourceFile));
24919
- const isRelatedDir = importDir === sourceDir || importDir === path48.join(sourceDir, "__tests__") || importDir === path48.join(sourceDir, "tests") || importDir === path48.join(sourceDir, "test") || importDir === path48.join(sourceDir, "spec");
25211
+ const sourceDir = path49.dirname(sourceFile);
25212
+ const sourceBasename = path49.basename(sourceFile, path49.extname(sourceFile));
25213
+ const isRelatedDir = importDir === sourceDir || importDir === path49.join(sourceDir, "__tests__") || importDir === path49.join(sourceDir, "tests") || importDir === path49.join(sourceDir, "test") || importDir === path49.join(sourceDir, "spec");
24920
25214
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
24921
25215
  dedupePush(testFiles, testFile);
24922
25216
  break;
@@ -24929,8 +25223,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
24929
25223
  while (match !== null) {
24930
25224
  const importPath = match[1];
24931
25225
  if (importPath.startsWith(".")) {
24932
- let resolvedImport = path48.resolve(testDir, importPath);
24933
- const existingExt = path48.extname(resolvedImport);
25226
+ let resolvedImport = path49.resolve(testDir, importPath);
25227
+ const existingExt = path49.extname(resolvedImport);
24934
25228
  if (!existingExt) {
24935
25229
  for (const extToTry of [
24936
25230
  ".ts",
@@ -24947,12 +25241,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
24947
25241
  }
24948
25242
  }
24949
25243
  }
24950
- const importDir = path48.dirname(resolvedImport);
24951
- const importBasename = path48.basename(resolvedImport, path48.extname(resolvedImport));
25244
+ const importDir = path49.dirname(resolvedImport);
25245
+ const importBasename = path49.basename(resolvedImport, path49.extname(resolvedImport));
24952
25246
  for (const sourceFile of absoluteSourceFiles) {
24953
- const sourceDir = path48.dirname(sourceFile);
24954
- const sourceBasename = path48.basename(sourceFile, path48.extname(sourceFile));
24955
- const isRelatedDir = importDir === sourceDir || importDir === path48.join(sourceDir, "__tests__") || importDir === path48.join(sourceDir, "tests") || importDir === path48.join(sourceDir, "test") || importDir === path48.join(sourceDir, "spec");
25247
+ const sourceDir = path49.dirname(sourceFile);
25248
+ const sourceBasename = path49.basename(sourceFile, path49.extname(sourceFile));
25249
+ const isRelatedDir = importDir === sourceDir || importDir === path49.join(sourceDir, "__tests__") || importDir === path49.join(sourceDir, "tests") || importDir === path49.join(sourceDir, "test") || importDir === path49.join(sourceDir, "spec");
24956
25250
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
24957
25251
  dedupePush(testFiles, testFile);
24958
25252
  break;
@@ -25072,8 +25366,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
25072
25366
  return ["mvn", "test"];
25073
25367
  case "gradle": {
25074
25368
  const isWindows = process.platform === "win32";
25075
- const hasGradlewBat = fs23.existsSync(path48.join(baseDir, "gradlew.bat"));
25076
- const hasGradlew = fs23.existsSync(path48.join(baseDir, "gradlew"));
25369
+ const hasGradlewBat = fs23.existsSync(path49.join(baseDir, "gradlew.bat"));
25370
+ const hasGradlew = fs23.existsSync(path49.join(baseDir, "gradlew"));
25077
25371
  if (hasGradlewBat && isWindows)
25078
25372
  return ["gradlew.bat", "test"];
25079
25373
  if (hasGradlew)
@@ -25090,7 +25384,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
25090
25384
  "cmake-build-release",
25091
25385
  "out"
25092
25386
  ];
25093
- const actualBuildDir = buildDirCandidates.find((d) => fs23.existsSync(path48.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
25387
+ const actualBuildDir = buildDirCandidates.find((d) => fs23.existsSync(path49.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
25094
25388
  return ["ctest", "--test-dir", actualBuildDir];
25095
25389
  }
25096
25390
  case "swift-test":
@@ -25524,11 +25818,11 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd, bail
25524
25818
  };
25525
25819
  }
25526
25820
  const startTime = Date.now();
25527
- const vitestJsonOutputPath = framework === "vitest" ? path48.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
25821
+ const vitestJsonOutputPath = framework === "vitest" ? path49.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
25528
25822
  try {
25529
25823
  if (vitestJsonOutputPath) {
25530
25824
  try {
25531
- fs23.mkdirSync(path48.dirname(vitestJsonOutputPath), { recursive: true });
25825
+ fs23.mkdirSync(path49.dirname(vitestJsonOutputPath), { recursive: true });
25532
25826
  if (fs23.existsSync(vitestJsonOutputPath)) {
25533
25827
  fs23.unlinkSync(vitestJsonOutputPath);
25534
25828
  }
@@ -25539,9 +25833,9 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd, bail
25539
25833
  stderr: "pipe",
25540
25834
  cwd
25541
25835
  });
25542
- const timeoutPromise = new Promise((resolve15) => setTimeout(() => {
25836
+ const timeoutPromise = new Promise((resolve16) => setTimeout(() => {
25543
25837
  proc.kill();
25544
- resolve15(-1);
25838
+ resolve16(-1);
25545
25839
  }, timeout_ms));
25546
25840
  const [exitCode, stdoutResult, stderrResult] = await Promise.all([
25547
25841
  Promise.race([proc.exited, timeoutPromise]),
@@ -25696,10 +25990,10 @@ var SKIP_DIRECTORIES = new Set([
25696
25990
  ]);
25697
25991
  function normalizeHistoryTestFile(testFile, workingDir) {
25698
25992
  const normalized = testFile.replace(/\\/g, "/");
25699
- if (!path48.isAbsolute(testFile))
25993
+ if (!path49.isAbsolute(testFile))
25700
25994
  return normalized;
25701
- const relative8 = path48.relative(workingDir, testFile);
25702
- if (relative8.startsWith("..") || path48.isAbsolute(relative8)) {
25995
+ const relative8 = path49.relative(workingDir, testFile);
25996
+ if (relative8.startsWith("..") || path49.isAbsolute(relative8)) {
25703
25997
  return normalized;
25704
25998
  }
25705
25999
  return relative8.replace(/\\/g, "/");
@@ -25938,7 +26232,7 @@ var test_runner = createSwarmTool({
25938
26232
  const sourceFiles = args.files.filter((file) => {
25939
26233
  if (directTestFiles.includes(file))
25940
26234
  return false;
25941
- const ext = path48.extname(file).toLowerCase();
26235
+ const ext = path49.extname(file).toLowerCase();
25942
26236
  return SOURCE_EXTENSIONS.has(ext);
25943
26237
  });
25944
26238
  const invalidFiles = args.files.filter((file) => !directTestFiles.includes(file) && !sourceFiles.includes(file));
@@ -25984,7 +26278,7 @@ var test_runner = createSwarmTool({
25984
26278
  if (isConventionTestFilePath(f)) {
25985
26279
  return false;
25986
26280
  }
25987
- const ext = path48.extname(f).toLowerCase();
26281
+ const ext = path49.extname(f).toLowerCase();
25988
26282
  return SOURCE_EXTENSIONS.has(ext);
25989
26283
  });
25990
26284
  if (sourceFiles.length === 0) {
@@ -26034,7 +26328,7 @@ var test_runner = createSwarmTool({
26034
26328
  if (isConventionTestFilePath(f)) {
26035
26329
  return false;
26036
26330
  }
26037
- const ext = path48.extname(f).toLowerCase();
26331
+ const ext = path49.extname(f).toLowerCase();
26038
26332
  return SOURCE_EXTENSIONS.has(ext);
26039
26333
  });
26040
26334
  if (sourceFiles.length === 0) {
@@ -26086,8 +26380,8 @@ var test_runner = createSwarmTool({
26086
26380
  }
26087
26381
  if (impactResult.impactedTests.length > 0) {
26088
26382
  testFiles = impactResult.impactedTests.map((absPath) => {
26089
- const relativePath = path48.relative(workingDir, absPath);
26090
- return path48.isAbsolute(relativePath) ? absPath : relativePath;
26383
+ const relativePath = path49.relative(workingDir, absPath);
26384
+ return path49.isAbsolute(relativePath) ? absPath : relativePath;
26091
26385
  });
26092
26386
  } else {
26093
26387
  graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
@@ -26182,8 +26476,8 @@ function validateDirectoryPath(dir) {
26182
26476
  if (dir.includes("..")) {
26183
26477
  throw new Error("Directory path must not contain path traversal sequences");
26184
26478
  }
26185
- const normalized = path49.normalize(dir);
26186
- const absolutePath = path49.isAbsolute(normalized) ? normalized : path49.resolve(normalized);
26479
+ const normalized = path50.normalize(dir);
26480
+ const absolutePath = path50.isAbsolute(normalized) ? normalized : path50.resolve(normalized);
26187
26481
  return absolutePath;
26188
26482
  }
26189
26483
  function validateTimeout(timeoutMs, defaultValue) {
@@ -26206,7 +26500,7 @@ function validateTimeout(timeoutMs, defaultValue) {
26206
26500
  }
26207
26501
  function getPackageVersion(dir) {
26208
26502
  try {
26209
- const packagePath = path49.join(dir, "package.json");
26503
+ const packagePath = path50.join(dir, "package.json");
26210
26504
  if (fs24.existsSync(packagePath)) {
26211
26505
  const content = fs24.readFileSync(packagePath, "utf-8");
26212
26506
  const pkg = JSON.parse(content);
@@ -26217,7 +26511,7 @@ function getPackageVersion(dir) {
26217
26511
  }
26218
26512
  function getChangelogVersion(dir) {
26219
26513
  try {
26220
- const changelogPath = path49.join(dir, "CHANGELOG.md");
26514
+ const changelogPath = path50.join(dir, "CHANGELOG.md");
26221
26515
  if (fs24.existsSync(changelogPath)) {
26222
26516
  const content = fs24.readFileSync(changelogPath, "utf-8");
26223
26517
  const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
@@ -26231,7 +26525,7 @@ function getChangelogVersion(dir) {
26231
26525
  function getVersionFileVersion(dir) {
26232
26526
  const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
26233
26527
  for (const file of possibleFiles) {
26234
- const filePath = path49.join(dir, file);
26528
+ const filePath = path50.join(dir, file);
26235
26529
  if (fs24.existsSync(filePath)) {
26236
26530
  try {
26237
26531
  const content = fs24.readFileSync(filePath, "utf-8").trim();
@@ -26969,7 +27263,7 @@ async function handleQaGatesCommand(directory, args, sessionID) {
26969
27263
 
26970
27264
  // src/commands/reset.ts
26971
27265
  import * as fs25 from "fs";
26972
- import * as path50 from "path";
27266
+ import * as path51 from "path";
26973
27267
 
26974
27268
  // src/background/circuit-breaker.ts
26975
27269
  class CircuitBreaker {
@@ -27021,13 +27315,13 @@ class CircuitBreaker {
27021
27315
  if (this.config.callTimeoutMs <= 0) {
27022
27316
  return fn();
27023
27317
  }
27024
- return new Promise((resolve16, reject) => {
27318
+ return new Promise((resolve17, reject) => {
27025
27319
  const timeout = setTimeout(() => {
27026
27320
  reject(new Error(`Call timeout after ${this.config.callTimeoutMs}ms`));
27027
27321
  }, this.config.callTimeoutMs);
27028
27322
  fn().then((result) => {
27029
27323
  clearTimeout(timeout);
27030
- resolve16(result);
27324
+ resolve17(result);
27031
27325
  }).catch((error2) => {
27032
27326
  clearTimeout(timeout);
27033
27327
  reject(error2);
@@ -27311,7 +27605,7 @@ class AutomationQueue {
27311
27605
 
27312
27606
  // src/background/worker.ts
27313
27607
  function sleep(ms) {
27314
- return new Promise((resolve16) => setTimeout(resolve16, ms));
27608
+ return new Promise((resolve17) => setTimeout(resolve17, ms));
27315
27609
  }
27316
27610
 
27317
27611
  class WorkerManager {
@@ -27686,7 +27980,7 @@ async function handleResetCommand(directory, args) {
27686
27980
  }
27687
27981
  for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
27688
27982
  try {
27689
- const rootPath = path50.join(directory, filename);
27983
+ const rootPath = path51.join(directory, filename);
27690
27984
  if (fs25.existsSync(rootPath)) {
27691
27985
  fs25.unlinkSync(rootPath);
27692
27986
  results.push(`- \u2705 Deleted ${filename} (root)`);
@@ -27724,7 +28018,7 @@ async function handleResetCommand(directory, args) {
27724
28018
 
27725
28019
  // src/commands/reset-session.ts
27726
28020
  import * as fs27 from "fs";
27727
- import * as path52 from "path";
28021
+ import * as path53 from "path";
27728
28022
 
27729
28023
  // src/hooks/trajectory-logger.ts
27730
28024
  var callStartTimes = new Map;
@@ -28131,16 +28425,16 @@ function detectPatterns(trajectory, config, lastProcessedStep = 0) {
28131
28425
  }
28132
28426
  // src/prm/replay.ts
28133
28427
  import { promises as fs26 } from "fs";
28134
- import path51 from "path";
28428
+ import path52 from "path";
28135
28429
  function isPathSafe(targetPath, basePath) {
28136
- const resolvedTarget = path51.resolve(targetPath);
28137
- const resolvedBase = path51.resolve(basePath);
28138
- const rel = path51.relative(resolvedBase, resolvedTarget);
28139
- return !rel.startsWith("..") && !path51.isAbsolute(rel);
28430
+ const resolvedTarget = path52.resolve(targetPath);
28431
+ const resolvedBase = path52.resolve(basePath);
28432
+ const rel = path52.relative(resolvedBase, resolvedTarget);
28433
+ return !rel.startsWith("..") && !path52.isAbsolute(rel);
28140
28434
  }
28141
28435
  function isWithinReplaysDir(targetPath) {
28142
- const resolved = path51.resolve(targetPath);
28143
- const parts = resolved.split(path51.sep);
28436
+ const resolved = path52.resolve(targetPath);
28437
+ const parts = resolved.split(path52.sep);
28144
28438
  for (let i = 0;i < parts.length - 1; i++) {
28145
28439
  if (parts[i] === ".swarm" && parts[i + 1] === "replays") {
28146
28440
  return true;
@@ -28153,10 +28447,10 @@ function sanitizeFilename(input) {
28153
28447
  }
28154
28448
  async function startReplayRecording(sessionID, directory) {
28155
28449
  try {
28156
- const replayDir = path51.join(directory, ".swarm", "replays");
28450
+ const replayDir = path52.join(directory, ".swarm", "replays");
28157
28451
  const safeSessionID = sanitizeFilename(sessionID);
28158
28452
  const filename = `${safeSessionID}-${Date.now()}.jsonl`;
28159
- const filepath = path51.join(replayDir, filename);
28453
+ const filepath = path52.join(replayDir, filename);
28160
28454
  if (!isPathSafe(filepath, replayDir)) {
28161
28455
  console.warn(`[replay] Invalid path detected - path traversal attempt blocked for session ${sessionID}`);
28162
28456
  return null;
@@ -28234,7 +28528,7 @@ async function handleResetSessionCommand(directory, _args) {
28234
28528
  } catch {
28235
28529
  results.push("\u274C Failed to delete state.json");
28236
28530
  }
28237
- const sessionDir = path52.dirname(validateSwarmPath(directory, "session/state.json"));
28531
+ const sessionDir = path53.dirname(validateSwarmPath(directory, "session/state.json"));
28238
28532
  let sessionFiles = [];
28239
28533
  if (fs27.existsSync(sessionDir)) {
28240
28534
  try {
@@ -28246,7 +28540,7 @@ async function handleResetSessionCommand(directory, _args) {
28246
28540
  for (const file of sessionFiles) {
28247
28541
  if (file === "state.json")
28248
28542
  continue;
28249
- const filePath = path52.join(sessionDir, file);
28543
+ const filePath = path53.join(sessionDir, file);
28250
28544
  try {
28251
28545
  if (!fs27.existsSync(filePath))
28252
28546
  continue;
@@ -28281,7 +28575,7 @@ async function handleResetSessionCommand(directory, _args) {
28281
28575
  }
28282
28576
 
28283
28577
  // src/summaries/manager.ts
28284
- import * as path53 from "path";
28578
+ import * as path54 from "path";
28285
28579
  var SUMMARY_ID_REGEX = /^S\d+$/;
28286
28580
  function sanitizeSummaryId(id) {
28287
28581
  if (!id || id.length === 0) {
@@ -28305,7 +28599,7 @@ function sanitizeSummaryId(id) {
28305
28599
  }
28306
28600
  async function loadFullOutput(directory, id) {
28307
28601
  const sanitizedId = sanitizeSummaryId(id);
28308
- const relativePath = path53.join("summaries", `${sanitizedId}.json`);
28602
+ const relativePath = path54.join("summaries", `${sanitizedId}.json`);
28309
28603
  validateSwarmPath(directory, relativePath);
28310
28604
  const content = await readSwarmFileAsync(directory, relativePath);
28311
28605
  if (content === null) {
@@ -28358,7 +28652,7 @@ ${error2 instanceof Error ? error2.message : String(error2)}`;
28358
28652
 
28359
28653
  // src/commands/rollback.ts
28360
28654
  import * as fs28 from "fs";
28361
- import * as path54 from "path";
28655
+ import * as path55 from "path";
28362
28656
  async function handleRollbackCommand(directory, args) {
28363
28657
  const phaseArg = args[0];
28364
28658
  if (!phaseArg) {
@@ -28424,8 +28718,8 @@ async function handleRollbackCommand(directory, args) {
28424
28718
  if (EXCLUDE_FILES.has(file) || file.startsWith("plan-ledger.archived-")) {
28425
28719
  continue;
28426
28720
  }
28427
- const src = path54.join(checkpointDir, file);
28428
- const dest = path54.join(swarmDir, file);
28721
+ const src = path55.join(checkpointDir, file);
28722
+ const dest = path55.join(swarmDir, file);
28429
28723
  try {
28430
28724
  fs28.cpSync(src, dest, { recursive: true, force: true });
28431
28725
  successes.push(file);
@@ -28444,7 +28738,7 @@ async function handleRollbackCommand(directory, args) {
28444
28738
  ].join(`
28445
28739
  `);
28446
28740
  }
28447
- const existingLedgerPath = path54.join(swarmDir, "plan-ledger.jsonl");
28741
+ const existingLedgerPath = path55.join(swarmDir, "plan-ledger.jsonl");
28448
28742
  let ledgerDeletionFailed = false;
28449
28743
  if (fs28.existsSync(existingLedgerPath)) {
28450
28744
  try {
@@ -28457,7 +28751,7 @@ async function handleRollbackCommand(directory, args) {
28457
28751
  }
28458
28752
  if (!ledgerDeletionFailed) {
28459
28753
  try {
28460
- const planJsonPath = path54.join(swarmDir, "plan.json");
28754
+ const planJsonPath = path55.join(swarmDir, "plan.json");
28461
28755
  if (fs28.existsSync(planJsonPath)) {
28462
28756
  const planRaw = fs28.readFileSync(planJsonPath, "utf-8");
28463
28757
  const plan = PlanSchema.parse(JSON.parse(planRaw));
@@ -28718,10 +29012,10 @@ Ensure this is a git repository with commit history.`;
28718
29012
  `);
28719
29013
  try {
28720
29014
  const fs29 = await import("fs/promises");
28721
- const path55 = await import("path");
28722
- const reportPath = path55.join(directory, ".swarm", "simulate-report.md");
28723
- await fs29.mkdir(path55.dirname(reportPath), { recursive: true });
28724
- const reportTempPath = path55.join(path55.dirname(reportPath), `${path55.basename(reportPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
29015
+ const path56 = await import("path");
29016
+ const reportPath = path56.join(directory, ".swarm", "simulate-report.md");
29017
+ await fs29.mkdir(path56.dirname(reportPath), { recursive: true });
29018
+ const reportTempPath = path56.join(path56.dirname(reportPath), `${path56.basename(reportPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
28725
29019
  try {
28726
29020
  await fs29.writeFile(reportTempPath, report, "utf-8");
28727
29021
  renameSync11(reportTempPath, reportPath);
@@ -28750,18 +29044,18 @@ async function handleSpecifyCommand(_directory, args) {
28750
29044
  // src/services/status-service.ts
28751
29045
  import * as fsSync3 from "fs";
28752
29046
  import { readFile as readFile15 } from "fs/promises";
28753
- import * as path56 from "path";
29047
+ import * as path57 from "path";
28754
29048
 
28755
29049
  // src/turbo/lean/state.ts
28756
29050
  init_logger();
28757
29051
  import * as fs29 from "fs";
28758
- import * as path55 from "path";
29052
+ import * as path56 from "path";
28759
29053
  var STATE_FILE3 = "turbo-state.json";
28760
29054
  function nowISO3() {
28761
29055
  return new Date().toISOString();
28762
29056
  }
28763
29057
  function ensureSwarmDir2(directory) {
28764
- const swarmDir = path55.resolve(directory, ".swarm");
29058
+ const swarmDir = path56.resolve(directory, ".swarm");
28765
29059
  if (!fs29.existsSync(swarmDir)) {
28766
29060
  fs29.mkdirSync(swarmDir, { recursive: true });
28767
29061
  }
@@ -28806,7 +29100,7 @@ function markStateUnreadable2(directory, reason) {
28806
29100
  }
28807
29101
  function readPersisted2(directory) {
28808
29102
  try {
28809
- const filePath = path55.join(directory, ".swarm", STATE_FILE3);
29103
+ const filePath = path56.join(directory, ".swarm", STATE_FILE3);
28810
29104
  if (!fs29.existsSync(filePath)) {
28811
29105
  const seed = emptyPersisted2();
28812
29106
  try {
@@ -28842,7 +29136,7 @@ function writePersisted2(directory, persisted) {
28842
29136
  let payload;
28843
29137
  try {
28844
29138
  ensureSwarmDir2(directory);
28845
- filePath = path55.join(directory, ".swarm", STATE_FILE3);
29139
+ filePath = path56.join(directory, ".swarm", STATE_FILE3);
28846
29140
  tmpPath = `${filePath}.tmp.${Date.now()}`;
28847
29141
  persisted.updatedAt = nowISO3();
28848
29142
  payload = `${JSON.stringify(persisted, null, 2)}
@@ -28960,7 +29254,7 @@ var _internals43 = {
28960
29254
  };
28961
29255
  function readSpecStalenessSnapshot(directory) {
28962
29256
  try {
28963
- const p = path56.join(directory, ".swarm", "spec-staleness.json");
29257
+ const p = path57.join(directory, ".swarm", "spec-staleness.json");
28964
29258
  if (!fsSync3.existsSync(p))
28965
29259
  return { stale: false };
28966
29260
  const raw = fsSync3.readFileSync(p, "utf-8");
@@ -29627,7 +29921,7 @@ function buildDetailedHelp(commandName, entry) {
29627
29921
  async function handleHelpCommand(ctx) {
29628
29922
  const targetCommand = ctx.args.join(" ");
29629
29923
  if (!targetCommand) {
29630
- const { buildHelpText } = await import("./index-r3f47swm.js");
29924
+ const { buildHelpText } = await import("./index-sr7g2msm.js");
29631
29925
  return buildHelpText();
29632
29926
  }
29633
29927
  const tokens = targetCommand.split(/\s+/);
@@ -29636,7 +29930,7 @@ async function handleHelpCommand(ctx) {
29636
29930
  return _internals45.buildDetailedHelp(resolved.key, resolved.entry);
29637
29931
  }
29638
29932
  const similar = _internals45.findSimilarCommands(targetCommand);
29639
- const { buildHelpText: fullHelp } = await import("./index-r3f47swm.js");
29933
+ const { buildHelpText: fullHelp } = await import("./index-sr7g2msm.js");
29640
29934
  if (similar.length > 0) {
29641
29935
  return `Command '/swarm ${targetCommand}' not found.
29642
29936
 
@@ -29769,7 +30063,7 @@ var COMMAND_REGISTRY = {
29769
30063
  },
29770
30064
  "guardrail explain": {
29771
30065
  handler: async (ctx) => {
29772
- const { handleGuardrailExplain } = await import("./guardrail-explain-2q9myk7c.js");
30066
+ const { handleGuardrailExplain } = await import("./guardrail-explain-995zavv8.js");
29773
30067
  return handleGuardrailExplain(ctx.directory, ctx.args);
29774
30068
  },
29775
30069
  description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
@@ -29779,7 +30073,7 @@ var COMMAND_REGISTRY = {
29779
30073
  },
29780
30074
  "guardrail-log": {
29781
30075
  handler: async (ctx) => {
29782
- const { handleGuardrailLog } = await import("./guardrail-log-eegabqcp.js");
30076
+ const { handleGuardrailLog } = await import("./guardrail-log-c7egm5km.js");
29783
30077
  return handleGuardrailLog(ctx.directory, ctx.args);
29784
30078
  },
29785
30079
  description: "Read the guardrail decision log (use --blocks-only for blocks)",
@@ -30509,24 +30803,24 @@ function validateAliases() {
30509
30803
  }
30510
30804
  aliasTargets.get(target).push(name);
30511
30805
  const visited = new Set;
30512
- const path57 = [];
30806
+ const path58 = [];
30513
30807
  let current = target;
30514
30808
  while (current) {
30515
30809
  const currentEntry = COMMAND_REGISTRY[current];
30516
30810
  if (!currentEntry)
30517
30811
  break;
30518
30812
  if (visited.has(current)) {
30519
- const cycleStart = path57.indexOf(current);
30813
+ const cycleStart = path58.indexOf(current);
30520
30814
  const fullChain = [
30521
30815
  name,
30522
- ...path57.slice(0, cycleStart > 0 ? cycleStart : path57.length),
30816
+ ...path58.slice(0, cycleStart > 0 ? cycleStart : path58.length),
30523
30817
  current
30524
30818
  ].join(" \u2192 ");
30525
30819
  errors.push(`Circular alias detected: ${fullChain}`);
30526
30820
  break;
30527
30821
  }
30528
30822
  visited.add(current);
30529
- path57.push(current);
30823
+ path58.push(current);
30530
30824
  current = currentEntry.aliasOf || "";
30531
30825
  }
30532
30826
  }