opencode-swarm 7.43.1 → 7.44.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -52,7 +52,7 @@ var package_default;
52
52
  var init_package = __esm(() => {
53
53
  package_default = {
54
54
  name: "opencode-swarm",
55
- version: "7.43.1",
55
+ version: "7.44.1",
56
56
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
57
57
  main: "dist/index.js",
58
58
  types: "dist/index.d.ts",
@@ -16522,6 +16522,8 @@ var init_tool_names = __esm(() => {
16522
16522
  "skill_improve",
16523
16523
  "spec_write",
16524
16524
  "knowledge_ack",
16525
+ "knowledge_receipt",
16526
+ "knowledge_archive",
16525
16527
  "swarm_memory_recall",
16526
16528
  "swarm_memory_propose",
16527
16529
  "swarm_command",
@@ -16766,6 +16768,7 @@ var init_constants = __esm(() => {
16766
16768
  "knowledge_add",
16767
16769
  "knowledge_recall",
16768
16770
  "knowledge_remove",
16771
+ "knowledge_archive",
16769
16772
  "co_change_analyzer",
16770
16773
  "suggest_patch",
16771
16774
  "repo_map",
@@ -16782,6 +16785,7 @@ var init_constants = __esm(() => {
16782
16785
  "skill_retire",
16783
16786
  "skill_improve",
16784
16787
  "knowledge_ack",
16788
+ "knowledge_receipt",
16785
16789
  "summarize_work",
16786
16790
  "write_architecture_supervisor_evidence",
16787
16791
  "swarm_command",
@@ -16822,6 +16826,7 @@ var init_constants = __esm(() => {
16822
16826
  "syntax_check",
16823
16827
  "knowledge_add",
16824
16828
  "knowledge_recall",
16829
+ "knowledge_receipt",
16825
16830
  "repo_map",
16826
16831
  "summarize_work",
16827
16832
  "swarm_command"
@@ -17045,6 +17050,7 @@ var init_constants = __esm(() => {
17045
17050
  knowledge_add: "store a new lesson in the knowledge base",
17046
17051
  knowledge_recall: "search the knowledge base for relevant past decisions",
17047
17052
  knowledge_remove: "delete an outdated swarm knowledge entry by ID (swarm tier only)",
17053
+ knowledge_archive: "archive (default), quarantine, or purge a swarm knowledge entry by ID with an immutable audit tombstone; purge requires an admin flag",
17048
17054
  knowledge_query: "query swarm or hive knowledge with optional filters",
17049
17055
  co_change_analyzer: "detect hidden couplings by analyzing git history",
17050
17056
  check_gate_status: "check the gate status of a specific task",
@@ -17078,6 +17084,7 @@ var init_constants = __esm(() => {
17078
17084
  skill_retire: "retire a generated skill by adding a retired.marker file; retired skills are excluded from scoring and injection",
17079
17085
  spec_write: "author or update .swarm/spec.md for the current project",
17080
17086
  knowledge_ack: "record an explicit KNOWLEDGE_APPLIED/IGNORED/VIOLATED acknowledgment",
17087
+ knowledge_receipt: "file a receipt for retrieved knowledge (applied/ignored/contradicted + new lessons), recorded as immutable knowledge events",
17081
17088
  swarm_memory_recall: "recall scoped Swarm memory for the current repository as untrusted background",
17082
17089
  swarm_memory_propose: "create a pending Swarm memory proposal; does not write durable memory directly",
17083
17090
  swarm_command: "run supported /swarm commands through the canonical command registry",
@@ -35869,8 +35876,12 @@ function normalizeEntry(raw) {
35869
35876
  const obj = raw;
35870
35877
  if (!("retrieval_outcomes" in obj))
35871
35878
  return raw;
35872
- const ro = obj.retrieval_outcomes;
35873
- if (ro && typeof ro === "object") {
35879
+ let ro = obj.retrieval_outcomes;
35880
+ if (!ro || typeof ro !== "object") {
35881
+ ro = {};
35882
+ obj.retrieval_outcomes = ro;
35883
+ }
35884
+ {
35874
35885
  if (typeof ro.shown_count !== "number") {
35875
35886
  ro.shown_count = typeof ro.applied_count === "number" ? ro.applied_count : 0;
35876
35887
  }
@@ -35883,6 +35894,8 @@ function normalizeEntry(raw) {
35883
35894
  ro.ignored_count = 0;
35884
35895
  if (typeof ro.violated_count !== "number")
35885
35896
  ro.violated_count = 0;
35897
+ if (typeof ro.contradicted_count !== "number")
35898
+ ro.contradicted_count = 0;
35886
35899
  if (typeof ro.succeeded_after_shown_count !== "number") {
35887
35900
  ro.succeeded_after_shown_count = typeof ro.succeeded_after_count === "number" ? ro.succeeded_after_count : 0;
35888
35901
  }
@@ -35920,6 +35933,9 @@ function normalizeEntry(raw) {
35920
35933
  delete obj[f];
35921
35934
  }
35922
35935
  }
35936
+ if (!Array.isArray(obj.tags)) {
35937
+ obj.tags = [];
35938
+ }
35923
35939
  return raw;
35924
35940
  }
35925
35941
  async function readRejectedLessons(directory) {
@@ -36009,7 +36025,8 @@ async function appendRejectedLesson(directory, lesson) {
36009
36025
  }
36010
36026
  }
36011
36027
  function normalize2(text) {
36012
- return text.toLowerCase().replace(/[^\w\s]/g, " ").replace(/\s+/g, " ").trim();
36028
+ const s = typeof text === "string" ? text : String(text ?? "");
36029
+ return s.toLowerCase().replace(/[^\w\s]/g, " ").replace(/\s+/g, " ").trim();
36013
36030
  }
36014
36031
  function wordBigrams(text) {
36015
36032
  const words = normalize2(text).split(" ").filter(Boolean);
@@ -36041,6 +36058,16 @@ function computeConfidence(confirmedByCount, autoGenerated) {
36041
36058
  score += 0.1;
36042
36059
  return Math.min(score, 1);
36043
36060
  }
36061
+ function computeOutcomeSignal(outcomes) {
36062
+ if (!outcomes)
36063
+ return 0;
36064
+ const positives = (outcomes.applied_explicit_count ?? 0) + (outcomes.succeeded_after_shown_count ?? 0);
36065
+ const negatives = (outcomes.ignored_count ?? 0) + (outcomes.violated_count ?? 0) + (outcomes.contradicted_count ?? 0) + (outcomes.failed_after_shown_count ?? 0);
36066
+ const total = positives + negatives;
36067
+ if (total === 0)
36068
+ return 0;
36069
+ return (positives - negatives) / (total + OUTCOME_SIGNAL_SMOOTHING);
36070
+ }
36044
36071
  function inferTags(lesson) {
36045
36072
  const lower = lesson.toLowerCase();
36046
36073
  const tags = [];
@@ -36136,7 +36163,7 @@ async function applyConfidenceDeltas(filePath, deltas) {
36136
36163
  }
36137
36164
  }
36138
36165
  }
36139
- var import_proper_lockfile3, CONFIDENCE_FLOOR = 0.1, CONFIDENCE_CEILING = 1;
36166
+ var import_proper_lockfile3, OUTCOME_SIGNAL_SMOOTHING = 4, CONFIDENCE_FLOOR = 0.1, CONFIDENCE_CEILING = 1;
36140
36167
  var init_knowledge_store = __esm(() => {
36141
36168
  init_task_file();
36142
36169
  import_proper_lockfile3 = __toESM(require_proper_lockfile(), 1);
@@ -37570,6 +37597,9 @@ async function runAutoPromotion(directory, config3) {
37570
37597
  for (const entry of entries) {
37571
37598
  if (entry.status === "promoted")
37572
37599
  continue;
37600
+ if (computeOutcomeSignal(entry.retrieval_outcomes) <= OUTCOME_PROMOTION_BLOCK) {
37601
+ continue;
37602
+ }
37573
37603
  const distinctPhases = new Set((entry.confirmed_by ?? []).map((c) => c.phase_number)).size;
37574
37604
  if (entry.status === "candidate" && distinctPhases >= 3) {
37575
37605
  entry.status = "established";
@@ -37667,7 +37697,7 @@ function createKnowledgeCuratorHook(directory, config3) {
37667
37697
  };
37668
37698
  return safeHook(handler);
37669
37699
  }
37670
- var seenRetroSections, _internals11;
37700
+ var seenRetroSections, OUTCOME_PROMOTION_BLOCK = -0.3, _internals11;
37671
37701
  var init_knowledge_curator = __esm(() => {
37672
37702
  init_knowledge_store();
37673
37703
  init_knowledge_validator();
@@ -40241,24 +40271,63 @@ var init_gate_bridge = __esm(() => {
40241
40271
  };
40242
40272
  });
40243
40273
 
40274
+ // src/hooks/knowledge-events.ts
40275
+ import { existsSync as existsSync12 } from "fs";
40276
+ import { appendFile as appendFile4, mkdir as mkdir7, readFile as readFile7 } from "fs/promises";
40277
+ import * as path23 from "path";
40278
+ function resolveKnowledgeEventsPath(directory) {
40279
+ return path23.join(directory, ".swarm", "knowledge-events.jsonl");
40280
+ }
40281
+ async function readKnowledgeEvents(directory) {
40282
+ const filePath = resolveKnowledgeEventsPath(directory);
40283
+ if (!existsSync12(filePath))
40284
+ return [];
40285
+ const content = await readFile7(filePath, "utf-8");
40286
+ const out = [];
40287
+ for (const line of content.split(`
40288
+ `)) {
40289
+ const trimmed = line.trim();
40290
+ if (!trimmed)
40291
+ continue;
40292
+ try {
40293
+ out.push(JSON.parse(trimmed));
40294
+ } catch {
40295
+ warn(`[knowledge-events] Skipping corrupted JSONL line in ${filePath}: ${trimmed.slice(0, 80)}`);
40296
+ }
40297
+ }
40298
+ return out;
40299
+ }
40300
+ var RECEIPT_EVENT_TYPES;
40301
+ var init_knowledge_events = __esm(() => {
40302
+ init_logger();
40303
+ init_knowledge_store();
40304
+ RECEIPT_EVENT_TYPES = new Set([
40305
+ "acknowledged",
40306
+ "applied",
40307
+ "ignored",
40308
+ "contradicted",
40309
+ "violated"
40310
+ ]);
40311
+ });
40312
+
40244
40313
  // src/services/version-check.ts
40245
- import { existsSync as existsSync12, mkdirSync as mkdirSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "fs";
40314
+ import { existsSync as existsSync13, mkdirSync as mkdirSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "fs";
40246
40315
  import { homedir as homedir5 } from "os";
40247
- import { join as join21 } from "path";
40316
+ import { join as join22 } from "path";
40248
40317
  function cacheDir() {
40249
40318
  const xdg = process.env.XDG_CACHE_HOME;
40250
- const base = xdg && xdg.length > 0 ? xdg : join21(homedir5(), ".cache");
40251
- return join21(base, "opencode-swarm");
40319
+ const base = xdg && xdg.length > 0 ? xdg : join22(homedir5(), ".cache");
40320
+ return join22(base, "opencode-swarm");
40252
40321
  }
40253
40322
  function cacheFile() {
40254
- return join21(cacheDir(), "version-check.json");
40323
+ return join22(cacheDir(), "version-check.json");
40255
40324
  }
40256
40325
  function readVersionCache() {
40257
40326
  try {
40258
- const path23 = cacheFile();
40259
- if (!existsSync12(path23))
40327
+ const path24 = cacheFile();
40328
+ if (!existsSync13(path24))
40260
40329
  return null;
40261
- const raw = readFileSync8(path23, "utf-8");
40330
+ const raw = readFileSync8(path24, "utf-8");
40262
40331
  const parsed = JSON.parse(raw);
40263
40332
  if (typeof parsed?.checkedAt !== "number")
40264
40333
  return null;
@@ -40295,10 +40364,156 @@ var init_version_check = __esm(() => {
40295
40364
  CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
40296
40365
  });
40297
40366
 
40367
+ // src/services/knowledge-diagnostics.ts
40368
+ import { existsSync as existsSync14 } from "fs";
40369
+ import { readFile as readFile8 } from "fs/promises";
40370
+ async function readRawLines(filePath) {
40371
+ if (!existsSync14(filePath))
40372
+ return { entries: [], corrupt: 0 };
40373
+ const content = await readFile8(filePath, "utf-8");
40374
+ const entries = [];
40375
+ let corrupt = 0;
40376
+ for (const line of content.split(`
40377
+ `)) {
40378
+ const trimmed = line.trim();
40379
+ if (!trimmed)
40380
+ continue;
40381
+ try {
40382
+ entries.push(JSON.parse(trimmed));
40383
+ } catch {
40384
+ corrupt++;
40385
+ }
40386
+ }
40387
+ return { entries, corrupt };
40388
+ }
40389
+ function hasV2Counters(entry) {
40390
+ const ro = entry.retrieval_outcomes;
40391
+ if (!ro || typeof ro !== "object")
40392
+ return false;
40393
+ return typeof ro.shown_count === "number" && typeof ro.applied_explicit_count === "number" && typeof ro.ignored_count === "number";
40394
+ }
40395
+ function cacheStatus() {
40396
+ const cache = readVersionCache();
40397
+ if (!cache?.npmLatest)
40398
+ return "unknown";
40399
+ return compareVersions(cache.npmLatest, version3) > 0 ? "stale" : "fresh";
40400
+ }
40401
+ async function computeKnowledgeDebug(directory) {
40402
+ const swarmPath = resolveSwarmKnowledgePath(directory);
40403
+ const hivePath = resolveHiveKnowledgePath();
40404
+ const eventsPath = resolveKnowledgeEventsPath(directory);
40405
+ const [swarmRaw, hiveRaw] = await Promise.all([
40406
+ readRawLines(swarmPath),
40407
+ readRawLines(hivePath)
40408
+ ]);
40409
+ const rawEntries = [...swarmRaw.entries, ...hiveRaw.entries];
40410
+ const corrupt = swarmRaw.corrupt + hiveRaw.corrupt;
40411
+ const schemaVersions = {};
40412
+ let missingV2 = 0;
40413
+ for (const e of rawEntries) {
40414
+ const sv = String(typeof e.schema_version === "number" ? e.schema_version : "unknown");
40415
+ schemaVersions[sv] = (schemaVersions[sv] ?? 0) + 1;
40416
+ if (!hasV2Counters(e))
40417
+ missingV2++;
40418
+ }
40419
+ let normalizedCount = 0;
40420
+ let active = 0;
40421
+ let archived = 0;
40422
+ let quarantined = 0;
40423
+ try {
40424
+ const swarm = await readKnowledge(swarmPath);
40425
+ const hive = await readKnowledge(hivePath);
40426
+ for (const e of [...swarm, ...hive]) {
40427
+ normalizedCount++;
40428
+ if (e.status === "archived")
40429
+ archived++;
40430
+ else if (e.status === "quarantined")
40431
+ quarantined++;
40432
+ else
40433
+ active++;
40434
+ }
40435
+ } catch {}
40436
+ let rejected = 0;
40437
+ try {
40438
+ rejected = (await readRejectedLessons(directory)).length;
40439
+ } catch {}
40440
+ let eventCount = 0;
40441
+ let retrieval7d = 0;
40442
+ try {
40443
+ const events = await readKnowledgeEvents(directory);
40444
+ eventCount = events.length;
40445
+ const cutoff = Date.now() - SEVEN_DAYS_MS;
40446
+ for (const ev of events) {
40447
+ if (ev.type !== "retrieved")
40448
+ continue;
40449
+ const t = Date.parse(ev.timestamp);
40450
+ if (!Number.isNaN(t) && t >= cutoff)
40451
+ retrieval7d++;
40452
+ }
40453
+ } catch {}
40454
+ return {
40455
+ plugin_version: version3,
40456
+ directory,
40457
+ swarm_path: swarmPath,
40458
+ hive_path: hivePath,
40459
+ events_path: eventsPath,
40460
+ raw_entry_count: rawEntries.length,
40461
+ normalized_entry_count: normalizedCount,
40462
+ corrupt_line_count: corrupt,
40463
+ schema_versions: schemaVersions,
40464
+ entries_missing_v2_counters: missingV2,
40465
+ status_breakdown: { active, archived, quarantined, rejected },
40466
+ event_count: eventCount,
40467
+ retrieval_events_7d: retrieval7d,
40468
+ cache_status: cacheStatus()
40469
+ };
40470
+ }
40471
+ async function checkKnowledgeHealth(directory) {
40472
+ let debug;
40473
+ try {
40474
+ debug = await computeKnowledgeDebug(directory);
40475
+ } catch {
40476
+ return {
40477
+ name: "Knowledge health",
40478
+ status: "\u26A0\uFE0F",
40479
+ detail: "Could not compute knowledge diagnostics"
40480
+ };
40481
+ }
40482
+ const sb = debug.status_breakdown;
40483
+ const summary = `active=${sb.active} archived=${sb.archived} quarantined=${sb.quarantined} ` + `rejected=${sb.rejected} | events=${debug.event_count} (retrieved/7d=${debug.retrieval_events_7d}) | ` + `schema=${JSON.stringify(debug.schema_versions)}`;
40484
+ const warnings = [];
40485
+ if (debug.corrupt_line_count > 0) {
40486
+ warnings.push(`${debug.corrupt_line_count} corrupt JSONL line(s) (raw=${debug.raw_entry_count} vs normalized=${debug.normalized_entry_count})`);
40487
+ }
40488
+ if (debug.entries_missing_v2_counters > 0) {
40489
+ warnings.push(`${debug.entries_missing_v2_counters} entr(y/ies) missing v2 counters (normalized on read)`);
40490
+ }
40491
+ if (debug.cache_status === "stale") {
40492
+ warnings.push("stale plugin cache \u2014 run `bunx opencode-swarm update` (knowledge tools may be running old code)");
40493
+ }
40494
+ if (warnings.length > 0) {
40495
+ return {
40496
+ name: "Knowledge health",
40497
+ status: "\u26A0\uFE0F",
40498
+ detail: `${summary} \u2014 ${warnings.join("; ")}`
40499
+ };
40500
+ }
40501
+ return { name: "Knowledge health", status: "\u2705", detail: summary };
40502
+ }
40503
+ var version3, SEVEN_DAYS_MS;
40504
+ var init_knowledge_diagnostics = __esm(() => {
40505
+ init_package();
40506
+ init_knowledge_events();
40507
+ init_knowledge_store();
40508
+ init_version_check();
40509
+ ({ version: version3 } = package_default);
40510
+ SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000;
40511
+ });
40512
+
40298
40513
  // src/services/diagnose-service.ts
40299
40514
  import * as child_process4 from "child_process";
40300
- import { existsSync as existsSync13, readdirSync as readdirSync4, readFileSync as readFileSync9, statSync as statSync7 } from "fs";
40301
- import path23 from "path";
40515
+ import { existsSync as existsSync15, readdirSync as readdirSync4, readFileSync as readFileSync9, statSync as statSync7 } from "fs";
40516
+ import path24 from "path";
40302
40517
  import { fileURLToPath } from "url";
40303
40518
  function validateTaskDag(plan) {
40304
40519
  const allTaskIds = new Set;
@@ -40545,7 +40760,7 @@ async function checkConfigBackups(directory) {
40545
40760
  }
40546
40761
  async function checkGitRepository(directory) {
40547
40762
  try {
40548
- if (!existsSync13(directory) || !statSync7(directory).isDirectory()) {
40763
+ if (!existsSync15(directory) || !statSync7(directory).isDirectory()) {
40549
40764
  return {
40550
40765
  name: "Git Repository",
40551
40766
  status: "\u274C",
@@ -40609,8 +40824,8 @@ async function checkSpecStaleness(directory, plan) {
40609
40824
  };
40610
40825
  }
40611
40826
  async function checkConfigParseability(directory) {
40612
- const configPath = path23.join(directory, ".opencode/opencode-swarm.json");
40613
- if (!existsSync13(configPath)) {
40827
+ const configPath = path24.join(directory, ".opencode/opencode-swarm.json");
40828
+ if (!existsSync15(configPath)) {
40614
40829
  return {
40615
40830
  name: "Config Parseability",
40616
40831
  status: "\u2705",
@@ -40638,7 +40853,7 @@ function resolveGrammarDir(thisDir) {
40638
40853
  const normalized = thisDir.replace(/\\/g, "/");
40639
40854
  const isSource = normalized.endsWith("/src/services");
40640
40855
  const isCliBundle = normalized.endsWith("/cli");
40641
- return isSource || isCliBundle ? path23.join(thisDir, "..", "lang", "grammars") : path23.join(thisDir, "lang", "grammars");
40856
+ return isSource || isCliBundle ? path24.join(thisDir, "..", "lang", "grammars") : path24.join(thisDir, "lang", "grammars");
40642
40857
  }
40643
40858
  async function checkGrammarWasmFiles() {
40644
40859
  const grammarFiles = [
@@ -40662,14 +40877,14 @@ async function checkGrammarWasmFiles() {
40662
40877
  "tree-sitter-ini.wasm",
40663
40878
  "tree-sitter-regex.wasm"
40664
40879
  ];
40665
- const thisDir = path23.dirname(fileURLToPath(import.meta.url));
40880
+ const thisDir = path24.dirname(fileURLToPath(import.meta.url));
40666
40881
  const grammarDir = resolveGrammarDir(thisDir);
40667
40882
  const missing = [];
40668
- if (!existsSync13(path23.join(grammarDir, "tree-sitter.wasm"))) {
40883
+ if (!existsSync15(path24.join(grammarDir, "tree-sitter.wasm"))) {
40669
40884
  missing.push("tree-sitter.wasm (core runtime)");
40670
40885
  }
40671
40886
  for (const file3 of grammarFiles) {
40672
- if (!existsSync13(path23.join(grammarDir, file3))) {
40887
+ if (!existsSync15(path24.join(grammarDir, file3))) {
40673
40888
  missing.push(file3);
40674
40889
  }
40675
40890
  }
@@ -40687,8 +40902,8 @@ async function checkGrammarWasmFiles() {
40687
40902
  };
40688
40903
  }
40689
40904
  async function checkCheckpointManifest(directory) {
40690
- const manifestPath = path23.join(directory, ".swarm/checkpoints.json");
40691
- if (!existsSync13(manifestPath)) {
40905
+ const manifestPath = path24.join(directory, ".swarm/checkpoints.json");
40906
+ if (!existsSync15(manifestPath)) {
40692
40907
  return {
40693
40908
  name: "Checkpoint Manifest",
40694
40909
  status: "\u2705",
@@ -40739,8 +40954,8 @@ async function checkCheckpointManifest(directory) {
40739
40954
  }
40740
40955
  }
40741
40956
  async function checkEventStreamIntegrity(directory) {
40742
- const eventsPath = path23.join(directory, ".swarm/events.jsonl");
40743
- if (!existsSync13(eventsPath)) {
40957
+ const eventsPath = path24.join(directory, ".swarm/events.jsonl");
40958
+ if (!existsSync15(eventsPath)) {
40744
40959
  return {
40745
40960
  name: "Event Stream",
40746
40961
  status: "\u2705",
@@ -40780,8 +40995,8 @@ async function checkEventStreamIntegrity(directory) {
40780
40995
  }
40781
40996
  }
40782
40997
  async function checkSteeringDirectives(directory) {
40783
- const eventsPath = path23.join(directory, ".swarm/events.jsonl");
40784
- if (!existsSync13(eventsPath)) {
40998
+ const eventsPath = path24.join(directory, ".swarm/events.jsonl");
40999
+ if (!existsSync15(eventsPath)) {
40785
41000
  return {
40786
41001
  name: "Steering Directives",
40787
41002
  status: "\u2705",
@@ -40836,8 +41051,8 @@ async function checkCurator(directory) {
40836
41051
  detail: "Disabled (enable via curator.enabled)"
40837
41052
  };
40838
41053
  }
40839
- const summaryPath = path23.join(directory, ".swarm/curator-summary.json");
40840
- if (!existsSync13(summaryPath)) {
41054
+ const summaryPath = path24.join(directory, ".swarm/curator-summary.json");
41055
+ if (!existsSync15(summaryPath)) {
40841
41056
  return {
40842
41057
  name: "Curator",
40843
41058
  status: "\u2705",
@@ -40881,16 +41096,16 @@ async function checkCurator(directory) {
40881
41096
  async function getDiagnoseData(directory) {
40882
41097
  const checks5 = [];
40883
41098
  const versionCache = readVersionCache();
40884
- let versionDetail = version3;
41099
+ let versionDetail = version4;
40885
41100
  let versionStatus = "\u2705";
40886
41101
  if (versionCache?.npmLatest) {
40887
41102
  const ageMs = Date.now() - versionCache.checkedAt;
40888
41103
  const ageMin = Math.max(0, Math.round(ageMs / 60000));
40889
- if (compareVersions(versionCache.npmLatest, version3) > 0) {
41104
+ if (compareVersions(versionCache.npmLatest, version4) > 0) {
40890
41105
  versionStatus = "\u26A0\uFE0F";
40891
- versionDetail = `${version3} (npm latest: ${versionCache.npmLatest}, checked ${ageMin}m ago) ` + "\u2014 run `bunx opencode-swarm update` to refresh";
41106
+ versionDetail = `${version4} (npm latest: ${versionCache.npmLatest}, checked ${ageMin}m ago) ` + "\u2014 run `bunx opencode-swarm update` to refresh";
40892
41107
  } else {
40893
- versionDetail = `${version3} (npm latest: ${versionCache.npmLatest}, checked ${ageMin}m ago)`;
41108
+ versionDetail = `${version4} (npm latest: ${versionCache.npmLatest}, checked ${ageMin}m ago)`;
40894
41109
  }
40895
41110
  }
40896
41111
  checks5.push({
@@ -41001,9 +41216,10 @@ async function getDiagnoseData(directory) {
41001
41216
  checks5.push(await checkEventStreamIntegrity(directory));
41002
41217
  checks5.push(await checkSteeringDirectives(directory));
41003
41218
  checks5.push(await checkCurator(directory));
41219
+ checks5.push(await checkKnowledgeHealth(directory));
41004
41220
  try {
41005
- const evidenceDir = path23.join(directory, ".swarm", "evidence");
41006
- const snapshotFiles = existsSync13(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
41221
+ const evidenceDir = path24.join(directory, ".swarm", "evidence");
41222
+ const snapshotFiles = existsSync15(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
41007
41223
  if (snapshotFiles.length > 0) {
41008
41224
  const latest = snapshotFiles.sort().pop();
41009
41225
  checks5.push({
@@ -41036,11 +41252,11 @@ async function getDiagnoseData(directory) {
41036
41252
  const cacheRows = [];
41037
41253
  for (const cachePath of cachePaths) {
41038
41254
  try {
41039
- if (!existsSync13(cachePath)) {
41255
+ if (!existsSync15(cachePath)) {
41040
41256
  cacheRows.push(`\u2B1C ${cachePath} \u2014 absent`);
41041
41257
  continue;
41042
41258
  }
41043
- const pkgJsonPath = path23.join(cachePath, "package.json");
41259
+ const pkgJsonPath = path24.join(cachePath, "package.json");
41044
41260
  try {
41045
41261
  const raw = readFileSync9(pkgJsonPath, "utf-8");
41046
41262
  const parsed = JSON.parse(raw);
@@ -41055,10 +41271,10 @@ async function getDiagnoseData(directory) {
41055
41271
  }
41056
41272
  const hasCacheEntry = cacheRows.some((r) => r.startsWith("\u2705"));
41057
41273
  const hasCacheWarning = cacheRows.some((r) => r.startsWith("\u26A0\uFE0F"));
41058
- const cacheStatus = hasCacheWarning ? "\u26A0\uFE0F" : hasCacheEntry ? "\u2705" : "\u2B1C";
41274
+ const cacheStatus2 = hasCacheWarning ? "\u26A0\uFE0F" : hasCacheEntry ? "\u2705" : "\u2B1C";
41059
41275
  checks5.push({
41060
41276
  name: "Plugin Caches",
41061
- status: cacheStatus,
41277
+ status: cacheStatus2,
41062
41278
  detail: cacheRows.join(" | ")
41063
41279
  });
41064
41280
  const passCount = checks5.filter((c) => c.status === "\u2705" || c.status === "\u2B1C").length;
@@ -41094,7 +41310,7 @@ async function handleDiagnoseCommand(directory, _args) {
41094
41310
  const diagnoseData = await getDiagnoseData(directory);
41095
41311
  return formatDiagnoseMarkdown(diagnoseData);
41096
41312
  }
41097
- var version3;
41313
+ var version4;
41098
41314
  var init_diagnose_service = __esm(() => {
41099
41315
  init_package();
41100
41316
  init_cache_paths();
@@ -41103,9 +41319,10 @@ var init_diagnose_service = __esm(() => {
41103
41319
  init_manager2();
41104
41320
  init_utils2();
41105
41321
  init_manager();
41322
+ init_knowledge_diagnostics();
41106
41323
  init_version_check();
41107
41324
  init_warning_buffer();
41108
- ({ version: version3 } = package_default);
41325
+ ({ version: version4 } = package_default);
41109
41326
  });
41110
41327
 
41111
41328
  // src/commands/diagnose.ts
@@ -41131,13 +41348,13 @@ __export(exports_config_doctor, {
41131
41348
  import * as crypto4 from "crypto";
41132
41349
  import * as fs9 from "fs";
41133
41350
  import * as os6 from "os";
41134
- import * as path24 from "path";
41351
+ import * as path25 from "path";
41135
41352
  function getUserConfigDir3() {
41136
- return process.env.XDG_CONFIG_HOME || path24.join(os6.homedir(), ".config");
41353
+ return process.env.XDG_CONFIG_HOME || path25.join(os6.homedir(), ".config");
41137
41354
  }
41138
41355
  function getConfigPaths(directory) {
41139
- const userConfigPath = path24.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
41140
- const projectConfigPath = path24.join(directory, ".opencode", "opencode-swarm.json");
41356
+ const userConfigPath = path25.join(getUserConfigDir3(), "opencode", "opencode-swarm.json");
41357
+ const projectConfigPath = path25.join(directory, ".opencode", "opencode-swarm.json");
41141
41358
  return { userConfigPath, projectConfigPath };
41142
41359
  }
41143
41360
  function computeHash(content) {
@@ -41162,9 +41379,9 @@ function isValidConfigPath(configPath, directory) {
41162
41379
  const normalizedUser = userConfigPath.replace(/\\/g, "/");
41163
41380
  const normalizedProject = projectConfigPath.replace(/\\/g, "/");
41164
41381
  try {
41165
- const resolvedConfig = path24.resolve(configPath);
41166
- const resolvedUser = path24.resolve(normalizedUser);
41167
- const resolvedProject = path24.resolve(normalizedProject);
41382
+ const resolvedConfig = path25.resolve(configPath);
41383
+ const resolvedUser = path25.resolve(normalizedUser);
41384
+ const resolvedProject = path25.resolve(normalizedProject);
41168
41385
  return resolvedConfig === resolvedUser || resolvedConfig === resolvedProject;
41169
41386
  } catch {
41170
41387
  return false;
@@ -41204,12 +41421,12 @@ function createConfigBackup(directory) {
41204
41421
  };
41205
41422
  }
41206
41423
  function writeBackupArtifact(directory, backup) {
41207
- const swarmDir = path24.join(directory, ".swarm");
41424
+ const swarmDir = path25.join(directory, ".swarm");
41208
41425
  if (!fs9.existsSync(swarmDir)) {
41209
41426
  fs9.mkdirSync(swarmDir, { recursive: true });
41210
41427
  }
41211
41428
  const backupFilename = `config-backup-${backup.createdAt}.json`;
41212
- const backupPath = path24.join(swarmDir, backupFilename);
41429
+ const backupPath = path25.join(swarmDir, backupFilename);
41213
41430
  const artifact = {
41214
41431
  createdAt: backup.createdAt,
41215
41432
  configPath: backup.configPath,
@@ -41239,7 +41456,7 @@ function restoreFromBackup(backupPath, directory) {
41239
41456
  return null;
41240
41457
  }
41241
41458
  const targetPath = artifact.configPath;
41242
- const targetDir = path24.dirname(targetPath);
41459
+ const targetDir = path25.dirname(targetPath);
41243
41460
  if (!fs9.existsSync(targetDir)) {
41244
41461
  fs9.mkdirSync(targetDir, { recursive: true });
41245
41462
  }
@@ -41270,9 +41487,9 @@ function readConfigFromFile(directory) {
41270
41487
  return null;
41271
41488
  }
41272
41489
  }
41273
- function validateConfigKey(path25, value, _config) {
41490
+ function validateConfigKey(path26, value, _config) {
41274
41491
  const findings = [];
41275
- switch (path25) {
41492
+ switch (path26) {
41276
41493
  case "agents": {
41277
41494
  if (value !== undefined) {
41278
41495
  findings.push({
@@ -41509,27 +41726,27 @@ function validateConfigKey(path25, value, _config) {
41509
41726
  }
41510
41727
  return findings;
41511
41728
  }
41512
- function walkConfigAndValidate(obj, path25, config3, findings) {
41729
+ function walkConfigAndValidate(obj, path26, config3, findings) {
41513
41730
  if (obj === null || obj === undefined) {
41514
41731
  return;
41515
41732
  }
41516
- if (path25 && typeof obj === "object" && !Array.isArray(obj)) {
41517
- const keyFindings = validateConfigKey(path25, obj, config3);
41733
+ if (path26 && typeof obj === "object" && !Array.isArray(obj)) {
41734
+ const keyFindings = validateConfigKey(path26, obj, config3);
41518
41735
  findings.push(...keyFindings);
41519
41736
  }
41520
41737
  if (typeof obj !== "object") {
41521
- const keyFindings = validateConfigKey(path25, obj, config3);
41738
+ const keyFindings = validateConfigKey(path26, obj, config3);
41522
41739
  findings.push(...keyFindings);
41523
41740
  return;
41524
41741
  }
41525
41742
  if (Array.isArray(obj)) {
41526
41743
  obj.forEach((item, index) => {
41527
- walkConfigAndValidate(item, `${path25}[${index}]`, config3, findings);
41744
+ walkConfigAndValidate(item, `${path26}[${index}]`, config3, findings);
41528
41745
  });
41529
41746
  return;
41530
41747
  }
41531
41748
  for (const [key, value] of Object.entries(obj)) {
41532
- const newPath = path25 ? `${path25}.${key}` : key;
41749
+ const newPath = path26 ? `${path26}.${key}` : key;
41533
41750
  walkConfigAndValidate(value, newPath, config3, findings);
41534
41751
  }
41535
41752
  }
@@ -41649,7 +41866,7 @@ function applySafeAutoFixes(directory, result) {
41649
41866
  }
41650
41867
  }
41651
41868
  if (appliedFixes.length > 0) {
41652
- const configDir = path24.dirname(configPath);
41869
+ const configDir = path25.dirname(configPath);
41653
41870
  if (!fs9.existsSync(configDir)) {
41654
41871
  fs9.mkdirSync(configDir, { recursive: true });
41655
41872
  }
@@ -41659,12 +41876,12 @@ function applySafeAutoFixes(directory, result) {
41659
41876
  return { appliedFixes, updatedConfigPath };
41660
41877
  }
41661
41878
  function writeDoctorArtifact(directory, result) {
41662
- const swarmDir = path24.join(directory, ".swarm");
41879
+ const swarmDir = path25.join(directory, ".swarm");
41663
41880
  if (!fs9.existsSync(swarmDir)) {
41664
41881
  fs9.mkdirSync(swarmDir, { recursive: true });
41665
41882
  }
41666
41883
  const artifactFilename = "config-doctor.json";
41667
- const artifactPath = path24.join(swarmDir, artifactFilename);
41884
+ const artifactPath = path25.join(swarmDir, artifactFilename);
41668
41885
  const guiOutput = {
41669
41886
  timestamp: result.timestamp,
41670
41887
  summary: result.summary,
@@ -41760,17 +41977,17 @@ function detectStraySwarmDirs(projectRoot) {
41760
41977
  if (!entry.isDirectory())
41761
41978
  continue;
41762
41979
  const name = entry.name;
41763
- const fullPath = path24.join(dir, name);
41980
+ const fullPath = path25.join(dir, name);
41764
41981
  if (SKIP_DIRS.has(name))
41765
41982
  continue;
41766
- const gitPath = path24.join(fullPath, ".git");
41983
+ const gitPath = path25.join(fullPath, ".git");
41767
41984
  try {
41768
41985
  const gitStat = fs9.statSync(gitPath);
41769
41986
  if (gitStat.isFile() || gitStat.isDirectory())
41770
41987
  continue;
41771
41988
  } catch {}
41772
41989
  if (name === ".swarm") {
41773
- const parentDir = path24.dirname(fullPath);
41990
+ const parentDir = path25.dirname(fullPath);
41774
41991
  if (parentDir === projectRoot)
41775
41992
  continue;
41776
41993
  let contents = [];
@@ -41780,7 +41997,7 @@ function detectStraySwarmDirs(projectRoot) {
41780
41997
  contents = ["<unreadable>"];
41781
41998
  }
41782
41999
  findings.push({
41783
- path: path24.relative(projectRoot, fullPath).replace(/\\/g, "/"),
42000
+ path: path25.relative(projectRoot, fullPath).replace(/\\/g, "/"),
41784
42001
  absolutePath: fullPath,
41785
42002
  contents: contents.slice(0, MAX_CONTENTS_ENTRIES),
41786
42003
  totalEntries: contents.length
@@ -41798,21 +42015,21 @@ function removeStraySwarmDir(projectRoot, strayPath) {
41798
42015
  let canonicalStray;
41799
42016
  try {
41800
42017
  canonicalRoot = fs9.realpathSync(projectRoot);
41801
- canonicalStray = fs9.realpathSync(path24.isAbsolute(strayPath) ? strayPath : path24.resolve(projectRoot, strayPath));
42018
+ canonicalStray = fs9.realpathSync(path25.isAbsolute(strayPath) ? strayPath : path25.resolve(projectRoot, strayPath));
41802
42019
  } catch (err) {
41803
42020
  return {
41804
42021
  success: false,
41805
42022
  message: `Failed to resolve paths: ${err instanceof Error ? err.message : String(err)}`
41806
42023
  };
41807
42024
  }
41808
- const rootSwarm = path24.join(canonicalRoot, ".swarm");
42025
+ const rootSwarm = path25.join(canonicalRoot, ".swarm");
41809
42026
  if (canonicalStray === rootSwarm || canonicalStray === canonicalRoot) {
41810
42027
  return {
41811
42028
  success: false,
41812
42029
  message: "Refusing to remove root .swarm/ directory"
41813
42030
  };
41814
42031
  }
41815
- if (!canonicalStray.startsWith(canonicalRoot + path24.sep)) {
42032
+ if (!canonicalStray.startsWith(canonicalRoot + path25.sep)) {
41816
42033
  return {
41817
42034
  success: false,
41818
42035
  message: "Path is outside project root \u2014 refusing to remove"
@@ -42901,7 +43118,7 @@ var init_profiles = __esm(() => {
42901
43118
 
42902
43119
  // src/lang/detector.ts
42903
43120
  import { access as access3, readdir as readdir2 } from "fs/promises";
42904
- import { extname as extname2, join as join23 } from "path";
43121
+ import { extname as extname2, join as join24 } from "path";
42905
43122
  async function detectProjectLanguages(projectDir) {
42906
43123
  const detected = new Set;
42907
43124
  async function scanDir(dir) {
@@ -42917,7 +43134,7 @@ async function detectProjectLanguages(projectDir) {
42917
43134
  if (detectFile.includes("*") || detectFile.includes("?"))
42918
43135
  continue;
42919
43136
  try {
42920
- await access3(join23(dir, detectFile));
43137
+ await access3(join24(dir, detectFile));
42921
43138
  detected.add(profile.id);
42922
43139
  break;
42923
43140
  } catch {}
@@ -42938,7 +43155,7 @@ async function detectProjectLanguages(projectDir) {
42938
43155
  const topEntries = await readdir2(projectDir, { withFileTypes: true });
42939
43156
  for (const entry of topEntries) {
42940
43157
  if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
42941
- await scanDir(join23(projectDir, entry.name));
43158
+ await scanDir(join24(projectDir, entry.name));
42942
43159
  }
42943
43160
  }
42944
43161
  } catch {}
@@ -42957,7 +43174,7 @@ var init_detector = __esm(() => {
42957
43174
 
42958
43175
  // src/build/discovery.ts
42959
43176
  import * as fs10 from "fs";
42960
- import * as path25 from "path";
43177
+ import * as path26 from "path";
42961
43178
  function isCommandAvailable(command) {
42962
43179
  if (toolchainCache.has(command)) {
42963
43180
  return toolchainCache.get(command);
@@ -42992,11 +43209,11 @@ function findBuildFiles(workingDir, patterns) {
42992
43209
  const regex = simpleGlobToRegex(pattern);
42993
43210
  const matches = files.filter((f) => regex.test(f));
42994
43211
  if (matches.length > 0) {
42995
- return path25.join(dir, matches[0]);
43212
+ return path26.join(dir, matches[0]);
42996
43213
  }
42997
43214
  } catch {}
42998
43215
  } else {
42999
- const filePath = path25.join(workingDir, pattern);
43216
+ const filePath = path26.join(workingDir, pattern);
43000
43217
  if (fs10.existsSync(filePath)) {
43001
43218
  return filePath;
43002
43219
  }
@@ -43005,7 +43222,7 @@ function findBuildFiles(workingDir, patterns) {
43005
43222
  return null;
43006
43223
  }
43007
43224
  function getRepoDefinedScripts(workingDir, scripts) {
43008
- const packageJsonPath = path25.join(workingDir, "package.json");
43225
+ const packageJsonPath = path26.join(workingDir, "package.json");
43009
43226
  if (!fs10.existsSync(packageJsonPath)) {
43010
43227
  return [];
43011
43228
  }
@@ -43046,7 +43263,7 @@ function findAllBuildFiles(workingDir) {
43046
43263
  const regex = simpleGlobToRegex(pattern);
43047
43264
  findFilesRecursive(workingDir, regex, allBuildFiles);
43048
43265
  } else {
43049
- const filePath = path25.join(workingDir, pattern);
43266
+ const filePath = path26.join(workingDir, pattern);
43050
43267
  if (fs10.existsSync(filePath)) {
43051
43268
  allBuildFiles.add(filePath);
43052
43269
  }
@@ -43059,7 +43276,7 @@ function findFilesRecursive(dir, regex, results) {
43059
43276
  try {
43060
43277
  const entries = fs10.readdirSync(dir, { withFileTypes: true });
43061
43278
  for (const entry of entries) {
43062
- const fullPath = path25.join(dir, entry.name);
43279
+ const fullPath = path26.join(dir, entry.name);
43063
43280
  if (entry.isDirectory() && !["node_modules", ".git", "dist", "build", "target"].includes(entry.name)) {
43064
43281
  findFilesRecursive(fullPath, regex, results);
43065
43282
  } else if (entry.isFile() && regex.test(entry.name)) {
@@ -43082,7 +43299,7 @@ async function discoverBuildCommandsFromProfiles(workingDir) {
43082
43299
  let foundCommand = false;
43083
43300
  for (const cmd of sortedCommands) {
43084
43301
  if (cmd.detectFile) {
43085
- const detectFilePath = path25.join(workingDir, cmd.detectFile);
43302
+ const detectFilePath = path26.join(workingDir, cmd.detectFile);
43086
43303
  if (!fs10.existsSync(detectFilePath)) {
43087
43304
  continue;
43088
43305
  }
@@ -43323,7 +43540,7 @@ var init_discovery = __esm(() => {
43323
43540
 
43324
43541
  // src/services/tool-doctor.ts
43325
43542
  import * as fs11 from "fs";
43326
- import * as path26 from "path";
43543
+ import * as path27 from "path";
43327
43544
  function extractRegisteredToolKeys(indexPath) {
43328
43545
  const registeredKeys = new Set;
43329
43546
  try {
@@ -43378,8 +43595,8 @@ function checkBinaryReadiness() {
43378
43595
  }
43379
43596
  function runToolDoctor(_directory, pluginRoot) {
43380
43597
  const findings = [];
43381
- const resolvedPluginRoot = pluginRoot ?? path26.resolve(import.meta.dir, "..", "..");
43382
- const indexPath = path26.join(resolvedPluginRoot, "src", "index.ts");
43598
+ const resolvedPluginRoot = pluginRoot ?? path27.resolve(import.meta.dir, "..", "..");
43599
+ const indexPath = path27.join(resolvedPluginRoot, "src", "index.ts");
43383
43600
  if (!fs11.existsSync(indexPath)) {
43384
43601
  return {
43385
43602
  findings: [
@@ -44137,12 +44354,12 @@ var init_export = __esm(() => {
44137
44354
 
44138
44355
  // src/full-auto/state.ts
44139
44356
  import * as fs12 from "fs";
44140
- import * as path27 from "path";
44357
+ import * as path28 from "path";
44141
44358
  function nowISO() {
44142
44359
  return new Date().toISOString();
44143
44360
  }
44144
44361
  function ensureSwarmDir(directory) {
44145
- const swarmDir = path27.resolve(directory, ".swarm");
44362
+ const swarmDir = path28.resolve(directory, ".swarm");
44146
44363
  if (!fs12.existsSync(swarmDir)) {
44147
44364
  fs12.mkdirSync(swarmDir, { recursive: true });
44148
44365
  }
@@ -44843,7 +45060,7 @@ var init_handoff_service = __esm(() => {
44843
45060
 
44844
45061
  // src/session/snapshot-writer.ts
44845
45062
  import { closeSync as closeSync4, fsyncSync as fsyncSync2, mkdirSync as mkdirSync12, openSync as openSync4, renameSync as renameSync8 } from "fs";
44846
- import * as path28 from "path";
45063
+ import * as path29 from "path";
44847
45064
  function serializeAgentSession(s) {
44848
45065
  const gateLog = {};
44849
45066
  const rawGateLog = s.gateLog ?? new Map;
@@ -44943,7 +45160,7 @@ async function writeSnapshot(directory, state) {
44943
45160
  }
44944
45161
  const content = JSON.stringify(snapshot, null, 2);
44945
45162
  const resolvedPath = validateSwarmPath(directory, "session/state.json");
44946
- const dir = path28.dirname(resolvedPath);
45163
+ const dir = path29.dirname(resolvedPath);
44947
45164
  mkdirSync12(dir, { recursive: true });
44948
45165
  const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
44949
45166
  await bunWrite(tempPath, content);
@@ -45403,9 +45620,9 @@ var KNOWLEDGE_SCHEMA_VERSION = 2;
45403
45620
 
45404
45621
  // src/hooks/knowledge-migrator.ts
45405
45622
  import { randomUUID as randomUUID3 } from "crypto";
45406
- import { existsSync as existsSync18, readFileSync as readFileSync14 } from "fs";
45407
- import { mkdir as mkdir7, readFile as readFile7, writeFile as writeFile8 } from "fs/promises";
45408
- import * as path29 from "path";
45623
+ import { existsSync as existsSync20, readFileSync as readFileSync14 } from "fs";
45624
+ import { mkdir as mkdir8, readFile as readFile9, writeFile as writeFile8 } from "fs/promises";
45625
+ import * as path30 from "path";
45409
45626
  async function migrateKnowledgeToExternal(_directory, _config) {
45410
45627
  return {
45411
45628
  migrated: false,
@@ -45416,10 +45633,10 @@ async function migrateKnowledgeToExternal(_directory, _config) {
45416
45633
  };
45417
45634
  }
45418
45635
  async function migrateContextToKnowledge(directory, config3) {
45419
- const sentinelPath = path29.join(directory, ".swarm", ".knowledge-migrated");
45420
- const contextPath = path29.join(directory, ".swarm", "context.md");
45636
+ const sentinelPath = path30.join(directory, ".swarm", ".knowledge-migrated");
45637
+ const contextPath = path30.join(directory, ".swarm", "context.md");
45421
45638
  const knowledgePath = resolveSwarmKnowledgePath(directory);
45422
- if (existsSync18(sentinelPath)) {
45639
+ if (existsSync20(sentinelPath)) {
45423
45640
  return {
45424
45641
  migrated: false,
45425
45642
  entriesMigrated: 0,
@@ -45428,7 +45645,7 @@ async function migrateContextToKnowledge(directory, config3) {
45428
45645
  skippedReason: "sentinel-exists"
45429
45646
  };
45430
45647
  }
45431
- if (!existsSync18(contextPath)) {
45648
+ if (!existsSync20(contextPath)) {
45432
45649
  return {
45433
45650
  migrated: false,
45434
45651
  entriesMigrated: 0,
@@ -45437,7 +45654,7 @@ async function migrateContextToKnowledge(directory, config3) {
45437
45654
  skippedReason: "no-context-file"
45438
45655
  };
45439
45656
  }
45440
- const contextContent = await readFile7(contextPath, "utf-8");
45657
+ const contextContent = await readFile9(contextPath, "utf-8");
45441
45658
  if (contextContent.trim().length === 0) {
45442
45659
  return {
45443
45660
  migrated: false,
@@ -45613,8 +45830,8 @@ function truncateLesson(text) {
45613
45830
  return `${text.slice(0, 277)}...`;
45614
45831
  }
45615
45832
  function inferProjectName(directory) {
45616
- const packageJsonPath = path29.join(directory, "package.json");
45617
- if (existsSync18(packageJsonPath)) {
45833
+ const packageJsonPath = path30.join(directory, "package.json");
45834
+ if (existsSync20(packageJsonPath)) {
45618
45835
  try {
45619
45836
  const pkg = JSON.parse(readFileSync14(packageJsonPath, "utf-8"));
45620
45837
  if (pkg.name && typeof pkg.name === "string") {
@@ -45622,7 +45839,7 @@ function inferProjectName(directory) {
45622
45839
  }
45623
45840
  } catch {}
45624
45841
  }
45625
- return path29.basename(directory);
45842
+ return path30.basename(directory);
45626
45843
  }
45627
45844
  async function writeSentinel(sentinelPath, migrated, dropped) {
45628
45845
  const sentinel = {
@@ -45634,7 +45851,7 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
45634
45851
  schema_version: 1,
45635
45852
  migration_tool: "knowledge-migrator.ts"
45636
45853
  };
45637
- await mkdir7(path29.dirname(sentinelPath), { recursive: true });
45854
+ await mkdir8(path30.dirname(sentinelPath), { recursive: true });
45638
45855
  await writeFile8(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
45639
45856
  }
45640
45857
  var _internals19;
@@ -45656,7 +45873,7 @@ var init_knowledge_migrator = __esm(() => {
45656
45873
  });
45657
45874
 
45658
45875
  // src/commands/knowledge.ts
45659
- import { join as join27 } from "path";
45876
+ import { join as join28 } from "path";
45660
45877
  function resolveEntryByPrefix(entries, inputId) {
45661
45878
  const exact = entries.find((e) => e.id === inputId);
45662
45879
  if (exact)
@@ -45707,7 +45924,7 @@ async function handleKnowledgeRestoreCommand(directory, args) {
45707
45924
  return "Invalid entry ID. IDs must be 1-64 characters: letters, digits, hyphens, underscores only.";
45708
45925
  }
45709
45926
  try {
45710
- const quarantinePath = join27(directory, ".swarm", "knowledge-quarantined.jsonl");
45927
+ const quarantinePath = join28(directory, ".swarm", "knowledge-quarantined.jsonl");
45711
45928
  const entries = await readKnowledge(quarantinePath);
45712
45929
  const resolved = resolveEntryByPrefix(entries, inputId);
45713
45930
  if ("error" in resolved) {
@@ -46682,15 +46899,15 @@ var init_scoring = __esm(() => {
46682
46899
 
46683
46900
  // src/memory/local-jsonl-provider.ts
46684
46901
  import { randomUUID as randomUUID4 } from "crypto";
46685
- import { existsSync as existsSync19 } from "fs";
46902
+ import { existsSync as existsSync21 } from "fs";
46686
46903
  import {
46687
- appendFile as appendFile4,
46688
- mkdir as mkdir8,
46689
- readFile as readFile8,
46904
+ appendFile as appendFile5,
46905
+ mkdir as mkdir9,
46906
+ readFile as readFile10,
46690
46907
  rename as rename6,
46691
46908
  writeFile as writeFile9
46692
46909
  } from "fs/promises";
46693
- import * as path30 from "path";
46910
+ import * as path31 from "path";
46694
46911
 
46695
46912
  class LocalJsonlMemoryProvider {
46696
46913
  name = "local-jsonl";
@@ -46706,7 +46923,7 @@ class LocalJsonlMemoryProvider {
46706
46923
  pathFor(file3) {
46707
46924
  const storageDir = this.config.storageDir.replace(/^\.swarm[/\\]?/, "");
46708
46925
  const filename = file3 === "memories" ? "memories.jsonl" : file3 === "proposals" ? "proposals.jsonl" : "audit.jsonl";
46709
- return validateSwarmPath(this.rootDirectory, path30.join(storageDir, filename));
46926
+ return validateSwarmPath(this.rootDirectory, path31.join(storageDir, filename));
46710
46927
  }
46711
46928
  async initialize() {
46712
46929
  if (this.initialized)
@@ -47033,9 +47250,9 @@ function validateLoadedProposals(values, config3) {
47033
47250
  return { records, invalidCount };
47034
47251
  }
47035
47252
  async function readJsonl(filePath) {
47036
- if (!existsSync19(filePath))
47253
+ if (!existsSync21(filePath))
47037
47254
  return [];
47038
- const content = await readFile8(filePath, "utf-8");
47255
+ const content = await readFile10(filePath, "utf-8");
47039
47256
  const records = [];
47040
47257
  for (const line of content.split(`
47041
47258
  `)) {
@@ -47089,12 +47306,12 @@ function parseRecallUsageEvent(event) {
47089
47306
  }
47090
47307
  }
47091
47308
  async function appendJsonl(filePath, value) {
47092
- await mkdir8(path30.dirname(filePath), { recursive: true });
47093
- await appendFile4(filePath, `${JSON.stringify(value)}
47309
+ await mkdir9(path31.dirname(filePath), { recursive: true });
47310
+ await appendFile5(filePath, `${JSON.stringify(value)}
47094
47311
  `, "utf-8");
47095
47312
  }
47096
47313
  async function writeJsonlAtomic(filePath, values) {
47097
- await mkdir8(path30.dirname(filePath), { recursive: true });
47314
+ await mkdir9(path31.dirname(filePath), { recursive: true });
47098
47315
  const tmp = `${filePath}.tmp.${randomUUID4()}`;
47099
47316
  const content = values.map((value) => JSON.stringify(value)).join(`
47100
47317
  `) + (values.length > 0 ? `
@@ -47119,9 +47336,9 @@ var init_prompt_block = __esm(() => {
47119
47336
  });
47120
47337
 
47121
47338
  // src/memory/jsonl-migration.ts
47122
- import { existsSync as existsSync20 } from "fs";
47123
- import { copyFile, mkdir as mkdir9, readFile as readFile9, stat as stat3, writeFile as writeFile10 } from "fs/promises";
47124
- import * as path31 from "path";
47339
+ import { existsSync as existsSync22 } from "fs";
47340
+ import { copyFile, mkdir as mkdir10, readFile as readFile11, stat as stat3, writeFile as writeFile10 } from "fs/promises";
47341
+ import * as path32 from "path";
47125
47342
  function resolveMemoryStorageDir(rootDirectory, config3 = {}) {
47126
47343
  const resolved = resolveConfig(config3);
47127
47344
  const storageDir = resolved.storageDir.replace(/^\.swarm[/\\]?/, "");
@@ -47135,8 +47352,8 @@ function resolveSqliteDatabasePath(rootDirectory, config3 = {}) {
47135
47352
  async function readLegacyJsonl(rootDirectory, config3 = {}) {
47136
47353
  const resolved = resolveConfig(config3);
47137
47354
  const storageDir = resolveMemoryStorageDir(rootDirectory, resolved);
47138
- const memoryLoad = await readMemoryJsonl(path31.join(storageDir, "memories.jsonl"), resolved);
47139
- const proposalLoad = await readProposalJsonl(path31.join(storageDir, "proposals.jsonl"), resolved);
47355
+ const memoryLoad = await readMemoryJsonl(path32.join(storageDir, "memories.jsonl"), resolved);
47356
+ const proposalLoad = await readProposalJsonl(path32.join(storageDir, "proposals.jsonl"), resolved);
47140
47357
  return {
47141
47358
  memories: memoryLoad.records,
47142
47359
  proposals: proposalLoad.records,
@@ -47146,15 +47363,15 @@ async function readLegacyJsonl(rootDirectory, config3 = {}) {
47146
47363
  }
47147
47364
  async function backupLegacyJsonl(rootDirectory, config3 = {}) {
47148
47365
  const storageDir = resolveMemoryStorageDir(rootDirectory, config3);
47149
- const backupDir = path31.join(storageDir, "backups");
47150
- await mkdir9(backupDir, { recursive: true });
47366
+ const backupDir = path32.join(storageDir, "backups");
47367
+ await mkdir10(backupDir, { recursive: true });
47151
47368
  const results = [];
47152
47369
  for (const filename of ["memories.jsonl", "proposals.jsonl"]) {
47153
- const source = path31.join(storageDir, filename);
47154
- if (!existsSync20(source))
47370
+ const source = path32.join(storageDir, filename);
47371
+ if (!existsSync22(source))
47155
47372
  continue;
47156
- const backup = path31.join(backupDir, `${filename}.pre-sqlite-migration`);
47157
- if (existsSync20(backup)) {
47373
+ const backup = path32.join(backupDir, `${filename}.pre-sqlite-migration`);
47374
+ if (existsSync22(backup)) {
47158
47375
  results.push({ source, backup, created: false });
47159
47376
  continue;
47160
47377
  }
@@ -47164,27 +47381,27 @@ async function backupLegacyJsonl(rootDirectory, config3 = {}) {
47164
47381
  return results;
47165
47382
  }
47166
47383
  async function writeJsonlExport(rootDirectory, config3, memories, proposals) {
47167
- const exportDir = path31.join(resolveMemoryStorageDir(rootDirectory, config3), "export");
47168
- await mkdir9(exportDir, { recursive: true });
47169
- const memoriesPath = path31.join(exportDir, "memories.jsonl");
47170
- const proposalsPath = path31.join(exportDir, "proposals.jsonl");
47384
+ const exportDir = path32.join(resolveMemoryStorageDir(rootDirectory, config3), "export");
47385
+ await mkdir10(exportDir, { recursive: true });
47386
+ const memoriesPath = path32.join(exportDir, "memories.jsonl");
47387
+ const proposalsPath = path32.join(exportDir, "proposals.jsonl");
47171
47388
  await writeFile10(memoriesPath, toJsonl(memories), "utf-8");
47172
47389
  await writeFile10(proposalsPath, toJsonl(proposals), "utf-8");
47173
47390
  return { directory: exportDir, memoriesPath, proposalsPath };
47174
47391
  }
47175
47392
  async function writeMigrationReport(rootDirectory, report, config3 = {}) {
47176
- const reportPath = path31.join(resolveMemoryStorageDir(rootDirectory, config3), "migration-report.json");
47177
- await mkdir9(path31.dirname(reportPath), { recursive: true });
47393
+ const reportPath = path32.join(resolveMemoryStorageDir(rootDirectory, config3), "migration-report.json");
47394
+ await mkdir10(path32.dirname(reportPath), { recursive: true });
47178
47395
  await writeFile10(reportPath, `${JSON.stringify(report, null, 2)}
47179
47396
  `, "utf-8");
47180
47397
  return reportPath;
47181
47398
  }
47182
47399
  async function readMigrationReport(rootDirectory, config3 = {}) {
47183
- const reportPath = path31.join(resolveMemoryStorageDir(rootDirectory, config3), "migration-report.json");
47184
- if (!existsSync20(reportPath))
47400
+ const reportPath = path32.join(resolveMemoryStorageDir(rootDirectory, config3), "migration-report.json");
47401
+ if (!existsSync22(reportPath))
47185
47402
  return null;
47186
47403
  try {
47187
- return JSON.parse(await readFile9(reportPath, "utf-8"));
47404
+ return JSON.parse(await readFile11(reportPath, "utf-8"));
47188
47405
  } catch {
47189
47406
  return null;
47190
47407
  }
@@ -47193,15 +47410,15 @@ async function getLegacyJsonlFileStatus(rootDirectory, config3 = {}) {
47193
47410
  const storageDir = resolveMemoryStorageDir(rootDirectory, config3);
47194
47411
  const statuses = [];
47195
47412
  for (const file3 of ["memories.jsonl", "proposals.jsonl"]) {
47196
- const filePath = path31.join(storageDir, file3);
47413
+ const filePath = path32.join(storageDir, file3);
47197
47414
  let sizeBytes = 0;
47198
- if (existsSync20(filePath)) {
47415
+ if (existsSync22(filePath)) {
47199
47416
  sizeBytes = (await stat3(filePath)).size;
47200
47417
  }
47201
47418
  statuses.push({
47202
47419
  file: file3,
47203
47420
  path: filePath,
47204
- exists: existsSync20(filePath),
47421
+ exists: existsSync22(filePath),
47205
47422
  sizeBytes
47206
47423
  });
47207
47424
  }
@@ -47282,10 +47499,10 @@ async function readProposalJsonl(filePath, config3) {
47282
47499
  return { records, invalidRows, totalRows: rows.totalRows };
47283
47500
  }
47284
47501
  async function readJsonlRows(filePath) {
47285
- if (!existsSync20(filePath)) {
47502
+ if (!existsSync22(filePath)) {
47286
47503
  return { rows: [], invalidRows: [], totalRows: 0 };
47287
47504
  }
47288
- const content = await readFile9(filePath, "utf-8");
47505
+ const content = await readFile11(filePath, "utf-8");
47289
47506
  const rows = [];
47290
47507
  const invalidRows = [];
47291
47508
  let totalRows = 0;
@@ -47322,7 +47539,7 @@ var init_jsonl_migration = __esm(() => {
47322
47539
  import { randomUUID as randomUUID5 } from "crypto";
47323
47540
  import { mkdirSync as mkdirSync13 } from "fs";
47324
47541
  import { createRequire as createRequire2 } from "module";
47325
- import * as path32 from "path";
47542
+ import * as path33 from "path";
47326
47543
  function loadDatabaseCtor2() {
47327
47544
  if (_DatabaseCtor2)
47328
47545
  return _DatabaseCtor2;
@@ -47380,7 +47597,7 @@ class SQLiteMemoryProvider {
47380
47597
  if (this.initialized)
47381
47598
  return;
47382
47599
  const dbPath = this.databasePath();
47383
- mkdirSync13(path32.dirname(dbPath), { recursive: true });
47600
+ mkdirSync13(path33.dirname(dbPath), { recursive: true });
47384
47601
  const Db = loadDatabaseCtor2();
47385
47602
  this.db = new Db(dbPath);
47386
47603
  this.db.run("PRAGMA journal_mode = WAL;");
@@ -47645,8 +47862,8 @@ class SQLiteMemoryProvider {
47645
47862
  const row = this.requireDb().query("SELECT version, name FROM schema_migrations WHERE name = ? LIMIT 1").get(name);
47646
47863
  return Boolean(row);
47647
47864
  }
47648
- markMigration(version4, name) {
47649
- this.requireDb().run("INSERT OR IGNORE INTO schema_migrations (version, name) VALUES (?, ?)", [version4, name]);
47865
+ markMigration(version5, name) {
47866
+ this.requireDb().run("INSERT OR IGNORE INTO schema_migrations (version, name) VALUES (?, ?)", [version5, name]);
47650
47867
  }
47651
47868
  selectRecallCandidates(request, scopedRecords) {
47652
47869
  const ftsQuery = buildFtsQuery(request);
@@ -48266,9 +48483,9 @@ var init_gateway = __esm(() => {
48266
48483
  // src/memory/evaluation.ts
48267
48484
  import * as fs13 from "fs/promises";
48268
48485
  import * as os7 from "os";
48269
- import * as path33 from "path";
48486
+ import * as path34 from "path";
48270
48487
  async function evaluateMemoryRecallFixtures(options) {
48271
- const fixtureDirectory = path33.resolve(options.fixtureDirectory);
48488
+ const fixtureDirectory = path34.resolve(options.fixtureDirectory);
48272
48489
  const providers = options.providers ?? DEFAULT_PROVIDERS;
48273
48490
  const modes = options.modes ?? DEFAULT_MODES;
48274
48491
  const generatedAt = new Date().toISOString();
@@ -48277,7 +48494,7 @@ async function evaluateMemoryRecallFixtures(options) {
48277
48494
  for (const fixture of fixtures) {
48278
48495
  const materialized = materializeFixture(fixture);
48279
48496
  for (const providerName of providers) {
48280
- const tempRoot = await fs13.realpath(await fs13.mkdtemp(path33.join(os7.tmpdir(), "swarm-memory-eval-")));
48497
+ const tempRoot = await fs13.realpath(await fs13.mkdtemp(path34.join(os7.tmpdir(), "swarm-memory-eval-")));
48281
48498
  const provider = createEvaluationProvider(providerName, tempRoot);
48282
48499
  try {
48283
48500
  await provider.initialize?.();
@@ -48321,7 +48538,7 @@ async function loadRecallEvaluationFixtures(fixtureDirectory) {
48321
48538
  const files = entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort((a, b) => a.localeCompare(b));
48322
48539
  const fixtures = [];
48323
48540
  for (const file3 of files) {
48324
- const raw = await fs13.readFile(path33.join(fixtureDirectory, file3), "utf-8");
48541
+ const raw = await fs13.readFile(path34.join(fixtureDirectory, file3), "utf-8");
48325
48542
  fixtures.push(validateFixture(JSON.parse(raw), file3));
48326
48543
  }
48327
48544
  return fixtures;
@@ -48659,8 +48876,8 @@ var init_memory = __esm(() => {
48659
48876
  });
48660
48877
 
48661
48878
  // src/commands/memory.ts
48662
- import { existsSync as existsSync21 } from "fs";
48663
- import * as path34 from "path";
48879
+ import { existsSync as existsSync23 } from "fs";
48880
+ import * as path35 from "path";
48664
48881
  import { fileURLToPath as fileURLToPath2 } from "url";
48665
48882
  async function handleMemoryCommand(_directory, _args) {
48666
48883
  return [
@@ -48691,7 +48908,7 @@ async function handleMemoryStatusCommand(directory, _args) {
48691
48908
  `- Provider: \`${config3.provider}\``,
48692
48909
  `- Storage: \`${storageDir}\``,
48693
48910
  `- SQLite path: \`${sqlitePath}\``,
48694
- `- SQLite database exists: \`${existsSync21(sqlitePath)}\``,
48911
+ `- SQLite database exists: \`${existsSync23(sqlitePath)}\``,
48695
48912
  `- Automatic destructive cleanup: \`disabled\``,
48696
48913
  "",
48697
48914
  "### Legacy JSONL"
@@ -48930,7 +49147,7 @@ function resolveCommandMemoryConfig(directory) {
48930
49147
  }
48931
49148
  function parseEvaluateArgs(directory, args) {
48932
49149
  let json3 = false;
48933
- let fixtureDirectory = path34.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall");
49150
+ let fixtureDirectory = path35.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall");
48934
49151
  for (let i = 0;i < args.length; i++) {
48935
49152
  const arg = args[i];
48936
49153
  if (arg === "--json") {
@@ -48944,7 +49161,7 @@ function parseEvaluateArgs(directory, args) {
48944
49161
  error: "Usage: /swarm memory evaluate [--json] [--fixtures <directory>]"
48945
49162
  };
48946
49163
  }
48947
- fixtureDirectory = path34.resolve(directory, next);
49164
+ fixtureDirectory = path35.resolve(directory, next);
48948
49165
  i++;
48949
49166
  continue;
48950
49167
  }
@@ -48977,15 +49194,15 @@ function parseMaintenanceArgs(args, options) {
48977
49194
  return { limit, confirm };
48978
49195
  }
48979
49196
  function resolvePackageRootFromModule(modulePath) {
48980
- const moduleDir = path34.dirname(modulePath);
48981
- const leaf = path34.basename(moduleDir);
49197
+ const moduleDir = path35.dirname(modulePath);
49198
+ const leaf = path35.basename(moduleDir);
48982
49199
  if (leaf === "commands" || leaf === "cli") {
48983
- return path34.resolve(moduleDir, "..", "..");
49200
+ return path35.resolve(moduleDir, "..", "..");
48984
49201
  }
48985
49202
  if (leaf === "dist") {
48986
- return path34.resolve(moduleDir, "..");
49203
+ return path35.resolve(moduleDir, "..");
48987
49204
  }
48988
- return path34.resolve(moduleDir, "..");
49205
+ return path35.resolve(moduleDir, "..");
48989
49206
  }
48990
49207
  function formatMigrationResult(label, report) {
48991
49208
  if (!report) {
@@ -49104,7 +49321,7 @@ var PACKAGE_ROOT;
49104
49321
  var init_memory2 = __esm(() => {
49105
49322
  init_loader();
49106
49323
  init_memory();
49107
- PACKAGE_ROOT = path34.resolve(resolvePackageRootFromModule(fileURLToPath2(import.meta.url)));
49324
+ PACKAGE_ROOT = path35.resolve(resolvePackageRootFromModule(fileURLToPath2(import.meta.url)));
49108
49325
  });
49109
49326
 
49110
49327
  // src/services/plan-service.ts
@@ -49492,7 +49709,7 @@ var init_path_security = () => {};
49492
49709
 
49493
49710
  // src/tools/lint.ts
49494
49711
  import * as fs14 from "fs";
49495
- import * as path35 from "path";
49712
+ import * as path36 from "path";
49496
49713
  function validateArgs(args) {
49497
49714
  if (typeof args !== "object" || args === null)
49498
49715
  return false;
@@ -49503,9 +49720,9 @@ function validateArgs(args) {
49503
49720
  }
49504
49721
  function getLinterCommand(linter, mode, projectDir) {
49505
49722
  const isWindows = process.platform === "win32";
49506
- const binDir = path35.join(projectDir, "node_modules", ".bin");
49507
- const biomeBin = isWindows ? path35.join(binDir, "biome.EXE") : path35.join(binDir, "biome");
49508
- const eslintBin = isWindows ? path35.join(binDir, "eslint.cmd") : path35.join(binDir, "eslint");
49723
+ const binDir = path36.join(projectDir, "node_modules", ".bin");
49724
+ const biomeBin = isWindows ? path36.join(binDir, "biome.EXE") : path36.join(binDir, "biome");
49725
+ const eslintBin = isWindows ? path36.join(binDir, "eslint.cmd") : path36.join(binDir, "eslint");
49509
49726
  switch (linter) {
49510
49727
  case "biome":
49511
49728
  if (mode === "fix") {
@@ -49521,7 +49738,7 @@ function getLinterCommand(linter, mode, projectDir) {
49521
49738
  }
49522
49739
  function getAdditionalLinterCommand(linter, mode, cwd) {
49523
49740
  const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
49524
- const gradlew = fs14.existsSync(path35.join(cwd, gradlewName)) ? path35.join(cwd, gradlewName) : null;
49741
+ const gradlew = fs14.existsSync(path36.join(cwd, gradlewName)) ? path36.join(cwd, gradlewName) : null;
49525
49742
  switch (linter) {
49526
49743
  case "ruff":
49527
49744
  return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
@@ -49555,10 +49772,10 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
49555
49772
  }
49556
49773
  }
49557
49774
  function detectRuff(cwd) {
49558
- if (fs14.existsSync(path35.join(cwd, "ruff.toml")))
49775
+ if (fs14.existsSync(path36.join(cwd, "ruff.toml")))
49559
49776
  return isCommandAvailable("ruff");
49560
49777
  try {
49561
- const pyproject = path35.join(cwd, "pyproject.toml");
49778
+ const pyproject = path36.join(cwd, "pyproject.toml");
49562
49779
  if (fs14.existsSync(pyproject)) {
49563
49780
  const content = fs14.readFileSync(pyproject, "utf-8");
49564
49781
  if (content.includes("[tool.ruff]"))
@@ -49568,19 +49785,19 @@ function detectRuff(cwd) {
49568
49785
  return false;
49569
49786
  }
49570
49787
  function detectClippy(cwd) {
49571
- return fs14.existsSync(path35.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
49788
+ return fs14.existsSync(path36.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
49572
49789
  }
49573
49790
  function detectGolangciLint(cwd) {
49574
- return fs14.existsSync(path35.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
49791
+ return fs14.existsSync(path36.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
49575
49792
  }
49576
49793
  function detectCheckstyle(cwd) {
49577
- const hasMaven = fs14.existsSync(path35.join(cwd, "pom.xml"));
49578
- const hasGradle = fs14.existsSync(path35.join(cwd, "build.gradle")) || fs14.existsSync(path35.join(cwd, "build.gradle.kts"));
49579
- const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs14.existsSync(path35.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
49794
+ const hasMaven = fs14.existsSync(path36.join(cwd, "pom.xml"));
49795
+ const hasGradle = fs14.existsSync(path36.join(cwd, "build.gradle")) || fs14.existsSync(path36.join(cwd, "build.gradle.kts"));
49796
+ const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradle && (fs14.existsSync(path36.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
49580
49797
  return (hasMaven || hasGradle) && hasBinary;
49581
49798
  }
49582
49799
  function detectKtlint(cwd) {
49583
- const hasKotlin = fs14.existsSync(path35.join(cwd, "build.gradle.kts")) || fs14.existsSync(path35.join(cwd, "build.gradle")) || (() => {
49800
+ const hasKotlin = fs14.existsSync(path36.join(cwd, "build.gradle.kts")) || fs14.existsSync(path36.join(cwd, "build.gradle")) || (() => {
49584
49801
  try {
49585
49802
  return fs14.readdirSync(cwd).some((f) => f.endsWith(".kt") || f.endsWith(".kts"));
49586
49803
  } catch {
@@ -49599,11 +49816,11 @@ function detectDotnetFormat(cwd) {
49599
49816
  }
49600
49817
  }
49601
49818
  function detectCppcheck(cwd) {
49602
- if (fs14.existsSync(path35.join(cwd, "CMakeLists.txt"))) {
49819
+ if (fs14.existsSync(path36.join(cwd, "CMakeLists.txt"))) {
49603
49820
  return isCommandAvailable("cppcheck");
49604
49821
  }
49605
49822
  try {
49606
- const dirsToCheck = [cwd, path35.join(cwd, "src")];
49823
+ const dirsToCheck = [cwd, path36.join(cwd, "src")];
49607
49824
  const hasCpp = dirsToCheck.some((dir) => {
49608
49825
  try {
49609
49826
  return fs14.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
@@ -49617,13 +49834,13 @@ function detectCppcheck(cwd) {
49617
49834
  }
49618
49835
  }
49619
49836
  function detectSwiftlint(cwd) {
49620
- return fs14.existsSync(path35.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
49837
+ return fs14.existsSync(path36.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
49621
49838
  }
49622
49839
  function detectDartAnalyze(cwd) {
49623
- return fs14.existsSync(path35.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
49840
+ return fs14.existsSync(path36.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
49624
49841
  }
49625
49842
  function detectRubocop(cwd) {
49626
- return (fs14.existsSync(path35.join(cwd, "Gemfile")) || fs14.existsSync(path35.join(cwd, "gems.rb")) || fs14.existsSync(path35.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
49843
+ return (fs14.existsSync(path36.join(cwd, "Gemfile")) || fs14.existsSync(path36.join(cwd, "gems.rb")) || fs14.existsSync(path36.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
49627
49844
  }
49628
49845
  function detectAdditionalLinter(cwd) {
49629
49846
  if (detectRuff(cwd))
@@ -49651,10 +49868,10 @@ function detectAdditionalLinter(cwd) {
49651
49868
  function findBinInAncestors(startDir, binName) {
49652
49869
  let dir = startDir;
49653
49870
  while (true) {
49654
- const candidate = path35.join(dir, "node_modules", ".bin", binName);
49871
+ const candidate = path36.join(dir, "node_modules", ".bin", binName);
49655
49872
  if (fs14.existsSync(candidate))
49656
49873
  return candidate;
49657
- const parent = path35.dirname(dir);
49874
+ const parent = path36.dirname(dir);
49658
49875
  if (parent === dir)
49659
49876
  break;
49660
49877
  dir = parent;
@@ -49663,10 +49880,10 @@ function findBinInAncestors(startDir, binName) {
49663
49880
  }
49664
49881
  function findBinInEnvPath(binName) {
49665
49882
  const searchPath = process.env.PATH ?? "";
49666
- for (const dir of searchPath.split(path35.delimiter)) {
49883
+ for (const dir of searchPath.split(path36.delimiter)) {
49667
49884
  if (!dir)
49668
49885
  continue;
49669
- const candidate = path35.join(dir, binName);
49886
+ const candidate = path36.join(dir, binName);
49670
49887
  if (fs14.existsSync(candidate))
49671
49888
  return candidate;
49672
49889
  }
@@ -49679,13 +49896,13 @@ async function detectAvailableLinter(directory) {
49679
49896
  return null;
49680
49897
  const projectDir = directory;
49681
49898
  const isWindows = process.platform === "win32";
49682
- const biomeBin = isWindows ? path35.join(projectDir, "node_modules", ".bin", "biome.EXE") : path35.join(projectDir, "node_modules", ".bin", "biome");
49683
- const eslintBin = isWindows ? path35.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path35.join(projectDir, "node_modules", ".bin", "eslint");
49899
+ const biomeBin = isWindows ? path36.join(projectDir, "node_modules", ".bin", "biome.EXE") : path36.join(projectDir, "node_modules", ".bin", "biome");
49900
+ const eslintBin = isWindows ? path36.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path36.join(projectDir, "node_modules", ".bin", "eslint");
49684
49901
  const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
49685
49902
  if (localResult)
49686
49903
  return localResult;
49687
- const biomeAncestor = findBinInAncestors(path35.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
49688
- const eslintAncestor = findBinInAncestors(path35.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
49904
+ const biomeAncestor = findBinInAncestors(path36.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
49905
+ const eslintAncestor = findBinInAncestors(path36.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
49689
49906
  if (biomeAncestor || eslintAncestor) {
49690
49907
  return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
49691
49908
  }
@@ -49908,7 +50125,7 @@ For Rust: rustup component add clippy`
49908
50125
 
49909
50126
  // src/tools/secretscan.ts
49910
50127
  import * as fs15 from "fs";
49911
- import * as path36 from "path";
50128
+ import * as path37 from "path";
49912
50129
  function calculateShannonEntropy(str) {
49913
50130
  if (str.length === 0)
49914
50131
  return 0;
@@ -49956,7 +50173,7 @@ function isGlobOrPathPattern(pattern) {
49956
50173
  return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
49957
50174
  }
49958
50175
  function loadSecretScanIgnore(scanDir) {
49959
- const ignorePath = path36.join(scanDir, ".secretscanignore");
50176
+ const ignorePath = path37.join(scanDir, ".secretscanignore");
49960
50177
  try {
49961
50178
  if (!fs15.existsSync(ignorePath))
49962
50179
  return [];
@@ -49979,7 +50196,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
49979
50196
  if (exactNames.has(entry))
49980
50197
  return true;
49981
50198
  for (const pattern of globPatterns) {
49982
- if (path36.matchesGlob(relPath, pattern))
50199
+ if (path37.matchesGlob(relPath, pattern))
49983
50200
  return true;
49984
50201
  }
49985
50202
  return false;
@@ -50000,7 +50217,7 @@ function validateDirectoryInput(dir) {
50000
50217
  return null;
50001
50218
  }
50002
50219
  function isBinaryFile(filePath, buffer) {
50003
- const ext = path36.extname(filePath).toLowerCase();
50220
+ const ext = path37.extname(filePath).toLowerCase();
50004
50221
  if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
50005
50222
  return true;
50006
50223
  }
@@ -50136,9 +50353,9 @@ function isSymlinkLoop(realPath, visited) {
50136
50353
  return false;
50137
50354
  }
50138
50355
  function isPathWithinScope(realPath, scanDir) {
50139
- const resolvedScanDir = path36.resolve(scanDir);
50140
- const resolvedRealPath = path36.resolve(realPath);
50141
- return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path36.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
50356
+ const resolvedScanDir = path37.resolve(scanDir);
50357
+ const resolvedRealPath = path37.resolve(realPath);
50358
+ return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path37.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
50142
50359
  }
50143
50360
  function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
50144
50361
  skippedDirs: 0,
@@ -50164,8 +50381,8 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
50164
50381
  return a.localeCompare(b);
50165
50382
  });
50166
50383
  for (const entry of entries) {
50167
- const fullPath = path36.join(dir, entry);
50168
- const relPath = path36.relative(scanDir, fullPath).replace(/\\/g, "/");
50384
+ const fullPath = path37.join(dir, entry);
50385
+ const relPath = path37.relative(scanDir, fullPath).replace(/\\/g, "/");
50169
50386
  if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
50170
50387
  stats.skippedDirs++;
50171
50388
  continue;
@@ -50200,7 +50417,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
50200
50417
  const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
50201
50418
  files.push(...subFiles);
50202
50419
  } else if (lstat.isFile()) {
50203
- const ext = path36.extname(fullPath).toLowerCase();
50420
+ const ext = path37.extname(fullPath).toLowerCase();
50204
50421
  if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
50205
50422
  files.push(fullPath);
50206
50423
  } else {
@@ -50460,7 +50677,7 @@ var init_secretscan = __esm(() => {
50460
50677
  }
50461
50678
  }
50462
50679
  try {
50463
- const _scanDirRaw = path36.resolve(directory);
50680
+ const _scanDirRaw = path37.resolve(directory);
50464
50681
  const scanDir = (() => {
50465
50682
  try {
50466
50683
  return fs15.realpathSync(_scanDirRaw);
@@ -50607,7 +50824,7 @@ var init_secretscan = __esm(() => {
50607
50824
 
50608
50825
  // src/lang/default-backend.ts
50609
50826
  import * as fs16 from "fs";
50610
- import * as path37 from "path";
50827
+ import * as path38 from "path";
50611
50828
  function detectFileExists(dir, pattern) {
50612
50829
  if (pattern.includes("*") || pattern.includes("?")) {
50613
50830
  try {
@@ -50619,7 +50836,7 @@ function detectFileExists(dir, pattern) {
50619
50836
  }
50620
50837
  }
50621
50838
  try {
50622
- fs16.accessSync(path37.join(dir, pattern));
50839
+ fs16.accessSync(path38.join(dir, pattern));
50623
50840
  return true;
50624
50841
  } catch {
50625
50842
  return false;
@@ -50747,8 +50964,8 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
50747
50964
  return ["mvn", "test"];
50748
50965
  case "gradle": {
50749
50966
  const isWindows = process.platform === "win32";
50750
- const hasGradlewBat = fs16.existsSync(path37.join(dir, "gradlew.bat"));
50751
- const hasGradlew = fs16.existsSync(path37.join(dir, "gradlew"));
50967
+ const hasGradlewBat = fs16.existsSync(path38.join(dir, "gradlew.bat"));
50968
+ const hasGradlew = fs16.existsSync(path38.join(dir, "gradlew"));
50752
50969
  if (hasGradlewBat && isWindows)
50753
50970
  return ["gradlew.bat", "test"];
50754
50971
  if (hasGradlew)
@@ -50765,7 +50982,7 @@ function defaultBuildTestCommand(profile, framework, files, dir = ".", opts = {}
50765
50982
  "cmake-build-release",
50766
50983
  "out"
50767
50984
  ];
50768
- const actualBuildDir = buildDirCandidates.find((d) => fs16.existsSync(path37.join(dir, d, "CMakeCache.txt"))) ?? "build";
50985
+ const actualBuildDir = buildDirCandidates.find((d) => fs16.existsSync(path38.join(dir, d, "CMakeCache.txt"))) ?? "build";
50769
50986
  return ["ctest", "--test-dir", actualBuildDir];
50770
50987
  }
50771
50988
  case "swift-test":
@@ -51052,17 +51269,17 @@ async function defaultSelectBuildCommand(profile, dir) {
51052
51269
  return null;
51053
51270
  }
51054
51271
  async function defaultTestFilesFor(profile, sourceFile, dir) {
51055
- const ext = path37.extname(sourceFile);
51272
+ const ext = path38.extname(sourceFile);
51056
51273
  if (!profile.extensions.includes(ext))
51057
51274
  return [];
51058
- const base = path37.basename(sourceFile, ext);
51059
- const rel = path37.relative(dir, sourceFile);
51060
- const relDir = path37.dirname(rel);
51275
+ const base = path38.basename(sourceFile, ext);
51276
+ const rel = path38.relative(dir, sourceFile);
51277
+ const relDir = path38.dirname(rel);
51061
51278
  const stripSrc = relDir.replace(/^src(\/|\\)/, "");
51062
51279
  const candidates = new Set;
51063
51280
  for (const tDir of ["tests", "test", "__tests__", "spec"]) {
51064
51281
  for (const suffix of ["", "_test", ".test", "_spec", ".spec"]) {
51065
- candidates.add(path37.join(dir, tDir, stripSrc, `${base}${suffix}${ext}`));
51282
+ candidates.add(path38.join(dir, tDir, stripSrc, `${base}${suffix}${ext}`));
51066
51283
  }
51067
51284
  }
51068
51285
  const existing = [];
@@ -51103,7 +51320,7 @@ var init_default_backend = __esm(() => {
51103
51320
 
51104
51321
  // src/lang/backends/go.ts
51105
51322
  import * as fs17 from "fs";
51106
- import * as path38 from "path";
51323
+ import * as path39 from "path";
51107
51324
  function extractImports(_sourceFile, source) {
51108
51325
  const out = new Set;
51109
51326
  IMPORT_REGEX_SINGLE.lastIndex = 0;
@@ -51129,7 +51346,7 @@ function extractImports(_sourceFile, source) {
51129
51346
  async function selectFramework(dir) {
51130
51347
  let content;
51131
51348
  try {
51132
- content = fs17.readFileSync(path38.join(dir, "go.mod"), "utf-8");
51349
+ content = fs17.readFileSync(path39.join(dir, "go.mod"), "utf-8");
51133
51350
  } catch {
51134
51351
  return null;
51135
51352
  }
@@ -51150,16 +51367,16 @@ async function selectFramework(dir) {
51150
51367
  async function selectEntryPoints(dir) {
51151
51368
  const points = [];
51152
51369
  try {
51153
- fs17.accessSync(path38.join(dir, "main.go"));
51370
+ fs17.accessSync(path39.join(dir, "main.go"));
51154
51371
  points.push("main.go");
51155
51372
  } catch {}
51156
51373
  try {
51157
- const cmdDir = path38.join(dir, "cmd");
51374
+ const cmdDir = path39.join(dir, "cmd");
51158
51375
  const subdirs = fs17.readdirSync(cmdDir, { withFileTypes: true }).filter((d) => d.isDirectory());
51159
51376
  for (const sub of subdirs) {
51160
- const main = path38.join("cmd", sub.name, "main.go");
51377
+ const main = path39.join("cmd", sub.name, "main.go");
51161
51378
  try {
51162
- fs17.accessSync(path38.join(dir, main));
51379
+ fs17.accessSync(path39.join(dir, main));
51163
51380
  points.push(main);
51164
51381
  } catch {}
51165
51382
  }
@@ -51190,7 +51407,7 @@ var init_go = __esm(() => {
51190
51407
 
51191
51408
  // src/lang/backends/python.ts
51192
51409
  import * as fs18 from "fs";
51193
- import * as path39 from "path";
51410
+ import * as path40 from "path";
51194
51411
  function parseImportTargets(rawTargets) {
51195
51412
  const cleaned = rawTargets.replace(/[()]/g, "").split(`
51196
51413
  `).map((line) => line.replace(/#.*$/, "").replace(/\\\s*$/, "")).join(" ");
@@ -51250,7 +51467,7 @@ async function selectFramework2(dir) {
51250
51467
  ];
51251
51468
  for (const candidate of ["pyproject.toml", "requirements.txt", "setup.py"]) {
51252
51469
  try {
51253
- const content = fs18.readFileSync(path39.join(dir, candidate), "utf-8");
51470
+ const content = fs18.readFileSync(path40.join(dir, candidate), "utf-8");
51254
51471
  const lower = content.toLowerCase();
51255
51472
  for (const [pkg, name] of candidates) {
51256
51473
  if (lower.includes(pkg)) {
@@ -51264,7 +51481,7 @@ async function selectFramework2(dir) {
51264
51481
  async function selectEntryPoints2(dir) {
51265
51482
  const points = new Set;
51266
51483
  try {
51267
- const content = fs18.readFileSync(path39.join(dir, "pyproject.toml"), "utf-8");
51484
+ const content = fs18.readFileSync(path40.join(dir, "pyproject.toml"), "utf-8");
51268
51485
  const scriptsBlock = content.match(/\[project\.scripts\][\s\S]*?(?=\n\[|$)/);
51269
51486
  if (scriptsBlock) {
51270
51487
  for (const line of scriptsBlock[0].split(`
@@ -51279,7 +51496,7 @@ async function selectEntryPoints2(dir) {
51279
51496
  } catch {}
51280
51497
  for (const name of ["manage.py", "main.py", "app.py", "__main__.py"]) {
51281
51498
  try {
51282
- fs18.accessSync(path39.join(dir, name));
51499
+ fs18.accessSync(path40.join(dir, name));
51283
51500
  points.add(name);
51284
51501
  } catch {}
51285
51502
  }
@@ -51308,10 +51525,23 @@ var init_python = __esm(() => {
51308
51525
 
51309
51526
  // src/test-impact/analyzer.ts
51310
51527
  import fs19 from "fs";
51311
- import path40 from "path";
51528
+ import path41 from "path";
51312
51529
  function normalizePath(p) {
51313
51530
  return p.replace(/\\/g, "/");
51314
51531
  }
51532
+ function sharedTrailingSegments(a, b) {
51533
+ const aParts = normalizePath(a).split("/").filter(Boolean);
51534
+ const bParts = normalizePath(b).split("/").filter(Boolean);
51535
+ let i = aParts.length - 1;
51536
+ let j = bParts.length - 1;
51537
+ let shared = 0;
51538
+ while (i >= 0 && j >= 0 && aParts[i] === bParts[j]) {
51539
+ shared++;
51540
+ i--;
51541
+ j--;
51542
+ }
51543
+ return shared;
51544
+ }
51315
51545
  function isCacheStale(impactMap, generatedAtMs) {
51316
51546
  for (const sourcePath of Object.keys(impactMap)) {
51317
51547
  try {
@@ -51329,8 +51559,8 @@ function resolveRelativeImport(fromDir, importPath) {
51329
51559
  if (!importPath.startsWith(".")) {
51330
51560
  return null;
51331
51561
  }
51332
- const resolved = path40.resolve(fromDir, importPath);
51333
- if (path40.extname(resolved)) {
51562
+ const resolved = path41.resolve(fromDir, importPath);
51563
+ if (path41.extname(resolved)) {
51334
51564
  if (fs19.existsSync(resolved) && fs19.statSync(resolved).isFile()) {
51335
51565
  return normalizePath(resolved);
51336
51566
  }
@@ -51350,20 +51580,20 @@ function resolvePythonImport(fromDir, module) {
51350
51580
  const leadingDots = module.match(/^\.+/)?.[0].length ?? 0;
51351
51581
  let baseDir = fromDir;
51352
51582
  for (let i = 1;i < leadingDots; i++) {
51353
- baseDir = path40.dirname(baseDir);
51583
+ baseDir = path41.dirname(baseDir);
51354
51584
  }
51355
51585
  const rest = module.slice(leadingDots);
51356
51586
  if (rest.length === 0) {
51357
- const initPath = path40.join(baseDir, "__init__.py");
51587
+ const initPath = path41.join(baseDir, "__init__.py");
51358
51588
  if (fs19.existsSync(initPath) && fs19.statSync(initPath).isFile()) {
51359
51589
  return normalizePath(initPath);
51360
51590
  }
51361
51591
  return null;
51362
51592
  }
51363
- const subpath = rest.replace(/\./g, path40.sep);
51593
+ const subpath = rest.replace(/\./g, path41.sep);
51364
51594
  const candidates = [
51365
- `${path40.join(baseDir, subpath)}.py`,
51366
- path40.join(baseDir, subpath, "__init__.py")
51595
+ `${path41.join(baseDir, subpath)}.py`,
51596
+ path41.join(baseDir, subpath, "__init__.py")
51367
51597
  ];
51368
51598
  for (const c of candidates) {
51369
51599
  if (fs19.existsSync(c) && fs19.statSync(c).isFile())
@@ -51372,7 +51602,7 @@ function resolvePythonImport(fromDir, module) {
51372
51602
  return null;
51373
51603
  }
51374
51604
  function findGoModule(fromDir) {
51375
- const resolved = path40.resolve(fromDir);
51605
+ const resolved = path41.resolve(fromDir);
51376
51606
  let cur = resolved;
51377
51607
  const walked = [];
51378
51608
  for (let i = 0;i < 16; i++) {
@@ -51384,7 +51614,7 @@ function findGoModule(fromDir) {
51384
51614
  }
51385
51615
  walked.push(cur);
51386
51616
  try {
51387
- const goMod = path40.join(cur, "go.mod");
51617
+ const goMod = path41.join(cur, "go.mod");
51388
51618
  const content = fs19.readFileSync(goMod, "utf-8");
51389
51619
  const moduleMatch = content.match(/^\s*module\s+"?([^"\s/]+(?:\/[^"\s]+)*)"?/m);
51390
51620
  if (moduleMatch) {
@@ -51395,10 +51625,10 @@ function findGoModule(fromDir) {
51395
51625
  }
51396
51626
  } catch {}
51397
51627
  try {
51398
- fs19.accessSync(path40.join(cur, ".git"));
51628
+ fs19.accessSync(path41.join(cur, ".git"));
51399
51629
  break;
51400
51630
  } catch {}
51401
- const parent = path40.dirname(cur);
51631
+ const parent = path41.dirname(cur);
51402
51632
  if (parent === cur)
51403
51633
  break;
51404
51634
  cur = parent;
@@ -51410,12 +51640,12 @@ function findGoModule(fromDir) {
51410
51640
  function resolveGoImport(fromDir, importPath) {
51411
51641
  let dir = null;
51412
51642
  if (importPath.startsWith(".")) {
51413
- dir = path40.resolve(fromDir, importPath);
51643
+ dir = path41.resolve(fromDir, importPath);
51414
51644
  } else {
51415
51645
  const mod = findGoModule(fromDir);
51416
51646
  if (mod && (importPath === mod.modulePath || importPath.startsWith(`${mod.modulePath}/`))) {
51417
51647
  const subpath = importPath.slice(mod.modulePath.length);
51418
- dir = path40.join(mod.moduleRoot, subpath);
51648
+ dir = path41.join(mod.moduleRoot, subpath);
51419
51649
  }
51420
51650
  }
51421
51651
  if (dir === null)
@@ -51423,7 +51653,7 @@ function resolveGoImport(fromDir, importPath) {
51423
51653
  if (!fs19.existsSync(dir) || !fs19.statSync(dir).isDirectory())
51424
51654
  return [];
51425
51655
  try {
51426
- return fs19.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath(path40.join(dir, f)));
51656
+ return fs19.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath(path41.join(dir, f)));
51427
51657
  } catch {
51428
51658
  return [];
51429
51659
  }
@@ -51462,15 +51692,15 @@ function findTestFilesSync(cwd) {
51462
51692
  for (const entry of entries) {
51463
51693
  if (entry.isDirectory()) {
51464
51694
  if (!skipDirs.has(entry.name)) {
51465
- walk(path40.join(dir, entry.name), visitedInodes);
51695
+ walk(path41.join(dir, entry.name), visitedInodes);
51466
51696
  }
51467
51697
  } else if (entry.isFile()) {
51468
51698
  const name = entry.name;
51469
51699
  const isTsTest = /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name);
51470
- const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${path40.sep}tests${path40.sep}`) && name.endsWith(".py");
51700
+ const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${path41.sep}tests${path41.sep}`) && name.endsWith(".py");
51471
51701
  const isGoTest = /.+_test\.go$/.test(name);
51472
51702
  if (isTsTest || isPyTest || isGoTest) {
51473
- testFiles.push(normalizePath(path40.join(dir, entry.name)));
51703
+ testFiles.push(normalizePath(path41.join(dir, entry.name)));
51474
51704
  }
51475
51705
  }
51476
51706
  }
@@ -51495,8 +51725,8 @@ function extractImports3(content) {
51495
51725
  ];
51496
51726
  }
51497
51727
  function addImpactEdgesForTestFile(testFile, content, impactMap) {
51498
- const ext = path40.extname(testFile).toLowerCase();
51499
- const testDir = path40.dirname(testFile);
51728
+ const ext = path41.extname(testFile).toLowerCase();
51729
+ const testDir = path41.dirname(testFile);
51500
51730
  function addEdge(source) {
51501
51731
  if (!impactMap[source])
51502
51732
  impactMap[source] = [];
@@ -51555,7 +51785,7 @@ async function buildImpactMap(cwd) {
51555
51785
  return impactMap;
51556
51786
  }
51557
51787
  async function loadImpactMap(cwd, options) {
51558
- const cachePath = path40.join(cwd, ".swarm", "cache", "impact-map.json");
51788
+ const cachePath = path41.join(cwd, ".swarm", "cache", "impact-map.json");
51559
51789
  if (fs19.existsSync(cachePath)) {
51560
51790
  try {
51561
51791
  const content = fs19.readFileSync(cachePath, "utf-8");
@@ -51588,12 +51818,12 @@ async function loadImpactMap(cwd, options) {
51588
51818
  return _internals25.buildImpactMap(cwd);
51589
51819
  }
51590
51820
  async function saveImpactMap(cwd, impactMap) {
51591
- if (!path40.isAbsolute(cwd)) {
51821
+ if (!path41.isAbsolute(cwd)) {
51592
51822
  throw new Error(`saveImpactMap requires an absolute project root path, got: "${cwd}"`);
51593
51823
  }
51594
51824
  _internals25.validateProjectRoot(cwd);
51595
- const cacheDir2 = path40.join(cwd, ".swarm", "cache");
51596
- const cachePath = path40.join(cacheDir2, "impact-map.json");
51825
+ const cacheDir2 = path41.join(cwd, ".swarm", "cache");
51826
+ const cachePath = path41.join(cacheDir2, "impact-map.json");
51597
51827
  if (!fs19.existsSync(cacheDir2)) {
51598
51828
  fs19.mkdirSync(cacheDir2, { recursive: true });
51599
51829
  }
@@ -51625,7 +51855,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
51625
51855
  budgetExceeded = true;
51626
51856
  break;
51627
51857
  }
51628
- const normalizedChanged = normalizePath(path40.resolve(changedFile));
51858
+ const normalizedChanged = normalizePath(path41.resolve(changedFile));
51629
51859
  const tests = impactMap[normalizedChanged];
51630
51860
  if (tests && tests.length > 0) {
51631
51861
  for (const test of tests) {
@@ -51639,25 +51869,43 @@ async function analyzeImpact(changedFiles, cwd, budget) {
51639
51869
  if (budgetExceeded)
51640
51870
  break;
51641
51871
  } else {
51642
- let found = false;
51643
- for (const [sourcePath, tests2] of Object.entries(impactMap)) {
51872
+ const changedDir = normalizePath(path41.dirname(normalizedChanged));
51873
+ const changedInputDir = normalizePath(path41.dirname(changedFile));
51874
+ const suffixMatches = Object.entries(impactMap).filter(([sourcePath]) => {
51875
+ return sourcePath.endsWith(changedFile) || changedFile.endsWith(sourcePath) || sourcePath.endsWith(normalizedChanged) || normalizedChanged.endsWith(sourcePath);
51876
+ }).sort(([sourceA], [sourceB]) => {
51877
+ const sourceDirA = normalizePath(path41.dirname(sourceA));
51878
+ const sourceDirB = normalizePath(path41.dirname(sourceB));
51879
+ const exactA = sourceDirA === changedDir || changedInputDir !== "." && (sourceDirA === changedInputDir || sourceDirA.endsWith(`/${changedInputDir}`));
51880
+ const exactB = sourceDirB === changedDir || changedInputDir !== "." && (sourceDirB === changedInputDir || sourceDirB.endsWith(`/${changedInputDir}`));
51881
+ if (exactA !== exactB)
51882
+ return exactA ? -1 : 1;
51883
+ const sharedA = Math.max(sharedTrailingSegments(sourceDirA, changedDir), changedInputDir === "." ? 0 : sharedTrailingSegments(sourceDirA, changedInputDir));
51884
+ const sharedB = Math.max(sharedTrailingSegments(sourceDirB, changedDir), changedInputDir === "." ? 0 : sharedTrailingSegments(sourceDirB, changedInputDir));
51885
+ const nearestA = sharedA > 0;
51886
+ const nearestB = sharedB > 0;
51887
+ if (nearestA !== nearestB)
51888
+ return nearestA ? -1 : 1;
51889
+ if (sharedA !== sharedB)
51890
+ return sharedB - sharedA;
51891
+ return sourceA.localeCompare(sourceB);
51892
+ });
51893
+ const found = suffixMatches.length > 0;
51894
+ for (const [, tests2] of suffixMatches) {
51644
51895
  if (budget !== undefined && visitedCount >= budget) {
51645
51896
  budgetExceeded = true;
51646
51897
  break;
51647
51898
  }
51648
- if (sourcePath.endsWith(changedFile) || changedFile.endsWith(sourcePath)) {
51649
- for (const test of tests2) {
51650
- if (budget !== undefined && visitedCount >= budget) {
51651
- budgetExceeded = true;
51652
- break;
51653
- }
51654
- impactedTestsSet.add(test);
51655
- visitedCount++;
51656
- }
51657
- if (budgetExceeded)
51899
+ for (const test of tests2) {
51900
+ if (budget !== undefined && visitedCount >= budget) {
51901
+ budgetExceeded = true;
51658
51902
  break;
51659
- found = true;
51903
+ }
51904
+ impactedTestsSet.add(test);
51905
+ visitedCount++;
51660
51906
  }
51907
+ if (budgetExceeded)
51908
+ break;
51661
51909
  }
51662
51910
  if (budgetExceeded)
51663
51911
  break;
@@ -51918,15 +52166,15 @@ var FLAKY_THRESHOLD = 0.3, MIN_RUNS_FOR_QUARANTINE = 5, MAX_HISTORY_RUNS = 20;
51918
52166
 
51919
52167
  // src/test-impact/history-store.ts
51920
52168
  import fs20 from "fs";
51921
- import path41 from "path";
52169
+ import path42 from "path";
51922
52170
  function getHistoryPath(workingDir) {
51923
52171
  if (!workingDir) {
51924
52172
  throw new Error("getHistoryPath requires a working directory \u2014 project root must be provided by the caller");
51925
52173
  }
51926
- if (!path41.isAbsolute(workingDir)) {
52174
+ if (!path42.isAbsolute(workingDir)) {
51927
52175
  throw new Error(`getHistoryPath requires an absolute project root path, got: "${workingDir}"`);
51928
52176
  }
51929
- return path41.join(workingDir, ".swarm", "cache", "test-history.jsonl");
52177
+ return path42.join(workingDir, ".swarm", "cache", "test-history.jsonl");
51930
52178
  }
51931
52179
  function sanitizeErrorMessage(errorMessage) {
51932
52180
  if (errorMessage === undefined) {
@@ -52013,7 +52261,7 @@ function batchAppendTestRuns(records, workingDir) {
52013
52261
  }
52014
52262
  }
52015
52263
  const historyPath = getHistoryPath(workingDir);
52016
- const historyDir = path41.dirname(historyPath);
52264
+ const historyDir = path42.dirname(historyPath);
52017
52265
  _internals26.validateProjectRoot(workingDir);
52018
52266
  if (!fs20.existsSync(historyDir)) {
52019
52267
  fs20.mkdirSync(historyDir, { recursive: true });
@@ -52109,7 +52357,7 @@ var init_history_store = __esm(() => {
52109
52357
 
52110
52358
  // src/tools/resolve-working-directory.ts
52111
52359
  import * as fs21 from "fs";
52112
- import * as path42 from "path";
52360
+ import * as path43 from "path";
52113
52361
  function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
52114
52362
  if (workingDirectory == null || workingDirectory === "") {
52115
52363
  return { success: true, directory: fallbackDirectory };
@@ -52129,15 +52377,15 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
52129
52377
  };
52130
52378
  }
52131
52379
  }
52132
- const normalizedDir = path42.normalize(workingDirectory);
52133
- const pathParts = normalizedDir.split(path42.sep);
52380
+ const normalizedDir = path43.normalize(workingDirectory);
52381
+ const pathParts = normalizedDir.split(path43.sep);
52134
52382
  if (pathParts.includes("..")) {
52135
52383
  return {
52136
52384
  success: false,
52137
52385
  message: "Invalid working_directory: path traversal sequences (..) are not allowed"
52138
52386
  };
52139
52387
  }
52140
- const resolvedDir = path42.resolve(normalizedDir);
52388
+ const resolvedDir = path43.resolve(normalizedDir);
52141
52389
  let statResult;
52142
52390
  try {
52143
52391
  statResult = fs21.statSync(resolvedDir);
@@ -52153,7 +52401,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
52153
52401
  message: `Invalid working_directory: path "${resolvedDir}" is not a directory`
52154
52402
  };
52155
52403
  }
52156
- const resolvedFallback = path42.resolve(fallbackDirectory);
52404
+ const resolvedFallback = path43.resolve(fallbackDirectory);
52157
52405
  let fallbackExists = false;
52158
52406
  try {
52159
52407
  fs21.statSync(resolvedFallback);
@@ -52163,7 +52411,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
52163
52411
  }
52164
52412
  if (workingDirectory != null && workingDirectory !== "") {
52165
52413
  if (fallbackExists) {
52166
- const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path42.sep);
52414
+ const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path43.sep);
52167
52415
  if (isSubdirectory) {
52168
52416
  return {
52169
52417
  success: false,
@@ -52218,10 +52466,10 @@ var init_registry_backend = __esm(() => {
52218
52466
 
52219
52467
  // src/lang/backends/typescript.ts
52220
52468
  import * as fs22 from "fs";
52221
- import * as path43 from "path";
52469
+ import * as path44 from "path";
52222
52470
  function readPackageJsonRaw(dir) {
52223
52471
  try {
52224
- const content = fs22.readFileSync(path43.join(dir, "package.json"), "utf-8");
52472
+ const content = fs22.readFileSync(path44.join(dir, "package.json"), "utf-8");
52225
52473
  return JSON.parse(content);
52226
52474
  } catch {
52227
52475
  return null;
@@ -52441,7 +52689,7 @@ __export(exports_dispatch, {
52441
52689
  _internals: () => _internals28
52442
52690
  });
52443
52691
  import * as fs23 from "fs";
52444
- import * as path44 from "path";
52692
+ import * as path45 from "path";
52445
52693
  function safeReaddirSet(dir) {
52446
52694
  try {
52447
52695
  return new Set(fs23.readdirSync(dir));
@@ -52458,14 +52706,14 @@ function manifestHash(dir) {
52458
52706
  if (!entries.has(name))
52459
52707
  continue;
52460
52708
  try {
52461
- const stat4 = fs23.statSync(path44.join(dir, name));
52709
+ const stat4 = fs23.statSync(path45.join(dir, name));
52462
52710
  parts.push(`${name}:${stat4.size}:${stat4.mtimeMs}:${stat4.ino}`);
52463
52711
  } catch {}
52464
52712
  }
52465
52713
  return parts.join("|");
52466
52714
  }
52467
52715
  function findManifestRoot(start) {
52468
- const resolved = path44.resolve(start);
52716
+ const resolved = path45.resolve(start);
52469
52717
  const cached3 = manifestRootCache.get(resolved);
52470
52718
  if (cached3 !== undefined)
52471
52719
  return cached3;
@@ -52484,7 +52732,7 @@ function findManifestRoot(start) {
52484
52732
  return cur;
52485
52733
  }
52486
52734
  }
52487
- const parent = path44.dirname(cur);
52735
+ const parent = path45.dirname(cur);
52488
52736
  if (parent === cur)
52489
52737
  break;
52490
52738
  cur = parent;
@@ -52594,13 +52842,13 @@ var init_dispatch = __esm(() => {
52594
52842
 
52595
52843
  // src/tools/test-runner.ts
52596
52844
  import * as fs24 from "fs";
52597
- import * as path45 from "path";
52845
+ import * as path46 from "path";
52598
52846
  async function estimateFanOut(sourceFiles, cwd) {
52599
52847
  try {
52600
52848
  const impactMap = await loadImpactMap(cwd, { skipRebuild: true });
52601
52849
  const uniqueTestFiles = new Set;
52602
52850
  for (const sourceFile of sourceFiles) {
52603
- const resolvedPath = path45.resolve(cwd, sourceFile);
52851
+ const resolvedPath = path46.resolve(cwd, sourceFile);
52604
52852
  const normalizedPath = resolvedPath.replace(/\\/g, "/");
52605
52853
  const testFiles = impactMap[normalizedPath];
52606
52854
  if (testFiles) {
@@ -52678,14 +52926,14 @@ function hasDevDependency(devDeps, ...patterns) {
52678
52926
  return hasPackageJsonDependency(devDeps, ...patterns);
52679
52927
  }
52680
52928
  function detectGoTest(cwd) {
52681
- return fs24.existsSync(path45.join(cwd, "go.mod")) && isCommandAvailable("go");
52929
+ return fs24.existsSync(path46.join(cwd, "go.mod")) && isCommandAvailable("go");
52682
52930
  }
52683
52931
  function detectJavaMaven(cwd) {
52684
- return fs24.existsSync(path45.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
52932
+ return fs24.existsSync(path46.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
52685
52933
  }
52686
52934
  function detectGradle(cwd) {
52687
- const hasBuildFile = fs24.existsSync(path45.join(cwd, "build.gradle")) || fs24.existsSync(path45.join(cwd, "build.gradle.kts"));
52688
- const hasGradlew = fs24.existsSync(path45.join(cwd, "gradlew")) || fs24.existsSync(path45.join(cwd, "gradlew.bat"));
52935
+ const hasBuildFile = fs24.existsSync(path46.join(cwd, "build.gradle")) || fs24.existsSync(path46.join(cwd, "build.gradle.kts"));
52936
+ const hasGradlew = fs24.existsSync(path46.join(cwd, "gradlew")) || fs24.existsSync(path46.join(cwd, "gradlew.bat"));
52689
52937
  return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
52690
52938
  }
52691
52939
  function detectDotnetTest(cwd) {
@@ -52698,25 +52946,25 @@ function detectDotnetTest(cwd) {
52698
52946
  }
52699
52947
  }
52700
52948
  function detectCTest(cwd) {
52701
- const hasSource = fs24.existsSync(path45.join(cwd, "CMakeLists.txt"));
52702
- const hasBuildCache = fs24.existsSync(path45.join(cwd, "CMakeCache.txt")) || fs24.existsSync(path45.join(cwd, "build", "CMakeCache.txt"));
52949
+ const hasSource = fs24.existsSync(path46.join(cwd, "CMakeLists.txt"));
52950
+ const hasBuildCache = fs24.existsSync(path46.join(cwd, "CMakeCache.txt")) || fs24.existsSync(path46.join(cwd, "build", "CMakeCache.txt"));
52703
52951
  return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
52704
52952
  }
52705
52953
  function detectSwiftTest(cwd) {
52706
- return fs24.existsSync(path45.join(cwd, "Package.swift")) && isCommandAvailable("swift");
52954
+ return fs24.existsSync(path46.join(cwd, "Package.swift")) && isCommandAvailable("swift");
52707
52955
  }
52708
52956
  function detectDartTest(cwd) {
52709
- return fs24.existsSync(path45.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
52957
+ return fs24.existsSync(path46.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
52710
52958
  }
52711
52959
  function detectRSpec(cwd) {
52712
- const hasRSpecFile = fs24.existsSync(path45.join(cwd, ".rspec"));
52713
- const hasGemfile = fs24.existsSync(path45.join(cwd, "Gemfile"));
52714
- const hasSpecDir = fs24.existsSync(path45.join(cwd, "spec"));
52960
+ const hasRSpecFile = fs24.existsSync(path46.join(cwd, ".rspec"));
52961
+ const hasGemfile = fs24.existsSync(path46.join(cwd, "Gemfile"));
52962
+ const hasSpecDir = fs24.existsSync(path46.join(cwd, "spec"));
52715
52963
  const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
52716
52964
  return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
52717
52965
  }
52718
52966
  function detectMinitest(cwd) {
52719
- return fs24.existsSync(path45.join(cwd, "test")) && (fs24.existsSync(path45.join(cwd, "Gemfile")) || fs24.existsSync(path45.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
52967
+ return fs24.existsSync(path46.join(cwd, "test")) && (fs24.existsSync(path46.join(cwd, "Gemfile")) || fs24.existsSync(path46.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
52720
52968
  }
52721
52969
  async function detectTestFrameworkViaDispatch(cwd) {
52722
52970
  try {
@@ -52778,7 +53026,7 @@ async function parseTestOutputViaDispatch(framework, output, baseDir) {
52778
53026
  async function detectTestFramework(cwd) {
52779
53027
  const baseDir = cwd;
52780
53028
  try {
52781
- const packageJsonPath = path45.join(baseDir, "package.json");
53029
+ const packageJsonPath = path46.join(baseDir, "package.json");
52782
53030
  if (fs24.existsSync(packageJsonPath)) {
52783
53031
  const content = fs24.readFileSync(packageJsonPath, "utf-8");
52784
53032
  const pkg = JSON.parse(content);
@@ -52799,16 +53047,16 @@ async function detectTestFramework(cwd) {
52799
53047
  return "jest";
52800
53048
  if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
52801
53049
  return "mocha";
52802
- if (fs24.existsSync(path45.join(baseDir, "bun.lockb")) || fs24.existsSync(path45.join(baseDir, "bun.lock"))) {
53050
+ if (fs24.existsSync(path46.join(baseDir, "bun.lockb")) || fs24.existsSync(path46.join(baseDir, "bun.lock"))) {
52803
53051
  if (scripts.test?.includes("bun"))
52804
53052
  return "bun";
52805
53053
  }
52806
53054
  }
52807
53055
  } catch {}
52808
53056
  try {
52809
- const pyprojectTomlPath = path45.join(baseDir, "pyproject.toml");
52810
- const setupCfgPath = path45.join(baseDir, "setup.cfg");
52811
- const requirementsTxtPath = path45.join(baseDir, "requirements.txt");
53057
+ const pyprojectTomlPath = path46.join(baseDir, "pyproject.toml");
53058
+ const setupCfgPath = path46.join(baseDir, "setup.cfg");
53059
+ const requirementsTxtPath = path46.join(baseDir, "requirements.txt");
52812
53060
  if (fs24.existsSync(pyprojectTomlPath)) {
52813
53061
  const content = fs24.readFileSync(pyprojectTomlPath, "utf-8");
52814
53062
  if (content.includes("[tool.pytest"))
@@ -52828,7 +53076,7 @@ async function detectTestFramework(cwd) {
52828
53076
  }
52829
53077
  } catch {}
52830
53078
  try {
52831
- const cargoTomlPath = path45.join(baseDir, "Cargo.toml");
53079
+ const cargoTomlPath = path46.join(baseDir, "Cargo.toml");
52832
53080
  if (fs24.existsSync(cargoTomlPath)) {
52833
53081
  const content = fs24.readFileSync(cargoTomlPath, "utf-8");
52834
53082
  if (content.includes("[dev-dependencies]")) {
@@ -52839,9 +53087,9 @@ async function detectTestFramework(cwd) {
52839
53087
  }
52840
53088
  } catch {}
52841
53089
  try {
52842
- const pesterConfigPath = path45.join(baseDir, "pester.config.ps1");
52843
- const pesterConfigJsonPath = path45.join(baseDir, "pester.config.ps1.json");
52844
- const pesterPs1Path = path45.join(baseDir, "tests.ps1");
53090
+ const pesterConfigPath = path46.join(baseDir, "pester.config.ps1");
53091
+ const pesterConfigJsonPath = path46.join(baseDir, "pester.config.ps1.json");
53092
+ const pesterPs1Path = path46.join(baseDir, "tests.ps1");
52845
53093
  if (fs24.existsSync(pesterConfigPath) || fs24.existsSync(pesterConfigJsonPath) || fs24.existsSync(pesterPs1Path)) {
52846
53094
  return "pester";
52847
53095
  }
@@ -52870,12 +53118,12 @@ function isTestDirectoryPath(normalizedPath) {
52870
53118
  return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
52871
53119
  }
52872
53120
  function resolveWorkspacePath(file3, workingDir) {
52873
- return path45.isAbsolute(file3) ? path45.resolve(file3) : path45.resolve(workingDir, file3);
53121
+ return path46.isAbsolute(file3) ? path46.resolve(file3) : path46.resolve(workingDir, file3);
52874
53122
  }
52875
53123
  function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
52876
53124
  if (!preferRelative)
52877
53125
  return absolutePath;
52878
- return path45.relative(workingDir, absolutePath);
53126
+ return path46.relative(workingDir, absolutePath);
52879
53127
  }
52880
53128
  function dedupePush(target, value) {
52881
53129
  if (!target.includes(value)) {
@@ -52912,18 +53160,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
52912
53160
  }
52913
53161
  }
52914
53162
  function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
52915
- const relativeDir = path45.dirname(relativePath);
53163
+ const relativeDir = path46.dirname(relativePath);
52916
53164
  const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
52917
53165
  const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
52918
- const rootDir = path45.join(workingDir, dirName);
52919
- return nestedRelativeDir ? [rootDir, path45.join(rootDir, nestedRelativeDir)] : [rootDir];
53166
+ const rootDir = path46.join(workingDir, dirName);
53167
+ return nestedRelativeDir ? [rootDir, path46.join(rootDir, nestedRelativeDir)] : [rootDir];
52920
53168
  });
52921
53169
  const normalizedRelativePath = relativePath.replace(/\\/g, "/");
52922
53170
  if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
52923
- directories.push(path45.join(workingDir, "src/test/java", path45.dirname(normalizedRelativePath.slice("src/main/java/".length))));
53171
+ directories.push(path46.join(workingDir, "src/test/java", path46.dirname(normalizedRelativePath.slice("src/main/java/".length))));
52924
53172
  }
52925
53173
  if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
52926
- directories.push(path45.join(workingDir, "src/test/kotlin", path45.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
53174
+ directories.push(path46.join(workingDir, "src/test/kotlin", path46.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
52927
53175
  }
52928
53176
  return [...new Set(directories)];
52929
53177
  }
@@ -52951,23 +53199,23 @@ function isLanguageSpecificTestFile(basename7) {
52951
53199
  }
52952
53200
  function isConventionTestFilePath(filePath) {
52953
53201
  const normalizedPath = filePath.replace(/\\/g, "/");
52954
- const basename7 = path45.basename(filePath);
53202
+ const basename7 = path46.basename(filePath);
52955
53203
  return hasCompoundTestExtension(basename7) || basename7.includes(".spec.") || basename7.includes(".test.") || isLanguageSpecificTestFile(basename7) || isTestDirectoryPath(normalizedPath);
52956
53204
  }
52957
53205
  function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
52958
53206
  const testFiles = [];
52959
53207
  for (const file3 of sourceFiles) {
52960
53208
  const absoluteFile = resolveWorkspacePath(file3, workingDir);
52961
- const relativeFile = path45.relative(workingDir, absoluteFile);
52962
- const basename7 = path45.basename(absoluteFile);
52963
- const dirname22 = path45.dirname(absoluteFile);
52964
- const preferRelativeOutput = !path45.isAbsolute(file3);
53209
+ const relativeFile = path46.relative(workingDir, absoluteFile);
53210
+ const basename7 = path46.basename(absoluteFile);
53211
+ const dirname23 = path46.dirname(absoluteFile);
53212
+ const preferRelativeOutput = !path46.isAbsolute(file3);
52965
53213
  if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file3)) {
52966
53214
  dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
52967
53215
  continue;
52968
53216
  }
52969
53217
  const nameWithoutExt = basename7.replace(/\.[^.]+$/, "");
52970
- const ext = path45.extname(basename7);
53218
+ const ext = path46.extname(basename7);
52971
53219
  const genericTestNames = [
52972
53220
  `${nameWithoutExt}.spec${ext}`,
52973
53221
  `${nameWithoutExt}.test${ext}`
@@ -52976,7 +53224,7 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
52976
53224
  const colocatedCandidates = [
52977
53225
  ...genericTestNames,
52978
53226
  ...languageSpecificTestNames
52979
- ].map((candidateName) => path45.join(dirname22, candidateName));
53227
+ ].map((candidateName) => path46.join(dirname23, candidateName));
52980
53228
  const testDirectoryNames = [
52981
53229
  basename7,
52982
53230
  ...genericTestNames,
@@ -52985,8 +53233,8 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
52985
53233
  const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
52986
53234
  const possibleTestFiles = [
52987
53235
  ...colocatedCandidates,
52988
- ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path45.join(dirname22, dirName, candidateName))),
52989
- ...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path45.join(candidateDir, candidateName)))
53236
+ ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path46.join(dirname23, dirName, candidateName))),
53237
+ ...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path46.join(candidateDir, candidateName)))
52990
53238
  ];
52991
53239
  for (const testFile of possibleTestFiles) {
52992
53240
  if (fs24.existsSync(testFile)) {
@@ -53007,7 +53255,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
53007
53255
  try {
53008
53256
  const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
53009
53257
  const content = fs24.readFileSync(absoluteTestFile, "utf-8");
53010
- const testDir = path45.dirname(absoluteTestFile);
53258
+ const testDir = path46.dirname(absoluteTestFile);
53011
53259
  const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
53012
53260
  let match;
53013
53261
  match = importRegex.exec(content);
@@ -53015,8 +53263,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
53015
53263
  const importPath = match[1];
53016
53264
  let resolvedImport;
53017
53265
  if (importPath.startsWith(".")) {
53018
- resolvedImport = path45.resolve(testDir, importPath);
53019
- const existingExt = path45.extname(resolvedImport);
53266
+ resolvedImport = path46.resolve(testDir, importPath);
53267
+ const existingExt = path46.extname(resolvedImport);
53020
53268
  if (!existingExt) {
53021
53269
  for (const extToTry of [
53022
53270
  ".ts",
@@ -53036,12 +53284,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
53036
53284
  } else {
53037
53285
  continue;
53038
53286
  }
53039
- const importBasename = path45.basename(resolvedImport, path45.extname(resolvedImport));
53040
- const importDir = path45.dirname(resolvedImport);
53287
+ const importBasename = path46.basename(resolvedImport, path46.extname(resolvedImport));
53288
+ const importDir = path46.dirname(resolvedImport);
53041
53289
  for (const sourceFile of absoluteSourceFiles) {
53042
- const sourceDir = path45.dirname(sourceFile);
53043
- const sourceBasename = path45.basename(sourceFile, path45.extname(sourceFile));
53044
- const isRelatedDir = importDir === sourceDir || importDir === path45.join(sourceDir, "__tests__") || importDir === path45.join(sourceDir, "tests") || importDir === path45.join(sourceDir, "test") || importDir === path45.join(sourceDir, "spec");
53290
+ const sourceDir = path46.dirname(sourceFile);
53291
+ const sourceBasename = path46.basename(sourceFile, path46.extname(sourceFile));
53292
+ const isRelatedDir = importDir === sourceDir || importDir === path46.join(sourceDir, "__tests__") || importDir === path46.join(sourceDir, "tests") || importDir === path46.join(sourceDir, "test") || importDir === path46.join(sourceDir, "spec");
53045
53293
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
53046
53294
  dedupePush(testFiles, testFile);
53047
53295
  break;
@@ -53054,8 +53302,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
53054
53302
  while (match !== null) {
53055
53303
  const importPath = match[1];
53056
53304
  if (importPath.startsWith(".")) {
53057
- let resolvedImport = path45.resolve(testDir, importPath);
53058
- const existingExt = path45.extname(resolvedImport);
53305
+ let resolvedImport = path46.resolve(testDir, importPath);
53306
+ const existingExt = path46.extname(resolvedImport);
53059
53307
  if (!existingExt) {
53060
53308
  for (const extToTry of [
53061
53309
  ".ts",
@@ -53072,12 +53320,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
53072
53320
  }
53073
53321
  }
53074
53322
  }
53075
- const importDir = path45.dirname(resolvedImport);
53076
- const importBasename = path45.basename(resolvedImport, path45.extname(resolvedImport));
53323
+ const importDir = path46.dirname(resolvedImport);
53324
+ const importBasename = path46.basename(resolvedImport, path46.extname(resolvedImport));
53077
53325
  for (const sourceFile of absoluteSourceFiles) {
53078
- const sourceDir = path45.dirname(sourceFile);
53079
- const sourceBasename = path45.basename(sourceFile, path45.extname(sourceFile));
53080
- const isRelatedDir = importDir === sourceDir || importDir === path45.join(sourceDir, "__tests__") || importDir === path45.join(sourceDir, "tests") || importDir === path45.join(sourceDir, "test") || importDir === path45.join(sourceDir, "spec");
53326
+ const sourceDir = path46.dirname(sourceFile);
53327
+ const sourceBasename = path46.basename(sourceFile, path46.extname(sourceFile));
53328
+ const isRelatedDir = importDir === sourceDir || importDir === path46.join(sourceDir, "__tests__") || importDir === path46.join(sourceDir, "tests") || importDir === path46.join(sourceDir, "test") || importDir === path46.join(sourceDir, "spec");
53081
53329
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
53082
53330
  dedupePush(testFiles, testFile);
53083
53331
  break;
@@ -53187,8 +53435,8 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
53187
53435
  return ["mvn", "test"];
53188
53436
  case "gradle": {
53189
53437
  const isWindows = process.platform === "win32";
53190
- const hasGradlewBat = fs24.existsSync(path45.join(baseDir, "gradlew.bat"));
53191
- const hasGradlew = fs24.existsSync(path45.join(baseDir, "gradlew"));
53438
+ const hasGradlewBat = fs24.existsSync(path46.join(baseDir, "gradlew.bat"));
53439
+ const hasGradlew = fs24.existsSync(path46.join(baseDir, "gradlew"));
53192
53440
  if (hasGradlewBat && isWindows)
53193
53441
  return ["gradlew.bat", "test"];
53194
53442
  if (hasGradlew)
@@ -53205,7 +53453,7 @@ function buildTestCommand2(framework, scope, files, coverage, baseDir) {
53205
53453
  "cmake-build-release",
53206
53454
  "out"
53207
53455
  ];
53208
- const actualBuildDir = buildDirCandidates.find((d) => fs24.existsSync(path45.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
53456
+ const actualBuildDir = buildDirCandidates.find((d) => fs24.existsSync(path46.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
53209
53457
  return ["ctest", "--test-dir", actualBuildDir];
53210
53458
  }
53211
53459
  case "swift-test":
@@ -53637,11 +53885,11 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
53637
53885
  };
53638
53886
  }
53639
53887
  const startTime = Date.now();
53640
- const vitestJsonOutputPath = framework === "vitest" ? path45.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
53888
+ const vitestJsonOutputPath = framework === "vitest" ? path46.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
53641
53889
  try {
53642
53890
  if (vitestJsonOutputPath) {
53643
53891
  try {
53644
- fs24.mkdirSync(path45.dirname(vitestJsonOutputPath), { recursive: true });
53892
+ fs24.mkdirSync(path46.dirname(vitestJsonOutputPath), { recursive: true });
53645
53893
  if (fs24.existsSync(vitestJsonOutputPath)) {
53646
53894
  fs24.unlinkSync(vitestJsonOutputPath);
53647
53895
  }
@@ -53757,10 +54005,10 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd) {
53757
54005
  }
53758
54006
  function normalizeHistoryTestFile(testFile, workingDir) {
53759
54007
  const normalized = testFile.replace(/\\/g, "/");
53760
- if (!path45.isAbsolute(testFile))
54008
+ if (!path46.isAbsolute(testFile))
53761
54009
  return normalized;
53762
- const relative9 = path45.relative(workingDir, testFile);
53763
- if (relative9.startsWith("..") || path45.isAbsolute(relative9)) {
54010
+ const relative9 = path46.relative(workingDir, testFile);
54011
+ if (relative9.startsWith("..") || path46.isAbsolute(relative9)) {
53764
54012
  return normalized;
53765
54013
  }
53766
54014
  return relative9.replace(/\\/g, "/");
@@ -54098,7 +54346,7 @@ var init_test_runner = __esm(() => {
54098
54346
  const sourceFiles = args.files.filter((file3) => {
54099
54347
  if (directTestFiles.includes(file3))
54100
54348
  return false;
54101
- const ext = path45.extname(file3).toLowerCase();
54349
+ const ext = path46.extname(file3).toLowerCase();
54102
54350
  return SOURCE_EXTENSIONS.has(ext);
54103
54351
  });
54104
54352
  const invalidFiles = args.files.filter((file3) => !directTestFiles.includes(file3) && !sourceFiles.includes(file3));
@@ -54144,7 +54392,7 @@ var init_test_runner = __esm(() => {
54144
54392
  if (isConventionTestFilePath(f)) {
54145
54393
  return false;
54146
54394
  }
54147
- const ext = path45.extname(f).toLowerCase();
54395
+ const ext = path46.extname(f).toLowerCase();
54148
54396
  return SOURCE_EXTENSIONS.has(ext);
54149
54397
  });
54150
54398
  if (sourceFiles.length === 0) {
@@ -54194,7 +54442,7 @@ var init_test_runner = __esm(() => {
54194
54442
  if (isConventionTestFilePath(f)) {
54195
54443
  return false;
54196
54444
  }
54197
- const ext = path45.extname(f).toLowerCase();
54445
+ const ext = path46.extname(f).toLowerCase();
54198
54446
  return SOURCE_EXTENSIONS.has(ext);
54199
54447
  });
54200
54448
  if (sourceFiles.length === 0) {
@@ -54246,8 +54494,8 @@ var init_test_runner = __esm(() => {
54246
54494
  }
54247
54495
  if (impactResult.impactedTests.length > 0) {
54248
54496
  testFiles = impactResult.impactedTests.map((absPath) => {
54249
- const relativePath = path45.relative(workingDir, absPath);
54250
- return path45.isAbsolute(relativePath) ? absPath : relativePath;
54497
+ const relativePath = path46.relative(workingDir, absPath);
54498
+ return path46.isAbsolute(relativePath) ? absPath : relativePath;
54251
54499
  });
54252
54500
  } else {
54253
54501
  graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
@@ -54323,7 +54571,7 @@ var init_test_runner = __esm(() => {
54323
54571
 
54324
54572
  // src/services/preflight-service.ts
54325
54573
  import * as fs25 from "fs";
54326
- import * as path46 from "path";
54574
+ import * as path47 from "path";
54327
54575
  function validateDirectoryPath(dir) {
54328
54576
  if (!dir || typeof dir !== "string") {
54329
54577
  throw new Error("Directory path is required");
@@ -54331,8 +54579,8 @@ function validateDirectoryPath(dir) {
54331
54579
  if (dir.includes("..")) {
54332
54580
  throw new Error("Directory path must not contain path traversal sequences");
54333
54581
  }
54334
- const normalized = path46.normalize(dir);
54335
- const absolutePath = path46.isAbsolute(normalized) ? normalized : path46.resolve(normalized);
54582
+ const normalized = path47.normalize(dir);
54583
+ const absolutePath = path47.isAbsolute(normalized) ? normalized : path47.resolve(normalized);
54336
54584
  return absolutePath;
54337
54585
  }
54338
54586
  function validateTimeout(timeoutMs, defaultValue) {
@@ -54355,7 +54603,7 @@ function validateTimeout(timeoutMs, defaultValue) {
54355
54603
  }
54356
54604
  function getPackageVersion(dir) {
54357
54605
  try {
54358
- const packagePath = path46.join(dir, "package.json");
54606
+ const packagePath = path47.join(dir, "package.json");
54359
54607
  if (fs25.existsSync(packagePath)) {
54360
54608
  const content = fs25.readFileSync(packagePath, "utf-8");
54361
54609
  const pkg = JSON.parse(content);
@@ -54366,7 +54614,7 @@ function getPackageVersion(dir) {
54366
54614
  }
54367
54615
  function getChangelogVersion(dir) {
54368
54616
  try {
54369
- const changelogPath = path46.join(dir, "CHANGELOG.md");
54617
+ const changelogPath = path47.join(dir, "CHANGELOG.md");
54370
54618
  if (fs25.existsSync(changelogPath)) {
54371
54619
  const content = fs25.readFileSync(changelogPath, "utf-8");
54372
54620
  const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
@@ -54380,7 +54628,7 @@ function getChangelogVersion(dir) {
54380
54628
  function getVersionFileVersion(dir) {
54381
54629
  const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
54382
54630
  for (const file3 of possibleFiles) {
54383
- const filePath = path46.join(dir, file3);
54631
+ const filePath = path47.join(dir, file3);
54384
54632
  if (fs25.existsSync(filePath)) {
54385
54633
  try {
54386
54634
  const content = fs25.readFileSync(filePath, "utf-8").trim();
@@ -54722,7 +54970,7 @@ async function runEvidenceCheck(dir) {
54722
54970
  async function runRequirementCoverageCheck(dir, currentPhase) {
54723
54971
  const startTime = Date.now();
54724
54972
  try {
54725
- const specPath = path46.join(dir, ".swarm", "spec.md");
54973
+ const specPath = path47.join(dir, ".swarm", "spec.md");
54726
54974
  if (!fs25.existsSync(specPath)) {
54727
54975
  return {
54728
54976
  type: "req_coverage",
@@ -55840,7 +56088,7 @@ var init_manager3 = __esm(() => {
55840
56088
 
55841
56089
  // src/commands/reset.ts
55842
56090
  import * as fs26 from "fs";
55843
- import * as path47 from "path";
56091
+ import * as path48 from "path";
55844
56092
  async function handleResetCommand(directory, args) {
55845
56093
  const hasConfirm = args.includes("--confirm");
55846
56094
  if (!hasConfirm) {
@@ -55880,7 +56128,7 @@ async function handleResetCommand(directory, args) {
55880
56128
  }
55881
56129
  for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
55882
56130
  try {
55883
- const rootPath = path47.join(directory, filename);
56131
+ const rootPath = path48.join(directory, filename);
55884
56132
  if (fs26.existsSync(rootPath)) {
55885
56133
  fs26.unlinkSync(rootPath);
55886
56134
  results.push(`- \u2705 Deleted ${filename} (root)`);
@@ -55920,7 +56168,7 @@ var init_reset = __esm(() => {
55920
56168
 
55921
56169
  // src/commands/reset-session.ts
55922
56170
  import * as fs27 from "fs";
55923
- import * as path48 from "path";
56171
+ import * as path49 from "path";
55924
56172
  async function handleResetSessionCommand(directory, _args) {
55925
56173
  const results = [];
55926
56174
  try {
@@ -55935,13 +56183,13 @@ async function handleResetSessionCommand(directory, _args) {
55935
56183
  results.push("\u274C Failed to delete state.json");
55936
56184
  }
55937
56185
  try {
55938
- const sessionDir = path48.dirname(validateSwarmPath(directory, "session/state.json"));
56186
+ const sessionDir = path49.dirname(validateSwarmPath(directory, "session/state.json"));
55939
56187
  if (fs27.existsSync(sessionDir)) {
55940
56188
  const files = fs27.readdirSync(sessionDir);
55941
56189
  const otherFiles = files.filter((f) => f !== "state.json");
55942
56190
  let deletedCount = 0;
55943
56191
  for (const file3 of otherFiles) {
55944
- const filePath = path48.join(sessionDir, file3);
56192
+ const filePath = path49.join(sessionDir, file3);
55945
56193
  if (fs27.lstatSync(filePath).isFile()) {
55946
56194
  fs27.unlinkSync(filePath);
55947
56195
  deletedCount++;
@@ -55973,7 +56221,7 @@ var init_reset_session = __esm(() => {
55973
56221
  });
55974
56222
 
55975
56223
  // src/summaries/manager.ts
55976
- import * as path49 from "path";
56224
+ import * as path50 from "path";
55977
56225
  function sanitizeSummaryId(id) {
55978
56226
  if (!id || id.length === 0) {
55979
56227
  throw new Error("Invalid summary ID: empty string");
@@ -55996,7 +56244,7 @@ function sanitizeSummaryId(id) {
55996
56244
  }
55997
56245
  async function loadFullOutput(directory, id) {
55998
56246
  const sanitizedId = sanitizeSummaryId(id);
55999
- const relativePath = path49.join("summaries", `${sanitizedId}.json`);
56247
+ const relativePath = path50.join("summaries", `${sanitizedId}.json`);
56000
56248
  validateSwarmPath(directory, relativePath);
56001
56249
  const content = await readSwarmFileAsync(directory, relativePath);
56002
56250
  if (content === null) {
@@ -56059,7 +56307,7 @@ var init_retrieve = __esm(() => {
56059
56307
 
56060
56308
  // src/commands/rollback.ts
56061
56309
  import * as fs28 from "fs";
56062
- import * as path50 from "path";
56310
+ import * as path51 from "path";
56063
56311
  async function handleRollbackCommand(directory, args) {
56064
56312
  const phaseArg = args[0];
56065
56313
  if (!phaseArg) {
@@ -56124,8 +56372,8 @@ async function handleRollbackCommand(directory, args) {
56124
56372
  if (EXCLUDE_FILES.has(file3) || file3.startsWith("plan-ledger.archived-")) {
56125
56373
  continue;
56126
56374
  }
56127
- const src = path50.join(checkpointDir, file3);
56128
- const dest = path50.join(swarmDir, file3);
56375
+ const src = path51.join(checkpointDir, file3);
56376
+ const dest = path51.join(swarmDir, file3);
56129
56377
  try {
56130
56378
  fs28.cpSync(src, dest, { recursive: true, force: true });
56131
56379
  successes.push(file3);
@@ -56144,12 +56392,12 @@ async function handleRollbackCommand(directory, args) {
56144
56392
  ].join(`
56145
56393
  `);
56146
56394
  }
56147
- const existingLedgerPath = path50.join(swarmDir, "plan-ledger.jsonl");
56395
+ const existingLedgerPath = path51.join(swarmDir, "plan-ledger.jsonl");
56148
56396
  if (fs28.existsSync(existingLedgerPath)) {
56149
56397
  fs28.unlinkSync(existingLedgerPath);
56150
56398
  }
56151
56399
  try {
56152
- const planJsonPath = path50.join(swarmDir, "plan.json");
56400
+ const planJsonPath = path51.join(swarmDir, "plan.json");
56153
56401
  if (fs28.existsSync(planJsonPath)) {
56154
56402
  const planRaw = fs28.readFileSync(planJsonPath, "utf-8");
56155
56403
  const plan = PlanSchema.parse(JSON.parse(planRaw));
@@ -56240,9 +56488,9 @@ Ensure this is a git repository with commit history.`;
56240
56488
  `);
56241
56489
  try {
56242
56490
  const fs29 = await import("fs/promises");
56243
- const path51 = await import("path");
56244
- const reportPath = path51.join(directory, ".swarm", "simulate-report.md");
56245
- await fs29.mkdir(path51.dirname(reportPath), { recursive: true });
56491
+ const path52 = await import("path");
56492
+ const reportPath = path52.join(directory, ".swarm", "simulate-report.md");
56493
+ await fs29.mkdir(path52.dirname(reportPath), { recursive: true });
56246
56494
  await fs29.writeFile(reportPath, report, "utf-8");
56247
56495
  } catch (err) {
56248
56496
  const writeErr = err instanceof Error ? err.message : String(err);
@@ -56266,12 +56514,12 @@ async function handleSpecifyCommand(_directory, args) {
56266
56514
 
56267
56515
  // src/turbo/lean/state.ts
56268
56516
  import * as fs29 from "fs";
56269
- import * as path51 from "path";
56517
+ import * as path52 from "path";
56270
56518
  function nowISO2() {
56271
56519
  return new Date().toISOString();
56272
56520
  }
56273
56521
  function ensureSwarmDir2(directory) {
56274
- const swarmDir = path51.resolve(directory, ".swarm");
56522
+ const swarmDir = path52.resolve(directory, ".swarm");
56275
56523
  if (!fs29.existsSync(swarmDir)) {
56276
56524
  fs29.mkdirSync(swarmDir, { recursive: true });
56277
56525
  }
@@ -56315,7 +56563,7 @@ function markStateUnreadable2(directory, reason) {
56315
56563
  }
56316
56564
  function readPersisted2(directory) {
56317
56565
  try {
56318
- const filePath = path51.join(directory, ".swarm", STATE_FILE2);
56566
+ const filePath = path52.join(directory, ".swarm", STATE_FILE2);
56319
56567
  if (!fs29.existsSync(filePath)) {
56320
56568
  const seed = emptyPersisted2();
56321
56569
  try {
@@ -56351,7 +56599,7 @@ function writePersisted2(directory, persisted) {
56351
56599
  let payload;
56352
56600
  try {
56353
56601
  ensureSwarmDir2(directory);
56354
- filePath = path51.join(directory, ".swarm", STATE_FILE2);
56602
+ filePath = path52.join(directory, ".swarm", STATE_FILE2);
56355
56603
  tmpPath = `${filePath}.tmp.${Date.now()}`;
56356
56604
  persisted.updatedAt = nowISO2();
56357
56605
  payload = `${JSON.stringify(persisted, null, 2)}
@@ -56478,10 +56726,10 @@ var init_context_budget_service = __esm(() => {
56478
56726
 
56479
56727
  // src/services/status-service.ts
56480
56728
  import * as fsSync2 from "fs";
56481
- import * as path52 from "path";
56729
+ import * as path53 from "path";
56482
56730
  function readSpecStalenessSnapshot(directory) {
56483
56731
  try {
56484
- const p = path52.join(directory, ".swarm", "spec-staleness.json");
56732
+ const p = path53.join(directory, ".swarm", "spec-staleness.json");
56485
56733
  if (!fsSync2.existsSync(p))
56486
56734
  return { stale: false };
56487
56735
  const raw = fsSync2.readFileSync(p, "utf-8");
@@ -57007,7 +57255,7 @@ var init_write_retro2 = __esm(() => {
57007
57255
 
57008
57256
  // src/commands/command-dispatch.ts
57009
57257
  import fs30 from "fs";
57010
- import path53 from "path";
57258
+ import path54 from "path";
57011
57259
  function normalizeSwarmCommandInput(command, argumentText) {
57012
57260
  if (command !== "swarm" && !command.startsWith("swarm-")) {
57013
57261
  return { isSwarmCommand: false, tokens: [] };
@@ -57043,9 +57291,9 @@ ${similar.map((cmd) => ` - /swarm ${cmd}`).join(`
57043
57291
  `);
57044
57292
  }
57045
57293
  function maybeMarkFirstRun(directory) {
57046
- const sentinelPath = path53.join(directory, ".swarm", ".first-run-complete");
57294
+ const sentinelPath = path54.join(directory, ".swarm", ".first-run-complete");
57047
57295
  try {
57048
- const swarmDir = path53.join(directory, ".swarm");
57296
+ const swarmDir = path54.join(directory, ".swarm");
57049
57297
  fs30.mkdirSync(swarmDir, { recursive: true });
57050
57298
  fs30.writeFileSync(sentinelPath, `first-run-complete: ${new Date().toISOString()}
57051
57299
  `, { flag: "wx" });
@@ -57787,24 +58035,24 @@ function validateAliases() {
57787
58035
  }
57788
58036
  aliasTargets.get(target).push(name);
57789
58037
  const visited = new Set;
57790
- const path54 = [];
58038
+ const path55 = [];
57791
58039
  let current = target;
57792
58040
  while (current) {
57793
58041
  const currentEntry = COMMAND_REGISTRY[current];
57794
58042
  if (!currentEntry)
57795
58043
  break;
57796
58044
  if (visited.has(current)) {
57797
- const cycleStart = path54.indexOf(current);
58045
+ const cycleStart = path55.indexOf(current);
57798
58046
  const fullChain = [
57799
58047
  name,
57800
- ...path54.slice(0, cycleStart > 0 ? cycleStart : path54.length),
58048
+ ...path55.slice(0, cycleStart > 0 ? cycleStart : path55.length),
57801
58049
  current
57802
58050
  ].join(" \u2192 ");
57803
58051
  errors5.push(`Circular alias detected: ${fullChain}`);
57804
58052
  break;
57805
58053
  }
57806
58054
  visited.add(current);
57807
- path54.push(current);
58055
+ path55.push(current);
57808
58056
  current = currentEntry.aliasOf || "";
57809
58057
  }
57810
58058
  }
@@ -58402,53 +58650,53 @@ init_cache_paths();
58402
58650
  init_constants();
58403
58651
  import * as fs31 from "fs";
58404
58652
  import * as os8 from "os";
58405
- import * as path54 from "path";
58406
- var { version: version4 } = package_default;
58653
+ import * as path55 from "path";
58654
+ var { version: version5 } = package_default;
58407
58655
  var CONFIG_DIR = getPluginConfigDir();
58408
- var OPENCODE_CONFIG_PATH = path54.join(CONFIG_DIR, "opencode.json");
58409
- var PLUGIN_CONFIG_PATH = path54.join(CONFIG_DIR, "opencode-swarm.json");
58410
- var PROMPTS_DIR = path54.join(CONFIG_DIR, "opencode-swarm");
58656
+ var OPENCODE_CONFIG_PATH = path55.join(CONFIG_DIR, "opencode.json");
58657
+ var PLUGIN_CONFIG_PATH = path55.join(CONFIG_DIR, "opencode-swarm.json");
58658
+ var PROMPTS_DIR = path55.join(CONFIG_DIR, "opencode-swarm");
58411
58659
  var OPENCODE_PLUGIN_CACHE_PATHS = getPluginCachePaths();
58412
58660
  var OPENCODE_PLUGIN_LOCK_FILE_PATHS = getPluginLockFilePaths();
58413
58661
  function isSafeCachePath(p) {
58414
- const resolved = path54.resolve(p);
58415
- const home = path54.resolve(os8.homedir());
58662
+ const resolved = path55.resolve(p);
58663
+ const home = path55.resolve(os8.homedir());
58416
58664
  if (resolved === "/" || resolved === home || resolved.length <= home.length) {
58417
58665
  return false;
58418
58666
  }
58419
- const segments = resolved.split(path54.sep).filter((s) => s.length > 0);
58667
+ const segments = resolved.split(path55.sep).filter((s) => s.length > 0);
58420
58668
  if (segments.length < 4) {
58421
58669
  return false;
58422
58670
  }
58423
- const leaf = path54.basename(resolved);
58671
+ const leaf = path55.basename(resolved);
58424
58672
  if (leaf !== "opencode-swarm@latest" && leaf !== "opencode-swarm") {
58425
58673
  return false;
58426
58674
  }
58427
- const parent = path54.basename(path54.dirname(resolved));
58675
+ const parent = path55.basename(path55.dirname(resolved));
58428
58676
  if (parent !== "packages" && parent !== "node_modules") {
58429
58677
  return false;
58430
58678
  }
58431
- const grandparent = path54.basename(path54.dirname(path54.dirname(resolved)));
58679
+ const grandparent = path55.basename(path55.dirname(path55.dirname(resolved)));
58432
58680
  if (grandparent !== "opencode") {
58433
58681
  return false;
58434
58682
  }
58435
58683
  return true;
58436
58684
  }
58437
58685
  function isSafeLockFilePath(p) {
58438
- const resolved = path54.resolve(p);
58439
- const home = path54.resolve(os8.homedir());
58686
+ const resolved = path55.resolve(p);
58687
+ const home = path55.resolve(os8.homedir());
58440
58688
  if (resolved === "/" || resolved === home || resolved.length <= home.length) {
58441
58689
  return false;
58442
58690
  }
58443
- const segments = resolved.split(path54.sep).filter((s) => s.length > 0);
58691
+ const segments = resolved.split(path55.sep).filter((s) => s.length > 0);
58444
58692
  if (segments.length < 4) {
58445
58693
  return false;
58446
58694
  }
58447
- const leaf = path54.basename(resolved);
58695
+ const leaf = path55.basename(resolved);
58448
58696
  if (leaf !== "bun.lock" && leaf !== "bun.lockb" && leaf !== "package-lock.json") {
58449
58697
  return false;
58450
58698
  }
58451
- const parent = path54.basename(path54.dirname(resolved));
58699
+ const parent = path55.basename(path55.dirname(resolved));
58452
58700
  if (parent !== "opencode") {
58453
58701
  return false;
58454
58702
  }
@@ -58474,8 +58722,8 @@ function saveJson(filepath, data) {
58474
58722
  }
58475
58723
  function writeProjectConfigIfMissing(cwd) {
58476
58724
  try {
58477
- const opencodeDir = path54.join(cwd, ".opencode");
58478
- const projectConfigPath = path54.join(opencodeDir, "opencode-swarm.json");
58725
+ const opencodeDir = path55.join(cwd, ".opencode");
58726
+ const projectConfigPath = path55.join(opencodeDir, "opencode-swarm.json");
58479
58727
  if (fs31.existsSync(projectConfigPath)) {
58480
58728
  return;
58481
58729
  }
@@ -58492,7 +58740,7 @@ async function install() {
58492
58740
  `);
58493
58741
  ensureDir(CONFIG_DIR);
58494
58742
  ensureDir(PROMPTS_DIR);
58495
- const LEGACY_CONFIG_PATH = path54.join(CONFIG_DIR, "config.json");
58743
+ const LEGACY_CONFIG_PATH = path55.join(CONFIG_DIR, "config.json");
58496
58744
  let opencodeConfig = loadJson(OPENCODE_CONFIG_PATH);
58497
58745
  if (!opencodeConfig) {
58498
58746
  const legacyConfig = loadJson(LEGACY_CONFIG_PATH);
@@ -58767,7 +59015,7 @@ Examples:
58767
59015
  async function main() {
58768
59016
  const args = process.argv.slice(2);
58769
59017
  if (args.includes("-v") || args.includes("--version")) {
58770
- console.log(`opencode-swarm ${version4}`);
59018
+ console.log(`opencode-swarm ${version5}`);
58771
59019
  process.exit(0);
58772
59020
  }
58773
59021
  if (args.includes("-h") || args.includes("--help")) {