opencode-swarm 7.88.0 → 7.88.2

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.
@@ -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.88.0",
902
+ version: "7.88.2",
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",
@@ -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) {
@@ -22000,31 +22294,35 @@ var _internals34 = {
22000
22294
  formatRelativeTime,
22001
22295
  listActive
22002
22296
  };
22003
- async function handlePrMonitorStatusCommand(directory, _args, sessionID) {
22297
+ async function handlePrMonitorStatusCommand(directory, _args, sessionID, source) {
22004
22298
  const allActive = await _internals34.listActive(directory);
22005
- const sessionSubs = allActive.filter((record) => record.sessionID === sessionID);
22006
- if (sessionSubs.length === 0) {
22007
- return "No active PR subscriptions for this session.";
22299
+ const allSessions = source === "cli";
22300
+ const subs = allSessions ? allActive : allActive.filter((record) => record.sessionID === sessionID);
22301
+ if (subs.length === 0) {
22302
+ return allSessions ? "No active PR subscriptions." : "No active PR subscriptions for this session.";
22008
22303
  }
22009
22304
  const lines = [];
22010
- lines.push(`PR Monitor Status \u2014 Session: ${sessionID}`);
22305
+ lines.push(allSessions ? "PR Monitor Status \u2014 all sessions" : `PR Monitor Status \u2014 Session: ${sessionID}`);
22011
22306
  lines.push("");
22012
22307
  const totalActive = allActive.length;
22013
- lines.push(`Active subscriptions (${sessionSubs.length}):`);
22014
- for (let i = 0;i < sessionSubs.length; i++) {
22015
- const sub = sessionSubs[i];
22308
+ lines.push(`Active subscriptions (${subs.length}):`);
22309
+ for (let i = 0;i < subs.length; i++) {
22310
+ const sub = subs[i];
22016
22311
  const index = i + 1;
22017
22312
  lines.push(` ${index}. ${sub.repoFullName}#${sub.prNumber}`);
22018
22313
  lines.push(` URL: ${sub.prUrl}`);
22314
+ if (allSessions) {
22315
+ lines.push(` Session: ${sub.sessionID}`);
22316
+ }
22019
22317
  lines.push(` Last checked: ${formatRelativeTime(sub.lastCheckedAt)}`);
22020
22318
  lines.push(` Watching: ${sub.isWatching ? "yes" : "no"}`);
22021
22319
  lines.push(` Errors: ${sub.errorCount}`);
22022
- if (i < sessionSubs.length - 1) {
22320
+ if (i < subs.length - 1) {
22023
22321
  lines.push("");
22024
22322
  }
22025
22323
  }
22026
22324
  lines.push("");
22027
- if (totalActive !== sessionSubs.length) {
22325
+ if (!allSessions && totalActive !== subs.length) {
22028
22326
  lines.push(`Total active across all sessions: ${totalActive}`);
22029
22327
  }
22030
22328
  return lines.join(`
@@ -22121,6 +22419,15 @@ async function handlePrSubscribeCommand(directory, args, sessionID) {
22121
22419
  "Expected: full GitHub URL, owner/repo#N shorthand,",
22122
22420
  "or a bare PR number (resolved against origin)."
22123
22421
  ].join(`
22422
+ `);
22423
+ }
22424
+ if (!sessionID || sessionID.trim() === "") {
22425
+ return [
22426
+ "Error: Cannot subscribe \u2014 no active session.",
22427
+ "",
22428
+ "PR subscriptions are session-scoped and require a live OpenCode session.",
22429
+ "Subscribe from inside OpenCode; the bunx CLI has no session context."
22430
+ ].join(`
22124
22431
  `);
22125
22432
  }
22126
22433
  const repoFullName = `${prInfo.owner}/${prInfo.repo}`;
@@ -22243,11 +22550,11 @@ var _internals36 = {
22243
22550
 
22244
22551
  // src/services/preflight-service.ts
22245
22552
  import * as fs24 from "fs";
22246
- import * as path49 from "path";
22553
+ import * as path50 from "path";
22247
22554
 
22248
22555
  // src/tools/lint.ts
22249
22556
  import * as fs18 from "fs";
22250
- import * as path43 from "path";
22557
+ import * as path44 from "path";
22251
22558
 
22252
22559
  // src/utils/path-security.ts
22253
22560
  function containsPathTraversal(str) {
@@ -22303,9 +22610,9 @@ function validateArgs(args) {
22303
22610
  }
22304
22611
  function getLinterCommand(linter, mode, projectDir) {
22305
22612
  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");
22613
+ const binDir = path44.join(projectDir, "node_modules", ".bin");
22614
+ const biomeBin = isWindows ? path44.join(binDir, "biome.EXE") : path44.join(binDir, "biome");
22615
+ const eslintBin = isWindows ? path44.join(binDir, "eslint.cmd") : path44.join(binDir, "eslint");
22309
22616
  switch (linter) {
22310
22617
  case "biome":
22311
22618
  if (mode === "fix") {
@@ -22321,7 +22628,7 @@ function getLinterCommand(linter, mode, projectDir) {
22321
22628
  }
22322
22629
  function getAdditionalLinterCommand(linter, mode, cwd) {
22323
22630
  const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
22324
- const gradlew = fs18.existsSync(path43.join(cwd, gradlewName)) ? path43.join(cwd, gradlewName) : null;
22631
+ const gradlew = fs18.existsSync(path44.join(cwd, gradlewName)) ? path44.join(cwd, gradlewName) : null;
22325
22632
  switch (linter) {
22326
22633
  case "ruff":
22327
22634
  return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
@@ -22355,10 +22662,10 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
22355
22662
  }
22356
22663
  }
22357
22664
  function detectRuff(cwd) {
22358
- if (fs18.existsSync(path43.join(cwd, "ruff.toml")))
22665
+ if (fs18.existsSync(path44.join(cwd, "ruff.toml")))
22359
22666
  return isCommandAvailable("ruff");
22360
22667
  try {
22361
- const pyproject = path43.join(cwd, "pyproject.toml");
22668
+ const pyproject = path44.join(cwd, "pyproject.toml");
22362
22669
  if (fs18.existsSync(pyproject)) {
22363
22670
  const content = fs18.readFileSync(pyproject, "utf-8");
22364
22671
  if (content.includes("[tool.ruff]"))
@@ -22368,19 +22675,19 @@ function detectRuff(cwd) {
22368
22675
  return false;
22369
22676
  }
22370
22677
  function detectClippy(cwd) {
22371
- return fs18.existsSync(path43.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
22678
+ return fs18.existsSync(path44.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
22372
22679
  }
22373
22680
  function detectGolangciLint(cwd) {
22374
- return fs18.existsSync(path43.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
22681
+ return fs18.existsSync(path44.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
22375
22682
  }
22376
22683
  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"));
22684
+ const hasMaven = fs18.existsSync(path44.join(cwd, "pom.xml"));
22685
+ const hasGradle = fs18.existsSync(path44.join(cwd, "build.gradle")) || fs18.existsSync(path44.join(cwd, "build.gradle.kts"));
22686
+ const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs18.existsSync(path44.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
22380
22687
  return (hasMaven || hasGradle) && hasBinary;
22381
22688
  }
22382
22689
  function detectKtlint(cwd) {
22383
- const hasKotlin = fs18.existsSync(path43.join(cwd, "build.gradle.kts")) || fs18.existsSync(path43.join(cwd, "build.gradle")) || (() => {
22690
+ const hasKotlin = fs18.existsSync(path44.join(cwd, "build.gradle.kts")) || fs18.existsSync(path44.join(cwd, "build.gradle")) || (() => {
22384
22691
  try {
22385
22692
  return fs18.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
22386
22693
  } catch {
@@ -22399,11 +22706,11 @@ function detectDotnetFormat(cwd) {
22399
22706
  }
22400
22707
  }
22401
22708
  function detectCppcheck(cwd) {
22402
- if (fs18.existsSync(path43.join(cwd, "CMakeLists.txt"))) {
22709
+ if (fs18.existsSync(path44.join(cwd, "CMakeLists.txt"))) {
22403
22710
  return isCommandAvailable("cppcheck");
22404
22711
  }
22405
22712
  try {
22406
- const dirsToCheck = [cwd, path43.join(cwd, "src")];
22713
+ const dirsToCheck = [cwd, path44.join(cwd, "src")];
22407
22714
  const hasCpp = dirsToCheck.some((dir) => {
22408
22715
  try {
22409
22716
  return fs18.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
@@ -22417,13 +22724,13 @@ function detectCppcheck(cwd) {
22417
22724
  }
22418
22725
  }
22419
22726
  function detectSwiftlint(cwd) {
22420
- return fs18.existsSync(path43.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
22727
+ return fs18.existsSync(path44.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
22421
22728
  }
22422
22729
  function detectDartAnalyze(cwd) {
22423
- return fs18.existsSync(path43.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
22730
+ return fs18.existsSync(path44.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
22424
22731
  }
22425
22732
  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"));
22733
+ 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
22734
  }
22428
22735
  function detectAdditionalLinter(cwd) {
22429
22736
  if (detectRuff(cwd))
@@ -22451,10 +22758,10 @@ function detectAdditionalLinter(cwd) {
22451
22758
  function findBinInAncestors(startDir, binName) {
22452
22759
  let dir = startDir;
22453
22760
  while (true) {
22454
- const candidate = path43.join(dir, "node_modules", ".bin", binName);
22761
+ const candidate = path44.join(dir, "node_modules", ".bin", binName);
22455
22762
  if (fs18.existsSync(candidate))
22456
22763
  return candidate;
22457
- const parent = path43.dirname(dir);
22764
+ const parent = path44.dirname(dir);
22458
22765
  if (parent === dir)
22459
22766
  break;
22460
22767
  dir = parent;
@@ -22463,10 +22770,10 @@ function findBinInAncestors(startDir, binName) {
22463
22770
  }
22464
22771
  function findBinInEnvPath(binName) {
22465
22772
  const searchPath = process.env.PATH ?? "";
22466
- for (const dir of searchPath.split(path43.delimiter)) {
22773
+ for (const dir of searchPath.split(path44.delimiter)) {
22467
22774
  if (!dir)
22468
22775
  continue;
22469
- const candidate = path43.join(dir, binName);
22776
+ const candidate = path44.join(dir, binName);
22470
22777
  if (fs18.existsSync(candidate))
22471
22778
  return candidate;
22472
22779
  }
@@ -22479,13 +22786,13 @@ async function detectAvailableLinter(directory) {
22479
22786
  return null;
22480
22787
  const projectDir = directory;
22481
22788
  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");
22789
+ const biomeBin = isWindows ? path44.join(projectDir, "node_modules", ".bin", "biome.EXE") : path44.join(projectDir, "node_modules", ".bin", "biome");
22790
+ const eslintBin = isWindows ? path44.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path44.join(projectDir, "node_modules", ".bin", "eslint");
22484
22791
  const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
22485
22792
  if (localResult)
22486
22793
  return localResult;
22487
- const biomeAncestor = findBinInAncestors(path43.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
22488
- const eslintAncestor = findBinInAncestors(path43.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
22794
+ const biomeAncestor = findBinInAncestors(path44.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
22795
+ const eslintAncestor = findBinInAncestors(path44.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
22489
22796
  if (biomeAncestor || eslintAncestor) {
22490
22797
  return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
22491
22798
  }
@@ -22504,7 +22811,7 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
22504
22811
  stderr: "pipe"
22505
22812
  });
22506
22813
  const biomeExit = biomeProc.exited;
22507
- const timeout = new Promise((resolve12) => setTimeout(() => resolve12("timeout"), DETECT_TIMEOUT));
22814
+ const timeout = new Promise((resolve13) => setTimeout(() => resolve13("timeout"), DETECT_TIMEOUT));
22508
22815
  const result = await Promise.race([biomeExit, timeout]);
22509
22816
  if (result === "timeout") {
22510
22817
  biomeProc.kill();
@@ -22518,7 +22825,7 @@ async function _detectAvailableLinter(_projectDir, biomeBin, eslintBin) {
22518
22825
  stderr: "pipe"
22519
22826
  });
22520
22827
  const eslintExit = eslintProc.exited;
22521
- const timeout = new Promise((resolve12) => setTimeout(() => resolve12("timeout"), DETECT_TIMEOUT));
22828
+ const timeout = new Promise((resolve13) => setTimeout(() => resolve13("timeout"), DETECT_TIMEOUT));
22522
22829
  const result = await Promise.race([eslintExit, timeout]);
22523
22830
  if (result === "timeout") {
22524
22831
  eslintProc.kill();
@@ -22699,7 +23006,7 @@ var _internals37 = {
22699
23006
 
22700
23007
  // src/tools/secretscan.ts
22701
23008
  import * as fs19 from "fs";
22702
- import * as path44 from "path";
23009
+ import * as path45 from "path";
22703
23010
  var MAX_FILE_PATH_LENGTH = 500;
22704
23011
  var MAX_FILE_SIZE_BYTES = 512 * 1024;
22705
23012
  var MAX_FILES_SCANNED = 1000;
@@ -22926,7 +23233,7 @@ function isGlobOrPathPattern(pattern) {
22926
23233
  return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
22927
23234
  }
22928
23235
  function loadSecretScanIgnore(scanDir) {
22929
- const ignorePath = path44.join(scanDir, ".secretscanignore");
23236
+ const ignorePath = path45.join(scanDir, ".secretscanignore");
22930
23237
  try {
22931
23238
  if (!fs19.existsSync(ignorePath))
22932
23239
  return [];
@@ -22949,7 +23256,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
22949
23256
  if (exactNames.has(entry))
22950
23257
  return true;
22951
23258
  for (const pattern of globPatterns) {
22952
- if (path44.matchesGlob(relPath, pattern))
23259
+ if (path45.matchesGlob(relPath, pattern))
22953
23260
  return true;
22954
23261
  }
22955
23262
  return false;
@@ -22970,7 +23277,7 @@ function validateDirectoryInput(dir) {
22970
23277
  return null;
22971
23278
  }
22972
23279
  function isBinaryFile(filePath, buffer) {
22973
- const ext = path44.extname(filePath).toLowerCase();
23280
+ const ext = path45.extname(filePath).toLowerCase();
22974
23281
  if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
22975
23282
  return true;
22976
23283
  }
@@ -23107,9 +23414,9 @@ function isSymlinkLoop(realPath, visited) {
23107
23414
  return false;
23108
23415
  }
23109
23416
  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}\\`);
23417
+ const resolvedScanDir = path45.resolve(scanDir);
23418
+ const resolvedRealPath = path45.resolve(realPath);
23419
+ return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path45.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
23113
23420
  }
23114
23421
  function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
23115
23422
  skippedDirs: 0,
@@ -23135,8 +23442,8 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
23135
23442
  return a.localeCompare(b);
23136
23443
  });
23137
23444
  for (const entry of entries) {
23138
- const fullPath = path44.join(dir, entry);
23139
- const relPath = path44.relative(scanDir, fullPath).replace(/\\/g, "/");
23445
+ const fullPath = path45.join(dir, entry);
23446
+ const relPath = path45.relative(scanDir, fullPath).replace(/\\/g, "/");
23140
23447
  if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
23141
23448
  stats.skippedDirs++;
23142
23449
  continue;
@@ -23171,7 +23478,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
23171
23478
  const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
23172
23479
  files.push(...subFiles);
23173
23480
  } else if (lstat2.isFile()) {
23174
- const ext = path44.extname(fullPath).toLowerCase();
23481
+ const ext = path45.extname(fullPath).toLowerCase();
23175
23482
  if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
23176
23483
  files.push(fullPath);
23177
23484
  } else {
@@ -23237,7 +23544,7 @@ var secretscan = createSwarmTool({
23237
23544
  }
23238
23545
  }
23239
23546
  try {
23240
- const _scanDirRaw = path44.resolve(directory);
23547
+ const _scanDirRaw = path45.resolve(directory);
23241
23548
  const scanDir = (() => {
23242
23549
  try {
23243
23550
  return fs19.realpathSync(_scanDirRaw);
@@ -23400,11 +23707,11 @@ var _internals38 = {
23400
23707
 
23401
23708
  // src/tools/test-runner.ts
23402
23709
  import * as fs23 from "fs";
23403
- import * as path48 from "path";
23710
+ import * as path49 from "path";
23404
23711
 
23405
23712
  // src/test-impact/analyzer.ts
23406
23713
  import fs20 from "fs";
23407
- import path45 from "path";
23714
+ import path46 from "path";
23408
23715
  var IMPORT_REGEX_ES = /import\s+[\s\S]*?\s+from\s+['"]([^'"]+)['"]/g;
23409
23716
  var IMPORT_REGEX_REQUIRE = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
23410
23717
  var IMPORT_REGEX_REEXPORT = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
@@ -23445,8 +23752,8 @@ function resolveRelativeImport(fromDir, importPath) {
23445
23752
  if (!importPath.startsWith(".")) {
23446
23753
  return null;
23447
23754
  }
23448
- const resolved = path45.resolve(fromDir, importPath);
23449
- if (path45.extname(resolved)) {
23755
+ const resolved = path46.resolve(fromDir, importPath);
23756
+ if (path46.extname(resolved)) {
23450
23757
  if (fs20.existsSync(resolved) && fs20.statSync(resolved).isFile()) {
23451
23758
  return normalizePath2(resolved);
23452
23759
  }
@@ -23466,20 +23773,20 @@ function resolvePythonImport(fromDir, module) {
23466
23773
  const leadingDots = module.match(/^\.+/)?.[0].length ?? 0;
23467
23774
  let baseDir = fromDir;
23468
23775
  for (let i = 1;i < leadingDots; i++) {
23469
- baseDir = path45.dirname(baseDir);
23776
+ baseDir = path46.dirname(baseDir);
23470
23777
  }
23471
23778
  const rest = module.slice(leadingDots);
23472
23779
  if (rest.length === 0) {
23473
- const initPath = path45.join(baseDir, "__init__.py");
23780
+ const initPath = path46.join(baseDir, "__init__.py");
23474
23781
  if (fs20.existsSync(initPath) && fs20.statSync(initPath).isFile()) {
23475
23782
  return normalizePath2(initPath);
23476
23783
  }
23477
23784
  return null;
23478
23785
  }
23479
- const subpath = rest.replace(/\./g, path45.sep);
23786
+ const subpath = rest.replace(/\./g, path46.sep);
23480
23787
  const candidates = [
23481
- `${path45.join(baseDir, subpath)}.py`,
23482
- path45.join(baseDir, subpath, "__init__.py")
23788
+ `${path46.join(baseDir, subpath)}.py`,
23789
+ path46.join(baseDir, subpath, "__init__.py")
23483
23790
  ];
23484
23791
  for (const c of candidates) {
23485
23792
  if (fs20.existsSync(c) && fs20.statSync(c).isFile())
@@ -23489,7 +23796,7 @@ function resolvePythonImport(fromDir, module) {
23489
23796
  }
23490
23797
  var goModuleCache = new Map;
23491
23798
  function findGoModule(fromDir) {
23492
- const resolved = path45.resolve(fromDir);
23799
+ const resolved = path46.resolve(fromDir);
23493
23800
  let cur = resolved;
23494
23801
  const walked = [];
23495
23802
  for (let i = 0;i < 16; i++) {
@@ -23501,7 +23808,7 @@ function findGoModule(fromDir) {
23501
23808
  }
23502
23809
  walked.push(cur);
23503
23810
  try {
23504
- const goMod = path45.join(cur, "go.mod");
23811
+ const goMod = path46.join(cur, "go.mod");
23505
23812
  const content = fs20.readFileSync(goMod, "utf-8");
23506
23813
  const moduleMatch = content.match(/^\s*module\s+"?([^"\s/]+(?:\/[^"\s]+)*)"?/m);
23507
23814
  if (moduleMatch) {
@@ -23512,10 +23819,10 @@ function findGoModule(fromDir) {
23512
23819
  }
23513
23820
  } catch {}
23514
23821
  try {
23515
- fs20.accessSync(path45.join(cur, ".git"));
23822
+ fs20.accessSync(path46.join(cur, ".git"));
23516
23823
  break;
23517
23824
  } catch {}
23518
- const parent = path45.dirname(cur);
23825
+ const parent = path46.dirname(cur);
23519
23826
  if (parent === cur)
23520
23827
  break;
23521
23828
  cur = parent;
@@ -23527,12 +23834,12 @@ function findGoModule(fromDir) {
23527
23834
  function resolveGoImport(fromDir, importPath) {
23528
23835
  let dir = null;
23529
23836
  if (importPath.startsWith(".")) {
23530
- dir = path45.resolve(fromDir, importPath);
23837
+ dir = path46.resolve(fromDir, importPath);
23531
23838
  } else {
23532
23839
  const mod = findGoModule(fromDir);
23533
23840
  if (mod && (importPath === mod.modulePath || importPath.startsWith(`${mod.modulePath}/`))) {
23534
23841
  const subpath = importPath.slice(mod.modulePath.length);
23535
- dir = path45.join(mod.moduleRoot, subpath);
23842
+ dir = path46.join(mod.moduleRoot, subpath);
23536
23843
  }
23537
23844
  }
23538
23845
  if (dir === null)
@@ -23540,7 +23847,7 @@ function resolveGoImport(fromDir, importPath) {
23540
23847
  if (!fs20.existsSync(dir) || !fs20.statSync(dir).isDirectory())
23541
23848
  return [];
23542
23849
  try {
23543
- return fs20.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath2(path45.join(dir, f)));
23850
+ return fs20.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath2(path46.join(dir, f)));
23544
23851
  } catch {
23545
23852
  return [];
23546
23853
  }
@@ -23579,15 +23886,15 @@ function findTestFilesSync(cwd) {
23579
23886
  for (const entry of entries) {
23580
23887
  if (entry.isDirectory()) {
23581
23888
  if (!skipDirs.has(entry.name)) {
23582
- walk(path45.join(dir, entry.name), visitedInodes);
23889
+ walk(path46.join(dir, entry.name), visitedInodes);
23583
23890
  }
23584
23891
  } else if (entry.isFile()) {
23585
23892
  const name = entry.name;
23586
23893
  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");
23894
+ const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${path46.sep}tests${path46.sep}`) && name.endsWith(".py");
23588
23895
  const isGoTest = /.+_test\.go$/.test(name);
23589
23896
  if (isTsTest || isPyTest || isGoTest) {
23590
- testFiles.push(normalizePath2(path45.join(dir, entry.name)));
23897
+ testFiles.push(normalizePath2(path46.join(dir, entry.name)));
23591
23898
  }
23592
23899
  }
23593
23900
  }
@@ -23612,8 +23919,8 @@ function extractImports(content) {
23612
23919
  ];
23613
23920
  }
23614
23921
  function addImpactEdgesForTestFile(testFile, content, impactMap) {
23615
- const ext = path45.extname(testFile).toLowerCase();
23616
- const testDir = path45.dirname(testFile);
23922
+ const ext = path46.extname(testFile).toLowerCase();
23923
+ const testDir = path46.dirname(testFile);
23617
23924
  function addEdge(source) {
23618
23925
  if (!impactMap[source])
23619
23926
  impactMap[source] = [];
@@ -23686,7 +23993,7 @@ async function buildImpactMap(cwd) {
23686
23993
  return impactMap;
23687
23994
  }
23688
23995
  async function loadImpactMap(cwd, options) {
23689
- const cachePath = path45.join(cwd, ".swarm", "cache", "impact-map.json");
23996
+ const cachePath = path46.join(cwd, ".swarm", "cache", "impact-map.json");
23690
23997
  if (fs20.existsSync(cachePath)) {
23691
23998
  try {
23692
23999
  const content = fs20.readFileSync(cachePath, "utf-8");
@@ -23719,12 +24026,12 @@ async function loadImpactMap(cwd, options) {
23719
24026
  return _internals39.buildImpactMap(cwd);
23720
24027
  }
23721
24028
  async function saveImpactMap(cwd, impactMap) {
23722
- if (!path45.isAbsolute(cwd)) {
24029
+ if (!path46.isAbsolute(cwd)) {
23723
24030
  throw new Error(`saveImpactMap requires an absolute project root path, got: "${cwd}"`);
23724
24031
  }
23725
24032
  _internals39.validateProjectRoot(cwd);
23726
- const cacheDir2 = path45.join(cwd, ".swarm", "cache");
23727
- const cachePath = path45.join(cacheDir2, "impact-map.json");
24033
+ const cacheDir2 = path46.join(cwd, ".swarm", "cache");
24034
+ const cachePath = path46.join(cacheDir2, "impact-map.json");
23728
24035
  if (!fs20.existsSync(cacheDir2)) {
23729
24036
  fs20.mkdirSync(cacheDir2, { recursive: true });
23730
24037
  }
@@ -23756,7 +24063,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
23756
24063
  budgetExceeded = true;
23757
24064
  break;
23758
24065
  }
23759
- const normalizedChanged = normalizePath2(path45.resolve(changedFile));
24066
+ const normalizedChanged = normalizePath2(path46.resolve(changedFile));
23760
24067
  const tests = impactMap[normalizedChanged];
23761
24068
  if (tests && tests.length > 0) {
23762
24069
  for (const test of tests) {
@@ -23770,13 +24077,13 @@ async function analyzeImpact(changedFiles, cwd, budget) {
23770
24077
  if (budgetExceeded)
23771
24078
  break;
23772
24079
  } else {
23773
- const changedDir = normalizePath2(path45.dirname(normalizedChanged));
23774
- const changedInputDir = normalizePath2(path45.dirname(changedFile));
24080
+ const changedDir = normalizePath2(path46.dirname(normalizedChanged));
24081
+ const changedInputDir = normalizePath2(path46.dirname(changedFile));
23775
24082
  const suffixMatches = Object.entries(impactMap).filter(([sourcePath]) => {
23776
24083
  return sourcePath.endsWith(changedFile) || changedFile.endsWith(sourcePath) || sourcePath.endsWith(normalizedChanged) || normalizedChanged.endsWith(sourcePath);
23777
24084
  }).sort(([sourceA], [sourceB]) => {
23778
- const sourceDirA = normalizePath2(path45.dirname(sourceA));
23779
- const sourceDirB = normalizePath2(path45.dirname(sourceB));
24085
+ const sourceDirA = normalizePath2(path46.dirname(sourceA));
24086
+ const sourceDirB = normalizePath2(path46.dirname(sourceB));
23780
24087
  const exactA = sourceDirA === changedDir || changedInputDir !== "." && (sourceDirA === changedInputDir || sourceDirA.endsWith(`/${changedInputDir}`));
23781
24088
  const exactB = sourceDirB === changedDir || changedInputDir !== "." && (sourceDirB === changedInputDir || sourceDirB.endsWith(`/${changedInputDir}`));
23782
24089
  if (exactA !== exactB)
@@ -24103,7 +24410,7 @@ function detectFlakyTests(allHistory) {
24103
24410
 
24104
24411
  // src/test-impact/history-store.ts
24105
24412
  import fs21 from "fs";
24106
- import path46 from "path";
24413
+ import path47 from "path";
24107
24414
  var MAX_HISTORY_PER_TEST = 20;
24108
24415
  var MAX_ERROR_LENGTH = 500;
24109
24416
  var MAX_STACK_LENGTH = 200;
@@ -24115,10 +24422,10 @@ function getHistoryPath(workingDir) {
24115
24422
  if (!workingDir) {
24116
24423
  throw new Error("getHistoryPath requires a working directory \u2014 project root must be provided by the caller");
24117
24424
  }
24118
- if (!path46.isAbsolute(workingDir)) {
24425
+ if (!path47.isAbsolute(workingDir)) {
24119
24426
  throw new Error(`getHistoryPath requires an absolute project root path, got: "${workingDir}"`);
24120
24427
  }
24121
- return path46.join(workingDir, ".swarm", "cache", "test-history.jsonl");
24428
+ return path47.join(workingDir, ".swarm", "cache", "test-history.jsonl");
24122
24429
  }
24123
24430
  function sanitizeErrorMessage(errorMessage) {
24124
24431
  if (errorMessage === undefined) {
@@ -24210,7 +24517,7 @@ function batchAppendTestRuns(records, workingDir) {
24210
24517
  }
24211
24518
  }
24212
24519
  const historyPath = getHistoryPath(workingDir);
24213
- const historyDir = path46.dirname(historyPath);
24520
+ const historyDir = path47.dirname(historyPath);
24214
24521
  _internals40.validateProjectRoot(workingDir);
24215
24522
  if (!fs21.existsSync(historyDir)) {
24216
24523
  fs21.mkdirSync(historyDir, { recursive: true });
@@ -24340,7 +24647,7 @@ var _internals40 = {
24340
24647
 
24341
24648
  // src/tools/resolve-working-directory.ts
24342
24649
  import * as fs22 from "fs";
24343
- import * as path47 from "path";
24650
+ import * as path48 from "path";
24344
24651
  function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
24345
24652
  if (workingDirectory == null || workingDirectory === "") {
24346
24653
  if (typeof fallbackDirectory !== "string" || fallbackDirectory === "") {
@@ -24372,15 +24679,15 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
24372
24679
  };
24373
24680
  }
24374
24681
  }
24375
- const rawPathParts = workingDirectory.split(path47.sep);
24682
+ const rawPathParts = workingDirectory.split(path48.sep);
24376
24683
  if (rawPathParts.includes("..")) {
24377
24684
  return {
24378
24685
  success: false,
24379
24686
  message: "Invalid working_directory: path traversal sequences (..) are not allowed"
24380
24687
  };
24381
24688
  }
24382
- const normalizedDir = path47.normalize(workingDirectory);
24383
- const resolvedDir = path47.resolve(normalizedDir);
24689
+ const normalizedDir = path48.normalize(workingDirectory);
24690
+ const resolvedDir = path48.resolve(normalizedDir);
24384
24691
  let statResult;
24385
24692
  try {
24386
24693
  statResult = fs22.statSync(resolvedDir);
@@ -24399,7 +24706,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
24399
24706
  if (typeof fallbackDirectory !== "string" || fallbackDirectory === "") {
24400
24707
  return { success: true, directory: resolvedDir };
24401
24708
  }
24402
- const resolvedFallback = path47.resolve(fallbackDirectory);
24709
+ const resolvedFallback = path48.resolve(fallbackDirectory);
24403
24710
  let fallbackExists = false;
24404
24711
  try {
24405
24712
  fs22.statSync(resolvedFallback);
@@ -24408,7 +24715,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
24408
24715
  fallbackExists = false;
24409
24716
  }
24410
24717
  if (fallbackExists) {
24411
- const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path47.sep);
24718
+ const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path48.sep);
24412
24719
  if (isSubdirectory) {
24413
24720
  return {
24414
24721
  success: false,
@@ -24431,7 +24738,7 @@ async function estimateFanOut(sourceFiles, cwd) {
24431
24738
  const impactMap = await loadImpactMap(cwd, { skipRebuild: true });
24432
24739
  const uniqueTestFiles = new Set;
24433
24740
  for (const sourceFile of sourceFiles) {
24434
- const resolvedPath = path48.resolve(cwd, sourceFile);
24741
+ const resolvedPath = path49.resolve(cwd, sourceFile);
24435
24742
  const normalizedPath = resolvedPath.replace(/\\/g, "/");
24436
24743
  const testFiles = impactMap[normalizedPath];
24437
24744
  if (testFiles) {
@@ -24516,14 +24823,14 @@ function hasDevDependency(devDeps, ...patterns) {
24516
24823
  return hasPackageJsonDependency(devDeps, ...patterns);
24517
24824
  }
24518
24825
  function detectGoTest(cwd) {
24519
- return fs23.existsSync(path48.join(cwd, "go.mod")) && isCommandAvailable("go");
24826
+ return fs23.existsSync(path49.join(cwd, "go.mod")) && isCommandAvailable("go");
24520
24827
  }
24521
24828
  function detectJavaMaven(cwd) {
24522
- return fs23.existsSync(path48.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
24829
+ return fs23.existsSync(path49.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
24523
24830
  }
24524
24831
  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"));
24832
+ const hasBuildFile = fs23.existsSync(path49.join(cwd, "build.gradle")) || fs23.existsSync(path49.join(cwd, "build.gradle.kts"));
24833
+ const hasGradlew = fs23.existsSync(path49.join(cwd, "gradlew")) || fs23.existsSync(path49.join(cwd, "gradlew.bat"));
24527
24834
  return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
24528
24835
  }
24529
24836
  function detectDotnetTest(cwd) {
@@ -24536,25 +24843,25 @@ function detectDotnetTest(cwd) {
24536
24843
  }
24537
24844
  }
24538
24845
  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"));
24846
+ const hasSource = fs23.existsSync(path49.join(cwd, "CMakeLists.txt"));
24847
+ const hasBuildCache = fs23.existsSync(path49.join(cwd, "CMakeCache.txt")) || fs23.existsSync(path49.join(cwd, "build", "CMakeCache.txt"));
24541
24848
  return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
24542
24849
  }
24543
24850
  function detectSwiftTest(cwd) {
24544
- return fs23.existsSync(path48.join(cwd, "Package.swift")) && isCommandAvailable("swift");
24851
+ return fs23.existsSync(path49.join(cwd, "Package.swift")) && isCommandAvailable("swift");
24545
24852
  }
24546
24853
  function detectDartTest(cwd) {
24547
- return fs23.existsSync(path48.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
24854
+ return fs23.existsSync(path49.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
24548
24855
  }
24549
24856
  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"));
24857
+ const hasRSpecFile = fs23.existsSync(path49.join(cwd, ".rspec"));
24858
+ const hasGemfile = fs23.existsSync(path49.join(cwd, "Gemfile"));
24859
+ const hasSpecDir = fs23.existsSync(path49.join(cwd, "spec"));
24553
24860
  const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
24554
24861
  return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
24555
24862
  }
24556
24863
  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");
24864
+ return fs23.existsSync(path49.join(cwd, "test")) && (fs23.existsSync(path49.join(cwd, "Gemfile")) || fs23.existsSync(path49.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
24558
24865
  }
24559
24866
  var DISPATCH_FRAMEWORK_MAP = {
24560
24867
  bun: "bun",
@@ -24639,7 +24946,7 @@ async function parseTestOutputViaDispatch(framework, output, baseDir) {
24639
24946
  async function detectTestFramework(cwd) {
24640
24947
  const baseDir = cwd;
24641
24948
  try {
24642
- const packageJsonPath = path48.join(baseDir, "package.json");
24949
+ const packageJsonPath = path49.join(baseDir, "package.json");
24643
24950
  if (fs23.existsSync(packageJsonPath)) {
24644
24951
  const content = fs23.readFileSync(packageJsonPath, "utf-8");
24645
24952
  const pkg = JSON.parse(content);
@@ -24660,16 +24967,16 @@ async function detectTestFramework(cwd) {
24660
24967
  return "jest";
24661
24968
  if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
24662
24969
  return "mocha";
24663
- if (fs23.existsSync(path48.join(baseDir, "bun.lockb")) || fs23.existsSync(path48.join(baseDir, "bun.lock"))) {
24970
+ if (fs23.existsSync(path49.join(baseDir, "bun.lockb")) || fs23.existsSync(path49.join(baseDir, "bun.lock"))) {
24664
24971
  if (scripts.test?.includes("bun"))
24665
24972
  return "bun";
24666
24973
  }
24667
24974
  }
24668
24975
  } catch {}
24669
24976
  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");
24977
+ const pyprojectTomlPath = path49.join(baseDir, "pyproject.toml");
24978
+ const setupCfgPath = path49.join(baseDir, "setup.cfg");
24979
+ const requirementsTxtPath = path49.join(baseDir, "requirements.txt");
24673
24980
  if (fs23.existsSync(pyprojectTomlPath)) {
24674
24981
  const content = fs23.readFileSync(pyprojectTomlPath, "utf-8");
24675
24982
  if (content.includes("[tool.pytest"))
@@ -24689,7 +24996,7 @@ async function detectTestFramework(cwd) {
24689
24996
  }
24690
24997
  } catch {}
24691
24998
  try {
24692
- const cargoTomlPath = path48.join(baseDir, "Cargo.toml");
24999
+ const cargoTomlPath = path49.join(baseDir, "Cargo.toml");
24693
25000
  if (fs23.existsSync(cargoTomlPath)) {
24694
25001
  const content = fs23.readFileSync(cargoTomlPath, "utf-8");
24695
25002
  if (content.includes("[dev-dependencies]")) {
@@ -24700,9 +25007,9 @@ async function detectTestFramework(cwd) {
24700
25007
  }
24701
25008
  } catch {}
24702
25009
  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");
25010
+ const pesterConfigPath = path49.join(baseDir, "pester.config.ps1");
25011
+ const pesterConfigJsonPath = path49.join(baseDir, "pester.config.ps1.json");
25012
+ const pesterPs1Path = path49.join(baseDir, "tests.ps1");
24706
25013
  if (fs23.existsSync(pesterConfigPath) || fs23.existsSync(pesterConfigJsonPath) || fs23.existsSync(pesterPs1Path)) {
24707
25014
  return "pester";
24708
25015
  }
@@ -24745,12 +25052,12 @@ function isTestDirectoryPath(normalizedPath) {
24745
25052
  return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
24746
25053
  }
24747
25054
  function resolveWorkspacePath(file, workingDir) {
24748
- return path48.isAbsolute(file) ? path48.resolve(file) : path48.resolve(workingDir, file);
25055
+ return path49.isAbsolute(file) ? path49.resolve(file) : path49.resolve(workingDir, file);
24749
25056
  }
24750
25057
  function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
24751
25058
  if (!preferRelative)
24752
25059
  return absolutePath;
24753
- return path48.relative(workingDir, absolutePath);
25060
+ return path49.relative(workingDir, absolutePath);
24754
25061
  }
24755
25062
  function dedupePush(target, value) {
24756
25063
  if (!target.includes(value)) {
@@ -24787,18 +25094,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
24787
25094
  }
24788
25095
  }
24789
25096
  function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
24790
- const relativeDir = path48.dirname(relativePath);
25097
+ const relativeDir = path49.dirname(relativePath);
24791
25098
  const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
24792
25099
  const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
24793
- const rootDir = path48.join(workingDir, dirName);
24794
- return nestedRelativeDir ? [rootDir, path48.join(rootDir, nestedRelativeDir)] : [rootDir];
25100
+ const rootDir = path49.join(workingDir, dirName);
25101
+ return nestedRelativeDir ? [rootDir, path49.join(rootDir, nestedRelativeDir)] : [rootDir];
24795
25102
  });
24796
25103
  const normalizedRelativePath = relativePath.replace(/\\/g, "/");
24797
25104
  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))));
25105
+ directories.push(path49.join(workingDir, "src/test/java", path49.dirname(normalizedRelativePath.slice("src/main/java/".length))));
24799
25106
  }
24800
25107
  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))));
25108
+ directories.push(path49.join(workingDir, "src/test/kotlin", path49.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
24802
25109
  }
24803
25110
  return [...new Set(directories)];
24804
25111
  }
@@ -24826,23 +25133,23 @@ function isLanguageSpecificTestFile(basename9) {
24826
25133
  }
24827
25134
  function isConventionTestFilePath(filePath) {
24828
25135
  const normalizedPath = filePath.replace(/\\/g, "/");
24829
- const basename9 = path48.basename(filePath);
25136
+ const basename9 = path49.basename(filePath);
24830
25137
  return hasCompoundTestExtension(basename9) || basename9.includes(".spec.") || basename9.includes(".test.") || isLanguageSpecificTestFile(basename9) || isTestDirectoryPath(normalizedPath);
24831
25138
  }
24832
25139
  function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
24833
25140
  const testFiles = [];
24834
25141
  for (const file of sourceFiles) {
24835
25142
  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);
25143
+ const relativeFile = path49.relative(workingDir, absoluteFile);
25144
+ const basename9 = path49.basename(absoluteFile);
25145
+ const dirname23 = path49.dirname(absoluteFile);
25146
+ const preferRelativeOutput = !path49.isAbsolute(file);
24840
25147
  if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file)) {
24841
25148
  dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
24842
25149
  continue;
24843
25150
  }
24844
25151
  const nameWithoutExt = basename9.replace(/\.[^.]+$/, "");
24845
- const ext = path48.extname(basename9);
25152
+ const ext = path49.extname(basename9);
24846
25153
  const genericTestNames = [
24847
25154
  `${nameWithoutExt}.spec${ext}`,
24848
25155
  `${nameWithoutExt}.test${ext}`
@@ -24851,7 +25158,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
24851
25158
  const colocatedCandidates = [
24852
25159
  ...genericTestNames,
24853
25160
  ...languageSpecificTestNames
24854
- ].map((candidateName) => path48.join(dirname23, candidateName));
25161
+ ].map((candidateName) => path49.join(dirname23, candidateName));
24855
25162
  const testDirectoryNames = [
24856
25163
  basename9,
24857
25164
  ...genericTestNames,
@@ -24860,8 +25167,8 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
24860
25167
  const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
24861
25168
  const possibleTestFiles = [
24862
25169
  ...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)))
25170
+ ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path49.join(dirname23, dirName, candidateName))),
25171
+ ...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path49.join(candidateDir, candidateName)))
24865
25172
  ];
24866
25173
  for (const testFile of possibleTestFiles) {
24867
25174
  if (fs23.existsSync(testFile)) {
@@ -24882,7 +25189,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
24882
25189
  try {
24883
25190
  const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
24884
25191
  const content = fs23.readFileSync(absoluteTestFile, "utf-8");
24885
- const testDir = path48.dirname(absoluteTestFile);
25192
+ const testDir = path49.dirname(absoluteTestFile);
24886
25193
  const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
24887
25194
  let match;
24888
25195
  match = importRegex.exec(content);
@@ -24890,8 +25197,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
24890
25197
  const importPath = match[1];
24891
25198
  let resolvedImport;
24892
25199
  if (importPath.startsWith(".")) {
24893
- resolvedImport = path48.resolve(testDir, importPath);
24894
- const existingExt = path48.extname(resolvedImport);
25200
+ resolvedImport = path49.resolve(testDir, importPath);
25201
+ const existingExt = path49.extname(resolvedImport);
24895
25202
  if (!existingExt) {
24896
25203
  for (const extToTry of [
24897
25204
  ".ts",
@@ -24911,12 +25218,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
24911
25218
  } else {
24912
25219
  continue;
24913
25220
  }
24914
- const importBasename = path48.basename(resolvedImport, path48.extname(resolvedImport));
24915
- const importDir = path48.dirname(resolvedImport);
25221
+ const importBasename = path49.basename(resolvedImport, path49.extname(resolvedImport));
25222
+ const importDir = path49.dirname(resolvedImport);
24916
25223
  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");
25224
+ const sourceDir = path49.dirname(sourceFile);
25225
+ const sourceBasename = path49.basename(sourceFile, path49.extname(sourceFile));
25226
+ 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
25227
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
24921
25228
  dedupePush(testFiles, testFile);
24922
25229
  break;
@@ -24929,8 +25236,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
24929
25236
  while (match !== null) {
24930
25237
  const importPath = match[1];
24931
25238
  if (importPath.startsWith(".")) {
24932
- let resolvedImport = path48.resolve(testDir, importPath);
24933
- const existingExt = path48.extname(resolvedImport);
25239
+ let resolvedImport = path49.resolve(testDir, importPath);
25240
+ const existingExt = path49.extname(resolvedImport);
24934
25241
  if (!existingExt) {
24935
25242
  for (const extToTry of [
24936
25243
  ".ts",
@@ -24947,12 +25254,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
24947
25254
  }
24948
25255
  }
24949
25256
  }
24950
- const importDir = path48.dirname(resolvedImport);
24951
- const importBasename = path48.basename(resolvedImport, path48.extname(resolvedImport));
25257
+ const importDir = path49.dirname(resolvedImport);
25258
+ const importBasename = path49.basename(resolvedImport, path49.extname(resolvedImport));
24952
25259
  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");
25260
+ const sourceDir = path49.dirname(sourceFile);
25261
+ const sourceBasename = path49.basename(sourceFile, path49.extname(sourceFile));
25262
+ 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
25263
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
24957
25264
  dedupePush(testFiles, testFile);
24958
25265
  break;
@@ -25072,8 +25379,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
25072
25379
  return ["mvn", "test"];
25073
25380
  case "gradle": {
25074
25381
  const isWindows = process.platform === "win32";
25075
- const hasGradlewBat = fs23.existsSync(path48.join(baseDir, "gradlew.bat"));
25076
- const hasGradlew = fs23.existsSync(path48.join(baseDir, "gradlew"));
25382
+ const hasGradlewBat = fs23.existsSync(path49.join(baseDir, "gradlew.bat"));
25383
+ const hasGradlew = fs23.existsSync(path49.join(baseDir, "gradlew"));
25077
25384
  if (hasGradlewBat && isWindows)
25078
25385
  return ["gradlew.bat", "test"];
25079
25386
  if (hasGradlew)
@@ -25090,7 +25397,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
25090
25397
  "cmake-build-release",
25091
25398
  "out"
25092
25399
  ];
25093
- const actualBuildDir = buildDirCandidates.find((d) => fs23.existsSync(path48.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
25400
+ const actualBuildDir = buildDirCandidates.find((d) => fs23.existsSync(path49.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
25094
25401
  return ["ctest", "--test-dir", actualBuildDir];
25095
25402
  }
25096
25403
  case "swift-test":
@@ -25524,11 +25831,11 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd, bail
25524
25831
  };
25525
25832
  }
25526
25833
  const startTime = Date.now();
25527
- const vitestJsonOutputPath = framework === "vitest" ? path48.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
25834
+ const vitestJsonOutputPath = framework === "vitest" ? path49.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
25528
25835
  try {
25529
25836
  if (vitestJsonOutputPath) {
25530
25837
  try {
25531
- fs23.mkdirSync(path48.dirname(vitestJsonOutputPath), { recursive: true });
25838
+ fs23.mkdirSync(path49.dirname(vitestJsonOutputPath), { recursive: true });
25532
25839
  if (fs23.existsSync(vitestJsonOutputPath)) {
25533
25840
  fs23.unlinkSync(vitestJsonOutputPath);
25534
25841
  }
@@ -25539,9 +25846,9 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd, bail
25539
25846
  stderr: "pipe",
25540
25847
  cwd
25541
25848
  });
25542
- const timeoutPromise = new Promise((resolve15) => setTimeout(() => {
25849
+ const timeoutPromise = new Promise((resolve16) => setTimeout(() => {
25543
25850
  proc.kill();
25544
- resolve15(-1);
25851
+ resolve16(-1);
25545
25852
  }, timeout_ms));
25546
25853
  const [exitCode, stdoutResult, stderrResult] = await Promise.all([
25547
25854
  Promise.race([proc.exited, timeoutPromise]),
@@ -25696,10 +26003,10 @@ var SKIP_DIRECTORIES = new Set([
25696
26003
  ]);
25697
26004
  function normalizeHistoryTestFile(testFile, workingDir) {
25698
26005
  const normalized = testFile.replace(/\\/g, "/");
25699
- if (!path48.isAbsolute(testFile))
26006
+ if (!path49.isAbsolute(testFile))
25700
26007
  return normalized;
25701
- const relative8 = path48.relative(workingDir, testFile);
25702
- if (relative8.startsWith("..") || path48.isAbsolute(relative8)) {
26008
+ const relative8 = path49.relative(workingDir, testFile);
26009
+ if (relative8.startsWith("..") || path49.isAbsolute(relative8)) {
25703
26010
  return normalized;
25704
26011
  }
25705
26012
  return relative8.replace(/\\/g, "/");
@@ -25938,7 +26245,7 @@ var test_runner = createSwarmTool({
25938
26245
  const sourceFiles = args.files.filter((file) => {
25939
26246
  if (directTestFiles.includes(file))
25940
26247
  return false;
25941
- const ext = path48.extname(file).toLowerCase();
26248
+ const ext = path49.extname(file).toLowerCase();
25942
26249
  return SOURCE_EXTENSIONS.has(ext);
25943
26250
  });
25944
26251
  const invalidFiles = args.files.filter((file) => !directTestFiles.includes(file) && !sourceFiles.includes(file));
@@ -25984,7 +26291,7 @@ var test_runner = createSwarmTool({
25984
26291
  if (isConventionTestFilePath(f)) {
25985
26292
  return false;
25986
26293
  }
25987
- const ext = path48.extname(f).toLowerCase();
26294
+ const ext = path49.extname(f).toLowerCase();
25988
26295
  return SOURCE_EXTENSIONS.has(ext);
25989
26296
  });
25990
26297
  if (sourceFiles.length === 0) {
@@ -26034,7 +26341,7 @@ var test_runner = createSwarmTool({
26034
26341
  if (isConventionTestFilePath(f)) {
26035
26342
  return false;
26036
26343
  }
26037
- const ext = path48.extname(f).toLowerCase();
26344
+ const ext = path49.extname(f).toLowerCase();
26038
26345
  return SOURCE_EXTENSIONS.has(ext);
26039
26346
  });
26040
26347
  if (sourceFiles.length === 0) {
@@ -26086,8 +26393,8 @@ var test_runner = createSwarmTool({
26086
26393
  }
26087
26394
  if (impactResult.impactedTests.length > 0) {
26088
26395
  testFiles = impactResult.impactedTests.map((absPath) => {
26089
- const relativePath = path48.relative(workingDir, absPath);
26090
- return path48.isAbsolute(relativePath) ? absPath : relativePath;
26396
+ const relativePath = path49.relative(workingDir, absPath);
26397
+ return path49.isAbsolute(relativePath) ? absPath : relativePath;
26091
26398
  });
26092
26399
  } else {
26093
26400
  graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
@@ -26182,8 +26489,8 @@ function validateDirectoryPath(dir) {
26182
26489
  if (dir.includes("..")) {
26183
26490
  throw new Error("Directory path must not contain path traversal sequences");
26184
26491
  }
26185
- const normalized = path49.normalize(dir);
26186
- const absolutePath = path49.isAbsolute(normalized) ? normalized : path49.resolve(normalized);
26492
+ const normalized = path50.normalize(dir);
26493
+ const absolutePath = path50.isAbsolute(normalized) ? normalized : path50.resolve(normalized);
26187
26494
  return absolutePath;
26188
26495
  }
26189
26496
  function validateTimeout(timeoutMs, defaultValue) {
@@ -26206,7 +26513,7 @@ function validateTimeout(timeoutMs, defaultValue) {
26206
26513
  }
26207
26514
  function getPackageVersion(dir) {
26208
26515
  try {
26209
- const packagePath = path49.join(dir, "package.json");
26516
+ const packagePath = path50.join(dir, "package.json");
26210
26517
  if (fs24.existsSync(packagePath)) {
26211
26518
  const content = fs24.readFileSync(packagePath, "utf-8");
26212
26519
  const pkg = JSON.parse(content);
@@ -26217,7 +26524,7 @@ function getPackageVersion(dir) {
26217
26524
  }
26218
26525
  function getChangelogVersion(dir) {
26219
26526
  try {
26220
- const changelogPath = path49.join(dir, "CHANGELOG.md");
26527
+ const changelogPath = path50.join(dir, "CHANGELOG.md");
26221
26528
  if (fs24.existsSync(changelogPath)) {
26222
26529
  const content = fs24.readFileSync(changelogPath, "utf-8");
26223
26530
  const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
@@ -26231,7 +26538,7 @@ function getChangelogVersion(dir) {
26231
26538
  function getVersionFileVersion(dir) {
26232
26539
  const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
26233
26540
  for (const file of possibleFiles) {
26234
- const filePath = path49.join(dir, file);
26541
+ const filePath = path50.join(dir, file);
26235
26542
  if (fs24.existsSync(filePath)) {
26236
26543
  try {
26237
26544
  const content = fs24.readFileSync(filePath, "utf-8").trim();
@@ -26969,7 +27276,7 @@ async function handleQaGatesCommand(directory, args, sessionID) {
26969
27276
 
26970
27277
  // src/commands/reset.ts
26971
27278
  import * as fs25 from "fs";
26972
- import * as path50 from "path";
27279
+ import * as path51 from "path";
26973
27280
 
26974
27281
  // src/background/circuit-breaker.ts
26975
27282
  class CircuitBreaker {
@@ -27021,13 +27328,13 @@ class CircuitBreaker {
27021
27328
  if (this.config.callTimeoutMs <= 0) {
27022
27329
  return fn();
27023
27330
  }
27024
- return new Promise((resolve16, reject) => {
27331
+ return new Promise((resolve17, reject) => {
27025
27332
  const timeout = setTimeout(() => {
27026
27333
  reject(new Error(`Call timeout after ${this.config.callTimeoutMs}ms`));
27027
27334
  }, this.config.callTimeoutMs);
27028
27335
  fn().then((result) => {
27029
27336
  clearTimeout(timeout);
27030
- resolve16(result);
27337
+ resolve17(result);
27031
27338
  }).catch((error2) => {
27032
27339
  clearTimeout(timeout);
27033
27340
  reject(error2);
@@ -27311,7 +27618,7 @@ class AutomationQueue {
27311
27618
 
27312
27619
  // src/background/worker.ts
27313
27620
  function sleep(ms) {
27314
- return new Promise((resolve16) => setTimeout(resolve16, ms));
27621
+ return new Promise((resolve17) => setTimeout(resolve17, ms));
27315
27622
  }
27316
27623
 
27317
27624
  class WorkerManager {
@@ -27686,7 +27993,7 @@ async function handleResetCommand(directory, args) {
27686
27993
  }
27687
27994
  for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
27688
27995
  try {
27689
- const rootPath = path50.join(directory, filename);
27996
+ const rootPath = path51.join(directory, filename);
27690
27997
  if (fs25.existsSync(rootPath)) {
27691
27998
  fs25.unlinkSync(rootPath);
27692
27999
  results.push(`- \u2705 Deleted ${filename} (root)`);
@@ -27724,7 +28031,7 @@ async function handleResetCommand(directory, args) {
27724
28031
 
27725
28032
  // src/commands/reset-session.ts
27726
28033
  import * as fs27 from "fs";
27727
- import * as path52 from "path";
28034
+ import * as path53 from "path";
27728
28035
 
27729
28036
  // src/hooks/trajectory-logger.ts
27730
28037
  var callStartTimes = new Map;
@@ -28131,16 +28438,16 @@ function detectPatterns(trajectory, config, lastProcessedStep = 0) {
28131
28438
  }
28132
28439
  // src/prm/replay.ts
28133
28440
  import { promises as fs26 } from "fs";
28134
- import path51 from "path";
28441
+ import path52 from "path";
28135
28442
  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);
28443
+ const resolvedTarget = path52.resolve(targetPath);
28444
+ const resolvedBase = path52.resolve(basePath);
28445
+ const rel = path52.relative(resolvedBase, resolvedTarget);
28446
+ return !rel.startsWith("..") && !path52.isAbsolute(rel);
28140
28447
  }
28141
28448
  function isWithinReplaysDir(targetPath) {
28142
- const resolved = path51.resolve(targetPath);
28143
- const parts = resolved.split(path51.sep);
28449
+ const resolved = path52.resolve(targetPath);
28450
+ const parts = resolved.split(path52.sep);
28144
28451
  for (let i = 0;i < parts.length - 1; i++) {
28145
28452
  if (parts[i] === ".swarm" && parts[i + 1] === "replays") {
28146
28453
  return true;
@@ -28153,10 +28460,10 @@ function sanitizeFilename(input) {
28153
28460
  }
28154
28461
  async function startReplayRecording(sessionID, directory) {
28155
28462
  try {
28156
- const replayDir = path51.join(directory, ".swarm", "replays");
28463
+ const replayDir = path52.join(directory, ".swarm", "replays");
28157
28464
  const safeSessionID = sanitizeFilename(sessionID);
28158
28465
  const filename = `${safeSessionID}-${Date.now()}.jsonl`;
28159
- const filepath = path51.join(replayDir, filename);
28466
+ const filepath = path52.join(replayDir, filename);
28160
28467
  if (!isPathSafe(filepath, replayDir)) {
28161
28468
  console.warn(`[replay] Invalid path detected - path traversal attempt blocked for session ${sessionID}`);
28162
28469
  return null;
@@ -28234,7 +28541,7 @@ async function handleResetSessionCommand(directory, _args) {
28234
28541
  } catch {
28235
28542
  results.push("\u274C Failed to delete state.json");
28236
28543
  }
28237
- const sessionDir = path52.dirname(validateSwarmPath(directory, "session/state.json"));
28544
+ const sessionDir = path53.dirname(validateSwarmPath(directory, "session/state.json"));
28238
28545
  let sessionFiles = [];
28239
28546
  if (fs27.existsSync(sessionDir)) {
28240
28547
  try {
@@ -28246,7 +28553,7 @@ async function handleResetSessionCommand(directory, _args) {
28246
28553
  for (const file of sessionFiles) {
28247
28554
  if (file === "state.json")
28248
28555
  continue;
28249
- const filePath = path52.join(sessionDir, file);
28556
+ const filePath = path53.join(sessionDir, file);
28250
28557
  try {
28251
28558
  if (!fs27.existsSync(filePath))
28252
28559
  continue;
@@ -28281,7 +28588,7 @@ async function handleResetSessionCommand(directory, _args) {
28281
28588
  }
28282
28589
 
28283
28590
  // src/summaries/manager.ts
28284
- import * as path53 from "path";
28591
+ import * as path54 from "path";
28285
28592
  var SUMMARY_ID_REGEX = /^S\d+$/;
28286
28593
  function sanitizeSummaryId(id) {
28287
28594
  if (!id || id.length === 0) {
@@ -28305,7 +28612,7 @@ function sanitizeSummaryId(id) {
28305
28612
  }
28306
28613
  async function loadFullOutput(directory, id) {
28307
28614
  const sanitizedId = sanitizeSummaryId(id);
28308
- const relativePath = path53.join("summaries", `${sanitizedId}.json`);
28615
+ const relativePath = path54.join("summaries", `${sanitizedId}.json`);
28309
28616
  validateSwarmPath(directory, relativePath);
28310
28617
  const content = await readSwarmFileAsync(directory, relativePath);
28311
28618
  if (content === null) {
@@ -28358,7 +28665,7 @@ ${error2 instanceof Error ? error2.message : String(error2)}`;
28358
28665
 
28359
28666
  // src/commands/rollback.ts
28360
28667
  import * as fs28 from "fs";
28361
- import * as path54 from "path";
28668
+ import * as path55 from "path";
28362
28669
  async function handleRollbackCommand(directory, args) {
28363
28670
  const phaseArg = args[0];
28364
28671
  if (!phaseArg) {
@@ -28424,8 +28731,8 @@ async function handleRollbackCommand(directory, args) {
28424
28731
  if (EXCLUDE_FILES.has(file) || file.startsWith("plan-ledger.archived-")) {
28425
28732
  continue;
28426
28733
  }
28427
- const src = path54.join(checkpointDir, file);
28428
- const dest = path54.join(swarmDir, file);
28734
+ const src = path55.join(checkpointDir, file);
28735
+ const dest = path55.join(swarmDir, file);
28429
28736
  try {
28430
28737
  fs28.cpSync(src, dest, { recursive: true, force: true });
28431
28738
  successes.push(file);
@@ -28444,7 +28751,7 @@ async function handleRollbackCommand(directory, args) {
28444
28751
  ].join(`
28445
28752
  `);
28446
28753
  }
28447
- const existingLedgerPath = path54.join(swarmDir, "plan-ledger.jsonl");
28754
+ const existingLedgerPath = path55.join(swarmDir, "plan-ledger.jsonl");
28448
28755
  let ledgerDeletionFailed = false;
28449
28756
  if (fs28.existsSync(existingLedgerPath)) {
28450
28757
  try {
@@ -28457,7 +28764,7 @@ async function handleRollbackCommand(directory, args) {
28457
28764
  }
28458
28765
  if (!ledgerDeletionFailed) {
28459
28766
  try {
28460
- const planJsonPath = path54.join(swarmDir, "plan.json");
28767
+ const planJsonPath = path55.join(swarmDir, "plan.json");
28461
28768
  if (fs28.existsSync(planJsonPath)) {
28462
28769
  const planRaw = fs28.readFileSync(planJsonPath, "utf-8");
28463
28770
  const plan = PlanSchema.parse(JSON.parse(planRaw));
@@ -28718,10 +29025,10 @@ Ensure this is a git repository with commit history.`;
28718
29025
  `);
28719
29026
  try {
28720
29027
  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)}`);
29028
+ const path56 = await import("path");
29029
+ const reportPath = path56.join(directory, ".swarm", "simulate-report.md");
29030
+ await fs29.mkdir(path56.dirname(reportPath), { recursive: true });
29031
+ const reportTempPath = path56.join(path56.dirname(reportPath), `${path56.basename(reportPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
28725
29032
  try {
28726
29033
  await fs29.writeFile(reportTempPath, report, "utf-8");
28727
29034
  renameSync11(reportTempPath, reportPath);
@@ -28750,18 +29057,18 @@ async function handleSpecifyCommand(_directory, args) {
28750
29057
  // src/services/status-service.ts
28751
29058
  import * as fsSync3 from "fs";
28752
29059
  import { readFile as readFile15 } from "fs/promises";
28753
- import * as path56 from "path";
29060
+ import * as path57 from "path";
28754
29061
 
28755
29062
  // src/turbo/lean/state.ts
28756
29063
  init_logger();
28757
29064
  import * as fs29 from "fs";
28758
- import * as path55 from "path";
29065
+ import * as path56 from "path";
28759
29066
  var STATE_FILE3 = "turbo-state.json";
28760
29067
  function nowISO3() {
28761
29068
  return new Date().toISOString();
28762
29069
  }
28763
29070
  function ensureSwarmDir2(directory) {
28764
- const swarmDir = path55.resolve(directory, ".swarm");
29071
+ const swarmDir = path56.resolve(directory, ".swarm");
28765
29072
  if (!fs29.existsSync(swarmDir)) {
28766
29073
  fs29.mkdirSync(swarmDir, { recursive: true });
28767
29074
  }
@@ -28806,7 +29113,7 @@ function markStateUnreadable2(directory, reason) {
28806
29113
  }
28807
29114
  function readPersisted2(directory) {
28808
29115
  try {
28809
- const filePath = path55.join(directory, ".swarm", STATE_FILE3);
29116
+ const filePath = path56.join(directory, ".swarm", STATE_FILE3);
28810
29117
  if (!fs29.existsSync(filePath)) {
28811
29118
  const seed = emptyPersisted2();
28812
29119
  try {
@@ -28842,7 +29149,7 @@ function writePersisted2(directory, persisted) {
28842
29149
  let payload;
28843
29150
  try {
28844
29151
  ensureSwarmDir2(directory);
28845
- filePath = path55.join(directory, ".swarm", STATE_FILE3);
29152
+ filePath = path56.join(directory, ".swarm", STATE_FILE3);
28846
29153
  tmpPath = `${filePath}.tmp.${Date.now()}`;
28847
29154
  persisted.updatedAt = nowISO3();
28848
29155
  payload = `${JSON.stringify(persisted, null, 2)}
@@ -28960,7 +29267,7 @@ var _internals43 = {
28960
29267
  };
28961
29268
  function readSpecStalenessSnapshot(directory) {
28962
29269
  try {
28963
- const p = path56.join(directory, ".swarm", "spec-staleness.json");
29270
+ const p = path57.join(directory, ".swarm", "spec-staleness.json");
28964
29271
  if (!fsSync3.existsSync(p))
28965
29272
  return { stale: false };
28966
29273
  const raw = fsSync3.readFileSync(p, "utf-8");
@@ -29627,7 +29934,7 @@ function buildDetailedHelp(commandName, entry) {
29627
29934
  async function handleHelpCommand(ctx) {
29628
29935
  const targetCommand = ctx.args.join(" ");
29629
29936
  if (!targetCommand) {
29630
- const { buildHelpText } = await import("./index-dkytd370.js");
29937
+ const { buildHelpText } = await import("./index-tjr1m8wf.js");
29631
29938
  return buildHelpText();
29632
29939
  }
29633
29940
  const tokens = targetCommand.split(/\s+/);
@@ -29636,7 +29943,7 @@ async function handleHelpCommand(ctx) {
29636
29943
  return _internals45.buildDetailedHelp(resolved.key, resolved.entry);
29637
29944
  }
29638
29945
  const similar = _internals45.findSimilarCommands(targetCommand);
29639
- const { buildHelpText: fullHelp } = await import("./index-dkytd370.js");
29946
+ const { buildHelpText: fullHelp } = await import("./index-tjr1m8wf.js");
29640
29947
  if (similar.length > 0) {
29641
29948
  return `Command '/swarm ${targetCommand}' not found.
29642
29949
 
@@ -29769,7 +30076,7 @@ var COMMAND_REGISTRY = {
29769
30076
  },
29770
30077
  "guardrail explain": {
29771
30078
  handler: async (ctx) => {
29772
- const { handleGuardrailExplain } = await import("./guardrail-explain-sw5bjxtk.js");
30079
+ const { handleGuardrailExplain } = await import("./guardrail-explain-qd243wrm.js");
29773
30080
  return handleGuardrailExplain(ctx.directory, ctx.args);
29774
30081
  },
29775
30082
  description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
@@ -30142,7 +30449,7 @@ Subcommands:
30142
30449
  deprecated: true
30143
30450
  },
30144
30451
  "pr status": {
30145
- handler: (ctx) => handlePrMonitorStatusCommand(ctx.directory, ctx.args, ctx.sessionID),
30452
+ handler: (ctx) => handlePrMonitorStatusCommand(ctx.directory, ctx.args, ctx.sessionID, ctx.source),
30146
30453
  description: "Show PR monitor subscription status for the current session",
30147
30454
  args: "",
30148
30455
  details: "Displays all active PR subscriptions for the current session. Shows PR URL, last checked time, watching status, and error count per subscription. Also shows total active subscriptions across all sessions.",
@@ -30151,7 +30458,7 @@ Subcommands:
30151
30458
  toolNoArgs: true
30152
30459
  },
30153
30460
  "pr-status": {
30154
- handler: (ctx) => handlePrMonitorStatusCommand(ctx.directory, ctx.args, ctx.sessionID),
30461
+ handler: (ctx) => handlePrMonitorStatusCommand(ctx.directory, ctx.args, ctx.sessionID, ctx.source),
30155
30462
  description: "Show PR monitor subscription status for the current session",
30156
30463
  aliasOf: "pr status",
30157
30464
  deprecated: true
@@ -30509,24 +30816,24 @@ function validateAliases() {
30509
30816
  }
30510
30817
  aliasTargets.get(target).push(name);
30511
30818
  const visited = new Set;
30512
- const path57 = [];
30819
+ const path58 = [];
30513
30820
  let current = target;
30514
30821
  while (current) {
30515
30822
  const currentEntry = COMMAND_REGISTRY[current];
30516
30823
  if (!currentEntry)
30517
30824
  break;
30518
30825
  if (visited.has(current)) {
30519
- const cycleStart = path57.indexOf(current);
30826
+ const cycleStart = path58.indexOf(current);
30520
30827
  const fullChain = [
30521
30828
  name,
30522
- ...path57.slice(0, cycleStart > 0 ? cycleStart : path57.length),
30829
+ ...path58.slice(0, cycleStart > 0 ? cycleStart : path58.length),
30523
30830
  current
30524
30831
  ].join(" \u2192 ");
30525
30832
  errors.push(`Circular alias detected: ${fullChain}`);
30526
30833
  break;
30527
30834
  }
30528
30835
  visited.add(current);
30529
- path57.push(current);
30836
+ path58.push(current);
30530
30837
  current = currentEntry.aliasOf || "";
30531
30838
  }
30532
30839
  }